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