os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mcodeseg.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mcodeseg.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1155 @@
     1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\memmodel\emul\win32\mcodeseg.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#define __INCLUDE_ALL_SUPPORTED_CAPABILITIES__
    1.22 +#include "memmodel.h"
    1.23 +#include <property.h>
    1.24 +#include <emulator.h>
    1.25 +#include <wchar.h>
    1.26 +
    1.27 +#define __CHECKHEAP()	((RHeapK*)K::Allocator)->Check()
    1.28 +
    1.29 +static TBool BootComplete;	// flag set when boot EXE is loaded as an EPOC process
    1.30 +static DWin32CodeSeg* KernelCodeSeg;
    1.31 +static HMODULE KernelModuleHandle;
    1.32 +
    1.33 +GLREF_C TInt CompareCodeSegsByName(const DCodeSeg& aA, const DCodeSeg& aB);
    1.34 +
    1.35 +void TruncToNarrow(TUint8* aDes, const TUint16* aSrc, int aLen)
    1.36 +	{
    1.37 +	//converts to narrow by dumping the high order byte
    1.38 +	if(aDes && aSrc)
    1.39 +		{
    1.40 +		if(aLen==-1)
    1.41 +			{
    1.42 +			for(int index=0;*aSrc;index++)
    1.43 +				*aDes++ = (TUint8)*aSrc++;
    1.44 +			*aDes = '\0';
    1.45 +			}
    1.46 +		else
    1.47 +			for(int index=0;index<aLen;index++)
    1.48 +				*aDes++ = (TUint8)*aSrc++;
    1.49 +		}
    1.50 +	}
    1.51 +
    1.52 +void ExpandToWide(TUint16* aDes, const TUint8* aSrc, int aLen)
    1.53 +	{
    1.54 +	if(aDes && aSrc)
    1.55 +		{
    1.56 +		for(int index=0;index<aLen;index++)
    1.57 +			*aDes++ = (TUint16)*aSrc++;
    1.58 +		}
    1.59 +	}
    1.60 +
    1.61 +#ifdef KDLL
    1.62 +void DumpWin32CodeSeg(DWin32CodeSeg& a)
    1.63 +	{
    1.64 +	const TUint32* uid=(const TUint32*)&a.iUids;
    1.65 +	Kern::Printf("DWin32CodeSeg@%08x:",&a);
    1.66 +	Kern::Printf("iLink = %08x %08x", a.iLink.iNext, a.iLink.iPrev);
    1.67 +	Kern::Printf("iTempLink = %08x %08x", a.iTempLink.iNext, a.iTempLink.iPrev);
    1.68 +	Kern::Printf("iGbgLink = %08x %08x", a.iGbgLink.iNext, a.iGbgLink.iPrev);
    1.69 +	Kern::Printf("iAccessCount = %d", a.iAccessCount);
    1.70 +	Kern::Printf("iEntryPtVeneer = %08x", a.iEntryPtVeneer);
    1.71 +	Kern::Printf("iFileEntryPoint = %08x", a.iFileEntryPoint);
    1.72 +	Kern::Printf("iFileName = %lS", a.iFileName);
    1.73 +	Kern::Printf("iRootName = %lS", &a.iRootName);
    1.74 +	Kern::Printf("iExtOffset = %d", a.iExtOffset);
    1.75 +	Kern::Printf("iModuleVersion = %08x", a.iModuleVersion);
    1.76 +	Kern::Printf("iUids = %08x %08x %08x", uid[0], uid[1], uid[2]);
    1.77 +	Kern::Printf("iDepCount=%d iDeps=%08x", a.iDepCount, a.iDeps);
    1.78 +	Kern::Printf("iNextDep=%d, iMark=%08x, iAttr=%08x", a.iNextDep, a.iMark, a.iAttr);
    1.79 +	Kern::Printf("iExeCodeSeg=%08x, iAttachProcess=%O", a.iExeCodeSeg, a.iAttachProcess);
    1.80 +	Kern::Printf("iWinInstance = %08x", a.iWinInstance);
    1.81 +	Kern::Printf("iModuleHandle = %08x", a.iModuleHandle);
    1.82 +	Kern::Printf("iModuleFile = %08x", a.iModuleFile);
    1.83 +	Kern::Printf("iAlwaysLoaded = %08x", a.iAlwaysLoaded);
    1.84 +	Kern::Printf("iModuleList = %08x", a.iModuleList);
    1.85 +	}
    1.86 +#endif
    1.87 +
    1.88 +void ExecInEntryPoint()
    1.89 +	{
    1.90 +	// This function will be called if an Exec:: call is attempted in the entry
    1.91 +	// point of a DLL which didn't specify 'epocallowdlldata'
    1.92 +	Kern::Fault("BAD DLL STATIC",0);
    1.93 +	}
    1.94 +
    1.95 +static const SFastExecTable DummyFastExecTable={0,{0}};
    1.96 +static const SSlowExecTable DummySlowExecTable={0,(TLinAddr)ExecInEntryPoint,0,{{0,0}}};
    1.97 +
    1.98 +// Force a call to a DLL entry point to initialise any gratuitous writeable data
    1.99 +// generated by the compiler.
   1.100 +// Change exec table to prevent any executive calls in case someone forgot to
   1.101 +// use the 'epocallowdlldata' option.
   1.102 +void ForceEntryPointCall(TLinAddr aEntryPoint)
   1.103 +	{
   1.104 +	__KTRACE_OPT(KDLL,Kern::Printf("ForceEntryPoint %08x", aEntryPoint));
   1.105 +	NKern::Lock();
   1.106 +	NThread* nthrd = NKern::CurrentThread();
   1.107 +	const SFastExecTable* fast = nthrd->iFastExecTable;
   1.108 +	const SSlowExecEntry* slow = nthrd->iSlowExecTable;
   1.109 +	nthrd->iFastExecTable = (SFastExecTable*)&DummyFastExecTable;
   1.110 +	nthrd->iSlowExecTable = DummySlowExecTable.iEntries;
   1.111 +	TLibraryEntry ep = (TLibraryEntry)aEntryPoint;
   1.112 +	(*ep)(KModuleEntryReasonProcessAttach);
   1.113 +	nthrd->iFastExecTable = fast;
   1.114 +	nthrd->iSlowExecTable = slow;
   1.115 +	NKern::Unlock();
   1.116 +	}
   1.117 +
   1.118 +class TWin32Filename
   1.119 +	{
   1.120 +public:
   1.121 +	inline TWin32Filename()
   1.122 +		{iBuf[0] = '\0';}
   1.123 +	inline TWin32Filename(const TDesC& aFilename)
   1.124 +		{Set(aFilename);}
   1.125 +	inline TWin32Filename& operator=(const TDesC& aFilename)
   1.126 +		{Set(aFilename);return *this;}
   1.127 +	inline operator LPCWSTR() const
   1.128 +		{return iBuf;}
   1.129 +private:
   1.130 +	void Set(const TDesC& aFilename);
   1.131 +private:
   1.132 +	WCHAR iBuf[KMaxFileName + 1];
   1.133 +	};
   1.134 +
   1.135 +void TWin32Filename::Set(const TDesC& aFilename)
   1.136 +	{
   1.137 +	TUint16 fileName[KMaxFileName];
   1.138 +	ExpandToWide(fileName, aFilename.Ptr(), aFilename.Length());
   1.139 +	TPtr p((TUint8*)iBuf,KMaxFileName<<1);
   1.140 +	Property::MapFilename(p, TPtrC((TUint8*)fileName,aFilename.Length()<<1));
   1.141 +	iBuf[p.Length()>>1] = '\0';
   1.142 +	}
   1.143 +
   1.144 +class DModuleList : public DBase
   1.145 +	{
   1.146 +public:
   1.147 +	enum TFlags
   1.148 +		{
   1.149 +		EFlagData=0x01,
   1.150 +		EFlagDataPresent=0x02,
   1.151 +		EFlagAlreadyLoaded=0x04,
   1.152 +		EFlagMark=0x08,
   1.153 +		EFlagExe=0x10,
   1.154 +		EFlagAlwaysLoaded=0x20,
   1.155 +		EFlagExeInTree=0x40,
   1.156 +		};
   1.157 +
   1.158 +	struct SModule
   1.159 +		{
   1.160 +		TLinAddr iModuleHandle;
   1.161 +		DWin32CodeSeg* iCodeSeg;
   1.162 +		TUint32 iFlags;
   1.163 +		SSecurityInfo iS;
   1.164 +		TUint32 iModuleVersion;
   1.165 +		TInt iDepCount;
   1.166 +		TInt* iDepList;
   1.167 +		};
   1.168 +public:
   1.169 +	DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess);
   1.170 +	virtual ~DModuleList();
   1.171 +	TInt Find(TInt aModule);
   1.172 +	TInt GatherDependencies(HMODULE aModule);
   1.173 +	TInt CompileDepLists();
   1.174 +	void SetFlags();
   1.175 +	TUint32 Flags(SModule* aM);
   1.176 +	TInt LoadDependencies();
   1.177 +	void LinkDependencies();
   1.178 +	TInt Loaded();
   1.179 +public:
   1.180 +	DWin32CodeSeg* iMain;
   1.181 +	DProcess* iAttachProcess;
   1.182 +	RArray<SModule> iModules;
   1.183 +	};
   1.184 +
   1.185 +DModuleList::DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess)
   1.186 +	:	iMain(aMainSeg), iAttachProcess(aProcess),
   1.187 +		iModules(8, _FOFF(SModule,iModuleHandle), 2*256)
   1.188 +	{
   1.189 +	}
   1.190 +
   1.191 +DModuleList::~DModuleList()
   1.192 +	{
   1.193 +	TInt c = iModules.Count();
   1.194 +	if (c)
   1.195 +		{
   1.196 +		SModule* pM = (SModule*)&iModules[0];
   1.197 +		SModule* pE = pM + c;
   1.198 +		for (; pM<pE; ++pM)
   1.199 +			{
   1.200 +			Kern::Free(pM->iDepList);
   1.201 +			}
   1.202 +		}
   1.203 +	iModules.Close();
   1.204 +	}
   1.205 +
   1.206 +TInt DModuleList::Find(TInt aModule)
   1.207 +	{
   1.208 +	SModule mod;
   1.209 +	mod.iModuleHandle=(TLinAddr)aModule;
   1.210 +	return iModules.FindInUnsignedKeyOrder(mod);
   1.211 +	}
   1.212 +/**
   1.213 +Populate iModules with SModule entries corresponding to supplied HModule and all of its dependencies,
   1.214 +direct and indirect.  
   1.215 +
   1.216 +@param aModule A Windows module handle
   1.217 +@return KErrNone if successful
   1.218 +*/
   1.219 +TInt DModuleList::GatherDependencies(HMODULE aModule)
   1.220 +	{
   1.221 +	__KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
   1.222 +	Emulator::TModule etm(aModule);
   1.223 +	SModule mod;
   1.224 +	mod.iModuleHandle=(TLinAddr)aModule;
   1.225 +	mod.iCodeSeg=NULL;
   1.226 +	mod.iDepList=NULL;
   1.227 +
   1.228 +	TUint32 uid[3];
   1.229 +	TUidType& uidref=*(TUidType*)uid;
   1.230 +	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
   1.231 +	if (!hdr)
   1.232 +		return KErrNotSupported;
   1.233 +	__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));
   1.234 +	mod.iS = hdr->iS;
   1.235 +	// Overide capabilities in image
   1.236 +	const SCapabilitySet& disabledCaps = *(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
   1.237 +	for(TInt i=0; i<SCapabilitySet::ENCapW; i++)
   1.238 +		{
   1.239 +		mod.iS.iCaps[i] |= disabledCaps[i];
   1.240 +		mod.iS.iCaps[i] &= AllSupportedCapabilities[i];
   1.241 +		}
   1.242 +	mod.iModuleVersion = hdr->iModuleVersion;
   1.243 +	mod.iFlags = (hdr->iFlags & KEmulatorImageFlagAllowDllData) ? EFlagData|EFlagDataPresent : 0;
   1.244 +	uidref = *(const TUidType*)&hdr->iUids[0];
   1.245 +	TBool isExe = (uid[0]==KExecutableImageUidValue);
   1.246 +	TBool data_section_present = (etm.Section(KWin32SectionName_EpocData) != NULL);
   1.247 +	if (data_section_present && isExe)
   1.248 +		mod.iFlags = EFlagData|EFlagDataPresent;
   1.249 +	__KTRACE_OPT(KDLL,Kern::Printf("DataSectionPresent = %x", data_section_present));
   1.250 +
   1.251 +	// Can't do this for CodeWarrior since it sticks everything in .data, even constants
   1.252 +	// On VC6 this check works for Base code, but not for some other code.
   1.253 +//	if (data_section_present && !isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
   1.254 +//		return KErrNotSupported;
   1.255 +
   1.256 +	if (!data_section_present)
   1.257 +		mod.iFlags = 0;
   1.258 +	if (isExe)
   1.259 +		mod.iFlags |= EFlagExe|EFlagExeInTree;
   1.260 +
   1.261 +	SWin32Module w32m;
   1.262 +	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
   1.263 +	w32m.iCodeSeg=NULL;
   1.264 +	TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
   1.265 +	__KTRACE_OPT(KDLL, Kern::Printf("GlobalIx=%d", ix));
   1.266 +	if ((ix>=0 && !MM::Win32Modules[ix].iCodeSeg) || aModule==KernelModuleHandle)
   1.267 +		mod.iFlags|=EFlagAlwaysLoaded;
   1.268 +	TInt r=iModules.InsertInUnsignedKeyOrder(mod);
   1.269 +	__KTRACE_OPT(KDLL, Kern::Printf("Flags=%08x, InsertRes=%d", mod.iFlags, r));
   1.270 +	if (r==KErrAlreadyExists)
   1.271 +		return KErrNone;
   1.272 +	if (r!=KErrNone)
   1.273 +		return r;
   1.274 +	if (mod.iFlags & EFlagAlwaysLoaded)
   1.275 +		return KErrNone;	// stop if we reach an extension or variant
   1.276 +	if (data_section_present && (mod.iFlags & EFlagData)==0)
   1.277 +		{
   1.278 +		// DLL, .data present but 'epocallowdlldata' not specified
   1.279 +		// - either the compiler forgetting that something's constant or
   1.280 +		// developer forgetting to specify 'epocallowdlldata'.
   1.281 +		// call entry point from here to keep the compiler happy
   1.282 +		const char* entry_name = "_E32Dll" ;
   1.283 +		TLinAddr ep = (TLinAddr)Emulator::GetProcAddress(aModule, entry_name);
   1.284 +		__NK_ASSERT_ALWAYS(ep!=0);
   1.285 +		ForceEntryPointCall(ep);
   1.286 +		}
   1.287 +
   1.288 +	const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
   1.289 +	if (imports)
   1.290 +		{
   1.291 +	    for (; imports->Characteristics; ++imports )
   1.292 +			{
   1.293 +			__KTRACE_OPT(KDLL, { TPtrC8 n((const TText8*)etm.Translate(imports->Name)); Kern::Printf("Importing from %S", &n);} );
   1.294 +			Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
   1.295 +
   1.296 +			if (!imp_etm.IsValid())
   1.297 +				{
   1.298 +				__KTRACE_OPT(KDLL, Kern::Printf("Spurious import"));
   1.299 +				continue;
   1.300 +				}
   1.301 +
   1.302 +			if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
   1.303 +				{
   1.304 +				__KTRACE_OPT(KDLL, Kern::Printf("Not EPOC Module"));
   1.305 +				continue;		// not an epoc DLL
   1.306 +				}
   1.307 +
   1.308 +			r=GatherDependencies(imp_etm.iModule);
   1.309 +			if (r!=KErrNone)
   1.310 +				return r;
   1.311 +			}
   1.312 +		}
   1.313 +	__KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
   1.314 +	return KErrNone;
   1.315 +	}
   1.316 +
   1.317 +#ifdef __VC32__
   1.318 +#pragma warning( disable : 4701 )   // disable warning C4701: local variable 'missingCaps' may be used without having been initialized
   1.319 +#endif
   1.320 +
   1.321 +/**
   1.322 +Iterate through imports (if any) of each SModule in list. Populate iDepList with the indicies (in iModules)
   1.323 +of directly required modules. Checks that dependencies are legal under platsec.
   1.324 +@return KErrNone on success.
   1.325 +*/
   1.326 +TInt DModuleList::CompileDepLists()
   1.327 +	{
   1.328 +	__KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::CompileDepLists"));
   1.329 +	TInt result=KErrNone;
   1.330 +	TInt c=iModules.Count();
   1.331 +	SModule* pM=(SModule*)&iModules[0];
   1.332 +	SModule* pE=pM+c;
   1.333 +	for (; pM<pE; ++pM)
   1.334 +		{
   1.335 +		pM->iDepList=(TInt*)Kern::Alloc(c*sizeof(TInt));
   1.336 +		if (!pM->iDepList)
   1.337 +			return KErrNoMemory;
   1.338 +		memset(pM->iDepList, 0xff, c*sizeof(TInt));
   1.339 +		Emulator::TModule etm((HINSTANCE)pM->iModuleHandle);
   1.340 +		const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
   1.341 +		__KTRACE_OPT(KDLL, Kern::Printf("Module %08x, imports=%08x flags=%08x", pM->iModuleHandle, imports, pM->iFlags));
   1.342 +		if (!imports || (pM->iFlags&EFlagAlwaysLoaded))
   1.343 +			continue;
   1.344 +
   1.345 +		const SCapabilitySet& cap = pM->iS.iCaps;
   1.346 +		const SCapabilitySet& disabledCaps=*(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
   1.347 +
   1.348 +		TInt* pI=pM->iDepList;
   1.349 +		for (; imports->Characteristics; ++imports )
   1.350 +			{
   1.351 +			Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
   1.352 +
   1.353 +			if (!imp_etm.IsValid())
   1.354 +				continue;		// spurious import
   1.355 +
   1.356 +			if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
   1.357 +				continue;		// not an epoc DLL
   1.358 +
   1.359 +			TInt ix=Find((TInt)imp_etm.iModule);
   1.360 +			__ASSERT_ALWAYS(ix>=0, MM::Panic(MM::ECompileDepLists));
   1.361 +			*pI++=ix;
   1.362 +			__KTRACE_OPT(KDLL, Kern::Printf("Depends on %08x, ix=%d", imp_etm.iModule, ix));
   1.363 +
   1.364 +			const SModule& dep = iModules[ix];
   1.365 +			
   1.366 +			SCapabilitySet missingCaps;
   1.367 +			SCapabilitySet depCaps = dep.iS.iCaps;
   1.368 +			TUint32 checkFail = 0;
   1.369 +			for (TInt i=0; i<SCapabilitySet::ENCapW; ++i)
   1.370 +				{
   1.371 +				depCaps[i] = dep.iS.iCaps[i]|disabledCaps[i];
   1.372 +				TUint32 missing = cap[i] & ~depCaps[i];
   1.373 +				missingCaps[i] = missing;
   1.374 +				checkFail |= missing;
   1.375 +				}
   1.376 +
   1.377 +			__KTRACE_OPT(KDLL, Kern::Printf("Cap=%08x %08x, DepCap=%08x %08x", cap[1], cap[0], depCaps[1], depCaps[0]));
   1.378 +
   1.379 +			if (checkFail)
   1.380 +				{
   1.381 +				TUint8	mainBuf8[MAX_PATH];
   1.382 +				TInt	mainlen;
   1.383 +				{
   1.384 +				TUint16 mainBuf[MAX_PATH];
   1.385 +				mainlen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(pM->iModuleHandle),(LPWSTR)mainBuf);
   1.386 +				TruncToNarrow(mainBuf8, mainBuf, mainlen);
   1.387 +				}
   1.388 +				TPtrC mainp(mainBuf8,mainlen);
   1.389 +				TInt ix=mainp.LocateReverse('\\');
   1.390 +				if (ix>=0)
   1.391 +					mainp.Set(mainp.Mid(ix+1));
   1.392 +				if (mainp.Length() && mainp[mainp.Length()-1]==')' && (ix=mainp.LocateReverse('('))>=0)
   1.393 +					mainp.Set(mainp.Left(ix));
   1.394 +
   1.395 +				TUint8	depBuf8[MAX_PATH];
   1.396 +				TInt	deplen;
   1.397 +				{
   1.398 +				TUint16 depBuf[MAX_PATH];
   1.399 +				deplen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(dep.iModuleHandle),(LPWSTR)depBuf);
   1.400 +				TruncToNarrow(depBuf8, depBuf, deplen);
   1.401 +				}
   1.402 +				TPtrC depp(depBuf8,deplen);
   1.403 +				if ((ix=depp.LocateReverse('\\'))>=0)
   1.404 +					depp.Set(depp.Mid(ix+1));
   1.405 +#ifndef __REMOVE_PLATSEC_DIAGNOSTICS__
   1.406 +				TInt r = PlatSec::LoaderCapabilityViolation(mainp, depp, missingCaps);
   1.407 +#else //__REMOVE_PLATSEC_DIAGNOSTICS__
   1.408 +				TInt r = PlatSec::EmitDiagnostic();
   1.409 +#endif // !__REMOVE_PLATSEC_DIAGNOSTICS__
   1.410 +				if(r!=KErrNone)
   1.411 +					result=r;
   1.412 +				}
   1.413 +			}
   1.414 +		}
   1.415 +	return result;
   1.416 +	}
   1.417 +
   1.418 +#ifdef __VC32__
   1.419 +#pragma warning( default : 4701 )   // enable warning C4701: local variable 'missingCaps' may be used without having been initialized
   1.420 +#endif
   1.421 +
   1.422 +void DModuleList::SetFlags()
   1.423 +	{
   1.424 +	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::SetFlags"));
   1.425 +	TInt c=iModules.Count();
   1.426 +	SModule* pM=(SModule*)&iModules[0];
   1.427 +	SModule* pE=pM+c;
   1.428 +	for (; pM<pE; ++pM)
   1.429 +		{
   1.430 +		SModule* pM2=(SModule*)&iModules[0];
   1.431 +		for (; pM2<pE; ++pM2)
   1.432 +			pM2->iFlags &= ~EFlagMark;
   1.433 +		TUint32 flags=Flags(pM);
   1.434 +		if (flags & EFlagData)
   1.435 +			pM->iFlags|=EFlagDataPresent;
   1.436 +		if (flags & EFlagExe)
   1.437 +			pM->iFlags|=EFlagExeInTree;
   1.438 +		__KTRACE_OPT(KDLL, Kern::Printf("Module %08x Flags=%08x", pM->iModuleHandle, pM->iFlags));
   1.439 +		}
   1.440 +	pM=(SModule*)&iModules[0];
   1.441 +	for (; pM<pE; ++pM)
   1.442 +		{	
   1.443 +		TInt dc=0;
   1.444 +		const TInt* pI=pM->iDepList;
   1.445 +		const TInt* pIE=pI+c;
   1.446 +		while (pI<pIE)
   1.447 +			{
   1.448 +			TInt ix=*pI++;
   1.449 +			if (ix<0)
   1.450 +				break;
   1.451 +			TUint32 mflags=iModules[ix].iFlags;
   1.452 +			if ( (mflags&(EFlagDataPresent|EFlagExeInTree)) && !(mflags&EFlagAlwaysLoaded))
   1.453 +				++dc;
   1.454 +			}
   1.455 +		pM->iDepCount=dc;
   1.456 +		__KTRACE_OPT(KDLL, Kern::Printf("Module %08x DepCount=%d", pM->iModuleHandle, pM->iDepCount));
   1.457 +		}
   1.458 +	}
   1.459 +
   1.460 +TUint32 DModuleList::Flags(SModule* aM)
   1.461 +	{
   1.462 +	TUint32 flags=aM->iFlags;
   1.463 +	__KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::Flags %08x", aM->iModuleHandle));
   1.464 +	if ((aM->iFlags & EFlagMark)==0)
   1.465 +		{
   1.466 +		aM->iFlags |= EFlagMark;
   1.467 +		const TInt* pI=aM->iDepList;
   1.468 +		const TInt* pE=pI+iModules.Count();
   1.469 +		while (pI<pE)
   1.470 +			{
   1.471 +			TInt ix=*pI++;
   1.472 +			if (ix<0)
   1.473 +				break;
   1.474 +			TUint32 mflags=Flags(&iModules[ix]);
   1.475 +			if (mflags&EFlagExe)
   1.476 +				mflags&=~EFlagData;
   1.477 +			flags |= mflags;
   1.478 +			}
   1.479 +		}
   1.480 +	__KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::Flags %08x = %08x", aM->iModuleHandle, flags));
   1.481 +	return flags;
   1.482 +	}
   1.483 +
   1.484 +TInt DModuleList::LoadDependencies()
   1.485 +	{
   1.486 +	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LoadDependencies"));
   1.487 +	TInt c=iModules.Count();
   1.488 +	SModule* pM=(SModule*)&iModules[0];
   1.489 +	SModule* pE=pM+c;
   1.490 +	for (; pM<pE; ++pM)
   1.491 +		{
   1.492 +		DWin32CodeSeg* pS;
   1.493 +		TUint32 flags=pM->iFlags;
   1.494 +		__KTRACE_OPT(KDLL, Kern::Printf("ModuleHandle %08x flags %08x", pM->iModuleHandle, flags));
   1.495 +		if (!(flags & (EFlagDataPresent|EFlagExeInTree)) || (flags&EFlagAlwaysLoaded))
   1.496 +			continue;
   1.497 +		SWin32Module w32m;
   1.498 +		w32m.iWin32ModuleHandle=(TLinAddr)pM->iModuleHandle;
   1.499 +		w32m.iCodeSeg=NULL;
   1.500 +		TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
   1.501 +		__KTRACE_OPT(KDLL, Kern::Printf("GlobalIndex=%d", ix));
   1.502 +		if (ix<0 && (flags & EFlagExe))
   1.503 +			return KErrNotSupported;	// we never implicitly load an EXE
   1.504 +		if (ix>=0)
   1.505 +			{
   1.506 +			pS=MM::Win32Modules[ix].iCodeSeg;
   1.507 +			__KTRACE_OPT(KDLL, Kern::Printf("Already loaded; CSEG=%08x %C", pS, pS));
   1.508 +			if (pS==iMain)
   1.509 +				{
   1.510 +				pS->iDepCount=pM->iDepCount;
   1.511 +				if (pS->iDepCount)
   1.512 +					{
   1.513 +					pS->iDeps=(DCodeSeg**)Kern::AllocZ(pS->iDepCount*sizeof(DCodeSeg*));
   1.514 +					if (!pS->iDeps)
   1.515 +						return KErrNoMemory;
   1.516 +					}
   1.517 +				}
   1.518 +			else
   1.519 +				{
   1.520 +				if (!(pS->iMark & DCodeSeg::EMarkLdr))
   1.521 +					{
   1.522 +					pS->iMark |= DCodeSeg::EMarkLdr;
   1.523 +					pS->CheckedOpen();
   1.524 +					}
   1.525 +				pM->iFlags|=EFlagAlreadyLoaded;
   1.526 +				}
   1.527 +			pM->iCodeSeg=pS;
   1.528 +			continue;
   1.529 +			}
   1.530 +		__KTRACE_OPT(KDLL, Kern::Printf("Create new, depcount=%d", pM->iDepCount));
   1.531 +		pS=new DWin32CodeSeg;
   1.532 +		if (!pS)
   1.533 +			return KErrNoMemory;
   1.534 +		TInt r=pS->CreateAlreadyLoaded((HMODULE)pM->iModuleHandle, pM->iDepCount);
   1.535 +		if (r!=KErrNone)
   1.536 +			{
   1.537 +			delete pS;
   1.538 +			return r;
   1.539 +			}
   1.540 +		pM->iCodeSeg=pS;
   1.541 +		pS->iS = pM->iS;
   1.542 +		pS->iModuleVersion = pM->iModuleVersion;
   1.543 +		if (iMain->iAttr & ECodeSegAttKernel)
   1.544 +			pS->iAttr |= ECodeSegAttKernel;
   1.545 +		if (flags & EFlagData)
   1.546 +			{
   1.547 +			pS->iMark |= DCodeSeg::EMarkData|DCodeSeg::EMarkDataPresent;
   1.548 +			if (!(flags&EFlagExe))
   1.549 +				pS->iMark |= DCodeSeg::EMarkDataInit;
   1.550 +			}
   1.551 +		if ( (flags & EFlagData) || ((flags&(EFlagExe|EFlagExeInTree))==EFlagExeInTree) )
   1.552 +			{
   1.553 +			if (iAttachProcess)
   1.554 +				{
   1.555 +				pS->iExeCodeSeg = iAttachProcess->CodeSeg();
   1.556 +				pS->SetAttachProcess(iAttachProcess);
   1.557 +				}
   1.558 +			}
   1.559 +		}
   1.560 +	return KErrNone;
   1.561 +	}
   1.562 +
   1.563 +void DModuleList::LinkDependencies()
   1.564 +	{
   1.565 +	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LinkDependencies"));
   1.566 +	TInt c=iModules.Count();
   1.567 +	SModule* pM=(SModule*)&iModules[0];
   1.568 +	SModule* pE=pM+c;
   1.569 +	for (; pM<pE; ++pM)
   1.570 +		{
   1.571 +		DWin32CodeSeg* pS=pM->iCodeSeg;
   1.572 +		if (!pS || (pM->iFlags&EFlagAlreadyLoaded))
   1.573 +			continue;
   1.574 +		const TInt* pI=pM->iDepList;
   1.575 +		const TInt* pIE=pI+c;
   1.576 +		while (pI<pIE)
   1.577 +			{
   1.578 +			TInt ix=*pI++;
   1.579 +			if (ix<0)
   1.580 +				break;
   1.581 +			DWin32CodeSeg* pD=iModules[ix].iCodeSeg;
   1.582 +			if (pD)
   1.583 +				pS->iDeps[pS->iNextDep++]=pD;
   1.584 +			}
   1.585 +		}
   1.586 +	pM=(SModule*)&iModules[0];
   1.587 +	}
   1.588 +
   1.589 +TInt DModuleList::Loaded()
   1.590 +	{
   1.591 +	__KTRACE_OPT(KDLL, Kern::Printf("DModuleList::Loaded()"));
   1.592 +	TInt c=iModules.Count();
   1.593 +	SModule* pM=(SModule*)&iModules[0];
   1.594 +	SModule* pE=pM+c;
   1.595 +	TInt r=KErrNone;
   1.596 +	for (; pM<pE && r==KErrNone; ++pM)
   1.597 +		{
   1.598 +		DWin32CodeSeg* pS=pM->iCodeSeg;
   1.599 +		if (pS && pS!=iMain)
   1.600 +			{
   1.601 +			pS->FinaliseRecursiveFlags();
   1.602 +			pS->iMark |= DCodeSeg::EMarkLoaded;
   1.603 +			}
   1.604 +		}
   1.605 +	if (r==KErrNone)
   1.606 +		{
   1.607 +		pM=(SModule*)&iModules[0];
   1.608 +		for (; pM<pE; ++pM)
   1.609 +			pM->iCodeSeg=NULL;	// cleanup will occur by EMarkLdr if needed
   1.610 +		}
   1.611 +	return r;
   1.612 +	}
   1.613 +
   1.614 +TInt MakeDll(HANDLE aFile)
   1.615 +	{
   1.616 +	IMAGE_DOS_HEADER dosh;
   1.617 +	DWORD bytes;
   1.618 +	ReadFile(aFile, &dosh, sizeof(dosh), &bytes, NULL);
   1.619 +	if ( IMAGE_DOS_SIGNATURE != dosh.e_magic )
   1.620 +		return KErrArgument;
   1.621 +	if (dosh.e_lfarlc < sizeof(dosh))
   1.622 +		return KErrArgument;
   1.623 +	SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
   1.624 +	IMAGE_NT_HEADERS32 peh;
   1.625 +	ReadFile(aFile, &peh, sizeof(peh), &bytes, NULL);
   1.626 +    if ( peh.Signature != IMAGE_NT_SIGNATURE )
   1.627 +		return KErrArgument;
   1.628 +
   1.629 +	peh.FileHeader.Characteristics |= IMAGE_FILE_DLL;
   1.630 +	peh.OptionalHeader.AddressOfEntryPoint = 0;
   1.631 +	SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
   1.632 +	WriteFile(aFile, &peh, sizeof(peh), &bytes, NULL);
   1.633 +	return KErrNone;
   1.634 +	}
   1.635 +
   1.636 +wchar_t* TempModuleName(const wchar_t* aExe)
   1.637 +	{
   1.638 +	static TInt ModuleGeneration = 0;
   1.639 +	static TInt Time = 0;
   1.640 +
   1.641 +	WCHAR ex_[KMaxFileName + 1];
   1.642 +
   1.643 +	if (!Time)
   1.644 +		{
   1.645 +		SYSTEMTIME st;
   1.646 +		GetSystemTime(&st);
   1.647 +		Time = st.wSecond + st.wMinute*60 + st.wHour*3600;
   1.648 +		}
   1.649 +
   1.650 +	const char* imagePath = Property::GetString("EmulatorImagePath");
   1.651 +	WCHAR* p = ex_;
   1.652 +	while ((*p++ = *imagePath++) != 0)
   1.653 +		;
   1.654 +	wcscpy(p-1, wcsrchr(aExe, '\\') + 1);
   1.655 +	p = ex_ + wcslen(ex_);
   1.656 +	*p++ = '(';
   1.657 +	_itow(Time, p, 36);
   1.658 +	p += wcslen(p);
   1.659 +	*p++ = '-';
   1.660 +	_itow(ModuleGeneration++, p, 10);
   1.661 +	p += wcslen(p);
   1.662 +	*p++ = ')';
   1.663 +	*p++ = '\0';
   1.664 +	wchar_t* file = (wchar_t*)Kern::Alloc((p-ex_)*sizeof(WCHAR));
   1.665 +	if (file)
   1.666 +		wcscpy(file, ex_);
   1.667 +	return file;
   1.668 +	}
   1.669 +
   1.670 +DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&)
   1.671 +//
   1.672 +// Create a new instance of this class.
   1.673 +//
   1.674 +	{
   1.675 +
   1.676 +	__KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg"));
   1.677 +	return new DWin32CodeSeg;
   1.678 +	}
   1.679 +
   1.680 +DWin32CodeSeg::DWin32CodeSeg()
   1.681 +//
   1.682 +// Constructor
   1.683 +//
   1.684 +	{
   1.685 +	}
   1.686 +
   1.687 +DWin32CodeSeg::~DWin32CodeSeg()
   1.688 +//
   1.689 +// Destructor
   1.690 +//
   1.691 +	{
   1.692 +	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Destruct %C", this));
   1.693 +	DBase::Delete(iModuleList);
   1.694 +	if (iWinInstance)
   1.695 +		{
   1.696 +		DCodeSeg::Wait();
   1.697 +		SWin32Module w32m;
   1.698 +		w32m.iWin32ModuleHandle=(TLinAddr)iModuleHandle;
   1.699 +		w32m.iCodeSeg=NULL;
   1.700 +		TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
   1.701 +		if (ix>=0)
   1.702 +			{
   1.703 +			if (iAlwaysLoaded)
   1.704 +				MM::Win32Modules[ix].iCodeSeg=NULL;
   1.705 +			else
   1.706 +				MM::Win32Modules.Remove(ix);
   1.707 +			}
   1.708 +		// Kernel process has to be told to unmap code seg to work round
   1.709 +		// a problem where failed driver code seg is not unmapped before delete
   1.710 +		K::TheKernelProcess->UnmapCodeSeg(this);
   1.711 +		Emulator::FreeLibrary(iWinInstance);
   1.712 +		DCodeSeg::Signal();
   1.713 +		}
   1.714 +	if (iModuleFile)
   1.715 +		{
   1.716 +		Emulator::DeleteFile(iModuleFile);
   1.717 +		Kern::Free(iModuleFile);
   1.718 +		}
   1.719 +	Kern::Free(iDataCopy);
   1.720 +	DCodeSeg::Destruct();
   1.721 +	}
   1.722 +
   1.723 +TInt DWin32CodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
   1.724 +	{
   1.725 +	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::DoCreate %C proc %O", this, aProcess));
   1.726 +
   1.727 +	TBool exe=(iExeCodeSeg==this);
   1.728 +	if (exe && (iAttr&ECodeSegAttKernel))
   1.729 +		{
   1.730 +		// loading EKERN.EXE
   1.731 +		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN"));
   1.732 +		TUint16 fileNameW[KMaxFileName];
   1.733 +		ExpandToWide(fileNameW, iFileName->Ptr(), iFileName->Length());
   1.734 +		fileNameW[iFileName->Length()] = '\0';
   1.735 +		iWinInstance = Emulator::LoadLibrary((LPCWSTR)fileNameW);
   1.736 +		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN %08x", iWinInstance));
   1.737 +		if (!iWinInstance)
   1.738 +			return KErrGeneral;
   1.739 +		if (aInfo.iTotalDataSize)
   1.740 +			iMark|=EMarkData|EMarkDataPresent;
   1.741 +		KernelCodeSeg=this;
   1.742 +		KernelModuleHandle=Emulator::GetModuleHandle((LPCWSTR)fileNameW);
   1.743 +		return RegisterCodeSeg(KernelModuleHandle);
   1.744 +		}
   1.745 +	TWin32Filename w32fn(*iFileName);
   1.746 +	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : w32fn=%S",iFileName))
   1.747 +	DWin32Process* p=(DWin32Process*)aProcess;
   1.748 +	TInt r=KErrNone;
   1.749 +	DCodeSeg::Wait();
   1.750 +	HMODULE h = Emulator::GetModuleHandle(w32fn);
   1.751 +	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : h=%08x exe=%08x",h,exe));
   1.752 +	if (h && exe)
   1.753 +		{
   1.754 +		if (h == GetModuleHandleA(NULL))
   1.755 +			{
   1.756 +			// This was the executable that was used to run the emulator
   1.757 +			// so all relocations will be valid and we can use it
   1.758 +			__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : initial exe"));
   1.759 +			if (BootComplete)
   1.760 +				goto makecopy;	// we can only do this once however
   1.761 +			iWinInstance = Emulator::LoadLibrary(w32fn);
   1.762 +			BootComplete = ETrue;
   1.763 +			}
   1.764 +		else
   1.765 +			r=KErrAlreadyExists;		// can't load same EXEXP twice
   1.766 +		}
   1.767 +	else if (h)
   1.768 +		{
   1.769 +		// Already loaded DLL
   1.770 +		// Code segment doesn't exist so create it
   1.771 +		__KTRACE_OPT(KDLL,Kern::Printf("Already loaded, module %08x",h));
   1.772 +		iWinInstance = Emulator::LoadLibrary(w32fn);
   1.773 +		}
   1.774 +	else if (iAttr & ECodeSegAttHDll)
   1.775 +		{
   1.776 +		// EXE with exports (EXEXP target) - can only have one instance
   1.777 +		// or DLL not already loaded
   1.778 +		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EXEXP or new DLL"));
   1.779 +		iWinInstance = Emulator::LoadLibrary(w32fn);
   1.780 +		if (iWinInstance)
   1.781 +			h=Emulator::GetModuleHandle(w32fn);
   1.782 +		}
   1.783 +	else
   1.784 +		{
   1.785 +		// EXE with no exports. In order that multiple instances of the EXE may be run,
   1.786 +		// we make a copy of the EXE file to a name which is unique across instances,
   1.787 +		// set the DLL flag and load it as a DLL.
   1.788 +makecopy:
   1.789 +		__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : MakeCopy"));
   1.790 +		h=0;
   1.791 +		iModuleFile = TempModuleName(w32fn);
   1.792 +		if (!iModuleFile)
   1.793 +			r=KErrNoMemory;
   1.794 +		else if (Emulator::CopyFile(w32fn,iModuleFile,FALSE))
   1.795 +			{
   1.796 +			DWORD fattr = Emulator::GetFileAttributes(iModuleFile);
   1.797 +			if (fattr != 0xffffffff && Emulator::SetFileAttributes(iModuleFile, fattr & ~FILE_ATTRIBUTE_READONLY))
   1.798 +				{
   1.799 +				HANDLE f = Emulator::CreateFile(iModuleFile,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL);
   1.800 +				if (INVALID_HANDLE_VALUE != f)
   1.801 +					{
   1.802 +					r = MakeDll(f);
   1.803 +					CloseHandle(f);
   1.804 +					if (r==KErrNone)
   1.805 +						{
   1.806 +						iWinInstance = Emulator::LoadLibrary(iModuleFile);
   1.807 +						if (iWinInstance)
   1.808 +							h=Emulator::GetModuleHandle(iModuleFile);
   1.809 +						}
   1.810 +					}
   1.811 +				}
   1.812 +			}
   1.813 +		}
   1.814 +	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d iWinInstance=%08x",__LINE__,r,iWinInstance));
   1.815 +	if (r==KErrNone && !iWinInstance)
   1.816 +		r=Emulator::LastError();
   1.817 +	__KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d",__LINE__,r));
   1.818 +	if (r==KErrNone)
   1.819 +		{
   1.820 +		const char* entry_name = exe ? "_E32Startup" : "_E32Dll" ;
   1.821 +		aInfo.iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, entry_name);
   1.822 +		if (!aInfo.iFileEntryPoint)
   1.823 +         {
   1.824 +			r=KErrNotSupported;
   1.825 +         }
   1.826 +		else
   1.827 +         {
   1.828 +			r=RegisterCodeSeg(h);
   1.829 +         }
   1.830 +
   1.831 +		if (r == KErrNone)
   1.832 +         {
   1.833 +			r = CopyDataBss();
   1.834 +         }
   1.835 +		}
   1.836 +	if (r==KErrNone && aInfo.iTotalDataSize && !iAlwaysLoaded)
   1.837 +		{
   1.838 +		iMark|=EMarkData|EMarkDataPresent;
   1.839 +		if (!exe)
   1.840 +			iMark|=EMarkDataInit;
   1.841 +		}
   1.842 +
   1.843 +	if (r==KErrNone)
   1.844 +		r=ProcessImports(p);
   1.845 +	__KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
   1.846 +	DCodeSeg::Signal();
   1.847 +	return r;
   1.848 +	}
   1.849 +
   1.850 +TInt DWin32CodeSeg::RegisterCodeSeg(HMODULE aModule)
   1.851 +	{
   1.852 +	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %C RegisterCodeSeg(%08x)", this, aModule));
   1.853 +	Emulator::TModule etm(aModule);
   1.854 +	const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
   1.855 +	iRunAddress = (TLinAddr)aModule;
   1.856 +	iSize = nth->OptionalHeader.SizeOfImage;
   1.857 +	SWin32Module w32m;
   1.858 +	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
   1.859 +	w32m.iCodeSeg=this;
   1.860 +	TInt r=KErrNone;
   1.861 +	TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
   1.862 +	if (ix>=0)
   1.863 +		{
   1.864 +		SWin32Module& wmr=MM::Win32Modules[ix];
   1.865 +		__ASSERT_ALWAYS(!wmr.iCodeSeg, MM::Panic(MM::EInvalidSharedModule));
   1.866 +		wmr.iCodeSeg=this;
   1.867 +		iAlwaysLoaded=ETrue;
   1.868 +		}
   1.869 +	else
   1.870 +		r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
   1.871 +	if (r==KErrNone)
   1.872 +		{
   1.873 +		iModuleHandle=aModule;
   1.874 +		iCodeSegId=++MM::NextCodeSegId;
   1.875 +		}
   1.876 +	return r;
   1.877 +	}
   1.878 +
   1.879 +TInt DWin32CodeSeg::CreateAlreadyLoaded(HMODULE aModule, TInt aDepCount)
   1.880 +	{
   1.881 +	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %08x CreateAlreadyLoaded(%08x,%d)", this, aModule, aDepCount));
   1.882 +	Emulator::TModule etm(aModule);
   1.883 +	etm.GetUids(iUids);
   1.884 +	TInt32 uid1=iUids.iUid[0].iUid;
   1.885 +	if (uid1!=KDynamicLibraryUidValue)	// only implicitly load DLLs
   1.886 +		return KErrNotSupported;
   1.887 +	
   1.888 +	WCHAR name[MAX_PATH+1];
   1.889 +	TInt r=Emulator::GetModuleFileName(aModule, name);
   1.890 +	if (!r)
   1.891 +		return Emulator::LastError();
   1.892 +	TUint8 name8[MAX_PATH+1];
   1.893 +	TruncToNarrow(name8,(const TUint16*)name,-1);
   1.894 +
   1.895 +   //SL:
   1.896 +   __KTRACE_OPT(KDLL, Kern::Printf("Loading library %s", name8));
   1.897 +
   1.898 +	TPtrC fpptr((const TText*)name8);
   1.899 +	TInt slash=fpptr.LocateReverse('\\');
   1.900 +	TPtrC nptr=fpptr.Mid(slash+1);
   1.901 +	iFileName=HBuf::New(nptr);
   1.902 +	if (!iFileName)
   1.903 +		return KErrNoMemory;
   1.904 +	iRootName.Set(*iFileName);
   1.905 +	iExtOffset = iFileName->LocateReverse('.');
   1.906 +	if (iExtOffset==KErrNotFound)
   1.907 +		iExtOffset = iFileName->Length();
   1.908 +	iModuleVersion = 0x00010000u;
   1.909 +	iDepCount=aDepCount;
   1.910 +	if (iDepCount)
   1.911 +		{
   1.912 +		iDeps=(DCodeSeg**)Kern::AllocZ(iDepCount*sizeof(DCodeSeg*));
   1.913 +		if (!iDeps)
   1.914 +			return KErrNoMemory;
   1.915 +		}
   1.916 +	iWinInstance = Emulator::LoadLibrary(name);
   1.917 +	if (!iWinInstance)
   1.918 +		return Emulator::LastError();
   1.919 +	iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, "_E32Dll");
   1.920 +	if (!iFileEntryPoint)
   1.921 +		return KErrNotSupported;
   1.922 +	iEntryPtVeneer = iFileEntryPoint;
   1.923 +	r=RegisterCodeSeg(aModule);
   1.924 +	if (r == KErrNone)
   1.925 +		r = CopyDataBss();
   1.926 +	if (r == KErrNone)
   1.927 +		r = CodeSegsByName.InsertInOrderAllowRepeats(this, &CompareCodeSegsByName);
   1.928 +	if (r == KErrNone)
   1.929 +		r = CodeSegsByAddress.Add(this);
   1.930 +	if (r==KErrNone)
   1.931 +		{
   1.932 +		GlobalList.Add(&iLink);
   1.933 +		iAsyncDeleteNext=this;
   1.934 +		}
   1.935 +	__KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
   1.936 +	return r;
   1.937 +	}
   1.938 +
   1.939 +TInt DWin32CodeSeg::CopyDataBss()
   1.940 +	{
   1.941 +	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::CopyDataBss()"));
   1.942 +
   1.943 +	Emulator::TModule etm(iModuleHandle);
   1.944 +	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
   1.945 +	if (!(hdr->iFlags & KEmulatorImageFlagAllowDllData))
   1.946 +		return KErrNone;
   1.947 +	const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
   1.948 +	const IMAGE_SECTION_HEADER* bss=etm.SectionHeader(KWin32SectionName_EpocBss);
   1.949 +	if (data)
   1.950 +		{
   1.951 +		iRealDataSize = data->Misc.VirtualSize;
   1.952 +		iDataDest = (TLinAddr)etm.Translate(data->VirtualAddress);
   1.953 +		iDataCopy = Kern::Alloc(iRealDataSize);
   1.954 +		if (!iDataCopy)
   1.955 +			return KErrNoMemory;
   1.956 +		memcpy(iDataCopy, (const TAny*)iDataDest, iRealDataSize);
   1.957 +		}
   1.958 +	if (bss)
   1.959 +		{
   1.960 +		iRealBssSize = bss->Misc.VirtualSize;
   1.961 +		iBssDest = (TLinAddr)etm.Translate(bss->VirtualAddress);
   1.962 +		}
   1.963 +	return KErrNone;
   1.964 +	}
   1.965 +
   1.966 +TInt DWin32CodeSeg::ProcessImports(DProcess* aProcess)
   1.967 +	{
   1.968 +	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::ProcessImports(%O)", aProcess));
   1.969 +	iModuleList=new DModuleList(this, aProcess);
   1.970 +	if (!iModuleList)
   1.971 +		return KErrNoMemory;
   1.972 +	TInt r=iModuleList->GatherDependencies(iModuleHandle);
   1.973 +	if (r!=KErrNone)
   1.974 +		return r;
   1.975 +	TInt ix=iModuleList->Find((TInt)iModuleHandle);
   1.976 +	DModuleList::SModule& mm=iModuleList->iModules[ix];
   1.977 +	r=iModuleList->CompileDepLists();
   1.978 +	if (r==KErrNone)
   1.979 +		{
   1.980 +		iModuleList->SetFlags();
   1.981 +		r=iModuleList->LoadDependencies();
   1.982 +		if (r==KErrNone)
   1.983 +			{
   1.984 +			if ((mm.iFlags&(DModuleList::EFlagDataPresent|DModuleList::EFlagExeInTree)) && !(mm.iFlags&DModuleList::EFlagAlwaysLoaded))
   1.985 +				{
   1.986 +				if (aProcess)
   1.987 +					{
   1.988 +					iExeCodeSeg=aProcess->CodeSeg();
   1.989 +					SetAttachProcess(aProcess);
   1.990 +					}
   1.991 +				}
   1.992 +			iModuleList->LinkDependencies();
   1.993 +			}
   1.994 +		}
   1.995 +	return r;
   1.996 +	}
   1.997 +
   1.998 +TInt DWin32CodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
   1.999 +	{
  1.1000 +	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded()"));
  1.1001 +	TInt r=KErrNone;
  1.1002 +	if (iModuleList)
  1.1003 +		{
  1.1004 +		r=iModuleList->Loaded();
  1.1005 +		if (r==KErrNone)
  1.1006 +			{
  1.1007 +			DBase::Delete(iModuleList);
  1.1008 +			iModuleList=NULL;
  1.1009 +			}
  1.1010 +		}
  1.1011 +	if (r==KErrNone)
  1.1012 +		r=DCodeSeg::Loaded(aInfo);
  1.1013 +	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded() - %d", r));
  1.1014 +	return r;
  1.1015 +	}
  1.1016 +
  1.1017 +void DWin32CodeSeg::ReadExportDir(TUint32*)
  1.1018 +	{
  1.1019 +	// not needed
  1.1020 +	}
  1.1021 +
  1.1022 +TBool DWin32CodeSeg::FindCheck(DProcess* /*aProcess*/)
  1.1023 +	{
  1.1024 +	// We never create multiple copies of the same code segment,
  1.1025 +	// so if code segment exists, allow it to be found.
  1.1026 +	// CodeSegOpen will fail if it is incompatible.
  1.1027 +	return ETrue;
  1.1028 +	}
  1.1029 +
  1.1030 +TBool DWin32CodeSeg::OpenCheck(DProcess* aProcess)
  1.1031 +	{
  1.1032 +	__KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
  1.1033 +	if (!aProcess)
  1.1034 +		return EFalse;	// never reuse EXE code segments
  1.1035 +	return ETrue;
  1.1036 +	}
  1.1037 +
  1.1038 +TLibraryFunction DWin32CodeSeg::Lookup(TInt aOrdinal)
  1.1039 +//
  1.1040 +// Find an exported function by ordinal
  1.1041 +//
  1.1042 +	{
  1.1043 +	TLibraryFunction f = NULL;
  1.1044 +	if (aOrdinal != 0)
  1.1045 +		{
  1.1046 +			
  1.1047 +		f = (TLibraryFunction)Emulator::GetProcAddress(iWinInstance, (const char *)aOrdinal);
  1.1048 +		if ((TLinAddr)f == iFileEntryPoint)
  1.1049 +			f = NULL;
  1.1050 +		}
  1.1051 +	else
  1.1052 +		{
  1.1053 +		// Find 0th Ordinal, which should be named symbol export data, from named data segment
  1.1054 +		Emulator::TModule etm(iModuleHandle);
  1.1055 +		f  = (TLibraryFunction)etm.Section(KWin32SectionName_NmdExpData);
  1.1056 +		}
  1.1057 + 	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Lookup(%d)->%08x",aOrdinal,f));
  1.1058 +	return f;
  1.1059 +	}
  1.1060 +
  1.1061 +DCodeSeg* DCodeSeg::FindRomCode(const TAny*)
  1.1062 +	{
  1.1063 +	// never used
  1.1064 +	return NULL;
  1.1065 +	}
  1.1066 +
  1.1067 +void DWin32CodeSeg::InitData()
  1.1068 +	{
  1.1069 +	}
  1.1070 +
  1.1071 +TInt DWin32CodeSeg::GetMemoryInfo(TModuleMemoryInfo&, DProcess*)
  1.1072 +	{
  1.1073 +	return KErrNotSupported;
  1.1074 +	}
  1.1075 +
  1.1076 +void DWin32CodeSeg::Info(TCodeSegCreateInfo& aInfo)
  1.1077 +	{
  1.1078 +	Emulator::TModule etm(iModuleHandle);
  1.1079 +	const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
  1.1080 +	const IMAGE_EXPORT_DIRECTORY* exd=
  1.1081 +		(const IMAGE_EXPORT_DIRECTORY*)etm.Translate(nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  1.1082 +	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
  1.1083 +	TBool isExe = hdr && hdr->iUids[0].iUid==KExecutableImageUidValue;
  1.1084 +	const IMAGE_SECTION_HEADER* text=etm.SectionHeader(KWin32SectionName_Text);
  1.1085 +	const IMAGE_SECTION_HEADER* rdata=etm.SectionHeader(KWin32SectionName_RData);
  1.1086 +	const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
  1.1087 +	if (!isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
  1.1088 +		data = NULL;
  1.1089 +	aInfo.iTextSize=text->Misc.VirtualSize;
  1.1090 +	aInfo.iCodeSize=text->Misc.VirtualSize;
  1.1091 +	if (rdata)
  1.1092 +		aInfo.iCodeSize+=rdata->Misc.VirtualSize;
  1.1093 +	aInfo.iDataSize=data ? (data->SizeOfRawData) : 0;
  1.1094 +	aInfo.iBssSize=data ? (data->Misc.VirtualSize-data->SizeOfRawData) : 0;
  1.1095 +	aInfo.iTotalDataSize=aInfo.iDataSize+aInfo.iBssSize;
  1.1096 +	aInfo.iExportDir=(TLinAddr)exd;
  1.1097 +	aInfo.iExportDirCount=exd ? exd->NumberOfFunctions : 0;
  1.1098 +	aInfo.iCodeLoadAddress=(TLinAddr)etm.Translate(text->VirtualAddress);
  1.1099 +	aInfo.iCodeRunAddress=aInfo.iCodeLoadAddress;
  1.1100 +	aInfo.iDataLoadAddress=data ? (TLinAddr)etm.Translate(data->VirtualAddress) : 0;
  1.1101 +	aInfo.iDataRunAddress=aInfo.iDataLoadAddress;
  1.1102 +	DCodeSeg::Info(aInfo);
  1.1103 +	}
  1.1104 +
  1.1105 +TLinAddr DCodeSeg::ExceptionDescriptor()
  1.1106 +	{
  1.1107 +	return 0;	// not used on emulator
  1.1108 +	}
  1.1109 +
  1.1110 +TInt MM::RegisterModule(HMODULE aModule)
  1.1111 +	{
  1.1112 +	__KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule %08x",aModule));
  1.1113 +	SWin32Module w32m;
  1.1114 +	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
  1.1115 +	w32m.iCodeSeg=NULL;
  1.1116 +	TInt r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
  1.1117 +	__KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule ret %d",r));
  1.1118 +	return r;
  1.1119 +	}
  1.1120 +
  1.1121 +_LIT(KRomSysBin, "Z:\\sys\\bin");
  1.1122 +
  1.1123 +// Massage file names returned for stuff in EPOCROOT\epoc32\release\wins\xxxx\
  1.1124 +// in order to make them appear to be in z:\system\libs
  1.1125 +void P::NormalizeExecutableFileName(TDes& a)
  1.1126 +	{
  1.1127 +	__KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName %lS", &a));
  1.1128 +	if (a.Length()<3 || a[1]!=':' || a[2]!='\\')
  1.1129 +		{
  1.1130 +		// don't have a drive so assume in 'ROM'
  1.1131 +		TFileName initial(a);
  1.1132 +		a=KRomSysBin();
  1.1133 +		if (initial.Length()==0 || initial[0]!='\\')
  1.1134 +			a.Append('\\');
  1.1135 +		a+=initial;
  1.1136 +		__KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName -> %lS", &a));
  1.1137 +		}
  1.1138 +	}
  1.1139 +
  1.1140 +TInt LookupDllUid(TInt aModule)
  1.1141 +	{
  1.1142 +	TInt r = KDllUid_Default;
  1.1143 +	Kern::AccessCode();
  1.1144 +	SWin32Module w32m;
  1.1145 +	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
  1.1146 +	TInt ix;
  1.1147 +	MM::Win32Modules.SpecificFindInUnsignedKeyOrder(w32m, ix, EArrayFindMode_Last);
  1.1148 +	if (ix>0)
  1.1149 +		{
  1.1150 +		DWin32CodeSeg* pS = MM::Win32Modules[ix-1].iCodeSeg;
  1.1151 +		if (pS && pS->iFileEntryPoint==(TLinAddr)aModule)
  1.1152 +			r = pS->iCodeSegId;
  1.1153 +		}
  1.1154 +	Kern::EndAccessCode();
  1.1155 +	return r;
  1.1156 +	}
  1.1157 +
  1.1158 +