boot/environ/CMakeLists.txt | 1 + boot/environ/lib/rtl/libsupp.c | 39 +++++++++ boot/freeldr/freeldr/lib/rtl/libsupp.c | 27 ++++++ dll/ntdll/rtl/libsupp.c | 43 +++++++++ dll/win32/kernel32/client/loader.c | 13 +-- ntoskrnl/rtl/libsupp.c | 43 +++++++++ sdk/lib/rtl/image.c | 3 +- win32ss/include/callback.h | 15 ++++ win32ss/user/ntuser/callback.c | 81 +++++++++++------ win32ss/user/ntuser/callback.h | 1 + win32ss/user/ntuser/message.c | 153 ++++++++++++++++++++++++++++++++- win32ss/user/ntuser/window.c | 83 ++---------------- win32ss/user/user32/windows/hook.c | 62 +++++++------ win32ss/user/user32/windows/window.c | 20 +++-- 14 files changed, 430 insertions(+), 154 deletions(-) diff --git a/boot/environ/CMakeLists.txt b/boot/environ/CMakeLists.txt index f79136c..daa621a 100644 --- a/boot/environ/CMakeLists.txt +++ b/boot/environ/CMakeLists.txt @@ -20,6 +20,7 @@ list(APPEND BOOTLIB_SOURCE lib/misc/resource.c lib/misc/font.c lib/misc/rtlcompat.c + lib/rtl/libsupp.c lib/firmware/fwutil.c lib/firmware/efi/firmware.c lib/mm/mm.c diff --git a/boot/environ/lib/rtl/libsupp.c b/boot/environ/lib/rtl/libsupp.c new file mode 100644 index 0000000..257b859 --- /dev/null +++ b/boot/environ/lib/rtl/libsupp.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: See COPYING.ARM in the top level directory + * PROJECT: ReactOS UEFI Boot Library + * FILE: boot/environ/lib/rtl/libsupp.c + * PURPOSE: RTL Support Routines + * PROGRAMMER: Mark Jansen (mark.jansen@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "bl.h" + +/* FUNCTIONS *****************************************************************/ + +/* Ldr access to IMAGE_NT_HEADERS without SEH */ + +/* Rtl SEH-Free version of this */ +NTSTATUS +NTAPI +RtlpImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders); + + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders) +{ + return RtlpImageNtHeaderEx(Flags, Base, Size, OutHeaders); +} diff --git a/boot/freeldr/freeldr/lib/rtl/libsupp.c b/boot/freeldr/freeldr/lib/rtl/libsupp.c index eb9bc2a..585164d 100644 --- a/boot/freeldr/freeldr/lib/rtl/libsupp.c +++ b/boot/freeldr/freeldr/lib/rtl/libsupp.c @@ -57,3 +57,30 @@ RtlpSafeCopyMemory( RtlCopyMemory(Destination, Source, Length); return STATUS_SUCCESS; } + +/* Ldr access to IMAGE_NT_HEADERS without SEH */ + +/* Rtl SEH-Free version of this */ +NTSTATUS +NTAPI +RtlpImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders); + + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders) +{ + return RtlpImageNtHeaderEx(Flags, Base, Size, OutHeaders); +} + diff --git a/dll/ntdll/rtl/libsupp.c b/dll/ntdll/rtl/libsupp.c index 94c6f0e..c16f243 100644 --- a/dll/ntdll/rtl/libsupp.c +++ b/dll/ntdll/rtl/libsupp.c @@ -505,6 +505,49 @@ RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index) return NULL; } +/* Ldr SEH-Protected access to IMAGE_NT_HEADERS */ + +/* Rtl SEH-Free version of this */ +NTSTATUS +NTAPI +RtlpImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders); + + +/* + * @implemented + * @note: This is here, so that we do not drag SEH into rosload, freeldr and bootmgfw + */ +NTSTATUS +NTAPI +RtlImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders) +{ + NTSTATUS Status; + + /* Assume failure. This is also done in RtlpImageNtHeaderEx, but this is guarded by SEH. */ + if (OutHeaders != NULL) + *OutHeaders = NULL; + + _SEH2_TRY + { + Status = RtlpImageNtHeaderEx(Flags, Base, Size, OutHeaders); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Fail with the SEH error */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + return Status; +} /* * Ldr Resource support code diff --git a/dll/win32/kernel32/client/loader.c b/dll/win32/kernel32/client/loader.c index ec41114..93eb366 100644 --- a/dll/win32/kernel32/client/loader.c +++ b/dll/win32/kernel32/client/loader.c @@ -464,17 +464,8 @@ FreeLibrary(HINSTANCE hLibModule) if (LDR_IS_DATAFILE(hLibModule)) { - // FIXME: This SEH should go inside RtlImageNtHeader instead - // See https://jira.reactos.org/browse/CORE-14857 - _SEH2_TRY - { - /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */ - NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - NtHeaders = NULL; - } _SEH2_END + /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */ + NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)); if (NtHeaders) { diff --git a/ntoskrnl/rtl/libsupp.c b/ntoskrnl/rtl/libsupp.c index d461a79..c1ded68 100644 --- a/ntoskrnl/rtl/libsupp.c +++ b/ntoskrnl/rtl/libsupp.c @@ -691,6 +691,49 @@ RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index) return Entry; } +/* Ldr SEH-Protected access to IMAGE_NT_HEADERS */ + +/* Rtl SEH-Free version of this */ +NTSTATUS +NTAPI +RtlpImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders); + +/* + * @implemented + * @note: This is here, so that we do not drag SEH into rosload, freeldr and bootmgfw + */ +NTSTATUS +NTAPI +RtlImageNtHeaderEx( + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS *OutHeaders) +{ + NTSTATUS Status; + + /* Assume failure. This is also done in RtlpImageNtHeaderEx, but this is guarded by SEH. */ + if (OutHeaders != NULL) + *OutHeaders = NULL; + + _SEH2_TRY + { + Status = RtlpImageNtHeaderEx(Flags, Base, Size, OutHeaders); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Fail with the SEH error */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + return Status; +} + /* * Ldr Resource support code */ diff --git a/sdk/lib/rtl/image.c b/sdk/lib/rtl/image.c index 5629c77..5ae6f67 100644 --- a/sdk/lib/rtl/image.c +++ b/sdk/lib/rtl/image.c @@ -134,11 +134,10 @@ LdrVerifyMappedImageMatchesChecksum( /* * @implemented - * @note This needs SEH (See https://jira.reactos.org/browse/CORE-14857) */ NTSTATUS NTAPI -RtlImageNtHeaderEx( +RtlpImageNtHeaderEx( _In_ ULONG Flags, _In_ PVOID Base, _In_ ULONG64 Size, diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h index 5b6f49c..7eef1d6 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 42d5000..7bcc65f 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,28 +597,38 @@ 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); - lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam); + pCWP = (CWPSTRUCT*) lParam; + ArgumentLength = sizeof(CWP_Struct); + if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE ) + { + lParamSize = sizeof(CREATESTRUCTW); + } + else + lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam); ArgumentLength += lParamSize; break; } case WH_CALLWNDPROCRET: { - CWPRETSTRUCT* pCWPR = (CWPRETSTRUCT*) lParam; - ArgumentLength += sizeof(CWPRETSTRUCT); - lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam); + pCWPR = (CWPRETSTRUCT*) lParam; + ArgumentLength = sizeof(CWPR_Struct); + if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE ) + { + lParamSize = sizeof(CREATESTRUCTW); + } + else + lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam); ArgumentLength += lParamSize; break; } @@ -635,7 +649,7 @@ co_IntCallHookProc(INT HookId, Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { - ERR("HookProc callback failed: out of memory\n"); + ERR("HookProc callback %d failed: out of memory %d\n",HookId,ArgumentLength); goto Fault_Exit; } Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument; @@ -647,6 +661,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) { @@ -666,9 +681,10 @@ co_IntCallHookProc(INT HookId, CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra; RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; - CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; - CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; + CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; + CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; Common->lParam = (LPARAM) (Extra - (PCHAR) Common); + //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, CbtCreateWnd->lpcs, CbtCreateWnd->lpcs->lpszName, CbtCreateWnd->lpcs->lpszClass); break; case HCBT_CLICKSKIPPED: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); @@ -697,25 +713,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 +763,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 ArgumentLength %d\n",HookId,Status,ArgumentLength); + iTheId = HookId; + } goto Fault_Exit; } @@ -1216,12 +1238,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 +1253,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/ntuser/callback.h b/win32ss/user/ntuser/callback.h index 2eee4e9..c83be89 100644 --- a/win32ss/user/ntuser/callback.h +++ b/win32ss/user/ntuser/callback.h @@ -75,3 +75,4 @@ HANDLE FASTCALL co_IntCopyImage(HANDLE,UINT,INT,INT,UINT); BOOL FASTCALL co_IntSetWndIcons(VOID); VOID FASTCALL co_IntDeliverUserAPC(VOID); VOID FASTCALL co_IntSetupOBM(VOID); +BOOL FASTCALL IntMsgCreateStructW(PWND,CREATESTRUCTW*,CREATESTRUCTW*,PVOID*,PVOID*); diff --git a/win32ss/user/ntuser/message.c b/win32ss/user/ntuser/message.c index 2fd47c4..d2649f2 100644 --- a/win32ss/user/ntuser/message.c +++ b/win32ss/user/ntuser/message.c @@ -577,37 +577,184 @@ GetWakeMask(UINT first, UINT last ) return mask; } +// +// Pass Strings to User Heap Space for Message Hook Callbacks. +// +BOOL +FASTCALL +IntMsgCreateStructW( + PWND Window, + CREATESTRUCTW *pCsw, + CREATESTRUCTW *Cs, + PVOID *ppszClass, + PVOID *ppszName ) +{ + PLARGE_STRING WindowName; + PUNICODE_STRING ClassName; + PVOID pszClass = NULL, pszName = NULL; + + /* Fill the new CREATESTRUCTW */ + RtlCopyMemory(pCsw, Cs, sizeof(CREATESTRUCTW)); + pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */ + + WindowName = (PLARGE_STRING) Cs->lpszName; + ClassName = (PUNICODE_STRING) Cs->lpszClass; + + // Based on the assumption this is from "unicode source" user32, ReactOS, answer is yes. + if (!IS_ATOM(ClassName->Buffer)) + { + if (ClassName->Length) + { + if (Window->state & WNDS_ANSICREATOR) + { + ANSI_STRING AnsiString; + AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(ClassName)+sizeof(CHAR); + pszClass = UserHeapAlloc(AnsiString.MaximumLength); + if (!pszClass) + { + ERR("UserHeapAlloc() failed!\n"); + return FALSE; + } + RtlZeroMemory(pszClass, AnsiString.MaximumLength); + AnsiString.Buffer = (PCHAR)pszClass; + RtlUnicodeStringToAnsiString(&AnsiString, ClassName, FALSE); + } + else + { + UNICODE_STRING UnicodeString; + UnicodeString.MaximumLength = ClassName->Length + sizeof(UNICODE_NULL); + pszClass = UserHeapAlloc(UnicodeString.MaximumLength); + if (!pszClass) + { + ERR("UserHeapAlloc() failed!\n"); + return FALSE; + } + RtlZeroMemory(pszClass, UnicodeString.MaximumLength); + UnicodeString.Buffer = (PWSTR)pszClass; + RtlCopyUnicodeString(&UnicodeString, ClassName); + } + *ppszClass = pszClass; + pCsw->lpszClass = UserHeapAddressToUser(pszClass); + } + else + { + pCsw->lpszClass = NULL; + } + } + else + { + pCsw->lpszClass = ClassName->Buffer; + } + if (WindowName->Length) + { + UNICODE_STRING Name; + Name.Buffer = WindowName->Buffer; + Name.Length = (USHORT)min(WindowName->Length, MAXUSHORT); // FIXME: LARGE_STRING truncated + Name.MaximumLength = (USHORT)min(WindowName->MaximumLength, MAXUSHORT); + + if (Window->state & WNDS_ANSICREATOR) + { + ANSI_STRING AnsiString; + AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&Name) + sizeof(CHAR); + pszName = UserHeapAlloc(AnsiString.MaximumLength); + if (!pszName) + { + ERR("UserHeapAlloc() failed!\n"); + return FALSE; + } + RtlZeroMemory(pszName, AnsiString.MaximumLength); + AnsiString.Buffer = (PCHAR)pszName; + RtlUnicodeStringToAnsiString(&AnsiString, &Name, FALSE); + } + else + { + UNICODE_STRING UnicodeString; + UnicodeString.MaximumLength = Name.Length + sizeof(UNICODE_NULL); + pszName = UserHeapAlloc(UnicodeString.MaximumLength); + if (!pszName) + { + ERR("UserHeapAlloc() failed!\n"); + return FALSE; + } + RtlZeroMemory(pszName, UnicodeString.MaximumLength); + UnicodeString.Buffer = (PWSTR)pszName; + RtlCopyUnicodeString(&UnicodeString, &Name); + } + *ppszName = pszName; + pCsw->lpszName = UserHeapAddressToUser(pszName); + } + else + { + pCsw->lpszName = NULL; + } + + return TRUE; +} + static VOID FASTCALL -IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) { BOOL SameThread = FALSE; CWPSTRUCT CWP; + PVOID pszClass = NULL, pszName = NULL; + CREATESTRUCTW Csw; + + //// Check for a hook to eliminate overhead. //// + if ( !ISITHOOKED(WH_CALLWNDPROC) && !(Window->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROC)) ) + return; if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread())) SameThread = TRUE; + if ( Msg == WM_CREATE || Msg == WM_NCCREATE ) + { // + // String pointers are in user heap space, like WH_CBT HCBT_CREATEWND. + // + if (!IntMsgCreateStructW( Window, &Csw, (CREATESTRUCTW *)lParam, &pszClass, &pszName )) + return; + lParam = (LPARAM)&Csw; + } + CWP.hwnd = hWnd; CWP.message = Msg; CWP.wParam = wParam; CWP.lParam = lParam; co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP ); + + if (pszName) UserHeapFree(pszName); + if (pszClass) UserHeapFree(pszClass); } static VOID FASTCALL -IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult) +IntCallWndProcRet( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult ) { BOOL SameThread = FALSE; CWPRETSTRUCT CWPR; + PVOID pszClass = NULL, pszName = NULL; + CREATESTRUCTW Csw; + + if ( !ISITHOOKED(WH_CALLWNDPROCRET) && !(Window->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROCRET)) ) + return; if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread())) SameThread = TRUE; + if ( Msg == WM_CREATE || Msg == WM_NCCREATE ) + { + if (!IntMsgCreateStructW( Window, &Csw, (CREATESTRUCTW *)lParam, &pszClass, &pszName )) + return; + lParam = (LPARAM)&Csw; + } + CWPR.hwnd = hWnd; CWPR.message = Msg; CWPR.wParam = wParam; CWPR.lParam = lParam; CWPR.lResult = uResult ? (*uResult) : 0; co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR ); + + if (pszName) UserHeapFree(pszName); + if (pszClass) UserHeapFree(pszClass); } static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam ) @@ -2892,7 +3039,7 @@ DWORD APIENTRY NtUserWaitForInputIdle( IN HANDLE hProcess, IN DWORD dwMilliseconds, - IN BOOL Unknown2) + IN BOOL bSharedWow) { PEPROCESS Process; PPROCESSINFO W32Process; diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c index c34dcea..c8bc768 100644 --- a/win32ss/user/ntuser/window.c +++ b/win32ss/user/ntuser/window.c @@ -2102,6 +2102,10 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, UserDereferenceObject(Window); ObDereferenceObject(WinSta); + /* NCCREATE, WM_NCCALCSIZE and Hooks need the original values */ + Cs->lpszName = (LPCWSTR) WindowName; + Cs->lpszClass = (LPCWSTR) ClassName; + //// Check for a hook to eliminate overhead. //// if ( ISITHOOKED(WH_CBT) || (pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)) ) { @@ -2114,79 +2118,10 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, goto cleanup; } - /* Fill the new CREATESTRUCTW */ - RtlCopyMemory(pCsw, Cs, sizeof(CREATESTRUCTW)); - pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */ - - // Based on the assumption this is from "unicode source" user32, ReactOS, answer is yes. - if (!IS_ATOM(ClassName->Buffer)) - { - if (Window->state & WNDS_ANSICREATOR) - { - ANSI_STRING AnsiString; - AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(ClassName)+sizeof(CHAR); - pszClass = UserHeapAlloc(AnsiString.MaximumLength); - if (!pszClass) - { - ERR("UserHeapAlloc() failed!\n"); - goto cleanup; - } - RtlZeroMemory(pszClass, AnsiString.MaximumLength); - AnsiString.Buffer = (PCHAR)pszClass; - RtlUnicodeStringToAnsiString(&AnsiString, ClassName, FALSE); - } - else - { - UNICODE_STRING UnicodeString; - UnicodeString.MaximumLength = ClassName->Length + sizeof(UNICODE_NULL); - pszClass = UserHeapAlloc(UnicodeString.MaximumLength); - if (!pszClass) - { - ERR("UserHeapAlloc() failed!\n"); - goto cleanup; - } - RtlZeroMemory(pszClass, UnicodeString.MaximumLength); - UnicodeString.Buffer = (PWSTR)pszClass; - RtlCopyUnicodeString(&UnicodeString, ClassName); - } - pCsw->lpszClass = UserHeapAddressToUser(pszClass); - } - if (WindowName->Length) + if (!IntMsgCreateStructW( Window, pCsw, Cs, &pszClass, &pszName ) ) { - UNICODE_STRING Name; - Name.Buffer = WindowName->Buffer; - Name.Length = (USHORT)min(WindowName->Length, MAXUSHORT); // FIXME: LARGE_STRING truncated - Name.MaximumLength = (USHORT)min(WindowName->MaximumLength, MAXUSHORT); - - if (Window->state & WNDS_ANSICREATOR) - { - ANSI_STRING AnsiString; - AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&Name) + sizeof(CHAR); - pszName = UserHeapAlloc(AnsiString.MaximumLength); - if (!pszName) - { - ERR("UserHeapAlloc() failed!\n"); - goto cleanup; - } - RtlZeroMemory(pszName, AnsiString.MaximumLength); - AnsiString.Buffer = (PCHAR)pszName; - RtlUnicodeStringToAnsiString(&AnsiString, &Name, FALSE); - } - else - { - UNICODE_STRING UnicodeString; - UnicodeString.MaximumLength = Name.Length + sizeof(UNICODE_NULL); - pszName = UserHeapAlloc(UnicodeString.MaximumLength); - if (!pszName) - { - ERR("UserHeapAlloc() failed!\n"); - goto cleanup; - } - RtlZeroMemory(pszName, UnicodeString.MaximumLength); - UnicodeString.Buffer = (PWSTR)pszName; - RtlCopyUnicodeString(&UnicodeString, &Name); - } - pCsw->lpszName = UserHeapAddressToUser(pszName); + ERR("IntMsgCreateStructW() failed!\n"); + goto cleanup; } pCbtCreate->lpcs = pCsw; @@ -2207,10 +2142,6 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, hwndInsertAfter = pCbtCreate->hwndInsertAfter; } - /* NCCREATE and WM_NCCALCSIZE need the original values */ - Cs->lpszName = (LPCWSTR) WindowName; - Cs->lpszClass = (LPCWSTR) ClassName; - if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) { if (ParentWindow != co_GetDesktopWindow(Window)) diff --git a/win32ss/user/user32/windows/hook.c b/win32ss/user/user32/windows/hook.c index e0cb8e4..78b1a37 100644 --- a/win32ss/user/user32/windows/hook.c +++ b/win32ss/user/user32/windows/hook.c @@ -554,8 +554,8 @@ NTSTATUS WINAPI User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) { PHOOKPROC_CALLBACK_ARGUMENTS Common; - CREATESTRUCTW Csw; - CBT_CREATEWNDW CbtCreatewndw; + CREATESTRUCTW *pCsw = NULL; + CBT_CREATEWNDW *pCbtCreatewndw = NULL; PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData; MSLLHOOKSTRUCT MouseLlData, *pMouseLlData; @@ -608,12 +608,18 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) case HCBT_CREATEWND: CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) ((PCHAR) Common + Common->lParam); - RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW)); - CbtCreatewndw.lpcs = &Csw; - CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; + + pCbtCreatewndw = (CBT_CREATEWNDW*)HeapAlloc(GetProcessHeap(), 0, sizeof(CBT_CREATEWNDW)); + RtlCopyMemory(pCbtCreatewndw, CbtCreatewndExtra, sizeof(CBT_CREATEWNDW)); + + pCsw = (CREATESTRUCTW*)HeapAlloc(GetProcessHeap(), 0, sizeof(CREATESTRUCTW)); + RtlCopyMemory(pCsw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW)); + + pCbtCreatewndw->lpcs = pCsw; + pCbtCreatewndw->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; wParam = Common->wParam; - lParam = (LPARAM) &CbtCreatewndw; - //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass); + lParam = (LPARAM) pCbtCreatewndw; + //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, pCsw, pCsw->lpszName, pCsw->lpszClass); break; case HCBT_CLICKSKIPPED: pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); @@ -665,11 +671,13 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) switch(Common->Code) { case HCBT_CREATEWND: - CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter; - CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x; - CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y; - CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx; - CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy; + CbtCreatewndExtra->WndInsertAfter = pCbtCreatewndw->hwndInsertAfter; + CbtCreatewndExtra->Cs.x = pCbtCreatewndw->lpcs->x; + CbtCreatewndExtra->Cs.y = pCbtCreatewndw->lpcs->y; + CbtCreatewndExtra->Cs.cx = pCbtCreatewndw->lpcs->cx; + CbtCreatewndExtra->Cs.cy = pCbtCreatewndw->lpcs->cy; + HeapFree(GetProcessHeap(), 0, pCsw); + HeapFree(GetProcessHeap(), 0, pCbtCreatewndw); break; } break; @@ -699,35 +707,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: diff --git a/win32ss/user/user32/windows/window.c b/win32ss/user/user32/windows/window.c index e94d9a1..0660c5f 100644 --- a/win32ss/user/user32/windows/window.c +++ b/win32ss/user/user32/windows/window.c @@ -159,16 +159,18 @@ RtlGetExpWinVer( HMODULE hModule ) if ( hModule && !((ULONG_PTR)hModule >> 16)) { pinth = RtlImageNtHeader( hModule ); - - dwMajorVersion = pinth->OptionalHeader.MajorSubsystemVersion; - - if ( dwMajorVersion == 1 ) - { - dwMajorVersion = 3; - } - else + if ( pinth ) { - dwMinorVersion = pinth->OptionalHeader.MinorSubsystemVersion; + dwMajorVersion = pinth->OptionalHeader.MajorSubsystemVersion; + + if ( dwMajorVersion == 1 ) + { + dwMajorVersion = 3; + } + else + { + dwMinorVersion = pinth->OptionalHeader.MinorSubsystemVersion; + } } } return MAKELONG(MAKEWORD(dwMinorVersion, dwMajorVersion), 0);