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