📄 loader.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
//
// NK Kernel loader code
//
//
// Module Name:
//
// loader.c
//
// Abstract:
//
// This file implements the NK kernel loader for EXE/DLL
//
//
//------------------------------------------------------------------------------
//
// The loader is derived from the Win32 executable file format spec. The only
// interesting thing is how we load a process. When we load a process, we
// simply schedule a thread in a new process context. That thread (in coredll)
// knows how to read in an executable, and does so. Then it traps into the kernel
// and starts running in the new process. Most of the code below is simply a direct
// implimentation of the executable file format specification
//
//------------------------------------------------------------------------------
#include "kernel.h"
#include "altimports.h"
#include "bldver.h"
#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif
#define SYSTEMDIR L"\\Windows\\"
#define SYSTEMDIRLEN 9
#define DBGDIR L"\\Release\\"
#define DBGDIRLEN 9
#define LOAD_LIBRARY_IN_KERNEL 0x8000
struct KDataStruct *PtrKData;
fslog_t *LogPtr;
BOOL fForceCleanBoot;
BOOL fNoDebugger;
BOOL fDebuggerLoaded;
FREEINFO FreeInfo[MAX_MEMORY_SECTIONS];
MEMORYINFO MemoryInfo;
ROMChain_t FirstROM;
ROMChain_t *ROMChain, *OEMRomChain;
PROMINFO g_pROMInfo;
extern CRITICAL_SECTION VAcs, DbgApiCS, LLcs, ModListcs, PagerCS;
extern BOOL IsCommittedSecureSlot (DWORD addr);
extern PMODULE LoadMUI (HANDLE hModule, LPBYTE BasePtr, e32_lite* eptr);
DWORD ROMDllLoadBase; // this is the low water mark for DLL loaded into per-process's slot
DWORD SharedDllBase; // base of dlls loaded in slot 1
extern PFN_SHIMINITMODULE g_pfnShimInitModule;
extern PFN_SHIMWHICHMOD g_pfnShimWhichMod;
extern PFN_SHIMUNDODEPENDS g_pfnShimUndoDepends;
extern PFN_SHIMIOCONTROL g_pfnShimIoControl;
extern PFN_SHIMGETPROCMODLIST g_pfnShimGetProcModList;
extern PFN_SHIMCLOSEMODULE g_pfnShimCloseModule;
extern PFN_SHIMCLOSEPROCESS g_pfnShimCloseProcess;
DWORD MainMemoryEndAddress, PagedInCount;
DWORD (*pNKEnumExtensionDRAM)(PMEMORY_SECTION pMemSections, DWORD cMemSections);
DWORD (*pOEMCalcFSPages)(DWORD dwMemPages, DWORD dwDefaultFSPages);
DWORD dwOEMCleanPages;
void DbgrNotifyDllLoad (PTHREAD pth, PPROCESS pproc, BOOL fWait, PMODULE pMod);
void DbgrNotifyDllUnload (PTHREAD pth, PPROCESS pproc, BOOL fWait, PMODULE pMod);
typedef void (* NFC_t)(DWORD, DWORD, DWORD, DWORD);
NFC_t pNotifyForceCleanboot;
extern Name *pPath;
extern Name *pInjectDLLs;
extern LPDWORD pIsExiting;
LPName pDbgList;
BOOL IsPreloadedDlls (PMODULE pMod)
{
if (((HANDLE) pMod == hCoreDll) || !strcmpW (L"mscoree.dll", pMod->lpszModName))
return TRUE;
if (pInjectDLLs) {
LPTSTR p = (LPTSTR)(pInjectDLLs->name);
while(*p) {
if (!strcmpW (pMod->lpszModName, p))
return TRUE;
p += (strlenW(p)+1);
}
}
return FALSE;
}
void FreeProcModList ()
{
PMODULELIST pML;
DEBUGCHK (LLcs.OwnerThread == hCurThread);
for (pML = pCurProc->pLastModList; pML; pML = pCurProc->pLastModList) {
pCurProc->pLastModList = pML->pNext;
FreeMem (pML, HEAP_MODLIST);
}
pCurProc->wModCount = 0;
}
#ifdef SH3
extern unsigned int SH3DSP;
#endif
ROMHDR *const volatile pTOC = (ROMHDR *)-1; // Gets replaced by RomLoader with real address
// ROM Header extension. The ROM loader (RomImage) will set the pExtensions field of the table
// of contents to point to this structure. This structure contains the PID and a extra field to point
// to further extensions.
const ROMPID RomExt = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
NULL
};
DWORD DecompressROM(LPBYTE BufIn, DWORD InSize, LPBYTE BufOut, DWORD OutSize, DWORD skip);
void GoToUserTime(void);
void GoToKernTime(void);
WCHAR lowerW(WCHAR ch) {
return ((ch >= 'A') && (ch <= 'Z')) ? (ch - 'A' + 'a') : ch;
}
#pragma prefast(disable: 394, "Kernel local string functions, no buffer overrun risk")
int strcmponeiW(const wchar_t *pwc1, const wchar_t *pwc2) {
while (*pwc1 && (lowerW(*pwc1) == *pwc2)) {
pwc1++;
pwc2++;
}
return (*pwc1 ? 1 : 0);
}
int strcmpdllnameW(LPCWSTR src, LPCWSTR tgt) {
while (*src && (*src == lowerW(*tgt))) {
src++;
tgt++;
}
return ((*tgt && strcmponeiW(tgt,L".dll") && strcmponeiW(tgt,L".cpl")) || (*src && memcmp(src,L".dll",10) && memcmp(src,L".cpl",10))) ? 1 : 0;
}
int strcmpiAandW(LPCHAR lpa, LPCWSTR lpu) {
while (*lpa && (lowerW((WCHAR)*lpa) == lowerW(*lpu))) {
lpa++;
lpu++;
}
return ((*lpa || *lpu) ? 1 : 0);
}
int kstrncmpi(LPCWSTR str1, LPCWSTR str2, int count) {
wchar_t f,l;
if (!count)
return 0;
do {
f = lowerW(*str1++);
l = lowerW(*str2++);
} while (--count && f && (f == l));
return (int)(f - l);
}
int kstrcmpi(LPCWSTR str1, LPCWSTR str2) {
wchar_t f,l;
do {
f = lowerW(*str1++);
l = lowerW(*str2++);
} while (f && (f == l));
return (int)(f - l);
}
void kstrcpyW(LPWSTR p1, LPCWSTR p2) {
while (*p2)
*p1++ = *p2++;
*p1 = 0;
}
#pragma prefast(pop)
o32_lite *FindOptr (o32_lite *optr, int nCnt, DWORD dwAddr)
{
for (dwAddr = ZeroPtr (dwAddr) ; nCnt; nCnt --, optr ++) {
if ((DWORD) (dwAddr - ZeroPtr(optr->o32_realaddr)) < optr->o32_vsize) {
return optr;
}
}
return NULL;
}
typedef BOOL (* OEMLoadInit_t)(LPWSTR lpszName);
typedef BOOL (* OEMLoadModule_t)(LPBYTE lpData, DWORD cbData);
OEMLoadInit_t pOEMLoadInit;
OEMLoadModule_t pOEMLoadModule;
ERRFALSE(!OEM_CERTIFY_FALSE);
ULONG FakeHDException (PEXCEPTION_RECORD ExceptionRecord, CONTEXT *ContextRecord, BOOLEAN SecondChance);
//------------------------------------------------------------------------------
// check if a particular module can be debugged
//------------------------------------------------------------------------------
BOOL ChkDebug (openexe_t *oeptr)
{
BOOL fRet = TRUE, dwAttrib;
DEBUGCHK (FA_PREFIXUP & oeptr->filetype);
dwAttrib = (FA_DIRECTROM & oeptr->filetype)? oeptr->tocptr->dwFileAttributes : oeptr->dwExtRomAttrib;
if (dwAttrib & MODULE_ATTR_NODEBUG) {
if (pCurProc->hDbgrThrd || pCurProc->DbgActive || fDebuggerLoaded) {
fRet = FALSE;
} else {
// set both the process flag and the global flag to prevent loading KD
// or attaching debugger to this process
pCurProc->fNoDebug = fNoDebugger = TRUE;
}
}
DEBUGMSG(ZONE_LOADER1,(TEXT("ChkDebug returns %d\r\n"), fRet));
return fRet;
}
//------------------------------------------------------------------------------
// check if we should load a module from debug directory
//------------------------------------------------------------------------------
BOOL IsInDbgList (LPCWSTR pszName)
{
if (pDbgList) {
LPCWSTR pTrav = pDbgList->name;
do {
if (!kstrcmpi (pszName, pTrav)) {
return TRUE;
}
pTrav += strlenW (pTrav) + 1;
} while (*pTrav);
}
return FALSE;
}
//------------------------------------------------------------------------------
// update the list for modules to be loaded from debug directory
// Note: nLen is the total length, including double 0 at the end
//------------------------------------------------------------------------------
BOOL SetDbgList (LPCWSTR pList, int nTotalLen)
{
LPName pNewList = NULL;
if (pList) {
int idx = 0;
// validate the list
if (nTotalLen < 3) { // at least 2 zeros + a charactor
return FALSE;
}
// make sure it's in multi-sz format
do {
idx += strlenW (pList + idx) + 1;
} while ((idx < nTotalLen) && pList[idx]);
if ((idx > nTotalLen) || pList[idx]) {
return FALSE;
}
// allocate memory
if (!(pNewList = AllocName (nTotalLen * sizeof (WCHAR)))) {
// out of memory or list too big
return FALSE;
}
// copy the list
memcpy (pNewList->name, pList, nTotalLen * sizeof(WCHAR));
}
// update the list
EnterCriticalSection (&LLcs);
if (pDbgList) {
FreeName (pDbgList);
}
pDbgList = pNewList;
LeaveCriticalSection (&LLcs);
return TRUE;
}
//------------------------------------------------------------------------------
// read O32/E32 from filesys for FT_EXTIMAGE/FT_EXTXIP
//------------------------------------------------------------------------------
BOOL ReadExtImageInfo (HANDLE hf, DWORD dwCode, DWORD cbSize, LPVOID pBuf)
{
DWORD cbRead;
return SC_DeviceIoControl (hf, dwCode, NULL, 0, pBuf, cbSize, &cbRead, NULL)
&& (cbSize == cbRead);
}
DWORD CertVerify (HANDLE hFile, HANDLE *phTok, LPCWSTR pszName, DWORD dwFlags);
//------------------------------------------------------------------------------
// returns getlasterror code, or 0 for success
//------------------------------------------------------------------------------
DWORD
VerifyBinary(
openexe_t *oeptr,
LPWSTR lpszName,
LPBYTE pbTrustLevel,
HANDLE *phTok
)
{
HANDLE hTok = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -