os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mcodeseg.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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),(LPWSTR)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),(LPWSTR)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((LPCWSTR)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((LPCWSTR)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          {
   821 			r=KErrNotSupported;
   822          }
   823 		else
   824          {
   825 			r=RegisterCodeSeg(h);
   826          }
   827 
   828 		if (r == KErrNone)
   829          {
   830 			r = CopyDataBss();
   831          }
   832 		}
   833 	if (r==KErrNone && aInfo.iTotalDataSize && !iAlwaysLoaded)
   834 		{
   835 		iMark|=EMarkData|EMarkDataPresent;
   836 		if (!exe)
   837 			iMark|=EMarkDataInit;
   838 		}
   839 
   840 	if (r==KErrNone)
   841 		r=ProcessImports(p);
   842 	__KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
   843 	DCodeSeg::Signal();
   844 	return r;
   845 	}
   846 
   847 TInt DWin32CodeSeg::RegisterCodeSeg(HMODULE aModule)
   848 	{
   849 	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %C RegisterCodeSeg(%08x)", this, aModule));
   850 	Emulator::TModule etm(aModule);
   851 	const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
   852 	iRunAddress = (TLinAddr)aModule;
   853 	iSize = nth->OptionalHeader.SizeOfImage;
   854 	SWin32Module w32m;
   855 	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
   856 	w32m.iCodeSeg=this;
   857 	TInt r=KErrNone;
   858 	TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
   859 	if (ix>=0)
   860 		{
   861 		SWin32Module& wmr=MM::Win32Modules[ix];
   862 		__ASSERT_ALWAYS(!wmr.iCodeSeg, MM::Panic(MM::EInvalidSharedModule));
   863 		wmr.iCodeSeg=this;
   864 		iAlwaysLoaded=ETrue;
   865 		}
   866 	else
   867 		r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
   868 	if (r==KErrNone)
   869 		{
   870 		iModuleHandle=aModule;
   871 		iCodeSegId=++MM::NextCodeSegId;
   872 		}
   873 	return r;
   874 	}
   875 
   876 TInt DWin32CodeSeg::CreateAlreadyLoaded(HMODULE aModule, TInt aDepCount)
   877 	{
   878 	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %08x CreateAlreadyLoaded(%08x,%d)", this, aModule, aDepCount));
   879 	Emulator::TModule etm(aModule);
   880 	etm.GetUids(iUids);
   881 	TInt32 uid1=iUids.iUid[0].iUid;
   882 	if (uid1!=KDynamicLibraryUidValue)	// only implicitly load DLLs
   883 		return KErrNotSupported;
   884 	
   885 	WCHAR name[MAX_PATH+1];
   886 	TInt r=Emulator::GetModuleFileName(aModule, name);
   887 	if (!r)
   888 		return Emulator::LastError();
   889 	TUint8 name8[MAX_PATH+1];
   890 	TruncToNarrow(name8,(const TUint16*)name,-1);
   891 
   892    //SL:
   893    __KTRACE_OPT(KDLL, Kern::Printf("Loading library %s", name8));
   894 
   895 	TPtrC fpptr((const TText*)name8);
   896 	TInt slash=fpptr.LocateReverse('\\');
   897 	TPtrC nptr=fpptr.Mid(slash+1);
   898 	iFileName=HBuf::New(nptr);
   899 	if (!iFileName)
   900 		return KErrNoMemory;
   901 	iRootName.Set(*iFileName);
   902 	iExtOffset = iFileName->LocateReverse('.');
   903 	if (iExtOffset==KErrNotFound)
   904 		iExtOffset = iFileName->Length();
   905 	iModuleVersion = 0x00010000u;
   906 	iDepCount=aDepCount;
   907 	if (iDepCount)
   908 		{
   909 		iDeps=(DCodeSeg**)Kern::AllocZ(iDepCount*sizeof(DCodeSeg*));
   910 		if (!iDeps)
   911 			return KErrNoMemory;
   912 		}
   913 	iWinInstance = Emulator::LoadLibrary(name);
   914 	if (!iWinInstance)
   915 		return Emulator::LastError();
   916 	iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, "_E32Dll");
   917 	if (!iFileEntryPoint)
   918 		return KErrNotSupported;
   919 	iEntryPtVeneer = iFileEntryPoint;
   920 	r=RegisterCodeSeg(aModule);
   921 	if (r == KErrNone)
   922 		r = CopyDataBss();
   923 	if (r == KErrNone)
   924 		r = CodeSegsByName.InsertInOrderAllowRepeats(this, &CompareCodeSegsByName);
   925 	if (r == KErrNone)
   926 		r = CodeSegsByAddress.Add(this);
   927 	if (r==KErrNone)
   928 		{
   929 		GlobalList.Add(&iLink);
   930 		iAsyncDeleteNext=this;
   931 		}
   932 	__KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
   933 	return r;
   934 	}
   935 
   936 TInt DWin32CodeSeg::CopyDataBss()
   937 	{
   938 	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::CopyDataBss()"));
   939 
   940 	Emulator::TModule etm(iModuleHandle);
   941 	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
   942 	if (!(hdr->iFlags & KEmulatorImageFlagAllowDllData))
   943 		return KErrNone;
   944 	const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
   945 	const IMAGE_SECTION_HEADER* bss=etm.SectionHeader(KWin32SectionName_EpocBss);
   946 	if (data)
   947 		{
   948 		iRealDataSize = data->Misc.VirtualSize;
   949 		iDataDest = (TLinAddr)etm.Translate(data->VirtualAddress);
   950 		iDataCopy = Kern::Alloc(iRealDataSize);
   951 		if (!iDataCopy)
   952 			return KErrNoMemory;
   953 		memcpy(iDataCopy, (const TAny*)iDataDest, iRealDataSize);
   954 		}
   955 	if (bss)
   956 		{
   957 		iRealBssSize = bss->Misc.VirtualSize;
   958 		iBssDest = (TLinAddr)etm.Translate(bss->VirtualAddress);
   959 		}
   960 	return KErrNone;
   961 	}
   962 
   963 TInt DWin32CodeSeg::ProcessImports(DProcess* aProcess)
   964 	{
   965 	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::ProcessImports(%O)", aProcess));
   966 	iModuleList=new DModuleList(this, aProcess);
   967 	if (!iModuleList)
   968 		return KErrNoMemory;
   969 	TInt r=iModuleList->GatherDependencies(iModuleHandle);
   970 	if (r!=KErrNone)
   971 		return r;
   972 	TInt ix=iModuleList->Find((TInt)iModuleHandle);
   973 	DModuleList::SModule& mm=iModuleList->iModules[ix];
   974 	r=iModuleList->CompileDepLists();
   975 	if (r==KErrNone)
   976 		{
   977 		iModuleList->SetFlags();
   978 		r=iModuleList->LoadDependencies();
   979 		if (r==KErrNone)
   980 			{
   981 			if ((mm.iFlags&(DModuleList::EFlagDataPresent|DModuleList::EFlagExeInTree)) && !(mm.iFlags&DModuleList::EFlagAlwaysLoaded))
   982 				{
   983 				if (aProcess)
   984 					{
   985 					iExeCodeSeg=aProcess->CodeSeg();
   986 					SetAttachProcess(aProcess);
   987 					}
   988 				}
   989 			iModuleList->LinkDependencies();
   990 			}
   991 		}
   992 	return r;
   993 	}
   994 
   995 TInt DWin32CodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
   996 	{
   997 	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded()"));
   998 	TInt r=KErrNone;
   999 	if (iModuleList)
  1000 		{
  1001 		r=iModuleList->Loaded();
  1002 		if (r==KErrNone)
  1003 			{
  1004 			DBase::Delete(iModuleList);
  1005 			iModuleList=NULL;
  1006 			}
  1007 		}
  1008 	if (r==KErrNone)
  1009 		r=DCodeSeg::Loaded(aInfo);
  1010 	__KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded() - %d", r));
  1011 	return r;
  1012 	}
  1013 
  1014 void DWin32CodeSeg::ReadExportDir(TUint32*)
  1015 	{
  1016 	// not needed
  1017 	}
  1018 
  1019 TBool DWin32CodeSeg::FindCheck(DProcess* /*aProcess*/)
  1020 	{
  1021 	// We never create multiple copies of the same code segment,
  1022 	// so if code segment exists, allow it to be found.
  1023 	// CodeSegOpen will fail if it is incompatible.
  1024 	return ETrue;
  1025 	}
  1026 
  1027 TBool DWin32CodeSeg::OpenCheck(DProcess* aProcess)
  1028 	{
  1029 	__KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
  1030 	if (!aProcess)
  1031 		return EFalse;	// never reuse EXE code segments
  1032 	return ETrue;
  1033 	}
  1034 
  1035 TLibraryFunction DWin32CodeSeg::Lookup(TInt aOrdinal)
  1036 //
  1037 // Find an exported function by ordinal
  1038 //
  1039 	{
  1040 	TLibraryFunction f = NULL;
  1041 	if (aOrdinal != 0)
  1042 		{
  1043 			
  1044 		f = (TLibraryFunction)Emulator::GetProcAddress(iWinInstance, (const char *)aOrdinal);
  1045 		if ((TLinAddr)f == iFileEntryPoint)
  1046 			f = NULL;
  1047 		}
  1048 	else
  1049 		{
  1050 		// Find 0th Ordinal, which should be named symbol export data, from named data segment
  1051 		Emulator::TModule etm(iModuleHandle);
  1052 		f  = (TLibraryFunction)etm.Section(KWin32SectionName_NmdExpData);
  1053 		}
  1054  	__KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Lookup(%d)->%08x",aOrdinal,f));
  1055 	return f;
  1056 	}
  1057 
  1058 DCodeSeg* DCodeSeg::FindRomCode(const TAny*)
  1059 	{
  1060 	// never used
  1061 	return NULL;
  1062 	}
  1063 
  1064 void DWin32CodeSeg::InitData()
  1065 	{
  1066 	}
  1067 
  1068 TInt DWin32CodeSeg::GetMemoryInfo(TModuleMemoryInfo&, DProcess*)
  1069 	{
  1070 	return KErrNotSupported;
  1071 	}
  1072 
  1073 void DWin32CodeSeg::Info(TCodeSegCreateInfo& aInfo)
  1074 	{
  1075 	Emulator::TModule etm(iModuleHandle);
  1076 	const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
  1077 	const IMAGE_EXPORT_DIRECTORY* exd=
  1078 		(const IMAGE_EXPORT_DIRECTORY*)etm.Translate(nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  1079 	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
  1080 	TBool isExe = hdr && hdr->iUids[0].iUid==KExecutableImageUidValue;
  1081 	const IMAGE_SECTION_HEADER* text=etm.SectionHeader(KWin32SectionName_Text);
  1082 	const IMAGE_SECTION_HEADER* rdata=etm.SectionHeader(KWin32SectionName_RData);
  1083 	const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
  1084 	if (!isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
  1085 		data = NULL;
  1086 	aInfo.iTextSize=text->Misc.VirtualSize;
  1087 	aInfo.iCodeSize=text->Misc.VirtualSize;
  1088 	if (rdata)
  1089 		aInfo.iCodeSize+=rdata->Misc.VirtualSize;
  1090 	aInfo.iDataSize=data ? (data->SizeOfRawData) : 0;
  1091 	aInfo.iBssSize=data ? (data->Misc.VirtualSize-data->SizeOfRawData) : 0;
  1092 	aInfo.iTotalDataSize=aInfo.iDataSize+aInfo.iBssSize;
  1093 	aInfo.iExportDir=(TLinAddr)exd;
  1094 	aInfo.iExportDirCount=exd ? exd->NumberOfFunctions : 0;
  1095 	aInfo.iCodeLoadAddress=(TLinAddr)etm.Translate(text->VirtualAddress);
  1096 	aInfo.iCodeRunAddress=aInfo.iCodeLoadAddress;
  1097 	aInfo.iDataLoadAddress=data ? (TLinAddr)etm.Translate(data->VirtualAddress) : 0;
  1098 	aInfo.iDataRunAddress=aInfo.iDataLoadAddress;
  1099 	DCodeSeg::Info(aInfo);
  1100 	}
  1101 
  1102 TLinAddr DCodeSeg::ExceptionDescriptor()
  1103 	{
  1104 	return 0;	// not used on emulator
  1105 	}
  1106 
  1107 TInt MM::RegisterModule(HMODULE aModule)
  1108 	{
  1109 	__KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule %08x",aModule));
  1110 	SWin32Module w32m;
  1111 	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
  1112 	w32m.iCodeSeg=NULL;
  1113 	TInt r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
  1114 	__KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule ret %d",r));
  1115 	return r;
  1116 	}
  1117 
  1118 _LIT(KRomSysBin, "Z:\\sys\\bin");
  1119 
  1120 // Massage file names returned for stuff in EPOCROOT\epoc32\release\wins\xxxx\
  1121 // in order to make them appear to be in z:\system\libs
  1122 void P::NormalizeExecutableFileName(TDes& a)
  1123 	{
  1124 	__KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName %lS", &a));
  1125 	if (a.Length()<3 || a[1]!=':' || a[2]!='\\')
  1126 		{
  1127 		// don't have a drive so assume in 'ROM'
  1128 		TFileName initial(a);
  1129 		a=KRomSysBin();
  1130 		if (initial.Length()==0 || initial[0]!='\\')
  1131 			a.Append('\\');
  1132 		a+=initial;
  1133 		__KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName -> %lS", &a));
  1134 		}
  1135 	}
  1136 
  1137 TInt LookupDllUid(TInt aModule)
  1138 	{
  1139 	TInt r = KDllUid_Default;
  1140 	Kern::AccessCode();
  1141 	SWin32Module w32m;
  1142 	w32m.iWin32ModuleHandle=(TLinAddr)aModule;
  1143 	TInt ix;
  1144 	MM::Win32Modules.SpecificFindInUnsignedKeyOrder(w32m, ix, EArrayFindMode_Last);
  1145 	if (ix>0)
  1146 		{
  1147 		DWin32CodeSeg* pS = MM::Win32Modules[ix-1].iCodeSeg;
  1148 		if (pS && pS->iFileEntryPoint==(TLinAddr)aModule)
  1149 			r = pS->iCodeSegId;
  1150 		}
  1151 	Kern::EndAccessCode();
  1152 	return r;
  1153 	}
  1154 
  1155