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