phonebookengines_old/contactsmodel/cntmodel/src/rcntmodel.cpp
changeset 40 b46a585f6909
equal deleted inserted replaced
37:fd64c38c277d 40:b46a585f6909
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 
       
    22 #include <s32mem.h>
       
    23 #include <cntitem.h>
       
    24 #include <cntdb.h>
       
    25 #include <cntfilt.h>
       
    26 
       
    27 #include "rcntmodel.h"
       
    28 #include "persistencelayer.h" // For MLplCollection.
       
    29 #include "CCntNotificationMonitor.h"
       
    30 #include "ccontactprivate.h" // For MProgressEventHander.
       
    31 #include "CCntPackager.h"
       
    32 #include <cntviewstore.h>
       
    33 
       
    34 
       
    35 /** Contacts server version number. */ 
       
    36 const TInt KCntServerMajorVersionNumber=1;
       
    37 const TInt KCntServerMinorVersionNumber=1;
       
    38 const TInt KCntServerBuildVersionNumber=1;
       
    39 
       
    40 /** Number of attempts to try restart the server after premature termination. */
       
    41 const TInt KMaxTimesToRestartServer = 3;
       
    42 
       
    43 /** Maximum number of asynchronous IPC calls. */
       
    44 const TInt KAsyncMessageSlots=6;
       
    45 
       
    46 
       
    47 /**
       
    48 Unlock the last locked contact item on the server.  Used by OpenLX().  If any
       
    49 method which locks a contact item leaves thenccnt this method is called as the
       
    50 cleanup stack unwinds, removing the lock for the last locked contact item.
       
    51 
       
    52 @capability None
       
    53 */
       
    54 void CleanupUnlockRecord(TAny *aSession)
       
    55 	{
       
    56 	static_cast<RCntModel*>(aSession)->UnlockLastLockedContact();
       
    57 	}
       
    58 
       
    59 
       
    60 /**
       
    61 Unlock the last locked contact item on the server.  Used by OpenLX().
       
    62 
       
    63 @capability None
       
    64 */
       
    65 void RCntModel::UnlockLastLockedContact()
       
    66 	{
       
    67 	CloseContact(KNullContactId);
       
    68 	}
       
    69 
       
    70 
       
    71 /**
       
    72 Push a Contact item unlock cleanup item on the cleanup stack.
       
    73 */
       
    74 void RCntModel::PushUnlockL() const
       
    75 	{
       
    76 	CleanupStack::PushL( TCleanupItem(CleanupUnlockRecord, const_cast<RCntModel *>(this)));
       
    77 	}
       
    78 
       
    79 
       
    80 /**
       
    81 RCntModel constructor.
       
    82 
       
    83 Member variables must be initialised (zero'd) in the constructor since
       
    84 RCntModel does not derive from CBase.
       
    85 */
       
    86 RCntModel::RCntModel()
       
    87 	:
       
    88 	iDbNotifyMonitor(NULL), 
       
    89 	iPackager(NULL),
       
    90 	iConnectionId(0),
       
    91 	iNoOfSvrStartAttempts(0)
       
    92 	{
       
    93 	}
       
    94 
       
    95 
       
    96 /**
       
    97 Get the Contacts server version number.
       
    98 
       
    99 @return Contacts server version number.
       
   100 */
       
   101 TVersion RCntModel::Version() const
       
   102 	{
       
   103 	return(TVersion(KCntServerMajorVersionNumber,KCntServerMinorVersionNumber,KCntServerBuildVersionNumber));
       
   104 	}
       
   105 
       
   106 
       
   107 /** Name of the executable for the Contacts server. */
       
   108 _LIT(KCntServerExe,"CNTSRV.EXE");
       
   109 /** Name used to connect a session to the Contacts server. */
       
   110 _LIT(KCntServerName,"CNTSRV");
       
   111 
       
   112 
       
   113 /**
       
   114 Open a Contacts server session.
       
   115 */
       
   116 void RCntModel::ConnectL()
       
   117 	{
       
   118 	// Assume the server is already running and attempt to create a session
       
   119 	// with a maximum of KAsyncMessageSlots message slots.
       
   120 	TInt err = CreateSession(KCntServerName,Version(),KAsyncMessageSlots);
       
   121 	
       
   122 	if(err == KErrNotFound) // Server not running?
       
   123 		{
       
   124 		// Use the RProcess API to start the server.
       
   125 		RProcess server;
       
   126 		User::LeaveIfError(server.Create(KCntServerExe,KNullDesC));
       
   127 		
       
   128 		//Enforce server to be at system default priority EPriorityForeground
       
   129 		//Contact server used to set as EPriorityHigh and this caused client could
       
   130 		//not get control or responsive until sorting by the idle sorter in remote 
       
   131 		//view was done.
       
   132 		server.SetPriority(EPriorityForeground);
       
   133 		
       
   134 		// Synchronise with the server.
       
   135 		TRequestStatus reqStatus;
       
   136 		server.Rendezvous(reqStatus);
       
   137 		server.Resume();
       
   138 		
       
   139 		// Server will call the reciprocal static synchronisation call.
       
   140 		User::WaitForRequest(reqStatus);
       
   141 		server.Close();
       
   142 		User::LeaveIfError(reqStatus.Int());
       
   143 		
       
   144 		// Create the server session.
       
   145 		User::LeaveIfError(CreateSession(KCntServerName,Version(),KAsyncMessageSlots));
       
   146 		}
       
   147 	else
       
   148 		{
       
   149 		User::LeaveIfError(err);
       
   150 		}
       
   151 
       
   152 	// Create object packer/unpacker if it doesn't already exist.
       
   153 	if (iPackager == NULL)	
       
   154 		{
       
   155 		iPackager = CCntPackager::NewL();
       
   156 		}
       
   157 	
       
   158 	// Each session (client) will be given a unique ID known as the Connection
       
   159 	// ID.  This ID forms part of the database event notification message.  This
       
   160 	// ID is created during the connection to the server.
       
   161 	ConnectionId();
       
   162 	}
       
   163 
       
   164 	
       
   165 /**
       
   166 Close session.
       
   167 */
       
   168 void RCntModel::Close()
       
   169 	{
       
   170 	delete iPackager;
       
   171 	iPackager = NULL;
       
   172 	delete iDbNotifyMonitor;
       
   173 	iDbNotifyMonitor = NULL;
       
   174 	RHandleBase::Close();
       
   175 	}
       
   176 
       
   177 
       
   178 /**
       
   179 Open a named contact database.
       
   180 
       
   181 Opens the default contacts database if the default argument is used.  The given
       
   182 descriptor must not contain more than KCntMaxFilePath characters.
       
   183 
       
   184 @param aCntFile Filename (in the form drive:database).  Defaults to
       
   185 KCntDefaultDrive.
       
   186 
       
   187 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   188         maximum length of 190 characters, otherwise one of the System error codes.
       
   189 
       
   190 @capability ReadUserData
       
   191 */
       
   192 TInt RCntModel::OpenDatabase(const TDesC& aCntFile) const
       
   193     {
       
   194     TInt err = SetFileName(aCntFile);
       
   195     if (err == KErrNone)
       
   196         {
       
   197         TIpcArgs args;
       
   198         args.Set(0,&aCntFile);
       
   199         err = SendReceive(ECntOpenDataBase, args);
       
   200         }
       
   201 
       
   202     return err;
       
   203     }
       
   204 
       
   205 
       
   206 /**
       
   207 Open a named contact database asynchronously.
       
   208 
       
   209 Opens the default contacts database if the default argument is used.  The given
       
   210 descriptor must not contain more than KCntMaxFilePath characters.
       
   211 
       
   212 @param aStatus Asynchronous request object.  Request is completed when database
       
   213 has been opened.
       
   214 @param aCntFile Contacts database filename (in the form drive:database).
       
   215 Defaults to KCntDefaultDrive.
       
   216 
       
   217 @capability ReadUserData
       
   218 */
       
   219 void RCntModel::OpenDatabaseAsyncL(TRequestStatus& aStatus, const TDesC& aCntFile)
       
   220     {
       
   221     User::LeaveIfError(SetFileName(aCntFile));
       
   222 
       
   223     TIpcArgs args;
       
   224     args.Set(0,&aCntFile);
       
   225     SendReceive(ECntOpenDataBase, args, aStatus);
       
   226     }
       
   227 
       
   228 
       
   229 /**
       
   230 Cancel last asynchronous database open request.
       
   231 
       
   232 @capability None
       
   233 */
       
   234 void RCntModel::CancelAsyncOpen() 
       
   235 	{
       
   236 	SendReceive(ECntCancelAsyncOpenDatabase);		
       
   237 	}
       
   238 
       
   239 
       
   240 /**
       
   241 Handle a premature termination of the contact server process by re-connecting
       
   242 the session and re-opening the database.
       
   243 
       
   244 @capability ReadUserData
       
   245 */
       
   246 void RCntModel::HandlePrematureServerTerminationL()
       
   247 	{
       
   248 	if (iNoOfSvrStartAttempts > KMaxTimesToRestartServer)
       
   249 		{
       
   250 		User::Leave(KErrServerTerminated);
       
   251 		}
       
   252 	ConnectL();
       
   253 	User::LeaveIfError(OpenDatabase(iFileName));
       
   254 	++iNoOfSvrStartAttempts;
       
   255 	}
       
   256 
       
   257 	
       
   258 /**
       
   259 Set the database filename. Used to re-open the database if the server is
       
   260 terminated prematurely.
       
   261 
       
   262 @param aCntFile Contacts database filename (in the form drive:database).
       
   263 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   264         maximum length of 190 characters.         
       
   265 */
       
   266 TInt RCntModel::SetFileName(const TDesC& aCntFile) const
       
   267     {
       
   268     if(aCntFile.Length() > KCntMaxFilePath)
       
   269         {
       
   270         return KErrArgument;
       
   271         }
       
   272 
       
   273     iFileName = aCntFile;
       
   274     return KErrNone;
       
   275     }
       
   276 
       
   277 
       
   278 /**
       
   279 Close currently open database.
       
   280 
       
   281 @capability None
       
   282 */
       
   283 void RCntModel::CloseDatabase() const
       
   284 	{
       
   285 	(void)SendReceive(ECntCloseDataBase);
       
   286 	}
       
   287 
       
   288 
       
   289 /**
       
   290 Get the machine ID. 
       
   291 
       
   292 Note: This function can leave.
       
   293 
       
   294 @return Machine ID.
       
   295 
       
   296 @leave KErrNone The send operation is successful
       
   297 @leave KErrServerTerminated The server no longer present
       
   298 @leave KErrServerBusy There are no message slots available
       
   299 @leave KErrNoMemory There is insufficient memory available
       
   300 
       
   301 
       
   302 @capability None
       
   303 */
       
   304 TInt64 RCntModel::MachineId() const
       
   305 	{
       
   306 	TIpcArgs args;
       
   307 	TPckgBuf<TInt64> machineID;
       
   308 	args.Set(0, &machineID);
       
   309 	User::LeaveIfError(SendReceive(ECntMachineID, args)); // this can leave
       
   310 	return machineID();	
       
   311 	}
       
   312 
       
   313 
       
   314 /**
       
   315 Set the machine ID (debug only).
       
   316 
       
   317 @param aMachineUniqueId New machine ID.
       
   318 
       
   319 @capability None
       
   320 */
       
   321 void RCntModel::OverrideMachineUniqueId(TInt64 aMachineUniqueId)
       
   322 	{
       
   323 	TIpcArgs args;
       
   324 	TPckgBuf<TInt64> machineID(aMachineUniqueId);
       
   325 	args.Set(0, &machineID);
       
   326 	(void)SendReceive(ECntOverrideMachineID, args);	
       
   327 	}
       
   328 
       
   329 
       
   330 /**
       
   331 Replace a named contact database with an empty one, replacing any database with
       
   332 the same name.  Replaces the default contacts database if the default argument
       
   333 is used.  The given descriptor must not contain more than KCntMaxFilePath
       
   334 characters.
       
   335 
       
   336 @param aCntFile Contacts database filename (in the form drive:database).
       
   337 Defaults to KCntDefaultDrive.
       
   338 
       
   339 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   340         maximum length of 190 characters, KErrInUse if the database is currently open, 
       
   341         otherwise one of the System error codes.
       
   342 
       
   343 @capability WriteUserData
       
   344 */
       
   345 TInt RCntModel::ReplaceDatabase(const TDesC& aCntFile) const
       
   346     {
       
   347     TInt err = SetFileName(aCntFile);
       
   348     if (err == KErrNone)
       
   349         {
       
   350         TIpcArgs args;
       
   351         args.Set(0,&aCntFile);
       
   352 
       
   353         err = SendReceive(ECntReplaceDatabase, args);
       
   354         }
       
   355 
       
   356     return err;
       
   357     }
       
   358 
       
   359 
       
   360 /**
       
   361 Returns an array of contact item IDs for all the contact items which may contain
       
   362 the specified telephone number in a telephone, fax or SMS type field.
       
   363 
       
   364 @see CContactDatabase::MatchPhoneNumberL() for more details on the match.
       
   365 
       
   366 @param aNumber Phone number string
       
   367 @param aMatchLengthFromRight Number of digits from the right of the phone number
       
   368 to use.  Up to 15 digits can be specified and it is recommended that at least 7
       
   369 match digits are specified.
       
   370 
       
   371 @return CContactIdArray of candidate matches.
       
   372 
       
   373 @capability ReadUserData
       
   374 */
       
   375 CContactIdArray* RCntModel::MatchPhoneNumberL(const TDesC& aNumber, const TInt aMatchLengthFromRight)
       
   376 	{
       
   377 	TIpcArgs args;
       
   378 	args.Set(0, &iPackager->GetReceivingBufferL());
       
   379 	args.Set(1, MLplCollection::EMatchPhoneNos);
       
   380 	args.Set(2, &aNumber);
       
   381 	args.Set(3, aMatchLengthFromRight);
       
   382 	
       
   383 	TInt newBuffSize = 0;
       
   384 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
   385 	
       
   386 	if (newBuffSize > 0)
       
   387 		{
       
   388 		// If the buffer is not large enough resize the packager's internal
       
   389 		// buffer and make the call again.
       
   390 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
   391 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
   392 		}
       
   393 		
       
   394 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
   395 	CleanupStack::Pop(idArray);
       
   396 
       
   397 	return idArray;
       
   398 	}
       
   399 	
       
   400 	
       
   401 
       
   402 /**
       
   403 Create an empty named contact database.
       
   404 
       
   405 Creates the default contacts database if the default argument is used.  The
       
   406 given descriptor must not contain more than KCntMaxFilePath characters.
       
   407 
       
   408 @param aCntFile Contacts database filename (in the form drive:database).
       
   409 Defaults to KCntDefaultDrive.
       
   410 
       
   411 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   412         maximum length of 190 characters, KErrAlreadyExists if the database already 
       
   413         exists otherwise one of the System error codes.
       
   414 
       
   415 @capability WriteUserData
       
   416 */
       
   417 TInt RCntModel::CreateDatabase(const TDesC& aCntFile) const
       
   418     {
       
   419     TInt err = SetFileName(aCntFile);
       
   420     if (err == KErrNone)
       
   421         {
       
   422         TIpcArgs args;
       
   423         args.Set(0,&aCntFile);
       
   424         err = SendReceive(ECntCreateDatabase, args);
       
   425         }
       
   426     return err;
       
   427     }
       
   428 
       
   429 
       
   430 /**
       
   431 Create the system template.
       
   432 
       
   433 @return KErrNone if success otherwise one of the System error codes.
       
   434 	
       
   435 @capability WriteUserData
       
   436 */
       
   437 TInt RCntModel::ReCreateTemplate() const
       
   438 	{
       
   439 	return SendReceive(ECntReCreateTemplate);
       
   440 	}
       
   441 
       
   442 
       
   443 /**
       
   444 Get the database file UID.
       
   445 
       
   446 @return Pointer to file UID.
       
   447 
       
   448 @capability None
       
   449 */
       
   450 TPtrC RCntModel::FileUidL() const
       
   451 	{
       
   452 	TIpcArgs args;
       
   453 	args.Set(0, &iFileUid);
       
   454 	User::LeaveIfError (SendReceive(ECntFileUniqueId, args));
       
   455     return iFileUid;
       
   456 	}
       
   457 
       
   458 
       
   459 /**
       
   460 Determine if the database is ready.  Ready in this context means that the
       
   461 database is open and readable/writable (i.e. the state machine is in
       
   462 CStateWritable).
       
   463 
       
   464 @capability None
       
   465 
       
   466 @return ETrue if the database is ready, EFalse if the database is not ready.
       
   467 */
       
   468 TBool RCntModel::DatabaseReadyL() const
       
   469     {
       
   470     TBool retVal = EFalse;
       
   471 
       
   472     // Although the ECntGetDatabaseReady msg. is completed with TBool values,
       
   473     // during message processing, it is possible that ServiceError() occurs,
       
   474     // causing the message to be completed with negative error codes.
       
   475     // LeaveIfError() would protect against such cases.
       
   476     User::LeaveIfError(retVal = SendReceive(ECntGetDatabaseReady));
       
   477 
       
   478     return retVal;
       
   479     }
       
   480 
       
   481 
       
   482 /**
       
   483 Tests whether a contact item's hint bit field matches a filter.
       
   484 
       
   485 @param aBitWiseFilter The filter to compare the item against.  This is a
       
   486 combination of TContactViewFilter values.
       
   487 @param aContactId The ID of the item in the database.
       
   488 
       
   489 @return ETrue if the item is of the correct type for inclusion in the database 
       
   490 and its hint bit field matches the specified filter, EFalse if either of these
       
   491 conditions are not met.
       
   492 
       
   493 @capability None
       
   494 */
       
   495 TBool RCntModel::ContactMatchesHintFieldL(TInt aBitWiseFilter, TContactItemId aContactId)
       
   496     {
       
   497     TIpcArgs args;
       
   498     args.Set(0, aBitWiseFilter);
       
   499     args.Set(1, aContactId);
       
   500     TBool retVal = EFalse;
       
   501 
       
   502     // Although the ECntMatchesHintField msg. is completed with TBool values,
       
   503     // during message processing, it is possible that ServiceError() occurs,
       
   504     // causing the message to be completed with negative error codes.
       
   505     // LeaveIfError() would protect against such cases.
       
   506     User::LeaveIfError (retVal = SendReceive(ECntMatchesHintField, args));
       
   507 
       
   508     return retVal;
       
   509     }
       
   510 
       
   511 
       
   512 /**
       
   513 Delete a named contact database.
       
   514 
       
   515 Deletes the default contacts database if the default argument is used.  The
       
   516 given descriptor must not contain more than KCntMaxFilePath characters.
       
   517 
       
   518 @param aCntFile Contacts database filename (in the form drive:database).
       
   519 Defaults to KCntDefaultDrive.
       
   520 
       
   521 @return KErrNone if success, KErrArgument if the given descriptor contains more 
       
   522         than the maximum length of 190 characters, KErrInUse if the database is 
       
   523         in use, KErrNotFound if the database does not exist otherwise one of the 
       
   524         System error codes.
       
   525 
       
   526 @capability WriteUserData
       
   527 */
       
   528 TInt RCntModel::DeleteDatabase(const TDesC& aCntFile) const
       
   529 	{
       
   530 	if(aCntFile.Length() > KCntMaxFilePath)
       
   531 		{
       
   532 		return KErrArgument;
       
   533 		}
       
   534 	TIpcArgs args;
       
   535 	args.Set(0,&aCntFile);
       
   536 	return SendReceive(ECntDeleteDatabase,args);
       
   537 	}
       
   538 
       
   539 
       
   540 /**
       
   541 Get the name of the default contact database file.
       
   542 
       
   543 The given descriptor must have room for minimum of KCntMaxFilePath characters.
       
   544 
       
   545 @param aCntFile Contains the default contact database name on return.
       
   546 
       
   547 @return KErrNone if success, KErrArgument if the given descriptor contains more 
       
   548         than the maximum length of 190 characters, otherwise one of the System 
       
   549         error codes.
       
   550 
       
   551 @capability None
       
   552 */
       
   553 TInt RCntModel::DefaultDatabase(TDes& aCntFile) const
       
   554 	{
       
   555 	TIpcArgs args;
       
   556 	args.Set(0,&aCntFile);
       
   557 	return SendReceive(ECntGetDefaultDatabaseName,args);
       
   558 	}
       
   559 
       
   560 
       
   561 /**
       
   562 Retrieve the current contact database drive.
       
   563 
       
   564 @param aDriveUnit Contains the current contact database drive unit on return.
       
   565 
       
   566 @return KErrNone if success otherwise one of the System error codes.
       
   567 
       
   568 @capability None
       
   569 */
       
   570 TInt RCntModel::DatabaseDrive(TDriveUnit& aDriveUnit) const
       
   571 	{
       
   572 	TInt ret = SendReceive(ECntDatabaseDrive);
       
   573 	if (ret >= KErrNone)
       
   574 		{
       
   575 		aDriveUnit = ret;	
       
   576 		}
       
   577 	return ret;
       
   578 	}
       
   579 
       
   580 
       
   581 /**
       
   582 Sets the contact database drive and optionally moves the default contact
       
   583 database from its current location to the new drive.  This function guarantees
       
   584 an all or nothing operation.  If the database is not successfully moved, the
       
   585 drive setting is not updated to reflect the change.
       
   586 
       
   587 @param aDriveUnit The drive to which to move the contact database.
       
   588 @param aCopy ETrue moves the existing file to the specified drive.  Deletion of
       
   589 the source file will fail if it is in use.  EFalse does not move the file.  The
       
   590 default argument value is ETrue.
       
   591 
       
   592 @return KErrNone if success, KErrInUse if destination file for copy is open,
       
   593 KErrNotFound found if source contact database (default) cannot be found,
       
   594 KErrAlreadyExists if the destination contact database file exists.
       
   595 
       
   596 @capability WriteUserData
       
   597 */
       
   598 void RCntModel::SetDatabaseDriveL(TDriveUnit aDriveUnit, TBool aCopy)
       
   599 	{
       
   600 	TIpcArgs args;
       
   601 	args.Set(0,aDriveUnit);
       
   602 	args.Set(1,aCopy);
       
   603 	User::LeaveIfError(SendReceive(ECntSetDatabaseDrive,args));
       
   604 	}
       
   605 
       
   606 /** 
       
   607 Gets the size of the database file in bytes.
       
   608 
       
   609 @return The size of the contact database in bytes.
       
   610 
       
   611 @capability None
       
   612 */
       
   613 TInt RCntModel::FileSize() const
       
   614 	{
       
   615 	return SendReceive(ECntFilesSize);	
       
   616 	}
       
   617 
       
   618 /**
       
   619 Determine if the named contact database file exists.
       
   620 
       
   621 If the aCntFile argument is the default, determines if default contact database
       
   622 file exists.
       
   623 
       
   624 @param aCntFile Contacts database filename (in the form drive:database).
       
   625 @leave KErrArgument if the given descriptor contains more than the maximum length 
       
   626        of 190 characters, otherwise one of the System error codes.
       
   627 @return ETrue if exists, EFalse does not exist. 
       
   628 @capability None
       
   629 */
       
   630 TBool RCntModel::DatabaseExistsL(const TDesC& aCntFile) const
       
   631     {
       
   632     if(aCntFile.Length() > KCntMaxFilePath)
       
   633         {
       
   634         User::Leave(KErrArgument);
       
   635         }
       
   636 
       
   637     TIpcArgs args;
       
   638     args.Set(0,&aCntFile);
       
   639     TBool ret = EFalse;
       
   640 
       
   641     // Although ECntDatabaseExists is normally completed with TBool values,
       
   642     // ServiceError() can occur which leads to a negative system error codes
       
   643     // being returned.  User::LeaveIfError will allow that to be properly handled.
       
   644     User::LeaveIfError(ret = SendReceive(ECntDatabaseExists,args));
       
   645 
       
   646     return ret;
       
   647     }
       
   648 
       
   649 
       
   650 /**
       
   651 List the contact database files for any given drive unit.  Lists all databases
       
   652 on all drives if aDriveUnit is set to NULL.
       
   653 
       
   654 @param aDriveUnit The drive unit to search.  Searches all drives if default
       
   655 argument is used.
       
   656 
       
   657 @return CDesCArray containing the database list.  Always returns list even if
       
   658 empty.
       
   659 
       
   660 @leave KErrNoMemory if not enough free memory, KErrNotReady if drive does not,
       
   661 otherwise one of the System error codes.
       
   662 
       
   663 @capability ReadUserData
       
   664 */
       
   665 CDesCArray* RCntModel::ListDatabasesL(TDriveUnit* aDriveUnit) const
       
   666 	{
       
   667 	// Convert the drive unit to an integer for IPC.  The TDriveUnit constructor
       
   668 	// does not allow values outside 0 - 25.
       
   669 	TInt driveNumber;
       
   670 	(aDriveUnit == NULL) ? (driveNumber = ECntAllDrives) : (driveNumber = *aDriveUnit);
       
   671 
       
   672 	// Provide a CBufFlat for receiving the list of databases from the server.
       
   673 	// Format is a (proprietary) serialized CDesCArray.
       
   674 	const TInt KInitialBufferSize = 200;
       
   675 	CBufFlat* listBuffer = CBufFlat::NewL(KInitialBufferSize);
       
   676 	CleanupStack::PushL(listBuffer);
       
   677 	listBuffer->ExpandL(0,KInitialBufferSize);
       
   678 
       
   679 	// IPC argument list is:
       
   680 	// 0 (Return param)	- Address of our receive buffer
       
   681 	// 1 (Param)		- The drive number 0 - 25 or ECntAllDrives
       
   682 	// 2 (Return param)	- The size of buffer required for the transfer
       
   683 	TIpcArgs args;
       
   684 	TPtr8 ptr(listBuffer->Ptr(0));
       
   685 	args.Set(0,&ptr);
       
   686 	args.Set(1,driveNumber);
       
   687 	TPckgBuf<TInt> size;
       
   688 	args.Set(2,&size);
       
   689 	User::LeaveIfError(SendReceive(ECntListDatabases,args));
       
   690 
       
   691 	// Check if our buffer was large enough by reading returned size argument.
       
   692 	// The server will not have written any data if our povided buffer was not
       
   693 	// big enough.
       
   694 	if(size() > KInitialBufferSize)
       
   695 		{
       
   696 		// Not big enough but now we know how big the buffer needs to be.
       
   697 		// Just allocate buffer again, reset the IPC args and call again.
       
   698 		CleanupStack::PopAndDestroy(listBuffer);
       
   699 		listBuffer = CBufFlat::NewL(size());
       
   700 		CleanupStack::PushL(listBuffer);
       
   701 		listBuffer->ExpandL(0,size());
       
   702 		ptr.Set(listBuffer->Ptr(0));
       
   703 		args.Set(0,&ptr);
       
   704 		args.Set(1,driveNumber);
       
   705 		args.Set(2,&size);
       
   706 		User::LeaveIfError(SendReceive(ECntListDatabases,args));
       
   707 		}
       
   708 
       
   709 	// Wrap the buffer in a read stream class to internalize.
       
   710 	RBufReadStream readStream;
       
   711 	readStream.Open(*listBuffer);
       
   712 	CleanupClosePushL(readStream);
       
   713 
       
   714 	// Number of array elements.
       
   715 	const TInt count = readStream.ReadUint32L();
       
   716 	// Use count if it is not zero.
       
   717 	CDesCArray* list = new(ELeave) CDesCArrayFlat(count ? count : 1);
       
   718 	CleanupStack::PushL(list);
       
   719 	for (TInt i=0; i<count; ++i)
       
   720 		{
       
   721 		TFileName path;
       
   722 		TInt length=readStream.ReadInt8L();
       
   723 		readStream.ReadL(path,length);
       
   724 		// Add to the list.
       
   725 		list->AppendL(path);
       
   726 		}
       
   727 
       
   728 	CleanupStack::Pop(list);
       
   729 	CleanupStack::PopAndDestroy(&readStream);
       
   730 	CleanupStack::PopAndDestroy(listBuffer);
       
   731 	
       
   732 	return list;
       
   733 	}
       
   734 
       
   735 
       
   736 /**
       
   737 Add a new contact to the database.
       
   738 
       
   739 @param aContact The contact to be added to the database.
       
   740 
       
   741 @capability WriteUserData
       
   742 */
       
   743 TContactItemId RCntModel::CreateContactL(CContactItem& aContact) const
       
   744 	{
       
   745 	// Pack the contact into the first IPC argument.
       
   746 	TIpcArgs args;
       
   747 	TPtr8 ptr(iPackager->PackL(aContact));
       
   748 	args.Set(0,&ptr);
       
   749 
       
   750 	TInt cntId = 0;
       
   751 	User::LeaveIfError(cntId = SendReceive(ECntItemCreate, args));
       
   752 
       
   753 	return cntId;
       
   754 	}
       
   755 
       
   756 
       
   757 /**
       
   758 Delete a contact from the database.
       
   759 
       
   760 @param aContact The contact to be deleted.
       
   761 @param aCntEventType The event type to pass on to the observers.
       
   762 @param aDecAccessCount If ETrue access count should be decremented prior to the
       
   763 deletion.
       
   764 
       
   765 @capability WriteUserData
       
   766 */
       
   767 void RCntModel::DeleteContactL(TContactItemId aCntId, TCntSendEventAction aCntEventType, TBool aDecAccessCount) const
       
   768 	{
       
   769 	TIpcArgs args(aCntId, aCntEventType, aDecAccessCount);
       
   770 	User::LeaveIfError(SendReceive(ECntItemDelete, args));
       
   771 	}
       
   772 
       
   773 /** 
       
   774 Open the database tables.
       
   775 
       
   776 @capability ReadUserData
       
   777 */
       
   778 void RCntModel::OpenTablesL()
       
   779 	{
       
   780 	User::LeaveIfError(SendReceive(ECntReOpenDbTables));
       
   781 	}
       
   782 
       
   783 
       
   784 /**
       
   785 Close the database tables.
       
   786 
       
   787 @capability None
       
   788 */
       
   789 void RCntModel::CloseTablesL()
       
   790 	{
       
   791 	User::LeaveIfError(SendReceive(ECntCloseDbTables));
       
   792 	}
       
   793 
       
   794 
       
   795 /**
       
   796 Update and unlock an existing contact in the database.
       
   797 
       
   798 @param aContact The contact to be updated and unlocked
       
   799 @param aSendChangedEvent If ETrue the changed event should be sent after the
       
   800 update/unlock.
       
   801 
       
   802 @capability WriteUserData
       
   803 */
       
   804 void RCntModel::CommitContactL(const CContactItem& aContact, TBool aSendChangedEvent) const
       
   805 	{
       
   806 	// Pack the contact into the first IPC argument.
       
   807 	TIpcArgs args; 
       
   808 	TPtr8 ptr(iPackager->PackL((const_cast<CContactItem&>(aContact))));
       
   809 	args.Set(0,&ptr);
       
   810 	
       
   811 	args.Set(1,aSendChangedEvent);
       
   812 
       
   813 	User::LeaveIfError(SendReceive(ECntItemCommit, args));
       
   814 	}
       
   815 
       
   816 
       
   817 /**
       
   818 Unpacks a contact item contained within the Packager's internal buffer and
       
   819 creates a contact item object.  Within the server, the contact item has been
       
   820 written to the Packager's internal buffer by the RMessage2.
       
   821 
       
   822 If the buffer size was returned then the buffer was not large enough to hold a
       
   823 serialised contact item.  The buffer must be expanded to the size returned by
       
   824 the server (ie aBufferSize) and the read operation performed again. 
       
   825 
       
   826 @see CCntPackager::SetBufferFromMessageL()
       
   827 	
       
   828 @param aBufferSize The new buffer size.
       
   829 @param aArgs The argument buffer where the serialised contact item is written by
       
   830 the server.
       
   831 
       
   832 @return CContactItem unpacked from Packager's internal buffer.
       
   833 
       
   834 @capability ReadUserData
       
   835 */
       
   836 CContactItem* RCntModel::UnPackContactLC(TInt aBufferSize, TIpcArgs& aArgs) const
       
   837 	{
       
   838 	if(aBufferSize > 0) // Packager's internal buffer is not large enough.
       
   839 		{
       
   840 		// Set new extended receiving buffer.
       
   841 		aArgs.Set(1, &iPackager->GetReceivingBufferL(aBufferSize));
       
   842 		// Perform read operation again.
       
   843 		User::LeaveIfError(SendReceive(ECntItemRead, aArgs));
       
   844 		}
       
   845 	return iPackager->UnpackCntItemLC();
       
   846 	}
       
   847 
       
   848 
       
   849 /**
       
   850 Read an existing contact in the database.
       
   851 
       
   852 @param aCntItemVDef The view definition to use.
       
   853 @param aCntId Contact ID to read.
       
   854 
       
   855 @return CContactItem object with contact ID aCntId.
       
   856 */
       
   857 CContactItem* RCntModel::ReadContactL(const CContactItemViewDef* aCntItemVDef, TContactItemId aCntId) const
       
   858 	{
       
   859 	TIpcArgs args;
       
   860 
       
   861 	if (aCntItemVDef) 
       
   862 		{
       
   863 		iPackager->PackL(*(const_cast<CContactItemViewDef*>(aCntItemVDef)));
       
   864 		// Indicates that a user ContactItemViewDef is present in first IPC
       
   865 		// argument.
       
   866 		args.Set(3,TRUE);
       
   867 		}
       
   868 	else
       
   869 		{
       
   870 		iPackager->Clear();
       
   871 		// Indicates that no user ContactItemViewDef is present in first IPC
       
   872 		// argument.  The default view definition will be used instead.
       
   873 		args.Set(3,FALSE);
       
   874 		}
       
   875 
       
   876 	args.Set(0, &iPackager->GetTransmittingBuffer());
       
   877 	args.Set(1, &iPackager->GetReceivingBufferL());
       
   878 	args.Set(2, aCntId);
       
   879 
       
   880 	TInt newBuffSize = 0;
       
   881 	User::LeaveIfError(newBuffSize = SendReceive(ECntItemRead, args));
       
   882 	CContactItem* cntItem = UnPackContactLC(newBuffSize, args);
       
   883 	CleanupStack::Pop(cntItem);
       
   884 
       
   885 	return cntItem;
       
   886 	}
       
   887 	
       
   888 	
       
   889 /**
       
   890 Open and lock an existing contact in the database.  The contact item lock is
       
   891 pushed onto the cleanup stack.
       
   892 
       
   893 @param aCntItemVDef The view definition to use.
       
   894 @param aCntId Contact ID to read.
       
   895 
       
   896 @return Opened/locked CContactItem object.
       
   897 */
       
   898 CContactItem* RCntModel::OpenContactLX(const CContactItemViewDef* aCntItemVDef, TContactItemId aCntId) const
       
   899 	{
       
   900 	TIpcArgs args;
       
   901 	if (aCntItemVDef) 
       
   902 		{
       
   903 		iPackager->PackL(*(const_cast<CContactItemViewDef*>(aCntItemVDef)));
       
   904 		// Indicates that a user ContactItemViewDef is present in first IPC
       
   905 		// argument.
       
   906 		args.Set(3,TRUE);
       
   907 		}
       
   908 	else
       
   909 		{
       
   910 		iPackager->Clear();
       
   911 		// Indicates that no user ContactItemViewDef is present in first IPC
       
   912 		// argument.  The default view definition will be used instead.
       
   913 		args.Set(3,FALSE);
       
   914 		}
       
   915 
       
   916 	args.Set(0, &iPackager->GetTransmittingBuffer());
       
   917 	args.Set(1, &iPackager->GetReceivingBufferL());
       
   918 	args.Set(2, aCntId);
       
   919 
       
   920 	TInt newBuffSize = 0;
       
   921 	User::LeaveIfError(newBuffSize = SendReceive(ECntItemOpen, args));
       
   922 
       
   923 	// Push the contact item lock onto the cleanup stack.  If UnPackContactLC()
       
   924 	// (or any other RCntModel method leaves after this point) then the last
       
   925 	// contact to be locked will be unlocked (aka closed).  The method returns
       
   926 	// with the lock remaining on the cleanup stack.
       
   927 	PushUnlockL(); 
       
   928 
       
   929 	CContactItem* cntItem = UnPackContactLC(newBuffSize, args);
       
   930 
       
   931 	CleanupStack::Pop(cntItem);
       
   932 
       
   933 	return cntItem;		
       
   934 	}
       
   935 
       
   936 
       
   937 /**
       
   938 Close/unLock an existing contact in the database.
       
   939 
       
   940 @param aCntId The contact ID of the contact to close.
       
   941 
       
   942 @return ETrue if the contact was opened before and closed after the call,
       
   943 EFalse if there was no need to close the contact.
       
   944 */
       
   945 TBool RCntModel::CloseContact(TContactItemId aCntId)
       
   946 	{
       
   947 	TInt res = SendReceive(ECntItemClose, TIpcArgs(aCntId));
       
   948 	if (res == KErrNone)
       
   949 		{
       
   950 		return ETrue;
       
   951 		}
       
   952 	return EFalse;
       
   953 	}
       
   954 
       
   955 
       
   956 /**
       
   957 Start a database transaction.
       
   958 */
       
   959 TInt RCntModel::BeginDbTransaction() const
       
   960 	{
       
   961 	return SendReceive(EBeginDbTransaction);
       
   962 	}
       
   963 
       
   964 	
       
   965 /**
       
   966 Commit a database transaction.
       
   967 */
       
   968 TInt RCntModel::CommitDbTransaction() const
       
   969 	{
       
   970 	return SendReceive(EEndDbTransaction);
       
   971 	}
       
   972 
       
   973 	
       
   974 /**
       
   975 Rollback a database transaction.
       
   976 */
       
   977 TInt RCntModel::RollbackDbTransaction() const
       
   978 	{
       
   979 	return SendReceive(ERollbackDbTransaction);
       
   980 	}
       
   981 
       
   982 
       
   983 /**
       
   984 Set the operation timeout value.  This value is the length of time that a
       
   985 deferred request will remain in the request queue in the State Machine before
       
   986 being completed with an error code.
       
   987 
       
   988 @param aMicroSeconds The operation timeout in microseconds.  This timeout will
       
   989 only be applied to requests sent by clients of this database after this point in
       
   990 time. 
       
   991 */
       
   992 void RCntModel::SetOperationTimeOutL(const TInt aMicroSeconds) const
       
   993 	{
       
   994 	TIpcArgs args;
       
   995 	args.Set(0, aMicroSeconds);
       
   996 	User::LeaveIfError(SendReceive(ECntOpsTimeOut, args));		
       
   997 	}
       
   998 
       
   999 	
       
  1000 /**
       
  1001 Change the existing contact view definition on the server.
       
  1002 
       
  1003 @param aView The new contact view defintion.
       
  1004 */
       
  1005 void RCntModel::SetViewDefinitionL(const CContactViewDef& aView)
       
  1006 	{
       
  1007 	TPtr8 ptr(iPackager->PackL(aView));
       
  1008 	User::LeaveIfError(SendReceive(ECntChangeViewDef, TIpcArgs(&ptr)));	
       
  1009 	}
       
  1010 
       
  1011 
       
  1012 /**
       
  1013 Add a database event observer.
       
  1014 
       
  1015 @param aObserver Observer callback inteface used to send database event.
       
  1016 */
       
  1017 void RCntModel::AddObserverL(MContactDbObserver& aObserver)
       
  1018 	{
       
  1019 	// If this is the first observer to be added then required to create the
       
  1020 	// database event notification monitor (lazy initialisation).
       
  1021 	if (!iDbNotifyMonitor)
       
  1022 		{
       
  1023 		iDbNotifyMonitor = CCntDbNotifyMonitor::NewL(*this);
       
  1024 		}
       
  1025 	iDbNotifyMonitor->AddObserverL(aObserver);
       
  1026 	}
       
  1027 
       
  1028 	
       
  1029 /**
       
  1030 Remove a database event observer.
       
  1031 
       
  1032 @param aObserver Observer callback inteface to be removed.
       
  1033 */
       
  1034 void RCntModel::RemoveObserver(const MContactDbObserver& aObserver)
       
  1035 	{
       
  1036 	if (iDbNotifyMonitor)
       
  1037 		{
       
  1038 		iDbNotifyMonitor->RemoveObserver(aObserver);
       
  1039 		// If this is the last observer to be removed then dispose of the
       
  1040 		// database event notification monitor (no longer required).
       
  1041 		if (iDbNotifyMonitor->NumberOfListeners() == 0)
       
  1042 			{
       
  1043 			delete iDbNotifyMonitor;
       
  1044 			iDbNotifyMonitor = NULL;
       
  1045 			}
       
  1046 		}
       
  1047 	}
       
  1048 
       
  1049 
       
  1050 /**
       
  1051 Request a database event from the server.
       
  1052 
       
  1053 @param aStatus Completed when database event is available.
       
  1054 @param aEvent When aStatus is completed contains the database event.
       
  1055 */
       
  1056 void RCntModel::StartNotificationTransfer(TRequestStatus& aStatus, TDes8& aEvent)
       
  1057 	{	
       
  1058 	SendReceive(ECntRequestEvent, TIpcArgs(&aEvent), aStatus);	
       
  1059 	}
       
  1060 
       
  1061 
       
  1062 /**
       
  1063 End (cancel) request for database event from server.
       
  1064 */
       
  1065 void RCntModel::EndNotificationTransfer()
       
  1066 	{	
       
  1067 	SendReceive(ECntCancelEventRequest);	
       
  1068 	}
       
  1069 	
       
  1070 /** 
       
  1071 Sets the ID of the current item and persists it in the database.  The current 
       
  1072 item is provided for use by clients who want to identify one contact item in the
       
  1073 database as the currently selected item.
       
  1074 
       
  1075 @param aContactId The ID of the current item. 
       
  1076 
       
  1077 @capability WriteUserData
       
  1078 */
       
  1079 void RCntModel::SetCurrentItem(TContactItemId aContactId) const
       
  1080 	{
       
  1081 	TIpcArgs args(aContactId);
       
  1082 	(void)SendReceive(ECntSetCurrentItem, args);	
       
  1083 	}
       
  1084 
       
  1085 	
       
  1086 /** 
       
  1087 Gets the ID of the current item, as set by SetCurrentItem().  The current item 
       
  1088 ID is initialised to KNullContactId when the database is opened.
       
  1089 
       
  1090 @return The ID of the current item. 
       
  1091 
       
  1092 @capability None
       
  1093 */
       
  1094 TContactItemId RCntModel::CurrentItem() const
       
  1095 	{		
       
  1096 	 TContactItemId id = SendReceive(ECntGetCurrentItem);
       
  1097 	 if (id < 0)
       
  1098 	 	{
       
  1099 		return KNullContactId;
       
  1100 		}
       
  1101 	 else
       
  1102 	 	{
       
  1103 		return id;
       
  1104 		}
       
  1105 	}
       
  1106 
       
  1107 
       
  1108 /** 
       
  1109 When there are multiple contact databases on a device this method can be used to
       
  1110 enquire which database is the current one.
       
  1111 
       
  1112 The current database functions are provided as part of current item
       
  1113 functionality.  In order to pass a current item from one contacts model client
       
  1114 to another, the receiving client needs to be using the same database.
       
  1115 
       
  1116 The current database is a path and filename, set using SetCurrentDatabase(),
       
  1117 which is persisted by the contacts server.
       
  1118 
       
  1119 @deprecated
       
  1120 
       
  1121 @param aDatabase The path and filename of the current database.  KNullDesC 
       
  1122 if no current database has been set.
       
  1123 
       
  1124 @return KErrNone if success otherwise one of the System error codes. 
       
  1125 
       
  1126 @capability None
       
  1127 */
       
  1128 TInt RCntModel::GetCurrentDatabase(TDes& aDatabase) const
       
  1129 	{
       
  1130 	TIpcArgs args(&aDatabase);
       
  1131 	return SendReceive(ECntGetCurrentDb, args);
       
  1132 	}
       
  1133 
       
  1134 
       
  1135 /** 
       
  1136 When there are multiple contact databases on a device this method can be used to
       
  1137 set a database as the current one.
       
  1138 
       
  1139 Note: this function simply updates a file name which is stored by the Contacts
       
  1140 server and its use is optional.  It is provided as part of current item
       
  1141 functionality. 
       
  1142 
       
  1143 In order to pass a current item from one contacts model client to another, 
       
  1144 the receiving client needs to be using the same database.
       
  1145 
       
  1146 @deprecated
       
  1147 
       
  1148 @param aDatabase The path and filename of the current database.
       
  1149 
       
  1150 @return KErrNone if success otherwise one of the System error codes. 
       
  1151 
       
  1152 @capability WriteUserData
       
  1153 */
       
  1154 TInt RCntModel::SetCurrentDatabase(const TDesC& aDatabase) const
       
  1155 	{
       
  1156 	TIpcArgs args(&aDatabase);
       
  1157 	return SendReceive(ECntSetCurrentDb, args);
       
  1158 	}
       
  1159 
       
  1160 
       
  1161 /** 
       
  1162 Returns the ID of the contact item whose telephone number field is mapped to 
       
  1163 the speed dial position specified.
       
  1164 
       
  1165 This function is provided so that information may be displayed about a contact
       
  1166 item whose telephone number is being dialled using speed dialling.
       
  1167 
       
  1168 The function also retrieves the telephone number stored in the field.
       
  1169 
       
  1170 @param aSpeedDialPosition The speed dial position.  This is an integer in the 
       
  1171 range 1 to 9 inclusive.  If outside this range, the function leaves with
       
  1172 KErrArgument.
       
  1173 @param aPhoneNumber On return contains the telephone number which is mapped to
       
  1174 the speed dial position specified.  Returns KNullDesC if the speed dial position
       
  1175 requested has not been set.
       
  1176 
       
  1177 @return The ID of the contact item to which the speed dial is mapped. 
       
  1178 
       
  1179 @capability ReadUserData
       
  1180 */
       
  1181 TContactItemId RCntModel::GetSpeedDialFieldL(TInt aSpeedDialPosition, TDes& aPhoneNumber)
       
  1182 	{
       
  1183 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex , User::Leave(KErrArgument));	
       
  1184 	TPckgBuf<TContactItemId> contact(KNullContactId);
       
  1185 	TIpcArgs args(aSpeedDialPosition,&aPhoneNumber);
       
  1186 	return (TContactItemId)SendReceive(ECntGetSpeedDialContactIdAndPhoneNumber, args);
       
  1187 	}
       
  1188 
       
  1189 	
       
  1190 /**
       
  1191 Sets a field containing a telephone number as a speed dial field.  The field 
       
  1192 is identified by aFieldIndex within the contact item aItem.  It is assigned a 
       
  1193 speed dial position between 1 and 9 inclusive.
       
  1194 
       
  1195 The field's speed dial and user added attributes are set and the appropriate 
       
  1196 UID (KUidSpeedDialXxx) is added to the field's content type.  The changes are 
       
  1197 committed to the database.
       
  1198 
       
  1199 Notes:
       
  1200 
       
  1201 - If an item's telephone number field has already been assigned to position 
       
  1202 aSpeedDialPosition, that item is updated so that the speed dial attribute 
       
  1203 is removed from its field and the speed dial field type UID is removed from 
       
  1204 the field's content type, before the new speed dial field is set.
       
  1205 
       
  1206 - The speed dial attribute can be tested for using the
       
  1207 CContactItemField::IsSpeedDial() method.
       
  1208 
       
  1209 - The contact item passed to this function (aItem) must have been obtained using 
       
  1210 one of the variants of CContactDatabase::OpenContactL().  This is because it 
       
  1211 is modified and committed to the database by this function - no further 
       
  1212 commits are necessary.
       
  1213 
       
  1214 @param aItem The contact item containing the field to set as a speed dial 
       
  1215 field.
       
  1216 @param aFieldIndex Index of a field in aItem's field set to set as a speed dial
       
  1217 field.
       
  1218 @param aSpeedDialPosition The speed dial position.  This is an integer in the 
       
  1219 range 1 to 9 inclusive.  If outside this range, the function leaves with
       
  1220 KErrArgument. 
       
  1221 
       
  1222 @leave KErrDiskFull The disk does not have enough free space to perform the
       
  1223 operation.
       
  1224 
       
  1225 @capability ReadUserData
       
  1226 @capability WriteUserData
       
  1227 */
       
  1228 void RCntModel::SetFieldAsSpeedDialL(TContactItemId aContactId, TInt aFieldIndex, TInt aSpeedDialPosition)
       
  1229 	{
       
  1230 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex , User::Leave(KErrArgument));
       
  1231 	TIpcArgs args(aSpeedDialPosition, aContactId, aFieldIndex);
       
  1232 	User::LeaveIfError(SendReceive(ECntSetSpeedDialIdForPosition, args));
       
  1233 	}
       
  1234 
       
  1235 
       
  1236 /** 
       
  1237 Removes the mapping between a contact item field and a speed dial position.
       
  1238 
       
  1239 Removes the KUidSpeedDialXxx UID from the field's content type, removes the 
       
  1240 field's speed dial attribute and commits the changes to the item.
       
  1241 
       
  1242 @param aContactId The ID of the contact item containing the speed dial field.
       
  1243 @param aSpeedDialPosition The speed dial position.  This is an integer in the 
       
  1244 range 1 to 9 inclusive.  If outside this range, the function leaves with
       
  1245 KErrArgument. 
       
  1246 
       
  1247 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1248 
       
  1249 @capability ReadUserData
       
  1250 @capability WriteUserData
       
  1251 */
       
  1252 void RCntModel::RemoveSpeedDialFieldL(TContactItemId aContactId, TInt aSpeedDialPosition)
       
  1253 	{
       
  1254 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex , User::Leave(KErrArgument));
       
  1255 	// Tell the server that this speed dial slot is now free.  Third argument
       
  1256 	// (i.e. field index) is not used.
       
  1257 	TIpcArgs args(aSpeedDialPosition, aContactId, -1);
       
  1258 	User::LeaveIfError(SendReceive(ECntSetSpeedDialIdForPosition, args));		
       
  1259 	}
       
  1260 
       
  1261 
       
  1262 /**
       
  1263 Returns the ID of the template that should be used with CContactICCEntry items.
       
  1264 If aPhonebookUid is set, the ID of the template belonging to the phonebook with 
       
  1265 TUid aPhonebookUid is returned.
       
  1266 
       
  1267 @param aPhonebookUid The phonebook ID with default KNullUid.
       
  1268 
       
  1269 @return A template ID.
       
  1270 */
       
  1271 TContactItemId RCntModel::ICCTemplateIdL(TUid aPhonebookUid)
       
  1272 	{
       
  1273 	TIpcArgs args(aPhonebookUid.iUid);
       
  1274 	return SendReceive(ECntICCTemplateId, args);
       
  1275 	}
       
  1276 
       
  1277 
       
  1278 /**
       
  1279 Returns the ID of the contacts model group which represents the ADN phonebook.
       
  1280 
       
  1281 @return ADN phonebook group ID.
       
  1282 */ 
       
  1283 TContactItemId RCntModel::PhonebookGroupIdL()
       
  1284 	{
       
  1285 	return SendReceive(ECntPhonebookGroupId);
       
  1286 	}
       
  1287 
       
  1288 
       
  1289 /** 
       
  1290 Sets an existing contact item to be the database's current own card.
       
  1291 
       
  1292 @param aContact The contact item to set as the database's current own card. 
       
  1293 It must already exist in the database.  It cannot be a group or a template.
       
  1294 
       
  1295 @leave KErrNotFound aContact does not exist in the database. 
       
  1296 @leave KErrDiskFull The disk does not have enough free space to perform the
       
  1297 operation.
       
  1298 
       
  1299 @capability None
       
  1300 */
       
  1301 void RCntModel::SetOwnCardL(const CContactItem& aContact)
       
  1302 	{
       
  1303 	TIpcArgs args; 
       
  1304 	TPtr8 ptr(iPackager->PackL(aContact));
       
  1305 	args.Set(0,&ptr);
       
  1306 	User::LeaveIfError(SendReceive(ECntSetOwnCard, args));	
       
  1307 	}
       
  1308 
       
  1309 
       
  1310 /**
       
  1311 Returns the ID of the database's current own card. 
       
  1312 
       
  1313 Having obtained this ID, the client may then open the own card in the same 
       
  1314 way as an ordinary contact card (using ReadContactL() or OpenContactL()).
       
  1315 
       
  1316 @return The ID of the database's current own card.  KNullContactId if the own 
       
  1317 card has been deleted or has not yet been set.
       
  1318 */
       
  1319 TContactItemId RCntModel::OwnCard() const
       
  1320 	{
       
  1321 	return static_cast<TContactItemId>(SendReceive(ECntGetOwnCard));
       
  1322 	}
       
  1323 
       
  1324 	
       
  1325 /**
       
  1326 Returns the connection ID of the current client session.
       
  1327 
       
  1328 @return Connection ID of the current client session.
       
  1329 */
       
  1330 TInt RCntModel::ConnectionId() const
       
  1331 	{
       
  1332 	// If asking for the connection ID the first time, then we ask the server
       
  1333 	// about the session id (lazy initialisation).
       
  1334 	if (!iConnectionId)
       
  1335 		{
       
  1336 		iConnectionId = SendReceive(ECntConnectionId); 	
       
  1337 		}
       
  1338 	return iConnectionId;		
       
  1339 	}
       
  1340 
       
  1341 
       
  1342 /** 
       
  1343 Debug only.
       
  1344 
       
  1345 @capability None
       
  1346 */
       
  1347 void RCntModel::SetHeapFailure(RHeap::TAllocFail aType, TInt aRate)
       
  1348 	{	
       
  1349 	TIpcArgs args(aType,aRate);
       
  1350 	SendReceive(ECntSetHeapFailure,args);
       
  1351 	}
       
  1352 
       
  1353 	
       
  1354 /** 
       
  1355 Debug only.
       
  1356 
       
  1357 @return The heap size usage of the server in debug mode, 0 in release mode.
       
  1358 
       
  1359 @capability None
       
  1360 */
       
  1361 TInt RCntModel::ResourceCount()
       
  1362 	{
       
  1363 	return(SendReceive(ECntResourceCount));
       
  1364 	}	
       
  1365 
       
  1366 	
       
  1367 /**
       
  1368 Returns the ID of the database's preferred template, as set by the method
       
  1369 SetPrefTemplateL().  The preferred template is for clients who may have 
       
  1370 multiple templates but want to identify one as preferred.
       
  1371 
       
  1372 @return The ID of the database's current preferred template.  KNullContactId if
       
  1373 not set.
       
  1374 */
       
  1375 TContactItemId RCntModel::PrefTemplateId() const
       
  1376 	{
       
  1377 	return(SendReceive(ECntGetPrefTemplateId));	
       
  1378 	}
       
  1379 
       
  1380 
       
  1381 /** 
       
  1382 Sets the database's preferred template.
       
  1383 
       
  1384 The preferred template's ID persists when the database is opened and closed. 
       
  1385 If the preferred template is subsequently deleted, the preferred template 
       
  1386 ID is set to KNullContactId.
       
  1387 
       
  1388 @param aContact The contact card template to set as the database's preferred 
       
  1389 template.
       
  1390 
       
  1391 @leave KErrNotSupported The item is not a template (i.e. is not of type
       
  1392 KUidContactCardTemplate).
       
  1393 @leave KErrDiskFull The disk does not have enough free space to perform the
       
  1394 operation.
       
  1395 
       
  1396 @capability WriteUserData
       
  1397 */
       
  1398 void RCntModel::SetPrefTemplateL(const TContactItemId aContactId)
       
  1399 	{
       
  1400 	TIpcArgs args(aContactId);
       
  1401 	User::LeaveIfError(SendReceive(ECntSetPrefTemplateId, args));
       
  1402 	}
       
  1403 
       
  1404 	
       
  1405 /**
       
  1406 Get a list of template IDs from the server.
       
  1407 
       
  1408 @return Array of template IDs.
       
  1409 */
       
  1410 CContactIdArray* RCntModel::FetchTemplateListIdsL()
       
  1411 {
       
  1412 	TIpcArgs args;
       
  1413 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1414 
       
  1415 	TInt newBuffSize;
       
  1416 	User::LeaveIfError(newBuffSize = SendReceive(ECntFetchTemplateIds, args));
       
  1417 	if (newBuffSize > 0)
       
  1418 		{
       
  1419 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1420 		User::LeaveIfError(newBuffSize = SendReceive(ECntFetchTemplateIds, args));		
       
  1421 		}
       
  1422 
       
  1423 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1424 	CleanupStack::Pop(idArray);
       
  1425 
       
  1426 	return idArray;	
       
  1427 }
       
  1428 
       
  1429 
       
  1430 /**
       
  1431 Get a list of group IDs from the server.
       
  1432 
       
  1433 @return Array of group IDs.
       
  1434 */
       
  1435 CContactIdArray* RCntModel::FetchGroupListIdsL()
       
  1436 {
       
  1437 	TIpcArgs args;
       
  1438 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1439 
       
  1440 	TInt newBuffSize;
       
  1441 	User::LeaveIfError(newBuffSize = SendReceive(ECntFetchGroupIdLists, args));
       
  1442 	if (newBuffSize > 0)
       
  1443 		{
       
  1444 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1445 		User::LeaveIfError(newBuffSize = SendReceive(ECntFetchGroupIdLists, args));		
       
  1446 		}
       
  1447 
       
  1448 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1449 	CleanupStack::Pop(idArray);
       
  1450 
       
  1451 	return idArray;	
       
  1452 }
       
  1453 
       
  1454 
       
  1455 /**
       
  1456 Get a collection of contact IDs using the specified collection parameters.
       
  1457 
       
  1458 @param aCollectionType Type of collection.
       
  1459 @param aTime Used if collection type is "changed since".
       
  1460 @param aGuid Used if collection type is "find GUID".
       
  1461 
       
  1462 @return Contact ID array of those contacts which match the specified collection
       
  1463 parameters.
       
  1464 */
       
  1465 CContactIdArray* RCntModel::CollectionL(TInt aCollectionType, TTime aTime,const TDesC& aGuid)
       
  1466 	{
       
  1467 	CContactIdArray* idArray = NULL;
       
  1468 	switch(aCollectionType)
       
  1469 	{
       
  1470 	case MLplCollection::EChangedSince :		
       
  1471 		{
       
  1472 		idArray = DoGetCollectionChangedSinceL(aTime);
       
  1473 		}
       
  1474 		break;
       
  1475 	case MLplCollection::EDeleted :
       
  1476 	case MLplCollection::EUnfiled :
       
  1477 		{
       
  1478 		idArray = DoGetCollectionL(aCollectionType);
       
  1479 		}
       
  1480 		break;
       
  1481 	case MLplCollection::EFindGuid :
       
  1482 		{
       
  1483 		idArray = DoGetCollectionGuidL(aGuid);
       
  1484 		}
       
  1485 		break;
       
  1486 	default:
       
  1487 		{
       
  1488 		User::Leave(KErrNotFound);
       
  1489 		}
       
  1490 		break;
       
  1491 	}	
       
  1492 	return idArray;
       
  1493 	}
       
  1494 
       
  1495 
       
  1496 /**
       
  1497 Get a collection of contact IDs which have changed since the given time.
       
  1498 
       
  1499 @param aTime Changed since time.
       
  1500 
       
  1501 @return Contact ID array of those contacts which have changed since the given
       
  1502 time.
       
  1503 */
       
  1504 CContactIdArray* RCntModel::DoGetCollectionChangedSinceL(TTime aTime)
       
  1505 	{
       
  1506 	TIpcArgs args;
       
  1507 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1508 	args.Set(1,MLplCollection::EChangedSince);
       
  1509 	TPckgBuf<TTime> pckg(aTime);
       
  1510 	args.Set(2,&pckg);
       
  1511 
       
  1512 	TInt newBuffSize;
       
  1513 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
  1514 	if (newBuffSize > 0)
       
  1515 		{
       
  1516 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1517 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
  1518 		}
       
  1519 
       
  1520 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1521 	CleanupStack::Pop(idArray);
       
  1522 
       
  1523 	return idArray;
       
  1524 	}
       
  1525 
       
  1526 	
       
  1527 /**
       
  1528 Get a collection of contact IDs for the given collection type.
       
  1529 
       
  1530 @param aCollectionType Collection type.
       
  1531 
       
  1532 @return Contact ID array of those contacts which meet the given collection type
       
  1533 criteria.
       
  1534 */
       
  1535 CContactIdArray* RCntModel::DoGetCollectionL(TInt aCollectionType)
       
  1536 	{
       
  1537 	TIpcArgs args;
       
  1538 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1539 	args.Set(1,aCollectionType);
       
  1540 
       
  1541 	TInt newBuffSize;
       
  1542 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
  1543 	if (newBuffSize > 0)
       
  1544 		{
       
  1545 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1546 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
  1547 		}
       
  1548 
       
  1549 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1550 	CleanupStack::Pop(idArray);
       
  1551 
       
  1552 	return idArray;
       
  1553 	}
       
  1554 
       
  1555 
       
  1556 /**
       
  1557 Get a collection of contact IDs which have the given GUID.  Since GUIDs are
       
  1558 unique (i.e. no two contacts can have the same GUID) there will only ever be
       
  1559 one contact ID in this collection.
       
  1560 
       
  1561 @param aGuid Contact GUID.
       
  1562 
       
  1563 @return Contact ID array containing the contact with the given GUID.
       
  1564 */
       
  1565 CContactIdArray* RCntModel::DoGetCollectionGuidL(const TDesC& aGuid)
       
  1566 	{
       
  1567 	TIpcArgs args;
       
  1568 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1569 	args.Set(1,MLplCollection::EFindGuid);
       
  1570 	args.Set(2,&aGuid);
       
  1571 
       
  1572 	TInt newBuffSize;
       
  1573 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
  1574 	if (newBuffSize > 0)
       
  1575 		{
       
  1576 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1577 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
  1578 		}
       
  1579 
       
  1580 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1581 	CleanupStack::Pop(idArray);
       
  1582 
       
  1583 	return idArray;
       
  1584 	}
       
  1585 
       
  1586 
       
  1587 /**
       
  1588 Set the sort preferences in the server.
       
  1589 
       
  1590 @param aSortOrder Sort order preferences.
       
  1591 */
       
  1592 void RCntModel::SetSortPreferenceL(const CArrayFix<CContactDatabase::TSortPref>& aSortOrder)
       
  1593 	{
       
  1594 	TPtr8 ptr(iPackager->PackL(aSortOrder));
       
  1595 	TIpcArgs args;
       
  1596 	args.Set(0,&ptr);
       
  1597 	User::LeaveIfError(SendReceive(ECntSetSortPrefs,args));	
       
  1598 	}
       
  1599 
       
  1600 
       
  1601 /**
       
  1602 Get the sort preferences from the server.
       
  1603 
       
  1604 @return Sort order preferences.
       
  1605 */
       
  1606 CArrayFix<CContactDatabase::TSortPref>* RCntModel::GetSortPreferenceL() const
       
  1607 	{
       
  1608 	TIpcArgs args;
       
  1609 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1610 
       
  1611 	TInt newBuffSize;
       
  1612 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetSortPrefs, args));
       
  1613 	if (newBuffSize > 0)
       
  1614 		{
       
  1615 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1616 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetSortPrefs, args));		
       
  1617 		}
       
  1618 
       
  1619 	CArrayFix<CContactDatabase::TSortPref>* prefs = iPackager->UnpackCArrayFixLC();	
       
  1620 	CleanupStack::Pop(prefs);
       
  1621 
       
  1622 	return prefs;
       
  1623 	}
       
  1624 
       
  1625 
       
  1626 /**
       
  1627 Get the number of contacts in the database.
       
  1628 
       
  1629 @return Number of contacts in the database if successful, otherwise it leaves.
       
  1630 */
       
  1631 TInt RCntModel::ContactCountL() const
       
  1632 	{
       
  1633     TInt numContacts = SendReceive( ECntDbContactCount );
       
  1634     User::LeaveIfError( numContacts );
       
  1635     return numContacts;
       
  1636 	}
       
  1637 
       
  1638 /**
       
  1639 Seek to the given contact ID.
       
  1640 
       
  1641 @param aContactId Contact ID to seek to.
       
  1642 @param aId On return the contact ID that the seek found.  This will be the
       
  1643 nearest contact ID if the given aContactID cannot be found.
       
  1644 @param aContactType On return the contact type of the contact that the seek
       
  1645 found.
       
  1646 @param aDeleted On return ETrue if the contact that the seek found is marked as
       
  1647 deleted, EFalse otherwise.
       
  1648 
       
  1649 @return ETrue if the seek was successful, EFalse otherwise.
       
  1650 */
       
  1651 TBool RCntModel::SeekContactL(TContactItemId aContactId,TContactItemId& aId,TUid& aContactType, TBool& aDeleted)
       
  1652     {
       
  1653     TPckgBuf<TInt> id;
       
  1654     TPckgBuf<TUid> type;
       
  1655     TPckgBuf<TBool> deleted;
       
  1656     TIpcArgs args(aContactId,&id,&type,&deleted);
       
  1657     TInt ret = SendReceive(ECntSeekContactInCollection,args);
       
  1658 
       
  1659     // Although ECntSeekContact/ECntSeekContactInCollection is normally completed
       
  1660     // with TBool values, ServiceError() can occur which leads to a negative system
       
  1661     // error codes being returned.  User::LeaveIfError will allow that to be properly
       
  1662     // handled.
       
  1663     User::LeaveIfError(ret);
       
  1664 
       
  1665     if(ret)
       
  1666         {
       
  1667         aContactType = type();
       
  1668         aId = id();
       
  1669         aDeleted = deleted();
       
  1670         return ETrue;
       
  1671         }
       
  1672     else
       
  1673         {
       
  1674         return EFalse;
       
  1675         }
       
  1676     }
       
  1677 
       
  1678 
       
  1679 void RCntModel::TextFieldL(TInt aCntItemId,TFieldType aFieldType, TDes& aText)
       
  1680 	{
       
  1681 	TPckgBuf<TFieldType> fieldType(aFieldType);
       
  1682 	TIpcArgs args(aCntItemId,&fieldType,&aText);
       
  1683 	User::LeaveIfError(SendReceive(ECntTextField,args));
       
  1684 	}
       
  1685 
       
  1686 
       
  1687 void RCntModel::ReadContactTextDefL(TContactItemId aContactId, TDes &aResult,const CContactTextDef& aTextDef)
       
  1688 	{
       
  1689 	iPackager->PackL( const_cast<CContactTextDef&>(aTextDef));
       
  1690 	TIpcArgs args(&iPackager->GetTransmittingBuffer(), &aResult,aContactId);
       
  1691 	User::LeaveIfError(SendReceive(ECntReadContactTextDef, args));
       
  1692 	}
       
  1693 
       
  1694 
       
  1695 CContactIdArray* RCntModel::FindL(const TDesC& aText,const CContactItemFieldDef* aFieldDef)
       
  1696 	{
       
  1697 	TIpcArgs args;
       
  1698 
       
  1699 	// Parameter can be NULL so send down an empty descriptor to the server.
       
  1700 	// Server can detect this and pass NULL parameter to the Persistence Layer
       
  1701 	// FindL() method.
       
  1702 	if(aFieldDef != NULL)
       
  1703 		{
       
  1704 		// Packager's sending buffer in slot 1 (contains packed field
       
  1705 		// definition).
       
  1706 		iPackager->PackL(*aFieldDef);
       
  1707 		args.Set(1,&iPackager->GetTransmittingBuffer());
       
  1708 		}
       
  1709 	else
       
  1710 		{
       
  1711 		// Frigged NULL.
       
  1712 		args.Set(1,&KNullDesC);
       
  1713 		}
       
  1714 
       
  1715 	// Packager's receiving buffer in slot 0.
       
  1716 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1717 
       
  1718 	// Text in slot 2.
       
  1719 	args.Set(2,&aText);
       
  1720 
       
  1721 	// Ensure receiving buffer is big enough.
       
  1722 	TInt newBuffSize;
       
  1723 	User::LeaveIfError(newBuffSize = SendReceive(ECntFind, args));
       
  1724 	if (newBuffSize > 0)
       
  1725 		{
       
  1726 		// Not big enough so resize and call again.
       
  1727 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1728 		User::LeaveIfError(newBuffSize = SendReceive(ECntFind, args));
       
  1729 		}
       
  1730 
       
  1731 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1732 	CleanupStack::Pop(idArray);
       
  1733 
       
  1734 	return idArray;	
       
  1735 	}
       
  1736 
       
  1737 
       
  1738 void RCntModel::SetDbViewContactType(const TUid aUid)
       
  1739 	{
       
  1740 	TIpcArgs args(aUid.iUid);
       
  1741 	(void)SendReceive(ECntSetDbViewContactType,args);
       
  1742 	}
       
  1743 
       
  1744 
       
  1745 TUid RCntModel::GetDbViewContactType() const
       
  1746 	{
       
  1747 	TPckgBuf<TUid> type;
       
  1748 	TIpcArgs args(&type);
       
  1749 	(void)SendReceive(ECntSetDbViewContactType,args);
       
  1750 	return type();	
       
  1751 	}
       
  1752 
       
  1753 
       
  1754 /**
       
  1755 Initialise the Persistence Layer collection class ready for iterative calls to
       
  1756 the FindAsyncL() method.  This form of initialisation is for an asynchronous
       
  1757 find which uses a text definition and an array of "find words".
       
  1758 
       
  1759 @param aWords "Find words" array.
       
  1760 @param aTextDef Text definition to use in find.
       
  1761 */
       
  1762 void RCntModel::FindAsyncTextDefInitL(const CDesCArray& aWords,CContactTextDef* aTextDef)
       
  1763 	{
       
  1764 	TIpcArgs args;
       
  1765 	if(aTextDef != NULL)
       
  1766 		{
       
  1767 		// Pack the text definition.
       
  1768 		iPackager->PackL(*aTextDef);
       
  1769 		args.Set(1,&iPackager->GetTransmittingBuffer());
       
  1770 		}
       
  1771 	else
       
  1772 		{
       
  1773 		// No user supplied text definition.
       
  1774 		args.Set(1, &KNullDesC);
       
  1775 		}
       
  1776 	
       
  1777 	// Do the CDesCArray manually as Packager can't do both.
       
  1778 	RBufWriteStream writeStream;
       
  1779 	CBufFlat* buf = CBufFlat::NewL(1 << 8);
       
  1780 	CleanupStack::PushL(buf);
       
  1781 
       
  1782 	writeStream.Open(*buf);
       
  1783 	TInt count = aWords.Count();
       
  1784 	writeStream.WriteInt32L(count);	
       
  1785 	TInt length = 0;
       
  1786 	for(TInt i=0; i<count;++i)
       
  1787 		{
       
  1788 		length = aWords[i].Length();
       
  1789 		writeStream.WriteInt32L(length);		
       
  1790 		writeStream.WriteL(aWords[i],length);
       
  1791 		}
       
  1792 	writeStream.CommitL();
       
  1793 	writeStream.Close();
       
  1794 
       
  1795 	TPtr8 ptr8(buf->Ptr(0));
       
  1796 	args.Set(0,&ptr8);
       
  1797 
       
  1798 	User::LeaveIfError(SendReceive(ECntFindAsyncTextDefInit,args));
       
  1799 
       
  1800 	CleanupStack::PopAndDestroy(buf);
       
  1801 	}
       
  1802 
       
  1803 
       
  1804 /**
       
  1805 Initialise the Persistence Layer collection class ready for iterative calls to
       
  1806 the FindAsyncL() method.  This form of initialisation is for an asynchronous
       
  1807 find which uses text and a field definition.
       
  1808 
       
  1809 @param aText Find text.
       
  1810 @param aFieldDef Field definition to use in find.
       
  1811 */
       
  1812 void RCntModel::FindAsyncInitL(const TDesC& aText,CContactItemFieldDef* aFieldDef)
       
  1813 	{
       
  1814 	TIpcArgs args;
       
  1815 	args.Set(0,&aText);
       
  1816 	if(aFieldDef != NULL)
       
  1817 		{
       
  1818 		// Pack the field definition.
       
  1819 		iPackager->PackL(*aFieldDef);
       
  1820 		args.Set(1,&iPackager->GetTransmittingBuffer());
       
  1821 		}
       
  1822 	else
       
  1823 		{
       
  1824 		// No user supplied field definition.
       
  1825 		args.Set(1, &KNullDesC);
       
  1826 		}
       
  1827 
       
  1828 	User::LeaveIfError(SendReceive(ECntFindAsyncInit,args));
       
  1829 	}
       
  1830 
       
  1831 
       
  1832 /**
       
  1833 Perform an asynchronous find iteration.  Either the FindAsyncTextDefInitL() or
       
  1834 the FindAsyncInitL() method above must have first been called.
       
  1835 
       
  1836 @param aOrigIdArray Set of contacts IDs from previous calls to FindAsyncL().
       
  1837 Will be NULL if this is the first iteration.
       
  1838 
       
  1839 @return ETrue if further find iterations are required, EFalse otherwise.
       
  1840 */
       
  1841 TBool RCntModel::FindAsyncL(CContactIdArray*& aOrigIdArray)
       
  1842 	{
       
  1843 	TBool moreToGo;
       
  1844 	TPckg<TBool> pckg(moreToGo);
       
  1845 	// Iterations can't fail so expand buffer to 4Kb.  4096 contacts should be
       
  1846 	// enough.  Rather than this brutal approach we could call ContactCountL()
       
  1847 	// and add a contingency in case another client adds some.
       
  1848 	TIpcArgs args(&iPackager->GetReceivingBufferL(4096),&pckg);
       
  1849 
       
  1850 	User::LeaveIfError(SendReceive(ECntFindAsync,args));
       
  1851 
       
  1852 	CContactIdArray* newIdArray = iPackager->UnpackCntIdArrayLC();	
       
  1853 	if(aOrigIdArray != NULL)
       
  1854 		{
       
  1855 		// Append to the old array if it was not NULL.
       
  1856 		for(TInt i=0;i<newIdArray->Count();++i)
       
  1857 			{
       
  1858 			if(aOrigIdArray->Find((*newIdArray)[i]) == KErrNotFound)
       
  1859 				{
       
  1860 				//Add only when we are sure that this ID has not been added to this array before.
       
  1861 				aOrigIdArray->AddL((*newIdArray)[i]);
       
  1862 				}
       
  1863 			}
       
  1864 		CleanupStack::PopAndDestroy(newIdArray);
       
  1865 		}
       
  1866 	else
       
  1867 		{
       
  1868 		CleanupStack::Pop(newIdArray);
       
  1869 		aOrigIdArray = newIdArray;
       
  1870 		}
       
  1871 
       
  1872 	return pckg();
       
  1873 	}
       
  1874 
       
  1875 
       
  1876 /**
       
  1877 Set the asynchronous activity flag in the server.  Any asynchronous activity
       
  1878 such as asynchronous find or asynchronous sort prevent the database from
       
  1879 being closed and should set this flag.  When all asynchronous activites are
       
  1880 finished this flag should be cleared.
       
  1881 
       
  1882 @capability None
       
  1883 
       
  1884 @param aAsyncActivity ETrue if at least one asynchronous activity, EFalse if
       
  1885 no asynchronous activities.
       
  1886 */
       
  1887 void RCntModel::SetAsyncActivityL(TBool aAsyncActivity)
       
  1888 	{
       
  1889 	TIpcArgs args;
       
  1890 	args.Set(0,aAsyncActivity);
       
  1891 	User::LeaveIfError(SendReceive(ECntSetAsyncActivity,args));
       
  1892 	}
       
  1893 
       
  1894 
       
  1895 /**
       
  1896 Filter the database using the given filter.
       
  1897 
       
  1898 @param aFilter Filter to use.  On return the contact IDs in this filter will be
       
  1899 augmented with those contact IDs which match the given filter.
       
  1900 */
       
  1901 void RCntModel::FilterDatabaseL(CCntFilter& aFilter)
       
  1902 	{
       
  1903 	CContactIdArray* origIdArray = aFilter.iIds;
       
  1904 	aFilter.iIds = NULL;
       
  1905 
       
  1906 	TIpcArgs args;
       
  1907 	iPackager->PackL(aFilter);
       
  1908 	args.Set(1,&iPackager->GetTransmittingBuffer());	
       
  1909 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1910 
       
  1911 	TInt newBuffSize(0);
       
  1912 	User::LeaveIfError(newBuffSize = SendReceive(ECntFilterDatabase, args));
       
  1913 	if (newBuffSize > 0)
       
  1914 		{
       
  1915 		// Not big enough so resize and call again.
       
  1916 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1917 		User::LeaveIfError(newBuffSize = SendReceive(ECntFilterDatabase, args));
       
  1918 		}
       
  1919 	
       
  1920 	CContactIdArray* newIdArray = iPackager->UnpackCntIdArrayLC();
       
  1921 	if(origIdArray != NULL)
       
  1922 		{
       
  1923 		for(TInt i=0;i<newIdArray->Count();++i)
       
  1924 			{
       
  1925 			origIdArray->AddL((*newIdArray)[i]);
       
  1926 			}
       
  1927 		aFilter.iIds = origIdArray;
       
  1928 		CleanupStack::PopAndDestroy(newIdArray);
       
  1929 		}
       
  1930 	else
       
  1931 		{
       
  1932 		CleanupStack::Pop(newIdArray);
       
  1933 		aFilter.iIds = newIdArray;
       
  1934 		}
       
  1935 	}
       
  1936 
       
  1937 	
       
  1938 TInt RCntModel::OpenViewL(const CContactTextDef& aTextDef, const TInt aViewPrefs)
       
  1939 	{
       
  1940 	TPckgBuf<TInt> viewSessionId;
       
  1941 	iPackager->PackL(const_cast<CContactTextDef&>(aTextDef));
       
  1942 	TIpcArgs args(&iPackager->GetTransmittingBuffer(), aViewPrefs, &viewSessionId);
       
  1943 	
       
  1944 	TInt ret = SendReceive(ECntOpenViewSession,args);
       
  1945 	User::LeaveIfError(ret);
       
  1946 	
       
  1947 	return 	viewSessionId();
       
  1948 	}
       
  1949 	
       
  1950 	
       
  1951 void RCntModel::CloseView(TInt aViewId)
       
  1952 	{
       
  1953 	TIpcArgs args(aViewId);
       
  1954 	SendReceive(ECntCloseViewSession,args);
       
  1955 	}
       
  1956 	
       
  1957 	
       
  1958 void RCntModel::ChangeSortOrderL(TInt aViewId, const CContactTextDef& aTextDef)
       
  1959 	{
       
  1960 	// Serialize the text def using packager overload.
       
  1961 	iPackager->PackL( const_cast<CContactTextDef&>(aTextDef));
       
  1962 	
       
  1963 
       
  1964 	TIpcArgs args(aViewId, &iPackager->GetTransmittingBuffer());
       
  1965 	TInt ret = SendReceive(ECntViewChangeSortOrderL, args);
       
  1966 	
       
  1967 	User::LeaveIfError(ret);
       
  1968 	}
       
  1969 	
       
  1970 	
       
  1971 void RCntModel::BeginIterateL(TInt aViewId)
       
  1972 	{
       
  1973 	TIpcArgs args(aViewId);
       
  1974 	TInt ret = SendReceive(ECntViewBeginIterate,args);
       
  1975 	User::LeaveIfError(ret);
       
  1976 	}
       
  1977 	
       
  1978 	
       
  1979 void RCntModel::EndIterateL(TInt aViewId)
       
  1980 	{
       
  1981 	TIpcArgs args(aViewId);
       
  1982 	TInt ret = SendReceive(ECntViewEndIterate,args);
       
  1983 	User::LeaveIfError(ret);
       
  1984 	}
       
  1985 	
       
  1986 	
       
  1987 CViewContact* RCntModel::NextItemL(TInt aViewId, const TInt aViewPrefs)
       
  1988 	{
       
  1989 	TIpcArgs args(aViewId, aViewPrefs, &iPackager->GetReceivingBufferL());
       
  1990 	TInt size = SendReceive(ECntViewNextItemL, args);
       
  1991 
       
  1992 	// KErrNotFound is returned if Persistence Layer view item manager 
       
  1993 	// can't reach end of the contacts.
       
  1994 	if(size == KErrNotFound)
       
  1995 		{
       
  1996 		// Not an error just no match.
       
  1997 		return NULL;
       
  1998 		}
       
  1999 
       
  2000 	// Leave on genuine errors.
       
  2001 	User::LeaveIfError(size);
       
  2002 
       
  2003 	if(size != 0) // Server session requires larger packager buffer.
       
  2004 		{
       
  2005 		// Increase the buffer size and call again.  Just in case some other
       
  2006 		// client has deleted in between calls do the KErrNotFound check.
       
  2007 		TIpcArgs args(aViewId, aViewPrefs, &iPackager->GetReceivingBufferL(size));
       
  2008 		TInt ret = SendReceive(ECntViewNextItemL, args);
       
  2009 		if(ret == KErrNotFound)
       
  2010 			{
       
  2011 			return NULL;
       
  2012 			}
       
  2013 		// Leave on genuine errors
       
  2014 		User::LeaveIfError(ret);
       
  2015 		}
       
  2016 
       
  2017 	// Got it so unpack and return.
       
  2018 	CViewContact* viewContact = iPackager->UnpackViewContactLC();
       
  2019 
       
  2020 	CleanupStack::Pop(viewContact);
       
  2021 
       
  2022 	return viewContact;
       
  2023 	}
       
  2024 
       
  2025 	
       
  2026 CViewContact* RCntModel::ItemAtL(TContactItemId aContactId, TInt aViewId)
       
  2027 	{
       
  2028 	TIpcArgs args(aContactId, aViewId, &iPackager->GetReceivingBufferL());
       
  2029 	TInt size = SendReceive(ECntItemAtL, args);
       
  2030 
       
  2031 	// KErrNotFound is returned if Persistence Layer view item manager cannot 
       
  2032 	// find the view contact by given aContactId.
       
  2033 	if(size == KErrNotFound)
       
  2034 		{
       
  2035 		// Not an error just no match.
       
  2036 		return NULL;
       
  2037 		}
       
  2038 
       
  2039 	// Leave on genuine errors.
       
  2040 	User::LeaveIfError(size);
       
  2041 
       
  2042 	if(size != 0) // Server session requires larger packager buffer.
       
  2043 		{
       
  2044 		// Increase the buffer size and call again.  Just in case some other
       
  2045 		// client has deleted in between calls do the KErrNotFound check.
       
  2046 		TIpcArgs args(aContactId, aViewId, &iPackager->GetReceivingBufferL(size));
       
  2047 		TInt ret = SendReceive(ECntItemAtL, args);
       
  2048 		if(ret == KErrNotFound)
       
  2049 			{
       
  2050 			return NULL;
       
  2051 			}
       
  2052 		// Leave on genuine errors
       
  2053 		User::LeaveIfError(ret);
       
  2054 		}
       
  2055 
       
  2056 	// Got it so unpack and return.
       
  2057 	CViewContact* viewContact = iPackager->UnpackViewContactLC();
       
  2058 
       
  2059 	CleanupStack::Pop(viewContact);
       
  2060 
       
  2061 	return viewContact;
       
  2062 	}
       
  2063 	
       
  2064 
       
  2065 #if defined(_DEBUG)	
       
  2066 void RCntModel::GetDefinitionsOfExistingViewsL(const TDesC& aDbName, RPointerArray<CContactDefaultViewDefinition>& aViewDefs)
       
  2067 	{
       
  2068 	RBuf8 buf;
       
  2069 	CleanupClosePushL(buf);
       
  2070 	buf.Create(256);
       
  2071 	TIpcArgs args(&aDbName, &buf);
       
  2072 
       
  2073 	TInt newBufSize;
       
  2074 	User::LeaveIfError(newBufSize = SendReceive(ECntGetDefinitionsForExistingView, args));
       
  2075 	if (newBufSize > 0)
       
  2076 		{
       
  2077 		buf.ReAllocL(newBufSize);
       
  2078 		args.Set(1, &buf);
       
  2079 		User::LeaveIfError(newBufSize = SendReceive(ECntGetDefinitionsForExistingView, args));		
       
  2080 		}
       
  2081 
       
  2082 	RDesReadStream readStream(buf);
       
  2083 	CleanupClosePushL(readStream);
       
  2084 	TInt32 count;
       
  2085 	readStream >> count;
       
  2086 	CContactDefaultViewDefinition* view;
       
  2087 	for (TInt i = 0; i < count; i++)
       
  2088 		{
       
  2089 		view = CContactDefaultViewDefinition::NewLC(readStream);
       
  2090 		aViewDefs.AppendL(view);
       
  2091 		CleanupStack::Pop(view);
       
  2092 		}
       
  2093 		
       
  2094 	CleanupStack::PopAndDestroy(2); // readStream, buf	
       
  2095 	}
       
  2096 #else
       
  2097 void RCntModel::GetDefinitionsOfExistingViewsL(const TDesC& /*aDbName*/, RPointerArray<CContactDefaultViewDefinition>& /*aViewDefs*/)
       
  2098 	{	
       
  2099 	}
       
  2100 #endif // _DEBUG