|
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 } |