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