こんにちは!
こんにちは!
構造体の定義は終わりましたか?
はい
前回の課題のNtUserUnloadKeyboardLayoutを見ていこう。 エクスポートでもエントリーポイントでもない関数には頭に''が付く。 [Functions]→[]→[_NtUser]→[_NtUserUnloadKeyboardLayout]のようにたどる。
undefined4 _NtUserUnloadKeyboardLayout@4(uint param_1)
{
int iVar1;
undefined4 uVar2;
_EnterCrit@0();
iVar1 = __GetProcessWindowStation@4((undefined4 *)0x0);
uVar2 = _xxxUnloadKeyboardLayout@8(iVar1,param_1);
_LeaveCrit@0();
return uVar2;
}
ReactOSの「NtUserUnloadKeyboardLayout」のプロトタイプを見ると、 「BOOL APIENTRY NtUserUnloadKeyboardLayout(HKL hKl)」 になっているので、「undefined4」をBOOLとし、「uint param_1」をHKL hKlとする。 これらに合わせて_xxxUnloadKeyboardLayoutのプロトタイプも修正。
「__GetProcessWindowStation@4((undefined4 *)0x0)」 の部分は、どうみてもReactOSの「UserGetProcessWindowStation()」だろう。
解析結果は次のようになる。
BOOL _NtUserUnloadKeyboardLayout@4(HKL hKl)
{
HWINSTA hWinSta;
BOOL ret;
_EnterCrit@0();
hWinSta = __GetProcessWindowStation@4((undefined4 *)0x0);
ret = _xxxUnloadKeyboardLayout@8(hWinSta,hKl);
_LeaveCrit@0();
return ret;
}
WinのEnterCrit();はReactOSのUserEnterExclusive();に相当する。 WinのLeaveCrit();はReactOSのUserLeave();に相当する。
清書すると
BOOL NTAPI NtUserUnloadKeyboardLayout(HKL hKl)
{
BOOL ret;
HWINSTA hWinSta;
UserEnterExclusive();
hWinSta = UserGetProcessWindowStation();
ret = xxxUnloadKeyboardLayout(hWinSta, hKl);
UserLeave();
return ret;
}
次は_xxxUnloadKeyboardLayoutを見よう。 _xxxUnloadKeyboardLayoutをダブルクリック。
BOOL _xxxUnloadKeyboardLayout@8(HWINSTA hWinSta,HKL hKL)
{
uint *puVar1;
puVar1 = (uint *)_HKLtoPKL@8((int)_gptiCurrent,(uint)hKL);
if (puVar1 != (uint *)0x0) {
puVar1 = (uint *)_xxxInternalUnloadKeyboardLayout@12((int)hWinSta,puVar1,0);
}
return (BOOL)puVar1;
}
_gptiCurrentは、PTHREADINFO型らしい。 HKLtoPKLの名前からしてその戻り値はおそらくPKL型。PKLは、KL構造体へのポインタ型だ。 win32ss/user/ntuser/input.hによると:
typedef struct tagKL
{
HEAD head;
struct tagKL *pklNext; // PVOIDを代用。
struct tagKL *pklPrev; // PVOIDを代用。
DWORD dwKL_Flags;
HKL hkl;
PKBDFILE spkf; // PVOIDを代用。
DWORD dwFontSigs;
UINT iBaseCharset;
USHORT CodePage;
WCHAR wchDiacritic;
PIMEINFOEX piiex; // PVOIDを代用。
} KL, *PKL;
解析結果は次のようになる。
BOOL _xxxUnloadKeyboardLayout@8(HWINSTA hWinSta,HKL hKL)
{
PKL pKL;
pKL = (PKL)_HKLtoPKL@8(_gptiCurrent,hKL);
if (pKL != (PKL)0x0) {
pKL = (PKL)_xxxInternalUnloadKeyboardLayout@12(hWinSta,pKL,0);
}
return (BOOL)pKL;
}
変数pKLをBOOL型の戻り値の格納場所として再利用しているので、ちょっとキャストが汚いことになっている。
清書すると
BOOL xxxUnloadKeyboardLayout(HWINSTA hWinSta, HKL hKL)
{
PKL pKL = HKLtoPKL(gptiCurrent, hKL);
if (!pKL)
return FALSE;
return xxxInternalUnloadKeyboardLayout(hWinSta, pKL, 0);
}
次は_HKLtoPKLと_xxxInternalUnloadKeyboardLayout。 THREADINFO構造体の型情報が必要だ。
typedef struct _THREADINFO
{
W32THREAD;
PTL ptl; // PVOIDを代用。
PPROCESSINFO ppi; // PVOIDを代用。
struct _USER_MESSAGE_QUEUE* MessageQueue; // PVOIDを代用。
struct tagKL* KeyboardLayout;
// ...以下略。
} THREADINFO;
typedef struct _THREADINFO *PTHREADINFO;
typedef struct _W32THREAD
{
PETHREAD pEThread; // PVOIDを代用。
LONG RefCount;
PTL ptlW32; // PVOIDを代用。
PVOID pgdiDcattr;
PVOID pgdiBrushAttr;
PVOID pUMPDObjs;
PVOID pUMPDHeap;
DWORD dwEngAcquireCount;
PVOID pSemTable;
PVOID pUMPDObj;
} W32THREAD, *PW32THREAD;
色々やると次が得られる。
PKL _HKLtoPKL@8(PTHREADINFO pti,HKL hKL)
{
PKL pKVar1;
PKL psVar2;
PKL pvVar1;
pvVar1 = pti->KeyboardLayout;
if (pvVar1 != (PKL)0x0) {
pKVar1 = pvVar1;
if (hKL == (HKL)0x0) {
do {
pKVar1 = pKVar1->pklPrev;
if ((*(byte *)((int)&pKVar1->dwKL_Flags + 3) & 0x20) == 0) {
return pKVar1;
}
} while (pKVar1 != pvVar1);
}
else {
psVar2 = pvVar1;
if (hKL == (HKL)&DAT_00000001) {
do {
psVar2 = psVar2->pklNext;
if ((*(byte *)((int)&psVar2->dwKL_Flags + 3) & 0x20) == 0) {
return psVar2;
}
} while (psVar2 != pvVar1);
}
else if (((uint)hKL & 0xffff0000) == 0) {
do {
if (*(short *)&pKVar1->hkl == (short)hKL) {
return pKVar1;
}
pKVar1 = pKVar1->pklNext;
} while (pKVar1 != pvVar1);
}
else {
do {
if (pKVar1->hkl == hKL) {
return pKVar1;
}
pKVar1 = pKVar1->pklNext;
} while (pKVar1 != pvVar1);
}
}
}
return (PKL)0x0;
}
「(HKL)&DAT_00000001」はおそらく「(HKL)HKL_NEXT」だろうと思われる。
「*(short *)&pKVar1->hkl == (short)hKL」は、「LOWORD(pKVar1->hkl) == LOWORD(hKL)」と同じ。 LOWORDマクロは下位ワードを取得する。
「((uint)hKL & 0xffff0000) == 0」は、「HIWORD(hKL) == 0」と同じ。 HIWORDマクロは上位ワードを取得する。
「(*(byte *)((int)&pKVar1->dwKL_Flags + 3) & 0x20) == 0」は、「(pKVar1->dwKL_Flags & 0x20000000) == 0」と同じ。
清書すると
PKL HKLtoPKL(PTHREADINFO pti, HKL hKL)
{
PKL pklFirst, pKL;
pklFirst = pti->KeyboardLayout;
if (!pklFirst)
return NULL;
pKL = pklFirst;
if (hKL == (HKL)(INT_PTR)HKL_PREV)
{
do {
pKL = pKL->pklPrev;
if ((pKL->dwKL_Flags & 0x20000000) == 0)
return pKL;
} while (pKL != pklFirst);
}
else if (hKL == (HKL)(INT_PTR)HKL_NEXT)
{
do {
pKL = pKL->pklNext;
if ((pKL->dwKL_Flags & 0x20000000) == 0)
return pKL;
} while (pKL != pklFirst);
}
else if (HIWORD(hKL) == 0)
{
do {
if (LOWORD(pKL->hkl) == LOWORD(hKL))
return pKL;
pKL = pKL->pklNext;
} while (pKL != pklFirst);
}
else
{
do {
if (pKL->hkl == hKL)
return pKL;
pKL = pKL->pklNext;
} while (pKL != pklFirst);
}
return NULL;
}
【課題】_xxxInternalUnloadKeyboardLayoutを解析せよ。
今日はここまで。
ありがとうございました
訂正。__GetProcessWindowStationの戻り値は、HWINSTAではなくPWINSTATION_OBJECTでした。お詫びします。