[WIN32SS/USER]

- Handle transferring buffer to user mode in WH_CALLWNDPROC(RET) hooks if lParam is a pointer.
This fixes the gallium3d opengl ICD, so newest VMWare opengl Driver should now work.
Please TEST!

svn path=/trunk/; revision=56931
This commit is contained in:
Jérôme Gardou 2012-07-21 22:59:41 +00:00
parent 5cc65e64c7
commit 4be2c40f92
4 changed files with 77 additions and 23 deletions

View file

@ -13,6 +13,7 @@
#include <win32k.h> #include <win32k.h>
DBG_DEFAULT_CHANNEL(UserCallback); DBG_DEFAULT_CHANNEL(UserCallback);
/* CALLBACK MEMORY MANAGEMENT ************************************************/ /* CALLBACK MEMORY MANAGEMENT ************************************************/
typedef struct _INT_CALLBACK_HEADER typedef struct _INT_CALLBACK_HEADER
@ -115,8 +116,8 @@ IntRestoreTebWndCallback (HWND hWnd, PWND pWnd, PVOID pActCtx)
/* Calls ClientLoadLibrary in user32 */ /* Calls ClientLoadLibrary in user32 */
HMODULE HMODULE
co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
PUNICODE_STRING pstrInitFunc, PUNICODE_STRING pstrInitFunc,
BOOL Unload, BOOL Unload,
BOOL ApiHook) BOOL ApiHook)
{ {
@ -139,7 +140,7 @@ co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
} }
if(pstrInitFunc) if(pstrInitFunc)
{ {
pInitFuncBuffer = ArgumentLength; pInitFuncBuffer = ArgumentLength;
ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR); ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR);
} }
@ -443,6 +444,7 @@ co_IntCallHookProc(INT HookId,
PWND pWnd; PWND pWnd;
PMSG pMsg = NULL; PMSG pMsg = NULL;
BOOL Hit = FALSE; BOOL Hit = FALSE;
UINT lParamSize = 0;
ASSERT(Proc); ASSERT(Proc);
@ -509,11 +511,21 @@ co_IntCallHookProc(INT HookId,
ArgumentLength += sizeof(MOUSEHOOKSTRUCT); ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
break; break;
case WH_CALLWNDPROC: case WH_CALLWNDPROC:
{
CWPSTRUCT* pCWP = (CWPSTRUCT*) lParam;
ArgumentLength += sizeof(CWPSTRUCT); ArgumentLength += sizeof(CWPSTRUCT);
lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam);
ArgumentLength += lParamSize;
break; break;
}
case WH_CALLWNDPROCRET: case WH_CALLWNDPROCRET:
{
CWPRETSTRUCT* pCWPR = (CWPRETSTRUCT*) lParam;
ArgumentLength += sizeof(CWPRETSTRUCT); ArgumentLength += sizeof(CWPRETSTRUCT);
lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam);
ArgumentLength += lParamSize;
break; break;
}
case WH_MSGFILTER: case WH_MSGFILTER:
case WH_SYSMSGFILTER: case WH_SYSMSGFILTER:
case WH_GETMESSAGE: case WH_GETMESSAGE:
@ -583,12 +595,25 @@ co_IntCallHookProc(INT HookId,
Common->lParam = (LPARAM) (Extra - (PCHAR) Common); Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
break; break;
case WH_CALLWNDPROC: case WH_CALLWNDPROC:
/* 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)); RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common); Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
if(lParamSize)
{
RtlCopyMemory(Extra + sizeof(CWPSTRUCT), (PVOID)((CWPSTRUCT*)lParam)->lParam, lParamSize);
((CWPSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
}
break; break;
case WH_CALLWNDPROCRET: case WH_CALLWNDPROCRET:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT)); RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common); Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
if(lParamSize)
{
RtlCopyMemory(Extra + sizeof(CWPRETSTRUCT), (PVOID)((CWPRETSTRUCT*)lParam)->lParam, lParamSize);
((CWPRETSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
}
break; break;
case WH_MSGFILTER: case WH_MSGFILTER:
case WH_SYSMSGFILTER: case WH_SYSMSGFILTER:

View file

@ -223,6 +223,13 @@ MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
return Size; return Size;
} }
UINT lParamMemorySize(UINT Msg, WPARAM wParam, LPARAM lParam)
{
PMSGMEMORY MsgMemory = FindMsgMemory(Msg);
if(MsgMemory == NULL) return 0;
return MsgMemorySize(MsgMemory, wParam, lParam);
}
static NTSTATUS static NTSTATUS
PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded) PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded)
{ {
@ -2143,7 +2150,7 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags)
} }
else else
{ {
ERR("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg.hwnd,SafeMsg.message); ERR("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg.hwnd,SafeMsg.message);
Ret = FALSE; Ret = FALSE;
} }
UserLeave(); UserLeave();

View file

@ -296,4 +296,6 @@ UserSetCursor(PCURICON_OBJECT NewCursor,
BOOL ForceChange); BOOL ForceChange);
DWORD APIENTRY IntGetQueueStatus(DWORD); DWORD APIENTRY IntGetQueueStatus(DWORD);
UINT lParamMemorySize(UINT Msg, WPARAM wParam, LPARAM lParam);
/* EOF */ /* EOF */

View file

@ -216,7 +216,7 @@ CallNextHookEx(
ClientInfo = GetWin32ClientInfo(); ClientInfo = GetWin32ClientInfo();
if (!ClientInfo->phkCurrent) return 0; if (!ClientInfo->phkCurrent) return 0;
pHook = DesktopPtrToUser(ClientInfo->phkCurrent); pHook = DesktopPtrToUser(ClientInfo->phkCurrent);
if (!pHook->phkNext) return 0; // Nothing to do.... if (!pHook->phkNext) return 0; // Nothing to do....
@ -240,7 +240,7 @@ CallNextHookEx(
NtUserMessageCall( pCWP->hwnd, NtUserMessageCall( pCWP->hwnd,
pCWP->message, pCWP->message,
pCWP->wParam, pCWP->wParam,
pCWP->lParam, pCWP->lParam,
(ULONG_PTR)&lResult, (ULONG_PTR)&lResult,
FNID_CALLWNDPROC, FNID_CALLWNDPROC,
phkNext->Ansi); phkNext->Ansi);
@ -254,7 +254,7 @@ CallNextHookEx(
NtUserMessageCall( pCWPR->hwnd, NtUserMessageCall( pCWPR->hwnd,
pCWPR->message, pCWPR->message,
pCWPR->wParam, pCWPR->wParam,
pCWPR->lParam, pCWPR->lParam,
(ULONG_PTR)&lResult, (ULONG_PTR)&lResult,
FNID_CALLWNDPROCRET, FNID_CALLWNDPROCRET,
phkNext->Ansi); phkNext->Ansi);
@ -427,8 +427,8 @@ SetWindowsHookExW(
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE); return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE);
} }
HINSTANCE ClientLoadLibrary(PUNICODE_STRING pstrLibName, HINSTANCE ClientLoadLibrary(PUNICODE_STRING pstrLibName,
PUNICODE_STRING pstrInitFunc, PUNICODE_STRING pstrInitFunc,
BOOL Unload, BOOL Unload,
BOOL ApiHook) BOOL ApiHook)
{ {
@ -440,7 +440,7 @@ HINSTANCE ClientLoadLibrary(PUNICODE_STRING pstrLibName,
TRACE("ClientLoadLibrary: pid: %d, strLibraryName: %S, " TRACE("ClientLoadLibrary: pid: %d, strLibraryName: %S, "
"strInitFuncName: %S, Unload: %d, ApiHook:%d\n", "strInitFuncName: %S, Unload: %d, ApiHook:%d\n",
GetCurrentProcessId(), GetCurrentProcessId(),
pstrLibName->Buffer, pstrLibName->Buffer,
pstrInitFunc->Buffer, pstrInitFunc->Buffer,
Unload, Unload,
@ -467,7 +467,7 @@ HINSTANCE ClientLoadLibrary(PUNICODE_STRING pstrLibName,
/* Initialize the user api hook */ /* Initialize the user api hook */
ASSERT(pstrInitFunc->Buffer); ASSERT(pstrInitFunc->Buffer);
/*Status = */ RtlUnicodeStringToAnsiString(&InitFuncName, /*Status = */ RtlUnicodeStringToAnsiString(&InitFuncName,
pstrInitFunc, pstrInitFunc,
TRUE); TRUE);
@ -539,7 +539,7 @@ User32CallClientLoadLibraryFromKernel(PVOID Arguments, ULONG ArgumentLength)
} }
/* Call the implementation of the callback */ /* Call the implementation of the callback */
Result = ClientLoadLibrary(&Argument->strLibraryName, Result = ClientLoadLibrary(&Argument->strLibraryName,
&Argument->strInitFuncName, &Argument->strInitFuncName,
Argument->Unload, Argument->Unload,
Argument->ApiHook); Argument->ApiHook);
@ -558,9 +558,9 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
MSLLHOOKSTRUCT MouseLlData, *pMouseLlData; MSLLHOOKSTRUCT MouseLlData, *pMouseLlData;
MSG *pcMsg, *pMsg; MSG *pcMsg, *pMsg;
PMOUSEHOOKSTRUCT pMHook; PMOUSEHOOKSTRUCT pMHook;
CWPSTRUCT CWP, *pCWP; CWPSTRUCT *pCWP;
CWPRETSTRUCT CWPR, *pCWPR; CWPRETSTRUCT *pCWPR;
PRECTL prl; PRECTL prl;
LPCBTACTIVATESTRUCT pcbtas; LPCBTACTIVATESTRUCT pcbtas;
WPARAM wParam = 0; WPARAM wParam = 0;
LPARAM lParam = 0; LPARAM lParam = 0;
@ -631,7 +631,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
switch(Common->Code) switch(Common->Code)
{ {
case HCBT_CREATEWND: case HCBT_CREATEWND:
CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter; CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x; CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y; CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx; CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
@ -666,14 +666,34 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
break; break;
case WH_CALLWNDPROC: case WH_CALLWNDPROC:
// ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam); // ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam); pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
RtlCopyMemory(&CWP, pCWP, sizeof(CWPSTRUCT)); RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT));
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWP); /* 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)))
{
RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT),
(PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT),
pCWP->lParam);
pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
}
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
HeapFree(GetProcessHeap(), 0, pCWP);
break; break;
case WH_CALLWNDPROCRET: case WH_CALLWNDPROCRET:
pCWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam); /* Almost the same as WH_CALLWNDPROC */
RtlCopyMemory(&CWPR, pCWPR, sizeof(CWPRETSTRUCT)); pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWPR); RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT));
if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
{
RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT),
(PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT),
pCWPR->lParam);
pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
}
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
HeapFree(GetProcessHeap(), 0, pCWPR);
break; break;
case WH_MSGFILTER: /* All SEH support */ case WH_MSGFILTER: /* All SEH support */
case WH_SYSMSGFILTER: case WH_SYSMSGFILTER:
@ -698,7 +718,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
case WH_KEYBOARD: case WH_KEYBOARD:
case WH_SHELL: case WH_SHELL:
Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
break; break;
case WH_FOREGROUNDIDLE: /* <-- SEH support */ case WH_FOREGROUNDIDLE: /* <-- SEH support */
_SEH2_TRY _SEH2_TRY
{ {