/* Calls ClientLoadLibrary in user32 */ BOOL NTAPI co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, PUNICODE_STRING pstrInitFunc, BOOL Unload, BOOL ApiHook) { PVOID ResultPointer; ULONG ResultLength; ULONG ArgumentLength; PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments; NTSTATUS Status; BOOL bResult; ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0; /* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook); /* Calculate the size of the argument */ ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS); if(pstrLibName) { pLibNameBuffer = ArgumentLength; ArgumentLength += pstrLibName->Length + sizeof(WCHAR); } if(pstrInitFunc) { pInitFuncBuffer = ArgumentLength; ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR); } /* Allocate the argument */ pArguments = IntCbAllocateMemory(ArgumentLength); if(pArguments == NULL) { return FALSE; } /* Fill the argument */ pArguments->Unload = Unload; pArguments->ApiHook = ApiHook; if(pstrLibName) { /* Copy the string to the callback memory */ pLibNameBuffer += (ULONG_PTR)pArguments; pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer; pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR); RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName); /* Fix argument pointer to be relative to the argument */ pLibNameBuffer -= (ULONG_PTR)pArguments; pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer); } else { RtlZeroMemory(&pArguments->strLibraryName, sizeof(UNICODE_STRING)); } if(pstrInitFunc) { /* Copy the strings to the callback memory */ pInitFuncBuffer += (ULONG_PTR)pArguments; pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer; pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR); RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc); /* Fix argument pointers to be relative to the argument */ pInitFuncBuffer -= (ULONG_PTR)pArguments; pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer); } else { RtlZeroMemory(&pArguments->strInitFuncName, sizeof(UNICODE_STRING)); } /* Do the callback */ UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY, pArguments, ArgumentLength, &ResultPointer, &ResultLength); UserEnterCo(); /* Free the argument */ IntCbFreeMemory(pArguments); if(!NT_SUCCESS(Status)) { return FALSE; } _SEH2_TRY { /* Probe and copy the usermode result data */ ProbeForRead(ResultPointer, sizeof(HMODULE), 1); bResult = *(BOOL*)ResultPointer; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { bResult = FALSE; } _SEH2_END; return bResult; }
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; }