messagingfw/msgsrvnstore/server/src/MSVENTRY.CPP
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 1998-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 #include <e32std.h>
       
    18 
       
    19 #include "MSVSTD.H"
       
    20 #include "MSVSTORE.H"
       
    21 #include "MSVIDS.H"
       
    22 
       
    23 #include "MSVENTRY.H"
       
    24 #include "MSVSERV.H"
       
    25 #include "MSVMOVE.H"
       
    26 #include "MSVDELET.H"
       
    27 #include "MSVCOPY.H"
       
    28 
       
    29 #include "MSVPANIC.H"
       
    30 #include "MSVUTILS.H"
       
    31 #include "msvindexadapter.h"
       
    32 const TInt KMsvServerEntryStandardBufLength=64;
       
    33 
       
    34 //**********************************
       
    35 // CMsvServerEntry
       
    36 //**********************************
       
    37 
       
    38 // static
       
    39 /**
       
    40 @internalComponent
       
    41 */
       
    42 EXPORT_C CMsvServerEntry* CMsvServerEntry::NewL(CMsvServer& aServer, TMsvId aId)
       
    43 //
       
    44 //
       
    45 //
       
    46 	{
       
    47 	CMsvServerEntry* self = new(ELeave) CMsvServerEntry(aServer);
       
    48 	CleanupStack::PushL(self);
       
    49 	self->ConstructL(aId);
       
    50 	CleanupStack::Pop();
       
    51 	return self;
       
    52 	}
       
    53 
       
    54 CMsvServerEntry::CMsvServerEntry(CMsvServer& aServer)
       
    55 : CActive(EPriorityStandard), iLockedStore(EFalse), iServer(aServer)
       
    56 //
       
    57 //
       
    58 //
       
    59 	{
       
    60 	__DECLARE_NAME(_S("CMsvServerEntry"));
       
    61 	}
       
    62 
       
    63 void CMsvServerEntry::ConstructL(TMsvId aId)
       
    64 //
       
    65 //
       
    66 //
       
    67 	{
       
    68 	iDescription = HBufC::NewL(KMsvServerEntryStandardBufLength);
       
    69 	iDetails	 = HBufC::NewL(KMsvServerEntryStandardBufLength);
       
    70 	User::LeaveIfError(SetEntry(aId));
       
    71 
       
    72 	CActiveScheduler::Add(this);
       
    73 	}
       
    74 
       
    75 
       
    76 CMsvServerEntry::~CMsvServerEntry()
       
    77 //
       
    78 //
       
    79 //
       
    80 /** Frees resources for the object. It:
       
    81 
       
    82 1. releases the lock on the entry
       
    83 
       
    84 2. releases the lock on the associated message store if has been opened with
       
    85 EditStoreL()
       
    86 
       
    87 3. cancels any outstanding asynchronous MoveEntryL() move operation */
       
    88 	{
       
    89 	__ASSERT_DEBUG(iStore==NULL, PanicServer(EMsvStoreLeftOpenOnDestruction));
       
    90 
       
    91 	if (iEntry.Id() != KMsvNullIndexEntryId)
       
    92 		{
       
    93 		iServer.IndexAdapter().ReleaseEntry(iEntry.Id()); // ignore any error
       
    94 		}
       
    95 
       
    96 	if (iLockedStore)
       
    97 		{
       
    98 		iServer.IndexAdapter().ReleaseStore(iEntry.Id()); // ignore any error
       
    99 		}
       
   100 
       
   101 	delete iDescription;
       
   102 	delete iDetails;
       
   103 
       
   104 	Cancel();
       
   105 	}
       
   106 
       
   107 
       
   108 
       
   109 EXPORT_C TInt CMsvServerEntry::SetEntry(TMsvId aId)
       
   110 //
       
   111 // Changes the entry used as the context
       
   112 //
       
   113 /** Changes the context of the specified entry.
       
   114 
       
   115 The call locks the entry, preventing it from being accessed by other clients.
       
   116 The lock is released when the object is deleted or the context is changed.
       
   117 
       
   118 Note that you can change the context to KMsvNullIndexEntryId to unlock an
       
   119 entry without locking another.
       
   120 
       
   121 @param aId ID of the entry to access
       
   122 @return KErrNone if successful, KErrNotFound if the entry does not exist, or
       
   123 KErrLocked if the entry is locked. */
       
   124 	{
       
   125 	__ASSERT_ALWAYS(iStore==NULL, PanicServer(EMsvEntryStoreLeftOpen));
       
   126 	__ASSERT_ALWAYS(iEntryState==EMsvIdle, PanicServer(EMsvServerEntryNotIdle));
       
   127 
       
   128 	// changing to itself
       
   129 	if (iEntry.Id()==aId)
       
   130 		return KErrNone;
       
   131 
       
   132 	if (aId == KMsvNullIndexEntryId)
       
   133 		{
       
   134 		// setting the context to NULL
       
   135 		iServer.IndexAdapter().ReleaseEntry(iEntry.Id()); // error ignored
       
   136 		*iDescription = TPtrC();
       
   137 		*iDetails = TPtrC();
       
   138 		iEntry = TMsvEntry();
       
   139 		return KErrNone;
       
   140 		}
       
   141 
       
   142 	// lock the new entry
       
   143 	TInt error = KErrNone;
       
   144     error = iServer.IndexAdapter().LockEntry(aId);
       
   145 	if (error)
       
   146 		return error;
       
   147 
       
   148 	// get the new entry
       
   149 	TMsvEntry* entryPtr;
       
   150 	error = iServer.IndexAdapter().GetEntry(aId, entryPtr, iContextOwnerId);
       
   151 	if (error==KErrNone)
       
   152 		{
       
   153 		// check we can copy the strings
       
   154 		error = IncreaseBufferSizes(entryPtr->iDescription.Length(), entryPtr->iDetails.Length());
       
   155 
       
   156 		if (error==KErrNone)
       
   157 			{
       
   158 			// release old entry
       
   159 			if (iEntry.Id()!=KMsvNullIndexEntryId)
       
   160 				{
       
   161 				iServer.IndexAdapter().ReleaseEntry(iEntry.Id()); // error ignored
       
   162 				}
       
   163 
       
   164 
       
   165 			// switch the context of this object
       
   166 			*iDescription = entryPtr->iDescription;
       
   167 			*iDetails = entryPtr->iDetails;
       
   168 			iEntry = *entryPtr;
       
   169 			iEntry.iDescription.Set(*iDescription);
       
   170 			iEntry.iDetails.Set(*iDetails);
       
   171 			}
       
   172 		}
       
   173 
       
   174 	// release the lock on the new entry
       
   175 	if (error)
       
   176 		{
       
   177 		iServer.IndexAdapter().ReleaseEntry(aId); // error ignored
       
   178 		}
       
   179 
       
   180 
       
   181 	return error;
       
   182 	}
       
   183 
       
   184 
       
   185 
       
   186 TInt CMsvServerEntry::IncreaseBufferSizes(TInt aNewDescriptionSize, TInt aNewDetailsSize)
       
   187 //
       
   188 // Increase the size of the buffers if needed. The current contents of the buffers is maintained
       
   189 //
       
   190 	{
       
   191 	if (aNewDescriptionSize > iDescription->Des().MaxLength())
       
   192 		{
       
   193 		HBufC* newBuf = iDescription->ReAlloc(aNewDescriptionSize);
       
   194 		if (newBuf==NULL)
       
   195 			return KErrNoMemory;
       
   196 		iDescription=newBuf;
       
   197 		}
       
   198 
       
   199 	if (aNewDetailsSize > iDetails->Des().MaxLength())
       
   200 		{
       
   201 		HBufC* newBuf = iDetails->ReAlloc(aNewDetailsSize);
       
   202 		if (newBuf==NULL)
       
   203 			return KErrNoMemory;
       
   204 		iDetails=newBuf;
       
   205 		}
       
   206 	return KErrNone;
       
   207 	}
       
   208 
       
   209 /**
       
   210 Sets the context's index entry to the specified values.
       
   211 
       
   212 @param	aEntry
       
   213 The new details for the entry.
       
   214 
       
   215 @return
       
   216 KErrNone - success; KErrAccessDenied - the entry is read only (deleted
       
   217 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the
       
   218 ID specified in aEntry is not the same as the context ID or no context has been
       
   219 set for the object; KErrNoMemory - a memory allocation failed.
       
   220 */
       
   221 EXPORT_C TInt CMsvServerEntry::ChangeEntry(const TMsvEntry& aEntry)
       
   222 	{
       
   223 	return DoChangeEntry(aEntry, KMsvServerId, EFalse, EFalse);
       
   224 	}
       
   225 
       
   226 /**
       
   227 Sets the context's index entry to the specified values and updates the owner of
       
   228 the entry to that specified by the supplied ID.
       
   229 
       
   230 @param	aEntry
       
   231 The new details for the entry.
       
   232 
       
   233 @param	aOwnerId
       
   234 The ID of the process that should own the entry.
       
   235 
       
   236 @return
       
   237 KErrNone - success; KErrAccessDenied - the entry is read only (deleted
       
   238 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the
       
   239 ID specified in aEntry is not the same as the context ID or no context has been
       
   240 set for the object; KErrNoMemory - a memory allocation failed.
       
   241 */
       
   242 EXPORT_C TInt CMsvServerEntry::ChangeEntry(const TMsvEntry& aEntry, TSecureId aOwnerId)
       
   243 	{
       
   244 	return DoChangeEntry(aEntry, aOwnerId, ETrue, EFalse);
       
   245 	}
       
   246 /**
       
   247 Sets the context's index entry to the specified values and updates the owner of
       
   248 the entry to that specified by the supplied ID. It does this as part of a bulk
       
   249 operation, so the changes are not immediately committed to file.
       
   250 
       
   251 @param	aEntry
       
   252 The new details for the entry.
       
   253 
       
   254 @param	aOwnerId
       
   255 The ID of the process that should own the entry. Only commits changes to
       
   256 file at specified bulk commit interval.
       
   257 
       
   258 @return
       
   259 KErrNone - success; KErrAccessDenied - the entry is read only (deleted
       
   260 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the
       
   261 ID specified in aEntry is not the same as the context ID or no context has been
       
   262 set for the object; KErrNoMemory - a memory allocation failed.
       
   263 */
       
   264 EXPORT_C TInt CMsvServerEntry::ChangeEntryBulk(const TMsvEntry& aEntry, TSecureId aOwnerId)
       
   265 	{
       
   266 	return DoChangeEntry(aEntry, aOwnerId, ETrue, ETrue);
       
   267 	}
       
   268 
       
   269 /**
       
   270 Sets the context's index entry to the specified values and updates the owner of
       
   271 the entry to that specified by the supplied ID. It does this as part of a bulk
       
   272 operation, so the changes are not immediately committed to file.
       
   273 
       
   274 @param	aEntry
       
   275 The new details for the entry.
       
   276 
       
   277 @return
       
   278 KErrNone - success; KErrAccessDenied - the entry is read only (deleted
       
   279 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the
       
   280 ID specified in aEntry is not the same as the context ID or no context has been
       
   281 set for the object; KErrNoMemory - a memory allocation failed.
       
   282 */
       
   283 EXPORT_C TInt CMsvServerEntry::ChangeEntryBulk(const TMsvEntry& aEntry)
       
   284 	{
       
   285 	return DoChangeEntry(aEntry, KMsvServerId, EFalse, ETrue);
       
   286 	}
       
   287 
       
   288 
       
   289 TInt CMsvServerEntry::DoChangeEntry(const TMsvEntry& aEntry, TSecureId aOwnerId, TBool aForcedUpdate, TBool aBulk)
       
   290 	{
       
   291 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext1));
       
   292 	__ASSERT_DEBUG(aEntry.Id()==iEntry.Id(), PanicServer(EMsvNotChangingCurrentContext));
       
   293 	__ASSERT_DEBUG(MsvUtils::ValidEntry(aEntry), PanicServer(EMsvBadEntryContents));
       
   294 	__ASSERT_DEBUG(!iEntry.Deleted(), PanicServer(EMsvChangingDeletedEntry));
       
   295 
       
   296 	// can only change the context, and must be valid
       
   297 	if (iEntry.Id()==KMsvNullIndexEntryId || aEntry.Id()!=iEntry.Id() || !MsvUtils::ValidEntry(aEntry))
       
   298 		return KErrNotSupported;
       
   299 
       
   300 	if (iEntry.Deleted() || iEntry.StandardFolder())
       
   301 		return KErrAccessDenied;
       
   302 
       
   303 	TInt error;
       
   304 
       
   305 	TBool permanentDataUnchanged = iEntry.PermanentDataUnchanged(aEntry);
       
   306 	if( permanentDataUnchanged && aForcedUpdate )
       
   307 		{
       
   308 		// Check to see if the owner ID is being updated - if so then need to
       
   309 		// update the permanent data.
       
   310 		permanentDataUnchanged = (iContextOwnerId == aOwnerId);
       
   311 		}
       
   312 
       
   313 	if( permanentDataUnchanged )
       
   314 		{
       
   315 		error = iServer.IndexAdapter().ChangeTemporaryData(aEntry);
       
   316 		if (error==KErrNone)
       
   317 			iEntry.iData = aEntry.iData;
       
   318 		}
       
   319 	else
       
   320 		{
       
   321 		error = IncreaseBufferSizes(aEntry.iDescription.Length(), aEntry.iDetails.Length());
       
   322 
       
   323 		if (error==KErrNone)
       
   324 			{
       
   325 			TMsvEntry entry = aEntry;
       
   326 
       
   327 			// check the hidden flags are correct
       
   328 			entry.SetOwner(iEntry.Owner());
       
   329 			entry.SetDeleted(iEntry.Deleted());
       
   330 			error = iServer.ChangeEntry(entry, aOwnerId, aForcedUpdate, aBulk);
       
   331 			if (error==KErrNone)
       
   332 				{
       
   333 				// switch the context of this object
       
   334 				*iDescription = entry.iDescription;
       
   335 				*iDetails = entry.iDetails;
       
   336 				iEntry = entry;
       
   337 				iEntry.iDescription.Set(*iDescription);
       
   338 				iEntry.iDetails.Set(*iDetails);
       
   339 				}
       
   340 			}
       
   341 		}
       
   342 
       
   343 	// notify everyone of the change unless this is a bulk change.
       
   344 	// for bulk changes (e.g. email synchronize, all notifications get handled elsewhere
       
   345 	if ((error == KErrNone) && (!aBulk))
       
   346 		{
       
   347 		iServer.NotifyChanged(EMsvEntriesChanged, iEntry.Id(), iEntry.Parent());
       
   348 		}
       
   349 
       
   350 	return error;
       
   351 	}
       
   352 
       
   353 /**
       
   354 Creates a new entry as a child of the current context.
       
   355 
       
   356 The parent ID and entry ID are set by the Message Server.
       
   357 
       
   358 @param	aEntry
       
   359 Index entry value for the new entry
       
   360 
       
   361 @return
       
   362 KErrNone - success; KErrNoMemory - a memory allocation failed;
       
   363 KErrNotSupported - aEntry is invalid
       
   364 */
       
   365 EXPORT_C TInt CMsvServerEntry::CreateEntry(TMsvEntry& aEntry)
       
   366 	{
       
   367 	return CreateEntry(aEntry, KMsvServerId);
       
   368 	}
       
   369 
       
   370 /**
       
   371 Creates a new entry as a child of the current context.
       
   372 
       
   373 Ownership of the created entry is given to the process with the specified SID.
       
   374 
       
   375 The parent ID and entry ID are set by the Message Server.
       
   376 
       
   377 @param	aEntry
       
   378 Index entry value for the new entry
       
   379 
       
   380 @param	aOwnerId
       
   381 The SID of the process that will own the create entry.
       
   382 
       
   383 @return
       
   384 KErrNone - success; KErrNoMemory - a memory allocation failed;
       
   385 KErrNotSupported - aEntry is invalid
       
   386 */
       
   387 EXPORT_C TInt CMsvServerEntry::CreateEntry(TMsvEntry& aEntry, TSecureId aOwnerId)
       
   388 	{
       
   389 	return CreateEntry(aEntry, aOwnerId, EFalse);
       
   390 	}
       
   391 
       
   392 /**
       
   393 Creates a new entry as a child of the current context as part of a
       
   394 bulk creation operation. The entry will not be committed to file immediately.
       
   395 
       
   396 The parent ID and entry ID are set by the Message Server.
       
   397 
       
   398 @param	aEntry
       
   399 Index entry value for the new entry
       
   400 
       
   401 @param	aOwnerId
       
   402 The SID of the process that will own the create entry.
       
   403 
       
   404 @return
       
   405 KErrNone - success; KErrNoMemory - a memory allocation failed;
       
   406 KErrNotSupported - aEntry is invalid
       
   407 */
       
   408 EXPORT_C TInt CMsvServerEntry::CreateEntryBulk(TMsvEntry& aEntry, TSecureId aOwnerId)
       
   409 	{
       
   410 	return CreateEntry(aEntry, aOwnerId, ETrue);
       
   411 	}
       
   412 /**
       
   413 Creates a new entry as a child of the current context as part of a
       
   414 bulk creation operation
       
   415 
       
   416 The parent ID and entry ID are set by the Message Server.
       
   417 
       
   418 @param	aEntry
       
   419 Index entry value for the new entry
       
   420 
       
   421 @return
       
   422 KErrNone - success; KErrNoMemory - a memory allocation failed;
       
   423 KErrNotSupported - aEntry is invalid
       
   424 */
       
   425 EXPORT_C TInt CMsvServerEntry::CreateEntryBulk(TMsvEntry& aEntry)
       
   426 	{
       
   427 	return CreateEntry(aEntry, KMsvServerId, ETrue);
       
   428 	}
       
   429 
       
   430 
       
   431 
       
   432 /**
       
   433 Creates a new entry as a child of the current context.
       
   434 
       
   435 Ownership of the created entry is given to the process with the specified SID.
       
   436 
       
   437 The parent ID and entry ID are set by the Message Server.
       
   438 
       
   439 @param	aEntry
       
   440 Index entry value for the new entry
       
   441 
       
   442 @param	aOwnerId
       
   443 The SID of the process that will own the create entry.
       
   444 
       
   445 @param aBulk
       
   446 A boolean value to indicate whether this is part of a bulk operation. (ETrue = bulk)
       
   447 
       
   448 @return
       
   449 KErrNone - success; KErrNoMemory - a memory allocation failed;
       
   450 KErrNotSupported - aEntry is invalid
       
   451 */
       
   452 EXPORT_C TInt CMsvServerEntry::CreateEntry(TMsvEntry& aEntry, TSecureId aOwnerId, TBool aBulk)
       
   453 	{
       
   454 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext2));
       
   455 	aEntry.SetParent(iEntry.Id());
       
   456 	__ASSERT_DEBUG(MsvUtils::ValidEntry(aEntry, ETrue), PanicServer(EMsvBadEntryContents));
       
   457 
       
   458 	// if valid - try to create the new child
       
   459 	TInt error;
       
   460 	if (iEntry.Id()==KMsvNullIndexEntryId || !MsvUtils::ValidEntry(aEntry, ETrue))
       
   461 		error = KErrNotSupported;
       
   462 	else
       
   463 		{
       
   464 		error = iServer.AddEntry(aEntry, aOwnerId, ETrue, aBulk);
       
   465 
       
   466 		// if the child was created,then notify everyone, otherwise reset the parent
       
   467 		if (error)
       
   468 			aEntry.SetParent(KMsvNullIndexEntryId);
       
   469 		else
       
   470 			{
       
   471 			if (!aBulk)
       
   472 				{
       
   473 				iServer.NotifyChanged(EMsvEntriesCreated, aEntry.Id(), aEntry.Parent());
       
   474 				}
       
   475 			iEntry.SetOwner(ETrue);
       
   476 			}
       
   477 		}
       
   478 
       
   479 	return error;
       
   480 	}
       
   481 
       
   482 EXPORT_C void CMsvServerEntry::CompleteBulk()
       
   483 //
       
   484 /** Completes the current bulk transaction (if any)
       
   485  Requests that the message server commit to the index file on disk
       
   486  any entries which have not been committed and to generate notifications
       
   487  for any entries which require them.
       
   488  @return void */
       
   489 	{
       
   490 	iServer.CompleteBulkTransaction();
       
   491 	}
       
   492 
       
   493 
       
   494 
       
   495 TBool CMsvServerEntry::AreChildren(const CMsvEntrySelection& aSelection) const
       
   496 //
       
   497 // Returns true if all the entries are children
       
   498 //
       
   499 	{
       
   500 	TInt count = aSelection.Count();
       
   501 	while (count--)
       
   502 		{
       
   503 		if (!IsAChild(aSelection.At(count)))
       
   504 			{
       
   505 			return EFalse;
       
   506 			}
       
   507 		}
       
   508 	return ETrue;
       
   509 	}
       
   510 
       
   511 TBool CMsvServerEntry::IsAChild(TMsvId aId) const
       
   512 //
       
   513 //
       
   514 //
       
   515 	{
       
   516 	TMsvEntry* entry=NULL;
       
   517 	TInt err = KErrNone;
       
   518 	err = iServer.IndexAdapter().GetEntry(aId, entry);
       
   519 	if (err ==KErrNone && entry->Parent()==iEntry.Id())
       
   520 		return ETrue;
       
   521 	return EFalse;
       
   522 	}
       
   523 
       
   524 
       
   525 EXPORT_C TInt CMsvServerEntry::DeleteEntry(TMsvId aId)
       
   526 //
       
   527 // Deletes the child of the current context recursively.
       
   528 //
       
   529 /** Deletes a child entry of the context. The delete works recursively through
       
   530 all the descendants.
       
   531 
       
   532 If a child or any descendant is locked by another client, then no entries
       
   533 are deleted.
       
   534 
       
   535 @param aId The ID of the entry to delete
       
   536 @return KErrNone if successful, KErrAccessDenied if the entry or a descendant
       
   537 was locked by another client, KErrInUse if the store or a file associated
       
   538 with the entry is open, or KErrNotFound if the entry is not a child of the
       
   539 context. */
       
   540 	{
       
   541 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext4));
       
   542 	__ASSERT_DEBUG(aId!=iEntry.Id(), PanicServer(EMsvDeletingCurrentContext));
       
   543 
       
   544 	// only delete children
       
   545 	if (!IsAChild(aId))
       
   546 		return KErrNotFound;
       
   547 
       
   548 	// get the total selection of entries to be deleted
       
   549 	CMsvEntrySelection* movedEntries=NULL;
       
   550 	CMsvEntrySelection* deletedEntries=NULL;
       
   551 	TRAPD(error, DoDeleteEntryL(aId, deletedEntries, movedEntries));
       
   552 
       
   553 	// notify server of the deletions & moves
       
   554 	if (deletedEntries && movedEntries && (deletedEntries->Count() || movedEntries->Count()))
       
   555 		{
       
   556 		if (deletedEntries->Count())
       
   557 			iServer.NotifyChanged(EMsvEntriesDeleted, *deletedEntries, iEntry.Id());
       
   558 		if (movedEntries->Count())
       
   559 			iServer.NotifyChanged(EMsvEntriesMoved, *movedEntries, KMsvDeletedEntryFolderEntryId, iEntry.Id());
       
   560 
       
   561 		// need to remove owner flag if has no children
       
   562 		TMsvEntry* pEntry;
       
   563 		TInt err = KErrNone;
       
   564 		err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry);
       
   565 		if (err ==KErrNone)
       
   566 			iEntry.SetOwner(pEntry->Owner());
       
   567 		}
       
   568 
       
   569 	delete movedEntries;
       
   570 	delete deletedEntries;
       
   571 
       
   572 	return error;
       
   573 	}
       
   574 
       
   575 void CMsvServerEntry::DoDeleteEntryL(TMsvId aId, CMsvEntrySelection*& aDeleted, CMsvEntrySelection*& aMoved)
       
   576 	{
       
   577 	aDeleted = new(ELeave)CMsvEntrySelection;
       
   578 	aMoved = new(ELeave)CMsvEntrySelection;
       
   579 
       
   580 	CMsvDelete* del = CMsvDelete::NewL(iServer);
       
   581 	CleanupStack::PushL(del);
       
   582 
       
   583 	del->StartL(aId, *aDeleted, *aMoved);
       
   584 
       
   585 	CleanupStack::PopAndDestroy(); // del
       
   586 	}
       
   587 
       
   588 EXPORT_C TInt CMsvServerEntry::DeleteEntries(CMsvEntrySelection& aSelection)
       
   589 //
       
   590 // Deletes the children of the current context in the selection recursively
       
   591 // Returns the children that could not be fully deleted in the selection
       
   592 //
       
   593 /** Deletes a selection of child entries. The delete works recursively through
       
   594 all the descendants.
       
   595 
       
   596 If a child or any descendant is locked by another client, then no entries
       
   597 are deleted.
       
   598 
       
   599 @param aSelection The entries to delete. On return, contains the children
       
   600 that could not be fully deleted
       
   601 @return KErrNone if successful, KErrAccessDenied if the entry or a descendant
       
   602 was locked by another client, KErrInUse if the store or a file associated
       
   603 with the entry is open, or KErrNotFound if the entry is not a child of the
       
   604 context. */
       
   605 	{
       
   606 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext4));
       
   607 
       
   608 	CMsvEntrySelection* deleted = NULL;
       
   609 	CMsvEntrySelection* moved = NULL;
       
   610 
       
   611 	TRAPD(error, DoDeleteEntriesL(aSelection, deleted, moved));
       
   612 
       
   613 	if (moved && deleted)
       
   614 		{
       
   615 		// Notify server of the deletions & moves
       
   616 		if (deleted->Count())
       
   617 			iServer.NotifyChanged(EMsvEntriesDeleted, *deleted, iEntry.Id());
       
   618 
       
   619 		if (moved->Count())
       
   620 			iServer.NotifyChanged(EMsvEntriesMoved, *moved, KMsvDeletedEntryFolderEntryId, iEntry.Id());
       
   621 
       
   622 		// need to remove owner flag if has no children
       
   623 		TMsvEntry* pEntry;
       
   624 		TInt err = KErrNone;
       
   625 		err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry);
       
   626 		if (err ==KErrNone)
       
   627 			iEntry.SetOwner(pEntry->Owner());
       
   628 		}
       
   629 
       
   630 	delete moved;
       
   631 	delete deleted;
       
   632 
       
   633 	return error;
       
   634 	}
       
   635 
       
   636 void CMsvServerEntry::DoDeleteEntriesL(CMsvEntrySelection& aSelection, CMsvEntrySelection*& aDeleted, CMsvEntrySelection*& aMoved)
       
   637 //
       
   638 //
       
   639 //
       
   640 	{
       
   641 	__ASSERT_DEBUG(!aDeleted && !aMoved, PanicServer(EMsvDeleteAndMoveSelectionsNotNull));
       
   642 	__ASSERT_DEBUG(aSelection.Count() > 0, PanicServer(EMsvDeletingEmptySelection));
       
   643 
       
   644 	// Total entries deleted and moved
       
   645 	aDeleted = new(ELeave)CMsvEntrySelection;
       
   646 	aMoved = new(ELeave)CMsvEntrySelection;
       
   647 
       
   648 	// Entries deleted when a single item is deleted
       
   649 	CMsvEntrySelection* deleted = new(ELeave)CMsvEntrySelection;
       
   650 	CleanupStack::PushL(deleted);
       
   651 
       
   652 	// Entries moved when a single item is deleted
       
   653 	CMsvEntrySelection* moved = new(ELeave)CMsvEntrySelection;
       
   654 	CleanupStack::PushL(moved);
       
   655 
       
   656 	CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection;
       
   657 	CleanupStack::PushL(selection);
       
   658 
       
   659 	CMsvDelete* del = CMsvDelete::NewL(iServer);
       
   660 	CleanupStack::PushL(del);
       
   661 
       
   662 	TInt firstError = KErrNone;
       
   663 
       
   664 	TInt count = aSelection.Count();
       
   665 	while(count--)
       
   666 		{
       
   667 		TMsvId id = aSelection.At(count);
       
   668 		TInt error = KErrNone;
       
   669 
       
   670 		// Only delete children
       
   671 		if (!IsAChild(id))
       
   672 			error = KErrNotFound;
       
   673 		else
       
   674 			{
       
   675 			// Need to know maximum number of entries that might be deleted
       
   676 			selection->AppendL(id);
       
   677 			error = iServer.IndexAdapter().ExpandSelectionRecursively(*selection);
       
   678 			if (error == KErrNone)
       
   679 				{
       
   680 				// Reserve space in lists
       
   681 				aDeleted->SetReserveL(aDeleted->Count() + selection->Count());
       
   682 				aMoved->SetReserveL(aMoved->Count() + selection->Count());
       
   683 				del->StartL(id, *deleted, *moved);
       
   684 				aSelection.Delete(count);
       
   685 
       
   686 				if (deleted->Count() > 0)
       
   687 					aDeleted->AppendL(deleted->Back(0), deleted->Count());
       
   688 
       
   689 				if (moved->Count() > 0)
       
   690 					aMoved->AppendL(moved->Back(0), moved->Count());
       
   691 				}
       
   692 
       
   693 			deleted->Reset();
       
   694 			moved->Reset();
       
   695 			selection->Reset();
       
   696 			}
       
   697 
       
   698 		// Remember error
       
   699 		if (error != KErrNone && firstError == KErrNone)
       
   700 			firstError = error;
       
   701 		}
       
   702 
       
   703 	User::LeaveIfError(firstError);
       
   704 	CleanupStack::PopAndDestroy(4); // del, selection, moved, deleted
       
   705 	}
       
   706 
       
   707 /** Gets the index entry for a specified entry ID.
       
   708 
       
   709 @param aId ID of the entry to get
       
   710 @param aEntry On return, a pointer to the index entry with ID aId
       
   711 @return KErrNone on success; KErrNotFound if the no entry exists with the specified ID
       
   712 */
       
   713 EXPORT_C TInt CMsvServerEntry::GetEntryFromId(TMsvId aId,TMsvEntry*& aEntry)
       
   714 //
       
   715 // sets aEntry to the TMsvEntry according to the TMsvId, returns error code
       
   716 //
       
   717 	{
       
   718 	return iServer.IndexAdapter().GetEntry(aId, aEntry);
       
   719 	}
       
   720 
       
   721 
       
   722 EXPORT_C CMsvStore* CMsvServerEntry::ReadStoreL()
       
   723 //
       
   724 // Returns the message store for the current context with read access only
       
   725 //
       
   726 /** Obtains the message store for the current context with read-only access.
       
   727 
       
   728 Multiple clients can read from a store simultaneously. If another client is already
       
   729 writing to the store, the function leaves with KErrAccessDenied.
       
   730 
       
   731 The returned CMsvStore must be deleted when it is no longer required.
       
   732 
       
   733 @leave KErrAccessDenied Store is locked by another process
       
   734 @leave KErrNoMemory Not enough memory to open store
       
   735 @leave KErrNotFound There is no store associated with this entry
       
   736 @return Context's message store open for read-only access */
       
   737 	{
       
   738 	// Leave if the message store is not currently available
       
   739 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   740 	__ASSERT_ALWAYS(iStore==NULL, PanicServer(EMsvStoreAlreadyOpen2));
       
   741 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext6));
       
   742 
       
   743 	// must have a context
       
   744 	if (iEntry.Id()==KMsvNullIndexEntryId)
       
   745 		User::Leave(KErrNotSupported);
       
   746 
       
   747 	TBool locked;
       
   748 	User::LeaveIfError(iServer.IndexAdapter().IsStoreLocked(iEntry.Id(), locked));
       
   749 	if (locked)
       
   750 		User::Leave(KErrAccessDenied);
       
   751 
       
   752 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	// open the store
       
   753 		{
       
   754 		iStore = CMsvStore::OpenForReadL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id(), iEntry.iMtm);
       
   755 		}
       
   756 #else
       
   757 	iStore = CMsvStore::OpenForReadL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id());
       
   758 #endif
       
   759 	// error ignored as the entry exists, we know this because IsStoreLocked would have returned and error otherwise
       
   760 	iServer.IndexAdapter().IncStoreReaderCount(iEntry.Id());
       
   761 	return iStore;
       
   762 	}
       
   763 
       
   764 
       
   765 EXPORT_C CMsvStore* CMsvServerEntry::EditStoreL()
       
   766 //
       
   767 // Returns the message store for the current context with write access
       
   768 //
       
   769 /** Obtains the message store for the current context with read-write access.
       
   770 
       
   771 Only one client can edit a message store at one time. If another client is
       
   772 already writing to the store, KErrAccessDenied is returned. However, any number
       
   773 of clients can read from the store simultaneously.
       
   774 
       
   775 If the message store does not exist when EditStore() is called, a new message
       
   776 store is created.
       
   777 
       
   778 The returned CMsvStore must be deleted when it is no longer required.
       
   779 
       
   780 @leave KErrAccessDenied Store is locked by another process or is read-only
       
   781 @leave KErrNoMemory Not enough memory to open store
       
   782 @return Context's message store open for read-write access */
       
   783 	{
       
   784 	__ASSERT_ALWAYS(iStore==NULL, PanicServer(EMsvStoreAlreadyOpen1));
       
   785 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext7));
       
   786 
       
   787 	// Leave if the message store is not currently available
       
   788 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   789 	// must have a context
       
   790 	if (iEntry.Id()==KMsvNullIndexEntryId)
       
   791 		User::Leave(KErrNotSupported);
       
   792 
       
   793 	if (iEntry.ReadOnly())
       
   794 		User::Leave(KErrAccessDenied);
       
   795 	User::LeaveIfError(iServer.IndexAdapter().LockStore(iEntry.Id()));
       
   796 	// open the store
       
   797 	TInt error = 0;
       
   798 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   799 		{
       
   800 		TRAP(error,  iStore = CMsvStore::OpenForWriteL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id(), iEntry.iMtm));
       
   801 		}
       
   802 #else
       
   803 	TRAP(error,  iStore = CMsvStore::OpenForWriteL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id()));
       
   804 #endif
       
   805 	if (error)
       
   806 		{
       
   807 		iServer.IndexAdapter().ReleaseStore(iEntry.Id());
       
   808 		User::Leave(error);
       
   809   		}
       
   810 
       
   811 	return iStore;
       
   812 	}
       
   813 
       
   814 
       
   815 
       
   816 void CMsvServerEntry::HandleStoreEvent(TMsvStoreEvent aEvent, TMsvId aId)
       
   817 //
       
   818 //
       
   819 //
       
   820 	{
       
   821 	__ASSERT_DEBUG(aId==iEntry.Id(), PanicServer(EMsvUnknownStoreId));
       
   822 
       
   823 	switch (aEvent)
       
   824 		{
       
   825 		case EMsvEditStoreClosed:
       
   826 			iServer.IndexAdapter().ReleaseStore(aId); // error ignored
       
   827 			iStore=NULL;
       
   828 			break;
       
   829 		case EMsvReadStoreClosed:
       
   830 			iServer.IndexAdapter().DecStoreReaderCount(aId); // error ignored
       
   831 			iStore=NULL;
       
   832 			break;
       
   833 		default:
       
   834 			__ASSERT_DEBUG(EFalse, PanicServer(EMsvUnknownStoreEvent2));
       
   835 		}
       
   836 	}
       
   837 
       
   838 EXPORT_C TInt CMsvServerEntry::GetChildren(CMsvEntrySelection& aSelection)
       
   839 //
       
   840 // Returns a the selection of the children of the current context
       
   841 //
       
   842 /** Gets a selection containing the IDs of all the context children.
       
   843 
       
   844 If the entry has no children, the selection is empty.
       
   845 
       
   846 @param aSelection Initially, this must be an empty selection. On return, it
       
   847 lists the children.
       
   848 @return KErrNone - success;
       
   849 KErrMemory - a memory allocation failed */
       
   850 	{
       
   851 	return DoGetChildren(KMsvNullIndexEntryId, KNullUid, KNullUid, aSelection);
       
   852 	}
       
   853 
       
   854 EXPORT_C TInt CMsvServerEntry::GetChildrenWithService(TMsvId aServiceId, CMsvEntrySelection& aSelection)
       
   855 //
       
   856 // Returns a the selection of the children of the current context with the given service
       
   857 //
       
   858 /** Gets a selection containing the IDs of all the context children with the specified
       
   859 service.
       
   860 
       
   861 If the entry has no children, the selection is empty.
       
   862 
       
   863 @param aServiceId Service by which to filter children
       
   864 @param aSelection Initially, this must be an empty selection. On return, it
       
   865 lists the children.
       
   866 @return KErrNone - success;
       
   867 KErrMemory - a memory allocation failed */
       
   868 	{
       
   869 	return DoGetChildren(aServiceId, KNullUid, KNullUid, aSelection);
       
   870 	}
       
   871 
       
   872 EXPORT_C TInt CMsvServerEntry::GetChildrenWithMtm(TUid aMtm, CMsvEntrySelection& aSelection)
       
   873 //
       
   874 // Returns a the selection of the children of the current context with the given Mtm
       
   875 //
       
   876 /** Gets a selection containing the IDs of all the context children with the specified
       
   877 MTM.
       
   878 
       
   879 If the entry has no children, the selection is empty.
       
   880 
       
   881 @param aMtm MTM by which to filter children
       
   882 @param aSelection Initially, this must be an empty selection. On return, it
       
   883 lists the children.
       
   884 @return KErrNone - success;
       
   885 KErrMemory - a memory allocation failed */
       
   886 	{
       
   887 	return DoGetChildren(KMsvNullIndexEntryId, aMtm, KNullUid, aSelection);
       
   888 	}
       
   889 
       
   890 EXPORT_C TInt CMsvServerEntry::GetChildrenWithType(TUid aType, CMsvEntrySelection& aSelection)
       
   891 //
       
   892 // Returns a the selection of the children of the current context with the given type
       
   893 //
       
   894 /** Gets a selection containing the IDs of all the context children with the specified
       
   895 entry type.
       
   896 
       
   897 If the entry has no children, the selection is empty.
       
   898 
       
   899 @param aType Entry type by which to filter children
       
   900 @param aSelection Initially, this must be an empty selection. On return, it
       
   901 lists the children.
       
   902 @return KErrNone - success;
       
   903 KErrMemory - a memory allocation failed */
       
   904 	{
       
   905 	return DoGetChildren(KMsvNullIndexEntryId, KNullUid, aType, aSelection);
       
   906 	}
       
   907 
       
   908 TInt CMsvServerEntry::DoGetChildren(TMsvId aServiceId, TUid aMtm, TUid aType, CMsvEntrySelection& aSelection)
       
   909 	{
       
   910 	TRAPD(err, DoGetChildrenL(aServiceId, aMtm, aType, aSelection));
       
   911 	return err;
       
   912 	}
       
   913 
       
   914 void CMsvServerEntry::DoGetChildrenL(TMsvId aServiceId, TUid aMtm, TUid aType, CMsvEntrySelection& aSelection)
       
   915 	{
       
   916 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext8));
       
   917 
       
   918 	CMsvEntryFilter* filter = CMsvEntryFilter::NewLC();
       
   919 
       
   920 	filter->SetService(aServiceId);
       
   921 	filter->SetMtm(aMtm);
       
   922 	filter->SetType(aType);
       
   923 	filter->SetOrder(iOrdering);
       
   924 	filter->SetSortMtm(iMtm);
       
   925 
       
   926 	aSelection.Reset();
       
   927 	User::LeaveIfError(iServer.IndexAdapter().GetChildrenId(iEntry.Id(), *filter, aSelection));
       
   928 	CleanupStack::PopAndDestroy(); // filter
       
   929 	}
       
   930 
       
   931 EXPORT_C CMsvServerEntry* CMsvServerEntry::NewEntryL(TMsvId aId)
       
   932 //
       
   933 // Creates a new server entry object set with entry aId as context
       
   934 //
       
   935 /** Gets a new CMsvServerEntry object for the specified entry ID.
       
   936 
       
   937 The call locks the entry, preventing it being accessed by other clients.
       
   938 
       
   939 The object must be deleted when it is no longer required. The lock is released
       
   940 when the object is deleted or the context is changed with SetEntry().
       
   941 
       
   942 @param aId ID of the entry to access
       
   943 @leave KErrLocked Entry is locked
       
   944 @leave KErrNoMemory A memory allocation failed
       
   945 @leave KErrNotFound The entry does not exist
       
   946 @return If the function succeeds, this is a pointer to a newly allocated and
       
   947 initialised object. */
       
   948 	{
       
   949 	return CMsvServerEntry::NewL(iServer, aId);
       
   950 	}
       
   951 
       
   952 
       
   953 EXPORT_C TInt CMsvServerEntry::MoveEntryWithinService(TMsvId aId, TMsvId aDestination)
       
   954 //
       
   955 // Moves the child of the current context
       
   956 //
       
   957 /** Moves a child of the context to under another entry. All descendants will be
       
   958 moved as well. The destination must belong to the same service as the context.
       
   959 
       
   960 If an error occurs, no changes are made.
       
   961 
       
   962 For pre-Unicode releases see the synchronous overload of MoveEntry().
       
   963 
       
   964 @param aId The ID of the entry to move
       
   965 @param aDestination The ID of new parent
       
   966 @return KErrNone if successful, KErrArgument if the destination is a child
       
   967 of aId, KErrInUse if the store or a file associated with the entry is open,
       
   968 KErrNotFound if the aId is not a child of the context KErrPathNotFound, if
       
   969 the destination does not exist. */
       
   970 	{
       
   971 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10));
       
   972 
       
   973 	// only move children
       
   974 	if (!IsAChild(aId))
       
   975 		return KErrNotFound;
       
   976 
       
   977 	// check for moving into its current parent
       
   978 	if (aDestination==iEntry.Id())
       
   979 		return KErrNone;
       
   980 
       
   981 	TRAPD(error, DoMoveEntryL(aId, aDestination));
       
   982 
       
   983 	// notify server of the move
       
   984 	if (error==KErrNone)
       
   985 		{
       
   986 		iServer.NotifyChanged(EMsvEntriesMoved, aId, aDestination, iEntry.Id());
       
   987 		// need to remove owner flag if has no children
       
   988 		TMsvEntry* pEntry;
       
   989 		TInt err = KErrNone;
       
   990 		err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry);
       
   991 		if (err==KErrNone)
       
   992 			iEntry.SetOwner(pEntry->Owner());
       
   993 		}
       
   994 
       
   995 	return error;
       
   996 	}
       
   997 
       
   998 void CMsvServerEntry::DoMoveEntryL(TMsvId aId, TMsvId aDestination)
       
   999 //
       
  1000 //
       
  1001 //
       
  1002 	{
       
  1003 	CMsvMove* move = CMsvMove::NewL(iServer);
       
  1004 	CleanupStack::PushL(move);
       
  1005 	move->StartL(aId, aDestination);
       
  1006 	CleanupStack::PopAndDestroy(); // move
       
  1007 	}
       
  1008 
       
  1009 EXPORT_C TInt CMsvServerEntry::MoveEntriesWithinService(CMsvEntrySelection& aSelection, TMsvId aDestination)
       
  1010 //
       
  1011 //
       
  1012 //
       
  1013 /** Moves a child of the context to under another entry. All descendants will be
       
  1014 moved as well. The destination must belong to the same service as the context.
       
  1015 
       
  1016 @param aSelection The entries to move. On return, contains the children that
       
  1017 could not be fully moved.
       
  1018 @param aDestination The ID of new parent
       
  1019 @return KErrNone if successful, KErrArgument if the destination is a child
       
  1020 of aSelection entry, KErrInUse if the store or a file associated with an entry
       
  1021 is open, KErrNotFound if an aSelection entry is not a child of the context
       
  1022 the, or KErrPathNotFound if the destination does not exist. */
       
  1023 	{
       
  1024 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10));
       
  1025 
       
  1026 	CMsvEntrySelection* moved = NULL;
       
  1027 
       
  1028 	TRAPD(error, DoMoveEntriesL(aSelection, aDestination, moved));
       
  1029 
       
  1030 	if (moved && moved->Count())
       
  1031 		{
       
  1032 		iServer.NotifyChanged(EMsvEntriesMoved, *moved, aDestination, iEntry.Id());
       
  1033 
       
  1034 		// need to remove owner flag if has no children
       
  1035 		TMsvEntry* pEntry;
       
  1036 		TInt err = KErrNone;
       
  1037 		err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry);
       
  1038 		if (err==KErrNone)
       
  1039 			iEntry.SetOwner(pEntry->Owner());
       
  1040 		}
       
  1041 
       
  1042 	delete moved;
       
  1043 	return error;
       
  1044 	}
       
  1045 
       
  1046 void CMsvServerEntry::DoMoveEntriesL(CMsvEntrySelection& aSelection, TMsvId aDestination, CMsvEntrySelection*& aMoved)
       
  1047 	{
       
  1048 	__ASSERT_DEBUG(!aMoved, PanicServer(EMsvMoveSelectionNotNull));
       
  1049 	__ASSERT_DEBUG(aSelection.Count() > 0, PanicServer(EMsvMovingEmptySelection));
       
  1050 
       
  1051 	aMoved = new(ELeave)CMsvEntrySelection;
       
  1052 	aMoved->SetReserveL(aSelection.Count());
       
  1053 
       
  1054 	CMsvMove* move = CMsvMove::NewL(iServer);
       
  1055 	CleanupStack::PushL(move);
       
  1056 
       
  1057 	TInt error = KErrNone;
       
  1058 
       
  1059 	TInt count = aSelection.Count();
       
  1060 	while(count--)
       
  1061 		{
       
  1062 		TMsvId id = aSelection.At(count);
       
  1063 		if (!IsAChild(id))
       
  1064 			error = KErrNotFound;
       
  1065 		else
       
  1066 			{
       
  1067 			move->StartL(id, aDestination);
       
  1068 			aSelection.Delete(count);
       
  1069 			aMoved->AppendL(id);
       
  1070 			}
       
  1071 		}
       
  1072 	User::LeaveIfError(error);
       
  1073 	CleanupStack::PopAndDestroy(); // move
       
  1074 	}
       
  1075 
       
  1076 EXPORT_C void CMsvServerEntry::MoveEntryL(TMsvId aId, TMsvId aDestination, TRequestStatus& aObserverStatus)
       
  1077 //
       
  1078 //
       
  1079 //
       
  1080 /** Moves a child of the context to another entry that belongs to a different service.
       
  1081 All descendants will be moved as well.
       
  1082 
       
  1083 The move is carried out asynchronously. The caller should supply in aObserverStatus
       
  1084 the status word of an active object that it owns. The function will signal
       
  1085 this to be completed when the move is complete.
       
  1086 
       
  1087 If the function leaves, no changes are made.
       
  1088 
       
  1089 In pre-Unicode versions an asynchronous move can be cancelled through CancelMoveEntry();
       
  1090 in other releases, use Cancel().
       
  1091 
       
  1092 @param aId The ID of the entry to move
       
  1093 @param aDestination The ID of new parent
       
  1094 @param aObserverStatus The request status to be completed when the operation
       
  1095 has finished
       
  1096 @leave KErrArgument The destination is a child of aId
       
  1097 @leave KErrInUse The store or a file associated with the entry is open
       
  1098 @leave KErrNoMemory A memory allocation failed
       
  1099 @leave KErrNotFound aId is not a child of the context
       
  1100 @leave KErrPathNotFound The destination does not exist */
       
  1101 	{
       
  1102 	CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection;
       
  1103 	CleanupStack::PushL(selection);
       
  1104 	selection->AppendL(aId);
       
  1105 
       
  1106 	MoveEntriesL(*selection, aDestination, aObserverStatus);
       
  1107 
       
  1108 	CleanupStack::PopAndDestroy(); // selection
       
  1109 	}
       
  1110 
       
  1111 EXPORT_C void CMsvServerEntry::MoveEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aObserverStatus)
       
  1112 //
       
  1113 //
       
  1114 //
       
  1115 /** Moves a selection of children of the context to another entry that belongs
       
  1116 to a different service. All descendants will be moved as well.
       
  1117 
       
  1118 The move is carried out asynchronously. The caller should supply in aObserverStatus
       
  1119 the status word of an active object that it owns. The function will signal
       
  1120 this to be completed when the move is complete.
       
  1121 
       
  1122 @param aSelection The IDs of the entry to move. On return, contains the children
       
  1123 that could not be fully moved.
       
  1124 @param aDestination The ID of new parent
       
  1125 @param aObserverStatus The request status to be completed when the operation
       
  1126 has finished
       
  1127 @leave KErrArgument The destination is a child of an aSelection entry
       
  1128 @leave KErrInUse The store or a file associated with an entry is open
       
  1129 @leave KErrNoMemory A memory allocation failed
       
  1130 @leave KErrNotFound An aSelection entry is not a child of the context
       
  1131 @leave KErrPathNotFound The destination does not exist */
       
  1132 	{
       
  1133 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10));
       
  1134 	__ASSERT_ALWAYS(aDestination!=iEntry.Id(), PanicServer(EMsvMovingToSamePArent));
       
  1135 	__ASSERT_ALWAYS(iEntryState == EMsvIdle, PanicServer(EMsvServerEntryNotIdle));
       
  1136 	__ASSERT_ALWAYS(aSelection.Count() > 0, PanicServer(EMsvEmptySelection));
       
  1137 	__ASSERT_DEBUG(iCopyMove==NULL, PanicServer(EMsvMoveNotCompleted));
       
  1138 
       
  1139 	// only move children
       
  1140 	if (!AreChildren(aSelection))
       
  1141 		User::Leave(KErrNotFound);
       
  1142 
       
  1143 	CMsvMoveEntries* move = CMsvMoveEntries::NewL(iServer);
       
  1144 	CleanupStack::PushL(move);
       
  1145 
       
  1146 	move->StartL(aSelection, aDestination, iStatus);
       
  1147 
       
  1148 	CleanupStack::Pop(); // move
       
  1149 
       
  1150 	iCopyMove=move;
       
  1151 	iEntryState = EMsvMoving;
       
  1152 	iObserverStatus = &aObserverStatus;
       
  1153 	*iObserverStatus = KRequestPending;
       
  1154 
       
  1155 	SetActive();
       
  1156 	}
       
  1157 
       
  1158 EXPORT_C void CMsvServerEntry::CopyEntryL(TMsvId aId, TMsvId aDestination, TRequestStatus& aObserverStatus)
       
  1159 //
       
  1160 // Recursively copies a child of the context to another entry that belongs to a different service.
       
  1161 //
       
  1162 /** Copies a child of the context to another entry. All descendants will be copied
       
  1163 as well.
       
  1164 
       
  1165 The copy is carried out asynchronously. The caller should supply in aObserverStatus
       
  1166 the status word of an active object that it owns. The function will signal
       
  1167 this to be completed when the copy is complete.
       
  1168 
       
  1169 If the function leaves, no changes are made.
       
  1170 
       
  1171 @param aId The ID of the entry to copy
       
  1172 @param aDestination The ID of new parent
       
  1173 @param aObserverStatus The request status to be completed when the operation
       
  1174 has finished
       
  1175 @leave KErrArgument The destination is a child of an aSelection entry
       
  1176 @leave KErrInUse The store or a file associated with an entry is open
       
  1177 @leave KErrNoMemory A memory allocation failed
       
  1178 @leave KErrNotFound An aSelection entry is not a child of the context
       
  1179 @leave KErrPathNotFound The destination does not exist */
       
  1180 	{
       
  1181 	CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection;
       
  1182 	CleanupStack::PushL(selection);
       
  1183 	selection->AppendL(aId);
       
  1184 	iCompletedSelection = NULL;
       
  1185 	iCompletedEntryId = NULL;
       
  1186 
       
  1187 	DoCopyEntriesL(*selection, aDestination, aObserverStatus);
       
  1188 
       
  1189 	CleanupStack::PopAndDestroy(); // selection
       
  1190 	}
       
  1191 
       
  1192 EXPORT_C void CMsvServerEntry::CopyEntryL(TMsvId aId, TMsvId aDestination, TMsvId& aCompletedEntry, TRequestStatus& aObserverStatus)
       
  1193 //
       
  1194 //
       
  1195 //
       
  1196 /** Copies a child of the context to another entry. All descendants will be copied
       
  1197 as well.
       
  1198 
       
  1199 This overload returns the ID of the new entry.
       
  1200 
       
  1201 The copy is carried out asynchronously. The caller should supply in aObserverStatus
       
  1202 the status word of an active object that it owns. The function will signal
       
  1203 this to be completed when the copy is complete.
       
  1204 
       
  1205 If the function leaves, no changes are made.
       
  1206 
       
  1207 @param aId The ID of the entry to copy
       
  1208 @param aDestination The ID of new parent
       
  1209 @param aCompletedEntry On return, the ID of the new entry
       
  1210 @param aObserverStatus The request status to be completed when the operation
       
  1211 has finished
       
  1212 @leave KErrArgument The destination is a child of an aSelection entry
       
  1213 @leave KErrInUse The store or a file associated with an entry is open
       
  1214 @leave KErrNoMemory A memory allocation failed
       
  1215 @leave KErrNotFound An aSelection entry is not a child of the context
       
  1216 @leave KErrPathNotFound The destination does not exist */
       
  1217 	{
       
  1218 	CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection;
       
  1219 	CleanupStack::PushL(selection);
       
  1220 	selection->AppendL(aId);
       
  1221 	iCompletedSelection = NULL;
       
  1222 	iCompletedEntryId = &aCompletedEntry;
       
  1223 
       
  1224 	DoCopyEntriesL(*selection, aDestination, aObserverStatus);
       
  1225 
       
  1226 	CleanupStack::PopAndDestroy(); // selection
       
  1227 	}
       
  1228 
       
  1229 EXPORT_C void CMsvServerEntry::CopyEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aObserverStatus)
       
  1230 //
       
  1231 //
       
  1232 //
       
  1233 /** Copies a selection of children of the context to another entry that belongs
       
  1234 to a different service. All descendants will be copied as well.
       
  1235 
       
  1236 The copy is carried out asynchronously. The caller should supply in aObserverStatus
       
  1237 the status word of an active object that it owns. The function will signal
       
  1238 this to be completed when the copy is complete.
       
  1239 
       
  1240 @param aSelection The IDs of the entry to copy. On return, contains the children
       
  1241 that could not be fully copied.
       
  1242 @param aDestination The ID of new parent
       
  1243 @param aObserverStatus The request status to be completed when the operation
       
  1244 has finished
       
  1245 @leave KErrArgument The destination is a child of an aSelection entry
       
  1246 @leave KErrInUse The store or a file associated with an entry is open
       
  1247 @leave KErrNoMemory A memory allocation failed
       
  1248 @leave KErrNotFound An aSelection entry is not a child of the context
       
  1249 @leave KErrPathNotFound The destination does not exist */
       
  1250 	{
       
  1251 	iCompletedSelection = NULL;
       
  1252 	iCompletedEntryId = NULL;
       
  1253 	DoCopyEntriesL(aSelection, aDestination, aObserverStatus);
       
  1254 	}
       
  1255 
       
  1256 EXPORT_C void CMsvServerEntry::CopyEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, CMsvEntrySelection& aCompletedSelection, TRequestStatus& aObserverStatus)
       
  1257 //
       
  1258 // Recursively copies a selection of children of the context to another entry that belongs to a different service.
       
  1259 // Will return the target entries through the aCompletedSelection parameter.
       
  1260 //
       
  1261 /** Copies a selection of children of the context to another entry that belongs
       
  1262 to a different service. All descendants will be copied as well.
       
  1263 
       
  1264 This overload returns the IDs of the new entries.
       
  1265 
       
  1266 The copy is carried out asynchronously. The caller should supply in aObserverStatus
       
  1267 the status word of an active object that it owns. The function will signal
       
  1268 this to be completed when the copy is complete.
       
  1269 
       
  1270 @param aSelection The IDs of the entry to copy. On return, contains the children
       
  1271 that could not be fully copied.
       
  1272 @param aDestination The ID of new parent
       
  1273 @param aCompletedSelection On return, the IDs of the new entries.
       
  1274 @param aObserverStatus The request status to be completed when the operation
       
  1275 has finished
       
  1276 @leave KErrArgument The destination is a child of an aSelection entry
       
  1277 @leave KErrInUse The store or a file associated with an entry is open
       
  1278 @leave KErrNoMemory A memory allocation failed
       
  1279 @leave KErrNotFound An aSelection entry is not a child of the context
       
  1280 @leave KErrPathNotFound The destination does not exist */
       
  1281 	{
       
  1282 	iCompletedSelection = &aCompletedSelection;
       
  1283 	iCompletedEntryId = NULL;
       
  1284 	DoCopyEntriesL(aSelection, aDestination, aObserverStatus);
       
  1285 	}
       
  1286 
       
  1287 void CMsvServerEntry::DoCopyEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aObserverStatus)
       
  1288 //
       
  1289 //
       
  1290 //
       
  1291 	{
       
  1292 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10));
       
  1293 	__ASSERT_ALWAYS(aDestination!=iEntry.Id(), PanicServer(EMsvCopyingToSameParent));
       
  1294 	__ASSERT_ALWAYS(iEntryState == EMsvIdle, PanicServer(EMsvServerEntryNotIdle));
       
  1295 	__ASSERT_ALWAYS(aSelection.Count() > 0, PanicServer(EMsvEmptySelection));
       
  1296 	__ASSERT_DEBUG(iCopyMove==NULL, PanicServer(EMsvCopyNotCompleted));
       
  1297 
       
  1298 	// only copy children
       
  1299 	if (!AreChildren(aSelection))
       
  1300 		User::Leave(KErrNotFound);
       
  1301 
       
  1302 	CMsvCopyEntries* copy = CMsvCopyEntries::NewL(iServer);
       
  1303 	CleanupStack::PushL(copy);
       
  1304 	copy->StartL(aSelection, aDestination, iStatus);
       
  1305 	CleanupStack::Pop(); // copy
       
  1306 
       
  1307 	iCopyMove=copy;
       
  1308 	iEntryState = EMsvCopying;
       
  1309 	iObserverStatus = &aObserverStatus;
       
  1310 	*iObserverStatus = KRequestPending;
       
  1311 
       
  1312 	SetActive();
       
  1313 	}
       
  1314 void CMsvServerEntry::RunL()
       
  1315 //
       
  1316 //
       
  1317 //
       
  1318 	{
       
  1319 	__ASSERT_DEBUG(iEntryState != EMsvIdle, PanicServer(EMsvServerEntryIdle));
       
  1320 	__ASSERT_DEBUG(iCopyMove, PanicServer(EMsvCopyMoveCompletionMissing));
       
  1321 
       
  1322 	if (iCopyMove->CompletedIds().Count() > 0)
       
  1323 		{
       
  1324 		switch (iEntryState)
       
  1325 			{
       
  1326 			case EMsvMoving:
       
  1327 				{
       
  1328 				iServer.NotifyChanged(EMsvEntriesMoved, iCopyMove->CompletedIds(), iCopyMove->TargetId(), iEntry.Id());
       
  1329 
       
  1330 				TMsvEntry* pEntry;
       
  1331 				TInt err = KErrNone;
       
  1332 				err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry);
       
  1333 				if (err ==KErrNone)
       
  1334 					iEntry.SetOwner(pEntry->Owner());
       
  1335 				break;
       
  1336 				}
       
  1337 
       
  1338 			case EMsvCopying:
       
  1339 				{
       
  1340 				const CMsvEntrySelection& newEntries = static_cast<CMsvCopyEntries*>(iCopyMove)->NewEntryIds();
       
  1341 				iServer.NotifyChanged(EMsvEntriesCreated, newEntries, iCopyMove->TargetId());
       
  1342 
       
  1343 				if (iCompletedSelection)
       
  1344 					{
       
  1345 					iCompletedSelection->Reset();
       
  1346 					TInt count = newEntries.Count();
       
  1347 
       
  1348 					while (count--)
       
  1349 						iCompletedSelection->AppendL(newEntries[count]);
       
  1350 					}
       
  1351 				else if (iCompletedEntryId)
       
  1352 					*iCompletedEntryId = newEntries[0];
       
  1353 
       
  1354 				break;
       
  1355 				}
       
  1356 
       
  1357 			default:
       
  1358 				break;
       
  1359 			}
       
  1360 		}
       
  1361 
       
  1362 	delete iCopyMove;
       
  1363 	iCopyMove = NULL;
       
  1364 	iEntryState = EMsvIdle;
       
  1365 
       
  1366 	User::RequestComplete(iObserverStatus, iStatus.Int());
       
  1367 	}
       
  1368 
       
  1369 
       
  1370 void CMsvServerEntry::DoCancel()
       
  1371 //
       
  1372 //
       
  1373 //
       
  1374 	{
       
  1375 	__ASSERT_DEBUG(iEntryState != EMsvIdle, PanicServer(EMsvServerEntryIdle));
       
  1376 	__ASSERT_DEBUG(iCopyMove, PanicServer(EMsvCopyMoveCancelMissing));
       
  1377 
       
  1378 	iCopyMove->Cancel();
       
  1379 
       
  1380 	delete iCopyMove;
       
  1381 	iCopyMove=NULL;
       
  1382 	iEntryState = EMsvIdle;
       
  1383 
       
  1384 	User::RequestComplete(iObserverStatus, KErrCancel);
       
  1385 	}
       
  1386 
       
  1387 
       
  1388 EXPORT_C TMsvId CMsvServerEntry::OwningService() const
       
  1389 //
       
  1390 //
       
  1391 //
       
  1392 /** Gets the ID of the service that owns the context.
       
  1393 
       
  1394 Local entries are considered as being members of the local service.
       
  1395 
       
  1396 If the entry is the root, then the root ID (KMsvRootIndexEntryId) is returned.
       
  1397 
       
  1398 @return ID of the service that owns this entry */
       
  1399 	{
       
  1400 	if (iEntry.Id()==KMsvRootIndexEntryId)
       
  1401 		return KMsvRootIndexEntryId;
       
  1402 	TMsvId owningService;
       
  1403 	iServer.IndexAdapter().OwningService(iEntry.Id(), owningService); // error ignored as entry obviously exists
       
  1404 	return owningService;
       
  1405 	}
       
  1406 
       
  1407 
       
  1408 EXPORT_C TInt CMsvServerEntry::ChangeAttributes(const CMsvEntrySelection& aSelection, TUint aSetAttributes, TUint aClearAttributes)
       
  1409 //
       
  1410 //
       
  1411 //
       
  1412 /** Provides a quick way to set or clear multiple fields in a selection of entries.
       
  1413 
       
  1414 Fields to change are specified using a bitmask of TMsvAttribute values. Possible
       
  1415 fields that can be changed using this function are:
       
  1416 
       
  1417 1. PC synchronisation
       
  1418 
       
  1419 2. Visibility flag
       
  1420 
       
  1421 3. Read flag
       
  1422 
       
  1423 4. In-preparation flag
       
  1424 
       
  1425 5. Connected flag
       
  1426 
       
  1427 6. New flag
       
  1428 
       
  1429 @param aSelection The entries to change
       
  1430 @param aSetAttributes A bitmask of the fields to set
       
  1431 @param aClearAttributes A bitmask of the fields to clear
       
  1432 @return KErrNone if successful, otherwise one of the system-wide error codes.
       
  1433 KErrNotFound if a specified entry does not exist.
       
  1434 @see TMsvAttribute */
       
  1435 	{
       
  1436 	__ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext11));
       
  1437 
       
  1438 	// only change children
       
  1439 	if (!AreChildren(aSelection))
       
  1440 		return KErrNotFound;
       
  1441 
       
  1442 	// get a copy of the selection
       
  1443 	CMsvEntrySelection* changedEntries=NULL;
       
  1444 	TRAPD(error, changedEntries = aSelection.CopyL());
       
  1445 	if (error)
       
  1446 		return error;
       
  1447 
       
  1448 	// lock all the selection
       
  1449 	TInt count1=aSelection.Count();
       
  1450 	while (count1--)
       
  1451 		{
       
  1452 		error = iServer.IndexAdapter().LockEntry(aSelection.At(count1));
       
  1453 		if (error)
       
  1454 			break;
       
  1455 		}
       
  1456 
       
  1457 	// change the attributes if all were locked
       
  1458 	if (error==KErrNone)
       
  1459 		{
       
  1460 		error = iServer.IndexAdapter().ChangeAttributes(*changedEntries, aSetAttributes, aClearAttributes);
       
  1461 		}
       
  1462 
       
  1463 	// release all that were locked
       
  1464 	TInt count2=aSelection.Count();
       
  1465 	while (--count2>count1)
       
  1466 		{
       
  1467 		iServer.IndexAdapter().ReleaseEntry(aSelection.At(count2));
       
  1468 		}
       
  1469 
       
  1470 
       
  1471 	// notify server if any have been changed
       
  1472 	if (error==KErrNone && changedEntries->Count())
       
  1473 		iServer.NotifyChanged(EMsvEntriesChanged, *changedEntries, iEntry.Id());
       
  1474 
       
  1475 	delete changedEntries;
       
  1476 
       
  1477 	return error;
       
  1478 	}
       
  1479 
       
  1480 
       
  1481 EXPORT_C TBool CMsvServerEntry::HasStoreL() const
       
  1482 /** Tests if the context has an associated message store.
       
  1483 
       
  1484 @return ETrue: entry has a message store EFalse: entry does not have a message
       
  1485 store */
       
  1486 	{
       
  1487 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  1488 	if(iServer.ServerStoreManager().DoesAnyStoreExists(iEntry.Id(), iEntry.iMtm))
       
  1489 		return ETrue;
       
  1490 	else
       
  1491 		return iServer.ServerStoreManager().FileStoreExistsL(iEntry.Id());
       
  1492 #else
       
  1493 	return iServer.ServerStoreManager().FileStoreExistsL(iEntry.Id());
       
  1494 #endif
       
  1495 	}
       
  1496 
       
  1497 
       
  1498 EXPORT_C RFs& CMsvServerEntry::FileSession()
       
  1499 /** Allows a Server-side MTM to access the file session handle created by the Message
       
  1500 Server. This is preferable, as more efficient, to creating another handle.
       
  1501 
       
  1502 @return File session handle */
       
  1503 	{
       
  1504 	return iServer.FileSession();
       
  1505 	}
       
  1506 	
       
  1507