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