VOID APIENTRY co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback, HWND hWnd, UINT Msg, ULONG_PTR CompletionCallbackContext, LRESULT Result) { SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments; PVOID ResultPointer, pActCtx; PWND pWnd; ULONG ResultLength; NTSTATUS Status; /* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); Arguments.Callback = CompletionCallback; Arguments.Wnd = hWnd; Arguments.Msg = Msg; Arguments.Context = CompletionCallbackContext; Arguments.Result = Result; IntSetTebWndCallback (&hWnd, &pWnd, &pActCtx); UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC, &Arguments, sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS), &ResultPointer, &ResultLength); UserEnterCo(); IntRestoreTebWndCallback (hWnd, pWnd, pActCtx); if (!NT_SUCCESS(Status)) { return; } return; }
LRESULT APIENTRY co_IntCallWindowProc(WNDPROC Proc, BOOLEAN IsAnsiProc, HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam, INT lParamBufferSize) { WINDOWPROC_CALLBACK_ARGUMENTS StackArguments; PWINDOWPROC_CALLBACK_ARGUMENTS Arguments; NTSTATUS Status; PVOID ResultPointer, pActCtx; PWND pWnd; ULONG ResultLength; ULONG ArgumentLength; LRESULT Result; /* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); if (lParamBufferSize != -1) { ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize; Arguments = IntCbAllocateMemory(ArgumentLength); if (NULL == Arguments) { ERR("Unable to allocate buffer for window proc callback\n"); return -1; } RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), (PVOID) lParam, lParamBufferSize); } else { Arguments = &StackArguments; ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS); } Arguments->Proc = Proc; Arguments->IsAnsiProc = IsAnsiProc; Arguments->Wnd = Wnd; Arguments->Msg = Message; Arguments->wParam = wParam; Arguments->lParam = lParam; Arguments->lParamBufferSize = lParamBufferSize; ResultPointer = NULL; ResultLength = ArgumentLength; IntSetTebWndCallback (&Wnd, &pWnd, &pActCtx); UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC, Arguments, ArgumentLength, &ResultPointer, &ResultLength); _SEH2_TRY { /* Simulate old behaviour: copy into our local buffer */ RtlMoveMemory(Arguments, ResultPointer, ArgumentLength); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Failed to copy result from user mode, Message %d lParam size %d!\n", Message, lParamBufferSize); Status = _SEH2_GetExceptionCode(); } _SEH2_END; UserEnterCo(); IntRestoreTebWndCallback (Wnd, pWnd, pActCtx); if (!NT_SUCCESS(Status)) { ERR("Call to user mode failed!\n"); if (lParamBufferSize != -1) { IntCbFreeMemory(Arguments); } return -1; } Result = Arguments->Result; if (lParamBufferSize != -1) { PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); // Is this message being processed from inside kernel space? BOOL InSendMessage = (pti->pcti->CTI_flags & CTI_INSENDMESSAGE); TRACE("Copy lParam Message %d lParam %d!\n", Message, lParam); switch (Message) { default: TRACE("Don't copy lParam, Message %d Size %d lParam %d!\n", Message, lParamBufferSize, lParam); break; // Write back to user/kernel space. Also see g_MsgMemory. case WM_CREATE: case WM_GETMINMAXINFO: case WM_GETTEXT: case WM_NCCALCSIZE: case WM_NCCREATE: case WM_STYLECHANGING: case WM_WINDOWPOSCHANGING: case WM_SIZING: case WM_MOVING: TRACE("Copy lParam, Message %d Size %d lParam %d!\n", Message, lParamBufferSize, lParam); if (InSendMessage) // Copy into kernel space. RtlMoveMemory((PVOID) lParam, (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), lParamBufferSize); else { _SEH2_TRY { // Copy into user space. RtlMoveMemory((PVOID) lParam, (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), lParamBufferSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Failed to copy lParam to user space, Message %d!\n", Message); } _SEH2_END; } break; } IntCbFreeMemory(Arguments); }
LRESULT APIENTRY co_IntCallWindowProc(WNDPROC Proc, BOOLEAN IsAnsiProc, HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam, INT lParamBufferSize) { WINDOWPROC_CALLBACK_ARGUMENTS StackArguments; PWINDOWPROC_CALLBACK_ARGUMENTS Arguments; NTSTATUS Status; PVOID ResultPointer, pActCtx; PWND pWnd; ULONG ResultLength; ULONG ArgumentLength; LRESULT Result; /* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); if (0 < lParamBufferSize) { ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize; Arguments = IntCbAllocateMemory(ArgumentLength); if (NULL == Arguments) { ERR("Unable to allocate buffer for window proc callback\n"); return -1; } RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), (PVOID) lParam, lParamBufferSize); } else { Arguments = &StackArguments; ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS); } Arguments->Proc = Proc; Arguments->IsAnsiProc = IsAnsiProc; Arguments->Wnd = Wnd; Arguments->Msg = Message; Arguments->wParam = wParam; Arguments->lParam = lParam; Arguments->lParamBufferSize = lParamBufferSize; ResultPointer = NULL; ResultLength = ArgumentLength; IntSetTebWndCallback (&Wnd, &pWnd, &pActCtx); UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC, Arguments, ArgumentLength, &ResultPointer, &ResultLength); _SEH2_TRY { /* Simulate old behaviour: copy into our local buffer */ RtlMoveMemory(Arguments, ResultPointer, ArgumentLength); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Failed to copy result from user mode!\n"); Status = _SEH2_GetExceptionCode(); } _SEH2_END; UserEnterCo(); IntRestoreTebWndCallback (Wnd, pWnd, pActCtx); if (!NT_SUCCESS(Status)) { ERR("Call to user mode failed!\n"); if (0 < lParamBufferSize) { IntCbFreeMemory(Arguments); } return -1; } Result = Arguments->Result; if (0 < lParamBufferSize) { RtlMoveMemory((PVOID) lParam, (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), lParamBufferSize); IntCbFreeMemory(Arguments); } return Result; }