|
1 // Copyright (c) 1995-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 "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // f32\sfile\sf_ldr.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "sf_std.h" |
|
19 #include <f32image.h> |
|
20 #include "sf_image.h" |
|
21 #include "sf_cache.h" |
|
22 #include "sf_ldr.h" |
|
23 #include <e32uid.h> |
|
24 #include <hal.h> |
|
25 |
|
26 |
|
27 #ifdef _DEBUG |
|
28 #define IF_DEBUG(x) x |
|
29 TInt KernHeapFailCount=0; |
|
30 TInt LdrHeapFailCount=0; |
|
31 TInt HeapFailActive=0; |
|
32 void SetupHeapFail(const RMessage2& aMsg); |
|
33 void EndHeapFailCheck(TInt); |
|
34 TInt RFsFailCount=0; |
|
35 TInt RFsErrorCode=0; |
|
36 TBool RFsFailActive=0; |
|
37 void SetupRFsFail(const RMessage2& aMsg); |
|
38 void EndRFsFailCheck(TInt); |
|
39 TRequestStatus ProcessDestructStat; |
|
40 TRequestStatus* ProcessDestructStatPtr=0; |
|
41 TBool ProcessCreated=EFalse; |
|
42 #else |
|
43 #define IF_DEBUG(x) |
|
44 #endif |
|
45 TInt DoLoaderDebugFunction(const RMessage2& aMsg); |
|
46 |
|
47 |
|
48 //#define __TRACE_LOADER_HEAP__ |
|
49 |
|
50 class RLoaderFs : public RFs |
|
51 { |
|
52 public: |
|
53 inline TInt SendReceive(TInt aFunction, const TIpcArgs& aArgs) const |
|
54 { return RSessionBase::SendReceive(aFunction, aArgs); } |
|
55 }; |
|
56 |
|
57 static TInt CheckLibraryHash(RLdrReq& aReq); |
|
58 const TInt KPriorityVeryHigh=14641; |
|
59 |
|
60 GLDEF_D RFs gTheLoaderFs; |
|
61 GLDEF_D TAny* gExeCodeSeg; |
|
62 GLDEF_D TUint32 gExeAttr; |
|
63 GLDEF_D TAny* gKernelCodeSeg; |
|
64 GLDEF_D TUint32 gKernelAttr; |
|
65 GLDEF_D SSecurityInfo gKernelSecInfo; |
|
66 GLDEF_D TBool gExecutesInSupervisorMode; |
|
67 GLDEF_D TAny* gFileServerCodeSeg; |
|
68 GLDEF_D TUint32 gFileServerAttr; |
|
69 GLDEF_D SSecurityInfo gFileServerSecInfo; |
|
70 GLDEF_D CActiveReaper* gActiveReaper=NULL; |
|
71 |
|
72 CSlottedChunkAllocator gFileDataAllocator; |
|
73 |
|
74 |
|
75 GLREF_D TCodePageUtils TheCodePage; |
|
76 |
|
77 |
|
78 _LIT(KDriveSystemRoot, "?:\\"); |
|
79 _LIT(KLoaderThreadName, "LoaderThread"); |
|
80 _LIT8(KFileExtensionExe,".EXE"); |
|
81 _LIT8(KFileExtensionDll,".DLL"); |
|
82 _LIT8(KFileExtensionLdd,".LDD"); |
|
83 _LIT8(KFileExtensionPdd,".PDD"); |
|
84 _LIT8(KFileExtensionFsy,".FSY"); |
|
85 _LIT8(KFileExtensionFxt,".FXT"); |
|
86 _LIT8(KFileExtensionPxt,".PXT"); |
|
87 _LIT8(KFileExtensionPxy,".PXY"); |
|
88 _LIT(KPathDel,"?:\\sys\\del\\"); |
|
89 const TInt KPathDelLength = 11; |
|
90 const TInt KExtensionLength=4; |
|
91 |
|
92 #if defined(__EPOC32__) && defined(__X86__) |
|
93 TInt UseFloppy; |
|
94 #endif |
|
95 |
|
96 /****************************************************************************** |
|
97 * Loader top level stuff |
|
98 ******************************************************************************/ |
|
99 |
|
100 TUint32 GetCodeSegAttr(TAny* aCodeSeg, SSecurityInfo* aS, TUint32* aVer) |
|
101 { |
|
102 TCodeSegCreateInfo info; |
|
103 E32Loader::CodeSegInfo(aCodeSeg, info); |
|
104 if (aS) |
|
105 *aS = info.iS; |
|
106 if (aVer) |
|
107 *aVer = info.iModuleVersion; |
|
108 return info.iAttr; |
|
109 } |
|
110 |
|
111 #ifdef __EPOC32__ |
|
112 extern void InitExecuteInSupervisorMode(); |
|
113 #endif |
|
114 |
|
115 _LIT(KNullThreadName,"EKern*Null"); |
|
116 void GetKernelInfo() |
|
117 { |
|
118 TFindThread ft(KNullThreadName); |
|
119 TFullName fn; |
|
120 TInt r = ft.Next(fn); |
|
121 if (r==KErrNone) |
|
122 { |
|
123 RThread null; |
|
124 r = null.Open(ft); |
|
125 if (r==KErrNone) |
|
126 { |
|
127 gKernelCodeSeg = E32Loader::ThreadProcessCodeSeg(null.Handle()); |
|
128 if (gKernelCodeSeg) |
|
129 { |
|
130 gKernelAttr = GetCodeSegAttr(gKernelCodeSeg, &gKernelSecInfo, NULL); |
|
131 __IF_DEBUG(Printf("gKernelCodeSeg=%08x", gKernelCodeSeg)); |
|
132 __IF_DEBUG(Printf("gKernelAttr=%08x", gKernelAttr)); |
|
133 } |
|
134 else |
|
135 r=KErrGeneral; |
|
136 null.Close(); |
|
137 } |
|
138 } |
|
139 if (r==KErrNone) |
|
140 { |
|
141 gFileServerCodeSeg = E32Loader::ThreadProcessCodeSeg(KCurrentThreadHandle); |
|
142 if (gFileServerCodeSeg) |
|
143 { |
|
144 gFileServerAttr = GetCodeSegAttr(gFileServerCodeSeg, &gFileServerSecInfo, NULL); |
|
145 __IF_DEBUG(Printf("gFileServerCodeSeg=%08x", gFileServerCodeSeg)); |
|
146 __IF_DEBUG(Printf("gFileServerAttr=%08x", gFileServerAttr)); |
|
147 } |
|
148 else |
|
149 r=KErrGeneral; |
|
150 } |
|
151 |
|
152 #ifdef __EPOC32__ |
|
153 InitExecuteInSupervisorMode(); |
|
154 #else |
|
155 // When running on the emulator the loader can access all memory so effectively it is |
|
156 // running in supervisor mode. |
|
157 gExecutesInSupervisorMode = ETrue; |
|
158 #endif |
|
159 |
|
160 __ASSERT_ALWAYS(r==KErrNone, Fault(ELdrGetKernelInfoFailed)); |
|
161 } |
|
162 |
|
163 |
|
164 #ifdef __TRACE_LOADER_HEAP__ |
|
165 void InstallHeapTracer(); |
|
166 #endif |
|
167 |
|
168 |
|
169 #ifdef __LAZY_DLL_UNLOAD |
|
170 const TInt KLoaderLazyDllDurationDefault=120; // 120 seconds default |
|
171 TInt KLoaderLazyDllDuration=KLoaderLazyDllDurationDefault; |
|
172 CLazyUnloadTimer* LazyUnloadTimer=NULL; |
|
173 |
|
174 void CLazyUnloadTimer::New() |
|
175 // |
|
176 // Create a new CLazyUnloadTimer. |
|
177 // |
|
178 { |
|
179 |
|
180 CLazyUnloadTimer* lazyUnloadTimer=new CLazyUnloadTimer; |
|
181 if(lazyUnloadTimer) |
|
182 { |
|
183 TRAPD(err,lazyUnloadTimer->ConstructL()); |
|
184 if(err==KErrNone) |
|
185 { |
|
186 lazyUnloadTimer->Start(); |
|
187 } |
|
188 else |
|
189 { |
|
190 delete lazyUnloadTimer; |
|
191 } |
|
192 } |
|
193 } |
|
194 |
|
195 CLazyUnloadTimer::CLazyUnloadTimer() |
|
196 // |
|
197 // Constructor |
|
198 // |
|
199 : CTimer(EPriorityIdle) |
|
200 { |
|
201 Finish(); |
|
202 LazyUnloadTimer = this; |
|
203 if (KLoaderLazyDllDuration < 0) |
|
204 KLoaderLazyDllDuration = KLoaderLazyDllDurationDefault; |
|
205 } |
|
206 |
|
207 CLazyUnloadTimer::~CLazyUnloadTimer() |
|
208 { |
|
209 LazyUnloadTimer = NULL; |
|
210 } |
|
211 |
|
212 void CLazyUnloadTimer::Start() |
|
213 { |
|
214 E32Loader::CodeSegDeferDeletes(); |
|
215 CActiveScheduler::Add(this); |
|
216 TTimeIntervalMicroSeconds32 timeout=KLoaderLazyDllDuration*1000000; |
|
217 After(timeout); |
|
218 } |
|
219 |
|
220 void CLazyUnloadTimer::RunL() |
|
221 // |
|
222 // The timer has completed. |
|
223 // |
|
224 { |
|
225 E32Loader::CodeSegEndDeferDeletes(); |
|
226 delete this; |
|
227 } |
|
228 |
|
229 void CLazyUnloadTimer::Finish() |
|
230 { |
|
231 if(LazyUnloadTimer) |
|
232 { |
|
233 LazyUnloadTimer->Cancel(); |
|
234 LazyUnloadTimer->RunL(); |
|
235 } |
|
236 } |
|
237 |
|
238 #endif |
|
239 |
|
240 /* ReaperCleanupTimer - Used to clear /sys/del/ shortly after boot. */ |
|
241 |
|
242 const TInt KLoaderReaperCleanupTimeDefault=60; // 60 seconds default |
|
243 TInt KLoaderReaperCleanupTime=KLoaderReaperCleanupTimeDefault; |
|
244 CReaperCleanupTimer* CReaperCleanupTimer::Timer=NULL; |
|
245 |
|
246 TInt CReaperCleanupTimer::New() |
|
247 // |
|
248 // Create a new CReaperCleanupTimer. |
|
249 // |
|
250 { |
|
251 if (Timer) |
|
252 return KErrInUse; |
|
253 |
|
254 CReaperCleanupTimer* timer=new CReaperCleanupTimer; |
|
255 if(timer) |
|
256 { |
|
257 TRAPD(err,Timer->ConstructL()); |
|
258 if(err==KErrNone) |
|
259 { |
|
260 Timer->Start(); |
|
261 return KErrNone; |
|
262 } |
|
263 else |
|
264 { |
|
265 delete Timer; |
|
266 return err; |
|
267 } |
|
268 } |
|
269 return KErrNoMemory; |
|
270 } |
|
271 |
|
272 CReaperCleanupTimer::CReaperCleanupTimer() |
|
273 : CTimer(EPriorityIdle) |
|
274 { |
|
275 Timer=this; |
|
276 } |
|
277 |
|
278 CReaperCleanupTimer::~CReaperCleanupTimer() |
|
279 { |
|
280 Timer = NULL; |
|
281 } |
|
282 |
|
283 void CReaperCleanupTimer::Start() |
|
284 { |
|
285 CActiveScheduler::Add(this); |
|
286 TTimeIntervalMicroSeconds32 timeout=KLoaderReaperCleanupTime*1000000; |
|
287 After(timeout); |
|
288 } |
|
289 |
|
290 void CReaperCleanupTimer::RunL() |
|
291 { |
|
292 if (gActiveReaper) |
|
293 gActiveReaper->InitDelDir(); |
|
294 delete this; |
|
295 } |
|
296 |
|
297 void CReaperCleanupTimer::Complete() |
|
298 { |
|
299 if(Timer) |
|
300 { |
|
301 Timer->Cancel(); |
|
302 Timer->RunL(); |
|
303 } |
|
304 } |
|
305 |
|
306 GLDEF_C TInt LoaderThread(TAny*) |
|
307 // |
|
308 // The loader thread. |
|
309 // |
|
310 { |
|
311 #ifdef __TRACE_LOADER_HEAP__ |
|
312 InstallHeapTracer(); |
|
313 #endif |
|
314 |
|
315 TInt r; |
|
316 __IF_DEBUG(Printf("LoaderThread")); |
|
317 User::SetCritical(User::ESystemCritical); |
|
318 GetKernelInfo(); |
|
319 |
|
320 CServerLoader* serverLoader; |
|
321 CActiveSchedulerLoader* scheduler; |
|
322 |
|
323 CTrapCleanup* cleanup=CTrapCleanup::New(); |
|
324 __ASSERT_ALWAYS(cleanup!=NULL, Fault(ELdrCleanupCreate)); |
|
325 scheduler=CActiveSchedulerLoader::New(); |
|
326 __ASSERT_ALWAYS(scheduler!=NULL, Fault(ELdrSchedulerCreate)); |
|
327 serverLoader=CServerLoader::New(); |
|
328 __ASSERT_ALWAYS(serverLoader!=NULL, Fault(ELdrServerCreate)); |
|
329 |
|
330 RThread::Rendezvous(KErrNone); |
|
331 r=gTheLoaderFs.Connect(); |
|
332 __ASSERT_ALWAYS(r==KErrNone, Fault(ELdrFsConnect)); |
|
333 TBuf<sizeof(KDriveSystemRoot)> driveSystemRoot(KDriveSystemRoot); |
|
334 driveSystemRoot[0] = (TUint8) RFs::GetSystemDriveChar(); |
|
335 r=gTheLoaderFs.SetSessionPath(driveSystemRoot); |
|
336 __ASSERT_ALWAYS(r==KErrNone, Fault(ELdrFsSetPath)); |
|
337 |
|
338 #ifdef __EPOC32__ |
|
339 InitializeFileNameCache(); |
|
340 |
|
341 r=gFileDataAllocator.Construct(); |
|
342 __ASSERT_ALWAYS(r==KErrNone, Fault(ELdrFileDataAllocInit)); |
|
343 #endif |
|
344 |
|
345 #ifdef __LAZY_DLL_UNLOAD |
|
346 CLazyUnloadTimer::New(); |
|
347 #endif |
|
348 |
|
349 gActiveReaper = CActiveReaper::New(); |
|
350 __ASSERT_ALWAYS(gActiveReaper!=NULL, Fault(ELdrReaperCreate)); |
|
351 |
|
352 r=CReaperCleanupTimer::New(); |
|
353 __ASSERT_ALWAYS(r==KErrNone, Fault(ELdrReaperCleanupTimerCreate)); |
|
354 |
|
355 CActiveSchedulerLoader::Start(); |
|
356 Fault(ELdrSchedulerStopped); |
|
357 return 0; |
|
358 } |
|
359 |
|
360 TInt InitLoader() |
|
361 { |
|
362 |
|
363 TRequestStatus lts; |
|
364 RThread loaderThread; |
|
365 RHeap* h = (RHeap*)&User::Allocator(); |
|
366 TInt maxsize = h->MaxLength(); // loader heap max size = file server heap max size |
|
367 TInt r=loaderThread.Create(KLoaderThreadName,LoaderThread,KLoaderStackSize,KHeapMinSize,maxsize,NULL); |
|
368 if (r!=KErrNone) |
|
369 { |
|
370 return r; |
|
371 } |
|
372 loaderThread.Rendezvous(lts); |
|
373 loaderThread.Resume(); |
|
374 User::WaitForRequest(lts); |
|
375 loaderThread.Close(); |
|
376 return lts.Int(); |
|
377 } |
|
378 |
|
379 TInt CompareVersions(TUint32 aL, TUint32 aR) |
|
380 { |
|
381 if (aL>aR) |
|
382 return 1; |
|
383 if (aL<aR) |
|
384 return -1; |
|
385 return 0; |
|
386 } |
|
387 |
|
388 TInt DetailedCompareVersions(TUint32 aCandidate, TUint32 aRequest) |
|
389 { |
|
390 if (aRequest == KModuleVersionNull) |
|
391 return EVersion_MinorBigger; |
|
392 if (aCandidate == KModuleVersionNull) |
|
393 return EVersion_MajorSmaller; |
|
394 TUint32 C = aCandidate >> 16; |
|
395 TUint32 c = aCandidate & 0x0000ffffu; |
|
396 TUint32 R = aRequest >> 16; |
|
397 TUint32 r = aRequest & 0x0000ffffu; |
|
398 if (C==R) |
|
399 { |
|
400 if (c>r) |
|
401 return EVersion_MinorBigger; |
|
402 if (c==r) |
|
403 return EVersion_Exact; |
|
404 return EVersion_MinorSmaller; |
|
405 } |
|
406 if (C>R) |
|
407 return EVersion_MajorBigger; |
|
408 return EVersion_MajorSmaller; |
|
409 } |
|
410 |
|
411 TInt DetailedCompareVersions(TUint32 aCandidate, TUint32 aRequest, TUint32 aCurrent, TBool aStrict) |
|
412 { |
|
413 TInt cvc = DetailedCompareVersions(aCandidate, aCurrent); |
|
414 if (aRequest == KModuleVersionWild) |
|
415 { |
|
416 return (cvc == EVersion_MinorBigger || cvc == EVersion_MajorBigger) ? EAction_Replace : EAction_Skip; |
|
417 } |
|
418 TInt candidate_state = DetailedCompareVersions(aCandidate, aRequest); |
|
419 if (aStrict) |
|
420 { |
|
421 if (candidate_state > EVersion_Exact) |
|
422 return EAction_Skip; // no match |
|
423 if (cvc == EVersion_MinorBigger) |
|
424 return EAction_Replace; // later minor version so take it |
|
425 return EAction_Skip; // same or earlier minor version |
|
426 } |
|
427 TInt current_state = DetailedCompareVersions(aCurrent, aRequest); |
|
428 if (candidate_state < current_state) |
|
429 { |
|
430 // better match |
|
431 if (candidate_state <= EVersion_Exact) |
|
432 return EAction_Replace; |
|
433 return (candidate_state == EVersion_MajorBigger) ? EAction_CheckImports : EAction_CheckLastImport; |
|
434 } |
|
435 if (candidate_state > current_state) |
|
436 return EAction_Skip; // worse match |
|
437 // match state same |
|
438 // skip if (i) state=exact |
|
439 // (ii) state=major smaller |
|
440 // replace if (i) state=minor bigger and candidate minor > current minor |
|
441 // (ii) state=minor smaller and candidate minor > current minor |
|
442 // (iii) state=major bigger, candidate major=current major and candidate minor > current minor |
|
443 // check if (i) state=major bigger and candidate major < current major |
|
444 switch (candidate_state) |
|
445 { |
|
446 case EVersion_MinorBigger: |
|
447 case EVersion_MinorSmaller: |
|
448 return (cvc == EVersion_MinorBigger) ? EAction_Replace : EAction_Skip; |
|
449 case EVersion_MajorBigger: |
|
450 if (cvc == EVersion_MinorBigger) |
|
451 return EAction_Replace; |
|
452 return (cvc == EVersion_MajorSmaller) ? EAction_CheckImports : EAction_Skip; |
|
453 default: |
|
454 return EAction_Skip; |
|
455 } |
|
456 } |
|
457 |
|
458 TFileNameInfo::TFileNameInfo() |
|
459 { |
|
460 memclr(this, sizeof(TFileNameInfo)); |
|
461 } |
|
462 |
|
463 TInt TFileNameInfo::Set(const TDesC8& aFileName, TUint aFlags) |
|
464 { |
|
465 __IF_DEBUG(Printf(">TFileNameInfo::Set %S %08x", &aFileName, aFlags)); |
|
466 iUid = 0; |
|
467 iVersion = 0; |
|
468 iPathPos = 0; |
|
469 iName = aFileName.Ptr(); |
|
470 iLen = aFileName.Length(); |
|
471 iExtPos = aFileName.LocateReverse('.'); |
|
472 if (iExtPos<0) |
|
473 iExtPos = iLen; |
|
474 TInt osq = aFileName.LocateReverse('['); |
|
475 TInt csq = aFileName.LocateReverse(']'); |
|
476 if (!(aFlags & EAllowUid) && (osq>=0 || csq>=0)) |
|
477 { |
|
478 __IF_DEBUG(Printf("<TFileNameInfo::Set BadName1")); |
|
479 return KErrBadName; |
|
480 } |
|
481 if (osq>=iExtPos || csq>=iExtPos) |
|
482 { |
|
483 __IF_DEBUG(Printf("<TFileNameInfo::Set BadName2")); |
|
484 return KErrBadName; |
|
485 } |
|
486 TInt p = iExtPos; |
|
487 if ((aFlags & EAllowUid) && p>=10 && iName[p-1]==']' && iName[p-10]=='[') |
|
488 { |
|
489 TPtrC8 uidstr(iName + p - 9, 8); |
|
490 TLex8 uidlex(uidstr); |
|
491 TUint32 uid = 0; |
|
492 TInt r = uidlex.Val(uid, EHex); |
|
493 if (r==KErrNone && uidlex.Eos()) |
|
494 iUid = uid, p -= 10; |
|
495 } |
|
496 iUidPos = p; |
|
497 TInt ob = aFileName.LocateReverse('{'); |
|
498 TInt cb = aFileName.LocateReverse('}'); |
|
499 if (ob>=iUidPos || cb>=iUidPos) |
|
500 { |
|
501 __IF_DEBUG(Printf("<TFileNameInfo::Set BadName3")); |
|
502 return KErrBadName; |
|
503 } |
|
504 if (ob>=0 && cb>=0 && p-1==cb) |
|
505 { |
|
506 TPtrC8 p8(iName, p); |
|
507 TInt d = p8.LocateReverse('.'); |
|
508 TPtrC8 verstr(iName+ob+1, p-ob-2); |
|
509 TLex8 verlex(verstr); |
|
510 if (ob==p-10 && d<ob) |
|
511 { |
|
512 TUint32 ver = 0; |
|
513 TInt r = verlex.Val(ver, EHex); |
|
514 if (r==KErrNone && verlex.Eos()) |
|
515 iVersion = ver, p = ob; |
|
516 } |
|
517 else if (d>ob && p-1>d && (aFlags & EAllowDecimalVersion)) |
|
518 { |
|
519 TUint32 maj = 0; |
|
520 TUint32 min = 0; |
|
521 TInt r = verlex.Val(maj, EDecimal); |
|
522 TUint c = (TUint)verlex.Get(); |
|
523 TInt r2 = verlex.Val(min, EDecimal); |
|
524 if (r==KErrNone && c=='.' && r2==KErrNone && verlex.Eos() && maj<32768 && min<32768) |
|
525 iVersion = (maj << 16) | min, p = ob; |
|
526 } |
|
527 } |
|
528 iVerPos = p; |
|
529 if (iLen>=2 && iName[1]==':') |
|
530 { |
|
531 TUint c = iName[0]; |
|
532 if (c!='?' || !(aFlags & EAllowPlaceholder)) |
|
533 { |
|
534 c |= 0x20; |
|
535 if (c<'a' || c>'z') |
|
536 { |
|
537 __IF_DEBUG(Printf("<TFileNameInfo::Set BadName4")); |
|
538 return KErrBadName; |
|
539 } |
|
540 } |
|
541 iPathPos = 2; |
|
542 } |
|
543 TPtrC8 pathp(iName+iPathPos, iVerPos-iPathPos); |
|
544 if (pathp.Locate('[')>=0 || pathp.Locate(']')>=0 || pathp.Locate('{')>=0 || pathp.Locate('}')>=0 || pathp.Locate(':')>=0) |
|
545 { |
|
546 __IF_DEBUG(Printf("<TFileNameInfo::Set BadName5")); |
|
547 return KErrBadName; |
|
548 } |
|
549 iBasePos = pathp.LocateReverse('\\') + 1 + iPathPos; |
|
550 __IF_DEBUG(Printf("<TFileNameInfo::Set OK")); |
|
551 __LDRTRACE(Dump()); |
|
552 return KErrNone; |
|
553 } |
|
554 |
|
555 void TFileNameInfo::GetName(TDes8& aName, TUint aFlags) const |
|
556 { |
|
557 if (aFlags & EIncludeDrive) |
|
558 aName.Append(Drive()); |
|
559 if (aFlags & EIncludePath) |
|
560 { |
|
561 if (PathLen() && iName[iPathPos]!='\\') |
|
562 aName.Append('\\'); |
|
563 aName.Append(Path()); |
|
564 } |
|
565 if (aFlags & EIncludeBase) |
|
566 aName.Append(Base()); |
|
567 if ((aFlags & EForceVer) || ((aFlags & EIncludeVer) && VerLen()) ) |
|
568 { |
|
569 aName.Append('{'); |
|
570 aName.AppendNumFixedWidth(iVersion, EHex, 8); |
|
571 aName.Append('}'); |
|
572 } |
|
573 if ((aFlags & EForceUid) || ((aFlags & EIncludeUid) && UidLen()) ) |
|
574 { |
|
575 aName.Append('['); |
|
576 aName.AppendNumFixedWidth(iUid, EHex, 8); |
|
577 aName.Append(']'); |
|
578 } |
|
579 if (aFlags & EIncludeExt) |
|
580 aName.Append(Ext()); |
|
581 } |
|
582 |
|
583 TInt OpenFile8(RFile& aFile, const TDesC8& aName) |
|
584 { |
|
585 TFileName fn; |
|
586 fn.Copy(aName); |
|
587 TInt r = aFile.Open(gTheLoaderFs, fn, EFileStream|EFileRead|EFileShareReadersOnly|EFileReadDirectIO); |
|
588 return r; |
|
589 } |
|
590 |
|
591 RLdrReq::RLdrReq() |
|
592 { |
|
593 memclr(&iFileName, sizeof(RLdrReq) - sizeof(TLdrInfo)); |
|
594 } |
|
595 |
|
596 void RLdrReq::Close() |
|
597 { |
|
598 delete iFileName; |
|
599 delete iCmd; |
|
600 delete iPath; |
|
601 iClientThread.Close(); |
|
602 iClientProcess.Close(); |
|
603 } |
|
604 |
|
605 void RLdrReq::Panic(TInt aPanic) |
|
606 { |
|
607 iMsg->Panic(KLitLoader,aPanic); |
|
608 } |
|
609 |
|
610 TInt CheckedCollapse(TDes8& aDest, const TDesC16& aSrc) |
|
611 { |
|
612 TInt rl = aSrc.Length(); |
|
613 aDest.SetLength(rl); |
|
614 TText8* d = (TText8*)aDest.Ptr(); |
|
615 const TText16* s = aSrc.Ptr(); |
|
616 const TText16* sE = s + rl; |
|
617 while (s<sE && *s>=0x20u && *s<0x7fu) |
|
618 *d++ = (TText8)*s++; |
|
619 return (s<sE) ? KErrBadName : KErrNone; |
|
620 } |
|
621 |
|
622 TInt RLoaderMsg::GetString(HBufC8*& aBuf, TInt aParam, TInt aMaxLen, TInt aHeadroom, TBool aReduce) const |
|
623 { |
|
624 aBuf=NULL; |
|
625 TInt l=GetDesLength(aParam); |
|
626 if (l<0) |
|
627 return l; |
|
628 if (l>aMaxLen) |
|
629 return KErrOverflow; |
|
630 aBuf=HBufC8::New((l+aHeadroom)*sizeof(TText)); |
|
631 if (!aBuf) |
|
632 return KErrNoMemory; |
|
633 TPtr8 bp8(aBuf->Des()); |
|
634 TPtr16 bp16((TText*)bp8.Ptr(), 0, bp8.MaxLength()/sizeof(TText)); |
|
635 TInt r = Read(aParam, bp16); |
|
636 if (r == KErrNone) |
|
637 { |
|
638 TInt rl = bp16.Length(); |
|
639 if (aReduce) |
|
640 r = CheckedCollapse(bp8, bp16); |
|
641 else |
|
642 bp8.SetLength(rl*sizeof(TText)); |
|
643 } |
|
644 if (r!=KErrNone) |
|
645 { |
|
646 delete aBuf; |
|
647 aBuf=NULL; |
|
648 } |
|
649 return r; |
|
650 } |
|
651 |
|
652 TInt RLoaderMsg::GetLdrInfo(TLdrInfo& aInfo) const |
|
653 { |
|
654 TPckg<TLdrInfo> infoPckg(aInfo); |
|
655 return Read(0, infoPckg); |
|
656 } |
|
657 |
|
658 TInt RLoaderMsg::UpdateLdrInfo(const TLdrInfo& aInfo) const |
|
659 { |
|
660 TPckgC<TLdrInfo> infoPckg(aInfo); |
|
661 return Write(0, infoPckg); |
|
662 } |
|
663 |
|
664 TInt RLdrReq::AddFileExtension(const TDesC8& aExt) |
|
665 { |
|
666 if (iFileName->LocateReverse('.')==KErrNotFound) |
|
667 { |
|
668 if (iFileName->Length()+aExt.Length()>KMaxFileName) |
|
669 return KErrBadName; |
|
670 iFileName->Des().Append(aExt); |
|
671 } |
|
672 TInt r = iFileNameInfo.Set(*iFileName, TFileNameInfo::EAllowDecimalVersion); |
|
673 if (r == KErrNone) |
|
674 { |
|
675 TInt l = iFileNameInfo.BaseLen() + iFileNameInfo.ExtLen(); |
|
676 if (l > KMaxProcessName) |
|
677 r = KErrBadName; |
|
678 } |
|
679 return r; |
|
680 } |
|
681 |
|
682 TInt CheckSubstDrive(TDes8& aDest, const TDesC8& aSrc, TBool aIsPathOnly) |
|
683 { |
|
684 TInt r = KErrNone; |
|
685 TInt l = aSrc.Length(); |
|
686 TInt mdl = aDest.MaxLength(); |
|
687 TInt pathStart = 0; |
|
688 if (l>=3 && aSrc[1]==':') |
|
689 { |
|
690 // drive letter specified... |
|
691 pathStart = 2; |
|
692 TInt drive; |
|
693 TDriveInfo dI; |
|
694 r = RFs::CharToDrive((TChar)aSrc[0], drive); |
|
695 if (r!=KErrNone) |
|
696 { |
|
697 return r; |
|
698 } |
|
699 r = gTheLoaderFs.Drive(dI, drive); |
|
700 if (r!=KErrNone) |
|
701 { |
|
702 return r; |
|
703 } |
|
704 if (dI.iDriveAtt & KDriveAttSubsted) |
|
705 { |
|
706 TPtr16 ptr16(aDest.Expand()); |
|
707 r = gTheLoaderFs.Subst(ptr16, drive); |
|
708 if (r!=KErrNone) |
|
709 { |
|
710 return r; |
|
711 } |
|
712 aDest.SetLength(ptr16.Length()*sizeof(TText)); |
|
713 aDest.Collapse(); |
|
714 TInt srcm = (aSrc[2]=='\\') ? 3 : 2; |
|
715 TPtrC8 rest(aSrc.Mid(srcm)); |
|
716 if (rest.Length() + aDest.Length() > mdl) |
|
717 return KErrBadName; |
|
718 aDest.Append(rest); |
|
719 r=1; |
|
720 } |
|
721 } |
|
722 |
|
723 if(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin)) |
|
724 return r; |
|
725 |
|
726 // make sure path starts with "\sys\bin\"... |
|
727 |
|
728 // get filename/path... |
|
729 TPtrC8 ptr; |
|
730 if(!r) |
|
731 ptr.Set(aSrc); |
|
732 else |
|
733 ptr.Set(aDest); |
|
734 |
|
735 // set pathStart to first character of path (after any initial '\') |
|
736 if(ptr.Length() && ptr[pathStart]=='\\') |
|
737 ++pathStart; // drop initial '\' |
|
738 |
|
739 // set pathEnd to first character after path (the final '\' if present) |
|
740 TInt pathEnd; |
|
741 if(aIsPathOnly) |
|
742 { |
|
743 pathEnd = ptr.Length(); |
|
744 if(pathEnd && ptr[pathEnd-1]==';') |
|
745 --pathEnd; // drop trailing ';' |
|
746 if(pathEnd && ptr[pathEnd-1]=='\\') |
|
747 --pathEnd; // drop trailing '\' |
|
748 } |
|
749 else |
|
750 { |
|
751 pathEnd = ptr.LocateReverse('\\'); |
|
752 if(pathEnd<0) |
|
753 return r; // no path, so end |
|
754 } |
|
755 |
|
756 // check if path starts with "sys\bin"... |
|
757 const TUint8* fn = ptr.Ptr(); |
|
758 _LIT8(KSysBin,"sys\\bin"); |
|
759 const TInt KSysBinLength = 7; |
|
760 if(pathStart+KSysBinLength <= pathEnd) |
|
761 if(KSysBin().CompareF(TPtrC8(fn+pathStart,KSysBinLength))==0) |
|
762 return r; // path already starts with "sys\bin", so end |
|
763 |
|
764 // replace path with "sys\bin"... |
|
765 TBuf8<KMaxFileName*sizeof(TText)> temp; |
|
766 temp.Append(TPtrC8(fn,pathStart)); // add bits before path |
|
767 temp.Append(KSysBin); // add "sys\bin" |
|
768 TInt rootLen = ptr.Length()-pathEnd; |
|
769 if(temp.Length()+rootLen>temp.MaxLength()) |
|
770 return KErrBadName; // would overflow |
|
771 temp.Append(TPtrC8(fn+pathEnd,rootLen)); // add bits after path |
|
772 |
|
773 // return modified string... |
|
774 aDest = temp; |
|
775 return 1; |
|
776 } |
|
777 |
|
778 |
|
779 TInt RLdrReq::CheckForSubstDriveInName() |
|
780 { |
|
781 TBuf8<KMaxFileName*sizeof(TText)> temp; |
|
782 TInt r = CheckSubstDrive(temp, *iFileName, EFalse); |
|
783 if (r<0) |
|
784 { |
|
785 return r; |
|
786 } |
|
787 if (r>0) |
|
788 { |
|
789 TInt l=temp.Length(); |
|
790 HBufC8* p = HBufC8::New(l+KExtensionLength); |
|
791 if (!p) |
|
792 return KErrNoMemory; |
|
793 TPtr8 bp8(p->Des()); |
|
794 bp8 = temp; |
|
795 delete iFileName; |
|
796 iFileName = p; |
|
797 r = KErrNone; |
|
798 } |
|
799 return r; |
|
800 } |
|
801 |
|
802 |
|
803 TInt RLdrReq::CheckForSubstDrivesInPath() |
|
804 { |
|
805 if (!iPath) |
|
806 return KErrNone; |
|
807 TBuf8<(KMaxFileName+1)*sizeof(TText)> temp; |
|
808 TInt ppos = 0; |
|
809 TInt plen = iPath->Length(); |
|
810 HBufC8* newpath = NULL; |
|
811 while (ppos < plen) |
|
812 { |
|
813 TPtrC8 rmn(iPath->Mid(ppos)); |
|
814 TInt term = rmn.Locate(';'); |
|
815 TInt pel = (term<0) ? rmn.Length() : term+1; |
|
816 TPtrC8 path_element(iPath->Mid(ppos, pel)); |
|
817 ppos += pel; |
|
818 temp.Zero(); |
|
819 TInt r = CheckSubstDrive(temp, path_element, ETrue); |
|
820 if (r<0) |
|
821 { |
|
822 delete newpath; |
|
823 return r; |
|
824 } |
|
825 else if (r>0 || newpath) |
|
826 { |
|
827 if(!newpath) |
|
828 { |
|
829 // initialise 'newpath' to contain everything in path before the element just processed... |
|
830 newpath = iPath->Left(ppos-pel).Alloc(); |
|
831 if(!newpath) |
|
832 return KErrNoMemory; |
|
833 } |
|
834 // grow 'newpath'... |
|
835 TInt xl = (r>0) ? temp.Length() : pel; |
|
836 HBufC8* np = newpath->ReAlloc(newpath->Length() + xl); |
|
837 if(!np) |
|
838 { |
|
839 delete newpath; |
|
840 return KErrNoMemory; |
|
841 } |
|
842 newpath = np; |
|
843 // append modified path element to the 'newpath'... |
|
844 newpath->Des().Append( (r>0) ? (const TDesC8&)temp : (const TDesC8&)path_element); |
|
845 } |
|
846 } |
|
847 if(newpath) |
|
848 { |
|
849 delete iPath; |
|
850 iPath = newpath; |
|
851 } |
|
852 return KErrNone; |
|
853 } |
|
854 |
|
855 #ifdef __VC32__ |
|
856 #pragma warning( disable : 4701 ) // disable warning C4701: local variable 'missingCaps' may be used without having been initialized |
|
857 #endif |
|
858 |
|
859 TInt RLdrReq::CheckSecInfo(const SSecurityInfo& aCandidate) const |
|
860 // |
|
861 // Check that the security info of a candidate loadee is sufficient |
|
862 // |
|
863 { |
|
864 if (iSecureId && iSecureId != aCandidate.iSecureId) |
|
865 return KErrPermissionDenied; |
|
866 |
|
867 SCapabilitySet missingCaps; |
|
868 TUint32 checkFail = 0; |
|
869 for (TInt i=0; i<SCapabilitySet::ENCapW; ++i) |
|
870 { |
|
871 TUint32 missing = iPlatSecCaps[i] & ~aCandidate.iCaps[i]; |
|
872 missingCaps[i] = missing; |
|
873 checkFail |= missing; |
|
874 } |
|
875 if(!checkFail) |
|
876 return KErrNone; |
|
877 // Failed check... |
|
878 if(iImporter) |
|
879 { |
|
880 #ifndef __REMOVE_PLATSEC_DIAGNOSTICS__ |
|
881 return PlatSec::LoaderCapabilityViolation(iImporter->iFileName,*iFileName,missingCaps); |
|
882 #else //__REMOVE_PLATSEC_DIAGNOSTICS__ |
|
883 return PlatSec::EmitDiagnostic(); |
|
884 #endif //!__REMOVE_PLATSEC_DIAGNOSTICS__ |
|
885 } |
|
886 |
|
887 #ifndef __REMOVE_PLATSEC_DIAGNOSTICS__ |
|
888 return PlatSec::LoaderCapabilityViolation(iClientProcess,*iFileName,missingCaps); |
|
889 #else //__REMOVE_PLATSEC_DIAGNOSTICS__ |
|
890 return PlatSec::EmitDiagnostic(); |
|
891 #endif //!__REMOVE_PLATSEC_DIAGNOSTICS__ |
|
892 } |
|
893 |
|
894 #ifdef __VC32__ |
|
895 #pragma warning( default : 4701 ) // enable warning C4701: local variable 'missingCaps' may be used without having been initialized |
|
896 #endif |
|
897 |
|
898 void CSessionLoader::ServiceL(const RMessage2& aMessage) |
|
899 // |
|
900 // Handle messages for this server. |
|
901 // |
|
902 { |
|
903 const RLoaderMsg& msg = (const RLoaderMsg&)aMessage; |
|
904 TLoaderMsg mid=(TLoaderMsg)msg.Function(); |
|
905 __IF_DEBUG(Printf("Loader: RX msg %d", mid)); |
|
906 if (mid<1 || mid>=EMaxLoaderMsg) |
|
907 { |
|
908 aMessage.Complete(KErrNotSupported); |
|
909 return; |
|
910 } |
|
911 #ifdef __EPOC32__ |
|
912 #ifdef __X86__ |
|
913 UseFloppy = -1; |
|
914 #endif |
|
915 TInt r=CheckLoaderCacheInit(); |
|
916 if (r!=KErrNone) |
|
917 { |
|
918 aMessage.Complete(r); |
|
919 return; |
|
920 } |
|
921 #else |
|
922 TInt r = KErrNone; |
|
923 #endif |
|
924 #ifdef _DEBUG |
|
925 if(mid==ELoaderDebugFunction) |
|
926 { |
|
927 msg.Complete(DoLoaderDebugFunction(msg)); |
|
928 return; |
|
929 } |
|
930 #endif |
|
931 if(mid==ELoaderCancelLazyDllUnload) |
|
932 { |
|
933 #ifdef __LAZY_DLL_UNLOAD |
|
934 CLazyUnloadTimer::Finish(); |
|
935 #endif |
|
936 msg.Complete(KErrNone); |
|
937 return; |
|
938 } |
|
939 #ifdef _DEBUG |
|
940 gTheLoaderFs.ResourceCountMarkStart(); |
|
941 #endif |
|
942 if(mid==EGetInfoFromHeader) |
|
943 { |
|
944 r=GetInfoFromHeader(msg); |
|
945 #ifdef _DEBUG |
|
946 gTheLoaderFs.ResourceCountMarkEnd(); |
|
947 #endif |
|
948 msg.Complete(r); |
|
949 return; |
|
950 } |
|
951 |
|
952 if (mid == ELdrDelete) |
|
953 { |
|
954 // TCB and AllFiles are sufficient to ensure that write |
|
955 // access to any part of the file system without having to |
|
956 // check substitutions and access rights here. |
|
957 if (! aMessage.HasCapability(ECapabilityTCB, ECapabilityAllFiles, __PLATSEC_DIAGNOSTIC_STRING("ELdrDelete,TCB+AllFiles"))) |
|
958 { |
|
959 r = KErrPermissionDenied; |
|
960 } |
|
961 // because this function is a general-purpose replacement for RFs::Delete, |
|
962 // it doesn't use the transformed filename which would be put into ldrReq.iFileName, |
|
963 // but the literal filename which was supplied, provided it is absolute. |
|
964 else |
|
965 { |
|
966 TInt filenameLength = msg.GetDesLength(1); |
|
967 if(filenameLength<0) |
|
968 r = filenameLength; |
|
969 else |
|
970 { |
|
971 HBufC* fnSupply = HBufC::New(filenameLength); |
|
972 if(!fnSupply) |
|
973 r = KErrNoMemory; |
|
974 else |
|
975 { |
|
976 TPtr buf = fnSupply->Des(); |
|
977 if ((r=msg.Read( 1, buf)) == KErrNone) |
|
978 { |
|
979 _LIT(KAbsolutePathPattern,"?:\\*"); |
|
980 if (fnSupply->MatchF(KAbsolutePathPattern) != 0) |
|
981 r = KErrBadName; |
|
982 else |
|
983 { |
|
984 _LIT(KSysBin,"?:\\sys\\bin\\*"); |
|
985 if (fnSupply->MatchF(KSysBin) == 0) |
|
986 r = DeleteExecutable(*fnSupply); |
|
987 else |
|
988 r = gTheLoaderFs.Delete(*fnSupply); |
|
989 } |
|
990 } |
|
991 delete fnSupply; |
|
992 } |
|
993 } |
|
994 } // endif !aMessage.HasCapability |
|
995 |
|
996 #ifdef _DEBUG |
|
997 gTheLoaderFs.ResourceCountMarkEnd(); |
|
998 #endif |
|
999 msg.Complete(r); |
|
1000 return; |
|
1001 } |
|
1002 |
|
1003 RLdrReq ldrReq; |
|
1004 ldrReq.iMsg=&msg; |
|
1005 r=msg.GetString(ldrReq.iFileName, 1, KMaxFileName, KExtensionLength, ETrue); |
|
1006 __IF_DEBUG(Printf("Filename: %S", ldrReq.iFileName)); |
|
1007 if (r==KErrNone) |
|
1008 r = ldrReq.CheckForSubstDriveInName(); |
|
1009 __IF_DEBUG(Printf("Post-subst filename: %S", ldrReq.iFileName)); |
|
1010 if (r!=KErrNone) |
|
1011 goto error; |
|
1012 |
|
1013 ldrReq.iPlatSecCaps = AllCapabilities; // secure default, require loaded executable to have all capabilities |
|
1014 |
|
1015 #ifndef __EPOC32__ |
|
1016 // On the emulator, temporarily disable CPU speed restrictions whilst loading executables... |
|
1017 TInt cpu; |
|
1018 HAL::Get(HALData::ECPUSpeed, cpu); |
|
1019 HAL::Set(HALData::ECPUSpeed, 0); |
|
1020 #endif |
|
1021 IF_DEBUG(SetupRFsFail(msg)); |
|
1022 IF_DEBUG(SetupHeapFail(msg)); |
|
1023 switch (mid) |
|
1024 { |
|
1025 //__DATA_CAGING__ |
|
1026 case EGetInfo: |
|
1027 { |
|
1028 r=ldrReq.AddFileExtension(KFileExtensionDll); |
|
1029 if (r==KErrNone) |
|
1030 r=msg.GetLdrInfo(ldrReq); |
|
1031 if (r==KErrNone) |
|
1032 r=GetModuleInfo(ldrReq); |
|
1033 break; |
|
1034 } |
|
1035 //__DATA_CAGING__ |
|
1036 case ELoadProcess: |
|
1037 { |
|
1038 r=ldrReq.AddFileExtension(KFileExtensionExe); |
|
1039 if (r==KErrNone) |
|
1040 r=msg.GetString(ldrReq.iCmd, 2, KMaxTInt, 0, EFalse); |
|
1041 if (r==KErrNone) |
|
1042 r=msg.GetLdrInfo(ldrReq); |
|
1043 if (r==KErrNone) |
|
1044 { |
|
1045 static const SCapabilitySet NoCapabilities={{0}}; |
|
1046 ldrReq.iPlatSecCaps=NoCapabilities; // We don't care what EXEs capabilities are |
|
1047 r=LoadProcess(ldrReq); |
|
1048 } |
|
1049 break; |
|
1050 } |
|
1051 case ELoadLibrary: |
|
1052 { |
|
1053 r=E32Loader::CheckClientState(msg.Handle()); |
|
1054 if (r!=KErrNone) |
|
1055 ldrReq.Panic(ELoadLibraryWithoutDllLock); |
|
1056 else |
|
1057 r=ldrReq.AddFileExtension(KFileExtensionDll); |
|
1058 if (r==KErrNone) |
|
1059 r=msg.GetString(ldrReq.iPath, 2, KMaxPath, 0, ETrue); |
|
1060 if (ldrReq.iPath) |
|
1061 { |
|
1062 __IF_DEBUG(Printf("Path: %S", ldrReq.iPath)); |
|
1063 } |
|
1064 if (r==KErrNone) |
|
1065 r = ldrReq.CheckForSubstDrivesInPath(); |
|
1066 if (ldrReq.iPath) |
|
1067 { |
|
1068 __IF_DEBUG(Printf("Post-subst Path: %S", ldrReq.iPath)); |
|
1069 } |
|
1070 if (r==KErrNone) |
|
1071 r=msg.GetLdrInfo(ldrReq); |
|
1072 if (r==KErrNone) |
|
1073 r=LoadLibrary(ldrReq); |
|
1074 break; |
|
1075 } |
|
1076 |
|
1077 case ECheckLibraryHash: |
|
1078 |
|
1079 r = ldrReq.AddFileExtension(KFileExtensionDll); |
|
1080 if (r==KErrNone) |
|
1081 { |
|
1082 r = CheckLibraryHash(ldrReq); |
|
1083 } |
|
1084 break; |
|
1085 |
|
1086 case ELoadLogicalDevice: |
|
1087 { |
|
1088 r=ldrReq.AddFileExtension(KFileExtensionLdd); |
|
1089 if (r==KErrNone) |
|
1090 r=LoadDeviceDriver(ldrReq, 0); |
|
1091 break; |
|
1092 } |
|
1093 case ELoadPhysicalDevice: |
|
1094 { |
|
1095 r=ldrReq.AddFileExtension(KFileExtensionPdd); |
|
1096 if (r==KErrNone) |
|
1097 r=LoadDeviceDriver(ldrReq, 1); |
|
1098 break; |
|
1099 } |
|
1100 case ELoadLocale: |
|
1101 { |
|
1102 r=ldrReq.AddFileExtension(KFileExtensionDll); |
|
1103 if (r==KErrNone) |
|
1104 { |
|
1105 ldrReq.iRequestedUids=TUidType(TUid::Uid(KDynamicLibraryUidValue),TUid::Uid(KLocaleDllUidValue)); |
|
1106 ldrReq.iOwnerType=EOwnerProcess; |
|
1107 ldrReq.iHandle=0; |
|
1108 ldrReq.iPlatSecCaps=AllCapabilities; |
|
1109 ldrReq.iMsg=NULL; // null msg -> client is self |
|
1110 TLibraryFunction functionList[KNumLocaleExports]; |
|
1111 r=LoadLocale(ldrReq, functionList); |
|
1112 if(r==KErrNone) |
|
1113 { |
|
1114 TInt size = KNumLocaleExports * sizeof(TLibraryFunction); |
|
1115 TPtr8 functionListBuf((TUint8*)&functionList[0], size, size); |
|
1116 TRAP(r, aMessage.WriteL(2, functionListBuf, 0)); |
|
1117 } |
|
1118 } |
|
1119 break; |
|
1120 } |
|
1121 case ELoadCodePage: |
|
1122 { |
|
1123 if (!KCapDiskAdmin.CheckPolicy(aMessage, __PLATSEC_DIAGNOSTIC_STRING("Loader : ELoadCodePage"))) |
|
1124 { |
|
1125 r = KErrPermissionDenied; |
|
1126 break; |
|
1127 } |
|
1128 r=ldrReq.AddFileExtension(KFileExtensionDll); |
|
1129 if (r==KErrNone) |
|
1130 { |
|
1131 ldrReq.iRequestedUids=TUidType(TUid::Uid(KDynamicLibraryUidValue),TUid::Uid(KLocaleDllUidValue)); |
|
1132 ldrReq.iOwnerType=EOwnerProcess; |
|
1133 ldrReq.iHandle=0; |
|
1134 ldrReq.iPlatSecCaps=gFileServerSecInfo.iCaps; |
|
1135 ldrReq.iMsg=NULL; // null msg -> client is self |
|
1136 r=LoadLibrary(ldrReq); |
|
1137 if (r==KErrNone) |
|
1138 { |
|
1139 // call file server to install code page dll |
|
1140 r = ((RLoaderFs*)&gTheLoaderFs)->SendReceive(EFsLoadCodePage, TIpcArgs(ldrReq.iHandle)); |
|
1141 } |
|
1142 } |
|
1143 if (r!=KErrNone) |
|
1144 { |
|
1145 RLibrary lib; |
|
1146 lib.SetHandle(ldrReq.iHandle); |
|
1147 lib.Close(); |
|
1148 } |
|
1149 break; |
|
1150 } |
|
1151 case ELoadFileSystem: |
|
1152 { |
|
1153 if (!KCapFsAddFileSystem.CheckPolicy(aMessage, __PLATSEC_DIAGNOSTIC_STRING("Add File System"))) |
|
1154 { |
|
1155 r = KErrPermissionDenied; |
|
1156 break; |
|
1157 } |
|
1158 r=ldrReq.AddFileExtension(KFileExtensionFsy); |
|
1159 if (r==KErrNone) |
|
1160 { |
|
1161 ldrReq.iRequestedUids=TUidType(TUid::Uid(KDynamicLibraryUidValue),TUid::Uid(KFileSystemUidValue)); |
|
1162 ldrReq.iOwnerType=EOwnerProcess; |
|
1163 ldrReq.iHandle=0; |
|
1164 ldrReq.iPlatSecCaps=gFileServerSecInfo.iCaps; |
|
1165 ldrReq.iMsg=NULL; // null msg -> client is self |
|
1166 r=LoadLibrary(ldrReq); |
|
1167 if (r==KErrNone) |
|
1168 { |
|
1169 // call file server to install file system |
|
1170 r = ((RLoaderFs*)&gTheLoaderFs)->SendReceive(EFsAddFileSystem, TIpcArgs(ldrReq.iHandle)); |
|
1171 } |
|
1172 } |
|
1173 if (r!=KErrNone) |
|
1174 { |
|
1175 RLibrary lib; |
|
1176 lib.SetHandle(ldrReq.iHandle); |
|
1177 lib.Close(); |
|
1178 } |
|
1179 break; |
|
1180 } |
|
1181 case ELoadFSExtension: |
|
1182 { |
|
1183 if (!KCapFsAddExtension.CheckPolicy(aMessage, __PLATSEC_DIAGNOSTIC_STRING("Add File Extension"))) |
|
1184 { |
|
1185 r = KErrPermissionDenied; |
|
1186 break; |
|
1187 } |
|
1188 r=ldrReq.AddFileExtension(KFileExtensionFxt); |
|
1189 if (r==KErrNone) |
|
1190 { |
|
1191 ldrReq.iRequestedUids=TUidType(TUid::Uid(KDynamicLibraryUidValue),TUid::Uid(KFileSystemUidValue)); |
|
1192 ldrReq.iOwnerType=EOwnerProcess; |
|
1193 ldrReq.iHandle=0; |
|
1194 ldrReq.iPlatSecCaps=gFileServerSecInfo.iCaps; |
|
1195 ldrReq.iMsg=NULL; // null msg -> client is self |
|
1196 r=LoadLibrary(ldrReq); |
|
1197 if (r==KErrNone) |
|
1198 { |
|
1199 // call file server to install file system |
|
1200 r = ((RLoaderFs*)&gTheLoaderFs)->SendReceive(EFsAddExtension, TIpcArgs(ldrReq.iHandle)); |
|
1201 } |
|
1202 } |
|
1203 if (r!=KErrNone) |
|
1204 { |
|
1205 RLibrary lib; |
|
1206 lib.SetHandle(ldrReq.iHandle); |
|
1207 lib.Close(); |
|
1208 } |
|
1209 break; |
|
1210 } |
|
1211 case ELoadFSProxyDrive: |
|
1212 { |
|
1213 if (!KCapFsAddProxyDrive.CheckPolicy(aMessage, __PLATSEC_DIAGNOSTIC_STRING("Add Proxy Drive"))) |
|
1214 { |
|
1215 r = KErrPermissionDenied; |
|
1216 break; |
|
1217 } |
|
1218 r=ldrReq.AddFileExtension(KFileExtensionPxy); |
|
1219 if (r==KErrNone) |
|
1220 { |
|
1221 ldrReq.iRequestedUids=TUidType(TUid::Uid(KDynamicLibraryUidValue),TUid::Uid(KFileSystemUidValue)); |
|
1222 ldrReq.iOwnerType=EOwnerProcess; |
|
1223 ldrReq.iHandle=0; |
|
1224 ldrReq.iPlatSecCaps=gFileServerSecInfo.iCaps; |
|
1225 ldrReq.iMsg=NULL; // null msg -> client is self |
|
1226 r=LoadLibrary(ldrReq); |
|
1227 if (r==KErrNone) |
|
1228 { |
|
1229 // call file server to install file system |
|
1230 r = ((RLoaderFs*)&gTheLoaderFs)->SendReceive(EFsAddProxyDrive, TIpcArgs(ldrReq.iHandle)); |
|
1231 } |
|
1232 } |
|
1233 if (r!=KErrNone) |
|
1234 { |
|
1235 RLibrary lib; |
|
1236 lib.SetHandle(ldrReq.iHandle); |
|
1237 lib.Close(); |
|
1238 } |
|
1239 break; |
|
1240 } |
|
1241 case ELoadFSPlugin: |
|
1242 { |
|
1243 r=ldrReq.AddFileExtension(KFileExtensionPxt); |
|
1244 if (r==KErrNone) |
|
1245 { |
|
1246 ldrReq.iRequestedUids=TUidType(TUid::Uid(KDynamicLibraryUidValue),TUid::Uid(KFileSystemUidValue)); |
|
1247 ldrReq.iOwnerType=EOwnerProcess; |
|
1248 ldrReq.iHandle=0; |
|
1249 ldrReq.iPlatSecCaps=gFileServerSecInfo.iCaps; |
|
1250 ldrReq.iMsg=NULL; // null msg -> client is self |
|
1251 r=LoadLibrary(ldrReq); |
|
1252 if (r==KErrNone) |
|
1253 { |
|
1254 // call file server to install file system |
|
1255 r = ((RLoaderFs*)&gTheLoaderFs)->SendReceive(EFsAddPlugin, TIpcArgs(ldrReq.iHandle)); |
|
1256 } |
|
1257 } |
|
1258 if (r!=KErrNone) |
|
1259 { |
|
1260 RLibrary lib; |
|
1261 lib.SetHandle(ldrReq.iHandle); |
|
1262 lib.Close(); |
|
1263 } |
|
1264 break; |
|
1265 } |
|
1266 |
|
1267 default: |
|
1268 r=KErrNotSupported; |
|
1269 break; |
|
1270 } |
|
1271 |
|
1272 ldrReq.Close(); |
|
1273 IF_DEBUG(EndRFsFailCheck(r)); |
|
1274 IF_DEBUG(EndHeapFailCheck(r)); |
|
1275 #ifndef __EPOC32__ |
|
1276 HAL::Set(HALData::ECPUSpeed, cpu); |
|
1277 #endif |
|
1278 error: |
|
1279 #ifdef _DEBUG |
|
1280 gTheLoaderFs.ResourceCountMarkEnd(); |
|
1281 #endif |
|
1282 if (!aMessage.IsNull()) |
|
1283 { |
|
1284 __IF_DEBUG(Printf("Loader: msg complete %d", r)); |
|
1285 aMessage.Complete(r); |
|
1286 } |
|
1287 } |
|
1288 |
|
1289 //----------------------------------------------------------------------------------- |
|
1290 #ifndef __WINS__ |
|
1291 /** |
|
1292 Helper function that reads a hash file from c:\\sys\\hash and compares it with the givem dll hash. |
|
1293 |
|
1294 @param aHashFile represents opened hash file in c:\\sys\\hash directory |
|
1295 @param aDllFileName full path to the dll file, which hash will be calculated and compared with aHashFile contents. |
|
1296 @leave on file operation error or if hashes differ. |
|
1297 */ |
|
1298 static void DoCheckHashL(RFile& aHashFile, const TDesC& aDllFileName) |
|
1299 { |
|
1300 TBuf8<SHA1_HASH> hashInstalled; //-- installed dll hash, from c:\\sys\\hash |
|
1301 User::LeaveIfError(aHashFile.Read(hashInstalled)); |
|
1302 |
|
1303 CSHA1* hasher=CSHA1::NewL(); |
|
1304 CleanupStack::PushL(hasher); |
|
1305 |
|
1306 RFile fileDll; |
|
1307 CleanupClosePushL(fileDll); |
|
1308 |
|
1309 //-- open dll file |
|
1310 User::LeaveIfError(fileDll.Open(gTheLoaderFs, aDllFileName, EFileRead|EFileReadDirectIO)); |
|
1311 |
|
1312 TInt fileSz; |
|
1313 User::LeaveIfError(fileDll.Size(fileSz)); |
|
1314 |
|
1315 //-- check if the file is on removable media |
|
1316 TInt drvNum; |
|
1317 TDriveInfo drvInfo; |
|
1318 User::LeaveIfError(fileDll.Drive(drvNum, drvInfo)); |
|
1319 if(!(drvInfo.iDriveAtt & KDriveAttRemovable)) |
|
1320 User::Leave(KErrNotSupported); |
|
1321 |
|
1322 TInt offset=0; |
|
1323 TInt readSize = KHashFileReadSize; |
|
1324 RBuf8 readBuf; |
|
1325 |
|
1326 CleanupClosePushL(readBuf); |
|
1327 readBuf.CreateMaxL(readSize); |
|
1328 |
|
1329 //-- calculate dll hash |
|
1330 do { |
|
1331 if((fileSz - offset) < readSize) |
|
1332 readSize = (fileSz - offset); |
|
1333 |
|
1334 User::LeaveIfError(fileDll.Read(offset, readBuf, readSize)); |
|
1335 hasher->Update(readBuf); |
|
1336 offset+=readSize; |
|
1337 } |
|
1338 while(offset < fileSz); |
|
1339 |
|
1340 TBuf8<SHA1_HASH> hashCalculated; //-- calculated dll hash |
|
1341 hashCalculated=hasher->Final(); |
|
1342 |
|
1343 //-- compare hashes |
|
1344 if(hashCalculated.Compare(hashInstalled) !=0) |
|
1345 User::Leave(KErrCorrupt); |
|
1346 |
|
1347 CleanupStack::PopAndDestroy(3); //hasher, fileDll, readBuf |
|
1348 } |
|
1349 #endif //__WINS__ |
|
1350 |
|
1351 //----------------------------------------------------------------------------------- |
|
1352 |
|
1353 /** |
|
1354 Check if specified dll hash exists in \\sys\\hash on system drive and optionally validate it. |
|
1355 |
|
1356 |
|
1357 @param aReq loader request parameters |
|
1358 |
|
1359 @return System-wide error code, see RLoader::CheckLibraryHash() description |
|
1360 @return KErrNotSupported for the emulator version, because loading dlls from the emulated removable media is not supported |
|
1361 */ |
|
1362 static TInt CheckLibraryHash(RLdrReq& aReq) |
|
1363 { |
|
1364 #ifdef __WINS__ |
|
1365 (void)aReq; |
|
1366 return KErrNotSupported; //-- loading dlls from removable media and dll hashing isn't supported for WINS |
|
1367 #else |
|
1368 |
|
1369 const TInt fNameLen=aReq.iFileName->Length(); |
|
1370 if(fNameLen <= 0 || fNameLen > KMaxFileName) |
|
1371 return KErrArgument; |
|
1372 |
|
1373 const TBool bValidateHash=aReq.iMsg->Int2(); |
|
1374 |
|
1375 //-- extract pure dll name |
|
1376 TInt posNameStart=aReq.iFileName->LocateReverse('\\'); |
|
1377 if(posNameStart <0) |
|
1378 posNameStart = 0; |
|
1379 else |
|
1380 posNameStart++; |
|
1381 |
|
1382 //-- compose hash file name \\sys\\hash\\xxx on system drive |
|
1383 TFileName hashFName; |
|
1384 hashFName.Copy(aReq.iFileName->Right(fNameLen-posNameStart)); |
|
1385 hashFName.Insert(0, KSysHash); |
|
1386 hashFName[0] = (TUint8) RFs::GetSystemDriveChar(); |
|
1387 |
|
1388 //-- try to locate hash file |
|
1389 TInt nRes=KErrNone; |
|
1390 RFile fileHash; |
|
1391 nRes = fileHash.Open(gTheLoaderFs, hashFName, EFileRead|EFileReadDirectIO); |
|
1392 |
|
1393 if(nRes != KErrNone) |
|
1394 { |
|
1395 nRes = KErrNotFound; //-- hash file couldn't be found |
|
1396 } |
|
1397 else if(bValidateHash) |
|
1398 {//-- request to validate the hash. |
|
1399 hashFName.Copy(aReq.iFileName->Left(fNameLen)); //-- expand file name to unicode |
|
1400 TRAP(nRes, DoCheckHashL(fileHash, hashFName)); |
|
1401 |
|
1402 if(nRes != KErrNone) |
|
1403 nRes=KErrCorrupt; |
|
1404 } |
|
1405 |
|
1406 fileHash.Close(); |
|
1407 |
|
1408 return nRes; |
|
1409 |
|
1410 #endif //__WINS__ |
|
1411 } |
|
1412 |
|
1413 // This safely deletes something that could be an executable (ie in /sys/bin) |
|
1414 // aName will be deleted either in, or sometime after this call |
|
1415 // (The descriptor and the file it represents) |
|
1416 TInt CSessionLoader::DeleteExecutable(const TDesC& aName) |
|
1417 { |
|
1418 __IF_DEBUG(Printf("DeleteExecutable %S", &aName)); |
|
1419 TInt r; |
|
1420 r = gTheLoaderFs.Delete(aName); |
|
1421 if (r!=KErrInUse) |
|
1422 { |
|
1423 return r; |
|
1424 } |
|
1425 RFile toDelete; |
|
1426 CReaperCleanupTimer::Complete(); |
|
1427 |
|
1428 HBufC* newName=NULL; |
|
1429 r = toDelete.Open(gTheLoaderFs,aName,EFileShareExclusive|EFileReadDirectIO); |
|
1430 if (r==KErrNone) |
|
1431 { |
|
1432 TInt64 startPos=0; |
|
1433 SBlockMapInfo blockmapInfo; |
|
1434 |
|
1435 // find drive number, and starting block |
|
1436 r = toDelete.BlockMap(blockmapInfo,startPos, 1, ETrue); |
|
1437 if (r == KErrCompletion) |
|
1438 { |
|
1439 TInt64 startBlock = blockmapInfo.iStartBlockAddress + |
|
1440 ((TBlockMapEntry *)(&(blockmapInfo.iMap[0])))->iStartBlock * |
|
1441 blockmapInfo.iBlockGranularity + |
|
1442 blockmapInfo.iBlockStartOffset; |
|
1443 TInt driveNumber = blockmapInfo.iLocalDriveNumber; |
|
1444 |
|
1445 newName = HBufC::New(KPathDelLength+2+16); // + 2 digits for drive and 16 for start block block |
|
1446 if(!newName) |
|
1447 r = KErrNoMemory; |
|
1448 else |
|
1449 { |
|
1450 // make unique name for file... |
|
1451 TPtr name = newName->Des(); |
|
1452 name.Copy(KPathDel); |
|
1453 name[0] = aName[0]; // copy drive letter |
|
1454 name.AppendNumFixedWidth(driveNumber, EHex, 2); |
|
1455 name.AppendNumFixedWidth(TUint32(startBlock>>32), EHex, 8); |
|
1456 name.AppendNumFixedWidth(TUint32(startBlock), EHex, 8); |
|
1457 |
|
1458 TLoaderDeletedList* tmpLink = new TLoaderDeletedList(); |
|
1459 if(tmpLink==NULL) |
|
1460 r = KErrNoMemory; |
|
1461 else |
|
1462 { |
|
1463 toDelete.Close(); |
|
1464 gTheLoaderFs.MkDirAll(*newName); // ignore error and let rename fail if path doesn't exists |
|
1465 r = gTheLoaderFs.Rename(aName, *newName); |
|
1466 __IF_DEBUG(Printf("DeleteExecutable rename to %S returns %d", &newName, r)); |
|
1467 if(r==KErrNone) |
|
1468 { |
|
1469 // add to pending deletion list |
|
1470 tmpLink->iStartBlock = startBlock; |
|
1471 tmpLink->iDriveNumber = driveNumber; |
|
1472 tmpLink->iFileName = newName; |
|
1473 gActiveReaper->AddDeleted(tmpLink); |
|
1474 return r; |
|
1475 } //endif rename |
|
1476 delete tmpLink; |
|
1477 } // alloc |
|
1478 delete newName; |
|
1479 } // alloc name |
|
1480 } //endif blockmap |
|
1481 else if (r == KErrNotSupported) |
|
1482 r = KErrInUse; |
|
1483 else if (r == KErrNone) |
|
1484 r = KErrGeneral; |
|
1485 toDelete.Close(); |
|
1486 } // endif open |
|
1487 return r; |
|
1488 } |
|
1489 |
|
1490 |
|
1491 GLDEF_C TInt LoadProcess(RLdrReq& aReq) |
|
1492 { |
|
1493 __LDRTRACE(aReq.Dump("LoadProcess:")); |
|
1494 TInt32* uid=(TInt32*)&aReq.iRequestedUids; |
|
1495 if (uid[0] && uid[0]!=KExecutableImageUidValue) |
|
1496 return KErrNotSupported; |
|
1497 uid[0]=KExecutableImageUidValue; |
|
1498 gExeCodeSeg=NULL; // new process doesn't load into another process |
|
1499 gExeAttr=0; |
|
1500 E32Image* e=new E32Image; |
|
1501 if (!e) |
|
1502 return KErrNoMemory; |
|
1503 e->iMain=e; |
|
1504 TInt r=e->LoadProcess(aReq); |
|
1505 if (r==KErrNone) |
|
1506 { |
|
1507 aReq.iHandle=e->iFinalHandle; |
|
1508 r=aReq.iMsg->UpdateLdrInfo(aReq); |
|
1509 if (r!=KErrNone) |
|
1510 aReq.Panic(KErrBadDescriptor); |
|
1511 } |
|
1512 if (r!=KErrNone && e->iProcessHandle) |
|
1513 { |
|
1514 RProcess p; |
|
1515 p.SetHandle(e->iProcessHandle); |
|
1516 p.Kill(0); |
|
1517 } |
|
1518 delete e; |
|
1519 return r; |
|
1520 } |
|
1521 |
|
1522 |
|
1523 |
|
1524 TInt LoadLibrary(RLdrReq& aReq) |
|
1525 { |
|
1526 __LDRTRACE(aReq.Dump("LoadLibrary:")); |
|
1527 TInt32* uid=(TInt32*)&aReq.iRequestedUids; |
|
1528 if (uid[0] && uid[0]!=KDynamicLibraryUidValue) |
|
1529 return KErrNotSupported; |
|
1530 uid[0]=KDynamicLibraryUidValue; |
|
1531 TInt r=KErrNone; |
|
1532 if (aReq.iMsg) |
|
1533 { |
|
1534 r = aReq.iMsg->Client(aReq.iClientThread); |
|
1535 if (r==KErrNone) |
|
1536 r = aReq.iClientThread.Process(aReq.iClientProcess); |
|
1537 if (r!=KErrNone) |
|
1538 { |
|
1539 return r; |
|
1540 } |
|
1541 } |
|
1542 else |
|
1543 { |
|
1544 aReq.iClientThread.SetHandle(KCurrentThreadHandle); |
|
1545 aReq.iClientProcess.SetHandle(KCurrentProcessHandle); |
|
1546 } |
|
1547 E32Loader::CodeSegDeferDeletes(); |
|
1548 gExeCodeSeg=E32Loader::ThreadProcessCodeSeg(aReq.iClientThread.Handle()); |
|
1549 SSecurityInfo si; |
|
1550 gExeAttr=GetCodeSegAttr(gExeCodeSeg, &si, NULL); |
|
1551 aReq.iPlatSecCaps=si.iCaps; |
|
1552 E32Loader::CodeSegEndDeferDeletes(); |
|
1553 E32Image* e=new E32Image; |
|
1554 if (!e) |
|
1555 return KErrNoMemory; |
|
1556 e->iMain=e; |
|
1557 e->iClientProcessHandle=aReq.iClientProcess.Handle(); |
|
1558 __IF_DEBUG(Printf("e->iClientProcessHandle = %08x", e->iClientProcessHandle)); |
|
1559 if (r==KErrNone) |
|
1560 r=e->LoadCodeSeg(aReq); |
|
1561 if (r==KErrNone) |
|
1562 { |
|
1563 TLibraryCreateInfo libInfo; |
|
1564 libInfo.iCodeSegHandle=e->iHandle; |
|
1565 libInfo.iClientHandle=aReq.iClientThread.Handle(); |
|
1566 libInfo.iLibraryHandle=0; |
|
1567 libInfo.iOwnerType=aReq.iOwnerType; |
|
1568 r=E32Loader::LibraryCreate(libInfo); |
|
1569 if (r==KErrNone) |
|
1570 { |
|
1571 aReq.iHandle=libInfo.iLibraryHandle; |
|
1572 if (aReq.iMsg) |
|
1573 { |
|
1574 r=aReq.iMsg->UpdateLdrInfo(aReq); |
|
1575 if (r!=KErrNone) |
|
1576 aReq.Panic(KErrBadDescriptor); |
|
1577 } |
|
1578 } |
|
1579 } |
|
1580 delete e; |
|
1581 return r; |
|
1582 } |
|
1583 |
|
1584 struct TFatUtilityFunctions; |
|
1585 |
|
1586 GLDEF_C TInt LoadLocale(RLdrReq& aReq, TLibraryFunction* aExportsList) |
|
1587 { |
|
1588 __LDRTRACE(aReq.Dump("LoadLocale:")); |
|
1589 TUint32* uid=(TUint32*)&aReq.iRequestedUids; |
|
1590 uid[2]=0; |
|
1591 gExeCodeSeg=NULL; |
|
1592 gExeAttr = gFileServerAttr; |
|
1593 E32Image* e=new E32Image; |
|
1594 if (!e) |
|
1595 return KErrNoMemory; |
|
1596 e->iMain=e; |
|
1597 e->iAttr=ECodeSegAttGlobal; |
|
1598 TInt r=e->LoadCodeSeg(aReq); |
|
1599 if (r==KErrNone) |
|
1600 { |
|
1601 r = E32Loader::LocaleExports(e->iHandle, aExportsList); |
|
1602 #ifdef SYMBIAN_DISTINCT_LOCALE_MODEL |
|
1603 _LIT8(KLocLan, "elocl_lan"); |
|
1604 _LIT8(KLoc, "elocl."); |
|
1605 if(aReq.iFileName->Find(KLocLan) != KErrNotFound) |
|
1606 { |
|
1607 TheCodePage.SetLocaleCodePage((TFatUtilityFunctions*)aExportsList[FnFatUtilityFunctionsV2]()); |
|
1608 } |
|
1609 if(aReq.iFileName->Find(KLoc) != KErrNotFound) |
|
1610 { |
|
1611 TheCodePage.SetLocaleCodePage((TFatUtilityFunctions*)aExportsList[FnFatUtilityFunctions]()); |
|
1612 } |
|
1613 #else |
|
1614 // The 'old' version of the locale DLL contained a set of code page conversion exports. |
|
1615 // This has now been superceeded by the use of a seperate code page DLL. |
|
1616 // - To ease migration both are currently supported. |
|
1617 // - If both locale and CP DLL functions are present, CP DLL's will take precedence |
|
1618 // - This functionality will eventually be deprecated. |
|
1619 TheCodePage.SetLocaleCodePage((TFatUtilityFunctions*)aExportsList[FnFatUtilityFunctions]()); |
|
1620 #endif |
|
1621 } |
|
1622 delete e; |
|
1623 return r; |
|
1624 } |
|
1625 |
|
1626 TInt LoadDeviceDriver(RLdrReq& aReq, TInt aDeviceType) |
|
1627 { |
|
1628 __IF_DEBUG(Printf("LoadDeviceDriver type %d", aDeviceType)); |
|
1629 __LDRTRACE(aReq.Dump("")); |
|
1630 TUint32* uid=(TUint32*)&aReq.iRequestedUids; |
|
1631 uid[0]=KDynamicLibraryUidValue; |
|
1632 uid[1]=aDeviceType ? KPhysicalDeviceDriverUidValue : KLogicalDeviceDriverUidValue; |
|
1633 uid[2]=0; |
|
1634 gExeCodeSeg=gKernelCodeSeg; |
|
1635 gExeAttr=gKernelAttr; |
|
1636 E32Image* e=new E32Image; |
|
1637 if (!e) |
|
1638 return KErrNoMemory; |
|
1639 e->iMain=e; |
|
1640 e->iAttr=ECodeSegAttKernel; |
|
1641 aReq.iOwnerType=EOwnerProcess; |
|
1642 aReq.iHandle=0; |
|
1643 aReq.iPlatSecCaps=gKernelSecInfo.iCaps; |
|
1644 TInt r=e->LoadCodeSeg(aReq); |
|
1645 if (r==KErrNone) |
|
1646 r=E32Loader::DeviceLoad(e->iHandle, aDeviceType); |
|
1647 delete e; |
|
1648 return r; |
|
1649 } |
|
1650 |
|
1651 CServerLoader* CServerLoader::New() |
|
1652 // |
|
1653 // Create a new CServerLoader. |
|
1654 // |
|
1655 { |
|
1656 CServerLoader* pS=new CServerLoader(EPriorityNormal); |
|
1657 if (pS==NULL) |
|
1658 return(NULL); |
|
1659 _LIT(KLoaderServerName,"!Loader"); |
|
1660 TInt r=pS->Start(KLoaderServerName); |
|
1661 if (r!=KErrNone) |
|
1662 return(NULL); |
|
1663 return(pS); |
|
1664 } |
|
1665 |
|
1666 CServerLoader::CServerLoader(TInt aPriority) |
|
1667 // |
|
1668 // Constructor. |
|
1669 // |
|
1670 : CServer2(aPriority) |
|
1671 { |
|
1672 } |
|
1673 |
|
1674 CSession2* CServerLoader::NewSessionL(const TVersion& aVersion, const RMessage2&) const |
|
1675 // |
|
1676 // Create a new client for this server. |
|
1677 // |
|
1678 { |
|
1679 |
|
1680 TVersion v(KLoaderMajorVersionNumber,KLoaderMinorVersionNumber,KF32BuildVersionNumber); |
|
1681 TBool r=User::QueryVersionSupported(v,aVersion); |
|
1682 if (!r) |
|
1683 User::Leave(KErrNotSupported); |
|
1684 return new (ELeave) CSessionLoader; |
|
1685 } |
|
1686 |
|
1687 TInt CServerLoader::RunError(TInt aError) |
|
1688 // |
|
1689 // Complete the request with the error code |
|
1690 // |
|
1691 { |
|
1692 Message().Complete(aError); |
|
1693 ReStart(); |
|
1694 return KErrNone; |
|
1695 } |
|
1696 |
|
1697 CActiveSchedulerLoader* CActiveSchedulerLoader::New() |
|
1698 // |
|
1699 // Create and install the active scheduler. |
|
1700 // |
|
1701 { |
|
1702 |
|
1703 CActiveSchedulerLoader* pA=new CActiveSchedulerLoader; |
|
1704 if (pA==NULL) |
|
1705 return(NULL); |
|
1706 CActiveScheduler::Install(pA); |
|
1707 return(pA); |
|
1708 } |
|
1709 |
|
1710 void CActiveSchedulerLoader::Error(TInt anError) const |
|
1711 // |
|
1712 // Called if any Run() method leaves. |
|
1713 // |
|
1714 { |
|
1715 _LIT(KPanicLoaderErr, "LOADER-ERR"); |
|
1716 User::Panic(KPanicLoaderErr,anError); |
|
1717 } |
|
1718 |
|
1719 /****************************************************************************** |
|
1720 * E32Image functions common to WINS and EPOC |
|
1721 ******************************************************************************/ |
|
1722 |
|
1723 TInt CheckUids(const TUidType& aUids, const TUidType& aRequestedUids) |
|
1724 { |
|
1725 const TUint32* uid=(const TUint32*)&aUids; |
|
1726 const TUint32* req=(const TUint32*)&aRequestedUids; |
|
1727 __IF_DEBUG(Printf("CheckUids %08x,%08x,%08x req %08x,%08x,%08x", uid[0],uid[1],uid[2], |
|
1728 req[0],req[1],req[2])); |
|
1729 return (CheckUid(uid[0],req[0]) && CheckUid(uid[1],req[1]) && CheckUid(uid[2],req[2])) |
|
1730 ? KErrNone : KErrNotSupported; |
|
1731 } |
|
1732 |
|
1733 E32Image::E32Image() |
|
1734 { |
|
1735 __IF_DEBUG(Printf("E32Image Constructor")); |
|
1736 Mem::FillZ(&iUids, sizeof(E32Image)-sizeof(iFileName)); |
|
1737 } |
|
1738 |
|
1739 E32Image::~E32Image() |
|
1740 { |
|
1741 |
|
1742 __IF_DEBUG(Printf("E32Image Destructor")); |
|
1743 Reset(); |
|
1744 } |
|
1745 |
|
1746 void E32Image::Reset() |
|
1747 { |
|
1748 __IF_DEBUG(Printf("E32Image::Reset")); |
|
1749 delete iHeader; |
|
1750 __IF_DEBUG(Printf("iHeader")); |
|
1751 |
|
1752 // demand paging fixup data |
|
1753 User::Free(iImportFixupTable); |
|
1754 __IF_DEBUG(Printf("iImportFixupTable")); |
|
1755 |
|
1756 // demand paging file data |
|
1757 __IF_DEBUG(Printf("iCodePageOffsets")); |
|
1758 delete[] iCodePageOffsets; |
|
1759 __IF_DEBUG(Printf("iCodeBlockMapEntries")); |
|
1760 User::Free(iCodeBlockMapEntries); |
|
1761 |
|
1762 __IF_DEBUG(Printf("iCodeRelocSection")); |
|
1763 User::Free(iCodeRelocTable); |
|
1764 __IF_DEBUG(Printf("iDataRelocSection")); |
|
1765 User::Free(iRestOfFileData); |
|
1766 __IF_DEBUG(Printf("iRestOfFileData")); |
|
1767 User::Free(iCurrentImportList); |
|
1768 __IF_DEBUG(Printf("iCurrentImportList")); |
|
1769 User::Free(iFixups); |
|
1770 __IF_DEBUG(Printf("iFixups")); |
|
1771 gFileDataAllocator.Free(iFileData); |
|
1772 iFileData = NULL; |
|
1773 __IF_DEBUG(Printf("iFileData")); |
|
1774 iFile.Close(); |
|
1775 __IF_DEBUG(Printf("iFile")); |
|
1776 User::Free(iCopyOfExportDir); |
|
1777 if (iProcessHandle) |
|
1778 { |
|
1779 RProcess p; |
|
1780 p.SetHandle(iProcessHandle); |
|
1781 p.Close(); |
|
1782 __IF_DEBUG(Printf("iProcessHandle")); |
|
1783 } |
|
1784 if (iCloseCodeSeg) |
|
1785 E32Loader::CodeSegClose(iCloseCodeSeg); |
|
1786 if (iMain==this) |
|
1787 E32Loader::CodeSegClose(NULL); |
|
1788 |
|
1789 // Unclamp file if load failed. Cannot handle error from RFs here. |
|
1790 __IF_DEBUG(Printf("iFileClamp,%ld,%ld", iFileClamp.iCookie[0], iFileClamp.iCookie[1])); |
|
1791 iFileClamp.Close(gTheLoaderFs); |
|
1792 |
|
1793 __IF_DEBUG(Printf("Reset done")); |
|
1794 } |
|
1795 |
|
1796 |
|
1797 TInt E32Image::OpenFile() |
|
1798 { |
|
1799 TBuf8<KMaxFileName*sizeof(TText)> fnb; |
|
1800 if (iAttr & ECodeSegAttExpVer) |
|
1801 { |
|
1802 TFileNameInfo fi; |
|
1803 fi.Set(iFileName, 0); |
|
1804 fi.iVersion = iModuleVersion; |
|
1805 fi.GetName(fnb, TFileNameInfo::EIncludeDrivePathBaseExt|TFileNameInfo::EForceVer); |
|
1806 } |
|
1807 else |
|
1808 fnb = iFileName; |
|
1809 TPtr16 fn(fnb.Expand()); |
|
1810 __IF_DEBUG(Print(_L(">E32Image::OpenFile %S"),&fn)); |
|
1811 TInt r = iFile.Open(gTheLoaderFs, fn, EFileStream|EFileRead|EFileShareReadersOnly|EFileReadDirectIO); |
|
1812 __IF_DEBUG(Printf("<E32Image::OpenFile %d", r)); |
|
1813 return r; |
|
1814 } |
|
1815 |
|
1816 |
|
1817 /** |
|
1818 Check if this executable is already loaded. If it is, set iAlreadyLoaded true and |
|
1819 iHandle to an newly opened reference on the CodeSeg. Also set iExportDirLoad if the |
|
1820 export directory of the executable is directly visible to the Loader. |
|
1821 */ |
|
1822 TInt E32Image::CheckAlreadyLoaded() |
|
1823 { |
|
1824 __IF_DEBUG(Printf(">E32Image::CheckAlreadyLoaded %S", &iFileName)); |
|
1825 __IF_DEBUG(Printf("UIDs %08x,%08x,%08x",iUids[0],iUids[1],iUids[2])); |
|
1826 __IF_DEBUG(Printf("VER %08x",iModuleVersion)); |
|
1827 __IF_DEBUG(Printf("CAPS %08x %08x SID %08x", iS.iSecureId, iS.iCaps[1], iS.iCaps[0])); |
|
1828 __IF_DEBUG(Printf("Client process handle %08x",iClientProcessHandle)); |
|
1829 |
|
1830 TFindCodeSeg find; |
|
1831 find.iUids = iUids; |
|
1832 find.iRomImgHdr = NULL; |
|
1833 #ifndef __WINS__ |
|
1834 // Make sure we check the code segment attributes (kernel or global) |
|
1835 // as part of the decision as to whether we are loaded or not. |
|
1836 find.iAttrMask = (ECodeSegAttKernel|ECodeSegAttGlobal); |
|
1837 find.iAttrVal = iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal); |
|
1838 #else |
|
1839 // On the emulator, all DLLs are loaded into the same process, so we |
|
1840 // don't distinguish between instances of the same DLL loaded with |
|
1841 // different code segment attributes. |
|
1842 find.iAttrMask = 0; |
|
1843 find.iAttrVal = 0; |
|
1844 #endif |
|
1845 find.iProcess = iClientProcessHandle; |
|
1846 find.iS = iS; |
|
1847 find.iModuleVersion = iModuleVersion; |
|
1848 find.iName = RootName(); |
|
1849 __IF_DEBUG(Printf("Required root name %S", &find.iName)); |
|
1850 |
|
1851 E32Loader::CodeSegDeferDeletes(); |
|
1852 iHandle = NULL; |
|
1853 TAny* h = NULL; |
|
1854 TInt r = KErrNone; |
|
1855 E32Loader::CodeSegNext(h, find); |
|
1856 if(h) |
|
1857 { |
|
1858 // found... |
|
1859 iHandle = h; |
|
1860 __IF_DEBUG(Printf("Client process handle %08x",iClientProcessHandle)); |
|
1861 E32Loader::CodeSegInfo(h, *this); |
|
1862 __IF_DEBUG(Printf("Client process handle %08x",iClientProcessHandle)); |
|
1863 r = E32Loader::CodeSegOpen(h, iClientProcessHandle); |
|
1864 } |
|
1865 E32Loader::CodeSegEndDeferDeletes(); |
|
1866 |
|
1867 if(iHandle && r==KErrNone) |
|
1868 { |
|
1869 iAlreadyLoaded = ETrue; |
|
1870 TUint32 attrMask = (gExecutesInSupervisorMode)? |
|
1871 // The loader reads export directories in kernel mode so it can access |
|
1872 // kernel code export directories and global export directories. |
|
1873 ECodeSegAttKernel | ECodeSegAttGlobal : |
|
1874 // The loader reads export directories in user mode so it can't access |
|
1875 // kernel code export directories but can access global export directories. |
|
1876 ECodeSegAttGlobal; |
|
1877 |
|
1878 if(iAttr & attrMask) |
|
1879 {// The export directory is visible to loader so set iExportDirLoad to prevent |
|
1880 // the loader from invoking E32Loader::ReadExportDir() to copy the kernel's copy |
|
1881 // of the export directory to the loader's heap. |
|
1882 iExportDirLoad = iExportDir; |
|
1883 } |
|
1884 } |
|
1885 |
|
1886 __IF_DEBUG(Printf("<E32Image::CheckAlreadyLoaded %08x, %d",iHandle,r)); |
|
1887 return r; |
|
1888 } |
|
1889 |
|
1890 TInt E32Image::Order(const E32Image& aL, const E32Image& aR) |
|
1891 { |
|
1892 return aL.RootName().CompareF(aR.RootName()); |
|
1893 } |
|
1894 |
|
1895 /****************************************************************************** |
|
1896 * Loader debug code |
|
1897 ******************************************************************************/ |
|
1898 |
|
1899 #ifdef _DEBUG |
|
1900 TInt DoLoaderDebugFunction(const RMessage2& aMsg) |
|
1901 { |
|
1902 TInt f=aMsg.Int0(); |
|
1903 __IF_DEBUG(Printf("LdrDbg: %d,%d,%d,%d",f,aMsg.Int1(),aMsg.Int2(),aMsg.Int3())); |
|
1904 switch(f) |
|
1905 { |
|
1906 case ELoaderDebug_SetHeapFail: |
|
1907 KernHeapFailCount=aMsg.Int2(); |
|
1908 LdrHeapFailCount=aMsg.Int1(); |
|
1909 return KErrNone; |
|
1910 case ELoaderDebug_SetRFsFail: |
|
1911 RFsErrorCode = aMsg.Int1(); |
|
1912 RFsFailCount = aMsg.Int2(); |
|
1913 return KErrNone; |
|
1914 default: |
|
1915 return KErrNotSupported; |
|
1916 } |
|
1917 } |
|
1918 #endif |
|
1919 |
|
1920 #ifdef _DEBUG |
|
1921 void SetupHeapFail(const RMessage2& /*aMsg*/) |
|
1922 { |
|
1923 __IF_DEBUG(Printf("SetupHeapFail: %d,%d",LdrHeapFailCount,KernHeapFailCount)); |
|
1924 if (KernHeapFailCount>0) |
|
1925 { |
|
1926 __KHEAP_SETFAIL(RHeap::EFailNext, KernHeapFailCount); |
|
1927 __KHEAP_MARK; |
|
1928 HeapFailActive|=1; |
|
1929 } |
|
1930 if (LdrHeapFailCount>0) |
|
1931 { |
|
1932 __UHEAP_SETFAIL(RHeap::EFailNext, LdrHeapFailCount); |
|
1933 __UHEAP_MARK; |
|
1934 HeapFailActive|=2; |
|
1935 } |
|
1936 ProcessCreated = EFalse; |
|
1937 ProcessDestructStat = KRequestPending; |
|
1938 ProcessDestructStatPtr = &ProcessDestructStat; |
|
1939 } |
|
1940 |
|
1941 void EndHeapFailCheck(TInt aError) |
|
1942 { |
|
1943 __IF_DEBUG(Printf("EndHeapFail: %d",aError)); |
|
1944 if (aError==KErrNone && ProcessCreated) |
|
1945 { |
|
1946 User::CancelMiscNotifier(ProcessDestructStat); |
|
1947 User::WaitForRequest(ProcessDestructStat); |
|
1948 } |
|
1949 if (aError!=KErrNone) |
|
1950 { |
|
1951 if (ProcessCreated) |
|
1952 // wait for any partially created process to die |
|
1953 User::WaitForRequest(ProcessDestructStat); |
|
1954 |
|
1955 // wait for reaper to run |
|
1956 TInt rr; |
|
1957 if (CActiveScheduler::RunIfReady(rr,KPriorityVeryHigh)) |
|
1958 User::WaitForAnyRequest(); |
|
1959 |
|
1960 // wait for any async cleanup in the supervisor to finish |
|
1961 UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); |
|
1962 |
|
1963 if (HeapFailActive&1) |
|
1964 { |
|
1965 __KHEAP_MARKEND; |
|
1966 } |
|
1967 if (HeapFailActive&2) |
|
1968 { |
|
1969 __UHEAP_MARKEND; |
|
1970 } |
|
1971 } |
|
1972 if (HeapFailActive & 3) |
|
1973 { |
|
1974 __KHEAP_TOTAL_RESET; |
|
1975 __UHEAP_TOTAL_RESET; |
|
1976 } |
|
1977 HeapFailActive=0; |
|
1978 ProcessDestructStatPtr = 0; |
|
1979 ProcessCreated = EFalse; |
|
1980 } |
|
1981 |
|
1982 void SetupRFsFail(const RMessage2& /*aMsg*/) |
|
1983 { |
|
1984 __IF_DEBUG(Printf("SetupRFsFail: %d,%d", RFsErrorCode, RFsFailCount)); |
|
1985 if (RFsErrorCode!=KErrNone && RFsFailCount>0) |
|
1986 { |
|
1987 gTheLoaderFs.SetErrorCondition(RFsErrorCode, RFsFailCount); |
|
1988 RFsFailActive = ETrue; |
|
1989 } |
|
1990 } |
|
1991 |
|
1992 void EndRFsFailCheck(TInt /*aError*/) |
|
1993 { |
|
1994 if (RFsFailActive) |
|
1995 { |
|
1996 gTheLoaderFs.SetErrorCondition(KErrNone); |
|
1997 RFsFailActive = EFalse; |
|
1998 } |
|
1999 } |
|
2000 |
|
2001 #endif |
|
2002 |
|
2003 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
2004 void RLdrReq::Dump(const char* aTitle) const |
|
2005 { |
|
2006 RDebug::Printf(aTitle); |
|
2007 if (iFileName) |
|
2008 RDebug::Printf("iFileName=%S", iFileName); |
|
2009 if (iPath) |
|
2010 RDebug::Printf("iPath=%S", iPath); |
|
2011 RDebug::Printf("SID %08x Caps %08x %08x", iSecureId, iPlatSecCaps[1], iPlatSecCaps[0]); |
|
2012 const TUint32* uid = (const TUint32*)&iRequestedUids; |
|
2013 RDebug::Printf("REQ UIDs %08x %08x %08x REQ VER %08x", uid[0], uid[1], uid[2], iRequestedVersion); |
|
2014 iFileNameInfo.Dump(); |
|
2015 } |
|
2016 |
|
2017 void TFileNameInfo::Dump() const |
|
2018 { |
|
2019 const TDesC8& d = Drive(); |
|
2020 const TDesC8& p = Path(); |
|
2021 const TDesC8& b = Base(); |
|
2022 const TDesC8& v = VerStr(); |
|
2023 const TDesC8& u = UidStr(); |
|
2024 const TDesC8& e = Ext(); |
|
2025 RDebug::Printf("D=%S P=%S B=%S V=%S U=%S E=%S", &d, &p, &b, &v, &u, &e); |
|
2026 } |
|
2027 #endif |
|
2028 |
|
2029 #ifdef __TRACE_LOADER_HEAP__ |
|
2030 |
|
2031 class RTraceHeap : public RAllocator |
|
2032 { |
|
2033 public: |
|
2034 virtual TAny* Alloc(TInt aSize); |
|
2035 virtual void Free(TAny* aPtr); |
|
2036 virtual TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0); |
|
2037 virtual TInt AllocLen(const TAny* aCell) const; |
|
2038 virtual TInt Compress(); |
|
2039 virtual void Reset(); |
|
2040 virtual TInt AllocSize(TInt& aTotalAllocSize) const; |
|
2041 virtual TInt Available(TInt& aBiggestBlock) const; |
|
2042 virtual TInt DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL); |
|
2043 public: |
|
2044 RAllocator* iA; |
|
2045 }; |
|
2046 |
|
2047 void InstallHeapTracer() |
|
2048 { |
|
2049 RTraceHeap* p = new RTraceHeap; |
|
2050 __ASSERT_ALWAYS(p!=NULL, User::Invariant()); |
|
2051 p->iA = &User::Heap(); |
|
2052 User::SwitchHeap(p); |
|
2053 } |
|
2054 |
|
2055 TAny* RTraceHeap::Alloc(TInt aSize) |
|
2056 { |
|
2057 RDebug::Printf("TH:Alloc(%08x)", aSize); |
|
2058 TAny* p = iA->Alloc(aSize); |
|
2059 RDebug::Printf("TH:returns %08x", p); |
|
2060 return p; |
|
2061 } |
|
2062 |
|
2063 void RTraceHeap::Free(TAny* aPtr) |
|
2064 { |
|
2065 RDebug::Printf("TH:Free(%08x)", aPtr); |
|
2066 iA->Free(aPtr); |
|
2067 } |
|
2068 |
|
2069 TAny* RTraceHeap::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0) |
|
2070 { |
|
2071 RDebug::Printf("TH:ReAlloc(%08x,%08x,%x)", aPtr, aSize, aMode); |
|
2072 TAny* p = iA->ReAlloc(aPtr,aSize,aMode); |
|
2073 RDebug::Printf("TH:returns %08x", p); |
|
2074 return p; |
|
2075 } |
|
2076 |
|
2077 TInt RTraceHeap::AllocLen(const TAny* aCell) const |
|
2078 { |
|
2079 RDebug::Printf("TH:AllocLen(%08x)", aCell); |
|
2080 TInt l = iA->AllocLen(aCell); |
|
2081 RDebug::Printf("TH:returns %08x", l); |
|
2082 return l; |
|
2083 } |
|
2084 |
|
2085 TInt RTraceHeap::Compress() |
|
2086 { |
|
2087 RDebug::Printf("TH:Compress()"); |
|
2088 TInt l = iA->Compress(); |
|
2089 RDebug::Printf("TH:returns %08x", l); |
|
2090 return l; |
|
2091 } |
|
2092 |
|
2093 void RTraceHeap::Reset() |
|
2094 { |
|
2095 RDebug::Printf("TH:Reset()"); |
|
2096 iA->Reset(); |
|
2097 } |
|
2098 |
|
2099 TInt RTraceHeap::AllocSize(TInt& aTotalAllocSize) const |
|
2100 { |
|
2101 RDebug::Printf("TH:AllocSize()"); |
|
2102 TInt s; |
|
2103 TInt r = iA->AllocSize(s); |
|
2104 RDebug::Printf("TH:returns %08x(%08x)", r, s); |
|
2105 aTotalAllocSize = s; |
|
2106 return r; |
|
2107 } |
|
2108 |
|
2109 TInt RTraceHeap::Available(TInt& aBiggestBlock) const |
|
2110 { |
|
2111 RDebug::Printf("TH:Available()"); |
|
2112 TInt s; |
|
2113 TInt r = iA->Available(s); |
|
2114 RDebug::Printf("TH:returns %08x(%08x)", r, s); |
|
2115 aBiggestBlock = s; |
|
2116 return r; |
|
2117 } |
|
2118 |
|
2119 TInt RTraceHeap::DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL) |
|
2120 { |
|
2121 RDebug::Printf("TH:DebugFunction(%d,%08x,%08x)", aFunc, a1, a2); |
|
2122 TInt r = iA->DebugFunction(aFunc, a1, a2); |
|
2123 RDebug::Printf("TH:returns %08x", r); |
|
2124 return r; |
|
2125 } |
|
2126 |
|
2127 #endif |
|
2128 |
|
2129 /* The Reaper - Used to delete binarys in /sys/del/ after they are no longer needed by demand paging */ |
|
2130 |
|
2131 CActiveReaper::CActiveReaper() |
|
2132 : CActive(KPriorityVeryHigh) |
|
2133 { |
|
2134 iLoaderDeletedList=NULL; |
|
2135 } |
|
2136 |
|
2137 CActiveReaper* CActiveReaper::New() |
|
2138 { |
|
2139 CActiveReaper *self = new CActiveReaper(); |
|
2140 if (self!=NULL) |
|
2141 self->Construct(); |
|
2142 return self; |
|
2143 } |
|
2144 |
|
2145 void CActiveReaper::Construct() |
|
2146 { |
|
2147 iStatus=KRequestPending; |
|
2148 CActiveScheduler::Add(this); |
|
2149 E32Loader::NotifyIfCodeSegDestroyed(iStatus); |
|
2150 SetActive(); |
|
2151 } |
|
2152 |
|
2153 /* |
|
2154 Initialises the \sys\del\ directory, where files can be moved too, on deletion. |
|
2155 If the directory exists, then it is emptied. |
|
2156 */ |
|
2157 |
|
2158 void CActiveReaper::InitDelDir() |
|
2159 { |
|
2160 TDriveList driveList; |
|
2161 TDriveInfo driveInfo; |
|
2162 CDir* dir=NULL; |
|
2163 TFileName fileName; |
|
2164 TInt i; |
|
2165 TBuf<KPathDelLength> drivePath(KPathDel); |
|
2166 TInt r = gTheLoaderFs.DriveList(driveList); |
|
2167 if (r!=KErrNone) |
|
2168 return; |
|
2169 TChar ch; |
|
2170 for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum) |
|
2171 { |
|
2172 if(!driveList[drvNum]) |
|
2173 continue; //-- skip nonexistent drive |
|
2174 r = gTheLoaderFs.Drive(driveInfo, drvNum); |
|
2175 if ((r==KErrNone) && (driveInfo.iDriveAtt & KDriveAttPageable) && !(driveInfo.iMediaAtt & KMediaAttWriteProtected)) |
|
2176 { |
|
2177 gTheLoaderFs.DriveToChar(drvNum, ch); |
|
2178 drivePath[0]=(TText)ch; |
|
2179 r = gTheLoaderFs.GetDir(drivePath,KEntryAttMatchExclude | KEntryAttDir ,ESortNone,dir); |
|
2180 if (r==KErrNone) |
|
2181 { |
|
2182 for (i=dir->Count()-1;i>=0;i--) |
|
2183 { |
|
2184 fileName = drivePath; |
|
2185 fileName.Append((*dir)[i].iName); |
|
2186 r = gTheLoaderFs.SetAtt(fileName,0,KEntryAttReadOnly|KEntryAttSystem); |
|
2187 r = gTheLoaderFs.Delete(fileName); |
|
2188 } |
|
2189 delete dir; |
|
2190 } |
|
2191 } |
|
2192 } |
|
2193 } |
|
2194 |
|
2195 |
|
2196 void CActiveReaper::RunL() |
|
2197 { |
|
2198 |
|
2199 TCodeSegLoaderCookie cookie; |
|
2200 TInt r; |
|
2201 |
|
2202 TLoaderDeletedList* link; |
|
2203 TLoaderDeletedList* prev; |
|
2204 |
|
2205 iStatus=KRequestPending; |
|
2206 E32Loader::NotifyIfCodeSegDestroyed(iStatus); |
|
2207 SetActive(); |
|
2208 FOREVER |
|
2209 { |
|
2210 r=E32Loader::GetDestroyedCodeSegInfo(cookie); |
|
2211 if (r!=KErrNone) |
|
2212 break; |
|
2213 r = cookie.iFileClamp.Close(gTheLoaderFs); |
|
2214 // See if its on our list. |
|
2215 if (r==KErrNone) |
|
2216 { |
|
2217 link = iLoaderDeletedList; |
|
2218 prev= (TLoaderDeletedList*) &iLoaderDeletedList; |
|
2219 |
|
2220 while (link!=NULL) |
|
2221 { |
|
2222 if ((link->iStartBlock==cookie.iStartAddress) && (link->iDriveNumber==cookie.iDriveNumber)) |
|
2223 { |
|
2224 gTheLoaderFs.Delete(*link->iFileName); |
|
2225 // Ignore error from file delete operation. If it does fail then the |
|
2226 // file will just have to sit around until it is cleaned up on the next reboot. |
|
2227 |
|
2228 // Remove from our list. |
|
2229 prev->iNext=link->iNext; |
|
2230 delete link; |
|
2231 link = prev->iNext; |
|
2232 } |
|
2233 else |
|
2234 { |
|
2235 prev = link; |
|
2236 link = link->iNext; |
|
2237 } |
|
2238 }// while |
|
2239 } // if unclamp ok |
|
2240 } //Forever |
|
2241 } |
|
2242 |
|
2243 void CActiveReaper::DoCancel(){}; |
|
2244 |
|
2245 CActiveReaper::~CActiveReaper() {} |
|
2246 |
|
2247 void CActiveReaper::AddDeleted(TLoaderDeletedList* aLink) |
|
2248 { |
|
2249 aLink->iNext=iLoaderDeletedList; |
|
2250 iLoaderDeletedList = aLink; |
|
2251 } |
|
2252 |
|
2253 /* Slotted allocator - used to store iFileData from hashchecked images */ |
|
2254 |
|
2255 TInt CSlottedChunkAllocator::Construct() |
|
2256 { |
|
2257 TInt r = iChunk.CreateDisconnectedLocal(0, 0, KSlotSize * KSlots); |
|
2258 if (r == KErrNone) |
|
2259 iBase = iChunk.Base(); |
|
2260 return r; |
|
2261 } |
|
2262 |
|
2263 TAny* CSlottedChunkAllocator::Alloc(TUint aSize) |
|
2264 { |
|
2265 if (aSize == 0 || aSize > KSlotSize) |
|
2266 return NULL; |
|
2267 |
|
2268 for (TInt i=0; i<KSlots; ++i) |
|
2269 if (!iUsed[i]) |
|
2270 { |
|
2271 if (iChunk.Commit(i * KSlotSize, aSize) == KErrNone) |
|
2272 { |
|
2273 iUsed[i] = aSize; |
|
2274 return iBase + i * KSlotSize; |
|
2275 } |
|
2276 else |
|
2277 return NULL; |
|
2278 } |
|
2279 |
|
2280 return NULL; |
|
2281 } |
|
2282 |
|
2283 void CSlottedChunkAllocator::Free(TAny* aPtr) |
|
2284 { |
|
2285 if (!aPtr) |
|
2286 return; |
|
2287 |
|
2288 TInt offset = ((TUint8*)aPtr) - iBase; |
|
2289 TInt slot = offset / KSlotSize; |
|
2290 __ASSERT_DEBUG(offset % KSlotSize == 0 && slot >= 0 && slot < KSlots, Fault(ELdrFileDataAllocError)); |
|
2291 #ifdef _DEBUG |
|
2292 TInt r = |
|
2293 #endif |
|
2294 iChunk.Decommit(offset, iUsed[slot]); |
|
2295 __ASSERT_DEBUG(r==KErrNone, Fault(ELdrFileDataAllocError)); |
|
2296 iUsed[slot] = 0; |
|
2297 } |