📄 loader.c
字号:
/* * NK Kernel loader code * * Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. * * 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 contect. 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"#define SYSTEMDIR L"\\Windows\\"#define SYSTEMDIRLEN 9struct KDataStruct *PtrKData;fslog_t *LogPtr;FREEINFO FreeInfo[2];MEMORYINFO MemoryInfo;ROMChain_t FirstROM;ROMChain_t *ROMChain, *OEMRomChain;extern CRITICAL_SECTION VAcs, DbgApiCS, LLcs, ModListcs, PagerCS;DWORD MainMemoryEndAddress, PagedInCount;typedef void (* NFC_t)(DWORD, DWORD, DWORD, DWORD);NFC_t pNotifyForceCleanboot;extern Name *pPath;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 Decompress(LPBYTE BufIn, DWORD InSize, LPBYTE BufOut, DWORD OutSize, DWORD skip);void GoToUserTime(void);void GoToKernTime(void);int currcrumb = -1;#define SetBreadcrumb(P) ((P)->breadcrumb |= (1<<currcrumb))#define ClearBreadcrumb(P) ((P)->breadcrumb &= ~(1<<currcrumb))#define HasBreadcrumb(P) ((P)->breadcrumb & (1<<currcrumb))_inline BOOL InitBreadcrumbs() { if (currcrumb == 31) { DEBUGCHK(0); return FALSE; } currcrumb++; return TRUE;}void FinishBreadcrumbs() { PMODULE pMod; DEBUGCHK(currcrumb != -1); DEBUGCHK(currcrumb < 32); for (pMod = pModList; pMod; pMod = pMod->pMod) ClearBreadcrumb(pMod); currcrumb--;}WCHAR lowerW(WCHAR ch) { return ((ch >= 'A') && (ch <= 'Z')) ? (ch - 'A' + 'a') : ch;}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, LPWSTR lpu) { while (*lpa && (lowerW((WCHAR)*lpa) == lowerW(*lpu))) { lpa++; lpu++; } return ((*lpa || *lpu) ? 1 : 0);}int kstrncmpi(LPWSTR str1, LPWSTR 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(LPWSTR str1, LPWSTR 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;}typedef BOOL (* OEMLoadInit_t)(LPWSTR lpszName);typedef BOOL (* OEMLoadModule_t)(LPBYTE lpData, DWORD cbData);OEMLoadInit_t pOEMLoadInit;OEMLoadModule_t pOEMLoadModule;ERRFALSE(!OEM_CERTIFY_FALSE);// returns getlasterror code, or 0 for successDWORD VerifyBinary(openexe_t *oeptr, LPWSTR lpszName, LPBYTE pbTrustLevel) {#define VBSIZE 1024 BYTE Buf[VBSIZE]; int iTrust; DWORD len, pos, size, bytesread; if ((oeptr->filetype == FT_ROMIMAGE) || !pOEMLoadInit || !pOEMLoadModule) return 0; if (!pOEMLoadInit(lpszName)) return (DWORD)NTE_BAD_SIGNATURE; if (oeptr->filetype == FT_PPFSFILE) len = rlseek(oeptr->hppfs,0,2); else len = SetFilePointer(oeptr->hf,0,0,2); for (pos = 0; pos < len; pos += size) { size = ((len - pos) > VBSIZE ? VBSIZE : (len - pos)); if (oeptr->filetype == FT_PPFSFILE) { if (rreadseek(oeptr->hppfs,Buf,size,pos) != (int)size) return (DWORD)NTE_BAD_SIGNATURE; } else { if (!ReadFileWithSeek(oeptr->hf,Buf,size,&bytesread,0,pos,0) || (bytesread != size)) return (DWORD)NTE_BAD_SIGNATURE; } if (!pOEMLoadModule(Buf,size)) return (DWORD)NTE_BAD_SIGNATURE; } if (!(iTrust = pOEMLoadModule(0,0))) return (DWORD)NTE_BAD_SIGNATURE; if (iTrust != OEM_CERTIFY_TRUST) *pbTrustLevel = KERN_TRUST_RUN; return 0;}BOOL OpenExe(LPWSTR lpszName, openexe_t *oeptr, BOOL bIsDLL, BOOL bAllowPaging) { static OEinfo_t OEinfo; return SafeOpenExe(lpszName,oeptr,bIsDLL,bAllowPaging,&OEinfo);}BOOL SafeOpenExe(LPWSTR lpszName, openexe_t *oeptr, BOOL bIsDLL, BOOL bAllowPaging, OEinfo_t *poeinfo) { CEGUID sysguid; TOCentry *tocptr; int loop, plainlen, totlen, copylen; LPWSTR nameptr, p2; BOOL inWin, isAbs; DWORD dwLastError; DWORD bytesread; HANDLE hFind; DEBUGMSG(ZONE_OPENEXE,(TEXT("OpenExe: %s\r\n"),lpszName)); dwLastError = KGetLastError(pCurThread); isAbs = ((*lpszName == '\\') || (*lpszName == '/')); totlen = strlenW(lpszName); nameptr = lpszName + totlen; while ((nameptr != lpszName) && (*nameptr != '\\') && (*nameptr != '/')) nameptr--; if ((*nameptr == '\\') || (*nameptr == '/')) nameptr++; inWin = 0; if ((nameptr != lpszName) && (nameptr != lpszName+1)) { if (((nameptr == lpszName + SYSTEMDIRLEN) && !kstrncmpi(lpszName,SYSTEMDIR,SYSTEMDIRLEN)) || ((nameptr == lpszName + SYSTEMDIRLEN - 1) && !kstrncmpi(lpszName,SYSTEMDIR+1,SYSTEMDIRLEN-1))) inWin = 1; else { memcpy(poeinfo->tmpname,lpszName,(nameptr-lpszName-1)*sizeof(WCHAR)); poeinfo->tmpname[nameptr-lpszName-1] = 0; hFind = FindFirstFile(poeinfo->tmpname,&poeinfo->wfd); if (hFind != INVALID_HANDLE_VALUE) { CloseHandle(hFind); if (poeinfo->wfd.dwOID == 1) inWin = 1; } } } p2 = (LPWSTR)poeinfo->plainname; while (*nameptr && (p2 - poeinfo->plainname < MAX_PATH-1)) *p2++ = *nameptr++; *p2 = 0; plainlen = p2 - poeinfo->plainname; DEBUGMSG(ZONE_OPENEXE,(TEXT("OpenExe: plain name %s\r\n"),poeinfo->plainname)); oeptr->bIsOID = 1; oeptr->lpName = 0; if (!(oeptr->lpName = AllocName(MAX_PATH*2))) { KSetLastError(pCurThread,dwLastError); return 0; } // check the file system if (SystemAPISets[SH_FILESYS_APIS]) { if (!isAbs) { // if dll, check in directory exe launched from if (bIsDLL) { PPROCESS pProc; pProc = (pCurThread->pcstkTop ? pCurThread->pcstkTop->pprcLast : pCurProc); if (pProc->oe.filetype != FT_ROMIMAGE) { if (pProc->oe.bIsOID) { CREATE_SYSTEMGUID(&sysguid); if (!(CeOidGetInfoEx(&sysguid,pProc->oe.ceOid,&poeinfo->ceoi)) || (poeinfo->ceoi.wObjType != OBJTYPE_FILE)) goto DoWinDir; } else kstrcpyW(poeinfo->ceoi.infFile.szFileName,pProc->oe.lpName->name); nameptr = poeinfo->ceoi.infFile.szFileName + strlenW(poeinfo->ceoi.infFile.szFileName); while ((*nameptr != '\\') && (*nameptr != '/') && (nameptr != poeinfo->ceoi.infFile.szFileName)) nameptr--; if ((nameptr != poeinfo->ceoi.infFile.szFileName) && (MAX_PATH - 1 - (nameptr + 1 - poeinfo->ceoi.infFile.szFileName) >= plainlen)) { memcpy(nameptr+1,poeinfo->plainname,plainlen*sizeof(WCHAR)); nameptr[plainlen+1] = 0; if ((oeptr->hf = CreateFileW(poeinfo->ceoi.infFile.szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0)) != INVALID_HANDLE_VALUE) { if (GetFileInformationByHandle(oeptr->hf,&poeinfo->bhfi) && (poeinfo->bhfi.dwOID != (ULONG)INVALID_HANDLE_VALUE)) { FreeName(oeptr->lpName); oeptr->ceOid = poeinfo->bhfi.dwOID; } else { LPName pName; oeptr->bIsOID = 0; if (pName = AllocName((strlenW(poeinfo->ceoi.infFile.szFileName)+1)*2)) { FreeName(oeptr->lpName); oeptr->lpName = pName; } kstrcpyW(oeptr->lpName->name,poeinfo->ceoi.infFile.szFileName); } oeptr->filetype = FT_OBJSTORE; 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; } KSetLastError(pCurThread,dwLastError); return 1; } } } }DoWinDir: oeptr->hf = INVALID_HANDLE_VALUE; // check for file as path from root if (plainlen != totlen) { poeinfo->tmpname[0] = '\\'; copylen = (totlen < MAX_PATH - 2 ? totlen : MAX_PATH - 2); memcpy((LPWSTR)poeinfo->tmpname+1,lpszName,totlen*sizeof(WCHAR)); poeinfo->tmpname[1+copylen] = 0; oeptr->hf = CreateFileW((LPWSTR)poeinfo->tmpname,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); } if (oeptr->hf == INVALID_HANDLE_VALUE) { // check for file in windows directory memcpy(poeinfo->tmpname,SYSTEMDIR,SYSTEMDIRLEN*sizeof(WCHAR)); copylen = (plainlen + SYSTEMDIRLEN < MAX_PATH-1) ? plainlen : MAX_PATH - 2 - SYSTEMDIRLEN; memcpy((LPWSTR)poeinfo->tmpname+SYSTEMDIRLEN,poeinfo->plainname,copylen*sizeof(WCHAR)); poeinfo->tmpname[SYSTEMDIRLEN+copylen] = 0; oeptr->hf = CreateFileW((LPWSTR)poeinfo->tmpname,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); } if (oeptr->hf == INVALID_HANDLE_VALUE) { // check for file in root directory poeinfo->tmpname[0] = '\\'; copylen = (plainlen + 1 < MAX_PATH-1) ? plainlen : MAX_PATH - 3; memcpy((LPWSTR)poeinfo->tmpname+1,poeinfo->plainname,copylen*sizeof(WCHAR)); poeinfo->tmpname[1+copylen] = 0; oeptr->hf = CreateFileW((LPWSTR)poeinfo->tmpname,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); } if (oeptr->hf != INVALID_HANDLE_VALUE) { if (GetFileInformationByHandle(oeptr->hf,&poeinfo->bhfi) && (poeinfo->bhfi.dwOID != (ULONG)INVALID_HANDLE_VALUE)) { FreeName(oeptr->lpName); oeptr->ceOid = poeinfo->bhfi.dwOID; } else { LPName pName; oeptr->bIsOID = 0; if (pName = AllocName((strlenW(poeinfo->tmpname)+1)*2)) { FreeName(oeptr->lpName); oeptr->lpName = pName; } kstrcpyW(oeptr->lpName->name,poeinfo->tmpname); } } } else { // check in main file system (will route to mounted if part of path) if ((oeptr->hf = CreateFileW((LPWSTR)lpszName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0)) != INVALID_HANDLE_VALUE) { if (GetFileInformationByHandle(oeptr->hf,&poeinfo->bhfi) && (poeinfo->bhfi.dwOID != (ULONG)INVALID_HANDLE_VALUE)) { FreeName(oeptr->lpName); oeptr->ceOid = poeinfo->bhfi.dwOID; } else { LPName pName; oeptr->bIsOID = 0; if (pName = AllocName((strlenW(lpszName)+1)*2)) { FreeName(oeptr->lpName); oeptr->lpName = pName; } kstrcpyW(oeptr->lpName->name,lpszName); } } } if (oeptr->hf != INVALID_HANDLE_VALUE) { DEBUGMSG(ZONE_OPENEXE,(TEXT("OpenExe %s: OSTORE: %8.8lx\r\n"),lpszName,oeptr->hf)); oeptr->filetype = FT_OBJSTORE; 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; } KSetLastError(pCurThread,dwLastError); return 1; } } if ((plainlen == totlen) || inWin) { ROMChain_t *pROM; for (pROM = ROMChain; pROM; pROM = pROM->pNext) { // check ROM for any copy tocptr = (TOCentry *)(pROM->pTOC+1); // toc entries follow the header for (loop = 0; loop < (int)pROM->pTOC->nummods; loop++) { if (!strcmpiAandW(tocptr->lpszFileName,poeinfo->plainname)) { DEBUGMSG(ZONE_OPENEXE,(TEXT("OpenExe %s: ROM: %8.8lx\r\n"),lpszName,tocptr)); oeptr->tocptr = tocptr; oeptr->filetype = FT_ROMIMAGE; oeptr->pagemode = (bAllowPaging && !(pTOC->ulKernelFlags & KFLAG_DISALLOW_PAGING)) ? PM_FULLPAGING : PM_NOPAGING; KSetLastError(pCurThread,dwLastError); if (oeptr->lpName) FreeName(oeptr->lpName,); return 1; } tocptr++; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -