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