📄 resource.c
字号:
/* * NK Kernel resource loader code * * Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. * * Module Name: * * heap.c * * Abstract: * * This file implements the NK kernel resource loader * * *//* Straight-forward implementation of the resouce API's. Since resources are read-only, we always return the slot 1 (kernel) copy of the resource, which is visable to all processes. */#include "kernel.h"#define DWORDUP(x) (((x)+3)&~03)extern CRITICAL_SECTION LLcs, RFBcs, ModListcs;typedef struct VERHEAD { WORD wTotLen; WORD wValLen; WORD wType; /* always 0 */ WCHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03]; VS_FIXEDFILEINFO vsf;} VERHEAD ;typedef struct resroot_t { DWORD flags; DWORD timestamp; DWORD version; WORD numnameents; WORD numidents;} resroot_t;typedef struct resent_t { DWORD id; DWORD rva;} resent_t;typedef struct resdata_t { DWORD rva; DWORD size; DWORD codepage; DWORD unused;} resdata_t;DWORD atoiW(LPWSTR str) { DWORD retval = 0; while (*str) { retval = retval * 10 + (*str-(WCHAR)'0'); str++; } return retval;}extern WCHAR lowerW(WCHAR);HANDLE FindResourcePart2(LPBYTE BasePtr, e32_lite* eptr, LPCWSTR lpszName, LPCWSTR lpszType);// Compare a Unicode string and a Pascal stringint StrCmpPascW(LPWSTR ustr, LPWSTR pstr) { int loop = (int)*pstr++; while (*ustr && loop--) if (lowerW(*ustr++) != lowerW(*pstr++)) return 1; return (!*ustr && !loop ? 0 : 1);}// Compare an Ascii string and a Pascal stringint StrCmpAPascW(LPSTR astr, LPWSTR pstr) { int loop = (int)*pstr++; while (*astr && loop--) if (lowerW((WCHAR)*astr++) != lowerW(*pstr++)) return 1; return (!*astr && !loop ? 0 : 1);}// Search for a named typeDWORD FindTypeByName(LPBYTE BasePtr, LPBYTE curr, LPWSTR str) { resroot_t *rootptr = (resroot_t *)curr; resent_t *resptr = (resent_t *)(curr + sizeof(resroot_t)); int count = rootptr->numnameents; while (count--) { if (!str || !StrCmpPascW(str,(LPWSTR)(BasePtr+(resptr->id&0x7fffffff)))) return resptr->rva; resptr++; } return 0;}// Search for a numbered typeDWORD FindTypeByNum(LPBYTE curr, DWORD id) { resroot_t *rootptr = (resroot_t *)curr; resent_t *resptr = (resent_t *)(curr + sizeof(resroot_t) + rootptr->numnameents*sizeof(resent_t)); int count = rootptr->numidents; while (count--) { if (!id || (resptr->id == id)) return resptr->rva; resptr++; } return 0;}// Find first entry (from curr pointer)DWORD FindFirst(LPBYTE curr) { resroot_t *rootptr = (resroot_t *)curr; resent_t *resptr = (resent_t *)(curr + sizeof(resroot_t) + rootptr->numnameents*sizeof(resent_t)); return resptr->rva;}// Find type entry (by name or number)DWORD FindType(LPBYTE BasePtr, LPBYTE curr, LPWSTR str) { DWORD res; if (((DWORD)str)>>16) if (str[0] == (WCHAR)'#') return FindTypeByNum(curr, atoiW(str+1)); else return FindTypeByName(BasePtr, curr, str); if (!(res = FindTypeByNum(curr, (DWORD)str)) && !str) res = FindTypeByName(BasePtr, curr, str); return res;}// global array that keeps our current UI language, and default UI languageLANGID g_rgwUILangs[6]; // at most 5 langs, one extra for array terminator// 0 == current UI lang// 1 == MAKELANGID(PRIMARYLANGID(g_rgwUILangs[0]), SUBLANG_DEFAULT)// 2 == default UI lang// 3 == MAKELANGID(PRIMARYLANGID(g_rgwUILangs[2]), SUBLANG_DEFAULT)// 4 == 0x0409 (US English) // The array may be smaller since duplicates are eliminated// Flag that enables/disables MUI globally 0==not inited, 1==inited&enabled 2==inited&disabledDWORD g_EnableMUI;// saved path to system MUI DLL. sizeof(\\windows\\ceosXXXX.mui)//WCHAR g_szSystemMUI[22];// Read language setting & add uniquely to arrayvoid AddLangUnique(DWORD dwValue, HKEY hkey, LPCTSTR szValName){ int i; DWORD dwType, dwSize; LANGID langid1, langid2; if(!dwValue) { dwSize = sizeof(DWORD); // load a langid, skip if error if( ERROR_SUCCESS!=RegQueryValueExW(hkey, szValName, (LPDWORD)L"MUI", &dwType, (LPBYTE)&dwValue, &dwSize) || (dwType != REG_DWORD) || !dwValue ) { DEBUGMSG(1,(L"InitMUI: Failed to read regkey %s\r\n", szValName)); return; } } langid1 = (LANGID)dwValue; langid2 = MAKELANGID(PRIMARYLANGID(langid1), SUBLANG_DEFAULT); if(langid2 == langid1) langid2 = 0; DEBUGMSG(1,(L"InitMUI: Got Langs=%x %x\r\n", langid1, langid2)); // add them uniquely to array for(i=0; ;i++) { if(!g_rgwUILangs[i]) { g_rgwUILangs[i] = langid1; g_rgwUILangs[i+1] = langid2; break; } else if(g_rgwUILangs[i]==langid1) { langid1 = 0; } else if(g_rgwUILangs[i]==langid2) { langid2 = 0; } }}// Initialize MUI language globals -- called only once during system startup, from RunAppsvoid InitMUILanguages(void){ DWORD dwType, dwSize, dwValue; DEBUGCHK(!g_EnableMUI); // this must be called only once if(!SystemAPISets[SH_FILESYS_APIS]) { g_EnableMUI = (DWORD)-1; // if this config has no filesystem then MUI is disabled return; } // check if MUI is enabled dwSize = sizeof(DWORD); if( ERROR_SUCCESS!=RegQueryValueExW(HKEY_LOCAL_MACHINE, L"Enable",(LPDWORD)L"MUI", &dwType, (LPBYTE)&dwValue, &dwSize) || (dwType != REG_DWORD) || !dwValue ) { DEBUGMSG(1,(L"InitMUI: DISABLED (%d)\r\n", dwValue)); g_EnableMUI = (DWORD)-1; // disable MUI return; } // memset(g_rgwUILangs, 0, sizeof(g_rgwUILangs)); // not reqd // load Current User language, skip if error AddLangUnique(0, HKEY_CURRENT_USER, L"CurLang"); // load System Default language, skip if error AddLangUnique(0, HKEY_LOCAL_MACHINE, L"SysLang"); // load English AddLangUnique(0x0409, 0, 0); DEBUGMSG(1,(L"InitMUI: Langs=%x %x %x %x %x %x\r\n", g_rgwUILangs[0], g_rgwUILangs[1], g_rgwUILangs[2], g_rgwUILangs[3], g_rgwUILangs[4], g_rgwUILangs[5])); g_EnableMUI = 1; // set this as the last thing before exit}// Called to load MUI resource DLL. NOT in a critsec. Must be re-entrant.HMODULE LoadMUI(HANDLE hModule, LPBYTE BasePtr2, e32_lite* eptr2){ WCHAR szPath[MAX_PATH]; int iLen, i; HMODULE hmodRes; DWORD dwLangID; HANDLE hRsrc; // if MUI disabled (or not yet inited, e.g. call by filesys.exe), then fail immediately if(g_EnableMUI != 1) return (HMODULE)-1; // See if module contains a reference to a MUI (resource type=222, id=1). If found, // the resource contains a basename to which we append .XXXX.MUI, where XXXX is the language code if( (hRsrc = FindResourcePart2(BasePtr2, eptr2, MAKEINTRESOURCE(ID_MUI), MAKEINTRESOURCE(RT_MUI))) && (iLen = ((resdata_t *)hRsrc)->size) && (iLen < sizeof(WCHAR)*(MAX_PATH-10)) ) { memcpy(szPath, (BasePtr2 + ((resdata_t *)hRsrc)->rva), iLen); iLen /= sizeof(WCHAR); szPath[iLen]=0; DEBUGMSG(1,(L"LoadMUI: Found indirection (%s, %d)\r\n", szPath, iLen)); } // otherwise search for local MUI dll, based on module path name else if(!(iLen=GetModuleFileName(hModule, szPath, MAX_PATH-10))) { DEBUGCHK(FALSE); return (HMODULE)-1; } for(i=0; g_rgwUILangs[i]; i++) { // try to find local DLL in each of current/default/english languages dwLangID = g_rgwUILangs[i]; NKwvsprintfW(szPath+iLen, TEXT(".%04X.MUI"), (LPVOID)&dwLangID, (MAX_PATH-iLen)); DEBUGMSG(1,(L"LoadMUI: Trying %s\r\n",szPath)); if(hmodRes=LoadLibraryEx(szPath, NULL, LOAD_LIBRARY_AS_DATAFILE)) { // dont call dllentry/resolve refs etc DEBUGMSG(1,(L"LoadMUI: Loaded %s\r\n", szPath)); return hmodRes; } } return (HMODULE)-1; } HANDLE FindResourcePart2(LPBYTE BasePtr, e32_lite* eptr, LPCWSTR lpszName, LPCWSTR lpszType) { DWORD trva; if (!eptr->e32_unit[RES].rva) return 0; BasePtr += eptr->e32_unit[RES].rva; if (!(trva = FindType(BasePtr, BasePtr, (LPWSTR)lpszType)) || !(trva = FindType(BasePtr, BasePtr+(trva&0x7fffffff),(LPWSTR)lpszName)) || !(trva = FindFirst(BasePtr+(trva&0x7fffffff)))) { return 0; } return (HANDLE)(BasePtr+(trva&0x7fffffff));}// Gets pmodResource, atomically updating it if reqdPMODULE InterlockedUpdatePmodRes(PMODULE* ppMod, HMODULE hModule, LPBYTE BasePtr2, e32_lite* eptr2){ PMODULE pmodRes; pmodRes = (PMODULE)LoadMUI(hModule, BasePtr2, eptr2); if(InterlockedTestExchange((LPLONG)ppMod, 0, (LONG)pmodRes)!=0) { if(pmodRes != (PMODULE)-1) FreeLibrary(pmodRes); pmodRes = *ppMod; } DEBUGCHK(pmodRes); return pmodRes;}// Win32 FindResourceHANDLE SC_FindResource(HANDLE hModule, LPCWSTR lpszName, LPCWSTR lpszType) { LPBYTE BasePtr2; e32_lite *eptr2; PPROCESS pProc; PMODULE pmodRes; HANDLE hRet; DEBUGMSG(ZONE_ENTRY,(L"SC_FindResource entry: %8.8lx %8.8lx %8.8lx\r\n",hModule,lpszName,lpszType)); if (hModule == GetCurrentProcess()) hModule = hCurProc; // Get Base & e32 ptr for current process or module as approp // also get MUI resource dll, loading it if neccesary if (pProc = HandleToProc(hModule)) { // a process BasePtr2 = (LPBYTE)MapPtrProc(pProc->BasePtr,pProc); eptr2 = &pProc->e32; if(!(pmodRes = pProc->pmodResource)) pmodRes = InterlockedUpdatePmodRes(&(pProc->pmodResource), hModule, BasePtr2, eptr2); } else if (IsValidModule((LPMODULE)hModule)) { // a module
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -