commands/sudo/sudo.cpp
changeset 0 7f656887cf89
child 45 534b01198c2d
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // sudo.cpp
       
     2 // 
       
     3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #define __INCLUDE_CAPABILITY_NAMES__
       
    14 #include <fshell/ioutils.h>
       
    15 #include <f32image.h>
       
    16 #include <fshell/memoryaccesscmd.h>
       
    17 #include <e32rom.h>
       
    18 
       
    19 using namespace IoUtils;
       
    20 
       
    21 class CCmdSudo : public CMemoryAccessCommandBase
       
    22 	{
       
    23 public:
       
    24 	static CCommandBase* NewLC();
       
    25 	~CCmdSudo();
       
    26 private:
       
    27 	CCmdSudo();
       
    28 	static void DeleteModifiedBinary(TAny* aSelf);
       
    29 	void DeleteModifiedBinary();
       
    30 	TBool FileExists(const TDesC& aFileName);
       
    31 	void FixupExeInMemoryL(RProcess& aProcess);
       
    32 	void CalculateCaps();
       
    33 
       
    34 	void FindExeL();
       
    35 	void CopyExeLC();
       
    36 	void FixupExeL();
       
    37 	void RunExeL();
       
    38 	void FixupCoreExeLC();
       
    39 
       
    40 private: // From CCommandBase.
       
    41 	virtual const TDesC& Name() const;
       
    42 	virtual void DoRunL();
       
    43 	virtual void ArgumentsL(RCommandArgumentList& aArguments);
       
    44 	virtual void OptionsL(RCommandOptionList& aOptions);
       
    45 
       
    46 private:
       
    47 	HBufC* iCmd;
       
    48 	HBufC* iArgs;
       
    49 	RPointerArray<HBufC> iAdd;
       
    50 	RPointerArray<HBufC> iRemove;
       
    51 	TCapabilitySet iCapsToAdd;
       
    52 	TCapabilitySet iCapsToRemove;
       
    53 	TUint iSid;
       
    54 	TUint iVid;
       
    55 	TUint iHeapMin;
       
    56 	TUint iHeapMax;
       
    57 	TUint iStackSize;
       
    58 	TInt iProcessPriority;
       
    59 
       
    60 	TBool iKeep;
       
    61 	TBool iWait;
       
    62 	TBool iChangeBinaryOnDisk;
       
    63 	TBool iFileIsInCore;
       
    64 
       
    65 	TFileName iPath;
       
    66 	TFileName iNewPath;
       
    67 	CArrayPtrFlat<HBufC>* iPathsToCleanup;
       
    68 	// following 2 are temporaries needed during CopyExeLC
       
    69 	TFileName iTempSrc;
       
    70 	TFileName iTempDest;
       
    71 	};
       
    72 
       
    73 
       
    74 CCommandBase* CCmdSudo::NewLC()
       
    75 	{
       
    76 	CCmdSudo* self = new(ELeave) CCmdSudo();
       
    77 	CleanupStack::PushL(self);
       
    78 	self->BaseConstructL();
       
    79 	return self;
       
    80 	}
       
    81 
       
    82 CCmdSudo::~CCmdSudo()
       
    83 	{
       
    84 	delete iCmd;
       
    85 	delete iArgs;
       
    86 	iAdd.ResetAndDestroy();
       
    87 	iRemove.ResetAndDestroy();
       
    88 	
       
    89 	if (iPathsToCleanup)
       
    90 		{
       
    91 		for (TInt i = 0; i < iPathsToCleanup->Count(); i++)
       
    92 			{
       
    93 			HBufC* file = (*iPathsToCleanup)[i];
       
    94 			//Printf(_L("Deleting file %S (not really)\n"), file);
       
    95 			Fs().Delete(*file);
       
    96 			delete file;
       
    97 			}
       
    98 		}
       
    99 	delete iPathsToCleanup;
       
   100 	}
       
   101 
       
   102 CCmdSudo::CCmdSudo()
       
   103 	{
       
   104 	}
       
   105 
       
   106 TCapability CapabilityFromString(const TDesC& aName)
       
   107 	{
       
   108 	TBuf<32> cap;
       
   109 	for (TInt i = 0; i < ECapability_Limit; i++)
       
   110 		{
       
   111 		cap.Copy(TPtrC8((TUint8*)CapabilityNames[i]));
       
   112 		if (aName.CompareF(cap) == 0)
       
   113 			{
       
   114 			return (TCapability)i;
       
   115 			}
       
   116 		}
       
   117 	return ECapability_None;
       
   118 	}
       
   119 
       
   120 void CCmdSudo::DoRunL()
       
   121 	{
       
   122 	iPathsToCleanup = new(ELeave) CArrayPtrFlat<HBufC>(8);
       
   123 	CalculateCaps();
       
   124 	FindExeL();
       
   125 	if (iChangeBinaryOnDisk)
       
   126 		{
       
   127 #ifndef __WINS__
       
   128 		// Don't try and use IsFileInRom on WINSCW, the emulator makes a mess of it and anyway, shadowing isn't supported so it being in the core is irrelevant
       
   129 		iFileIsInCore = FsL().IsFileInRom(iPath) != NULL;
       
   130 #endif
       
   131 		if (iFileIsInCore)
       
   132 			{
       
   133 			// Things in core have to be handled differently
       
   134 			iNewPath = iPath; // We don't call CopyExeLC so something has to set this
       
   135 			FixupCoreExeLC();
       
   136 			}
       
   137 		else
       
   138 			{
       
   139 			CopyExeLC();
       
   140 			FixupExeL();
       
   141 			}
       
   142 		}
       
   143 	else
       
   144 		{
       
   145 		if (iHeapMin || iHeapMax  || iStackSize) LeaveIfErr(KErrArgument, _L("Heap or stack sizes cannot be modified unless you specify --disk"));
       
   146 		if (iKeep) LeaveIfErr(KErrArgument, _L("--keep option makes no sense if --disk isn't specified."));
       
   147 
       
   148 		CleanupStack::PushL((CBase*)NULL); // RunExeL expects a cleanup item for DeleteModifiedBinary, which isn't necessary when --disk isn't specified
       
   149 		// Everything else is taken care of from RunExeL
       
   150 		}
       
   151 	RunExeL();
       
   152 	}
       
   153 
       
   154 void CCmdSudo::FindExeL()
       
   155 	{
       
   156 	if (!iChangeBinaryOnDisk)
       
   157 		{
       
   158 		// If we're not changing on disk, it's fine to just use the path as-is and let RProcess::Create sort it out
       
   159 		iPath = *iCmd;
       
   160 		iNewPath = iPath;
       
   161 		return;
       
   162 		}
       
   163 
       
   164 #ifdef __WINS__
       
   165 	PrintWarning(_L("On WINS, exe-name must be a complete path to a E32 exe"));
       
   166 	iPath = *iCmd;
       
   167 #else
       
   168 
       
   169 	// We can't reliably use RProcess::Create then FileName because the reason we're calling sudo may be because
       
   170 	// the capabilities don't allow it to load.
       
   171 	_LIT(KExe, ".exe");
       
   172 	_LIT(KSysBin, "\\sys\\bin\\");
       
   173 	iPath = *iCmd;
       
   174 	if (iPath.Right(KExe().Length()).CompareF(KExe) != 0)
       
   175 		{
       
   176 		iPath.Append(KExe);
       
   177 		}
       
   178 	TParsePtrC parse(iPath);
       
   179 	if (!parse.PathPresent())
       
   180 		{
       
   181 		TFindFile find(FsL());
       
   182 		TInt found = find.FindByDir(iPath, KSysBin);
       
   183 		LeaveIfErr(found, _L("Couldn't locate file %S"), &iPath);
       
   184 		iPath = find.File();
       
   185 		}
       
   186 #endif
       
   187 	}
       
   188 
       
   189 void CCmdSudo::CopyExeLC()
       
   190 	{
       
   191 	iNewPath = iPath;
       
   192 	iNewPath[0] = 'c'; // Has to be on C otherwise the loader performs hash checks
       
   193 	iNewPath.Append(_L(".sudoed.exe"));
       
   194 
       
   195 	CleanupStack::PushL(TCleanupItem(&CCmdSudo::DeleteModifiedBinary, this));
       
   196 
       
   197 	TInt err = FsL().MkDirAll(iNewPath); // In case C:\sys\bin doesn't exist yet
       
   198 	if (err && err != KErrAlreadyExists)
       
   199 		{
       
   200 		LeaveIfErr(err, _L("Couldn't create C:\\sys\\bin"));
       
   201 		}
       
   202 
       
   203 	CFileMan* fm = CFileMan::NewL(Fs());
       
   204 	CleanupStack::PushL(fm);
       
   205 
       
   206 	LeaveIfErr(fm->Copy(iPath, iNewPath), _L("Couldn't copy file from %S to %S"), &iPath, &iNewPath);
       
   207 	// Clear the read-only bit in the case where we've copied from Z drive
       
   208 	LeaveIfErr(Fs().SetAtt(iNewPath, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag"));
       
   209 
       
   210 	/* TODO this code looks like it should work but doesn't. Something in cone or similar is not behaving the way it looks like it should.
       
   211 
       
   212 	// In case it's an app which will rely on having its main rsc and its mbm file on the same drive as it, copy them over too
       
   213 	// (Damn cone for not searching drives or working relative to the reg rsc...)
       
   214 	TParsePtrC parse(iPath);
       
   215 	TPtrC exename = parse.Name();
       
   216 
       
   217 	_LIT(KResFmt, "%c:\\Resource\\Apps\\%S.rsc");
       
   218 	_LIT(KResDestFmt, "C:\\Resource\\Apps\\%S.sudoed.rsc");
       
   219 	iTempSrc.Format(KResFmt, iPath[0], &exename);
       
   220 	iTempDest.Format(KResDestFmt, &exename);
       
   221 
       
   222 	iPathsToCleanup->SetReserveL(iPathsToCleanup->Count() + 2);
       
   223 	iPathsToCleanup->AppendL(iTempDest.AllocL());
       
   224 	LeaveIfErr(fm->Copy(iTempSrc, iTempDest), _L("Couldn't copy ancillary file %S to %S"), &iTempSrc, &iTempDest);
       
   225 	LeaveIfErr(Fs().SetAtt(iTempDest, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag of %S"), &iTempDest);
       
   226 
       
   227 	_LIT(KMbmFmt, "%c:\\Resource\\Apps\\%S.mbm");
       
   228 	iTempSrc.Format(KMbmFmt, iPath[0], &exename);
       
   229 	iTempDest.Format(KMbmFmt, 'c', &exename);
       
   230 	if (!FileExists(iTempDest))
       
   231 		{
       
   232 		iPathsToCleanup->AppendL(iTempDest.AllocL());
       
   233 		LeaveIfErr(fm->Copy(iTempSrc, iTempDest), _L("Couldn't copy ancillary file %S to %S"), &iTempSrc, &iTempDest);
       
   234 		LeaveIfErr(Fs().SetAtt(iTempDest, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag of %S"), &iTempDest);
       
   235 		}
       
   236 	*/
       
   237 	CleanupStack::PopAndDestroy(fm);
       
   238 	}
       
   239 
       
   240 void CCmdSudo::FixupExeL()
       
   241 	{
       
   242 	// Now fix up the capabilities or other stuff
       
   243 	RFile file;
       
   244 	CleanupClosePushL(file);
       
   245 	LeaveIfErr(file.Open(Fs(), iNewPath, EFileWrite|EFileStream|EFileShareAny), _L("Couldn't open file"));
       
   246 
       
   247 	E32ImageHeaderV* imageHeader=new(ELeave)E32ImageHeaderV;
       
   248 	CleanupStack::PushL(imageHeader);
       
   249 	TPckg<E32ImageHeaderV> ptr(*imageHeader);
       
   250 	LeaveIfErr(file.Read(ptr, sizeof(E32ImageHeaderV)), _L("Couldn't read E32ImageHeader"));
       
   251 
       
   252 	SSecurityInfo& secinfo = imageHeader->iS;
       
   253 	for (TInt i = 0; i < ECapability_Limit; i++)
       
   254 		{
       
   255 		TCapability cap = (TCapability)i;
       
   256 		if (iCapsToAdd.HasCapability(cap)) secinfo.iCaps.AddCapability(cap);
       
   257 		if (iCapsToRemove.HasCapability(cap)) reinterpret_cast<TCapabilitySet*>(&secinfo.iCaps)->RemoveCapability(cap);
       
   258 		}
       
   259 
       
   260 	if (iOptions.IsPresent(&iSid))
       
   261 		{
       
   262 		secinfo.iSecureId = iSid;
       
   263 		}
       
   264 	if (iOptions.IsPresent(&iVid))
       
   265 		{
       
   266 		secinfo.iVendorId = iVid;
       
   267 		}
       
   268 	if (iHeapMin)
       
   269 		{
       
   270 		imageHeader->iHeapSizeMin = iHeapMin;
       
   271 		}
       
   272 	if (iHeapMax)
       
   273 		{
       
   274 		imageHeader->iHeapSizeMax = iHeapMax;
       
   275 		}
       
   276 	if (iStackSize)
       
   277 		{
       
   278 		imageHeader->iStackSize = iStackSize;
       
   279 		}
       
   280 	if (iProcessPriority)
       
   281 		{
       
   282 		imageHeader->iProcessPriority = iProcessPriority;
       
   283 		}
       
   284 
       
   285 	// Update e32 checksum
       
   286 	imageHeader->iHeaderCrc = KImageCrcInitialiser;
       
   287 	TUint32 crc = 0;
       
   288 	Mem::Crc32(crc, imageHeader, imageHeader->TotalSize());
       
   289 	imageHeader->iHeaderCrc = crc;
       
   290 
       
   291 	LeaveIfErr(file.Write(0, ptr), _L("Couldn't write updated header back to file"));
       
   292 	CleanupStack::PopAndDestroy(2, &file); // imageHeader, file
       
   293 	}
       
   294 
       
   295 void CCmdSudo::RunExeL()
       
   296 	{
       
   297 	// Now actually execute it
       
   298 #ifdef __WINS__
       
   299 	if (iChangeBinaryOnDisk)
       
   300 		{
       
   301 		PrintWarning(_L("Updated file written to %S. Not actually executing it."), &iNewPath);
       
   302 		CleanupStack::Pop(); // DeleteModifiedBinary
       
   303 		return;
       
   304 		}
       
   305 #endif
       
   306 
       
   307 	RChildProcess childProcess;
       
   308 	TRAPL(childProcess.CreateL(iNewPath, iArgs ? *iArgs : KNullDesC(), IoSession(), Stdin(), Stdout(), Stderr(), Env()), _L("Failed to execute %S"), &iNewPath);
       
   309 	if (iKeep)
       
   310 		{
       
   311 		Printf(_L("Executing %S...\r\n"), &iNewPath);
       
   312 		CleanupStack::Pop(); // Don't delete if user asked for --keep
       
   313 		}
       
   314 	else
       
   315 		{
       
   316 		CleanupStack::PopAndDestroy(); // DeleteModifiedBinary - remove the binary before we actually start running it, so it is guaranteed cleaned up even if the user kills us with ctrl-c
       
   317 		}
       
   318 	if (!iChangeBinaryOnDisk)
       
   319 		{
       
   320 		// Time to get memaccess involved
       
   321 		TRAPD(err, FixupExeInMemoryL(childProcess.Process()));
       
   322 		if (err)
       
   323 			{
       
   324 			childProcess.Process().Kill(err);
       
   325 			childProcess.Close();
       
   326 			User::Leave(err);
       
   327 			}
       
   328 		}
       
   329 
       
   330 	if (iWait)
       
   331 		{
       
   332 		Printf(_L("Process is created but not yet resumed. Press a key to continue...\r\n"));
       
   333 		Stdin().ReadKey();
       
   334 		}
       
   335 
       
   336 	TRequestStatus stat;
       
   337 	childProcess.Run(stat);
       
   338 	User::WaitForRequest(stat);
       
   339 	TInt err = stat.Int();
       
   340 	childProcess.Close();
       
   341 	User::LeaveIfError(err); // This gets translated to our exe's return code I hope
       
   342 	}
       
   343 
       
   344 const TDesC& CCmdSudo::Name() const
       
   345 	{
       
   346 	_LIT(KName, "sudo");
       
   347 	return KName;
       
   348 	}
       
   349 
       
   350 void CCmdSudo::ArgumentsL(RCommandArgumentList& aArguments)
       
   351 	{
       
   352 	aArguments.AppendStringL(iCmd, _L("exe-name"));
       
   353 	aArguments.AppendStringL(iArgs, _L("arguments"));
       
   354 	}
       
   355 
       
   356 void CCmdSudo::OptionsL(RCommandOptionList& aOptions)
       
   357 	{
       
   358 	aOptions.AppendStringL(iAdd, _L("add-cap"));
       
   359 	aOptions.AppendStringL(iRemove, _L("remove-cap"));
       
   360 	aOptions.AppendUintL(iSid, _L("sid"));
       
   361 	aOptions.AppendUintL(iVid, _L("vid"));
       
   362 	aOptions.AppendUintL(iHeapMin, _L("heap-min"));
       
   363 	aOptions.AppendUintL(iHeapMax, _L("heap-max"));
       
   364 	aOptions.AppendUintL(iStackSize, _L("stack-size"));
       
   365 	aOptions.AppendIntL(iProcessPriority, _L("process-priority"));
       
   366 	aOptions.AppendBoolL(iKeep, _L("keep"));
       
   367 	aOptions.AppendBoolL(iChangeBinaryOnDisk, _L("disk"));
       
   368 	aOptions.AppendBoolL(iWait, _L("wait"));
       
   369 	}
       
   370 
       
   371 void CCmdSudo::DeleteModifiedBinary(TAny* aSelf)
       
   372 	{
       
   373 	CCmdSudo* self = static_cast<CCmdSudo*>(aSelf);
       
   374 	self->DeleteModifiedBinary();
       
   375 	}
       
   376 
       
   377 void CCmdSudo::DeleteModifiedBinary()
       
   378 	{
       
   379 	if (iFileIsInCore)
       
   380 		{
       
   381 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
   382 		iMemAccess.FreeShadowMemory((TLinAddr)Fs().IsFileInRom(iPath), sizeof(TRomImageHeader));
       
   383 #endif
       
   384 		}
       
   385 	else
       
   386 		{
       
   387 		TInt err = Fs().Delete(iNewPath);
       
   388 		if (err && err != KErrNotFound && err != KErrPathNotFound) PrintError(err, _L("Couldn't delete file %S"), &iNewPath);
       
   389 		}
       
   390 	}
       
   391 
       
   392 EXE_BOILER_PLATE(CCmdSudo)
       
   393 
       
   394 TBool CCmdSudo::FileExists(const TDesC& aFileName)
       
   395 	{
       
   396 	TEntry entry;
       
   397 	return Fs().Entry(aFileName, entry) == KErrNone;
       
   398 	}
       
   399 
       
   400 void CCmdSudo::FixupExeInMemoryL(RProcess& aProcess)
       
   401 	{
       
   402 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
   403 	LoadMemoryAccessL();
       
   404 	TProcessProperties prop;
       
   405 	prop.iCapsToAdd = iCapsToAdd;
       
   406 	prop.iCapsToRemove = iCapsToRemove;
       
   407 	prop.iProcessPriority = iProcessPriority;
       
   408 	if (iOptions.IsPresent(&iSid))
       
   409 		{
       
   410 		prop.iSid = iSid;
       
   411 		}
       
   412 	if (iOptions.IsPresent(&iVid))
       
   413 		{
       
   414 		prop.iVid = iVid;
       
   415 		}
       
   416 	LeaveIfErr(iMemAccess.SetProcessProperties(aProcess, prop), _L("Couldn't set process properties using memoryaccess"));
       
   417 #else
       
   418 	(void)aProcess;
       
   419 	LeaveIfErr(KErrNotSupported, _L("Can't fixup process in memory without MemoryAccess, try the --disk option instead"));
       
   420 #endif
       
   421 	}
       
   422 
       
   423 void CCmdSudo::CalculateCaps()
       
   424 	{
       
   425 	_LIT(KAll, "All");
       
   426 	// Add caps
       
   427 	iCapsToAdd.SetEmpty();
       
   428 	for (TInt i = 0; i < iAdd.Count(); i++)
       
   429 		{
       
   430 		const TDesC& capName = *iAdd[i];
       
   431 		TCapability cap = CapabilityFromString(capName);
       
   432 		if (cap == ECapability_None)
       
   433 			{
       
   434 			if (capName.CompareF(KAll) == 0)
       
   435 				{
       
   436 				// The pseudo-cap 'All'
       
   437 				iCapsToAdd.SetAllSupported();
       
   438 				}
       
   439 			else
       
   440 				{
       
   441 				PrintWarning(_L("Couldn't understand capability name %S"), &capName);
       
   442 				}
       
   443 			}
       
   444 		else
       
   445 			{
       
   446 			iCapsToAdd.AddCapability(cap);
       
   447 			}
       
   448 		}
       
   449 	// Remove caps
       
   450 	iCapsToRemove.SetEmpty();
       
   451 	for (TInt i = 0; i < iRemove.Count(); i++)
       
   452 		{
       
   453 		const TDesC& capName = *iRemove[i];
       
   454 		TCapability cap = CapabilityFromString(capName);
       
   455 		if (cap == ECapability_None)
       
   456 			{
       
   457 			if (capName.CompareF(KAll) == 0)
       
   458 				{
       
   459 				// The pseudo-cap 'All'
       
   460 				iCapsToRemove.SetAllSupported();
       
   461 				}
       
   462 			else
       
   463 				{
       
   464 				PrintWarning(_L("Couldn't understand capability name %S"), &capName);
       
   465 				}
       
   466 			}
       
   467 		else
       
   468 			{
       
   469 			iCapsToRemove.AddCapability(cap);
       
   470 			}
       
   471 		}
       
   472 
       
   473 	TBool noOptions = (iAdd.Count() == 0) && (iRemove.Count() == 0) && !iOptions.IsPresent(&iSid) && !iOptions.IsPresent(&iVid) && (iHeapMin == 0) && (iHeapMax == 0) && (iStackSize == 0) && (iProcessPriority == 0);
       
   474 
       
   475 	if (noOptions)
       
   476 		{
       
   477 		// Default to All -TCB
       
   478 		iCapsToAdd.SetAllSupported();
       
   479 		iCapsToRemove.AddCapability(ECapabilityTCB);
       
   480 		}
       
   481 	}
       
   482 
       
   483 void CCmdSudo::FixupCoreExeLC()
       
   484 	{
       
   485 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
   486 	LoadMemoryAccessL();
       
   487 
       
   488 	const TRomImageHeader* imageHeader = (const TRomImageHeader*)FsL().IsFileInRom(iPath);
       
   489 	if (!imageHeader) LeaveIfErr(KErrNotFound, _L("In FixupCoreExeLC but IsFileInRom returned null??"));
       
   490 
       
   491 	SCapabilitySet caps = imageHeader->iS.iCaps;
       
   492 	for (TInt i = 0; i < ECapability_Limit; i++)
       
   493 		{
       
   494 		TCapability cap = (TCapability)i;
       
   495 		if (iCapsToAdd.HasCapability(cap)) caps.AddCapability(cap);
       
   496 		if (iCapsToRemove.HasCapability(cap)) reinterpret_cast<TCapabilitySet*>(&caps)->RemoveCapability(cap);
       
   497 		}
       
   498 	TPckg<SCapabilitySet> pkg(caps);
       
   499 	LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iS.iCaps, pkg), _L("Couldn't write shadow memory for caps"));
       
   500 
       
   501 	if (iOptions.IsPresent(&iSid))
       
   502 		{
       
   503 		TPckg<TUint> pkg(iSid);
       
   504 		LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iS.iSecureId, pkg), _L("Couldn't write shadow memory for sid"));
       
   505 		}
       
   506 	if (iOptions.IsPresent(&iVid))
       
   507 		{
       
   508 		TPckg<TUint> pkg(iVid);
       
   509 		LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iS.iVendorId, pkg), _L("Couldn't write shadow memory for sid"));
       
   510 		}
       
   511 	if (iHeapMin)
       
   512 		{
       
   513 		TPckg<TUint> pkg(iHeapMin);
       
   514 		LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iHeapSizeMin, pkg), _L("Couldn't write shadow memory for iHeapSizeMin"));
       
   515 		}
       
   516 	if (iHeapMax)
       
   517 		{
       
   518 		TPckg<TUint> pkg(iHeapMax);
       
   519 		LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iHeapSizeMax, pkg), _L("Couldn't write shadow memory for iHeapSizeMax"));
       
   520 		}
       
   521 	if (iStackSize)
       
   522 		{
       
   523 		TPckg<TUint> pkg(iStackSize);
       
   524 		LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iStackSize, pkg), _L("Couldn't write shadow memory for iStackSize"));
       
   525 		}
       
   526 	if (iProcessPriority)
       
   527 		{
       
   528 		TPckg<TUint> pkg(iProcessPriority);
       
   529 		LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iPriority, pkg), _L("Couldn't write shadow memory for iProcessPriority"));
       
   530 		}
       
   531 
       
   532 	// DeleteModifiedBinary does the right thing in the case of shadowing
       
   533 	CleanupStack::PushL(TCleanupItem(&CCmdSudo::DeleteModifiedBinary, this));
       
   534 #else
       
   535 	LeaveIfErr(KErrNotSupported, _L("Can't fixup an exe in Core image without memoryaccess"));
       
   536 #endif
       
   537 	}