[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / 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: subsystems/win32/win32k/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 /* CALLBACK MEMORY MANAGEMENT ************************************************/
17
18 typedef struct _INT_CALLBACK_HEADER
19 {
20 /* List entry in the THREADINFO structure */
21 LIST_ENTRY ListEntry;
22 }
23 INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER;
24
25 PVOID FASTCALL
26 IntCbAllocateMemory(ULONG Size)
27 {
28 PINT_CALLBACK_HEADER Mem;
29 PTHREADINFO W32Thread;
30
31 if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER),
32 USERTAG_CALLBACK)))
33 {
34 return NULL;
35 }
36
37 W32Thread = PsGetCurrentThreadWin32Thread();
38 ASSERT(W32Thread);
39
40 /* Insert the callback memory into the thread's callback list */
41
42 InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry);
43
44 return (Mem + 1);
45 }
46
47 VOID FASTCALL
48 IntCbFreeMemory(PVOID Data)
49 {
50 PINT_CALLBACK_HEADER Mem;
51 PTHREADINFO W32Thread;
52
53 ASSERT(Data);
54
55 Mem = ((PINT_CALLBACK_HEADER)Data - 1);
56
57 W32Thread = PsGetCurrentThreadWin32Thread();
58 ASSERT(W32Thread);
59
60 /* Remove the memory block from the thread's callback list */
61 RemoveEntryList(&Mem->ListEntry);
62
63 /* Free memory */
64 ExFreePoolWithTag(Mem, USERTAG_CALLBACK);
65 }
66
67 VOID FASTCALL
68 IntCleanupThreadCallbacks(PTHREADINFO W32Thread)
69 {
70 PLIST_ENTRY CurrentEntry;
71 PINT_CALLBACK_HEADER Mem;
72
73 while (!IsListEmpty(&W32Thread->W32CallbackListHead))
74 {
75 CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead);
76 Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER,
77 ListEntry);
78
79 /* Free memory */
80 ExFreePool(Mem);
81 }
82 }
83
84 //
85 // Pass the Current Window handle and pointer to the Client Callback.
86 // This will help user space programs speed up read access with the window object.
87 //
88 static VOID
89 IntSetTebWndCallback (HWND * hWnd, PWND * pWnd, PVOID * pActCtx)
90 {
91 HWND hWndS = *hWnd;
92 PWND Window = UserGetWindowObject(*hWnd);
93 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
94
95 *hWnd = ClientInfo->CallbackWnd.hWnd;
96 *pWnd = ClientInfo->CallbackWnd.pWnd;
97 *pActCtx = ClientInfo->CallbackWnd.pActCtx;
98
99 ClientInfo->CallbackWnd.hWnd = hWndS;
100 ClientInfo->CallbackWnd.pWnd = DesktopHeapAddressToUser(Window);
101 ClientInfo->CallbackWnd.pActCtx = Window->pActCtx;
102 }
103
104 static VOID
105 IntRestoreTebWndCallback (HWND hWnd, PWND pWnd, PVOID pActCtx)
106 {
107 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
108
109 ClientInfo->CallbackWnd.hWnd = hWnd;
110 ClientInfo->CallbackWnd.pWnd = pWnd;
111 ClientInfo->CallbackWnd.pActCtx = pActCtx;
112 }
113
114 /* FUNCTIONS *****************************************************************/
115
116 /* Calls ClientLoadLibrary in user32 */
117 HMODULE
118 co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
119 PUNICODE_STRING pstrInitFunc,
120 BOOL Unload,
121 BOOL ApiHook)
122 {
123 PVOID ResultPointer;
124 ULONG ResultLength;
125 ULONG ArgumentLength;
126 PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments;
127 NTSTATUS Status;
128 HMODULE Result;
129 ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0;
130
131 TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook);
132
133 /* Calculate the size of the argument */
134 ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS);
135 if(pstrLibName)
136 {
137 pLibNameBuffer = ArgumentLength;
138 ArgumentLength += pstrLibName->Length + sizeof(WCHAR);
139 }
140 if(pstrInitFunc)
141 {
142 pInitFuncBuffer = ArgumentLength;
143 ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR);
144 }
145
146 /* Allocate the argument */
147 pArguments = IntCbAllocateMemory(ArgumentLength);
148 if(pArguments == NULL)
149 {
150 return FALSE;
151 }
152
153 /* Fill the argument */
154 pArguments->Unload = Unload;
155 pArguments->ApiHook = ApiHook;
156 if(pstrLibName)
157 {
158 /* Copy the string to the callback memory */
159 pLibNameBuffer += (ULONG_PTR)pArguments;
160 pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer;
161 pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR);
162 RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName);
163
164 /* Fix argument pointer to be relative to the argument */
165 pLibNameBuffer -= (ULONG_PTR)pArguments;
166 pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer);
167 }
168 else
169 {
170 RtlZeroMemory(&pArguments->strLibraryName, sizeof(UNICODE_STRING));
171 }
172
173 if(pstrInitFunc)
174 {
175 /* Copy the strings to the callback memory */
176 pInitFuncBuffer += (ULONG_PTR)pArguments;
177 pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer;
178 pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR);
179 RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc);
180
181 /* Fix argument pointers to be relative to the argument */
182 pInitFuncBuffer -= (ULONG_PTR)pArguments;
183 pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer);
184 }
185 else
186 {
187 RtlZeroMemory(&pArguments->strInitFuncName, sizeof(UNICODE_STRING));
188 }
189
190 /* Do the callback */
191 UserLeaveCo();
192
193 Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY,
194 pArguments,
195 ArgumentLength,
196 &ResultPointer,
197 &ResultLength);
198
199 UserEnterCo();
200
201 /* Free the argument */
202 IntCbFreeMemory(pArguments);
203
204 if(!NT_SUCCESS(Status))
205 {
206 return FALSE;
207 }
208
209 _SEH2_TRY
210 {
211 ProbeForRead(ResultPointer, sizeof(HMODULE), 1);
212 /* Simulate old behaviour: copy into our local buffer */
213 Result = *(HMODULE*)ResultPointer;
214 }
215 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
216 {
217 Result = 0;
218 }
219 _SEH2_END;
220
221 return Result;
222 }
223
224 VOID APIENTRY
225 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
226 HWND hWnd,
227 UINT Msg,
228 ULONG_PTR CompletionCallbackContext,
229 LRESULT Result)
230 {
231 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments;
232 PVOID ResultPointer, pActCtx;
233 PWND pWnd;
234 ULONG ResultLength;
235 NTSTATUS Status;
236
237 Arguments.Callback = CompletionCallback;
238 Arguments.Wnd = hWnd;
239 Arguments.Msg = Msg;
240 Arguments.Context = CompletionCallbackContext;
241 Arguments.Result = Result;
242
243 IntSetTebWndCallback (&hWnd, &pWnd, &pActCtx);
244
245 UserLeaveCo();
246
247 Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC,
248 &Arguments,
249 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS),
250 &ResultPointer,
251 &ResultLength);
252
253 UserEnterCo();
254
255 IntRestoreTebWndCallback (hWnd, pWnd, pActCtx);
256
257 if (!NT_SUCCESS(Status))
258 {
259 return;
260 }
261 return;
262 }
263
264 LRESULT APIENTRY
265 co_IntCallWindowProc(WNDPROC Proc,
266 BOOLEAN IsAnsiProc,
267 HWND Wnd,
268 UINT Message,
269 WPARAM wParam,
270 LPARAM lParam,
271 INT lParamBufferSize)
272 {
273 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments;
274 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments;
275 NTSTATUS Status;
276 PVOID ResultPointer, pActCtx;
277 PWND pWnd;
278 ULONG ResultLength;
279 ULONG ArgumentLength;
280 LRESULT Result;
281
282 if (0 < lParamBufferSize)
283 {
284 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize;
285 Arguments = IntCbAllocateMemory(ArgumentLength);
286 if (NULL == Arguments)
287 {
288 ERR("Unable to allocate buffer for window proc callback\n");
289 return -1;
290 }
291 RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
292 (PVOID) lParam, lParamBufferSize);
293 }
294 else
295 {
296 Arguments = &StackArguments;
297 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS);
298 }
299 Arguments->Proc = Proc;
300 Arguments->IsAnsiProc = IsAnsiProc;
301 Arguments->Wnd = Wnd;
302 Arguments->Msg = Message;
303 Arguments->wParam = wParam;
304 Arguments->lParam = lParam;
305 Arguments->lParamBufferSize = lParamBufferSize;
306 ResultPointer = NULL;
307 ResultLength = ArgumentLength;
308
309 IntSetTebWndCallback (&Wnd, &pWnd, &pActCtx);
310
311 UserLeaveCo();
312
313 Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC,
314 Arguments,
315 ArgumentLength,
316 &ResultPointer,
317 &ResultLength);
318
319 _SEH2_TRY
320 {
321 /* Simulate old behaviour: copy into our local buffer */
322 RtlMoveMemory(Arguments, ResultPointer, ArgumentLength);
323 }
324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
325 {
326 ERR("Failed to copy result from user mode!\n");
327 Status = _SEH2_GetExceptionCode();
328 }
329 _SEH2_END;
330
331 UserEnterCo();
332
333 IntRestoreTebWndCallback (Wnd, pWnd, pActCtx);
334
335 if (!NT_SUCCESS(Status))
336 {
337 ERR("Call to user mode failed!\n");
338 if (0 < lParamBufferSize)
339 {
340 IntCbFreeMemory(Arguments);
341 }
342 return -1;
343 }
344 Result = Arguments->Result;
345
346 if (0 < lParamBufferSize)
347 {
348 RtlMoveMemory((PVOID) lParam,
349 (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
350 lParamBufferSize);
351 IntCbFreeMemory(Arguments);
352 }
353
354 return Result;
355 }
356
357 HMENU APIENTRY
358 co_IntLoadSysMenuTemplate()
359 {
360 LRESULT Result = 0;
361 NTSTATUS Status;
362 PVOID ResultPointer;
363 ULONG ResultLength;
364
365 ResultPointer = NULL;
366 ResultLength = sizeof(LRESULT);
367
368 UserLeaveCo();
369
370 Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE,
371 NULL,
372 0,
373 &ResultPointer,
374 &ResultLength);
375 if (NT_SUCCESS(Status))
376 {
377 /* Simulate old behaviour: copy into our local buffer */
378 _SEH2_TRY
379 {
380 ProbeForRead(ResultPointer, sizeof(LRESULT), 1);
381 Result = *(LRESULT*)ResultPointer;
382 }
383 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
384 {
385 Result = 0;
386 }
387 _SEH2_END
388 }
389
390 UserEnterCo();
391
392 return (HMENU)Result;
393 }
394
395 BOOL APIENTRY
396 co_IntLoadDefaultCursors(VOID)
397 {
398 NTSTATUS Status;
399 PVOID ResultPointer;
400 ULONG ResultLength;
401 BOOL DefaultCursor = TRUE;
402
403 ResultPointer = NULL;
404 ResultLength = sizeof(LRESULT);
405
406 UserLeaveCo();
407
408 Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS,
409 &DefaultCursor,
410 sizeof(BOOL),
411 &ResultPointer,
412 &ResultLength);
413
414 UserEnterCo();
415
416 if (!NT_SUCCESS(Status))
417 {
418 return FALSE;
419 }
420 return TRUE;
421 }
422
423 LRESULT APIENTRY
424 co_IntCallHookProc(INT HookId,
425 INT Code,
426 WPARAM wParam,
427 LPARAM lParam,
428 HOOKPROC Proc,
429 BOOLEAN Ansi,
430 PUNICODE_STRING ModuleName)
431 {
432 ULONG ArgumentLength;
433 PVOID Argument = NULL;
434 LRESULT Result = 0;
435 NTSTATUS Status;
436 PVOID ResultPointer;
437 ULONG ResultLength;
438 PHOOKPROC_CALLBACK_ARGUMENTS Common;
439 CBT_CREATEWNDW *CbtCreateWnd = NULL;
440 PCHAR Extra;
441 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
442 PTHREADINFO pti;
443 PWND pWnd;
444 PMSG pMsg = NULL;
445 BOOL Hit = FALSE;
446
447 ASSERT(Proc);
448
449 pti = PsGetCurrentThreadWin32Thread();
450 if (pti->TIF_flags & TIF_INCLEANUP)
451 {
452 ERR("Thread is in cleanup and trying to call hook %d\n", Code);
453 return 0;
454 }
455
456 ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
457
458 switch(HookId)
459 {
460 case WH_CBT:
461 TRACE("WH_CBT: Code %d\n", Code);
462 switch(Code)
463 {
464 case HCBT_CREATEWND:
465 pWnd = UserGetWindowObject((HWND) wParam);
466 if (!pWnd)
467 {
468 ERR("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
469 goto Fault_Exit;
470 }
471 TRACE("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False");
472 // Due to KsStudio.exe, just pass the callers original pointers
473 // except class which point to kernel space if not an atom.
474 // Found by, Olaf Siejka
475 CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
476 ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
477 break;
478
479 case HCBT_MOVESIZE:
480 ArgumentLength += sizeof(RECTL);
481 break;
482 case HCBT_ACTIVATE:
483 ArgumentLength += sizeof(CBTACTIVATESTRUCT);
484 break;
485 case HCBT_CLICKSKIPPED:
486 ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
487 break;
488 /* ATM pass on */
489 case HCBT_KEYSKIPPED:
490 case HCBT_MINMAX:
491 case HCBT_SETFOCUS:
492 case HCBT_SYSCOMMAND:
493 /* These types pass through. */
494 case HCBT_DESTROYWND:
495 case HCBT_QS:
496 break;
497 default:
498 ERR("Trying to call unsupported CBT hook %d\n", Code);
499 goto Fault_Exit;
500 }
501 break;
502 case WH_KEYBOARD_LL:
503 ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
504 break;
505 case WH_MOUSE_LL:
506 ArgumentLength += sizeof(MSLLHOOKSTRUCT);
507 break;
508 case WH_MOUSE:
509 ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
510 break;
511 case WH_CALLWNDPROC:
512 ArgumentLength += sizeof(CWPSTRUCT);
513 break;
514 case WH_CALLWNDPROCRET:
515 ArgumentLength += sizeof(CWPRETSTRUCT);
516 break;
517 case WH_MSGFILTER:
518 case WH_SYSMSGFILTER:
519 case WH_GETMESSAGE:
520 ArgumentLength += sizeof(MSG);
521 break;
522 case WH_FOREGROUNDIDLE:
523 case WH_KEYBOARD:
524 case WH_SHELL:
525 break;
526 default:
527 ERR("Trying to call unsupported window hook %d\n", HookId);
528 goto Fault_Exit;
529 }
530
531 Argument = IntCbAllocateMemory(ArgumentLength);
532 if (NULL == Argument)
533 {
534 ERR("HookProc callback failed: out of memory\n");
535 goto Fault_Exit;
536 }
537 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
538 Common->HookId = HookId;
539 Common->Code = Code;
540 Common->wParam = wParam;
541 Common->lParam = lParam;
542 Common->Proc = Proc;
543 Common->Ansi = Ansi;
544 Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
545
546 switch(HookId)
547 {
548 case WH_CBT:
549 switch(Code)
550 { // Need to remember this is not the first time through! Call Next Hook?
551 case HCBT_CREATEWND:
552 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra;
553 RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) );
554 CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
555 CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass;
556 CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName;
557 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
558 break;
559 case HCBT_CLICKSKIPPED:
560 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
561 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
562 break;
563 case HCBT_MOVESIZE:
564 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(RECTL));
565 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
566 break;
567 case HCBT_ACTIVATE:
568 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CBTACTIVATESTRUCT));
569 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
570 break;
571 }
572 break;
573 case WH_KEYBOARD_LL:
574 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT));
575 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
576 break;
577 case WH_MOUSE_LL:
578 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
579 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
580 break;
581 case WH_MOUSE:
582 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
583 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
584 break;
585 case WH_CALLWNDPROC:
586 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
587 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
588 break;
589 case WH_CALLWNDPROCRET:
590 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
591 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
592 break;
593 case WH_MSGFILTER:
594 case WH_SYSMSGFILTER:
595 case WH_GETMESSAGE:
596 pMsg = (PMSG)lParam;
597 RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG));
598 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
599 break;
600 case WH_FOREGROUNDIDLE:
601 case WH_KEYBOARD:
602 case WH_SHELL:
603 break;
604 }
605
606 ResultPointer = NULL;
607 ResultLength = sizeof(LRESULT);
608
609 UserLeaveCo();
610
611 Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC,
612 Argument,
613 ArgumentLength,
614 &ResultPointer,
615 &ResultLength);
616
617 UserEnterCo();
618
619 if (ResultPointer)
620 {
621 _SEH2_TRY
622 {
623 ProbeForRead(ResultPointer, sizeof(LRESULT), 1);
624 /* Simulate old behaviour: copy into our local buffer */
625 Result = *(LRESULT*)ResultPointer;
626 }
627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
628 {
629 Result = 0;
630 Hit = TRUE;
631 }
632 _SEH2_END;
633 }
634 else
635 {
636 ERR("ERROR: Hook ResultPointer 0x%x ResultLength %d\n",ResultPointer,ResultLength);
637 }
638
639 if (!NT_SUCCESS(Status))
640 {
641 ERR("Failure to make Callback! Status 0x%x",Status);
642 goto Fault_Exit;
643 }
644 /* Support write backs... SEH is in UserCallNextHookEx. */
645 switch (HookId)
646 {
647 case WH_CBT:
648 if (Code == HCBT_CREATEWND)
649 {
650 if (CbtCreatewndExtra)
651 {/*
652 The parameters could have been changed, include the coordinates
653 and dimensions of the window. We copy it back.
654 */
655 CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
656 CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x;
657 CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y;
658 CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
659 CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
660 }
661 }
662 break;
663 // "The GetMsgProc hook procedure can examine or modify the message."
664 case WH_GETMESSAGE:
665 if (pMsg)
666 {
667 RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG));
668 }
669 break;
670 }
671
672 Fault_Exit:
673 if (Hit)
674 {
675 ERR("Exception CallHookProc HookId %d Code %d\n",HookId,Code);
676 }
677 if (Argument) IntCbFreeMemory(Argument);
678
679 return Result;
680 }
681
682 //
683 // Events are notifications w/o results.
684 //
685 LRESULT
686 APIENTRY
687 co_IntCallEventProc(HWINEVENTHOOK hook,
688 DWORD event,
689 HWND hWnd,
690 LONG idObject,
691 LONG idChild,
692 DWORD dwEventThread,
693 DWORD dwmsEventTime,
694 WINEVENTPROC Proc)
695 {
696 LRESULT Result = 0;
697 NTSTATUS Status;
698 PEVENTPROC_CALLBACK_ARGUMENTS Common;
699 ULONG ArgumentLength, ResultLength;
700 PVOID Argument, ResultPointer;
701
702 ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS);
703
704 Argument = IntCbAllocateMemory(ArgumentLength);
705 if (NULL == Argument)
706 {
707 ERR("EventProc callback failed: out of memory\n");
708 return 0;
709 }
710 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument;
711 Common->hook = hook;
712 Common->event = event;
713 Common->hwnd = hWnd;
714 Common->idObject = idObject;
715 Common->idChild = idChild;
716 Common->dwEventThread = dwEventThread;
717 Common->dwmsEventTime = dwmsEventTime;
718 Common->Proc = Proc;
719
720 ResultPointer = NULL;
721 ResultLength = sizeof(LRESULT);
722
723 UserLeaveCo();
724
725 Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC,
726 Argument,
727 ArgumentLength,
728 &ResultPointer,
729 &ResultLength);
730
731 UserEnterCo();
732
733 IntCbFreeMemory(Argument);
734
735 if (!NT_SUCCESS(Status))
736 {
737 return 0;
738 }
739
740 return Result;
741 }
742
743 //
744 // Callback Load Menu and results.
745 //
746 HMENU
747 APIENTRY
748 co_IntCallLoadMenu( HINSTANCE hModule,
749 PUNICODE_STRING pMenuName )
750 {
751 LRESULT Result = 0;
752 NTSTATUS Status;
753 PLOADMENU_CALLBACK_ARGUMENTS Common;
754 ULONG ArgumentLength, ResultLength;
755 PVOID Argument, ResultPointer;
756
757 ArgumentLength = sizeof(LOADMENU_CALLBACK_ARGUMENTS);
758
759 ArgumentLength += pMenuName->Length + sizeof(WCHAR);
760
761 Argument = IntCbAllocateMemory(ArgumentLength);
762 if (NULL == Argument)
763 {
764 ERR("LoadMenu callback failed: out of memory\n");
765 return 0;
766 }
767 Common = (PLOADMENU_CALLBACK_ARGUMENTS) Argument;
768
769 // Help Intersource check and MenuName is now 4 bytes + so zero it.
770 RtlZeroMemory(Common, ArgumentLength);
771
772 Common->hModule = hModule;
773 if (pMenuName->Length)
774 RtlCopyMemory(&Common->MenuName, pMenuName->Buffer, pMenuName->Length);
775 else
776 RtlCopyMemory(&Common->MenuName, &pMenuName->Buffer, sizeof(WCHAR));
777
778 ResultPointer = NULL;
779 ResultLength = sizeof(LRESULT);
780
781 UserLeaveCo();
782
783 Status = KeUserModeCallback(USER32_CALLBACK_LOADMENU,
784 Argument,
785 ArgumentLength,
786 &ResultPointer,
787 &ResultLength);
788
789 UserEnterCo();
790
791 Result = *(LRESULT*)ResultPointer;
792
793 IntCbFreeMemory(Argument);
794
795 if (!NT_SUCCESS(Status))
796 {
797 return 0;
798 }
799
800 return (HMENU)Result;
801 }
802
803 NTSTATUS
804 APIENTRY
805 co_IntClientThreadSetup(VOID)
806 {
807 NTSTATUS Status;
808 ULONG ArgumentLength, ResultLength;
809 PVOID Argument, ResultPointer;
810
811 ArgumentLength = ResultLength = 0;
812 Argument = ResultPointer = NULL;
813
814 UserLeaveCo();
815
816 Status = KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP,
817 Argument,
818 ArgumentLength,
819 &ResultPointer,
820 &ResultLength);
821
822 UserEnterCo();
823
824 return Status;
825 }
826
827 /* EOF */