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