Merge from amd64-branch:
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / callback.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window classes
5 * FILE: subsys/win32k/ntuser/wndproc.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
8 * REVISION HISTORY:
9 * 06-06-2001 CSH Created
10 * NOTES: Please use the Callback Memory Management functions for
11 * callbacks to make sure, the memory is freed on thread
12 * termination!
13 */
14
15 /* INCLUDES ******************************************************************/
16
17 #include <w32k.h>
18
19 #define NDEBUG
20 #include <debug.h>
21
22 /* CALLBACK MEMORY MANAGEMENT ************************************************/
23
24 typedef struct _INT_CALLBACK_HEADER
25 {
26 /* list entry in the THREADINFO structure */
27 LIST_ENTRY ListEntry;
28 }
29 INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER;
30
31 PVOID FASTCALL
32 IntCbAllocateMemory(ULONG Size)
33 {
34 PINT_CALLBACK_HEADER Mem;
35 PTHREADINFO W32Thread;
36
37 if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER),
38 TAG_CALLBACK)))
39 {
40 return NULL;
41 }
42
43 W32Thread = PsGetCurrentThreadWin32Thread();
44 ASSERT(W32Thread);
45
46 /* insert the callback memory into the thread's callback list */
47
48 InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry);
49
50 return (Mem + 1);
51 }
52
53 VOID FASTCALL
54 IntCbFreeMemory(PVOID Data)
55 {
56 PINT_CALLBACK_HEADER Mem;
57 PTHREADINFO W32Thread;
58
59 ASSERT(Data);
60
61 Mem = ((PINT_CALLBACK_HEADER)Data - 1);
62
63 W32Thread = PsGetCurrentThreadWin32Thread();
64 ASSERT(W32Thread);
65
66 /* remove the memory block from the thread's callback list */
67 RemoveEntryList(&Mem->ListEntry);
68
69 /* free memory */
70 ExFreePoolWithTag(Mem, TAG_CALLBACK);
71 }
72
73 VOID FASTCALL
74 IntCleanupThreadCallbacks(PTHREADINFO W32Thread)
75 {
76 PLIST_ENTRY CurrentEntry;
77 PINT_CALLBACK_HEADER Mem;
78
79 while (!IsListEmpty(&W32Thread->W32CallbackListHead))
80 {
81 CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead);
82 Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER,
83 ListEntry);
84
85 /* free memory */
86 ExFreePool(Mem);
87 }
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, PVOID * pWnd)
97 {
98 HWND hWndS = *hWnd;
99 PWINDOW_OBJECT Window = UserGetWindowObject(*hWnd);
100 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
101
102 *hWnd = ClientInfo->CallbackWnd.hWnd;
103 *pWnd = ClientInfo->CallbackWnd.pvWnd;
104
105 ClientInfo->CallbackWnd.hWnd = hWndS;
106 ClientInfo->CallbackWnd.pvWnd = DesktopHeapAddressToUser(Window->Wnd);
107 }
108
109 static VOID
110 IntRestoreTebWndCallback (HWND hWnd, PVOID pWnd)
111 {
112 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
113
114 ClientInfo->CallbackWnd.hWnd = hWnd;
115 ClientInfo->CallbackWnd.pvWnd = pWnd;
116 }
117
118 /* FUNCTIONS *****************************************************************/
119
120 VOID APIENTRY
121 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
122 HWND hWnd,
123 UINT Msg,
124 ULONG_PTR CompletionCallbackContext,
125 LRESULT Result)
126 {
127 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments;
128 PVOID ResultPointer, pWnd;
129 ULONG ResultLength;
130 NTSTATUS Status;
131
132 Arguments.Callback = CompletionCallback;
133 Arguments.Wnd = hWnd;
134 Arguments.Msg = Msg;
135 Arguments.Context = CompletionCallbackContext;
136 Arguments.Result = Result;
137
138 IntSetTebWndCallback (&hWnd, &pWnd);
139
140 UserLeaveCo();
141
142 Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC,
143 &Arguments,
144 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS),
145 &ResultPointer,
146 &ResultLength);
147
148 UserEnterCo();
149
150 IntRestoreTebWndCallback (hWnd, pWnd);
151
152 if (!NT_SUCCESS(Status))
153 {
154 return;
155 }
156 return;
157 }
158
159 LRESULT APIENTRY
160 co_IntCallWindowProc(WNDPROC Proc,
161 BOOLEAN IsAnsiProc,
162 HWND Wnd,
163 UINT Message,
164 WPARAM wParam,
165 LPARAM lParam,
166 INT lParamBufferSize)
167 {
168 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments;
169 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments;
170 NTSTATUS Status;
171 PVOID ResultPointer, pWnd;
172 ULONG ResultLength;
173 ULONG ArgumentLength;
174 LRESULT Result;
175
176 if (0 < lParamBufferSize)
177 {
178 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize;
179 Arguments = IntCbAllocateMemory(ArgumentLength);
180 if (NULL == Arguments)
181 {
182 DPRINT1("Unable to allocate buffer for window proc callback\n");
183 return -1;
184 }
185 RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
186 (PVOID) lParam, lParamBufferSize);
187 }
188 else
189 {
190 Arguments = &StackArguments;
191 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS);
192 }
193 Arguments->Proc = Proc;
194 Arguments->IsAnsiProc = IsAnsiProc;
195 Arguments->Wnd = Wnd;
196 Arguments->Msg = Message;
197 Arguments->wParam = wParam;
198 Arguments->lParam = lParam;
199 Arguments->lParamBufferSize = lParamBufferSize;
200 ResultPointer = NULL;
201 ResultLength = ArgumentLength;
202
203 IntSetTebWndCallback (&Wnd, &pWnd);
204
205 UserLeaveCo();
206
207 Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC,
208 Arguments,
209 ArgumentLength,
210 &ResultPointer,
211 &ResultLength);
212
213 _SEH2_TRY
214 {
215 /* Simulate old behaviour: copy into our local buffer */
216 RtlMoveMemory(Arguments, ResultPointer, ArgumentLength);
217 }
218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
219 {
220 Status = _SEH2_GetExceptionCode();
221 }
222 _SEH2_END;
223
224 UserEnterCo();
225
226 IntRestoreTebWndCallback (Wnd, pWnd);
227
228 if (!NT_SUCCESS(Status))
229 {
230 if (0 < lParamBufferSize)
231 {
232 IntCbFreeMemory(Arguments);
233 }
234 return -1;
235 }
236 Result = Arguments->Result;
237
238 if (0 < lParamBufferSize)
239 {
240 RtlMoveMemory((PVOID) lParam,
241 (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
242 lParamBufferSize);
243 IntCbFreeMemory(Arguments);
244 }
245
246 return Result;
247 }
248
249 HMENU APIENTRY
250 co_IntLoadSysMenuTemplate()
251 {
252 LRESULT Result = 0;
253 NTSTATUS Status;
254 PVOID ResultPointer;
255 ULONG ResultLength;
256
257 ResultPointer = NULL;
258 ResultLength = sizeof(LRESULT);
259
260 UserLeaveCo();
261
262 Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE,
263 NULL,
264 0,
265 &ResultPointer,
266 &ResultLength);
267 if (NT_SUCCESS(Status))
268 {
269 /* Simulate old behaviour: copy into our local buffer */
270 Result = *(LRESULT*)ResultPointer;
271 }
272
273 UserEnterCo();
274
275 return (HMENU)Result;
276 }
277
278 BOOL APIENTRY
279 co_IntLoadDefaultCursors(VOID)
280 {
281 NTSTATUS Status;
282 PVOID ResultPointer;
283 ULONG ResultLength;
284 BOOL DefaultCursor = TRUE;
285
286 ResultPointer = NULL;
287 ResultLength = sizeof(LRESULT);
288
289 UserLeaveCo();
290
291 Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS,
292 &DefaultCursor,
293 sizeof(BOOL),
294 &ResultPointer,
295 &ResultLength);
296
297 UserEnterCo();
298
299 if (!NT_SUCCESS(Status))
300 {
301 return FALSE;
302 }
303 return TRUE;
304 }
305
306 LRESULT APIENTRY
307 co_IntCallHookProc(INT HookId,
308 INT Code,
309 WPARAM wParam,
310 LPARAM lParam,
311 HOOKPROC Proc,
312 BOOLEAN Ansi,
313 PUNICODE_STRING ModuleName)
314 {
315 ULONG ArgumentLength;
316 PVOID Argument;
317 LRESULT Result = 0;
318 NTSTATUS Status;
319 PVOID ResultPointer;
320 ULONG ResultLength;
321 PHOOKPROC_CALLBACK_ARGUMENTS Common;
322 CBT_CREATEWNDW *CbtCreateWnd =NULL;
323 PCHAR Extra;
324 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
325 UNICODE_STRING WindowName;
326 UNICODE_STRING ClassName;
327 PANSI_STRING asWindowName;
328 PANSI_STRING asClassName;
329 PTHREADINFO pti;
330
331 pti = PsGetCurrentThreadWin32Thread();
332 if (pti->TIF_flags & TIF_INCLEANUP)
333 {
334 DPRINT1("Thread is in cleanup and trying to call hook %d\n", Code);
335 return 0;
336 }
337
338 ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS) - sizeof(WCHAR)
339 + ModuleName->Length;
340 switch(HookId)
341 {
342 case WH_CBT:
343 switch(Code)
344 {
345 case HCBT_CREATEWND:
346 CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
347 ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
348
349 asWindowName = (PANSI_STRING)&WindowName;
350 asClassName = (PANSI_STRING)&ClassName;
351
352 if (Ansi)
353 {
354 RtlInitAnsiString(asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName);
355 ArgumentLength += WindowName.Length + sizeof(CHAR);
356 }
357 else
358 {
359 RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName);
360 ArgumentLength += WindowName.Length + sizeof(WCHAR);
361 }
362
363 if (! IS_ATOM(CbtCreateWnd->lpcs->lpszClass))
364 {
365 if (Ansi)
366 {
367 RtlInitAnsiString(asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass);
368 ArgumentLength += ClassName.Length + sizeof(CHAR);
369 }
370 else
371 {
372 RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass);
373 ArgumentLength += ClassName.Length + sizeof(WCHAR);
374 }
375 }
376 break;
377
378 case HCBT_MOVESIZE:
379 ArgumentLength += sizeof(RECTL);
380 break;
381 case HCBT_ACTIVATE:
382 ArgumentLength += sizeof(CBTACTIVATESTRUCT);
383 break;
384 case HCBT_CLICKSKIPPED:
385 ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
386 break;
387 /* ATM pass on */
388 case HCBT_KEYSKIPPED:
389 case HCBT_MINMAX:
390 case HCBT_SETFOCUS:
391 case HCBT_SYSCOMMAND:
392 /* These types pass through. */
393 case HCBT_DESTROYWND:
394 case HCBT_QS:
395 break;
396 default:
397 DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
398 return 0;
399 }
400 break;
401 case WH_KEYBOARD_LL:
402 ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
403 break;
404 case WH_MOUSE_LL:
405 ArgumentLength += sizeof(MSLLHOOKSTRUCT);
406 break;
407 case WH_MOUSE:
408 ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
409 break;
410 case WH_CALLWNDPROC:
411 ArgumentLength += sizeof(CWPSTRUCT);
412 break;
413 case WH_CALLWNDPROCRET:
414 ArgumentLength += sizeof(CWPRETSTRUCT);
415 break;
416 case WH_MSGFILTER:
417 case WH_SYSMSGFILTER:
418 case WH_GETMESSAGE:
419 ArgumentLength += sizeof(MSG);
420 break;
421 case WH_FOREGROUNDIDLE:
422 case WH_KEYBOARD:
423 case WH_SHELL:
424 break;
425 default:
426 DPRINT1("Trying to call unsupported window hook %d\n", HookId);
427 return 0;
428 }
429
430 Argument = IntCbAllocateMemory(ArgumentLength);
431 if (NULL == Argument)
432 {
433 DPRINT1("HookProc callback failed: out of memory\n");
434 return 0;
435 }
436 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
437 Common->HookId = HookId;
438 Common->Code = Code;
439 Common->wParam = wParam;
440 Common->lParam = lParam;
441 Common->Proc = Proc;
442 Common->Ansi = Ansi;
443 Common->ModuleNameLength = ModuleName->Length;
444 memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
445 Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength;
446
447 switch(HookId)
448 {
449 case WH_CBT:
450 switch(Code)
451 {
452 case HCBT_CREATEWND:
453 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
454 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra;
455 RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) );
456 CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
457 Extra = (PCHAR) (CbtCreatewndExtra + 1);
458 RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length);
459 CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
460 CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer;
461 Extra += WindowName.Length;
462 if (Ansi)
463 {
464 *((CHAR *) Extra) = '\0';
465 Extra += sizeof(CHAR);
466 }
467 else
468 {
469 *((WCHAR *) Extra) = L'\0';
470 Extra += sizeof(WCHAR);
471 }
472
473 if (! IS_ATOM(ClassName.Buffer))
474 {
475 RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length);
476 CbtCreatewndExtra->Cs.lpszClass =
477 (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
478 Extra += ClassName.Length;
479
480 if (Ansi)
481 *((CHAR *) Extra) = '\0';
482 else
483 *((WCHAR *) Extra) = L'\0';
484 }
485 break;
486 case HCBT_CLICKSKIPPED:
487 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
488 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
489 break;
490 case HCBT_MOVESIZE:
491 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(RECTL));
492 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
493 break;
494 case HCBT_ACTIVATE:
495 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CBTACTIVATESTRUCT));
496 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
497 break;
498 }
499 break;
500 case WH_KEYBOARD_LL:
501 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT));
502 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
503 break;
504 case WH_MOUSE_LL:
505 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
506 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
507 break;
508 case WH_MOUSE:
509 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
510 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
511 break;
512 case WH_CALLWNDPROC:
513 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
514 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
515 break;
516 case WH_CALLWNDPROCRET:
517 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
518 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
519 break;
520 case WH_MSGFILTER:
521 case WH_SYSMSGFILTER:
522 case WH_GETMESSAGE:
523 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG));
524 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
525 // DPRINT1("KHOOK Memory: %x\n",Common);
526 break;
527 case WH_FOREGROUNDIDLE:
528 case WH_KEYBOARD:
529 case WH_SHELL:
530 break;
531 }
532
533 ResultPointer = NULL;
534 ResultLength = sizeof(LRESULT);
535
536 UserLeaveCo();
537
538 Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC,
539 Argument,
540 ArgumentLength,
541 &ResultPointer,
542 &ResultLength);
543
544 UserEnterCo();
545
546 _SEH2_TRY
547 {
548 ProbeForRead(ResultPointer, sizeof(LRESULT), 1);
549 /* Simulate old behaviour: copy into our local buffer */
550 Result = *(LRESULT*)ResultPointer;
551 }
552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
553 {
554 Result = 0;
555 }
556 _SEH2_END;
557
558 if (!NT_SUCCESS(Status))
559 {
560 return 0;
561 }
562
563 if (HookId == WH_CBT && Code == HCBT_CREATEWND)
564 {
565 if (CbtCreatewndExtra)
566 {
567 _SEH2_TRY
568 { /*
569 The parameters could have been changed, include the coordinates
570 and dimensions of the window. We copy it back.
571 */
572 CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
573 CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x;
574 CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y;
575 CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
576 CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
577 }
578 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
579 {
580 Result = 0;
581 }
582 _SEH2_END;
583 }
584 }
585
586 if (Argument) IntCbFreeMemory(Argument);
587
588 return Result;
589 }
590
591 //
592 // Events are notifications w/o results.
593 //
594 LRESULT
595 APIENTRY
596 co_IntCallEventProc(HWINEVENTHOOK hook,
597 DWORD event,
598 HWND hWnd,
599 LONG idObject,
600 LONG idChild,
601 DWORD dwEventThread,
602 DWORD dwmsEventTime,
603 WINEVENTPROC Proc)
604 {
605 LRESULT Result = 0;
606 NTSTATUS Status;
607 PEVENTPROC_CALLBACK_ARGUMENTS Common;
608 ULONG ArgumentLength, ResultLength;
609 PVOID Argument, ResultPointer;
610
611 ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS);
612
613 Argument = IntCbAllocateMemory(ArgumentLength);
614 if (NULL == Argument)
615 {
616 DPRINT1("EventProc callback failed: out of memory\n");
617 return 0;
618 }
619 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument;
620 Common->hook = hook;
621 Common->event = event;
622 Common->hwnd = hWnd;
623 Common->idObject = idObject;
624 Common->idChild = idChild;
625 Common->dwEventThread = dwEventThread;
626 Common->dwmsEventTime = dwmsEventTime;
627 Common->Proc = Proc;
628
629 ResultPointer = NULL;
630 ResultLength = sizeof(LRESULT);
631
632 UserLeaveCo();
633
634 Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC,
635 Argument,
636 ArgumentLength,
637 &ResultPointer,
638 &ResultLength);
639
640 UserEnterCo();
641
642 IntCbFreeMemory(Argument);
643
644 if (!NT_SUCCESS(Status))
645 {
646 return 0;
647 }
648
649 return Result;
650 }
651
652 //
653 // Callback Load Menu and results.
654 //
655 HMENU
656 APIENTRY
657 co_IntCallLoadMenu( HINSTANCE hModule,
658 PUNICODE_STRING pMenuName )
659 {
660 LRESULT Result = 0;
661 NTSTATUS Status;
662 PLOADMENU_CALLBACK_ARGUMENTS Common;
663 ULONG ArgumentLength, ResultLength;
664 PVOID Argument, ResultPointer;
665
666 ArgumentLength = sizeof(LOADMENU_CALLBACK_ARGUMENTS);
667
668 ArgumentLength += pMenuName->Length + sizeof(WCHAR);
669
670 Argument = IntCbAllocateMemory(ArgumentLength);
671 if (NULL == Argument)
672 {
673 DPRINT1("LoadMenu callback failed: out of memory\n");
674 return 0;
675 }
676 Common = (PLOADMENU_CALLBACK_ARGUMENTS) Argument;
677
678 // Help Intersource check and MenuName is now 4 bytes + so zero it.
679 RtlZeroMemory(Common, ArgumentLength);
680
681 Common->hModule = hModule;
682 if (pMenuName->Length)
683 RtlCopyMemory(&Common->MenuName, pMenuName->Buffer, pMenuName->Length);
684 else
685 RtlCopyMemory(&Common->MenuName, &pMenuName->Buffer, sizeof(WCHAR));
686
687 ResultPointer = NULL;
688 ResultLength = sizeof(LRESULT);
689
690 UserLeaveCo();
691
692 Status = KeUserModeCallback(USER32_CALLBACK_LOADMENU,
693 Argument,
694 ArgumentLength,
695 &ResultPointer,
696 &ResultLength);
697
698 UserEnterCo();
699
700 Result = *(LRESULT*)ResultPointer;
701
702 IntCbFreeMemory(Argument);
703
704 if (!NT_SUCCESS(Status))
705 {
706 return 0;
707 }
708
709 return (HMENU)Result;
710 }
711
712 NTSTATUS
713 APIENTRY
714 co_IntClientThreadSetup(VOID)
715 {
716 NTSTATUS Status;
717 ULONG ArgumentLength, ResultLength;
718 PVOID Argument, ResultPointer;
719
720 ArgumentLength = ResultLength = 0;
721 Argument = ResultPointer = NULL;
722
723 UserLeaveCo();
724
725 Status = KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP,
726 Argument,
727 ArgumentLength,
728 &ResultPointer,
729 &ResultLength);
730
731 UserEnterCo();
732
733 return Status;
734 }
735
736
737 /* EOF */