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