📄 loader.c
字号:
while (blockptr->imp_lookup) {
FreeLibraryByName((LPCHAR)pMod->BasePtr+blockptr->imp_dllname);
blockptr++;
}
}
FreeModuleMemory(pMod);
}
return TRUE;
} else
return FALSE;
}
BOOL FreeOneLibrary(PMODULE pMod, BOOL bCallEntry) {
BOOL retval = FALSE;
if (!InitBreadcrumbs())
KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY);
else {
retval = FreeOneLibraryPart2(pMod, bCallEntry);
FinishBreadcrumbs();
}
return retval;
}
// Decrement ref count on library, freeing if needed
void FreeLibraryByName(LPCHAR lpszName) {
PMODULE pMod;
LPWSTR pTrav1;
LPBYTE pTrav2;
for (pMod = pModList; pMod; pMod = pMod->pMod) {
for (pTrav1 = pMod->lpszModName, pTrav2 = lpszName; *pTrav1 && (*pTrav1 == (WCHAR)*pTrav2); pTrav1++, pTrav2++)
;
if (*pTrav1 == (WCHAR)*pTrav2) {
FreeOneLibraryPart2(pMod, 1);
return;
}
}
}
void KAsciiToUnicode(LPWSTR wchptr, LPBYTE chptr, int maxlen) {
while ((maxlen-- > 1) && *chptr) {
*wchptr++ = (WCHAR)*chptr++;
}
*wchptr = 0;
}
void KUnicodeToAscii(LPCHAR chptr, LPCWSTR wchptr, int maxlen) {
while ((maxlen-- > 1) && *wchptr) {
*chptr++ = (CHAR)*wchptr++;
}
*chptr = 0;
}
// Do imports from an exe/dll
#define MAX_DLLNAME_LEN 32
DWORD DoImports(e32_lite *eptr, o32_lite *oarry, ulong BaseAddr, ulong BaseAdj) {
ulong blocksize;
LPDWORD ltptr, atptr;
PMODULE pMod;
DWORD retval, loop;
WCHAR ucptr[MAX_DLLNAME_LEN];
struct ImpHdr *blockptr, *blockstart;
struct ImpProc *impptr;
if (!(blocksize = eptr->e32_unit[IMP].size)) // No relocations
return 0;
blockstart = blockptr = (struct ImpHdr *)(BaseAddr+eptr->e32_unit[IMP].rva);
while (blockptr->imp_lookup) {
KAsciiToUnicode(ucptr,(LPCHAR)BaseAddr+blockptr->imp_dllname,MAX_DLLNAME_LEN);
pMod = LoadOneLibraryPart2(ucptr,1,0);
if (!pMod) {
if (!(retval = GetLastError()))
retval = ERROR_OUTOFMEMORY;
while (blockstart != blockptr) {
FreeLibraryByName((LPBYTE)BaseAddr+blockstart->imp_dllname);
blockstart++;
}
return retval;
}
DEBUGMSG(ZONE_LOADER1,(TEXT("Doing imports from module %a (pMod %8.8lx)\r\n"),
BaseAddr+blockptr->imp_dllname,pMod));
ltptr = (LPDWORD)(BaseAddr+blockptr->imp_lookup);
atptr = (LPDWORD)(BaseAddr+blockptr->imp_address);
while (*ltptr) {
if (*ltptr & 0x80000000)
retval = ResolveImpOrd(pMod,*ltptr&0x7fffffff);
else {
impptr = (struct ImpProc *)((*ltptr&0x7fffffff)+BaseAddr);
retval = ResolveImpHintStr(pMod,impptr->ip_hint,(LPBYTE)impptr->ip_name);
}
if (*atptr != retval) {
__try {
*atptr = retval;
} __except (EXCEPTION_EXECUTE_HANDLER) {
// this is the case for the -optidata linker flag, where the idata is in the .rdata
// section, and thus read-only
o32_lite *dataptr;
VirtualFree(atptr,4,MEM_DECOMMIT);
for (loop = 0; loop < eptr->e32_objcnt; loop++) {
dataptr = &oarry[loop];
if ((dataptr->o32_realaddr <= (DWORD)atptr) && (dataptr->o32_realaddr+dataptr->o32_vsize > (DWORD)atptr)) {
dataptr->o32_access = PAGE_EXECUTE_READWRITE;
break;
}
}
if (loop == eptr->e32_objcnt)
return ERROR_BAD_EXE_FORMAT;
*atptr = retval;
}
} else
DEBUGCHK(*atptr == retval);
ltptr++;
atptr++;
}
blockptr++;
}
return 0;
}
// Adjust permissions on regions, decommitting discardable ones
BOOL AdjustRegions(e32_lite *eptr, o32_lite *oarry) {
int loop;
DWORD oldprot;
for (loop = 0; loop < eptr->e32_objcnt; loop++) {
if (oarry->o32_flags & IMAGE_SCN_MEM_DISCARDABLE) {
VirtualFree((LPVOID)oarry->o32_realaddr,oarry->o32_vsize,MEM_DECOMMIT);
oarry->o32_realaddr = 0;
} else
VirtualProtect((LPVOID)oarry->o32_realaddr,oarry->o32_vsize,oarry->o32_access,&oldprot);
oarry++;
}
return TRUE;
}
BOOL GetNameFromOE(CEOIDINFO *pceoi, openexe_t *oeptr) {
LPWSTR pstr;
LPBYTE pbyte;
BOOL retval = 1;
__try {
if (oeptr->filetype == FT_ROMIMAGE) {
memcpy(pceoi->infFile.szFileName,L"\\Windows\\",9*sizeof(WCHAR));
pstr = &pceoi->infFile.szFileName[9];
pbyte = oeptr->tocptr->lpszFileName;
while (*pbyte)
*pstr++ = (WCHAR)*pbyte++;
*pstr = 0;
} else if (oeptr->bIsOID) {
CEGUID sysguid;
CREATE_SYSTEMGUID(&sysguid);
if (!(CeOidGetInfoEx(&sysguid,oeptr->ceOid,pceoi)) || (pceoi->wObjType != OBJTYPE_FILE))
retval = 0;
} else
kstrcpyW(pceoi->infFile.szFileName,oeptr->lpName->name);
} __except (EXCEPTION_EXECUTE_HANDLER) {
retval = 0;
}
return retval;
}
BOOL ReopenExe(openexe_t *oeptr, LPCWSTR pExeName, BOOL bAllowPaging) {
DWORD bytesread;
BY_HANDLE_FILE_INFORMATION bhfi;
if (!(oeptr->lpName = AllocName(MAX_PATH)))
return 0;
if ((oeptr->hf = CreateFileW(pExeName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0)) == INVALID_HANDLE_VALUE) {
FreeName(oeptr->lpName);
return 0;
}
oeptr->bIsOID = 1;
oeptr->filetype = FT_OBJSTORE;
if (GetFileInformationByHandle(oeptr->hf,&bhfi) && (bhfi.dwOID != (ULONG)INVALID_HANDLE_VALUE)) {
FreeName(oeptr->lpName);
oeptr->ceOid = bhfi.dwOID;
} else {
LPName pName;
oeptr->bIsOID = 0;
if (pName = AllocName((strlenW(pExeName)+1)*2)) {
FreeName(oeptr->lpName);
oeptr->lpName = pName;
}
kstrcpyW(oeptr->lpName->name,pExeName);
}
oeptr->pagemode = (bAllowPaging && !(pTOC->ulKernelFlags & KFLAG_DISALLOW_PAGING) &&
ReadFileWithSeek(oeptr->hf,0,0,0,0,0,0)) ? PM_FULLPAGING : PM_NOPAGING;
if ((SetFilePointer(oeptr->hf,0x3c,0,FILE_BEGIN) != 0x3c) ||
!ReadFile(oeptr->hf,(LPBYTE)&oeptr->offset,4,&bytesread,0) || (bytesread != 4)) {
CloseExe(oeptr);
return 0;
}
return 1;
}
openexe_t globoe;
BOOL globpageallowed;
HANDLE JitOpenFile(LPCWSTR pName) {
CALLBACKINFO cbi;
cbi.hProc = ProcArray[0].hProc;
cbi.pfn = (FARPROC)ReopenExe;
cbi.pvArg0 = (LPVOID)&globoe;
if (!PerformCallBack4Int(&cbi,pName,globpageallowed))
return INVALID_HANDLE_VALUE;
if (globoe.filetype != FT_OBJSTORE) {
CloseExe(&globoe);
return INVALID_HANDLE_VALUE;
}
return globoe.hf;
}
void JitCloseFile(HANDLE hFile) {
DEBUGCHK(globoe.hf == hFile);
CloseExe(&globoe);
}
// Load E32 header
DWORD ModuleJit(LPCWSTR, LPWSTR, HANDLE *);
// defined in kmisc.c
extern BOOL fJitIsPresent;
DWORD LoadE32(openexe_t *oeptr, e32_lite *eptr, DWORD *lpflags, DWORD *lpEntry, BOOL bIgnoreCPU, BOOL bAllowPaging, LPBYTE pbTrustLevel) {
e32_exe e32;
e32_exe *e32ptr;
e32_rom *e32rptr;
int bytesread;
CEOIDINFO ceoi;
CALLBACKINFO cbi;
top:
if (oeptr->filetype == FT_PPFSFILE) {
DEBUGMSG(ZONE_LOADER1,(TEXT("PEBase at %8.8lx\r\n"),oeptr->offset));
if (rlseek(oeptr->hppfs,oeptr->offset,0) != (int)oeptr->offset)
return ERROR_BAD_EXE_FORMAT;
if (rread(oeptr->hppfs,(LPBYTE)&e32,sizeof(e32_exe)) != sizeof(e32_exe))
return ERROR_BAD_EXE_FORMAT;
e32ptr = &e32;
} else if (oeptr->filetype == FT_OBJSTORE) {
DEBUGMSG(ZONE_LOADER1,(TEXT("PEBase at %8.8lx\r\n"),oeptr->offset));
if (SetFilePointer(oeptr->hf,oeptr->offset,0,FILE_BEGIN) != oeptr->offset)
return ERROR_BAD_EXE_FORMAT;
if (!ReadFile(oeptr->hf,(LPBYTE)&e32,sizeof(e32_exe),&bytesread,0) || (bytesread != sizeof(e32_exe)))
return ERROR_BAD_EXE_FORMAT;
e32ptr = &e32;
} else {
e32rptr = (struct e32_rom *)(oeptr->tocptr->ulE32Offset);
eptr->e32_objcnt = e32rptr->e32_objcnt;
if (lpflags)
*lpflags = e32rptr->e32_imageflags;
if (lpEntry)
*lpEntry = e32rptr->e32_entryrva;
eptr->e32_vbase = e32rptr->e32_vbase;
eptr->e32_vsize = e32rptr->e32_vsize;
if (e32rptr->e32_subsys == IMAGE_SUBSYSTEM_WINDOWS_CE_GUI) {
eptr->e32_cevermajor = (BYTE)e32rptr->e32_subsysmajor;
eptr->e32_ceverminor = (BYTE)e32rptr->e32_subsysminor;
} else {
eptr->e32_cevermajor = 1;
eptr->e32_ceverminor = 0;
}
eptr->e32_stackmax = e32rptr->e32_stackmax;
memcpy(&eptr->e32_unit[0],&e32rptr->e32_unit[0],
sizeof(struct info)*LITE_EXTRA);
eptr->e32_sect14rva = e32rptr->e32_sect14rva;
eptr->e32_sect14size = e32rptr->e32_sect14size;
return 0;
}
if (*(LPDWORD)e32ptr->e32_magic != 0x4550)
return ERROR_BAD_EXE_FORMAT;
if (!bIgnoreCPU && fJitIsPresent && e32ptr->e32_unit[14].rva) {
if (GetNameFromOE(&ceoi,oeptr)) {
DWORD dwRet;
CloseExe(oeptr);
globpageallowed = bAllowPaging;
dwRet = ModuleJit(ceoi.infFile.szFileName,0,&oeptr->hf);
switch (dwRet) {
/*
We use -1 in the case where ModuleJit is a stub or
when the source file is not a CEF file. We want to
behave as if the translator was never invoked
since URT files will get dealt with in CreateNewProc,
long after the CEF translators are done.
*/
case -1:
break;
case OEM_CERTIFY_FALSE:
return NTE_BAD_SIGNATURE;
case OEM_CERTIFY_TRUST:
case OEM_CERTIFY_RUN:
if (pbTrustLevel)
*pbTrustLevel = (BYTE)dwRet;
memcpy(oeptr,&globoe,sizeof(openexe_t));
goto top;
default:
cbi.hProc = ProcArray[0].hProc;
cbi.pfn = (FARPROC)ReopenExe;
cbi.pvArg0 = (LPVOID)oeptr;
if (!PerformCallBack4Int(&cbi,ceoi.infFile.szFileName,bAllowPaging))
return ERROR_BAD_EXE_FORMAT;
}
}
}
if (!bIgnoreCPU && !e32ptr->e32_unit[14].rva && (e32ptr->e32_cpu != THISCPUID)) {
#if defined(MIPS16SUPPORT)
if (e32ptr->e32_cpu != IMAGE_FILE_MACHINE_MIPS16)
return ERROR_BAD_EXE_FORMAT;
#elif defined(THUMBSUPPORT)
if (e32ptr->e32_cpu != IMAGE_FILE_MACHINE_THUMB)
return ERROR_BAD_EXE_FORMAT;
#else
return ERROR_BAD_EXE_FORMAT;
#endif
}
eptr->e32_objcnt = e32ptr->e32_objcnt;
if (lpflags)
*lpflags = e32ptr->e32_imageflags;
if (lpEntry)
*lpEntry = e32ptr->e32_entryrva;
eptr->e32_vbase = e32ptr->e32_vbase;
eptr->e32_vsize = e32ptr->e32_vsize;
if (e32ptr->e32_subsys == IMAGE_SUBSYSTEM_WINDOWS_CE_GUI) {
eptr->e32_cevermajor = (BYTE)e32ptr->e32_subsysmajor;
eptr->e32_ceverminor = (BYTE)e32ptr->e32_subsysminor;
} else {
eptr->e32_cevermajor = 1;
eptr->e32_ceverminor = 0;
}
if ((eptr->e32_cevermajor > 2) || ((eptr->e32_cevermajor == 2) && (eptr->e32_ceverminor >= 2)))
eptr->e32_stackmax = e32ptr->e32_stackmax;
else
eptr->e32_stackmax = 64*1024; // backward compatibility
if ((eptr->e32_cevermajor > CE_VERSION_MAJOR) ||
((eptr->e32_cevermajor == CE_VERSION_MAJOR) && (eptr->e32_ceverminor > CE_VERSION_MINOR))) {
return ERROR_OLD_WIN_VERSION;
}
eptr->e32_sect14rva = e32ptr->e32_unit[14].rva;
eptr->e32_sect14size = e32ptr->e32_unit[14].size;
memcpy(&eptr->e32_unit[0],&e32ptr->e32_unit[0],
sizeof(struct info)*LITE_EXTRA);
return 0;
}
BOOL PageInPage(openexe_t *oeptr, LPVOID pMem2, DWORD offset, o32_lite *o32ptr, DWORD size) {
DWORD bytesread;
BOOL retval = TRUE;
DEBUGCHK(PagerCS.OwnerThread == hCurThread);
Le
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -