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