userlibandfileserver/fileserver/sfile/sf_ldr.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	}