os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mcodeseg.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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
// e32\memmodel\emul\win32\mcodeseg.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#define __INCLUDE_ALL_SUPPORTED_CAPABILITIES__
sl@0
    19
#include "memmodel.h"
sl@0
    20
#include <property.h>
sl@0
    21
#include <emulator.h>
sl@0
    22
#include <wchar.h>
sl@0
    23
sl@0
    24
#define __CHECKHEAP()	((RHeapK*)K::Allocator)->Check()
sl@0
    25
sl@0
    26
static TBool BootComplete;	// flag set when boot EXE is loaded as an EPOC process
sl@0
    27
static DWin32CodeSeg* KernelCodeSeg;
sl@0
    28
static HMODULE KernelModuleHandle;
sl@0
    29
sl@0
    30
GLREF_C TInt CompareCodeSegsByName(const DCodeSeg& aA, const DCodeSeg& aB);
sl@0
    31
sl@0
    32
void TruncToNarrow(TUint8* aDes, const TUint16* aSrc, int aLen)
sl@0
    33
	{
sl@0
    34
	//converts to narrow by dumping the high order byte
sl@0
    35
	if(aDes && aSrc)
sl@0
    36
		{
sl@0
    37
		if(aLen==-1)
sl@0
    38
			{
sl@0
    39
			for(int index=0;*aSrc;index++)
sl@0
    40
				*aDes++ = (TUint8)*aSrc++;
sl@0
    41
			*aDes = '\0';
sl@0
    42
			}
sl@0
    43
		else
sl@0
    44
			for(int index=0;index<aLen;index++)
sl@0
    45
				*aDes++ = (TUint8)*aSrc++;
sl@0
    46
		}
sl@0
    47
	}
sl@0
    48
sl@0
    49
void ExpandToWide(TUint16* aDes, const TUint8* aSrc, int aLen)
sl@0
    50
	{
sl@0
    51
	if(aDes && aSrc)
sl@0
    52
		{
sl@0
    53
		for(int index=0;index<aLen;index++)
sl@0
    54
			*aDes++ = (TUint16)*aSrc++;
sl@0
    55
		}
sl@0
    56
	}
sl@0
    57
sl@0
    58
#ifdef KDLL
sl@0
    59
void DumpWin32CodeSeg(DWin32CodeSeg& a)
sl@0
    60
	{
sl@0
    61
	const TUint32* uid=(const TUint32*)&a.iUids;
sl@0
    62
	Kern::Printf("DWin32CodeSeg@%08x:",&a);
sl@0
    63
	Kern::Printf("iLink = %08x %08x", a.iLink.iNext, a.iLink.iPrev);
sl@0
    64
	Kern::Printf("iTempLink = %08x %08x", a.iTempLink.iNext, a.iTempLink.iPrev);
sl@0
    65
	Kern::Printf("iGbgLink = %08x %08x", a.iGbgLink.iNext, a.iGbgLink.iPrev);
sl@0
    66
	Kern::Printf("iAccessCount = %d", a.iAccessCount);
sl@0
    67
	Kern::Printf("iEntryPtVeneer = %08x", a.iEntryPtVeneer);
sl@0
    68
	Kern::Printf("iFileEntryPoint = %08x", a.iFileEntryPoint);
sl@0
    69
	Kern::Printf("iFileName = %lS", a.iFileName);
sl@0
    70
	Kern::Printf("iRootName = %lS", &a.iRootName);
sl@0
    71
	Kern::Printf("iExtOffset = %d", a.iExtOffset);
sl@0
    72
	Kern::Printf("iModuleVersion = %08x", a.iModuleVersion);
sl@0
    73
	Kern::Printf("iUids = %08x %08x %08x", uid[0], uid[1], uid[2]);
sl@0
    74
	Kern::Printf("iDepCount=%d iDeps=%08x", a.iDepCount, a.iDeps);
sl@0
    75
	Kern::Printf("iNextDep=%d, iMark=%08x, iAttr=%08x", a.iNextDep, a.iMark, a.iAttr);
sl@0
    76
	Kern::Printf("iExeCodeSeg=%08x, iAttachProcess=%O", a.iExeCodeSeg, a.iAttachProcess);
sl@0
    77
	Kern::Printf("iWinInstance = %08x", a.iWinInstance);
sl@0
    78
	Kern::Printf("iModuleHandle = %08x", a.iModuleHandle);
sl@0
    79
	Kern::Printf("iModuleFile = %08x", a.iModuleFile);
sl@0
    80
	Kern::Printf("iAlwaysLoaded = %08x", a.iAlwaysLoaded);
sl@0
    81
	Kern::Printf("iModuleList = %08x", a.iModuleList);
sl@0
    82
	}
sl@0
    83
#endif
sl@0
    84
sl@0
    85
void ExecInEntryPoint()
sl@0
    86
	{
sl@0
    87
	// This function will be called if an Exec:: call is attempted in the entry
sl@0
    88
	// point of a DLL which didn't specify 'epocallowdlldata'
sl@0
    89
	Kern::Fault("BAD DLL STATIC",0);
sl@0
    90
	}
sl@0
    91
sl@0
    92
static const SFastExecTable DummyFastExecTable={0,{0}};
sl@0
    93
static const SSlowExecTable DummySlowExecTable={0,(TLinAddr)ExecInEntryPoint,0,{{0,0}}};
sl@0
    94
sl@0
    95
// Force a call to a DLL entry point to initialise any gratuitous writeable data
sl@0
    96
// generated by the compiler.
sl@0
    97
// Change exec table to prevent any executive calls in case someone forgot to
sl@0
    98
// use the 'epocallowdlldata' option.
sl@0
    99
void ForceEntryPointCall(TLinAddr aEntryPoint)
sl@0
   100
	{
sl@0
   101
	__KTRACE_OPT(KDLL,Kern::Printf("ForceEntryPoint %08x", aEntryPoint));
sl@0
   102
	NKern::Lock();
sl@0
   103
	NThread* nthrd = NKern::CurrentThread();
sl@0
   104
	const SFastExecTable* fast = nthrd->iFastExecTable;
sl@0
   105
	const SSlowExecEntry* slow = nthrd->iSlowExecTable;
sl@0
   106
	nthrd->iFastExecTable = (SFastExecTable*)&DummyFastExecTable;
sl@0
   107
	nthrd->iSlowExecTable = DummySlowExecTable.iEntries;
sl@0
   108
	TLibraryEntry ep = (TLibraryEntry)aEntryPoint;
sl@0
   109
	(*ep)(KModuleEntryReasonProcessAttach);
sl@0
   110
	nthrd->iFastExecTable = fast;
sl@0
   111
	nthrd->iSlowExecTable = slow;
sl@0
   112
	NKern::Unlock();
sl@0
   113
	}
sl@0
   114
sl@0
   115
class TWin32Filename
sl@0
   116
	{
sl@0
   117
public:
sl@0
   118
	inline TWin32Filename()
sl@0
   119
		{iBuf[0] = '\0';}
sl@0
   120
	inline TWin32Filename(const TDesC& aFilename)
sl@0
   121
		{Set(aFilename);}
sl@0
   122
	inline TWin32Filename& operator=(const TDesC& aFilename)
sl@0
   123
		{Set(aFilename);return *this;}
sl@0
   124
	inline operator LPCWSTR() const
sl@0
   125
		{return iBuf;}
sl@0
   126
private:
sl@0
   127
	void Set(const TDesC& aFilename);
sl@0
   128
private:
sl@0
   129
	WCHAR iBuf[KMaxFileName + 1];
sl@0
   130
	};
sl@0
   131
sl@0
   132
void TWin32Filename::Set(const TDesC& aFilename)
sl@0
   133
	{
sl@0
   134
	TUint16 fileName[KMaxFileName];
sl@0
   135
	ExpandToWide(fileName, aFilename.Ptr(), aFilename.Length());
sl@0
   136
	TPtr p((TUint8*)iBuf,KMaxFileName<<1);
sl@0
   137
	Property::MapFilename(p, TPtrC((TUint8*)fileName,aFilename.Length()<<1));
sl@0
   138
	iBuf[p.Length()>>1] = '\0';
sl@0
   139
	}
sl@0
   140
sl@0
   141
class DModuleList : public DBase
sl@0
   142
	{
sl@0
   143
public:
sl@0
   144
	enum TFlags
sl@0
   145
		{
sl@0
   146
		EFlagData=0x01,
sl@0
   147
		EFlagDataPresent=0x02,
sl@0
   148
		EFlagAlreadyLoaded=0x04,
sl@0
   149
		EFlagMark=0x08,
sl@0
   150
		EFlagExe=0x10,
sl@0
   151
		EFlagAlwaysLoaded=0x20,
sl@0
   152
		EFlagExeInTree=0x40,
sl@0
   153
		};
sl@0
   154
sl@0
   155
	struct SModule
sl@0
   156
		{
sl@0
   157
		TLinAddr iModuleHandle;
sl@0
   158
		DWin32CodeSeg* iCodeSeg;
sl@0
   159
		TUint32 iFlags;
sl@0
   160
		SSecurityInfo iS;
sl@0
   161
		TUint32 iModuleVersion;
sl@0
   162
		TInt iDepCount;
sl@0
   163
		TInt* iDepList;
sl@0
   164
		};
sl@0
   165
public:
sl@0
   166
	DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess);
sl@0
   167
	virtual ~DModuleList();
sl@0
   168
	TInt Find(TInt aModule);
sl@0
   169
	TInt GatherDependencies(HMODULE aModule);
sl@0
   170
	TInt CompileDepLists();
sl@0
   171
	void SetFlags();
sl@0
   172
	TUint32 Flags(SModule* aM);
sl@0
   173
	TInt LoadDependencies();
sl@0
   174
	void LinkDependencies();
sl@0
   175
	TInt Loaded();
sl@0
   176
public:
sl@0
   177
	DWin32CodeSeg* iMain;
sl@0
   178
	DProcess* iAttachProcess;
sl@0
   179
	RArray<SModule> iModules;
sl@0
   180
	};
sl@0
   181
sl@0
   182
DModuleList::DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess)
sl@0
   183
	:	iMain(aMainSeg), iAttachProcess(aProcess),
sl@0
   184
		iModules(8, _FOFF(SModule,iModuleHandle), 2*256)
sl@0
   185
	{
sl@0
   186
	}
sl@0
   187
sl@0
   188
DModuleList::~DModuleList()
sl@0
   189
	{
sl@0
   190
	TInt c = iModules.Count();
sl@0
   191
	if (c)
sl@0
   192
		{
sl@0
   193
		SModule* pM = (SModule*)&iModules[0];
sl@0
   194
		SModule* pE = pM + c;
sl@0
   195
		for (; pM<pE; ++pM)
sl@0
   196
			{
sl@0
   197
			Kern::Free(pM->iDepList);
sl@0
   198
			}
sl@0
   199
		}
sl@0
   200
	iModules.Close();
sl@0
   201
	}
sl@0
   202
sl@0
   203
TInt DModuleList::Find(TInt aModule)
sl@0
   204
	{
sl@0
   205
	SModule mod;
sl@0
   206
	mod.iModuleHandle=(TLinAddr)aModule;
sl@0
   207
	return iModules.FindInUnsignedKeyOrder(mod);
sl@0
   208
	}
sl@0
   209
/**
sl@0
   210
Populate iModules with SModule entries corresponding to supplied HModule and all of its dependencies,
sl@0
   211
direct and indirect.  
sl@0
   212
sl@0
   213
@param aModule A Windows module handle
sl@0
   214
@return KErrNone if successful
sl@0
   215
*/
sl@0
   216
TInt DModuleList::GatherDependencies(HMODULE aModule)
sl@0
   217
	{
sl@0
   218
	__KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
sl@0
   219
	Emulator::TModule etm(aModule);
sl@0
   220
	SModule mod;
sl@0
   221
	mod.iModuleHandle=(TLinAddr)aModule;
sl@0
   222
	mod.iCodeSeg=NULL;
sl@0
   223
	mod.iDepList=NULL;
sl@0
   224
sl@0
   225
	TUint32 uid[3];
sl@0
   226
	TUidType& uidref=*(TUidType*)uid;
sl@0
   227
	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
sl@0
   228
	if (!hdr)
sl@0
   229
		return KErrNotSupported;
sl@0
   230
	__KTRACE_OPT(KDLL,Kern::Printf("Module flags %08x, cap %08x %08x, sid %08x", hdr->iFlags, hdr->iS.iCaps[1], hdr->iS.iCaps[0], hdr->iS.iSecureId));
sl@0
   231
	mod.iS = hdr->iS;
sl@0
   232
	// Overide capabilities in image
sl@0
   233
	const SCapabilitySet& disabledCaps = *(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
sl@0
   234
	for(TInt i=0; i<SCapabilitySet::ENCapW; i++)
sl@0
   235
		{
sl@0
   236
		mod.iS.iCaps[i] |= disabledCaps[i];
sl@0
   237
		mod.iS.iCaps[i] &= AllSupportedCapabilities[i];
sl@0
   238
		}
sl@0
   239
	mod.iModuleVersion = hdr->iModuleVersion;
sl@0
   240
	mod.iFlags = (hdr->iFlags & KEmulatorImageFlagAllowDllData) ? EFlagData|EFlagDataPresent : 0;
sl@0
   241
	uidref = *(const TUidType*)&hdr->iUids[0];
sl@0
   242
	TBool isExe = (uid[0]==KExecutableImageUidValue);
sl@0
   243
	TBool data_section_present = (etm.Section(KWin32SectionName_EpocData) != NULL);
sl@0
   244
	if (data_section_present && isExe)
sl@0
   245
		mod.iFlags = EFlagData|EFlagDataPresent;
sl@0
   246
	__KTRACE_OPT(KDLL,Kern::Printf("DataSectionPresent = %x", data_section_present));
sl@0
   247
sl@0
   248
	// Can't do this for CodeWarrior since it sticks everything in .data, even constants
sl@0
   249
	// On VC6 this check works for Base code, but not for some other code.
sl@0
   250
//	if (data_section_present && !isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
sl@0
   251
//		return KErrNotSupported;
sl@0
   252
sl@0
   253
	if (!data_section_present)
sl@0
   254
		mod.iFlags = 0;
sl@0
   255
	if (isExe)
sl@0
   256
		mod.iFlags |= EFlagExe|EFlagExeInTree;
sl@0
   257
sl@0
   258
	SWin32Module w32m;
sl@0
   259
	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
sl@0
   260
	w32m.iCodeSeg=NULL;
sl@0
   261
	TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
sl@0
   262
	__KTRACE_OPT(KDLL, Kern::Printf("GlobalIx=%d", ix));
sl@0
   263
	if ((ix>=0 && !MM::Win32Modules[ix].iCodeSeg) || aModule==KernelModuleHandle)
sl@0
   264
		mod.iFlags|=EFlagAlwaysLoaded;
sl@0
   265
	TInt r=iModules.InsertInUnsignedKeyOrder(mod);
sl@0
   266
	__KTRACE_OPT(KDLL, Kern::Printf("Flags=%08x, InsertRes=%d", mod.iFlags, r));
sl@0
   267
	if (r==KErrAlreadyExists)
sl@0
   268
		return KErrNone;
sl@0
   269
	if (r!=KErrNone)
sl@0
   270
		return r;
sl@0
   271
	if (mod.iFlags & EFlagAlwaysLoaded)
sl@0
   272
		return KErrNone;	// stop if we reach an extension or variant
sl@0
   273
	if (data_section_present && (mod.iFlags & EFlagData)==0)
sl@0
   274
		{
sl@0
   275
		// DLL, .data present but 'epocallowdlldata' not specified
sl@0
   276
		// - either the compiler forgetting that something's constant or
sl@0
   277
		// developer forgetting to specify 'epocallowdlldata'.
sl@0
   278
		// call entry point from here to keep the compiler happy
sl@0
   279
		const char* entry_name = "_E32Dll" ;
sl@0
   280
		TLinAddr ep = (TLinAddr)Emulator::GetProcAddress(aModule, entry_name);
sl@0
   281
		__NK_ASSERT_ALWAYS(ep!=0);
sl@0
   282
		ForceEntryPointCall(ep);
sl@0
   283
		}
sl@0
   284
sl@0
   285
	const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
sl@0
   286
	if (imports)
sl@0
   287
		{
sl@0
   288
	    for (; imports->Characteristics; ++imports )
sl@0
   289
			{
sl@0
   290
			__KTRACE_OPT(KDLL, { TPtrC8 n((const TText8*)etm.Translate(imports->Name)); Kern::Printf("Importing from %S", &n);} );
sl@0
   291
			Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
sl@0
   292
sl@0
   293
			if (!imp_etm.IsValid())
sl@0
   294
				{
sl@0
   295
				__KTRACE_OPT(KDLL, Kern::Printf("Spurious import"));
sl@0
   296
				continue;
sl@0
   297
				}
sl@0
   298
sl@0
   299
			if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
sl@0
   300
				{
sl@0
   301
				__KTRACE_OPT(KDLL, Kern::Printf("Not EPOC Module"));
sl@0
   302
				continue;		// not an epoc DLL
sl@0
   303
				}
sl@0
   304
sl@0
   305
			r=GatherDependencies(imp_etm.iModule);
sl@0
   306
			if (r!=KErrNone)
sl@0
   307
				return r;
sl@0
   308
			}
sl@0
   309
		}
sl@0
   310
	__KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
sl@0
   311
	return KErrNone;
sl@0
   312
	}
sl@0
   313
sl@0
   314
#ifdef __VC32__
sl@0
   315
#pragma warning( disable : 4701 )   // disable warning C4701: local variable 'missingCaps' may be used without having been initialized
sl@0
   316
#endif
sl@0
   317
sl@0
   318
/**
sl@0
   319
Iterate through imports (if any) of each SModule in list. Populate iDepList with the indicies (in iModules)
sl@0
   320
of directly required modules. Checks that dependencies are legal under platsec.
sl@0
   321
@return KErrNone on success.
sl@0
   322
*/
sl@0
   323
TInt DModuleList::CompileDepLists()
sl@0
   324
	{
sl@0
   325
	__KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::CompileDepLists"));
sl@0
   326
	TInt result=KErrNone;
sl@0
   327
	TInt c=iModules.Count();
sl@0
   328
	SModule* pM=(SModule*)&iModules[0];
sl@0
   329
	SModule* pE=pM+c;
sl@0
   330
	for (; pM<pE; ++pM)
sl@0
   331
		{
sl@0
   332
		pM->iDepList=(TInt*)Kern::Alloc(c*sizeof(TInt));
sl@0
   333
		if (!pM->iDepList)
sl@0
   334
			return KErrNoMemory;
sl@0
   335
		memset(pM->iDepList, 0xff, c*sizeof(TInt));
sl@0
   336
		Emulator::TModule etm((HINSTANCE)pM->iModuleHandle);
sl@0
   337
		const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
sl@0
   338
		__KTRACE_OPT(KDLL, Kern::Printf("Module %08x, imports=%08x flags=%08x", pM->iModuleHandle, imports, pM->iFlags));
sl@0
   339
		if (!imports || (pM->iFlags&EFlagAlwaysLoaded))
sl@0
   340
			continue;
sl@0
   341
sl@0
   342
		const SCapabilitySet& cap = pM->iS.iCaps;
sl@0
   343
		const SCapabilitySet& disabledCaps=*(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
sl@0
   344
sl@0
   345
		TInt* pI=pM->iDepList;
sl@0
   346
		for (; imports->Characteristics; ++imports )
sl@0
   347
			{
sl@0
   348
			Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
sl@0
   349
sl@0
   350
			if (!imp_etm.IsValid())
sl@0
   351
				continue;		// spurious import
sl@0
   352
sl@0
   353
			if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
sl@0
   354
				continue;		// not an epoc DLL
sl@0
   355
sl@0
   356
			TInt ix=Find((TInt)imp_etm.iModule);
sl@0
   357
			__ASSERT_ALWAYS(ix>=0, MM::Panic(MM::ECompileDepLists));
sl@0
   358
			*pI++=ix;
sl@0
   359
			__KTRACE_OPT(KDLL, Kern::Printf("Depends on %08x, ix=%d", imp_etm.iModule, ix));
sl@0
   360
sl@0
   361
			const SModule& dep = iModules[ix];
sl@0
   362
			
sl@0
   363
			SCapabilitySet missingCaps;
sl@0
   364
			SCapabilitySet depCaps = dep.iS.iCaps;
sl@0
   365
			TUint32 checkFail = 0;
sl@0
   366
			for (TInt i=0; i<SCapabilitySet::ENCapW; ++i)
sl@0
   367
				{
sl@0
   368
				depCaps[i] = dep.iS.iCaps[i]|disabledCaps[i];
sl@0
   369
				TUint32 missing = cap[i] & ~depCaps[i];
sl@0
   370
				missingCaps[i] = missing;
sl@0
   371
				checkFail |= missing;
sl@0
   372
				}
sl@0
   373
sl@0
   374
			__KTRACE_OPT(KDLL, Kern::Printf("Cap=%08x %08x, DepCap=%08x %08x", cap[1], cap[0], depCaps[1], depCaps[0]));
sl@0
   375
sl@0
   376
			if (checkFail)
sl@0
   377
				{
sl@0
   378
				TUint8	mainBuf8[MAX_PATH];
sl@0
   379
				TInt	mainlen;
sl@0
   380
				{
sl@0
   381
				TUint16 mainBuf[MAX_PATH];
sl@0
   382
				mainlen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(pM->iModuleHandle),(LPWSTR)mainBuf);
sl@0
   383
				TruncToNarrow(mainBuf8, mainBuf, mainlen);
sl@0
   384
				}
sl@0
   385
				TPtrC mainp(mainBuf8,mainlen);
sl@0
   386
				TInt ix=mainp.LocateReverse('\\');
sl@0
   387
				if (ix>=0)
sl@0
   388
					mainp.Set(mainp.Mid(ix+1));
sl@0
   389
				if (mainp.Length() && mainp[mainp.Length()-1]==')' && (ix=mainp.LocateReverse('('))>=0)
sl@0
   390
					mainp.Set(mainp.Left(ix));
sl@0
   391
sl@0
   392
				TUint8	depBuf8[MAX_PATH];
sl@0
   393
				TInt	deplen;
sl@0
   394
				{
sl@0
   395
				TUint16 depBuf[MAX_PATH];
sl@0
   396
				deplen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(dep.iModuleHandle),(LPWSTR)depBuf);
sl@0
   397
				TruncToNarrow(depBuf8, depBuf, deplen);
sl@0
   398
				}
sl@0
   399
				TPtrC depp(depBuf8,deplen);
sl@0
   400
				if ((ix=depp.LocateReverse('\\'))>=0)
sl@0
   401
					depp.Set(depp.Mid(ix+1));
sl@0
   402
#ifndef __REMOVE_PLATSEC_DIAGNOSTICS__
sl@0
   403
				TInt r = PlatSec::LoaderCapabilityViolation(mainp, depp, missingCaps);
sl@0
   404
#else //__REMOVE_PLATSEC_DIAGNOSTICS__
sl@0
   405
				TInt r = PlatSec::EmitDiagnostic();
sl@0
   406
#endif // !__REMOVE_PLATSEC_DIAGNOSTICS__
sl@0
   407
				if(r!=KErrNone)
sl@0
   408
					result=r;
sl@0
   409
				}
sl@0
   410
			}
sl@0
   411
		}
sl@0
   412
	return result;
sl@0
   413
	}
sl@0
   414
sl@0
   415
#ifdef __VC32__
sl@0
   416
#pragma warning( default : 4701 )   // enable warning C4701: local variable 'missingCaps' may be used without having been initialized
sl@0
   417
#endif
sl@0
   418
sl@0
   419
void DModuleList::SetFlags()
sl@0
   420
	{
sl@0
   421
	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::SetFlags"));
sl@0
   422
	TInt c=iModules.Count();
sl@0
   423
	SModule* pM=(SModule*)&iModules[0];
sl@0
   424
	SModule* pE=pM+c;
sl@0
   425
	for (; pM<pE; ++pM)
sl@0
   426
		{
sl@0
   427
		SModule* pM2=(SModule*)&iModules[0];
sl@0
   428
		for (; pM2<pE; ++pM2)
sl@0
   429
			pM2->iFlags &= ~EFlagMark;
sl@0
   430
		TUint32 flags=Flags(pM);
sl@0
   431
		if (flags & EFlagData)
sl@0
   432
			pM->iFlags|=EFlagDataPresent;
sl@0
   433
		if (flags & EFlagExe)
sl@0
   434
			pM->iFlags|=EFlagExeInTree;
sl@0
   435
		__KTRACE_OPT(KDLL, Kern::Printf("Module %08x Flags=%08x", pM->iModuleHandle, pM->iFlags));
sl@0
   436
		}
sl@0
   437
	pM=(SModule*)&iModules[0];
sl@0
   438
	for (; pM<pE; ++pM)
sl@0
   439
		{	
sl@0
   440
		TInt dc=0;
sl@0
   441
		const TInt* pI=pM->iDepList;
sl@0
   442
		const TInt* pIE=pI+c;
sl@0
   443
		while (pI<pIE)
sl@0
   444
			{
sl@0
   445
			TInt ix=*pI++;
sl@0
   446
			if (ix<0)
sl@0
   447
				break;
sl@0
   448
			TUint32 mflags=iModules[ix].iFlags;
sl@0
   449
			if ( (mflags&(EFlagDataPresent|EFlagExeInTree)) && !(mflags&EFlagAlwaysLoaded))
sl@0
   450
				++dc;
sl@0
   451
			}
sl@0
   452
		pM->iDepCount=dc;
sl@0
   453
		__KTRACE_OPT(KDLL, Kern::Printf("Module %08x DepCount=%d", pM->iModuleHandle, pM->iDepCount));
sl@0
   454
		}
sl@0
   455
	}
sl@0
   456
sl@0
   457
TUint32 DModuleList::Flags(SModule* aM)
sl@0
   458
	{
sl@0
   459
	TUint32 flags=aM->iFlags;
sl@0
   460
	__KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::Flags %08x", aM->iModuleHandle));
sl@0
   461
	if ((aM->iFlags & EFlagMark)==0)
sl@0
   462
		{
sl@0
   463
		aM->iFlags |= EFlagMark;
sl@0
   464
		const TInt* pI=aM->iDepList;
sl@0
   465
		const TInt* pE=pI+iModules.Count();
sl@0
   466
		while (pI<pE)
sl@0
   467
			{
sl@0
   468
			TInt ix=*pI++;
sl@0
   469
			if (ix<0)
sl@0
   470
				break;
sl@0
   471
			TUint32 mflags=Flags(&iModules[ix]);
sl@0
   472
			if (mflags&EFlagExe)
sl@0
   473
				mflags&=~EFlagData;
sl@0
   474
			flags |= mflags;
sl@0
   475
			}
sl@0
   476
		}
sl@0
   477
	__KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::Flags %08x = %08x", aM->iModuleHandle, flags));
sl@0
   478
	return flags;
sl@0
   479
	}
sl@0
   480
sl@0
   481
TInt DModuleList::LoadDependencies()
sl@0
   482
	{
sl@0
   483
	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LoadDependencies"));
sl@0
   484
	TInt c=iModules.Count();
sl@0
   485
	SModule* pM=(SModule*)&iModules[0];
sl@0
   486
	SModule* pE=pM+c;
sl@0
   487
	for (; pM<pE; ++pM)
sl@0
   488
		{
sl@0
   489
		DWin32CodeSeg* pS;
sl@0
   490
		TUint32 flags=pM->iFlags;
sl@0
   491
		__KTRACE_OPT(KDLL, Kern::Printf("ModuleHandle %08x flags %08x", pM->iModuleHandle, flags));
sl@0
   492
		if (!(flags & (EFlagDataPresent|EFlagExeInTree)) || (flags&EFlagAlwaysLoaded))
sl@0
   493
			continue;
sl@0
   494
		SWin32Module w32m;
sl@0
   495
		w32m.iWin32ModuleHandle=(TLinAddr)pM->iModuleHandle;
sl@0
   496
		w32m.iCodeSeg=NULL;
sl@0
   497
		TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
sl@0
   498
		__KTRACE_OPT(KDLL, Kern::Printf("GlobalIndex=%d", ix));
sl@0
   499
		if (ix<0 && (flags & EFlagExe))
sl@0
   500
			return KErrNotSupported;	// we never implicitly load an EXE
sl@0
   501
		if (ix>=0)
sl@0
   502
			{
sl@0
   503
			pS=MM::Win32Modules[ix].iCodeSeg;
sl@0
   504
			__KTRACE_OPT(KDLL, Kern::Printf("Already loaded; CSEG=%08x %C", pS, pS));
sl@0
   505
			if (pS==iMain)
sl@0
   506
				{
sl@0
   507
				pS->iDepCount=pM->iDepCount;
sl@0
   508
				if (pS->iDepCount)
sl@0
   509
					{
sl@0
   510
					pS->iDeps=(DCodeSeg**)Kern::AllocZ(pS->iDepCount*sizeof(DCodeSeg*));
sl@0
   511
					if (!pS->iDeps)
sl@0
   512
						return KErrNoMemory;
sl@0
   513
					}
sl@0
   514
				}
sl@0
   515
			else
sl@0
   516
				{
sl@0
   517
				if (!(pS->iMark & DCodeSeg::EMarkLdr))
sl@0
   518
					{
sl@0
   519
					pS->iMark |= DCodeSeg::EMarkLdr;
sl@0
   520
					pS->CheckedOpen();
sl@0
   521
					}
sl@0
   522
				pM->iFlags|=EFlagAlreadyLoaded;
sl@0
   523
				}
sl@0
   524
			pM->iCodeSeg=pS;
sl@0
   525
			continue;
sl@0
   526
			}
sl@0
   527
		__KTRACE_OPT(KDLL, Kern::Printf("Create new, depcount=%d", pM->iDepCount));
sl@0
   528
		pS=new DWin32CodeSeg;
sl@0
   529
		if (!pS)
sl@0
   530
			return KErrNoMemory;
sl@0
   531
		TInt r=pS->CreateAlreadyLoaded((HMODULE)pM->iModuleHandle, pM->iDepCount);
sl@0
   532
		if (r!=KErrNone)
sl@0
   533
			{
sl@0
   534
			delete pS;
sl@0
   535
			return r;
sl@0
   536
			}
sl@0
   537
		pM->iCodeSeg=pS;
sl@0
   538
		pS->iS = pM->iS;
sl@0
   539
		pS->iModuleVersion = pM->iModuleVersion;
sl@0
   540
		if (iMain->iAttr & ECodeSegAttKernel)
sl@0
   541
			pS->iAttr |= ECodeSegAttKernel;
sl@0
   542
		if (flags & EFlagData)
sl@0
   543
			{
sl@0
   544
			pS->iMark |= DCodeSeg::EMarkData|DCodeSeg::EMarkDataPresent;
sl@0
   545
			if (!(flags&EFlagExe))
sl@0
   546
				pS->iMark |= DCodeSeg::EMarkDataInit;
sl@0
   547
			}
sl@0
   548
		if ( (flags & EFlagData) || ((flags&(EFlagExe|EFlagExeInTree))==EFlagExeInTree) )
sl@0
   549
			{
sl@0
   550
			if (iAttachProcess)
sl@0
   551
				{
sl@0
   552
				pS->iExeCodeSeg = iAttachProcess->CodeSeg();
sl@0
   553
				pS->SetAttachProcess(iAttachProcess);
sl@0
   554
				}
sl@0
   555
			}
sl@0
   556
		}
sl@0
   557
	return KErrNone;
sl@0
   558
	}
sl@0
   559
sl@0
   560
void DModuleList::LinkDependencies()
sl@0
   561
	{
sl@0
   562
	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LinkDependencies"));
sl@0
   563
	TInt c=iModules.Count();
sl@0
   564
	SModule* pM=(SModule*)&iModules[0];
sl@0
   565
	SModule* pE=pM+c;
sl@0
   566
	for (; pM<pE; ++pM)
sl@0
   567
		{
sl@0
   568
		DWin32CodeSeg* pS=pM->iCodeSeg;
sl@0
   569
		if (!pS || (pM->iFlags&EFlagAlreadyLoaded))
sl@0
   570
			continue;
sl@0
   571
		const TInt* pI=pM->iDepList;
sl@0
   572
		const TInt* pIE=pI+c;
sl@0
   573
		while (pI<pIE)
sl@0
   574
			{
sl@0
   575
			TInt ix=*pI++;
sl@0
   576
			if (ix<0)
sl@0
   577
				break;
sl@0
   578
			DWin32CodeSeg* pD=iModules[ix].iCodeSeg;
sl@0
   579
			if (pD)
sl@0
   580
				pS->iDeps[pS->iNextDep++]=pD;
sl@0
   581
			}
sl@0
   582
		}
sl@0
   583
	pM=(SModule*)&iModules[0];
sl@0
   584
	}
sl@0
   585
sl@0
   586
TInt DModuleList::Loaded()
sl@0
   587
	{
sl@0
   588
	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::Loaded()"));
sl@0
   589
	TInt c=iModules.Count();
sl@0
   590
	SModule* pM=(SModule*)&iModules[0];
sl@0
   591
	SModule* pE=pM+c;
sl@0
   592
	TInt r=KErrNone;
sl@0
   593
	for (; pM<pE && r==KErrNone; ++pM)
sl@0
   594
		{
sl@0
   595
		DWin32CodeSeg* pS=pM->iCodeSeg;
sl@0
   596
		if (pS && pS!=iMain)
sl@0
   597
			{
sl@0
   598
			pS->FinaliseRecursiveFlags();
sl@0
   599
			pS->iMark |= DCodeSeg::EMarkLoaded;
sl@0
   600
			}
sl@0
   601
		}
sl@0
   602
	if (r==KErrNone)
sl@0
   603
		{
sl@0
   604
		pM=(SModule*)&iModules[0];
sl@0
   605
		for (; pM<pE; ++pM)
sl@0
   606
			pM->iCodeSeg=NULL;	// cleanup will occur by EMarkLdr if needed
sl@0
   607
		}
sl@0
   608
	return r;
sl@0
   609
	}
sl@0
   610
sl@0
   611
TInt MakeDll(HANDLE aFile)
sl@0
   612
	{
sl@0
   613
	IMAGE_DOS_HEADER dosh;
sl@0
   614
	DWORD bytes;
sl@0
   615
	ReadFile(aFile, &dosh, sizeof(dosh), &bytes, NULL);
sl@0
   616
	if ( IMAGE_DOS_SIGNATURE != dosh.e_magic )
sl@0
   617
		return KErrArgument;
sl@0
   618
	if (dosh.e_lfarlc < sizeof(dosh))
sl@0
   619
		return KErrArgument;
sl@0
   620
	SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
sl@0
   621
	IMAGE_NT_HEADERS32 peh;
sl@0
   622
	ReadFile(aFile, &peh, sizeof(peh), &bytes, NULL);
sl@0
   623
    if ( peh.Signature != IMAGE_NT_SIGNATURE )
sl@0
   624
		return KErrArgument;
sl@0
   625
sl@0
   626
	peh.FileHeader.Characteristics |= IMAGE_FILE_DLL;
sl@0
   627
	peh.OptionalHeader.AddressOfEntryPoint = 0;
sl@0
   628
	SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
sl@0
   629
	WriteFile(aFile, &peh, sizeof(peh), &bytes, NULL);
sl@0
   630
	return KErrNone;
sl@0
   631
	}
sl@0
   632
sl@0
   633
wchar_t* TempModuleName(const wchar_t* aExe)
sl@0
   634
	{
sl@0
   635
	static TInt ModuleGeneration = 0;
sl@0
   636
	static TInt Time = 0;
sl@0
   637
sl@0
   638
	WCHAR ex_[KMaxFileName + 1];
sl@0
   639
sl@0
   640
	if (!Time)
sl@0
   641
		{
sl@0
   642
		SYSTEMTIME st;
sl@0
   643
		GetSystemTime(&st);
sl@0
   644
		Time = st.wSecond + st.wMinute*60 + st.wHour*3600;
sl@0
   645
		}
sl@0
   646
sl@0
   647
	const char* imagePath = Property::GetString("EmulatorImagePath");
sl@0
   648
	WCHAR* p = ex_;
sl@0
   649
	while ((*p++ = *imagePath++) != 0)
sl@0
   650
		;
sl@0
   651
	wcscpy(p-1, wcsrchr(aExe, '\\') + 1);
sl@0
   652
	p = ex_ + wcslen(ex_);
sl@0
   653
	*p++ = '(';
sl@0
   654
	_itow(Time, p, 36);
sl@0
   655
	p += wcslen(p);
sl@0
   656
	*p++ = '-';
sl@0
   657
	_itow(ModuleGeneration++, p, 10);
sl@0
   658
	p += wcslen(p);
sl@0
   659
	*p++ = ')';
sl@0
   660
	*p++ = '\0';
sl@0
   661
	wchar_t* file = (wchar_t*)Kern::Alloc((p-ex_)*sizeof(WCHAR));
sl@0
   662
	if (file)
sl@0
   663
		wcscpy(file, ex_);
sl@0
   664
	return file;
sl@0
   665
	}
sl@0
   666
sl@0
   667
DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&)
sl@0
   668
//
sl@0
   669
// Create a new instance of this class.
sl@0
   670
//
sl@0
   671
	{
sl@0
   672
sl@0
   673
	__KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg"));
sl@0
   674
	return new DWin32CodeSeg;
sl@0
   675
	}
sl@0
   676
sl@0
   677
DWin32CodeSeg::DWin32CodeSeg()
sl@0
   678
//
sl@0
   679
// Constructor
sl@0
   680
//
sl@0
   681
	{
sl@0
   682
	}
sl@0
   683
sl@0
   684
DWin32CodeSeg::~DWin32CodeSeg()
sl@0
   685
//
sl@0
   686
// Destructor
sl@0
   687
//
sl@0
   688
	{
sl@0
   689
	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Destruct %C", this));
sl@0
   690
	DBase::Delete(iModuleList);
sl@0
   691
	if (iWinInstance)
sl@0
   692
		{
sl@0
   693
		DCodeSeg::Wait();
sl@0
   694
		SWin32Module w32m;
sl@0
   695
		w32m.iWin32ModuleHandle=(TLinAddr)iModuleHandle;
sl@0
   696
		w32m.iCodeSeg=NULL;
sl@0
   697
		TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
sl@0
   698
		if (ix>=0)
sl@0
   699
			{
sl@0
   700
			if (iAlwaysLoaded)
sl@0
   701
				MM::Win32Modules[ix].iCodeSeg=NULL;
sl@0
   702
			else
sl@0
   703
				MM::Win32Modules.Remove(ix);
sl@0
   704
			}
sl@0
   705
		// Kernel process has to be told to unmap code seg to work round
sl@0
   706
		// a problem where failed driver code seg is not unmapped before delete
sl@0
   707
		K::TheKernelProcess->UnmapCodeSeg(this);
sl@0
   708
		Emulator::FreeLibrary(iWinInstance);
sl@0
   709
		DCodeSeg::Signal();
sl@0
   710
		}
sl@0
   711
	if (iModuleFile)
sl@0
   712
		{
sl@0
   713
		Emulator::DeleteFile(iModuleFile);
sl@0
   714
		Kern::Free(iModuleFile);
sl@0
   715
		}
sl@0
   716
	Kern::Free(iDataCopy);
sl@0
   717
	DCodeSeg::Destruct();
sl@0
   718
	}
sl@0
   719
sl@0
   720
TInt DWin32CodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
sl@0
   721
	{
sl@0
   722
	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::DoCreate %C proc %O", this, aProcess));
sl@0
   723
sl@0
   724
	TBool exe=(iExeCodeSeg==this);
sl@0
   725
	if (exe && (iAttr&ECodeSegAttKernel))
sl@0
   726
		{
sl@0
   727
		// loading EKERN.EXE
sl@0
   728
		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN"));
sl@0
   729
		TUint16 fileNameW[KMaxFileName];
sl@0
   730
		ExpandToWide(fileNameW, iFileName->Ptr(), iFileName->Length());
sl@0
   731
		fileNameW[iFileName->Length()] = '\0';
sl@0
   732
		iWinInstance = Emulator::LoadLibrary((LPCWSTR)fileNameW);
sl@0
   733
		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN %08x", iWinInstance));
sl@0
   734
		if (!iWinInstance)
sl@0
   735
			return KErrGeneral;
sl@0
   736
		if (aInfo.iTotalDataSize)
sl@0
   737
			iMark|=EMarkData|EMarkDataPresent;
sl@0
   738
		KernelCodeSeg=this;
sl@0
   739
		KernelModuleHandle=Emulator::GetModuleHandle((LPCWSTR)fileNameW);
sl@0
   740
		return RegisterCodeSeg(KernelModuleHandle);
sl@0
   741
		}
sl@0
   742
	TWin32Filename w32fn(*iFileName);
sl@0
   743
	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : w32fn=%S",iFileName))
sl@0
   744
	DWin32Process* p=(DWin32Process*)aProcess;
sl@0
   745
	TInt r=KErrNone;
sl@0
   746
	DCodeSeg::Wait();
sl@0
   747
	HMODULE h = Emulator::GetModuleHandle(w32fn);
sl@0
   748
	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : h=%08x exe=%08x",h,exe));
sl@0
   749
	if (h && exe)
sl@0
   750
		{
sl@0
   751
		if (h == GetModuleHandleA(NULL))
sl@0
   752
			{
sl@0
   753
			// This was the executable that was used to run the emulator
sl@0
   754
			// so all relocations will be valid and we can use it
sl@0
   755
			__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : initial exe"));
sl@0
   756
			if (BootComplete)
sl@0
   757
				goto makecopy;	// we can only do this once however
sl@0
   758
			iWinInstance = Emulator::LoadLibrary(w32fn);
sl@0
   759
			BootComplete = ETrue;
sl@0
   760
			}
sl@0
   761
		else
sl@0
   762
			r=KErrAlreadyExists;		// can't load same EXEXP twice
sl@0
   763
		}
sl@0
   764
	else if (h)
sl@0
   765
		{
sl@0
   766
		// Already loaded DLL
sl@0
   767
		// Code segment doesn't exist so create it
sl@0
   768
		__KTRACE_OPT(KDLL,Kern::Printf("Already loaded, module %08x",h));
sl@0
   769
		iWinInstance = Emulator::LoadLibrary(w32fn);
sl@0
   770
		}
sl@0
   771
	else if (iAttr & ECodeSegAttHDll)
sl@0
   772
		{
sl@0
   773
		// EXE with exports (EXEXP target) - can only have one instance
sl@0
   774
		// or DLL not already loaded
sl@0
   775
		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EXEXP or new DLL"));
sl@0
   776
		iWinInstance = Emulator::LoadLibrary(w32fn);
sl@0
   777
		if (iWinInstance)
sl@0
   778
			h=Emulator::GetModuleHandle(w32fn);
sl@0
   779
		}
sl@0
   780
	else
sl@0
   781
		{
sl@0
   782
		// EXE with no exports. In order that multiple instances of the EXE may be run,
sl@0
   783
		// we make a copy of the EXE file to a name which is unique across instances,
sl@0
   784
		// set the DLL flag and load it as a DLL.
sl@0
   785
makecopy:
sl@0
   786
		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : MakeCopy"));
sl@0
   787
		h=0;
sl@0
   788
		iModuleFile = TempModuleName(w32fn);
sl@0
   789
		if (!iModuleFile)
sl@0
   790
			r=KErrNoMemory;
sl@0
   791
		else if (Emulator::CopyFile(w32fn,iModuleFile,FALSE))
sl@0
   792
			{
sl@0
   793
			DWORD fattr = Emulator::GetFileAttributes(iModuleFile);
sl@0
   794
			if (fattr != 0xffffffff && Emulator::SetFileAttributes(iModuleFile, fattr & ~FILE_ATTRIBUTE_READONLY))
sl@0
   795
				{
sl@0
   796
				HANDLE f = Emulator::CreateFile(iModuleFile,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL);
sl@0
   797
				if (INVALID_HANDLE_VALUE != f)
sl@0
   798
					{
sl@0
   799
					r = MakeDll(f);
sl@0
   800
					CloseHandle(f);
sl@0
   801
					if (r==KErrNone)
sl@0
   802
						{
sl@0
   803
						iWinInstance = Emulator::LoadLibrary(iModuleFile);
sl@0
   804
						if (iWinInstance)
sl@0
   805
							h=Emulator::GetModuleHandle(iModuleFile);
sl@0
   806
						}
sl@0
   807
					}
sl@0
   808
				}
sl@0
   809
			}
sl@0
   810
		}
sl@0
   811
	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d iWinInstance=%08x",__LINE__,r,iWinInstance));
sl@0
   812
	if (r==KErrNone && !iWinInstance)
sl@0
   813
		r=Emulator::LastError();
sl@0
   814
	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d",__LINE__,r));
sl@0
   815
	if (r==KErrNone)
sl@0
   816
		{
sl@0
   817
		const char* entry_name = exe ? "_E32Startup" : "_E32Dll" ;
sl@0
   818
		aInfo.iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, entry_name);
sl@0
   819
		if (!aInfo.iFileEntryPoint)
sl@0
   820
         {
sl@0
   821
			r=KErrNotSupported;
sl@0
   822
         }
sl@0
   823
		else
sl@0
   824
         {
sl@0
   825
			r=RegisterCodeSeg(h);
sl@0
   826
         }
sl@0
   827
sl@0
   828
		if (r == KErrNone)
sl@0
   829
         {
sl@0
   830
			r = CopyDataBss();
sl@0
   831
         }
sl@0
   832
		}
sl@0
   833
	if (r==KErrNone && aInfo.iTotalDataSize && !iAlwaysLoaded)
sl@0
   834
		{
sl@0
   835
		iMark|=EMarkData|EMarkDataPresent;
sl@0
   836
		if (!exe)
sl@0
   837
			iMark|=EMarkDataInit;
sl@0
   838
		}
sl@0
   839
sl@0
   840
	if (r==KErrNone)
sl@0
   841
		r=ProcessImports(p);
sl@0
   842
	__KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
sl@0
   843
	DCodeSeg::Signal();
sl@0
   844
	return r;
sl@0
   845
	}
sl@0
   846
sl@0
   847
TInt DWin32CodeSeg::RegisterCodeSeg(HMODULE aModule)
sl@0
   848
	{
sl@0
   849
	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %C RegisterCodeSeg(%08x)", this, aModule));
sl@0
   850
	Emulator::TModule etm(aModule);
sl@0
   851
	const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
sl@0
   852
	iRunAddress = (TLinAddr)aModule;
sl@0
   853
	iSize = nth->OptionalHeader.SizeOfImage;
sl@0
   854
	SWin32Module w32m;
sl@0
   855
	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
sl@0
   856
	w32m.iCodeSeg=this;
sl@0
   857
	TInt r=KErrNone;
sl@0
   858
	TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
sl@0
   859
	if (ix>=0)
sl@0
   860
		{
sl@0
   861
		SWin32Module& wmr=MM::Win32Modules[ix];
sl@0
   862
		__ASSERT_ALWAYS(!wmr.iCodeSeg, MM::Panic(MM::EInvalidSharedModule));
sl@0
   863
		wmr.iCodeSeg=this;
sl@0
   864
		iAlwaysLoaded=ETrue;
sl@0
   865
		}
sl@0
   866
	else
sl@0
   867
		r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
sl@0
   868
	if (r==KErrNone)
sl@0
   869
		{
sl@0
   870
		iModuleHandle=aModule;
sl@0
   871
		iCodeSegId=++MM::NextCodeSegId;
sl@0
   872
		}
sl@0
   873
	return r;
sl@0
   874
	}
sl@0
   875
sl@0
   876
TInt DWin32CodeSeg::CreateAlreadyLoaded(HMODULE aModule, TInt aDepCount)
sl@0
   877
	{
sl@0
   878
	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %08x CreateAlreadyLoaded(%08x,%d)", this, aModule, aDepCount));
sl@0
   879
	Emulator::TModule etm(aModule);
sl@0
   880
	etm.GetUids(iUids);
sl@0
   881
	TInt32 uid1=iUids.iUid[0].iUid;
sl@0
   882
	if (uid1!=KDynamicLibraryUidValue)	// only implicitly load DLLs
sl@0
   883
		return KErrNotSupported;
sl@0
   884
	
sl@0
   885
	WCHAR name[MAX_PATH+1];
sl@0
   886
	TInt r=Emulator::GetModuleFileName(aModule, name);
sl@0
   887
	if (!r)
sl@0
   888
		return Emulator::LastError();
sl@0
   889
	TUint8 name8[MAX_PATH+1];
sl@0
   890
	TruncToNarrow(name8,(const TUint16*)name,-1);
sl@0
   891
sl@0
   892
   //SL:
sl@0
   893
   __KTRACE_OPT(KDLL, Kern::Printf("Loading library %s", name8));
sl@0
   894
sl@0
   895
	TPtrC fpptr((const TText*)name8);
sl@0
   896
	TInt slash=fpptr.LocateReverse('\\');
sl@0
   897
	TPtrC nptr=fpptr.Mid(slash+1);
sl@0
   898
	iFileName=HBuf::New(nptr);
sl@0
   899
	if (!iFileName)
sl@0
   900
		return KErrNoMemory;
sl@0
   901
	iRootName.Set(*iFileName);
sl@0
   902
	iExtOffset = iFileName->LocateReverse('.');
sl@0
   903
	if (iExtOffset==KErrNotFound)
sl@0
   904
		iExtOffset = iFileName->Length();
sl@0
   905
	iModuleVersion = 0x00010000u;
sl@0
   906
	iDepCount=aDepCount;
sl@0
   907
	if (iDepCount)
sl@0
   908
		{
sl@0
   909
		iDeps=(DCodeSeg**)Kern::AllocZ(iDepCount*sizeof(DCodeSeg*));
sl@0
   910
		if (!iDeps)
sl@0
   911
			return KErrNoMemory;
sl@0
   912
		}
sl@0
   913
	iWinInstance = Emulator::LoadLibrary(name);
sl@0
   914
	if (!iWinInstance)
sl@0
   915
		return Emulator::LastError();
sl@0
   916
	iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, "_E32Dll");
sl@0
   917
	if (!iFileEntryPoint)
sl@0
   918
		return KErrNotSupported;
sl@0
   919
	iEntryPtVeneer = iFileEntryPoint;
sl@0
   920
	r=RegisterCodeSeg(aModule);
sl@0
   921
	if (r == KErrNone)
sl@0
   922
		r = CopyDataBss();
sl@0
   923
	if (r == KErrNone)
sl@0
   924
		r = CodeSegsByName.InsertInOrderAllowRepeats(this, &CompareCodeSegsByName);
sl@0
   925
	if (r == KErrNone)
sl@0
   926
		r = CodeSegsByAddress.Add(this);
sl@0
   927
	if (r==KErrNone)
sl@0
   928
		{
sl@0
   929
		GlobalList.Add(&iLink);
sl@0
   930
		iAsyncDeleteNext=this;
sl@0
   931
		}
sl@0
   932
	__KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
sl@0
   933
	return r;
sl@0
   934
	}
sl@0
   935
sl@0
   936
TInt DWin32CodeSeg::CopyDataBss()
sl@0
   937
	{
sl@0
   938
	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::CopyDataBss()"));
sl@0
   939
sl@0
   940
	Emulator::TModule etm(iModuleHandle);
sl@0
   941
	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
sl@0
   942
	if (!(hdr->iFlags & KEmulatorImageFlagAllowDllData))
sl@0
   943
		return KErrNone;
sl@0
   944
	const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
sl@0
   945
	const IMAGE_SECTION_HEADER* bss=etm.SectionHeader(KWin32SectionName_EpocBss);
sl@0
   946
	if (data)
sl@0
   947
		{
sl@0
   948
		iRealDataSize = data->Misc.VirtualSize;
sl@0
   949
		iDataDest = (TLinAddr)etm.Translate(data->VirtualAddress);
sl@0
   950
		iDataCopy = Kern::Alloc(iRealDataSize);
sl@0
   951
		if (!iDataCopy)
sl@0
   952
			return KErrNoMemory;
sl@0
   953
		memcpy(iDataCopy, (const TAny*)iDataDest, iRealDataSize);
sl@0
   954
		}
sl@0
   955
	if (bss)
sl@0
   956
		{
sl@0
   957
		iRealBssSize = bss->Misc.VirtualSize;
sl@0
   958
		iBssDest = (TLinAddr)etm.Translate(bss->VirtualAddress);
sl@0
   959
		}
sl@0
   960
	return KErrNone;
sl@0
   961
	}
sl@0
   962
sl@0
   963
TInt DWin32CodeSeg::ProcessImports(DProcess* aProcess)
sl@0
   964
	{
sl@0
   965
	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::ProcessImports(%O)", aProcess));
sl@0
   966
	iModuleList=new DModuleList(this, aProcess);
sl@0
   967
	if (!iModuleList)
sl@0
   968
		return KErrNoMemory;
sl@0
   969
	TInt r=iModuleList->GatherDependencies(iModuleHandle);
sl@0
   970
	if (r!=KErrNone)
sl@0
   971
		return r;
sl@0
   972
	TInt ix=iModuleList->Find((TInt)iModuleHandle);
sl@0
   973
	DModuleList::SModule& mm=iModuleList->iModules[ix];
sl@0
   974
	r=iModuleList->CompileDepLists();
sl@0
   975
	if (r==KErrNone)
sl@0
   976
		{
sl@0
   977
		iModuleList->SetFlags();
sl@0
   978
		r=iModuleList->LoadDependencies();
sl@0
   979
		if (r==KErrNone)
sl@0
   980
			{
sl@0
   981
			if ((mm.iFlags&(DModuleList::EFlagDataPresent|DModuleList::EFlagExeInTree)) && !(mm.iFlags&DModuleList::EFlagAlwaysLoaded))
sl@0
   982
				{
sl@0
   983
				if (aProcess)
sl@0
   984
					{
sl@0
   985
					iExeCodeSeg=aProcess->CodeSeg();
sl@0
   986
					SetAttachProcess(aProcess);
sl@0
   987
					}
sl@0
   988
				}
sl@0
   989
			iModuleList->LinkDependencies();
sl@0
   990
			}
sl@0
   991
		}
sl@0
   992
	return r;
sl@0
   993
	}
sl@0
   994
sl@0
   995
TInt DWin32CodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
sl@0
   996
	{
sl@0
   997
	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded()"));
sl@0
   998
	TInt r=KErrNone;
sl@0
   999
	if (iModuleList)
sl@0
  1000
		{
sl@0
  1001
		r=iModuleList->Loaded();
sl@0
  1002
		if (r==KErrNone)
sl@0
  1003
			{
sl@0
  1004
			DBase::Delete(iModuleList);
sl@0
  1005
			iModuleList=NULL;
sl@0
  1006
			}
sl@0
  1007
		}
sl@0
  1008
	if (r==KErrNone)
sl@0
  1009
		r=DCodeSeg::Loaded(aInfo);
sl@0
  1010
	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded() - %d", r));
sl@0
  1011
	return r;
sl@0
  1012
	}
sl@0
  1013
sl@0
  1014
void DWin32CodeSeg::ReadExportDir(TUint32*)
sl@0
  1015
	{
sl@0
  1016
	// not needed
sl@0
  1017
	}
sl@0
  1018
sl@0
  1019
TBool DWin32CodeSeg::FindCheck(DProcess* /*aProcess*/)
sl@0
  1020
	{
sl@0
  1021
	// We never create multiple copies of the same code segment,
sl@0
  1022
	// so if code segment exists, allow it to be found.
sl@0
  1023
	// CodeSegOpen will fail if it is incompatible.
sl@0
  1024
	return ETrue;
sl@0
  1025
	}
sl@0
  1026
sl@0
  1027
TBool DWin32CodeSeg::OpenCheck(DProcess* aProcess)
sl@0
  1028
	{
sl@0
  1029
	__KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
sl@0
  1030
	if (!aProcess)
sl@0
  1031
		return EFalse;	// never reuse EXE code segments
sl@0
  1032
	return ETrue;
sl@0
  1033
	}
sl@0
  1034
sl@0
  1035
TLibraryFunction DWin32CodeSeg::Lookup(TInt aOrdinal)
sl@0
  1036
//
sl@0
  1037
// Find an exported function by ordinal
sl@0
  1038
//
sl@0
  1039
	{
sl@0
  1040
	TLibraryFunction f = NULL;
sl@0
  1041
	if (aOrdinal != 0)
sl@0
  1042
		{
sl@0
  1043
			
sl@0
  1044
		f = (TLibraryFunction)Emulator::GetProcAddress(iWinInstance, (const char *)aOrdinal);
sl@0
  1045
		if ((TLinAddr)f == iFileEntryPoint)
sl@0
  1046
			f = NULL;
sl@0
  1047
		}
sl@0
  1048
	else
sl@0
  1049
		{
sl@0
  1050
		// Find 0th Ordinal, which should be named symbol export data, from named data segment
sl@0
  1051
		Emulator::TModule etm(iModuleHandle);
sl@0
  1052
		f  = (TLibraryFunction)etm.Section(KWin32SectionName_NmdExpData);
sl@0
  1053
		}
sl@0
  1054
 	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Lookup(%d)->%08x",aOrdinal,f));
sl@0
  1055
	return f;
sl@0
  1056
	}
sl@0
  1057
sl@0
  1058
DCodeSeg* DCodeSeg::FindRomCode(const TAny*)
sl@0
  1059
	{
sl@0
  1060
	// never used
sl@0
  1061
	return NULL;
sl@0
  1062
	}
sl@0
  1063
sl@0
  1064
void DWin32CodeSeg::InitData()
sl@0
  1065
	{
sl@0
  1066
	}
sl@0
  1067
sl@0
  1068
TInt DWin32CodeSeg::GetMemoryInfo(TModuleMemoryInfo&, DProcess*)
sl@0
  1069
	{
sl@0
  1070
	return KErrNotSupported;
sl@0
  1071
	}
sl@0
  1072
sl@0
  1073
void DWin32CodeSeg::Info(TCodeSegCreateInfo& aInfo)
sl@0
  1074
	{
sl@0
  1075
	Emulator::TModule etm(iModuleHandle);
sl@0
  1076
	const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
sl@0
  1077
	const IMAGE_EXPORT_DIRECTORY* exd=
sl@0
  1078
		(const IMAGE_EXPORT_DIRECTORY*)etm.Translate(nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
sl@0
  1079
	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
sl@0
  1080
	TBool isExe = hdr && hdr->iUids[0].iUid==KExecutableImageUidValue;
sl@0
  1081
	const IMAGE_SECTION_HEADER* text=etm.SectionHeader(KWin32SectionName_Text);
sl@0
  1082
	const IMAGE_SECTION_HEADER* rdata=etm.SectionHeader(KWin32SectionName_RData);
sl@0
  1083
	const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
sl@0
  1084
	if (!isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
sl@0
  1085
		data = NULL;
sl@0
  1086
	aInfo.iTextSize=text->Misc.VirtualSize;
sl@0
  1087
	aInfo.iCodeSize=text->Misc.VirtualSize;
sl@0
  1088
	if (rdata)
sl@0
  1089
		aInfo.iCodeSize+=rdata->Misc.VirtualSize;
sl@0
  1090
	aInfo.iDataSize=data ? (data->SizeOfRawData) : 0;
sl@0
  1091
	aInfo.iBssSize=data ? (data->Misc.VirtualSize-data->SizeOfRawData) : 0;
sl@0
  1092
	aInfo.iTotalDataSize=aInfo.iDataSize+aInfo.iBssSize;
sl@0
  1093
	aInfo.iExportDir=(TLinAddr)exd;
sl@0
  1094
	aInfo.iExportDirCount=exd ? exd->NumberOfFunctions : 0;
sl@0
  1095
	aInfo.iCodeLoadAddress=(TLinAddr)etm.Translate(text->VirtualAddress);
sl@0
  1096
	aInfo.iCodeRunAddress=aInfo.iCodeLoadAddress;
sl@0
  1097
	aInfo.iDataLoadAddress=data ? (TLinAddr)etm.Translate(data->VirtualAddress) : 0;
sl@0
  1098
	aInfo.iDataRunAddress=aInfo.iDataLoadAddress;
sl@0
  1099
	DCodeSeg::Info(aInfo);
sl@0
  1100
	}
sl@0
  1101
sl@0
  1102
TLinAddr DCodeSeg::ExceptionDescriptor()
sl@0
  1103
	{
sl@0
  1104
	return 0;	// not used on emulator
sl@0
  1105
	}
sl@0
  1106
sl@0
  1107
TInt MM::RegisterModule(HMODULE aModule)
sl@0
  1108
	{
sl@0
  1109
	__KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule %08x",aModule));
sl@0
  1110
	SWin32Module w32m;
sl@0
  1111
	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
sl@0
  1112
	w32m.iCodeSeg=NULL;
sl@0
  1113
	TInt r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
sl@0
  1114
	__KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule ret %d",r));
sl@0
  1115
	return r;
sl@0
  1116
	}
sl@0
  1117
sl@0
  1118
_LIT(KRomSysBin, "Z:\\sys\\bin");
sl@0
  1119
sl@0
  1120
// Massage file names returned for stuff in EPOCROOT\epoc32\release\wins\xxxx\
sl@0
  1121
// in order to make them appear to be in z:\system\libs
sl@0
  1122
void P::NormalizeExecutableFileName(TDes& a)
sl@0
  1123
	{
sl@0
  1124
	__KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName %lS", &a));
sl@0
  1125
	if (a.Length()<3 || a[1]!=':' || a[2]!='\\')
sl@0
  1126
		{
sl@0
  1127
		// don't have a drive so assume in 'ROM'
sl@0
  1128
		TFileName initial(a);
sl@0
  1129
		a=KRomSysBin();
sl@0
  1130
		if (initial.Length()==0 || initial[0]!='\\')
sl@0
  1131
			a.Append('\\');
sl@0
  1132
		a+=initial;
sl@0
  1133
		__KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName -> %lS", &a));
sl@0
  1134
		}
sl@0
  1135
	}
sl@0
  1136
sl@0
  1137
TInt LookupDllUid(TInt aModule)
sl@0
  1138
	{
sl@0
  1139
	TInt r = KDllUid_Default;
sl@0
  1140
	Kern::AccessCode();
sl@0
  1141
	SWin32Module w32m;
sl@0
  1142
	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
sl@0
  1143
	TInt ix;
sl@0
  1144
	MM::Win32Modules.SpecificFindInUnsignedKeyOrder(w32m, ix, EArrayFindMode_Last);
sl@0
  1145
	if (ix>0)
sl@0
  1146
		{
sl@0
  1147
		DWin32CodeSeg* pS = MM::Win32Modules[ix-1].iCodeSeg;
sl@0
  1148
		if (pS && pS->iFileEntryPoint==(TLinAddr)aModule)
sl@0
  1149
			r = pS->iCodeSegId;
sl@0
  1150
		}
sl@0
  1151
	Kern::EndAccessCode();
sl@0
  1152
	return r;
sl@0
  1153
	}
sl@0
  1154
sl@0
  1155