https://git.reactos.org/?p=reactos.git;a=commitdiff;h=915a5764a98be6f8a03471...
commit 915a5764a98be6f8a03471d68a55e4b1a5899f66 Author: jimtabor james.tabor@reactos.org AuthorDate: Sat Mar 28 14:18:14 2020 -0500 Commit: jimtabor james.tabor@reactos.org CommitDate: Sat Mar 28 14:18:14 2020 -0500
[Win32SS] Form Sanity to Hook Callbacks
Fix WH_CALLWNDPROC/RET data to user hook calls. See CORE-13019 and CORE-13907. --- win32ss/include/callback.h | 15 ++++++++++ win32ss/user/ntuser/callback.c | 60 +++++++++++++++++++++++--------------- win32ss/user/user32/windows/hook.c | 30 ++++++++++--------- 3 files changed, 69 insertions(+), 36 deletions(-)
diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h index 5b6f49ce3a2..7eef1d6c278 100644 --- a/win32ss/include/callback.h +++ b/win32ss/include/callback.h @@ -61,6 +61,7 @@ typedef struct _HOOKPROC_CALLBACK_ARGUMENTS ULONG_PTR offPfn; BOOLEAN Ansi; LRESULT Result; + UINT lParamSize; WCHAR ModuleName[512]; } HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS;
@@ -72,6 +73,20 @@ typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS /* WCHAR szClass[] */ } HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS, *PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS;
+typedef struct tagCWP_Struct +{ + HOOKPROC_CALLBACK_ARGUMENTS hpca; + CWPSTRUCT cwps; + PBYTE Extra[4]; +} CWP_Struct, *PCWP_Struct; + +typedef struct tagCWPR_Struct +{ + HOOKPROC_CALLBACK_ARGUMENTS hpca; + CWPRETSTRUCT cwprs; + PBYTE Extra[4]; +} CWPR_Struct, *PCWPR_Struct; + typedef struct _EVENTPROC_CALLBACK_ARGUMENTS { HWINEVENTHOOK hook; diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c index 42d50002d33..1497d72a892 100644 --- a/win32ss/user/ntuser/callback.c +++ b/win32ss/user/ntuser/callback.c @@ -509,6 +509,8 @@ co_IntLoadDefaultCursors(VOID) return TRUE; }
+static INT iTheId = -2; // Set it out of range. + LRESULT APIENTRY co_IntCallHookProc(INT HookId, INT Code, @@ -535,6 +537,8 @@ co_IntCallHookProc(INT HookId, PMSG pMsg = NULL; BOOL Hit = FALSE; UINT lParamSize = 0; + CWPSTRUCT* pCWP = NULL; + CWPRETSTRUCT* pCWPR = NULL;
ASSERT(Proc); /* Do not allow the desktop thread to do callback to user mode */ @@ -593,27 +597,27 @@ co_IntCallHookProc(INT HookId, goto Fault_Exit; } break; - case WH_KEYBOARD_LL: + case WH_KEYBOARD_LL: ArgumentLength += sizeof(KBDLLHOOKSTRUCT); break; - case WH_MOUSE_LL: + case WH_MOUSE_LL: ArgumentLength += sizeof(MSLLHOOKSTRUCT); break; - case WH_MOUSE: + case WH_MOUSE: ArgumentLength += sizeof(MOUSEHOOKSTRUCT); break; case WH_CALLWNDPROC: { - CWPSTRUCT* pCWP = (CWPSTRUCT*) lParam; - ArgumentLength += sizeof(CWPSTRUCT); + pCWP = (CWPSTRUCT*) lParam; + ArgumentLength = sizeof(CWP_Struct); lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam); ArgumentLength += lParamSize; break; } case WH_CALLWNDPROCRET: { - CWPRETSTRUCT* pCWPR = (CWPRETSTRUCT*) lParam; - ArgumentLength += sizeof(CWPRETSTRUCT); + pCWPR = (CWPRETSTRUCT*) lParam; + ArgumentLength = sizeof(CWPR_Struct); lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam); ArgumentLength += lParamSize; break; @@ -647,6 +651,7 @@ co_IntCallHookProc(INT HookId, Common->Mod = Mod; Common->offPfn = offPfn; Common->Ansi = Ansi; + Common->lParamSize = lParamSize; RtlZeroMemory(&Common->ModuleName, sizeof(Common->ModuleName)); if (ModuleName->Buffer && ModuleName->Length) { @@ -697,25 +702,27 @@ co_IntCallHookProc(INT HookId, Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_CALLWNDPROC: + { + PCWP_Struct pcwps = (PCWP_Struct)Common; + RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT)); /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that * lParam could be a pointer to a buffer. This buffer must be exported * to user space too */ - RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT)); - Common->lParam = (LPARAM) (Extra - (PCHAR) Common); - if(lParamSize) + if ( lParamSize ) { - RtlCopyMemory(Extra + sizeof(CWPSTRUCT), (PVOID)((CWPSTRUCT*)lParam)->lParam, lParamSize); - ((CWPSTRUCT*)Extra)->lParam = (LPARAM)lParamSize; + RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize ); } + } break; case WH_CALLWNDPROCRET: - RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT)); - Common->lParam = (LPARAM) (Extra - (PCHAR) Common); - if(lParamSize) + { + PCWPR_Struct pcwprs = (PCWPR_Struct)Common; + RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT)); + if ( lParamSize ) { - RtlCopyMemory(Extra + sizeof(CWPRETSTRUCT), (PVOID)((CWPRETSTRUCT*)lParam)->lParam, lParamSize); - ((CWPRETSTRUCT*)Extra)->lParam = (LPARAM)lParamSize; + RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize ); } + } break; case WH_MSGFILTER: case WH_SYSMSGFILTER: @@ -745,7 +752,11 @@ co_IntCallHookProc(INT HookId,
if (!NT_SUCCESS(Status)) { - ERR("Failure to make Callback! Status 0x%x\n",Status); + if ( iTheId != HookId ) // Hook ID can change. + { + ERR("Failure to make Callback %d! Status 0x%x\n",HookId,Status); + iTheId = HookId; + } goto Fault_Exit; }
@@ -1216,12 +1227,13 @@ APIENTRY co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize ) { NTSTATUS Status; + PVOID ResultPointer;
- Status = KeUserModeCallback(USER32_CALLBACK_UMPD, - pkt, - InSize, - pvOutData, - (PULONG)&OutSize); + Status = KeUserModeCallback( USER32_CALLBACK_UMPD, + pkt, + InSize, + &ResultPointer, + (PULONG)&OutSize );
if (!NT_SUCCESS(Status)) @@ -1230,6 +1242,8 @@ co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize return 1; }
+ if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize ); + return 0; }
diff --git a/win32ss/user/user32/windows/hook.c b/win32ss/user/user32/windows/hook.c index e0cb8e4a041..f525bf1cc5a 100644 --- a/win32ss/user/user32/windows/hook.c +++ b/win32ss/user/user32/windows/hook.c @@ -699,35 +699,39 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) _SEH2_END; break; case WH_CALLWNDPROC: -// ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam); - pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS)); - RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT)); + { + PCWP_Struct pcwps = (PCWP_Struct)Common; + CWPSTRUCT *pCWPT = &pcwps->cwps; + pCWP = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPSTRUCT)); + RtlCopyMemory(pCWP, pCWPT, sizeof(CWPSTRUCT)); +// ERR("WH_CALLWNDPROC: Code %d, wParam %d msg %d\n",Common->Code,Common->wParam,pCWP->message); /* If more memory is reserved, then lParam is a pointer. * Size of the buffer is stocked in the lParam member, and its content * is at the end of the argument buffer */ - if(ArgumentLength > (sizeof(CWPSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS))) + if ( Common->lParamSize ) { - RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT), - (PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT), - pCWP->lParam); pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT)); + RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize ); } Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP); HeapFree(GetProcessHeap(), 0, pCWP); + } break; case WH_CALLWNDPROCRET: /* Almost the same as WH_CALLWNDPROC */ - pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS)); - RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT)); - if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS))) + { + PCWPR_Struct pcwprs = (PCWPR_Struct)Common; + CWPRETSTRUCT *pCWPRT = &pcwprs->cwprs; + pCWPR = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPRETSTRUCT)); + RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT)); + if ( Common->lParamSize ) { - RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT), - (PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT), - pCWPR->lParam); pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT)); + RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize ); } Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR); HeapFree(GetProcessHeap(), 0, pCWPR); + } break; case WH_MSGFILTER: /* All SEH support */ case WH_SYSMSGFILTER: