xref: /reactos/win32ss/user/ntuser/callback.c (revision 85e292d5)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:        See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:          ReactOS Win32k subsystem
4c2c66affSColin Finck  * PURPOSE:          Callback to usermode support
5c2c66affSColin Finck  * FILE:             win32ss/user/ntuser/callback.c
6c2c66affSColin Finck  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
7c2c66affSColin Finck  *                   Thomas Weidenmueller (w3seek@users.sourceforge.net)
8c2c66affSColin Finck  * NOTES:            Please use the Callback Memory Management functions for
9c2c66affSColin Finck  *                   callbacks to make sure, the memory is freed on thread
10c2c66affSColin Finck  *                   termination!
11c2c66affSColin Finck  */
12c2c66affSColin Finck 
13c2c66affSColin Finck #include <win32k.h>
14c2c66affSColin Finck DBG_DEFAULT_CHANNEL(UserCallback);
15c2c66affSColin Finck 
16c2c66affSColin Finck 
17c2c66affSColin Finck /* CALLBACK MEMORY MANAGEMENT ************************************************/
18c2c66affSColin Finck 
19c2c66affSColin Finck typedef struct _INT_CALLBACK_HEADER
20c2c66affSColin Finck {
21c2c66affSColin Finck    /* List entry in the THREADINFO structure */
22c2c66affSColin Finck    LIST_ENTRY ListEntry;
23c2c66affSColin Finck }
24c2c66affSColin Finck INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER;
25c2c66affSColin Finck 
26c2c66affSColin Finck PVOID FASTCALL
IntCbAllocateMemory(ULONG Size)27c2c66affSColin Finck IntCbAllocateMemory(ULONG Size)
28c2c66affSColin Finck {
29c2c66affSColin Finck    PINT_CALLBACK_HEADER Mem;
30c2c66affSColin Finck    PTHREADINFO W32Thread;
31c2c66affSColin Finck 
32c2c66affSColin Finck    if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER),
33c2c66affSColin Finck                                     USERTAG_CALLBACK)))
34c2c66affSColin Finck    {
35c2c66affSColin Finck       return NULL;
36c2c66affSColin Finck    }
37c2c66affSColin Finck 
38a279b1d2SNguyen Trung Khanh    RtlZeroMemory(Mem, Size + sizeof(INT_CALLBACK_HEADER));
39c2c66affSColin Finck    W32Thread = PsGetCurrentThreadWin32Thread();
40c2c66affSColin Finck    ASSERT(W32Thread);
41c2c66affSColin Finck 
42c2c66affSColin Finck    /* Insert the callback memory into the thread's callback list */
43c2c66affSColin Finck 
44c2c66affSColin Finck    InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry);
45c2c66affSColin Finck 
46c2c66affSColin Finck    return (Mem + 1);
47c2c66affSColin Finck }
48c2c66affSColin Finck 
49c2c66affSColin Finck VOID FASTCALL
IntCbFreeMemory(PVOID Data)50c2c66affSColin Finck IntCbFreeMemory(PVOID Data)
51c2c66affSColin Finck {
52c2c66affSColin Finck    PINT_CALLBACK_HEADER Mem;
53c2c66affSColin Finck    PTHREADINFO W32Thread;
54c2c66affSColin Finck 
55c2c66affSColin Finck    W32Thread = PsGetCurrentThreadWin32Thread();
56c2c66affSColin Finck    ASSERT(W32Thread);
57c2c66affSColin Finck 
58c2c66affSColin Finck    if (W32Thread->TIF_flags & TIF_INCLEANUP)
59c2c66affSColin Finck    {
60c2c66affSColin Finck       ERR("CbFM Thread is already in cleanup\n");
61c2c66affSColin Finck       return;
62c2c66affSColin Finck    }
63c2c66affSColin Finck 
64c2c66affSColin Finck    ASSERT(Data);
65c2c66affSColin Finck 
66c2c66affSColin Finck    Mem = ((PINT_CALLBACK_HEADER)Data - 1);
67c2c66affSColin Finck 
68c2c66affSColin Finck    /* Remove the memory block from the thread's callback list */
69c2c66affSColin Finck    RemoveEntryList(&Mem->ListEntry);
70c2c66affSColin Finck 
71c2c66affSColin Finck    /* Free memory */
72c2c66affSColin Finck    ExFreePoolWithTag(Mem, USERTAG_CALLBACK);
73c2c66affSColin Finck }
74c2c66affSColin Finck 
75c2c66affSColin Finck VOID FASTCALL
IntCleanupThreadCallbacks(PTHREADINFO W32Thread)76c2c66affSColin Finck IntCleanupThreadCallbacks(PTHREADINFO W32Thread)
77c2c66affSColin Finck {
78c2c66affSColin Finck    PLIST_ENTRY CurrentEntry;
79c2c66affSColin Finck    PINT_CALLBACK_HEADER Mem;
80c2c66affSColin Finck 
81c2c66affSColin Finck    while (!IsListEmpty(&W32Thread->W32CallbackListHead))
82c2c66affSColin Finck    {
83c2c66affSColin Finck       CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead);
84c2c66affSColin Finck       Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER,
85c2c66affSColin Finck                               ListEntry);
86c2c66affSColin Finck 
87c2c66affSColin Finck       /* Free memory */
88c2c66affSColin Finck       ExFreePoolWithTag(Mem, USERTAG_CALLBACK);
89c2c66affSColin Finck    }
90c2c66affSColin Finck }
91c2c66affSColin Finck 
92c2c66affSColin Finck //
93c2c66affSColin Finck // Pass the Current Window handle and pointer to the Client Callback.
94c2c66affSColin Finck // This will help user space programs speed up read access with the window object.
95c2c66affSColin Finck //
96c2c66affSColin Finck static VOID
IntSetTebWndCallback(HWND * hWnd,PWND * pWnd,PVOID * pActCtx)97c2c66affSColin Finck IntSetTebWndCallback (HWND * hWnd, PWND * pWnd, PVOID * pActCtx)
98c2c66affSColin Finck {
99c2c66affSColin Finck   HWND hWndS = *hWnd;
100c2c66affSColin Finck   PWND Window = UserGetWindowObject(*hWnd);
101c2c66affSColin Finck   PCLIENTINFO ClientInfo = GetWin32ClientInfo();
102c2c66affSColin Finck 
103c2c66affSColin Finck   *hWnd = ClientInfo->CallbackWnd.hWnd;
104c2c66affSColin Finck   *pWnd = ClientInfo->CallbackWnd.pWnd;
105c2c66affSColin Finck   *pActCtx = ClientInfo->CallbackWnd.pActCtx;
106c2c66affSColin Finck 
107c2c66affSColin Finck   if (Window)
108c2c66affSColin Finck   {
109c2c66affSColin Finck      ClientInfo->CallbackWnd.hWnd = hWndS;
110c2c66affSColin Finck      ClientInfo->CallbackWnd.pWnd = DesktopHeapAddressToUser(Window);
111c2c66affSColin Finck      ClientInfo->CallbackWnd.pActCtx = Window->pActCtx;
112c2c66affSColin Finck   }
113c2c66affSColin Finck   else //// What if Dispatching WM_SYS/TIMER with NULL window? Fix AbiWord Crash when sizing.
114c2c66affSColin Finck   {
115c2c66affSColin Finck      ClientInfo->CallbackWnd.hWnd = hWndS;
116c2c66affSColin Finck      ClientInfo->CallbackWnd.pWnd = Window;
117c2c66affSColin Finck      ClientInfo->CallbackWnd.pActCtx = 0;
118c2c66affSColin Finck   }
119c2c66affSColin Finck }
120c2c66affSColin Finck 
121c2c66affSColin Finck static VOID
IntRestoreTebWndCallback(HWND hWnd,PWND pWnd,PVOID pActCtx)122c2c66affSColin Finck IntRestoreTebWndCallback (HWND hWnd, PWND pWnd, PVOID pActCtx)
123c2c66affSColin Finck {
124c2c66affSColin Finck   PCLIENTINFO ClientInfo = GetWin32ClientInfo();
125c2c66affSColin Finck 
126c2c66affSColin Finck   ClientInfo->CallbackWnd.hWnd = hWnd;
127c2c66affSColin Finck   ClientInfo->CallbackWnd.pWnd = pWnd;
128c2c66affSColin Finck   ClientInfo->CallbackWnd.pActCtx = pActCtx;
129c2c66affSColin Finck }
130c2c66affSColin Finck 
131c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
132c2c66affSColin Finck 
133c2c66affSColin Finck /* Calls ClientLoadLibrary in user32 */
134c2c66affSColin Finck BOOL
135c2c66affSColin Finck NTAPI
co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,PUNICODE_STRING pstrInitFunc,BOOL Unload,BOOL ApiHook)136c2c66affSColin Finck co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
137c2c66affSColin Finck                         PUNICODE_STRING pstrInitFunc,
138c2c66affSColin Finck                         BOOL Unload,
139c2c66affSColin Finck                         BOOL ApiHook)
140c2c66affSColin Finck {
141c2c66affSColin Finck    PVOID ResultPointer;
142c2c66affSColin Finck    ULONG ResultLength;
143c2c66affSColin Finck    ULONG ArgumentLength;
144c2c66affSColin Finck    PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments;
145c2c66affSColin Finck    NTSTATUS Status;
146c2c66affSColin Finck    BOOL bResult;
147c2c66affSColin Finck    ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0;
148c2c66affSColin Finck 
149c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
150c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
151c2c66affSColin Finck 
152c2c66affSColin Finck    TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook);
153c2c66affSColin Finck 
154c2c66affSColin Finck    /* Calculate the size of the argument */
155c2c66affSColin Finck    ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS);
156c2c66affSColin Finck    if(pstrLibName)
157c2c66affSColin Finck    {
158c2c66affSColin Finck        pLibNameBuffer = ArgumentLength;
159c2c66affSColin Finck        ArgumentLength += pstrLibName->Length + sizeof(WCHAR);
160c2c66affSColin Finck    }
161c2c66affSColin Finck    if(pstrInitFunc)
162c2c66affSColin Finck    {
163c2c66affSColin Finck        pInitFuncBuffer = ArgumentLength;
164c2c66affSColin Finck        ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR);
165c2c66affSColin Finck    }
166c2c66affSColin Finck 
167c2c66affSColin Finck    /* Allocate the argument */
168c2c66affSColin Finck    pArguments = IntCbAllocateMemory(ArgumentLength);
169c2c66affSColin Finck    if(pArguments == NULL)
170c2c66affSColin Finck    {
171c2c66affSColin Finck        return FALSE;
172c2c66affSColin Finck    }
173c2c66affSColin Finck 
174c2c66affSColin Finck    /* Fill the argument */
175c2c66affSColin Finck    pArguments->Unload = Unload;
176c2c66affSColin Finck    pArguments->ApiHook = ApiHook;
177c2c66affSColin Finck    if(pstrLibName)
178c2c66affSColin Finck    {
179c2c66affSColin Finck        /* Copy the string to the callback memory */
180c2c66affSColin Finck        pLibNameBuffer += (ULONG_PTR)pArguments;
181c2c66affSColin Finck        pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer;
182c2c66affSColin Finck        pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR);
183c2c66affSColin Finck        RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName);
184c2c66affSColin Finck 
185c2c66affSColin Finck        /* Fix argument pointer to be relative to the argument */
186c2c66affSColin Finck        pLibNameBuffer -= (ULONG_PTR)pArguments;
187c2c66affSColin Finck        pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer);
188c2c66affSColin Finck    }
189c2c66affSColin Finck 
190c2c66affSColin Finck    if(pstrInitFunc)
191c2c66affSColin Finck    {
192c2c66affSColin Finck        /* Copy the strings to the callback memory */
193c2c66affSColin Finck        pInitFuncBuffer += (ULONG_PTR)pArguments;
194c2c66affSColin Finck        pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer;
195c2c66affSColin Finck        pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR);
196c2c66affSColin Finck        RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc);
197c2c66affSColin Finck 
198c2c66affSColin Finck        /* Fix argument pointers to be relative to the argument */
199c2c66affSColin Finck        pInitFuncBuffer -= (ULONG_PTR)pArguments;
200c2c66affSColin Finck        pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer);
201c2c66affSColin Finck    }
202c2c66affSColin Finck 
203c2c66affSColin Finck    /* Do the callback */
204c2c66affSColin Finck    UserLeaveCo();
205c2c66affSColin Finck 
206c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY,
207c2c66affSColin Finck                                pArguments,
208c2c66affSColin Finck                                ArgumentLength,
209c2c66affSColin Finck                                &ResultPointer,
210c2c66affSColin Finck                                &ResultLength);
211c2c66affSColin Finck 
212c2c66affSColin Finck    UserEnterCo();
213c2c66affSColin Finck 
214c2c66affSColin Finck    /* Free the argument */
215c2c66affSColin Finck    IntCbFreeMemory(pArguments);
216c2c66affSColin Finck 
217c2c66affSColin Finck    if(!NT_SUCCESS(Status))
218c2c66affSColin Finck    {
219c2c66affSColin Finck        return FALSE;
220c2c66affSColin Finck    }
221c2c66affSColin Finck 
222c2c66affSColin Finck    _SEH2_TRY
223c2c66affSColin Finck    {
224c2c66affSColin Finck        /* Probe and copy the usermode result data */
225c2c66affSColin Finck        ProbeForRead(ResultPointer, sizeof(HMODULE), 1);
226c2c66affSColin Finck        bResult = *(BOOL*)ResultPointer;
227c2c66affSColin Finck    }
228c2c66affSColin Finck    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
229c2c66affSColin Finck    {
230c2c66affSColin Finck        bResult = FALSE;
231c2c66affSColin Finck    }
232c2c66affSColin Finck    _SEH2_END;
233c2c66affSColin Finck 
234c2c66affSColin Finck    return bResult;
235c2c66affSColin Finck }
236c2c66affSColin Finck 
237c2c66affSColin Finck VOID APIENTRY
co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,HWND hWnd,UINT Msg,ULONG_PTR CompletionCallbackContext,LRESULT Result)238c2c66affSColin Finck co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
239c2c66affSColin Finck                               HWND hWnd,
240c2c66affSColin Finck                               UINT Msg,
241c2c66affSColin Finck                               ULONG_PTR CompletionCallbackContext,
242c2c66affSColin Finck                               LRESULT Result)
243c2c66affSColin Finck {
244c2c66affSColin Finck    SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments;
245c2c66affSColin Finck    PVOID ResultPointer, pActCtx;
246c2c66affSColin Finck    PWND pWnd;
247c2c66affSColin Finck    ULONG ResultLength;
248c2c66affSColin Finck    NTSTATUS Status;
249c2c66affSColin Finck 
250c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
251c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
252c2c66affSColin Finck 
253c2c66affSColin Finck    Arguments.Callback = CompletionCallback;
254c2c66affSColin Finck    Arguments.Wnd = hWnd;
255c2c66affSColin Finck    Arguments.Msg = Msg;
256c2c66affSColin Finck    Arguments.Context = CompletionCallbackContext;
257c2c66affSColin Finck    Arguments.Result = Result;
258c2c66affSColin Finck 
259c2c66affSColin Finck    IntSetTebWndCallback (&hWnd, &pWnd, &pActCtx);
260c2c66affSColin Finck 
261c2c66affSColin Finck    UserLeaveCo();
262c2c66affSColin Finck 
263c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC,
264c2c66affSColin Finck                                &Arguments,
265c2c66affSColin Finck                                sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS),
266c2c66affSColin Finck                                &ResultPointer,
267c2c66affSColin Finck                                &ResultLength);
268c2c66affSColin Finck 
269c2c66affSColin Finck    UserEnterCo();
270c2c66affSColin Finck 
271c2c66affSColin Finck    IntRestoreTebWndCallback (hWnd, pWnd, pActCtx);
272c2c66affSColin Finck 
273c2c66affSColin Finck    if (!NT_SUCCESS(Status))
274c2c66affSColin Finck    {
275c2c66affSColin Finck       ERR("KeUserModeCallback failed with %lx\n", Status);
276c2c66affSColin Finck       return;
277c2c66affSColin Finck    }
278c2c66affSColin Finck    return;
279c2c66affSColin Finck }
280c2c66affSColin Finck 
281c2c66affSColin Finck LRESULT APIENTRY
co_IntCallWindowProc(WNDPROC Proc,BOOLEAN IsAnsiProc,HWND Wnd,UINT Message,WPARAM wParam,LPARAM lParam,INT lParamBufferSize)282c2c66affSColin Finck co_IntCallWindowProc(WNDPROC Proc,
283c2c66affSColin Finck                      BOOLEAN IsAnsiProc,
284c2c66affSColin Finck                      HWND Wnd,
285c2c66affSColin Finck                      UINT Message,
286c2c66affSColin Finck                      WPARAM wParam,
287c2c66affSColin Finck                      LPARAM lParam,
288c2c66affSColin Finck                      INT lParamBufferSize)
289c2c66affSColin Finck {
290a279b1d2SNguyen Trung Khanh    WINDOWPROC_CALLBACK_ARGUMENTS StackArguments = { 0 };
291c2c66affSColin Finck    PWINDOWPROC_CALLBACK_ARGUMENTS Arguments;
292c2c66affSColin Finck    NTSTATUS Status;
293c2c66affSColin Finck    PVOID ResultPointer, pActCtx;
294c2c66affSColin Finck    PWND pWnd;
295c2c66affSColin Finck    ULONG ResultLength;
296c2c66affSColin Finck    ULONG ArgumentLength;
297c2c66affSColin Finck    LRESULT Result;
298c2c66affSColin Finck 
299c2c66affSColin Finck    TRACE("co_IntCallWindowProc(Proc %p, IsAnsiProc: %s, Wnd %p, Message %u, wParam %Iu, lParam %Id, lParamBufferSize %d)\n",
300c2c66affSColin Finck        Proc, IsAnsiProc ? "TRUE" : "FALSE", Wnd, Message, wParam, lParam, lParamBufferSize);
301c2c66affSColin Finck 
302c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
303c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
304c2c66affSColin Finck 
305c2c66affSColin Finck    if (lParamBufferSize != -1)
306c2c66affSColin Finck    {
307c2c66affSColin Finck       ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize;
308c2c66affSColin Finck       Arguments = IntCbAllocateMemory(ArgumentLength);
309c2c66affSColin Finck       if (NULL == Arguments)
310c2c66affSColin Finck       {
311c2c66affSColin Finck          ERR("Unable to allocate buffer for window proc callback\n");
312c2c66affSColin Finck          return -1;
313c2c66affSColin Finck       }
314c2c66affSColin Finck       RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
315c2c66affSColin Finck                     (PVOID) lParam, lParamBufferSize);
316c2c66affSColin Finck    }
317c2c66affSColin Finck    else
318c2c66affSColin Finck    {
319c2c66affSColin Finck       Arguments = &StackArguments;
320c2c66affSColin Finck       ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS);
321c2c66affSColin Finck    }
322c2c66affSColin Finck    Arguments->Proc = Proc;
323c2c66affSColin Finck    Arguments->IsAnsiProc = IsAnsiProc;
324c2c66affSColin Finck    Arguments->Wnd = Wnd;
325c2c66affSColin Finck    Arguments->Msg = Message;
326c2c66affSColin Finck    Arguments->wParam = wParam;
327c2c66affSColin Finck    Arguments->lParam = lParam;
328c2c66affSColin Finck    Arguments->lParamBufferSize = lParamBufferSize;
329c2c66affSColin Finck    ResultPointer = NULL;
330c2c66affSColin Finck    ResultLength = ArgumentLength;
331c2c66affSColin Finck 
332c2c66affSColin Finck    IntSetTebWndCallback (&Wnd, &pWnd, &pActCtx);
333c2c66affSColin Finck 
334c2c66affSColin Finck    UserLeaveCo();
335c2c66affSColin Finck 
336c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC,
337c2c66affSColin Finck                                Arguments,
338c2c66affSColin Finck                                ArgumentLength,
339c2c66affSColin Finck                                &ResultPointer,
340c2c66affSColin Finck                                &ResultLength);
341c2c66affSColin Finck    if (!NT_SUCCESS(Status))
342c2c66affSColin Finck    {
343c2c66affSColin Finck       ERR("Error Callback to User space Status %lx Message %d\n",Status,Message);
344c2c66affSColin Finck       UserEnterCo();
345c2c66affSColin Finck       return 0;
346c2c66affSColin Finck    }
347c2c66affSColin Finck 
348c2c66affSColin Finck    _SEH2_TRY
349c2c66affSColin Finck    {
350c2c66affSColin Finck       /* Simulate old behaviour: copy into our local buffer */
351c2c66affSColin Finck       RtlMoveMemory(Arguments, ResultPointer, ArgumentLength);
352c2c66affSColin Finck    }
353c2c66affSColin Finck    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
354c2c66affSColin Finck    {
355c2c66affSColin Finck       ERR("Failed to copy result from user mode, Message %u lParam size %d!\n", Message, lParamBufferSize);
356c2c66affSColin Finck       Status = _SEH2_GetExceptionCode();
357c2c66affSColin Finck    }
358c2c66affSColin Finck    _SEH2_END;
359c2c66affSColin Finck 
360c2c66affSColin Finck    UserEnterCo();
361c2c66affSColin Finck 
362c2c66affSColin Finck    IntRestoreTebWndCallback (Wnd, pWnd, pActCtx);
363c2c66affSColin Finck 
364c2c66affSColin Finck    if (!NT_SUCCESS(Status))
365c2c66affSColin Finck    {
366c2c66affSColin Finck      ERR("Call to user mode failed! 0x%08lx\n",Status);
367c2c66affSColin Finck       if (lParamBufferSize != -1)
368c2c66affSColin Finck       {
369c2c66affSColin Finck          IntCbFreeMemory(Arguments);
370c2c66affSColin Finck       }
371c2c66affSColin Finck       return -1;
372c2c66affSColin Finck    }
373c2c66affSColin Finck    Result = Arguments->Result;
374c2c66affSColin Finck 
375c2c66affSColin Finck    if (lParamBufferSize != -1)
376c2c66affSColin Finck    {
377c2c66affSColin Finck       PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
378c2c66affSColin Finck       // Is this message being processed from inside kernel space?
379c2c66affSColin Finck       BOOL InSendMessage = (pti->pcti->CTI_flags & CTI_INSENDMESSAGE);
380c2c66affSColin Finck 
381c2c66affSColin Finck       TRACE("Copy lParam Message %u lParam %d!\n", Message, lParam);
382c2c66affSColin Finck       switch (Message)
383c2c66affSColin Finck       {
384c2c66affSColin Finck           default:
385c2c66affSColin Finck             TRACE("Don't copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam);
386c2c66affSColin Finck             break;
387c2c66affSColin Finck           // Write back to user/kernel space. Also see g_MsgMemory.
388c2c66affSColin Finck           case WM_CREATE:
389c2c66affSColin Finck           case WM_GETMINMAXINFO:
390c2c66affSColin Finck           case WM_GETTEXT:
391c2c66affSColin Finck           case WM_NCCALCSIZE:
392c2c66affSColin Finck           case WM_NCCREATE:
393c2c66affSColin Finck           case WM_STYLECHANGING:
394c2c66affSColin Finck           case WM_WINDOWPOSCHANGING:
395c2c66affSColin Finck           case WM_SIZING:
396c2c66affSColin Finck           case WM_MOVING:
397c2c66affSColin Finck           case WM_MEASUREITEM:
398c2c66affSColin Finck           case WM_NEXTMENU:
399c2c66affSColin Finck             TRACE("Copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam);
400c2c66affSColin Finck             if (InSendMessage)
401c2c66affSColin Finck                // Copy into kernel space.
402c2c66affSColin Finck                RtlMoveMemory((PVOID) lParam,
403c2c66affSColin Finck                              (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
404c2c66affSColin Finck                               lParamBufferSize);
405c2c66affSColin Finck             else
406c2c66affSColin Finck             {
407c2c66affSColin Finck              _SEH2_TRY
408c2c66affSColin Finck              { // Copy into user space.
409c2c66affSColin Finck                RtlMoveMemory((PVOID) lParam,
410c2c66affSColin Finck                              (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
411c2c66affSColin Finck                               lParamBufferSize);
412c2c66affSColin Finck              }
413c2c66affSColin Finck              _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
414c2c66affSColin Finck              {
415c2c66affSColin Finck                 ERR("Failed to copy lParam to user space, Message %u!\n", Message);
416c2c66affSColin Finck              }
417c2c66affSColin Finck              _SEH2_END;
418c2c66affSColin Finck             }
419c2c66affSColin Finck             break;
420c2c66affSColin Finck       }
421c2c66affSColin Finck       IntCbFreeMemory(Arguments);
422c2c66affSColin Finck    }
423c2c66affSColin Finck 
424c2c66affSColin Finck    return Result;
425c2c66affSColin Finck }
426c2c66affSColin Finck 
427c2c66affSColin Finck HMENU APIENTRY
co_IntLoadSysMenuTemplate(VOID)428c2c66affSColin Finck co_IntLoadSysMenuTemplate(VOID)
429c2c66affSColin Finck {
430c2c66affSColin Finck    LRESULT Result = 0;
431c2c66affSColin Finck    NTSTATUS Status;
432c2c66affSColin Finck    PVOID ResultPointer;
433c2c66affSColin Finck    ULONG ResultLength;
434c2c66affSColin Finck 
435c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
436c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
437c2c66affSColin Finck 
438c2c66affSColin Finck    ResultPointer = NULL;
439c2c66affSColin Finck    ResultLength = sizeof(LRESULT);
440c2c66affSColin Finck 
441c2c66affSColin Finck    UserLeaveCo();
442c2c66affSColin Finck 
443c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE,
444c2c66affSColin Finck                                &ResultPointer,
445c2c66affSColin Finck                                0,
446c2c66affSColin Finck                                &ResultPointer,
447c2c66affSColin Finck                                &ResultLength);
448c2c66affSColin Finck    if (NT_SUCCESS(Status))
449c2c66affSColin Finck    {
450c2c66affSColin Finck       /* Simulate old behaviour: copy into our local buffer */
451c2c66affSColin Finck       _SEH2_TRY
452c2c66affSColin Finck       {
453c2c66affSColin Finck         ProbeForRead(ResultPointer, sizeof(LRESULT), 1);
454c2c66affSColin Finck         Result = *(LRESULT*)ResultPointer;
455c2c66affSColin Finck       }
456c2c66affSColin Finck       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
457c2c66affSColin Finck       {
458c2c66affSColin Finck         Result = 0;
459c2c66affSColin Finck       }
460c2c66affSColin Finck       _SEH2_END;
461c2c66affSColin Finck    }
462c2c66affSColin Finck 
463c2c66affSColin Finck    UserEnterCo();
464c2c66affSColin Finck 
465c2c66affSColin Finck    return (HMENU)Result;
466c2c66affSColin Finck }
467c2c66affSColin Finck 
468c2c66affSColin Finck extern HCURSOR gDesktopCursor;
469c2c66affSColin Finck 
470c2c66affSColin Finck BOOL APIENTRY
co_IntLoadDefaultCursors(VOID)471c2c66affSColin Finck co_IntLoadDefaultCursors(VOID)
472c2c66affSColin Finck {
473c2c66affSColin Finck    NTSTATUS Status;
474c2c66affSColin Finck    PVOID ResultPointer;
475c2c66affSColin Finck    ULONG ResultLength;
476c2c66affSColin Finck    BOOL DefaultCursor = TRUE;
477c2c66affSColin Finck 
478c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
479c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
480c2c66affSColin Finck 
481c2c66affSColin Finck    ResultPointer = NULL;
482c2c66affSColin Finck    ResultLength = sizeof(HCURSOR);
483c2c66affSColin Finck 
484c2c66affSColin Finck    UserLeaveCo();
485c2c66affSColin Finck 
486c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS,
487c2c66affSColin Finck                                &DefaultCursor,
488c2c66affSColin Finck                                sizeof(BOOL),
489c2c66affSColin Finck                                &ResultPointer,
490c2c66affSColin Finck                                &ResultLength);
491c2c66affSColin Finck 
492c2c66affSColin Finck    UserEnterCo();
493c2c66affSColin Finck 
494c2c66affSColin Finck    if (!NT_SUCCESS(Status))
495c2c66affSColin Finck    {
496c2c66affSColin Finck       return FALSE;
497c2c66affSColin Finck    }
498c2c66affSColin Finck 
499c2c66affSColin Finck    /* HACK: The desktop class doen't have a proper cursor yet, so set it here */
500c2c66affSColin Finck     gDesktopCursor = *((HCURSOR*)ResultPointer);
501c2c66affSColin Finck 
502c2c66affSColin Finck    return TRUE;
503c2c66affSColin Finck }
504c2c66affSColin Finck 
505915a5764Sjimtabor static INT iTheId = -2; // Set it out of range.
506915a5764Sjimtabor 
507c2c66affSColin Finck LRESULT APIENTRY
co_IntCallHookProc(INT HookId,INT Code,WPARAM wParam,LPARAM lParam,HOOKPROC Proc,INT Mod,ULONG_PTR offPfn,BOOLEAN Ansi,PUNICODE_STRING ModuleName)508c2c66affSColin Finck co_IntCallHookProc(INT HookId,
509c2c66affSColin Finck                    INT Code,
510c2c66affSColin Finck                    WPARAM wParam,
511c2c66affSColin Finck                    LPARAM lParam,
512c2c66affSColin Finck                    HOOKPROC Proc,
513c2c66affSColin Finck                    INT Mod,
514c2c66affSColin Finck                    ULONG_PTR offPfn,
515c2c66affSColin Finck                    BOOLEAN Ansi,
516c2c66affSColin Finck                    PUNICODE_STRING ModuleName)
517c2c66affSColin Finck {
518c2c66affSColin Finck    ULONG ArgumentLength;
519c2c66affSColin Finck    PVOID Argument = NULL;
520c2c66affSColin Finck    LRESULT Result = 0;
521c2c66affSColin Finck    NTSTATUS Status;
522c2c66affSColin Finck    PVOID ResultPointer;
523c2c66affSColin Finck    ULONG ResultLength;
524c2c66affSColin Finck    PHOOKPROC_CALLBACK_ARGUMENTS Common;
525c2c66affSColin Finck    CBT_CREATEWNDW *CbtCreateWnd = NULL;
526c2c66affSColin Finck    PCHAR Extra;
527c2c66affSColin Finck    PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
528c2c66affSColin Finck    PTHREADINFO pti;
529c2c66affSColin Finck    PWND pWnd;
530c2c66affSColin Finck    PMSG pMsg = NULL;
531c2c66affSColin Finck    BOOL Hit = FALSE;
532c2c66affSColin Finck    UINT lParamSize = 0;
533915a5764Sjimtabor    CWPSTRUCT* pCWP = NULL;
534915a5764Sjimtabor    CWPRETSTRUCT* pCWPR = NULL;
535c2c66affSColin Finck 
536c2c66affSColin Finck    ASSERT(Proc);
537c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
538c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
539c2c66affSColin Finck 
540c2c66affSColin Finck    pti = PsGetCurrentThreadWin32Thread();
541c2c66affSColin Finck    if (pti->TIF_flags & TIF_INCLEANUP)
542c2c66affSColin Finck    {
543c2c66affSColin Finck       ERR("Thread is in cleanup and trying to call hook %d\n", Code);
544c2c66affSColin Finck       return 0;
545c2c66affSColin Finck    }
546c2c66affSColin Finck 
547c2c66affSColin Finck    ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
548c2c66affSColin Finck 
549c2c66affSColin Finck    switch(HookId)
550c2c66affSColin Finck    {
551c2c66affSColin Finck       case WH_CBT:
552c2c66affSColin Finck          TRACE("WH_CBT: Code %d\n", Code);
553c2c66affSColin Finck          switch(Code)
554c2c66affSColin Finck          {
555c2c66affSColin Finck             case HCBT_CREATEWND:
556c2c66affSColin Finck                pWnd = UserGetWindowObject((HWND) wParam);
557c2c66affSColin Finck                if (!pWnd)
558c2c66affSColin Finck                {
559c2c66affSColin Finck                   ERR("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
560c2c66affSColin Finck                   goto Fault_Exit;
561c2c66affSColin Finck                }
562c2c66affSColin Finck                TRACE("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False");
563c2c66affSColin Finck               // Due to KsStudio.exe, just pass the callers original pointers
564c2c66affSColin Finck               // except class which point to kernel space if not an atom.
565c2c66affSColin Finck               // Found by, Olaf Siejka
566c2c66affSColin Finck                CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
567c2c66affSColin Finck                ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
568c2c66affSColin Finck                break;
569c2c66affSColin Finck 
570c2c66affSColin Finck             case HCBT_MOVESIZE:
571c2c66affSColin Finck                ArgumentLength += sizeof(RECTL);
572c2c66affSColin Finck                break;
573c2c66affSColin Finck             case HCBT_ACTIVATE:
574c2c66affSColin Finck                ArgumentLength += sizeof(CBTACTIVATESTRUCT);
575c2c66affSColin Finck                break;
576c2c66affSColin Finck             case HCBT_CLICKSKIPPED:
577c2c66affSColin Finck                ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
578c2c66affSColin Finck                break;
579c2c66affSColin Finck /*   ATM pass on */
580c2c66affSColin Finck             case HCBT_KEYSKIPPED:
581c2c66affSColin Finck             case HCBT_MINMAX:
582c2c66affSColin Finck             case HCBT_SETFOCUS:
583c2c66affSColin Finck             case HCBT_SYSCOMMAND:
584c2c66affSColin Finck /*   These types pass through. */
585c2c66affSColin Finck             case HCBT_DESTROYWND:
586c2c66affSColin Finck             case HCBT_QS:
587c2c66affSColin Finck                break;
588c2c66affSColin Finck             default:
589c2c66affSColin Finck                ERR("Trying to call unsupported CBT hook %d\n", Code);
590c2c66affSColin Finck                goto Fault_Exit;
591c2c66affSColin Finck          }
592c2c66affSColin Finck          break;
593c2c66affSColin Finck      case WH_KEYBOARD_LL:
594c2c66affSColin Finck          ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
595c2c66affSColin Finck          break;
596c2c66affSColin Finck      case WH_MOUSE_LL:
597c2c66affSColin Finck          ArgumentLength += sizeof(MSLLHOOKSTRUCT);
598c2c66affSColin Finck          break;
599c2c66affSColin Finck      case WH_MOUSE:
600c2c66affSColin Finck          ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
601c2c66affSColin Finck          break;
602c2c66affSColin Finck      case WH_CALLWNDPROC:
603c2c66affSColin Finck      {
604915a5764Sjimtabor          pCWP = (CWPSTRUCT*) lParam;
605915a5764Sjimtabor          ArgumentLength = sizeof(CWP_Struct);
606568b6d05SJames Tabor          if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE )
607568b6d05SJames Tabor          {
608568b6d05SJames Tabor              lParamSize = sizeof(CREATESTRUCTW);
609568b6d05SJames Tabor          }
610568b6d05SJames Tabor          else
611c2c66affSColin Finck              lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam);
612c2c66affSColin Finck          ArgumentLength += lParamSize;
613c2c66affSColin Finck          break;
614c2c66affSColin Finck       }
615c2c66affSColin Finck       case WH_CALLWNDPROCRET:
616c2c66affSColin Finck       {
617915a5764Sjimtabor          pCWPR = (CWPRETSTRUCT*) lParam;
618915a5764Sjimtabor          ArgumentLength = sizeof(CWPR_Struct);
619568b6d05SJames Tabor          if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE )
620568b6d05SJames Tabor          {
621568b6d05SJames Tabor              lParamSize = sizeof(CREATESTRUCTW);
622568b6d05SJames Tabor          }
623568b6d05SJames Tabor          else
624c2c66affSColin Finck              lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam);
625c2c66affSColin Finck          ArgumentLength += lParamSize;
626c2c66affSColin Finck          break;
627c2c66affSColin Finck       }
628c2c66affSColin Finck       case WH_MSGFILTER:
629c2c66affSColin Finck       case WH_SYSMSGFILTER:
630c2c66affSColin Finck       case WH_GETMESSAGE:
631c2c66affSColin Finck          ArgumentLength += sizeof(MSG);
632c2c66affSColin Finck          break;
633c2c66affSColin Finck       case WH_FOREGROUNDIDLE:
634c2c66affSColin Finck       case WH_KEYBOARD:
635c2c66affSColin Finck       case WH_SHELL:
636c2c66affSColin Finck          break;
637c2c66affSColin Finck       default:
638c2c66affSColin Finck          ERR("Trying to call unsupported window hook %d\n", HookId);
639c2c66affSColin Finck          goto Fault_Exit;
640c2c66affSColin Finck    }
641c2c66affSColin Finck 
642c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
643c2c66affSColin Finck    if (NULL == Argument)
644c2c66affSColin Finck    {
645568b6d05SJames Tabor       ERR("HookProc callback %d failed: out of memory %d\n",HookId,ArgumentLength);
646c2c66affSColin Finck       goto Fault_Exit;
647c2c66affSColin Finck    }
648c2c66affSColin Finck    Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
649c2c66affSColin Finck    Common->HookId = HookId;
650c2c66affSColin Finck    Common->Code = Code;
651c2c66affSColin Finck    Common->wParam = wParam;
652c2c66affSColin Finck    Common->lParam = lParam;
653c2c66affSColin Finck    Common->Proc = Proc;
654c2c66affSColin Finck    Common->Mod = Mod;
655c2c66affSColin Finck    Common->offPfn = offPfn;
656c2c66affSColin Finck    Common->Ansi = Ansi;
657915a5764Sjimtabor    Common->lParamSize = lParamSize;
658c2c66affSColin Finck    if (ModuleName->Buffer && ModuleName->Length)
659c2c66affSColin Finck    {
660c2c66affSColin Finck       RtlCopyMemory(&Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
661c2c66affSColin Finck       // If ModuleName->Buffer NULL while in destroy,
662c2c66affSColin Finck       //    this will make User32:Hook.c complain about not loading the library module.
663c2c66affSColin Finck       // Fix symptom for CORE-10549.
664c2c66affSColin Finck    }
665c2c66affSColin Finck    Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
666c2c66affSColin Finck 
667c2c66affSColin Finck    switch(HookId)
668c2c66affSColin Finck    {
669c2c66affSColin Finck       case WH_CBT:
670c2c66affSColin Finck          switch(Code)
671c2c66affSColin Finck          { // Need to remember this is not the first time through! Call Next Hook?
672c2c66affSColin Finck             case HCBT_CREATEWND:
673c2c66affSColin Finck                CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra;
674c2c66affSColin Finck                RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) );
675c2c66affSColin Finck                CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
676c2c66affSColin Finck                CbtCreatewndExtra->Cs.lpszClass   = CbtCreateWnd->lpcs->lpszClass;
677c2c66affSColin Finck                CbtCreatewndExtra->Cs.lpszName    = CbtCreateWnd->lpcs->lpszName;
678c2c66affSColin Finck                Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
679568b6d05SJames Tabor                //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, CbtCreateWnd->lpcs, CbtCreateWnd->lpcs->lpszName, CbtCreateWnd->lpcs->lpszClass);
680c2c66affSColin Finck                break;
681c2c66affSColin Finck             case HCBT_CLICKSKIPPED:
682c2c66affSColin Finck                RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
683c2c66affSColin Finck                Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
684c2c66affSColin Finck                break;
685c2c66affSColin Finck             case HCBT_MOVESIZE:
686c2c66affSColin Finck                RtlCopyMemory(Extra, (PVOID) lParam, sizeof(RECTL));
687c2c66affSColin Finck                Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
688c2c66affSColin Finck                break;
689c2c66affSColin Finck             case HCBT_ACTIVATE:
690c2c66affSColin Finck                RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CBTACTIVATESTRUCT));
691c2c66affSColin Finck                Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
692c2c66affSColin Finck                break;
693c2c66affSColin Finck          }
694c2c66affSColin Finck          break;
695c2c66affSColin Finck       case WH_KEYBOARD_LL:
696c2c66affSColin Finck          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT));
697c2c66affSColin Finck          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
698c2c66affSColin Finck          break;
699c2c66affSColin Finck       case WH_MOUSE_LL:
700c2c66affSColin Finck          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
701c2c66affSColin Finck          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
702c2c66affSColin Finck          break;
703c2c66affSColin Finck       case WH_MOUSE:
704c2c66affSColin Finck          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
705c2c66affSColin Finck          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
706c2c66affSColin Finck          break;
707c2c66affSColin Finck       case WH_CALLWNDPROC:
708915a5764Sjimtabor       {
709915a5764Sjimtabor          PCWP_Struct pcwps = (PCWP_Struct)Common;
710915a5764Sjimtabor          RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT));
711c2c66affSColin Finck          /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that
712c2c66affSColin Finck           * lParam could be a pointer to a buffer. This buffer must be exported
713c2c66affSColin Finck           * to user space too */
714c2c66affSColin Finck          if ( lParamSize )
715c2c66affSColin Finck          {
716915a5764Sjimtabor              RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize );
717915a5764Sjimtabor          }
718c2c66affSColin Finck       }
719c2c66affSColin Finck          break;
720c2c66affSColin Finck       case WH_CALLWNDPROCRET:
721915a5764Sjimtabor       {
722915a5764Sjimtabor          PCWPR_Struct pcwprs = (PCWPR_Struct)Common;
723915a5764Sjimtabor          RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT));
724c2c66affSColin Finck          if ( lParamSize )
725c2c66affSColin Finck          {
726915a5764Sjimtabor              RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize );
727915a5764Sjimtabor          }
728c2c66affSColin Finck       }
729c2c66affSColin Finck          break;
730c2c66affSColin Finck       case WH_MSGFILTER:
731c2c66affSColin Finck       case WH_SYSMSGFILTER:
732c2c66affSColin Finck       case WH_GETMESSAGE:
733c2c66affSColin Finck          pMsg = (PMSG)lParam;
734c2c66affSColin Finck          RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG));
735c2c66affSColin Finck          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
736c2c66affSColin Finck          break;
737c2c66affSColin Finck       case WH_FOREGROUNDIDLE:
738c2c66affSColin Finck       case WH_KEYBOARD:
739c2c66affSColin Finck       case WH_SHELL:
740c2c66affSColin Finck          break;
741c2c66affSColin Finck    }
742c2c66affSColin Finck 
743c2c66affSColin Finck    ResultPointer = NULL;
744c2c66affSColin Finck    ResultLength = ArgumentLength;
745c2c66affSColin Finck 
746c2c66affSColin Finck    UserLeaveCo();
747c2c66affSColin Finck 
748c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC,
749c2c66affSColin Finck                                Argument,
750c2c66affSColin Finck                                ArgumentLength,
751c2c66affSColin Finck                                &ResultPointer,
752c2c66affSColin Finck                                &ResultLength);
753c2c66affSColin Finck 
754c2c66affSColin Finck    UserEnterCo();
755c2c66affSColin Finck 
756c2c66affSColin Finck    if (!NT_SUCCESS(Status))
757c2c66affSColin Finck    {
758915a5764Sjimtabor       if ( iTheId != HookId ) // Hook ID can change.
759915a5764Sjimtabor       {
760568b6d05SJames Tabor           ERR("Failure to make Callback %d! Status 0x%x ArgumentLength %d\n",HookId,Status,ArgumentLength);
761915a5764Sjimtabor           iTheId = HookId;
762915a5764Sjimtabor       }
763c2c66affSColin Finck       goto Fault_Exit;
764c2c66affSColin Finck    }
765c2c66affSColin Finck 
766c2c66affSColin Finck    if (ResultPointer)
767c2c66affSColin Finck    {
768c2c66affSColin Finck       _SEH2_TRY
769c2c66affSColin Finck       {
770c2c66affSColin Finck          /* Simulate old behaviour: copy into our local buffer */
771c2c66affSColin Finck          RtlMoveMemory(Argument, ResultPointer, ArgumentLength);
772c2c66affSColin Finck          Result = Common->Result;
773c2c66affSColin Finck       }
774c2c66affSColin Finck       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
775c2c66affSColin Finck       {
776c2c66affSColin Finck          Result = 0;
777c2c66affSColin Finck          Hit = TRUE;
778c2c66affSColin Finck       }
779c2c66affSColin Finck       _SEH2_END;
780c2c66affSColin Finck    }
781c2c66affSColin Finck    else
782c2c66affSColin Finck    {
783c2c66affSColin Finck       ERR("ERROR: Hook %d Code %d ResultPointer 0x%p ResultLength %u\n",HookId,Code,ResultPointer,ResultLength);
784c2c66affSColin Finck    }
785c2c66affSColin Finck 
786c2c66affSColin Finck    /* Support write backs... SEH is in UserCallNextHookEx. */
787c2c66affSColin Finck    switch (HookId)
788c2c66affSColin Finck    {
789c2c66affSColin Finck       case WH_CBT:
790c2c66affSColin Finck       {
791c2c66affSColin Finck          switch (Code)
792c2c66affSColin Finck          {
793c2c66affSColin Finck             case HCBT_CREATEWND:
794c2c66affSColin Finck                if (CbtCreatewndExtra)
795c2c66affSColin Finck                {/*
796c2c66affSColin Finck                   The parameters could have been changed, include the coordinates
797c2c66affSColin Finck                   and dimensions of the window. We copy it back.
798c2c66affSColin Finck                  */
799c2c66affSColin Finck                   CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
800c2c66affSColin Finck                   CbtCreateWnd->lpcs->x  = CbtCreatewndExtra->Cs.x;
801c2c66affSColin Finck                   CbtCreateWnd->lpcs->y  = CbtCreatewndExtra->Cs.y;
802c2c66affSColin Finck                   CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
803c2c66affSColin Finck                   CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
804c2c66affSColin Finck                }
805c2c66affSColin Finck             break;
806c2c66affSColin Finck             case HCBT_MOVESIZE:
807c2c66affSColin Finck                if (Extra && lParam)
808c2c66affSColin Finck                {
809c2c66affSColin Finck                   RtlCopyMemory((PVOID) lParam, Extra, sizeof(RECTL));
810c2c66affSColin Finck                }
811c2c66affSColin Finck             break;
812c2c66affSColin Finck          }
813c2c66affSColin Finck       }
814c2c66affSColin Finck       // "The GetMsgProc hook procedure can examine or modify the message."
815c2c66affSColin Finck       case WH_GETMESSAGE:
816c2c66affSColin Finck          if (pMsg)
817c2c66affSColin Finck          {
818c2c66affSColin Finck             RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG));
819c2c66affSColin Finck          }
820c2c66affSColin Finck          break;
821c2c66affSColin Finck    }
822c2c66affSColin Finck 
823c2c66affSColin Finck Fault_Exit:
824c2c66affSColin Finck    if (Hit)
825c2c66affSColin Finck    {
826c2c66affSColin Finck       ERR("Exception CallHookProc HookId %d Code %d\n",HookId,Code);
827c2c66affSColin Finck    }
828c2c66affSColin Finck    if (Argument) IntCbFreeMemory(Argument);
829c2c66affSColin Finck 
830c2c66affSColin Finck    return Result;
831c2c66affSColin Finck }
832c2c66affSColin Finck 
833c2c66affSColin Finck //
834c2c66affSColin Finck // Events are notifications w/o results.
835c2c66affSColin Finck //
836c2c66affSColin Finck LRESULT
837c2c66affSColin Finck APIENTRY
co_IntCallEventProc(HWINEVENTHOOK hook,DWORD event,HWND hWnd,LONG idObject,LONG idChild,DWORD dwEventThread,DWORD dwmsEventTime,WINEVENTPROC Proc,INT Mod,ULONG_PTR offPfn)838c2c66affSColin Finck co_IntCallEventProc(HWINEVENTHOOK hook,
839c2c66affSColin Finck                            DWORD event,
840c2c66affSColin Finck                              HWND hWnd,
841c2c66affSColin Finck                          LONG idObject,
842c2c66affSColin Finck                           LONG idChild,
843c2c66affSColin Finck                    DWORD dwEventThread,
844c2c66affSColin Finck                    DWORD dwmsEventTime,
845c2c66affSColin Finck                      WINEVENTPROC Proc,
846c2c66affSColin Finck                                INT Mod,
847c2c66affSColin Finck                      ULONG_PTR offPfn)
848c2c66affSColin Finck {
849c2c66affSColin Finck    LRESULT Result = 0;
850c2c66affSColin Finck    NTSTATUS Status;
851c2c66affSColin Finck    PEVENTPROC_CALLBACK_ARGUMENTS Common;
852c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
853c2c66affSColin Finck    PVOID Argument, ResultPointer;
854c2c66affSColin Finck 
855c2c66affSColin Finck    ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS);
856c2c66affSColin Finck 
857c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
858c2c66affSColin Finck    if (NULL == Argument)
859c2c66affSColin Finck    {
860c2c66affSColin Finck       ERR("EventProc callback failed: out of memory\n");
861c2c66affSColin Finck       return 0;
862c2c66affSColin Finck    }
863c2c66affSColin Finck    Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument;
864c2c66affSColin Finck    Common->hook = hook;
865c2c66affSColin Finck    Common->event = event;
866c2c66affSColin Finck    Common->hwnd = hWnd;
867c2c66affSColin Finck    Common->idObject = idObject;
868c2c66affSColin Finck    Common->idChild = idChild;
869c2c66affSColin Finck    Common->dwEventThread = dwEventThread;
870c2c66affSColin Finck    Common->dwmsEventTime = dwmsEventTime;
871c2c66affSColin Finck    Common->Proc = Proc;
872c2c66affSColin Finck    Common->Mod = Mod;
873c2c66affSColin Finck    Common->offPfn = offPfn;
874c2c66affSColin Finck 
875c2c66affSColin Finck    ResultPointer = NULL;
876c2c66affSColin Finck    ResultLength = sizeof(LRESULT);
877c2c66affSColin Finck 
878c2c66affSColin Finck    UserLeaveCo();
879c2c66affSColin Finck 
880c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC,
881c2c66affSColin Finck                                Argument,
882c2c66affSColin Finck                                ArgumentLength,
883c2c66affSColin Finck                                &ResultPointer,
884c2c66affSColin Finck                                &ResultLength);
885c2c66affSColin Finck 
886c2c66affSColin Finck    UserEnterCo();
887c2c66affSColin Finck 
888c2c66affSColin Finck    IntCbFreeMemory(Argument);
889c2c66affSColin Finck 
890c2c66affSColin Finck    if (!NT_SUCCESS(Status))
891c2c66affSColin Finck    {
892c2c66affSColin Finck       return 0;
893c2c66affSColin Finck    }
894c2c66affSColin Finck 
895c2c66affSColin Finck    return Result;
896c2c66affSColin Finck }
897c2c66affSColin Finck 
898c2c66affSColin Finck //
899c2c66affSColin Finck // Callback Load Menu and results.
900c2c66affSColin Finck //
901c2c66affSColin Finck HMENU
902c2c66affSColin Finck APIENTRY
co_IntCallLoadMenu(HINSTANCE hModule,PUNICODE_STRING pMenuName)903c2c66affSColin Finck co_IntCallLoadMenu( HINSTANCE hModule,
904c2c66affSColin Finck                     PUNICODE_STRING pMenuName )
905c2c66affSColin Finck {
906c2c66affSColin Finck    LRESULT Result = 0;
907c2c66affSColin Finck    NTSTATUS Status;
908c2c66affSColin Finck    PLOADMENU_CALLBACK_ARGUMENTS Common;
909c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
910c2c66affSColin Finck    PVOID Argument, ResultPointer;
911c2c66affSColin Finck 
912c2c66affSColin Finck    ArgumentLength = sizeof(LOADMENU_CALLBACK_ARGUMENTS);
913c2c66affSColin Finck 
914c2c66affSColin Finck    ArgumentLength += pMenuName->Length + sizeof(WCHAR);
915c2c66affSColin Finck 
916c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
917c2c66affSColin Finck    if (NULL == Argument)
918c2c66affSColin Finck    {
919c2c66affSColin Finck       ERR("LoadMenu callback failed: out of memory\n");
920c2c66affSColin Finck       return 0;
921c2c66affSColin Finck    }
922c2c66affSColin Finck    Common = (PLOADMENU_CALLBACK_ARGUMENTS) Argument;
923c2c66affSColin Finck 
924c2c66affSColin Finck    Common->hModule = hModule;
925c2c66affSColin Finck    if (pMenuName->Length)
926c2c66affSColin Finck       RtlCopyMemory(&Common->MenuName, pMenuName->Buffer, pMenuName->Length);
927c2c66affSColin Finck    else
928c2c66affSColin Finck       Common->InterSource = pMenuName->Buffer;
929c2c66affSColin Finck 
930c2c66affSColin Finck    ResultPointer = NULL;
931c2c66affSColin Finck    ResultLength = sizeof(LRESULT);
932c2c66affSColin Finck 
933c2c66affSColin Finck    UserLeaveCo();
934c2c66affSColin Finck 
935c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_LOADMENU,
936c2c66affSColin Finck                                Argument,
937c2c66affSColin Finck                                ArgumentLength,
938c2c66affSColin Finck                                &ResultPointer,
939c2c66affSColin Finck                                &ResultLength);
940c2c66affSColin Finck 
941c2c66affSColin Finck    UserEnterCo();
942c2c66affSColin Finck 
943c2c66affSColin Finck    if (NT_SUCCESS(Status))
944c2c66affSColin Finck    {
945c2c66affSColin Finck       Result = *(LRESULT*)ResultPointer;
946c2c66affSColin Finck    }
947c2c66affSColin Finck    else
948c2c66affSColin Finck    {
949c2c66affSColin Finck       Result = 0;
950c2c66affSColin Finck    }
951c2c66affSColin Finck 
952c2c66affSColin Finck    IntCbFreeMemory(Argument);
953c2c66affSColin Finck 
954c2c66affSColin Finck    return (HMENU)Result;
955c2c66affSColin Finck }
956c2c66affSColin Finck 
957c2c66affSColin Finck NTSTATUS
958c2c66affSColin Finck APIENTRY
co_IntClientThreadSetup(VOID)959c2c66affSColin Finck co_IntClientThreadSetup(VOID)
960c2c66affSColin Finck {
961c2c66affSColin Finck    NTSTATUS Status;
962c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
963c2c66affSColin Finck    PVOID Argument, ResultPointer;
964c2c66affSColin Finck 
965c2c66affSColin Finck    /* Do not allow the desktop thread to do callback to user mode */
966c2c66affSColin Finck    ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
967c2c66affSColin Finck 
968c2c66affSColin Finck    ArgumentLength = ResultLength = 0;
969c2c66affSColin Finck    Argument = ResultPointer = NULL;
970c2c66affSColin Finck 
971c2c66affSColin Finck    UserLeaveCo();
972c2c66affSColin Finck 
973c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP,
974c2c66affSColin Finck                                Argument,
975c2c66affSColin Finck                                ArgumentLength,
976c2c66affSColin Finck                                &ResultPointer,
977c2c66affSColin Finck                                &ResultLength);
978c2c66affSColin Finck 
979c2c66affSColin Finck    UserEnterCo();
980c2c66affSColin Finck 
981c2c66affSColin Finck    return Status;
982c2c66affSColin Finck }
983c2c66affSColin Finck 
984c2c66affSColin Finck HANDLE FASTCALL
co_IntCopyImage(HANDLE hnd,UINT type,INT desiredx,INT desiredy,UINT flags)985c2c66affSColin Finck co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
986c2c66affSColin Finck {
987c2c66affSColin Finck    HANDLE Handle;
988c2c66affSColin Finck    NTSTATUS Status;
989c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
990c2c66affSColin Finck    PVOID Argument, ResultPointer;
991c2c66affSColin Finck    PCOPYIMAGE_CALLBACK_ARGUMENTS Common;
992c2c66affSColin Finck 
993c2c66affSColin Finck    ArgumentLength = ResultLength = 0;
994c2c66affSColin Finck    Argument = ResultPointer = NULL;
995c2c66affSColin Finck 
996c2c66affSColin Finck    ArgumentLength = sizeof(COPYIMAGE_CALLBACK_ARGUMENTS);
997c2c66affSColin Finck 
998c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
999c2c66affSColin Finck    if (NULL == Argument)
1000c2c66affSColin Finck    {
1001c2c66affSColin Finck       ERR("CopyImage callback failed: out of memory\n");
1002c2c66affSColin Finck       return 0;
1003c2c66affSColin Finck    }
1004c2c66affSColin Finck    Common = (PCOPYIMAGE_CALLBACK_ARGUMENTS) Argument;
1005c2c66affSColin Finck 
1006c2c66affSColin Finck    Common->hImage = hnd;
1007c2c66affSColin Finck    Common->uType = type;
1008c2c66affSColin Finck    Common->cxDesired = desiredx;
1009c2c66affSColin Finck    Common->cyDesired = desiredy;
1010c2c66affSColin Finck    Common->fuFlags = flags;
1011c2c66affSColin Finck 
1012c2c66affSColin Finck    UserLeaveCo();
1013c2c66affSColin Finck 
1014c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_COPYIMAGE,
1015c2c66affSColin Finck                                Argument,
1016c2c66affSColin Finck                                ArgumentLength,
1017c2c66affSColin Finck                                &ResultPointer,
1018c2c66affSColin Finck                                &ResultLength);
1019c2c66affSColin Finck 
1020c2c66affSColin Finck 
1021c2c66affSColin Finck    UserEnterCo();
1022c2c66affSColin Finck 
1023c2c66affSColin Finck    if (NT_SUCCESS(Status))
1024c2c66affSColin Finck    {
1025c2c66affSColin Finck       Handle = *(HANDLE*)ResultPointer;
1026c2c66affSColin Finck    }
1027c2c66affSColin Finck    else
1028c2c66affSColin Finck    {
1029c2c66affSColin Finck       ERR("CopyImage callback failed!\n");
1030c2c66affSColin Finck       Handle = NULL;
1031c2c66affSColin Finck    }
1032c2c66affSColin Finck 
1033c2c66affSColin Finck    IntCbFreeMemory(Argument);
1034c2c66affSColin Finck 
1035c2c66affSColin Finck    return Handle;
1036c2c66affSColin Finck }
1037c2c66affSColin Finck 
1038c2c66affSColin Finck BOOL
1039c2c66affSColin Finck APIENTRY
co_IntGetCharsetInfo(LCID Locale,PCHARSETINFO pCs)1040c2c66affSColin Finck co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs)
1041c2c66affSColin Finck {
1042c2c66affSColin Finck    NTSTATUS Status;
1043c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
1044c2c66affSColin Finck    PVOID Argument, ResultPointer;
1045c2c66affSColin Finck    PGET_CHARSET_INFO Common;
1046c2c66affSColin Finck 
1047c2c66affSColin Finck    ArgumentLength = sizeof(GET_CHARSET_INFO);
1048c2c66affSColin Finck 
1049c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
1050c2c66affSColin Finck    if (NULL == Argument)
1051c2c66affSColin Finck    {
1052c2c66affSColin Finck       ERR("GetCharsetInfo callback failed: out of memory\n");
1053c2c66affSColin Finck       return 0;
1054c2c66affSColin Finck    }
1055c2c66affSColin Finck    Common = (PGET_CHARSET_INFO) Argument;
1056c2c66affSColin Finck 
1057c2c66affSColin Finck    Common->Locale = Locale;
1058c2c66affSColin Finck 
1059c2c66affSColin Finck    ResultPointer = NULL;
1060c2c66affSColin Finck    ResultLength = ArgumentLength;
1061c2c66affSColin Finck 
1062c2c66affSColin Finck    UserLeaveCo();
1063c2c66affSColin Finck 
1064c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_GETCHARSETINFO,
1065c2c66affSColin Finck                                Argument,
1066c2c66affSColin Finck                                ArgumentLength,
1067c2c66affSColin Finck                                &ResultPointer,
1068c2c66affSColin Finck                                &ResultLength);
1069c2c66affSColin Finck 
1070c2c66affSColin Finck    if (NT_SUCCESS(Status))
1071c2c66affSColin Finck    {
1072c2c66affSColin Finck       _SEH2_TRY
1073c2c66affSColin Finck       {
1074c2c66affSColin Finck          /* Need to copy into our local buffer */
1075c2c66affSColin Finck          RtlMoveMemory(Argument, ResultPointer, ArgumentLength);
1076c2c66affSColin Finck       }
1077c2c66affSColin Finck       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1078c2c66affSColin Finck       {
1079c2c66affSColin Finck          ERR("Failed to copy result from user mode!\n");
1080c2c66affSColin Finck          Status = _SEH2_GetExceptionCode();
1081c2c66affSColin Finck       }
1082c2c66affSColin Finck       _SEH2_END;
1083c2c66affSColin Finck    }
1084c2c66affSColin Finck 
1085c2c66affSColin Finck    UserEnterCo();
1086c2c66affSColin Finck 
1087c2c66affSColin Finck    RtlCopyMemory(pCs, &Common->Cs, sizeof(CHARSETINFO));
1088c2c66affSColin Finck 
1089c2c66affSColin Finck    IntCbFreeMemory(Argument);
1090c2c66affSColin Finck 
1091c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1092c2c66affSColin Finck    {
1093c2c66affSColin Finck       ERR("GetCharsetInfo Failed!!\n");
1094c2c66affSColin Finck       return FALSE;
1095c2c66affSColin Finck    }
1096c2c66affSColin Finck 
1097c2c66affSColin Finck    return TRUE;
1098c2c66affSColin Finck }
1099c2c66affSColin Finck 
1100c2c66affSColin Finck BOOL FASTCALL
co_IntSetWndIcons(VOID)1101c2c66affSColin Finck co_IntSetWndIcons(VOID)
1102c2c66affSColin Finck {
1103c2c66affSColin Finck    NTSTATUS Status;
1104c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
1105c2c66affSColin Finck    PVOID Argument, ResultPointer;
1106c2c66affSColin Finck    PSETWNDICONS_CALLBACK_ARGUMENTS Common;
1107c2c66affSColin Finck 
1108c2c66affSColin Finck    ResultPointer = NULL;
1109c2c66affSColin Finck    ResultLength = ArgumentLength = sizeof(SETWNDICONS_CALLBACK_ARGUMENTS);
1110c2c66affSColin Finck 
1111c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
1112c2c66affSColin Finck    if (NULL == Argument)
1113c2c66affSColin Finck    {
1114c2c66affSColin Finck       ERR("Set Window Icons callback failed: out of memory\n");
1115c2c66affSColin Finck       return FALSE;
1116c2c66affSColin Finck    }
1117c2c66affSColin Finck    Common = (PSETWNDICONS_CALLBACK_ARGUMENTS) Argument;
1118c2c66affSColin Finck 
1119c2c66affSColin Finck    UserLeaveCo();
1120c2c66affSColin Finck 
1121c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_SETWNDICONS,
1122c2c66affSColin Finck                                Argument,
1123c2c66affSColin Finck                                ArgumentLength,
1124c2c66affSColin Finck                                &ResultPointer,
1125c2c66affSColin Finck                                &ResultLength);
1126c2c66affSColin Finck 
1127c2c66affSColin Finck 
1128c2c66affSColin Finck    UserEnterCo();
1129c2c66affSColin Finck 
1130c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1131c2c66affSColin Finck    {
1132c2c66affSColin Finck       ERR("Set Window Icons callback failed!\n");
1133c2c66affSColin Finck       IntCbFreeMemory(Argument);
1134c2c66affSColin Finck       return FALSE;
1135c2c66affSColin Finck    }
1136c2c66affSColin Finck 
1137c2c66affSColin Finck    RtlMoveMemory(Common, ResultPointer, ArgumentLength);
1138c2c66affSColin Finck    gpsi->hIconSmWindows = Common->hIconSmWindows;
1139c2c66affSColin Finck    gpsi->hIconWindows   = Common->hIconWindows;
1140c2c66affSColin Finck 
1141c2c66affSColin Finck    IntLoadSystenIcons(Common->hIconSample,   OIC_SAMPLE);
1142c2c66affSColin Finck    IntLoadSystenIcons(Common->hIconHand,     OIC_HAND);
1143c2c66affSColin Finck    IntLoadSystenIcons(Common->hIconQuestion, OIC_QUES);
1144c2c66affSColin Finck    IntLoadSystenIcons(Common->hIconBang,     OIC_BANG);
1145c2c66affSColin Finck    IntLoadSystenIcons(Common->hIconNote,     OIC_NOTE);
1146c2c66affSColin Finck    IntLoadSystenIcons(gpsi->hIconWindows,    OIC_WINLOGO);
1147c2c66affSColin Finck    IntLoadSystenIcons(gpsi->hIconSmWindows,  OIC_WINLOGO+1);
1148c2c66affSColin Finck 
1149c2c66affSColin Finck    ERR("hIconSmWindows %p hIconWindows %p \n",gpsi->hIconSmWindows,gpsi->hIconWindows);
1150c2c66affSColin Finck 
1151c2c66affSColin Finck    IntCbFreeMemory(Argument);
1152c2c66affSColin Finck 
1153c2c66affSColin Finck    return TRUE;
1154c2c66affSColin Finck }
1155c2c66affSColin Finck 
1156c2c66affSColin Finck VOID FASTCALL
co_IntDeliverUserAPC(VOID)1157c2c66affSColin Finck co_IntDeliverUserAPC(VOID)
1158c2c66affSColin Finck {
1159c2c66affSColin Finck    ULONG ResultLength;
1160c2c66affSColin Finck    PVOID ResultPointer;
1161c2c66affSColin Finck    NTSTATUS Status;
1162c2c66affSColin Finck    UserLeaveCo();
1163c2c66affSColin Finck 
1164c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_DELIVERUSERAPC,
1165c2c66affSColin Finck                                0,
1166c2c66affSColin Finck                                0,
1167c2c66affSColin Finck                                &ResultPointer,
1168c2c66affSColin Finck                                &ResultLength);
1169c2c66affSColin Finck 
1170c2c66affSColin Finck 
1171c2c66affSColin Finck    UserEnterCo();
1172c2c66affSColin Finck 
1173c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1174c2c66affSColin Finck    {
1175c2c66affSColin Finck       ERR("Delivering User APC callback failed!\n");
1176c2c66affSColin Finck    }
1177c2c66affSColin Finck }
1178c2c66affSColin Finck 
1179c2c66affSColin Finck VOID FASTCALL
co_IntSetupOBM(VOID)1180c2c66affSColin Finck co_IntSetupOBM(VOID)
1181c2c66affSColin Finck {
1182c2c66affSColin Finck    NTSTATUS Status;
1183c2c66affSColin Finck    ULONG ArgumentLength, ResultLength;
1184c2c66affSColin Finck    PVOID Argument, ResultPointer;
1185c2c66affSColin Finck    PSETOBM_CALLBACK_ARGUMENTS Common;
1186c2c66affSColin Finck 
1187c2c66affSColin Finck    ResultPointer = NULL;
1188c2c66affSColin Finck    ResultLength = ArgumentLength = sizeof(SETOBM_CALLBACK_ARGUMENTS);
1189c2c66affSColin Finck 
1190c2c66affSColin Finck    Argument = IntCbAllocateMemory(ArgumentLength);
1191c2c66affSColin Finck    if (NULL == Argument)
1192c2c66affSColin Finck    {
1193c2c66affSColin Finck       ERR("Set Window Icons callback failed: out of memory\n");
1194c2c66affSColin Finck       return;
1195c2c66affSColin Finck    }
1196c2c66affSColin Finck    Common = (PSETOBM_CALLBACK_ARGUMENTS) Argument;
1197c2c66affSColin Finck 
1198c2c66affSColin Finck    UserLeaveCo();
1199c2c66affSColin Finck 
1200c2c66affSColin Finck    Status = KeUserModeCallback(USER32_CALLBACK_SETOBM,
1201c2c66affSColin Finck                                Argument,
1202c2c66affSColin Finck                                ArgumentLength,
1203c2c66affSColin Finck                                &ResultPointer,
1204c2c66affSColin Finck                                &ResultLength);
1205c2c66affSColin Finck 
1206c2c66affSColin Finck 
1207c2c66affSColin Finck    UserEnterCo();
1208c2c66affSColin Finck 
1209c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1210c2c66affSColin Finck    {
1211c2c66affSColin Finck       ERR("Set Window Icons callback failed!\n");
1212c2c66affSColin Finck       IntCbFreeMemory(Argument);
1213c2c66affSColin Finck       return;
1214c2c66affSColin Finck    }
1215c2c66affSColin Finck 
1216c2c66affSColin Finck    RtlMoveMemory(Common, ResultPointer, ArgumentLength);
1217c2c66affSColin Finck    RtlCopyMemory(gpsi->oembmi, Common->oembmi, sizeof(gpsi->oembmi));
1218c2c66affSColin Finck 
1219c2c66affSColin Finck    IntCbFreeMemory(Argument);
1220c2c66affSColin Finck }
1221c2c66affSColin Finck 
12228c7705ebSjimtabor //
12238c7705ebSjimtabor //  Called from Kernel GDI sides, no UserLeave/EnterCo required.
12248c7705ebSjimtabor //
122540c42305SJames Tabor LRESULT
122640c42305SJames Tabor APIENTRY
co_UserCBClientPrinterThunk(PVOID pkt,INT InSize,PVOID pvOutData,INT OutSize)122740c42305SJames Tabor co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize )
122840c42305SJames Tabor {
122940c42305SJames Tabor    NTSTATUS Status;
1230915a5764Sjimtabor    PVOID ResultPointer;
123140c42305SJames Tabor 
123240c42305SJames Tabor    Status = KeUserModeCallback( USER32_CALLBACK_UMPD,
12338c7705ebSjimtabor                                 pkt,
12348c7705ebSjimtabor                                 InSize,
1235915a5764Sjimtabor                                &ResultPointer,
12368c7705ebSjimtabor                                (PULONG)&OutSize );
123740c42305SJames Tabor 
123840c42305SJames Tabor 
123940c42305SJames Tabor    if (!NT_SUCCESS(Status))
124040c42305SJames Tabor    {
124140c42305SJames Tabor       ERR("User UMPD callback failed!\n");
12428c7705ebSjimtabor       return 1;
124340c42305SJames Tabor    }
124440c42305SJames Tabor 
1245915a5764Sjimtabor    if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize );
1246915a5764Sjimtabor 
124740c42305SJames Tabor    return 0;
124840c42305SJames Tabor }
1249c2c66affSColin Finck 
12505df5ef2bSKatayama Hirofumi MZ // Win: ClientImmProcessKey
1251b5c9d532SKatayama Hirofumi MZ DWORD
1252b5c9d532SKatayama Hirofumi MZ APIENTRY
co_IntImmProcessKey(HWND hWnd,HKL hKL,UINT vKey,LPARAM lParam,DWORD dwHotKeyID)1253b5c9d532SKatayama Hirofumi MZ co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID)
1254b5c9d532SKatayama Hirofumi MZ {
1255b5c9d532SKatayama Hirofumi MZ     DWORD ret = 0;
1256b5c9d532SKatayama Hirofumi MZ     NTSTATUS Status;
1257b5c9d532SKatayama Hirofumi MZ     ULONG ResultLength = sizeof(DWORD);
1258b5c9d532SKatayama Hirofumi MZ     PVOID ResultPointer = NULL;
1259b5c9d532SKatayama Hirofumi MZ     IMMPROCESSKEY_CALLBACK_ARGUMENTS Common = { hWnd, hKL, vKey, lParam, dwHotKeyID };
1260b5c9d532SKatayama Hirofumi MZ 
1261b5c9d532SKatayama Hirofumi MZ     UserLeaveCo();
1262b5c9d532SKatayama Hirofumi MZ     Status = KeUserModeCallback(USER32_CALLBACK_IMMPROCESSKEY,
1263b5c9d532SKatayama Hirofumi MZ                                 &Common,
1264b5c9d532SKatayama Hirofumi MZ                                 sizeof(Common),
1265b5c9d532SKatayama Hirofumi MZ                                 &ResultPointer,
1266b5c9d532SKatayama Hirofumi MZ                                 &ResultLength);
1267b5c9d532SKatayama Hirofumi MZ     UserEnterCo();
1268b5c9d532SKatayama Hirofumi MZ 
1269b5c9d532SKatayama Hirofumi MZ     if (NT_SUCCESS(Status))
1270b5c9d532SKatayama Hirofumi MZ         ret = *(LPDWORD)ResultPointer;
1271b5c9d532SKatayama Hirofumi MZ 
1272b5c9d532SKatayama Hirofumi MZ     return ret;
1273b5c9d532SKatayama Hirofumi MZ }
1274b5c9d532SKatayama Hirofumi MZ 
1275*85e292d5SKatayama Hirofumi MZ /* Win: ClientImmLoadLayout */
1276*85e292d5SKatayama Hirofumi MZ BOOL
1277*85e292d5SKatayama Hirofumi MZ APIENTRY
co_ClientImmLoadLayout(_In_ HKL hKL,_Inout_ PIMEINFOEX pImeInfoEx)1278*85e292d5SKatayama Hirofumi MZ co_ClientImmLoadLayout(
1279*85e292d5SKatayama Hirofumi MZ     _In_ HKL hKL,
1280*85e292d5SKatayama Hirofumi MZ     _Inout_ PIMEINFOEX pImeInfoEx)
1281*85e292d5SKatayama Hirofumi MZ {
1282*85e292d5SKatayama Hirofumi MZ     BOOL ret;
1283*85e292d5SKatayama Hirofumi MZ     NTSTATUS Status;
1284*85e292d5SKatayama Hirofumi MZ     IMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = { hKL };
1285*85e292d5SKatayama Hirofumi MZ     ULONG ResultLength = sizeof(IMMLOADLAYOUT_CALLBACK_OUTPUT);
1286*85e292d5SKatayama Hirofumi MZ     PIMMLOADLAYOUT_CALLBACK_OUTPUT ResultPointer = NULL;
1287*85e292d5SKatayama Hirofumi MZ 
1288*85e292d5SKatayama Hirofumi MZ     RtlZeroMemory(pImeInfoEx, sizeof(IMEINFOEX));
1289*85e292d5SKatayama Hirofumi MZ 
1290*85e292d5SKatayama Hirofumi MZ     UserLeaveCo();
1291*85e292d5SKatayama Hirofumi MZ     Status = KeUserModeCallback(USER32_CALLBACK_IMMLOADLAYOUT,
1292*85e292d5SKatayama Hirofumi MZ                                 &Common,
1293*85e292d5SKatayama Hirofumi MZ                                 sizeof(Common),
1294*85e292d5SKatayama Hirofumi MZ                                 (PVOID*)&ResultPointer,
1295*85e292d5SKatayama Hirofumi MZ                                 &ResultLength);
1296*85e292d5SKatayama Hirofumi MZ     UserEnterCo();
1297*85e292d5SKatayama Hirofumi MZ 
1298*85e292d5SKatayama Hirofumi MZ     if (!NT_SUCCESS(Status) || !ResultPointer ||
1299*85e292d5SKatayama Hirofumi MZ         ResultLength != sizeof(IMMLOADLAYOUT_CALLBACK_OUTPUT))
1300*85e292d5SKatayama Hirofumi MZ     {
1301*85e292d5SKatayama Hirofumi MZ         ERR("0x%lX, %p, %lu\n", Status, ResultPointer, ResultLength);
1302*85e292d5SKatayama Hirofumi MZ         return FALSE;
1303*85e292d5SKatayama Hirofumi MZ     }
1304*85e292d5SKatayama Hirofumi MZ 
1305*85e292d5SKatayama Hirofumi MZ     _SEH2_TRY
1306*85e292d5SKatayama Hirofumi MZ     {
1307*85e292d5SKatayama Hirofumi MZ         ProbeForRead(ResultPointer, ResultLength, 1);
1308*85e292d5SKatayama Hirofumi MZ         ret = ResultPointer->ret;
1309*85e292d5SKatayama Hirofumi MZ         if (ret)
1310*85e292d5SKatayama Hirofumi MZ             RtlCopyMemory(pImeInfoEx, &ResultPointer->iiex, sizeof(IMEINFOEX));
1311*85e292d5SKatayama Hirofumi MZ     }
1312*85e292d5SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1313*85e292d5SKatayama Hirofumi MZ     {
1314*85e292d5SKatayama Hirofumi MZ         ret = FALSE;
1315*85e292d5SKatayama Hirofumi MZ     }
1316*85e292d5SKatayama Hirofumi MZ     _SEH2_END;
1317*85e292d5SKatayama Hirofumi MZ 
1318*85e292d5SKatayama Hirofumi MZ     return ret;
1319*85e292d5SKatayama Hirofumi MZ }
1320*85e292d5SKatayama Hirofumi MZ 
1321c2c66affSColin Finck /* EOF */
1322