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