localisation/apparchitecture/apserv/apsnnappupdates.cpp
branchSymbian2
changeset 1 8758140453c0
child 6 c108117318cb
equal deleted inserted replaced
0:e8c1ea2c6496 1:8758140453c0
       
     1 // Copyright (c) 2007-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 the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Non-Native application registration functionality for the AppArc server session
       
    15 // 
       
    16 //
       
    17 
       
    18 
       
    19 #include "apsnnappupdates.h"
       
    20 
       
    21 #include <bautils.h>
       
    22 #include <f32file.h>
       
    23 #include <s32file.h>
       
    24 
       
    25 #include "APAID.H"
       
    26 #include "APGAPLST.H"
       
    27 #include "APSSERV.H"
       
    28 #include "APSSTD.H"
       
    29 #include "../apfile/aprfndr.h"
       
    30 #include "../apgrfx/apprivate.h"
       
    31 #include "apsnnapps.h"
       
    32 
       
    33 
       
    34 /**************************************************************************************************************
       
    35  * TFilePositionReset
       
    36  **************************************************************************************************************/
       
    37 
       
    38 /**
       
    39 This class is used to ensure that a RFile's read/write position is reset to its original value
       
    40 if a leave occurs.
       
    41 
       
    42 @internalComponent
       
    43 */
       
    44 NONSHARABLE_CLASS(TFilePositionReset)
       
    45 	{
       
    46 public:
       
    47 	TFilePositionReset(RFile& aFile) :
       
    48 	 		iFile(aFile),
       
    49  			iOriginalFilePosition(-1)
       
    50  		{
       
    51 	 	}
       
    52 
       
    53 	void RewindToStartLC()
       
    54 		{
       
    55 		TInt originalFilePosition=0;
       
    56 		User::LeaveIfError(iFile.Seek(ESeekCurrent, originalFilePosition)); // retrieves the current file-position
       
    57 		TInt newFilePosition=0;
       
    58 		User::LeaveIfError(iFile.Seek(ESeekStart, newFilePosition)); // RFile::Seek(ESeekStart,..) will not modify the TInt, but needs a reference.
       
    59 		iOriginalFilePosition=originalFilePosition;
       
    60 		CleanupStack::PushL(TCleanupItem(&StaticReset, this));
       
    61 		}
       
    62 
       
    63 	TInt Reset()
       
    64 		{
       
    65 		__ASSERT_DEBUG(iOriginalFilePosition>=0, Panic(ENonNativeAppsNegativeStoredFilePosition));
       
    66 		const TInt error = iFile.Seek(ESeekStart, iOriginalFilePosition);
       
    67 		iOriginalFilePosition=-1;
       
    68 		return error;
       
    69 		}
       
    70 
       
    71 private:
       
    72 	static void StaticReset(TAny* aThis)
       
    73 		{
       
    74 		// ignore the error code from this, we can't do anything about it
       
    75 		static_cast<TFilePositionReset*>(aThis)->Reset();
       
    76 		}
       
    77 
       
    78 private:
       
    79 	RFile& iFile;
       
    80 	TInt iOriginalFilePosition;
       
    81 	};
       
    82 
       
    83 
       
    84 /**************************************************************************************************************
       
    85  * TFileDetails
       
    86  **************************************************************************************************************/
       
    87 
       
    88 TFileDetails::TFileDetails() :
       
    89 		iState(EStateNull) 
       
    90 	{
       
    91 	}
       
    92 
       
    93 /*
       
    94 Returns the real path, (aka the target location) of this file
       
    95 */
       
    96 const TDesC& TFileDetails::Path()
       
    97 	{
       
    98 	__ASSERT_DEBUG(iPath != KNullDesC, Panic(ENonNativeAppsTFileDetailsPathNotSet));
       
    99 	return iPath;
       
   100 	}
       
   101 
       
   102 
       
   103 /*
       
   104 Sets the real path, (aka the target location) of this file
       
   105 */
       
   106 void TFileDetails::SetPath(const TDesC& aPath)
       
   107 	{
       
   108 	__ASSERT_DEBUG(iPath == KNullDesC, Panic(ENonNativeAppsTFileDetailsPathAlreadySet));
       
   109 	iPath = aPath;
       
   110 	}
       
   111 
       
   112 
       
   113 /*
       
   114 Determines whether this TFileDetails has a real path set.
       
   115 If thie object doesn't have a real path set, it is assumed to not be in use
       
   116 */
       
   117 TBool TFileDetails::Exists() const
       
   118 	{
       
   119 	return (iPath != KNullDesC);
       
   120 	}
       
   121 
       
   122 
       
   123 /*
       
   124 Releases whatever file handle is currently held, whether it is on the real file,
       
   125 temporary file, or none at all
       
   126 */
       
   127 void TFileDetails::CloseHandle()
       
   128 	{
       
   129 	iHandle.Close();
       
   130 	}
       
   131 
       
   132 
       
   133 /*
       
   134 Opens a handle on a real file
       
   135 */
       
   136 void TFileDetails::OpenL(RFs& aFs, const TFileName& aFileName)
       
   137 	{
       
   138 	__ASSERT_DEBUG(iState == EStateNull, Panic(ENonNativeAppsTFileDetailsOpenInBadState));
       
   139 	__ASSERT_DEBUG(iPath == KNullDesC, Panic(ENonNativeAppsTFileDetailsOpenWithRealPathSet));
       
   140 	__ASSERT_DEBUG(iTempPath == KNullDesC, Panic(ENonNativeAppsTFileDetailsOpenWithTempPathSet));
       
   141 
       
   142 	User::LeaveIfError(iHandle.Open(aFs, aFileName, EFileShareExclusive|EFileStream|EFileWrite));
       
   143 	iPath = aFileName;
       
   144 	iState = EStateReal;
       
   145 	}
       
   146 
       
   147 /*
       
   148 Creates a new, temporary file to write new data into
       
   149 Used in the preparation of a register-application update to create new resource
       
   150 and icon files before they are moved into their target locations.
       
   151 */
       
   152 void TFileDetails::CreateTemporaryL(RFs& aFs, const TFileName& aDir)
       
   153 	{
       
   154 	__ASSERT_DEBUG(iState == EStateNull, Panic(ENonNativeAppsTFileDetailsCreateTempInBadState));
       
   155 	__ASSERT_DEBUG(iTempPath == KNullDesC, Panic(ENonNativeAppsTFileDetailsCreateTempWithTempPathSet));
       
   156 	RFile file;
       
   157 	CleanupClosePushL(file);
       
   158 	// TODO: remove this hack if/when RFile::Temp is fixed by base
       
   159 	TInt tempErr = KErrAlreadyExists;
       
   160 	/* RFile::Temp is a bit dodgy, at least on Winscw with the proxy FS */
       
   161 	for(TInt tries = 0; tempErr == KErrAlreadyExists && tries < 50; ++tries)
       
   162 		{
       
   163 		tempErr = file.Temp(aFs, aDir, iTempPath, EFileShareExclusive|EFileStream|EFileWrite);
       
   164 		}
       
   165 	User::LeaveIfError(tempErr);
       
   166 	CleanupStack::Pop(&file);
       
   167 	iHandle = file;
       
   168 	iState = EStateTemporary;
       
   169 	}
       
   170 
       
   171 /*
       
   172 Makes aFile a duplicates of the file handle owned by this class.
       
   173 Used to write to a file created by CreateTemporaryL()
       
   174 */
       
   175 void TFileDetails::GetDuplicateHandleL(RFile& aFile)
       
   176 	{
       
   177 	User::LeaveIfError(aFile.Duplicate(iHandle));
       
   178 	}
       
   179 
       
   180 
       
   181 /*
       
   182 RenameToRealL
       
   183 
       
   184 Used to perform a register-appliction update
       
   185 This uses the same code as the non-leaving
       
   186 RenameToReal().
       
   187 */
       
   188 void TFileDetails::RenameToRealL(RFs& aFs)
       
   189 	{
       
   190 	User::LeaveIfError(RenameToReal(aFs));
       
   191 	}
       
   192 
       
   193 /*
       
   194 RenameToReal
       
   195 
       
   196 Used by RenameToRealL() and RestoreReal()
       
   197 @see RenameToRealL
       
   198 @see RestoreReal
       
   199 */
       
   200 TInt TFileDetails::RenameToReal(RFs& aFs)
       
   201 	{
       
   202 	__ASSERT_DEBUG(iState == EStateTemporary, Panic(ENonNativeAppsTFileDetailsRenameToRealInBadState));
       
   203 	__ASSERT_DEBUG(iTempPath != KNullDesC, Panic(ENonNativeAppsTFileDetailsRenameToRealWithoutTempPath));
       
   204 	__ASSERT_DEBUG(iPath != KNullDesC, Panic(ENonNativeAppsTFileDetailsRenameToRealWithoutRealPath));
       
   205 	TParse parse;
       
   206 	parse.SetNoWild(iPath,NULL,NULL);
       
   207 	if(!BaflUtils::FolderExists(aFs,parse.DriveAndPath())) 
       
   208 		{
       
   209 		TInt err = aFs.MkDirAll(parse.DriveAndPath());
       
   210 		if(err != KErrNone)
       
   211 			{
       
   212 			return err;
       
   213 			}
       
   214 		}
       
   215 	//Check if file already exists, if it exists delete it because we might be trying to register an upgrade
       
   216 	if(BaflUtils::FileExists(aFs, iPath))
       
   217 		{
       
   218 		TInt err = BaflUtils::DeleteFile(aFs, iPath);
       
   219 		if(KErrNone != err)
       
   220 			{
       
   221 			return err;
       
   222 			}
       
   223 		}
       
   224 	TInt err = iHandle.Rename(iPath);
       
   225 	if(err != KErrNone)
       
   226 		{
       
   227 		return err;
       
   228 		}
       
   229 	iTempPath.Zero();
       
   230 	iState = EStateReal;
       
   231 	return KErrNone;
       
   232 	}
       
   233 
       
   234 /*
       
   235 RenameToTemporaryL
       
   236 
       
   237 Used to perform a deregister-application update
       
   238 */
       
   239 void TFileDetails::RenameToTemporaryL(RFs& aFs, const TFileName& aDir)
       
   240 	{
       
   241 	__ASSERT_DEBUG(iState == EStateReal, Panic(ENonNativeAppsTFileDetailsRenameToTempInBadState));
       
   242 	__ASSERT_DEBUG(iPath != KNullDesC, Panic(ENonNativeAppsTFileDetailsRenameToTempWithoutRealPathSet));
       
   243 	__ASSERT_DEBUG(iTempPath == KNullDesC, Panic(ENonNativeAppsTFileDetailsRenameToTempWithTempPathSet));
       
   244 	/* create a temp file and delete it to get an unused filename */
       
   245 	RFile file;
       
   246 	CleanupClosePushL(file);
       
   247 	// TODO: remove this hack if/when RFile::Temp is fixed by base
       
   248 	TInt tempErr = KErrAlreadyExists;
       
   249 	/* RFile::Temp is a bit dodgy, at least on Winscw with the proxy FS */
       
   250 	for(TInt tries = 0; tempErr == KErrAlreadyExists && tries < 50; ++tries)
       
   251 		{
       
   252 		tempErr = file.Temp(aFs, aDir, iTempPath, EFileShareExclusive|EFileStream|EFileWrite);
       
   253 		}
       
   254 	User::LeaveIfError(tempErr);
       
   255 	CleanupStack::PopAndDestroy(&file); // close the file handle
       
   256 	const TInt err = aFs.Delete(iTempPath);
       
   257 	if(err != KErrNone && err != KErrNotFound) 
       
   258 		{
       
   259 		User::Leave(err);
       
   260 		}
       
   261 
       
   262 	User::LeaveIfError(iHandle.Rename(iTempPath));
       
   263 	iState = EStateTemporary;
       
   264 	}
       
   265 
       
   266 
       
   267 /*
       
   268 Delete
       
   269 
       
   270 Whatever the state, real or temporary, delete it.
       
   271 Used in the rollback phase of a register-application update.
       
   272 
       
   273 This function releases the handle (if any) and sets the state back to EStateNull
       
   274 */
       
   275 TInt TFileDetails::Delete(RFs& aFs)
       
   276 	{
       
   277 	__ASSERT_DEBUG(iState == EStateNull || iState == EStateReal || iState == EStateTemporary,
       
   278 			Panic(ENonNativeAppsTFileDetailsDeleteInBadState));
       
   279 	if(iState == EStateNull)
       
   280 		{
       
   281 		return KErrNone;
       
   282 		}
       
   283 
       
   284 	iHandle.Close();
       
   285 	TInt err;
       
   286 	if(iState == EStateReal)
       
   287 		{
       
   288 		err = aFs.Delete(iPath);
       
   289 		}
       
   290 	else if(iState == EStateTemporary)
       
   291 		{
       
   292 		err = aFs.Delete(iTempPath);
       
   293 		}
       
   294 	else
       
   295 		{
       
   296 		err = KErrGeneral;
       
   297 		ASSERT(EFalse);
       
   298 		}
       
   299 	iPath.Zero();
       
   300 	iTempPath.Zero();
       
   301 	iState = EStateNull;
       
   302 	return err;
       
   303 	}
       
   304 
       
   305 
       
   306 /*
       
   307 DeleteTemporary
       
   308 
       
   309 Check that the state is EStateTemporary, and delete it.
       
   310 This function is used by the destructor of a deregister-application update
       
   311 
       
   312 This function releases the handle (if any) and sets the state back to EStateNull
       
   313 */
       
   314 TInt TFileDetails::DeleteTemporary(RFs& aFs)
       
   315 	{
       
   316 	__ASSERT_DEBUG(iState == EStateNull || iState == EStateTemporary,
       
   317 			Panic(ENonNativeAppsTFileDetailsDeleteTemporaryInBadState));
       
   318 	if(iState == EStateNull || iState == EStateTemporary)
       
   319 		{
       
   320 		return Delete(aFs);
       
   321 		}
       
   322 	return KErrGeneral;
       
   323 	}
       
   324 
       
   325 
       
   326 /*
       
   327 RestoreReal
       
   328 
       
   329 Whatever the state, real or temporary, try to move it back to the real location.
       
   330 Used in the rollback phase of a deregister-application update.
       
   331 
       
   332 This function releases the handle (if any) and sets the state back to EStateNull
       
   333 */
       
   334 TInt TFileDetails::RestoreReal(RFs& aFs)
       
   335 	{
       
   336 	__ASSERT_DEBUG(iState == EStateNull || iState == EStateReal || iState == EStateTemporary,
       
   337 		Panic(ENonNativeAppsTFileDetailsRestoreRealInBadState));
       
   338 	if(iState == EStateNull)
       
   339 		{
       
   340 		return KErrNone;
       
   341 		}
       
   342 
       
   343 	TInt err = KErrNone;
       
   344 	if(iState == EStateReal)
       
   345 		{
       
   346 		iHandle.Close();
       
   347 		}
       
   348 	else if(iState == EStateTemporary)
       
   349 		{
       
   350 		err = RenameToReal(aFs);
       
   351 		iHandle.Close();
       
   352 		}
       
   353 	else
       
   354 		{
       
   355 		ASSERT(EFalse);
       
   356 		}
       
   357 	iPath.Zero();
       
   358 	iTempPath.Zero();
       
   359 	iState = EStateNull;
       
   360 	return err;
       
   361 	}
       
   362 
       
   363 
       
   364 void TFileDetails::ExternalizeL(RWriteStream& aStream)
       
   365 	{
       
   366 	aStream.WriteUint8L(iState);
       
   367 	aStream.WriteUint32L(iPath.Length());
       
   368 	aStream.WriteL(iPath);
       
   369 	aStream.WriteUint32L(iTempPath.Length());
       
   370 	aStream.WriteL(iTempPath);
       
   371 	}
       
   372 
       
   373 void TFileDetails::ExternalizeContinuationL(RWriteStream& aStream, TInt aTag)
       
   374 	{
       
   375 	aStream.WriteInt8L(CApsNonNativeApplicationsUpdate::EContinuationOfUpdate);
       
   376 	aStream.WriteInt8L(aTag);
       
   377 	ExternalizeL(aStream);
       
   378 	aStream.CommitL(); // beta stopping point
       
   379 	}
       
   380 
       
   381 TInt TFileDetails::ExternalizeContinuation(RWriteStream& aStream, TInt aTag)
       
   382 	{
       
   383 	TRAPD(err,ExternalizeContinuationL(aStream,aTag));
       
   384 	return err;
       
   385 	}
       
   386 
       
   387 void TFileDetails::InternalizeL(RReadStream& aStream, TInt& aPosition)
       
   388 	{
       
   389 	TState state = static_cast<TState>(aStream.ReadUint8L());
       
   390 	TUint pathLen = aStream.ReadUint32L();
       
   391 	if(pathLen > KMaxFileName)
       
   392 		{
       
   393 		User::Leave(KErrCorrupt);
       
   394 		}
       
   395 	TFileName path;
       
   396 	aStream.ReadL(path, pathLen);
       
   397 	TUint tempPathLen = aStream.ReadUint32L();
       
   398 	if(tempPathLen > KMaxFileName)
       
   399 		{
       
   400 		User::Leave(KErrCorrupt);
       
   401 		}
       
   402 	TFileName tempPath;
       
   403 	aStream.ReadL(tempPath, tempPathLen);
       
   404 
       
   405 	/* all dangerous operations are now out of the way */
       
   406 	iState = state;
       
   407 	iPath = path;
       
   408 	iTempPath = tempPath;
       
   409 	// state, length, path, length, temppath
       
   410 	aPosition += sizeof(TUint8) +  sizeof(TUint32) + (pathLen * sizeof(TText)) +  sizeof(TUint32) + (tempPathLen * sizeof(TText));
       
   411 	}
       
   412 
       
   413 /*
       
   414 Works out what file we had a handle on when the log was written, and try to regain it.
       
   415 */	
       
   416 void TFileDetails::PostInternalizeL(RFs& aFs)
       
   417 	{
       
   418 	TInt err;
       
   419 	switch(iState)
       
   420 		{
       
   421 	case EStateNull:
       
   422 		if(iTempPath != KNullDesC)
       
   423 			{
       
   424 			User::Leave(KErrCorrupt);
       
   425 			}
       
   426 		break;
       
   427 	case EStateTemporary:
       
   428 		if(iTempPath == KNullDesC)
       
   429 			{
       
   430 			User::Leave(KErrCorrupt);
       
   431 			}
       
   432 		err = iHandle.Open(aFs, iTempPath, EFileShareExclusive|EFileStream|EFileWrite);
       
   433 		if(err == KErrNotFound || err == KErrPathNotFound)
       
   434 			{
       
   435 			iTempPath.Zero();
       
   436 			iPath.Zero();
       
   437 			iState = EStateNull;
       
   438 			}
       
   439 		else 
       
   440 			{
       
   441 			User::LeaveIfError(err);
       
   442 			}
       
   443 		break;
       
   444 	case EStateReal:
       
   445 		if(iPath == KNullDesC)
       
   446 			{
       
   447 			User::Leave(KErrCorrupt);
       
   448 			}
       
   449 		err = iHandle.Open(aFs, iPath, EFileShareExclusive|EFileStream|EFileWrite);
       
   450 		if(err == KErrNotFound || err == KErrPathNotFound)
       
   451 			{
       
   452 			iTempPath.Zero();
       
   453 			iPath.Zero();
       
   454 			iState = EStateNull;
       
   455 			}
       
   456 		else 
       
   457 			{
       
   458 			User::LeaveIfError(err);
       
   459 			}
       
   460 		break;
       
   461 	default:
       
   462 		User::Leave(KErrCorrupt);
       
   463 		break;
       
   464 		}
       
   465 	}
       
   466 
       
   467 /**************************************************************************************************************
       
   468  * CApsNonNativeApplicationsUpdate
       
   469  **************************************************************************************************************/
       
   470 
       
   471 CApsNonNativeApplicationsUpdate::CApsNonNativeApplicationsUpdate(RFs& aFs, TUid aUid, TState aState, TLogUpdateType aType) :
       
   472 		iState(aState),
       
   473 		iFs(aFs),
       
   474 		iType(aType),
       
   475 		iUid(aUid)
       
   476 	{
       
   477 	}
       
   478 
       
   479 CApsNonNativeApplicationsUpdate::~CApsNonNativeApplicationsUpdate()
       
   480 	{
       
   481 	}
       
   482 
       
   483 CApsNonNativeApplicationsUpdate* CApsNonNativeApplicationsUpdate::Previous() const
       
   484 	{
       
   485 	return iPrevious;
       
   486 	}
       
   487 
       
   488 CApsNonNativeApplicationsUpdate* CApsNonNativeApplicationsUpdate::Next() const
       
   489 	{
       
   490 	return iNext;
       
   491 	}
       
   492 
       
   493 TUid CApsNonNativeApplicationsUpdate::Uid() 
       
   494 	{
       
   495 	return iUid;
       
   496 	}
       
   497 
       
   498 void CApsNonNativeApplicationsUpdate::PerformUpdateL(RApsUpdateLog& aUpdateLog)
       
   499 	{
       
   500 	ASSERT(iState == ENew);
       
   501 	RWriteStream& stream = aUpdateLog.LogWriteStream();
       
   502 
       
   503 	/* NewUpdateSection */
       
   504 	stream.WriteInt8L(ENewUpdate);
       
   505 	stream.WriteInt8L(iType);
       
   506 	stream.WriteInt32L(iUid.iUid);
       
   507 	ExternalizeL(stream);
       
   508 	stream.CommitL(); // alpha stopping point
       
   509 
       
   510 	/* PerformUpdateSection */
       
   511 	stream.WriteInt8L(EPerformUpdate);
       
   512 	stream.WriteInt8L(iType);
       
   513 	stream.WriteInt32L(iUid.iUid);     // beta stopping points
       
   514 	StateChangeL(EPerforming, stream); // ...
       
   515 	DoPerformUpdateL(aUpdateLog);      // ...
       
   516 	StateChangeL(EPerformed, stream);  // ...
       
   517 	stream.WriteInt8L(EEndOfUpdate);
       
   518 	stream.CommitL();                  // alpha stopping point
       
   519 	}
       
   520 
       
   521 void CApsNonNativeApplicationsUpdate::RollbackUpdateL(RApsUpdateLog& aUpdateLog)
       
   522 	{
       
   523 	ASSERT(iState == EPerforming || iState == EPerformed || iState == ERollingBack);
       
   524 	RWriteStream& stream = aUpdateLog.LogWriteStream();
       
   525 	stream.WriteInt8L(ERollbackUpdate);
       
   526 	stream.WriteInt8L(iType);
       
   527 	stream.WriteInt32L(iUid.iUid);
       
   528 	stream.CommitL();                   // beta stopping point
       
   529  	// even if we're already in ERollingBack because we crashed and are reattempting it,
       
   530  	// it's harmless to write a duplicate statechange to the log
       
   531 	StateChangeL(ERollingBack, stream); // beta stopping points
       
   532 	DoRollbackUpdate(aUpdateLog);       // ...
       
   533 	StateChangeL(ERolledBack, stream);  // ...
       
   534 	stream.WriteInt8L(EEndOfUpdate);
       
   535 	stream.CommitL();                   // alpha stopping point
       
   536 	}
       
   537 
       
   538 TFileName CApsNonNativeApplicationsUpdate::TemporaryFilePathL(TDriveName& aDrive)
       
   539 	{
       
   540 	TFileName dir(aDrive);
       
   541 	
       
   542 	// this is safe since KMaxFileName >= (KMaxDriveName + length(KLitPathForTemporaryNonNativeResourceAndIconFiles))
       
   543 	dir.Append(KLitPathForTemporaryNonNativeResourceAndIconFiles);
       
   544 
       
   545 	if(!BaflUtils::FolderExists(iFs,dir)) 
       
   546 		{
       
   547 		User::LeaveIfError(iFs.MkDirAll(dir));
       
   548 		}	
       
   549 	return dir;
       
   550 	}
       
   551 
       
   552 void CApsNonNativeApplicationsUpdate::StateChangeL(TState aState, RWriteStream& aStream)
       
   553 	{
       
   554 	iState = aState;
       
   555 	aStream.WriteInt8L(EChangeOfUpdateState);
       
   556 	aStream.WriteInt8L(iState);
       
   557 	aStream.CommitL(); // beta stopping point
       
   558 	}
       
   559 
       
   560 void CApsNonNativeApplicationsUpdate::InternalizeStateChangeL(RReadStream& aStream, TInt& aPosition)
       
   561 	{
       
   562 	TState state = static_cast<TState>(aStream.ReadInt8L());
       
   563 	++aPosition;
       
   564 	iState = state;
       
   565 	}
       
   566 
       
   567 void CApsNonNativeApplicationsUpdate::InternalizeNewUpdateL(RReadStream& aStream, TInt& aPosition)
       
   568 	{
       
   569 	__ASSERT_DEBUG(iState == ENeedsInternalizing, Panic(ENonNativeAppsNonNativeApplicationsUpdateInternalizeNewUpdateInBadState));
       
   570 	/*
       
   571 	internalize all member variables to how they were before any updates were performed.
       
   572 	*/
       
   573 	InternalizeL(aStream, aPosition);
       
   574 	
       
   575 	iState = ENew; /* the update is now OK to add to the list */
       
   576 	}
       
   577 
       
   578 void CApsNonNativeApplicationsUpdate::InternalizePerformUpdateL(RReadStream& aStream, TInt& aPosition)
       
   579 	{
       
   580 	/*
       
   581 	internalize any state changes and update-specific continuations, until EEndOfUpdate
       
   582 	*/
       
   583 	SharedInternalizeLoopL(aStream, aPosition);
       
   584 	}
       
   585 
       
   586 void CApsNonNativeApplicationsUpdate::InternalizeRollbackUpdateL(RReadStream& aStream, TInt& aPosition)
       
   587 	{
       
   588 	/*
       
   589 	internalize any state changes and update-specific continuations, until EEndOfUpdate
       
   590 	*/
       
   591 	SharedInternalizeLoopL(aStream, aPosition);
       
   592 	}
       
   593 
       
   594 void CApsNonNativeApplicationsUpdate::SharedInternalizeLoopL(RReadStream& aStream, TInt& aPosition)
       
   595 	{
       
   596 	while (ETrue)
       
   597 		{
       
   598 		TInt pos = aPosition;
       
   599 		TLogActionType action = static_cast<TLogActionType>(aStream.ReadInt8L());
       
   600 		pos += sizeof(TInt8);
       
   601 		/* we are at a beta stopping point at the start of each loop iteration,
       
   602 		   so don't update aPosition until we have reached the end of the loop.
       
   603 		   give the funcitons a copy to stop them updating aPosition direclty and
       
   604 		   then leaving */
       
   605 		switch(action)
       
   606 			{
       
   607 		case EChangeOfUpdateState:
       
   608 			InternalizeStateChangeL(aStream, pos);
       
   609 			break;
       
   610 		case EContinuationOfUpdate:
       
   611 			InternalizeUpdateContinuationL(aStream, pos);
       
   612 			break;
       
   613 		case EEndOfUpdate:
       
   614 			aPosition = pos;
       
   615 			return;
       
   616 		default:
       
   617 			User::Leave(KErrCorrupt);
       
   618 			break;
       
   619 			}
       
   620 		aPosition = pos;
       
   621 		}
       
   622 	}
       
   623 
       
   624 /*
       
   625  Default implemenation of a virtual function. does nothing.
       
   626 
       
   627  In this method, subclasses should write out all important, subclass-specific data.
       
   628  It will be called before DoPerformUpdateL.
       
   629  */
       
   630 void CApsNonNativeApplicationsUpdate::ExternalizeL(RWriteStream& /*aStream*/)
       
   631 	{
       
   632 	}
       
   633 
       
   634 /*
       
   635  Default implemenation of a virtual function. does nothing.
       
   636 
       
   637  In this method, subclasses read in any subclass-specific data that was written out
       
   638  by ExternalizeL().
       
   639  */
       
   640 void CApsNonNativeApplicationsUpdate::InternalizeL(RReadStream& /*aStream*/, TInt& /*aPosition*/)
       
   641 	{
       
   642 	}
       
   643 
       
   644 /*
       
   645  Default implemenation of a virtual function. does nothing.
       
   646 
       
   647  In this method, subclasses should handle any EContinuationOfUpdate messages that
       
   648  they might have written to the log during DoPerformUpdateL or DoRollbackUpdate
       
   649  */
       
   650 void CApsNonNativeApplicationsUpdate::InternalizeUpdateContinuationL(RReadStream& /*aStream*/, TInt& /*aPosition*/)
       
   651 	{
       
   652 	}
       
   653 
       
   654 /*
       
   655  Default implemenation of a virtual function. does nothing.
       
   656 
       
   657  In this method, subclasses should do any internal initialization that is dependent on
       
   658  data that may be changed by InternalizeUpdateContinuationL().
       
   659  
       
   660  InternalizeUpdateContinuationL() may be called many times over and its implementation
       
   661  may change the same member variable many times.
       
   662  This function will only be called once, and it will be called after the entire log has
       
   663  been read and InternalizeUpdateContinuationL() has been called for the last time.
       
   664  */
       
   665 void CApsNonNativeApplicationsUpdate::PostInternalizeL()
       
   666 	{
       
   667 	}
       
   668 
       
   669 /**************************************************************************************************************
       
   670  * CApsRegisterNonNativeApplication
       
   671  **************************************************************************************************************/
       
   672 
       
   673 CApsRegisterNonNativeApplication* CApsRegisterNonNativeApplication::NewL(RFs& aFs, TUid aUid, const TDriveName& aDrive, TState aState)
       
   674 	{
       
   675 	return new(ELeave) CApsRegisterNonNativeApplication(aFs, aUid, aDrive, aState);
       
   676 	}
       
   677 
       
   678 CApsRegisterNonNativeApplication::CApsRegisterNonNativeApplication(RFs& aFs, TUid aUid, const TDriveName& aDrive, TState aState) :
       
   679 		CApsNonNativeApplicationsUpdate(aFs, aUid, aState, ERegisterApplication),
       
   680 		iDrive(aDrive)
       
   681 	{
       
   682 	}
       
   683 
       
   684 void CApsRegisterNonNativeApplication::SetResourceFileTargetLocation(const TDesC& aLocation)
       
   685 	{
       
   686 	iResourceFile.SetPath(aLocation);
       
   687 	}
       
   688 
       
   689 void CApsRegisterNonNativeApplication::SetLocalisableResourceFileTargetLocation(const TDesC& aLocation)
       
   690 	{
       
   691 	iLocalisableResourceFile.SetPath(aLocation);
       
   692 	}
       
   693 
       
   694 void CApsRegisterNonNativeApplication::SetIconFileTargetLocation(const TDesC& aLocation)
       
   695 	{
       
   696 	iIconFile.SetPath(aLocation);
       
   697 	}
       
   698 
       
   699 void CApsRegisterNonNativeApplication::WriteResourceFileL(const TDesC8& aData, const TDesC8* aDataPrefix) 
       
   700 	{
       
   701 	WriteResourceFileL(iResourceFile, aData, aDataPrefix);
       
   702 	}
       
   703 
       
   704 void CApsRegisterNonNativeApplication::WriteLocalisableResourceFileL(const TDesC8& aData, const TDesC8* aDataPrefix)
       
   705 	{
       
   706 	WriteResourceFileL(iLocalisableResourceFile, aData, aDataPrefix);
       
   707 	}
       
   708 
       
   709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   710 
       
   711 /**
       
   712 Create a new file in a designated temporary-files directory
       
   713 */
       
   714 void CApsRegisterNonNativeApplication::NewTemporaryFileL(TFileDetails& aFile)
       
   715 	{
       
   716 	TFileName path(TemporaryFilePathL(iDrive));
       
   717 	aFile.CreateTemporaryL(iFs,path);
       
   718 	}
       
   719 
       
   720 /**
       
   721 Writes a resource file to a new temporary file
       
   722  */
       
   723 void CApsRegisterNonNativeApplication::WriteResourceFileL(TFileDetails& aFile, const TDesC8& aData, const TDesC8* aDataPrefix)
       
   724 	{
       
   725 	// create temp file, put stuff on the cleanup stack
       
   726 	NewTemporaryFileL(aFile);
       
   727 	RFileWriteStream targetStream;
       
   728 	CleanupClosePushL(targetStream);
       
   729 
       
   730 	// the stream takes ownership of the file handle and closes it, so make a copy
       
   731 	RFile targetFile;
       
   732 	aFile.GetDuplicateHandleL(targetFile);
       
   733 	targetStream.Attach(targetFile); // will take ownership of the handle and set targetFile to a Null handle
       
   734 
       
   735 	if (aDataPrefix!=NULL)
       
   736 		{
       
   737 		targetStream.WriteL(*aDataPrefix);
       
   738 		}
       
   739 	targetStream.WriteL(aData);
       
   740 	targetStream.CommitL();
       
   741 
       
   742 	CleanupStack::PopAndDestroy(&targetStream);
       
   743 	}
       
   744 
       
   745 /**
       
   746 This function will copy the file provided to a new temporary file.
       
   747 Upon success or failure, the read/write position of aSourceFile should remain unchanged.
       
   748  */
       
   749 void CApsRegisterNonNativeApplication::CopyIconFileL(RFile& aSourceFile)
       
   750 	{
       
   751 	NewTemporaryFileL(iIconFile);
       
   752 
       
   753 	// RFile*Stream::Attach will take ownership of the handle we give it, but we want to hold
       
   754 	// on to the handles we have. To achieve this, we give Attach a copy of the file handle,
       
   755 	// for both streams.
       
   756 	RFileWriteStream targetStream;
       
   757 	CleanupClosePushL(targetStream);
       
   758 	RFile targetFile;
       
   759 	iIconFile.GetDuplicateHandleL(targetFile);
       
   760 	targetStream.Attach(targetFile);
       
   761 
       
   762 	// rewind to start, but restore original position if a leave occurs
       
   763 	TFilePositionReset filePositionReset(aSourceFile);
       
   764 	filePositionReset.RewindToStartLC();
       
   765 
       
   766 	RFileReadStream sourceStream;
       
   767 	CleanupClosePushL(sourceStream);
       
   768 	RFile sourceFile;
       
   769 	User::LeaveIfError(sourceFile.Duplicate(aSourceFile));
       
   770 	sourceStream.Attach(sourceFile);
       
   771 
       
   772 	targetStream.WriteL(sourceStream);
       
   773 	targetStream.CommitL();
       
   774 	CleanupStack::PopAndDestroy(&sourceStream);
       
   775 
       
   776 	// perform these seperately so we can leave if Reset fails
       
   777 	CleanupStack::Pop(&filePositionReset);
       
   778 	User::LeaveIfError(filePositionReset.Reset());
       
   779 
       
   780 	CleanupStack::PopAndDestroy(&targetStream);
       
   781 	}
       
   782 
       
   783 void CApsRegisterNonNativeApplication::DoPerformUpdateL(RApsUpdateLog& aUpdateLog)
       
   784 	{
       
   785 	HBufC* hDrive = iDrive.AllocL();
       
   786 	TInt err = aUpdateLog.DrivesAffected().InsertInOrder(hDrive, TLinearOrder<HBufC>(CApaAppList::CompareStrings));
       
   787 	if(err != KErrNone)
       
   788 		{
       
   789 		delete hDrive;
       
   790 		}
       
   791 
       
   792 	if ((err != KErrNone) &&
       
   793 	    (err != KErrAlreadyExists)) // We silently ignore attempts to insert duplicates
       
   794 		{
       
   795 		User::Leave(err);
       
   796 		}
       
   797 	
       
   798 	RWriteStream& stream = aUpdateLog.LogWriteStream();
       
   799 
       
   800 	iResourceFile.RenameToRealL(iFs);
       
   801 
       
   802 	/* make a note of what's changed */
       
   803 	iResourceFile.ExternalizeContinuationL(stream, EResourceFileUpdate);
       
   804 
       
   805 	if(iLocalisableResourceFile.Exists()) 
       
   806 		{
       
   807 		iLocalisableResourceFile.RenameToRealL(iFs);
       
   808 		iResourceFile.ExternalizeContinuationL(stream, ELocalisableResourceFileUpdate);
       
   809 		}
       
   810 
       
   811 	if(iIconFile.Exists())
       
   812 		{
       
   813 		iIconFile.RenameToRealL(iFs);
       
   814 		iResourceFile.ExternalizeContinuationL(stream, EIconFileUpdate);
       
   815 		}
       
   816 	
       
   817 	HBufC* hPath = iResourceFile.Path().AllocL();
       
   818 	err = aUpdateLog.NewRegistrationFiles().InsertInOrder(hPath, TLinearOrder<HBufC>(CApaAppList::CompareStrings));
       
   819 	if(err != KErrNone)
       
   820 		{
       
   821 		delete hPath;
       
   822 		}
       
   823 	
       
   824 	if ((err != KErrNone) &&
       
   825 	    (err != KErrAlreadyExists)) // We silently ignore attempts to insert duplicates
       
   826 		{
       
   827 		User::Leave(err);
       
   828 		}
       
   829 	}
       
   830 
       
   831 void CApsRegisterNonNativeApplication::DoRollbackUpdate(RApsUpdateLog& aUpdateLog)
       
   832 	{
       
   833 	RWriteStream& stream = aUpdateLog.LogWriteStream();
       
   834 
       
   835 	/* TFileDetails::Delete() is safe to call whatever state the object is in.
       
   836 
       
   837 	   if it was never opened, it'll do nothing, otherwise it'll delete whichever
       
   838 	   file (real/temp) it has a handle on.
       
   839 	
       
   840 	   ignore the return codes since we can't do anything about it if they fail */
       
   841 	iResourceFile.Delete(iFs);
       
   842 	iResourceFile.ExternalizeContinuation(stream, EResourceFileUpdate);
       
   843 
       
   844 	iLocalisableResourceFile.Delete(iFs);
       
   845 	iResourceFile.ExternalizeContinuation(stream, ELocalisableResourceFileUpdate);
       
   846 
       
   847 	iIconFile.Delete(iFs);
       
   848 	iResourceFile.ExternalizeContinuation(stream, EIconFileUpdate);
       
   849 	}
       
   850 
       
   851 
       
   852 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   853 
       
   854 void CApsRegisterNonNativeApplication::ExternalizeL(RWriteStream& aStream)
       
   855 	{
       
   856 	/* write our initial state to the log stream */
       
   857 	aStream.WriteUint32L(iDrive.Length());
       
   858 	aStream.WriteL(iDrive);
       
   859 	iResourceFile.ExternalizeL(aStream);
       
   860 	iLocalisableResourceFile.ExternalizeL(aStream);
       
   861 	iIconFile.ExternalizeL(aStream);
       
   862 	}
       
   863 
       
   864 void CApsRegisterNonNativeApplication::InternalizeL(RReadStream& aStream, TInt& aPosition)
       
   865 	{
       
   866 	// we can update aPosition whenever we like in this function since we're protected
       
   867 	// from it being left at a bad value by the copy taken by CApsNonNativeApplicationsUpdateList::InternalizeActionL
       
   868 	TUint driveLen = aStream.ReadUint32L();
       
   869 	aPosition += sizeof(TUint32);
       
   870 	if(driveLen > KMaxDriveName)
       
   871 		{
       
   872 		User::Leave(KErrCorrupt);
       
   873 		}
       
   874 	iDrive.Zero();
       
   875 	aStream.ReadL(iDrive, driveLen);
       
   876 	aPosition += driveLen * sizeof(TText);
       
   877 
       
   878 	iResourceFile.InternalizeL(aStream, aPosition);
       
   879 	iLocalisableResourceFile.InternalizeL(aStream, aPosition);
       
   880 	iIconFile.InternalizeL(aStream, aPosition);
       
   881 	}
       
   882 	
       
   883 void CApsRegisterNonNativeApplication::InternalizeUpdateContinuationL(RReadStream& aStream, TInt& aPosition)
       
   884 	{
       
   885 	// we can update aPosition whenever we like in this function since we're protected
       
   886 	// from it being left at a bad value by the copy taken by CApsNonNativeApplicationsUpdate::SharedInternalizeLoopL
       
   887 
       
   888 	TLogContinuationType type = static_cast<TLogContinuationType>(aStream.ReadInt8L());
       
   889 	aPosition += sizeof(TInt8);
       
   890 
       
   891 	switch(type)
       
   892 		{
       
   893 	case EResourceFileUpdate:
       
   894 		iResourceFile.InternalizeL(aStream, aPosition);
       
   895 		break;
       
   896 	case ELocalisableResourceFileUpdate:
       
   897 		iLocalisableResourceFile.InternalizeL(aStream, aPosition);
       
   898 		break;
       
   899 	case EIconFileUpdate:
       
   900 		iIconFile.InternalizeL(aStream, aPosition);
       
   901 		break;
       
   902 	default:
       
   903 		User::Leave(KErrCorrupt);
       
   904 		break;
       
   905 		}
       
   906 	}
       
   907 
       
   908 void CApsRegisterNonNativeApplication::PostInternalizeL()
       
   909 	{
       
   910 	iResourceFile.PostInternalizeL(iFs);
       
   911 	iLocalisableResourceFile.PostInternalizeL(iFs);
       
   912 	iIconFile.PostInternalizeL(iFs);
       
   913 	}
       
   914 	
       
   915 CApsRegisterNonNativeApplication::~CApsRegisterNonNativeApplication()
       
   916 	{
       
   917 	/*
       
   918 	if we performed the update successfully, just close the handles and leave
       
   919 	the reg files in place.
       
   920 
       
   921 	in all other cases, just delete everything that still exists
       
   922 	 */
       
   923 	if(iState == EPerformed) 
       
   924 		{
       
   925 		iResourceFile.CloseHandle();
       
   926 		iLocalisableResourceFile.CloseHandle();
       
   927 		iIconFile.CloseHandle();
       
   928 		}
       
   929 	else
       
   930 		{
       
   931 		iResourceFile.Delete(iFs);
       
   932 		iLocalisableResourceFile.Delete(iFs);
       
   933 		iIconFile.Delete(iFs);
       
   934 		}
       
   935 	}
       
   936 
       
   937 
       
   938 /**************************************************************************************************************
       
   939  * CApsDeregisterNonNativeApplication
       
   940  **************************************************************************************************************/
       
   941 
       
   942 CApsDeregisterNonNativeApplication* CApsDeregisterNonNativeApplication::NewL(RFs& aFs, CApaAppListServer& aServ, TUid aUid, TState aState)
       
   943 	{
       
   944 	return new(ELeave)CApsDeregisterNonNativeApplication(aFs, aServ, aUid, aState);
       
   945 	}
       
   946 
       
   947 CApsDeregisterNonNativeApplication::CApsDeregisterNonNativeApplication(RFs& aFs, CApaAppListServer& aServ, TUid aUid, TState aState) :
       
   948 		CApsNonNativeApplicationsUpdate(aFs, aUid, aState, EDeregisterApplication),
       
   949 		iServ(aServ)
       
   950 	{
       
   951 	}
       
   952 
       
   953 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   954 
       
   955 
       
   956 CApaAppData* CApsDeregisterNonNativeApplication::FindAppDataLC(RApsUpdateLog& aUpdateLog)
       
   957 	{
       
   958 	/* search back through the list for a an update concerning the same Uid */
       
   959 	CApsNonNativeApplicationsUpdate* prev = Previous();
       
   960 	while(prev != NULL)
       
   961 		{
       
   962 		if(prev->Uid() == Uid())
       
   963 			break;
       
   964 		prev = prev->Previous();
       
   965 		}
       
   966 
       
   967 	/* if none found, use apparc's app list as a shortcut */
       
   968 	CApaAppData* appData = NULL;
       
   969 	if(prev == NULL)
       
   970 		{
       
   971 		appData = iServ.AppList().AppDataByUid(Uid());
       
   972 
       
   973 		if(appData != NULL) 
       
   974 			{
       
   975 			// create a new AppData so we can put it on the cleanup stack.
       
   976 			// if the NewL fails for whatever reson, fall back to the search code below
       
   977 
       
   978 			// this is a bit tricky because we need to create the appdata from a
       
   979 			// TApaAppEntry for the reg file, but using appData->AppEntry() will give us
       
   980 			// one for the dll.
       
   981 			TApaAppEntry entry;
       
   982 			entry.iFullName = appData->RegistrationFileName();
       
   983 			TEntry fsEntry;
       
   984 
       
   985 			User::LeaveIfError(iFs.Entry(entry.iFullName,fsEntry));
       
   986 			entry.iUidType = fsEntry.iType;
       
   987 
       
   988 			appData = NULL;
       
   989 			#ifdef SYMBIAN_APPARC_APPINFO_CACHE
       
   990  				TRAP_IGNORE(appData = CApaAppData::NewL(entry,iFs));
       
   991  			#else
       
   992  				{
       
   993  				// find the default icons (.mbm file) for applications, wrt current locale
       
   994  				TFileName* tempFileName = NULL;
       
   995  				tempFileName->Append(KDefaultAppIconMbm);
       
   996  				BaflUtils::NearestLanguageFile(iFs, *tempFileName); 
       
   997  				HBufC* defaultAppIcon = tempFileName->AllocL();
       
   998  				TRAP_IGNORE(appData = CApaAppData::NewL(entry,iFs,*defaultAppIcon));
       
   999  				}
       
  1000  			#endif //SYMBIAN_APPARC_APPINFO_CACHE
       
  1001 			if(appData != NULL)
       
  1002 				{
       
  1003 				CleanupStack::PushL(appData);
       
  1004 				return appData;
       
  1005 				}
       
  1006 			}
       
  1007 		}
       
  1008 
       
  1009 	/*
       
  1010 	 * If the appData wasn't found or we can't trust the app list because of previous updates,
       
  1011 	 * attempt to find and load the appData manually
       
  1012 	 */
       
  1013 	CApaAppRegFinder* regFinder = CApaAppRegFinder::NewLC(iFs);
       
  1014 	TBool found = EFalse;
       
  1015 	TApaAppEntry appEntry;
       
  1016 
       
  1017 	regFinder->FindAllAppsL();
       
  1018 	RPointerArray<HBufC>& forcedRegs = aUpdateLog.NewRegistrationFiles();
       
  1019 
       
  1020 	while(regFinder->NextL(appEntry,forcedRegs))
       
  1021 		{
       
  1022 		if (appEntry.iUidType[2] == Uid())
       
  1023 			{
       
  1024 			found = ETrue;
       
  1025 			break;
       
  1026 			}
       
  1027 		}
       
  1028 	CleanupStack::PopAndDestroy(regFinder);
       
  1029 
       
  1030 	if(found)
       
  1031 		{
       
  1032 		#ifdef SYMBIAN_APPARC_APPINFO_CACHE
       
  1033  			appData = CApaAppData::NewL(appEntry, iFs);
       
  1034  		#else
       
  1035 			{
       
  1036  			// find the default icons (.mbm file) for applications, wrt current locale
       
  1037  			TFileName* tempFileName = NULL;
       
  1038  			tempFileName->Append(KDefaultAppIconMbm);
       
  1039  			BaflUtils::NearestLanguageFile(iFs, *tempFileName); 
       
  1040  			HBufC* defaultAppIcon = tempFileName->AllocL();
       
  1041  			appData = CApaAppData::NewL(appEntry, iFs,*defaultAppIcon);	
       
  1042  			}
       
  1043  		#endif //SYMBIAN_APPARC_APPINFO_CACHE 
       
  1044 		CleanupStack::PushL(appData);
       
  1045 		return appData;
       
  1046 		}
       
  1047 
       
  1048 	CleanupStack::PushL(static_cast<CApaAppData*>(NULL));
       
  1049 	return NULL;
       
  1050 	}
       
  1051 		
       
  1052 void CApsDeregisterNonNativeApplication::RenameToTemporaryL(TFileDetails& aFile, RApsUpdateLog& aUpdateLog)
       
  1053 	{
       
  1054 	/* get the drive */
       
  1055 	TParse parse;
       
  1056 	parse.SetNoWild(aFile.Path(), NULL, NULL);
       
  1057 	if(!parse.DrivePresent())
       
  1058 		{
       
  1059 		// should really never happen
       
  1060 		User::Leave(KErrPathNotFound);
       
  1061 		}
       
  1062 	TDriveName drive(parse.Drive());
       
  1063 
       
  1064 	HBufC* hDrive = drive.AllocL();
       
  1065 	TInt err = aUpdateLog.DrivesAffected().InsertInOrder(hDrive, TLinearOrder<HBufC>(CApaAppList::CompareStrings));
       
  1066 	if(err != KErrNone)
       
  1067 		{
       
  1068 		delete hDrive;
       
  1069 		}
       
  1070 	
       
  1071 	TFileName path(TemporaryFilePathL(drive));
       
  1072 
       
  1073 	aFile.RenameToTemporaryL(iFs,path);
       
  1074 	}
       
  1075 
       
  1076 void CApsDeregisterNonNativeApplication::DoPerformUpdateL(RApsUpdateLog& aUpdateLog)
       
  1077 	{
       
  1078 	CApaAppData* appData = FindAppDataLC(aUpdateLog);
       
  1079 	if(appData == NULL)
       
  1080 		{
       
  1081 		/*
       
  1082 		 * App not found.
       
  1083 		 * Behavioural backwards compatibility says we shouldn't raise an error here,
       
  1084 		 * instead just let it go and carry on.
       
  1085 		 */
       
  1086 		CleanupStack::Pop(appData);
       
  1087 		return;
       
  1088 		}
       
  1089 
       
  1090 	/*
       
  1091 	 for each of the 3 files, open a handle on the real file if it exists
       
  1092 	 the first one (iResourceFile) is mandatory
       
  1093 	 */
       
  1094 	TRAPD(err,iResourceFile.OpenL(iFs, appData->RegistrationFileName()));
       
  1095 	if(err != KErrNone && err != KErrNotFound)
       
  1096 		{
       
  1097 		User::Leave(err);
       
  1098 		}
       
  1099 
       
  1100 	if(appData->LocalisableResourceFileName() != KNullDesC)
       
  1101 		{
       
  1102 		TRAP(err,iLocalisableResourceFile.OpenL(iFs, appData->LocalisableResourceFileName()));
       
  1103 		if(err != KErrNone && err != KErrNotFound)
       
  1104 			{
       
  1105 			User::Leave(err);
       
  1106 			}
       
  1107 		}
       
  1108 
       
  1109 	if(appData->IconFileName() != KNullDesC)
       
  1110 		{
       
  1111 		TRAP(err,iIconFile.OpenL(iFs, appData->IconFileName()));
       
  1112 		if(err != KErrNone && err != KErrNotFound)
       
  1113 			{
       
  1114 			User::Leave(err);
       
  1115 			}
       
  1116 		}
       
  1117 
       
  1118 	CleanupStack::PopAndDestroy(appData);
       
  1119 
       
  1120 	/*
       
  1121 	 perform the actual updates
       
  1122 	 */
       
  1123 	RWriteStream& stream = aUpdateLog.LogWriteStream();
       
  1124 
       
  1125 	if(iIconFile.Exists())
       
  1126 		{
       
  1127 		RenameToTemporaryL(iIconFile, aUpdateLog);
       
  1128 		iIconFile.ExternalizeContinuationL(stream, EIconFileUpdate);
       
  1129 		}
       
  1130 	
       
  1131 	if(iLocalisableResourceFile.Exists())
       
  1132 		{
       
  1133 		RenameToTemporaryL(iLocalisableResourceFile, aUpdateLog);
       
  1134 		iLocalisableResourceFile.ExternalizeContinuationL(stream, ELocalisableResourceFileUpdate);
       
  1135 		}
       
  1136 
       
  1137 	RenameToTemporaryL(iResourceFile, aUpdateLog);
       
  1138 	iResourceFile.ExternalizeContinuationL(stream, EResourceFileUpdate);
       
  1139 	}
       
  1140 
       
  1141 void CApsDeregisterNonNativeApplication::DoRollbackUpdate(RApsUpdateLog& aUpdateLog)
       
  1142 	{
       
  1143 	RWriteStream& stream = aUpdateLog.LogWriteStream();
       
  1144 
       
  1145 	iResourceFile.RestoreReal(iFs);
       
  1146 	iResourceFile.ExternalizeContinuation(stream, EResourceFileUpdate);
       
  1147 
       
  1148 	iLocalisableResourceFile.RestoreReal(iFs);
       
  1149 	iLocalisableResourceFile.ExternalizeContinuation(stream, ELocalisableResourceFileUpdate);
       
  1150 	
       
  1151 	iIconFile.RestoreReal(iFs);
       
  1152 	iIconFile.ExternalizeContinuation(stream, EIconFileUpdate);
       
  1153 	}
       
  1154 
       
  1155 void CApsDeregisterNonNativeApplication::ExternalizeL(RWriteStream& aStream)
       
  1156 	{
       
  1157 	iResourceFile.ExternalizeL(aStream);
       
  1158 	iLocalisableResourceFile.ExternalizeL(aStream);
       
  1159 	iIconFile.ExternalizeL(aStream);
       
  1160 	}
       
  1161 
       
  1162 void CApsDeregisterNonNativeApplication::InternalizeL(RReadStream& aStream, TInt& aPosition)
       
  1163 	{
       
  1164 	// we can update aPosition whenever we like in this function since we're protected
       
  1165 	// from it being left at a bad value by the copy taken by CApsNonNativeApplicationsUpdateList::InternalizeActionL
       
  1166 	iResourceFile.InternalizeL(aStream, aPosition);
       
  1167 	iLocalisableResourceFile.InternalizeL(aStream, aPosition);
       
  1168 	iIconFile.InternalizeL(aStream, aPosition);
       
  1169 	}
       
  1170 
       
  1171 void CApsDeregisterNonNativeApplication::InternalizeUpdateContinuationL(RReadStream& aStream, TInt& aPosition)
       
  1172 	{
       
  1173 	// we can update aPosition whenever we like in this function since we're protected
       
  1174 	// from it being left at a bad value by the copy taken by CApsNonNativeApplicationsUpdate::SharedInternalizeLoopL
       
  1175 
       
  1176 	TLogContinuationType type = static_cast<TLogContinuationType>(aStream.ReadInt8L());
       
  1177 	aPosition += sizeof(TInt8);
       
  1178 
       
  1179 	switch(type)
       
  1180 		{
       
  1181 	case EResourceFileUpdate:
       
  1182 		iResourceFile.InternalizeL(aStream, aPosition);
       
  1183 		break;
       
  1184 	case ELocalisableResourceFileUpdate:
       
  1185 		iLocalisableResourceFile.InternalizeL(aStream, aPosition);
       
  1186 		break;
       
  1187 	case EIconFileUpdate:
       
  1188 		iIconFile.InternalizeL(aStream, aPosition);
       
  1189 		break;
       
  1190 	default:
       
  1191 		User::Leave(KErrCorrupt);
       
  1192 		break;
       
  1193 		}
       
  1194 	}
       
  1195 
       
  1196 void CApsDeregisterNonNativeApplication::PostInternalizeL()
       
  1197 	{
       
  1198 	iResourceFile.PostInternalizeL(iFs);
       
  1199 	iLocalisableResourceFile.PostInternalizeL(iFs);
       
  1200 	iIconFile.PostInternalizeL(iFs);
       
  1201 	}
       
  1202 
       
  1203 CApsDeregisterNonNativeApplication::~CApsDeregisterNonNativeApplication()
       
  1204 	{
       
  1205 	/*
       
  1206 	if we performed the update successfully, we need to delete the temporary
       
  1207 
       
  1208 	in all other cases, just delete everything that still exists
       
  1209 	 */
       
  1210 	if(iState == EPerformed) 
       
  1211 		{
       
  1212 		// in this state we know that Perform has completed successfully.
       
  1213 		iResourceFile.DeleteTemporary(iFs);
       
  1214 		iLocalisableResourceFile.DeleteTemporary(iFs);
       
  1215 		iIconFile.DeleteTemporary(iFs);
       
  1216 		}
       
  1217 	else
       
  1218 		{
       
  1219 		// Hopefully these are now (back) in their target locations.
       
  1220 		// if they're not, there's nothing we can do now, so abandon them either way
       
  1221 		iResourceFile.CloseHandle();
       
  1222 		iLocalisableResourceFile.CloseHandle();
       
  1223 		iIconFile.CloseHandle();
       
  1224 		}
       
  1225 	}
       
  1226 
       
  1227 #ifdef _DEBUG
       
  1228 /**************************************************************************************************************
       
  1229  * CApsAlwaysFailUpdate
       
  1230  **************************************************************************************************************/
       
  1231 
       
  1232 CApsAlwaysFailUpdate::CApsAlwaysFailUpdate(RFs& aFs, TState aState) :
       
  1233 		CApsNonNativeApplicationsUpdate(aFs,TUid::Uid(0xDEADBEEF),aState,EFail)
       
  1234 	{
       
  1235 	}
       
  1236 
       
  1237 void CApsAlwaysFailUpdate::DoPerformUpdateL(RApsUpdateLog& /*aUpdateLog*/)
       
  1238 	{
       
  1239 	User::Leave(KErrGeneral);
       
  1240 	}
       
  1241 
       
  1242 /**************************************************************************************************************
       
  1243  * CApsAlwaysPanicUpdate
       
  1244  **************************************************************************************************************/
       
  1245 
       
  1246 CApsAlwaysPanicUpdate::CApsAlwaysPanicUpdate(RFs& aFs, TState aState) :
       
  1247 		CApsNonNativeApplicationsUpdate(aFs,TUid::Uid(0xCAFEBABE),aState,EPanic)
       
  1248 	{
       
  1249 	}
       
  1250 
       
  1251 void CApsAlwaysPanicUpdate::DoPerformUpdateL(RApsUpdateLog& /*aUpdateLog*/)
       
  1252 	{
       
  1253 	TBool jit = User::JustInTime();
       
  1254 	User::SetJustInTime(EFalse);
       
  1255 	Panic(ENonNativeAppsTestHandlingPanicDuringUpdate);
       
  1256 	User::SetJustInTime(jit);
       
  1257 	}
       
  1258 
       
  1259 /**************************************************************************************************************
       
  1260  * CApsAlwaysPanicOnRollbackUpdate
       
  1261  **************************************************************************************************************/
       
  1262 
       
  1263 CApsAlwaysPanicOnRollbackUpdate::CApsAlwaysPanicOnRollbackUpdate(RFs& aFs, TState aState) :
       
  1264 		CApsNonNativeApplicationsUpdate(aFs,TUid::Uid(0x1337D00D),aState,ERollbackPanic)
       
  1265 	{
       
  1266 	}
       
  1267 
       
  1268 void CApsAlwaysPanicOnRollbackUpdate::DoRollbackUpdate(RApsUpdateLog& /*aUpdateLog*/)
       
  1269 	{
       
  1270 	TBool jit = User::JustInTime();
       
  1271 	User::SetJustInTime(EFalse);
       
  1272 	Panic(ENonNativeAppsTestHandlingPanicDuringRollback);
       
  1273 	User::SetJustInTime(jit);
       
  1274 	}
       
  1275 
       
  1276 #endif // _DEBUG