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