📄 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 string
int 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 string
int 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 type
DWORD 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 type
DWORD 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 language
LANGID 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&disabled
DWORD g_EnableMUI;
// saved path to system MUI DLL. sizeof(\\windows\\ceosXXXX.mui)
//WCHAR g_szSystemMUI[22];
// Read language setting & add uniquely to array
void 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 RunApps
void 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 reqd
PMODULE 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 FindResource
HANDLE 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 + -