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
14 DBG_DEFAULT_CHANNEL(UserCallback
);
17 /* CALLBACK MEMORY MANAGEMENT ************************************************/
19 typedef struct _INT_CALLBACK_HEADER
21 /* List entry in the THREADINFO structure */
24 INT_CALLBACK_HEADER
, *PINT_CALLBACK_HEADER
;
27 IntCbAllocateMemory(ULONG Size
)
29 PINT_CALLBACK_HEADER Mem
;
30 PTHREADINFO W32Thread
;
32 if(!(Mem
= ExAllocatePoolWithTag(PagedPool
, Size
+ sizeof(INT_CALLBACK_HEADER
),
38 W32Thread
= PsGetCurrentThreadWin32Thread();
41 /* Insert the callback memory into the thread's callback list */
43 InsertTailList(&W32Thread
->W32CallbackListHead
, &Mem
->ListEntry
);
49 IntCbFreeMemory(PVOID Data
)
51 PINT_CALLBACK_HEADER Mem
;
52 PTHREADINFO W32Thread
;
56 Mem
= ((PINT_CALLBACK_HEADER
)Data
- 1);
58 W32Thread
= PsGetCurrentThreadWin32Thread();
61 /* Remove the memory block from the thread's callback list */
62 RemoveEntryList(&Mem
->ListEntry
);
65 ExFreePoolWithTag(Mem
, USERTAG_CALLBACK
);
69 IntCleanupThreadCallbacks(PTHREADINFO W32Thread
)
71 PLIST_ENTRY CurrentEntry
;
72 PINT_CALLBACK_HEADER Mem
;
74 while (!IsListEmpty(&W32Thread
->W32CallbackListHead
))
76 CurrentEntry
= RemoveHeadList(&W32Thread
->W32CallbackListHead
);
77 Mem
= CONTAINING_RECORD(CurrentEntry
, INT_CALLBACK_HEADER
,
81 ExFreePoolWithTag(Mem
, USERTAG_CALLBACK
);
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.
90 IntSetTebWndCallback (HWND
* hWnd
, PWND
* pWnd
, PVOID
* pActCtx
)
93 PWND Window
= UserGetWindowObject(*hWnd
);
94 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
96 *hWnd
= ClientInfo
->CallbackWnd
.hWnd
;
97 *pWnd
= ClientInfo
->CallbackWnd
.pWnd
;
98 *pActCtx
= ClientInfo
->CallbackWnd
.pActCtx
;
100 ClientInfo
->CallbackWnd
.hWnd
= hWndS
;
101 ClientInfo
->CallbackWnd
.pWnd
= DesktopHeapAddressToUser(Window
);
102 ClientInfo
->CallbackWnd
.pActCtx
= Window
->pActCtx
;
106 IntRestoreTebWndCallback (HWND hWnd
, PWND pWnd
, PVOID pActCtx
)
108 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
110 ClientInfo
->CallbackWnd
.hWnd
= hWnd
;
111 ClientInfo
->CallbackWnd
.pWnd
= pWnd
;
112 ClientInfo
->CallbackWnd
.pActCtx
= pActCtx
;
115 /* FUNCTIONS *****************************************************************/
117 /* Calls ClientLoadLibrary in user32 */
120 co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName
,
121 PUNICODE_STRING pstrInitFunc
,
127 ULONG ArgumentLength
;
128 PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments
;
131 ULONG_PTR pLibNameBuffer
= 0, pInitFuncBuffer
= 0;
133 TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName
->Buffer
, pstrLibName
->Buffer
, Unload
, ApiHook
);
135 /* Calculate the size of the argument */
136 ArgumentLength
= sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS
);
139 pLibNameBuffer
= ArgumentLength
;
140 ArgumentLength
+= pstrLibName
->Length
+ sizeof(WCHAR
);
144 pInitFuncBuffer
= ArgumentLength
;
145 ArgumentLength
+= pstrInitFunc
->Length
+ sizeof(WCHAR
);
148 /* Allocate the argument */
149 pArguments
= IntCbAllocateMemory(ArgumentLength
);
150 if(pArguments
== NULL
)
155 /* Fill the argument */
156 pArguments
->Unload
= Unload
;
157 pArguments
->ApiHook
= ApiHook
;
160 /* Copy the string to the callback memory */
161 pLibNameBuffer
+= (ULONG_PTR
)pArguments
;
162 pArguments
->strLibraryName
.Buffer
= (PWCHAR
)pLibNameBuffer
;
163 pArguments
->strLibraryName
.MaximumLength
= pstrLibName
->Length
+ sizeof(WCHAR
);
164 RtlCopyUnicodeString(&pArguments
->strLibraryName
, pstrLibName
);
166 /* Fix argument pointer to be relative to the argument */
167 pLibNameBuffer
-= (ULONG_PTR
)pArguments
;
168 pArguments
->strLibraryName
.Buffer
= (PWCHAR
)(pLibNameBuffer
);
172 RtlZeroMemory(&pArguments
->strLibraryName
, sizeof(UNICODE_STRING
));
177 /* Copy the strings to the callback memory */
178 pInitFuncBuffer
+= (ULONG_PTR
)pArguments
;
179 pArguments
->strInitFuncName
.Buffer
= (PWCHAR
)pInitFuncBuffer
;
180 pArguments
->strInitFuncName
.MaximumLength
= pstrInitFunc
->Length
+ sizeof(WCHAR
);
181 RtlCopyUnicodeString(&pArguments
->strInitFuncName
, pstrInitFunc
);
183 /* Fix argument pointers to be relative to the argument */
184 pInitFuncBuffer
-= (ULONG_PTR
)pArguments
;
185 pArguments
->strInitFuncName
.Buffer
= (PWCHAR
)(pInitFuncBuffer
);
189 RtlZeroMemory(&pArguments
->strInitFuncName
, sizeof(UNICODE_STRING
));
192 /* Do the callback */
195 Status
= KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY
,
203 /* Free the argument */
204 IntCbFreeMemory(pArguments
);
206 if(!NT_SUCCESS(Status
))
213 /* Probe and copy the usermode result data */
214 ProbeForRead(ResultPointer
, sizeof(HMODULE
), 1);
215 bResult
= *(BOOL
*)ResultPointer
;
217 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
227 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback
,
230 ULONG_PTR CompletionCallbackContext
,
233 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments
;
234 PVOID ResultPointer
, pActCtx
;
239 Arguments
.Callback
= CompletionCallback
;
240 Arguments
.Wnd
= hWnd
;
242 Arguments
.Context
= CompletionCallbackContext
;
243 Arguments
.Result
= Result
;
245 IntSetTebWndCallback (&hWnd
, &pWnd
, &pActCtx
);
249 Status
= KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC
,
251 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS
),
257 IntRestoreTebWndCallback (hWnd
, pWnd
, pActCtx
);
259 if (!NT_SUCCESS(Status
))
267 co_IntCallWindowProc(WNDPROC Proc
,
273 INT lParamBufferSize
)
275 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments
;
276 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments
;
278 PVOID ResultPointer
, pActCtx
;
281 ULONG ArgumentLength
;
284 if (0 < lParamBufferSize
)
286 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
) + lParamBufferSize
;
287 Arguments
= IntCbAllocateMemory(ArgumentLength
);
288 if (NULL
== Arguments
)
290 ERR("Unable to allocate buffer for window proc callback\n");
293 RtlMoveMemory((PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
294 (PVOID
) lParam
, lParamBufferSize
);
298 Arguments
= &StackArguments
;
299 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
);
301 Arguments
->Proc
= Proc
;
302 Arguments
->IsAnsiProc
= IsAnsiProc
;
303 Arguments
->Wnd
= Wnd
;
304 Arguments
->Msg
= Message
;
305 Arguments
->wParam
= wParam
;
306 Arguments
->lParam
= lParam
;
307 Arguments
->lParamBufferSize
= lParamBufferSize
;
308 ResultPointer
= NULL
;
309 ResultLength
= ArgumentLength
;
311 IntSetTebWndCallback (&Wnd
, &pWnd
, &pActCtx
);
315 Status
= KeUserModeCallback(USER32_CALLBACK_WINDOWPROC
,
323 /* Simulate old behaviour: copy into our local buffer */
324 RtlMoveMemory(Arguments
, ResultPointer
, ArgumentLength
);
326 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
328 ERR("Failed to copy result from user mode!\n");
329 Status
= _SEH2_GetExceptionCode();
335 IntRestoreTebWndCallback (Wnd
, pWnd
, pActCtx
);
337 if (!NT_SUCCESS(Status
))
339 ERR("Call to user mode failed!\n");
340 if (0 < lParamBufferSize
)
342 IntCbFreeMemory(Arguments
);
346 Result
= Arguments
->Result
;
348 if (0 < lParamBufferSize
)
350 RtlMoveMemory((PVOID
) lParam
,
351 (PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
353 IntCbFreeMemory(Arguments
);
360 co_IntLoadSysMenuTemplate()
367 ResultPointer
= NULL
;
368 ResultLength
= sizeof(LRESULT
);
372 Status
= KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE
,
377 if (NT_SUCCESS(Status
))
379 /* Simulate old behaviour: copy into our local buffer */
382 ProbeForRead(ResultPointer
, sizeof(LRESULT
), 1);
383 Result
= *(LRESULT
*)ResultPointer
;
385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
394 return (HMENU
)Result
;
398 co_IntLoadDefaultCursors(VOID
)
403 BOOL DefaultCursor
= TRUE
;
405 ResultPointer
= NULL
;
406 ResultLength
= sizeof(LRESULT
);
410 Status
= KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS
,
418 if (!NT_SUCCESS(Status
))
426 co_IntCallHookProc(INT HookId
,
432 PUNICODE_STRING ModuleName
)
434 ULONG ArgumentLength
;
435 PVOID Argument
= NULL
;
440 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
441 CBT_CREATEWNDW
*CbtCreateWnd
= NULL
;
443 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
452 pti
= PsGetCurrentThreadWin32Thread();
453 if (pti
->TIF_flags
& TIF_INCLEANUP
)
455 ERR("Thread is in cleanup and trying to call hook %d\n", Code
);
459 ArgumentLength
= sizeof(HOOKPROC_CALLBACK_ARGUMENTS
);
464 TRACE("WH_CBT: Code %d\n", Code
);
468 pWnd
= UserGetWindowObject((HWND
) wParam
);
471 ERR("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
474 TRACE("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd
->state
& WNDS_ANSICREATOR
? "True" : "False", Ansi
? "True" : "False");
475 // Due to KsStudio.exe, just pass the callers original pointers
476 // except class which point to kernel space if not an atom.
477 // Found by, Olaf Siejka
478 CbtCreateWnd
= (CBT_CREATEWNDW
*) lParam
;
479 ArgumentLength
+= sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
);
483 ArgumentLength
+= sizeof(RECTL
);
486 ArgumentLength
+= sizeof(CBTACTIVATESTRUCT
);
488 case HCBT_CLICKSKIPPED
:
489 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
492 case HCBT_KEYSKIPPED
:
495 case HCBT_SYSCOMMAND
:
496 /* These types pass through. */
497 case HCBT_DESTROYWND
:
501 ERR("Trying to call unsupported CBT hook %d\n", Code
);
506 ArgumentLength
+= sizeof(KBDLLHOOKSTRUCT
);
509 ArgumentLength
+= sizeof(MSLLHOOKSTRUCT
);
512 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
516 CWPSTRUCT
* pCWP
= (CWPSTRUCT
*) lParam
;
517 ArgumentLength
+= sizeof(CWPSTRUCT
);
518 lParamSize
= lParamMemorySize(pCWP
->message
, pCWP
->wParam
, pCWP
->lParam
);
519 ArgumentLength
+= lParamSize
;
522 case WH_CALLWNDPROCRET
:
524 CWPRETSTRUCT
* pCWPR
= (CWPRETSTRUCT
*) lParam
;
525 ArgumentLength
+= sizeof(CWPRETSTRUCT
);
526 lParamSize
= lParamMemorySize(pCWPR
->message
, pCWPR
->wParam
, pCWPR
->lParam
);
527 ArgumentLength
+= lParamSize
;
531 case WH_SYSMSGFILTER
:
533 ArgumentLength
+= sizeof(MSG
);
535 case WH_FOREGROUNDIDLE
:
540 ERR("Trying to call unsupported window hook %d\n", HookId
);
544 Argument
= IntCbAllocateMemory(ArgumentLength
);
545 if (NULL
== Argument
)
547 ERR("HookProc callback failed: out of memory\n");
550 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Argument
;
551 Common
->HookId
= HookId
;
553 Common
->wParam
= wParam
;
554 Common
->lParam
= lParam
;
557 Extra
= (PCHAR
) Common
+ sizeof(HOOKPROC_CALLBACK_ARGUMENTS
);
563 { // Need to remember this is not the first time through! Call Next Hook?
565 CbtCreatewndExtra
= (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
) Extra
;
566 RtlCopyMemory( &CbtCreatewndExtra
->Cs
, CbtCreateWnd
->lpcs
, sizeof(CREATESTRUCTW
) );
567 CbtCreatewndExtra
->WndInsertAfter
= CbtCreateWnd
->hwndInsertAfter
;
568 CbtCreatewndExtra
->Cs
.lpszClass
= CbtCreateWnd
->lpcs
->lpszClass
;
569 CbtCreatewndExtra
->Cs
.lpszName
= CbtCreateWnd
->lpcs
->lpszName
;
570 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
572 case HCBT_CLICKSKIPPED
:
573 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
574 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
577 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(RECTL
));
578 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
581 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CBTACTIVATESTRUCT
));
582 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
587 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(KBDLLHOOKSTRUCT
));
588 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
591 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MSLLHOOKSTRUCT
));
592 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
595 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
596 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
599 /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that
600 * lParam could be a pointer to a buffer. This buffer must be exported
601 * to user space too */
602 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPSTRUCT
));
603 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
606 RtlCopyMemory(Extra
+ sizeof(CWPSTRUCT
), (PVOID
)((CWPSTRUCT
*)lParam
)->lParam
, lParamSize
);
607 ((CWPSTRUCT
*)Extra
)->lParam
= (LPARAM
)lParamSize
;
610 case WH_CALLWNDPROCRET
:
611 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPRETSTRUCT
));
612 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
615 RtlCopyMemory(Extra
+ sizeof(CWPRETSTRUCT
), (PVOID
)((CWPRETSTRUCT
*)lParam
)->lParam
, lParamSize
);
616 ((CWPRETSTRUCT
*)Extra
)->lParam
= (LPARAM
)lParamSize
;
620 case WH_SYSMSGFILTER
:
623 RtlCopyMemory(Extra
, (PVOID
) pMsg
, sizeof(MSG
));
624 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
626 case WH_FOREGROUNDIDLE
:
632 ResultPointer
= NULL
;
633 ResultLength
= sizeof(LRESULT
);
637 Status
= KeUserModeCallback(USER32_CALLBACK_HOOKPROC
,
649 ProbeForRead(ResultPointer
, sizeof(LRESULT
), 1);
650 /* Simulate old behaviour: copy into our local buffer */
651 Result
= *(LRESULT
*)ResultPointer
;
653 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
662 ERR("ERROR: Hook ResultPointer 0x%p ResultLength %u\n",ResultPointer
,ResultLength
);
665 if (!NT_SUCCESS(Status
))
667 ERR("Failure to make Callback! Status 0x%x",Status
);
670 /* Support write backs... SEH is in UserCallNextHookEx. */
674 if (Code
== HCBT_CREATEWND
)
676 if (CbtCreatewndExtra
)
678 The parameters could have been changed, include the coordinates
679 and dimensions of the window. We copy it back.
681 CbtCreateWnd
->hwndInsertAfter
= CbtCreatewndExtra
->WndInsertAfter
;
682 CbtCreateWnd
->lpcs
->x
= CbtCreatewndExtra
->Cs
.x
;
683 CbtCreateWnd
->lpcs
->y
= CbtCreatewndExtra
->Cs
.y
;
684 CbtCreateWnd
->lpcs
->cx
= CbtCreatewndExtra
->Cs
.cx
;
685 CbtCreateWnd
->lpcs
->cy
= CbtCreatewndExtra
->Cs
.cy
;
689 // "The GetMsgProc hook procedure can examine or modify the message."
693 RtlCopyMemory((PVOID
) pMsg
, Extra
, sizeof(MSG
));
701 ERR("Exception CallHookProc HookId %d Code %d\n",HookId
,Code
);
703 if (Argument
) IntCbFreeMemory(Argument
);
709 // Events are notifications w/o results.
713 co_IntCallEventProc(HWINEVENTHOOK hook
,
724 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
725 ULONG ArgumentLength
, ResultLength
;
726 PVOID Argument
, ResultPointer
;
728 ArgumentLength
= sizeof(EVENTPROC_CALLBACK_ARGUMENTS
);
730 Argument
= IntCbAllocateMemory(ArgumentLength
);
731 if (NULL
== Argument
)
733 ERR("EventProc callback failed: out of memory\n");
736 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Argument
;
738 Common
->event
= event
;
740 Common
->idObject
= idObject
;
741 Common
->idChild
= idChild
;
742 Common
->dwEventThread
= dwEventThread
;
743 Common
->dwmsEventTime
= dwmsEventTime
;
746 ResultPointer
= NULL
;
747 ResultLength
= sizeof(LRESULT
);
751 Status
= KeUserModeCallback(USER32_CALLBACK_EVENTPROC
,
759 IntCbFreeMemory(Argument
);
761 if (!NT_SUCCESS(Status
))
770 // Callback Load Menu and results.
774 co_IntCallLoadMenu( HINSTANCE hModule
,
775 PUNICODE_STRING pMenuName
)
779 PLOADMENU_CALLBACK_ARGUMENTS Common
;
780 ULONG ArgumentLength
, ResultLength
;
781 PVOID Argument
, ResultPointer
;
783 ArgumentLength
= sizeof(LOADMENU_CALLBACK_ARGUMENTS
);
785 ArgumentLength
+= pMenuName
->Length
+ sizeof(WCHAR
);
787 Argument
= IntCbAllocateMemory(ArgumentLength
);
788 if (NULL
== Argument
)
790 ERR("LoadMenu callback failed: out of memory\n");
793 Common
= (PLOADMENU_CALLBACK_ARGUMENTS
) Argument
;
795 // Help Intersource check and MenuName is now 4 bytes + so zero it.
796 RtlZeroMemory(Common
, ArgumentLength
);
798 Common
->hModule
= hModule
;
799 if (pMenuName
->Length
)
800 RtlCopyMemory(&Common
->MenuName
, pMenuName
->Buffer
, pMenuName
->Length
);
802 RtlCopyMemory(&Common
->MenuName
, &pMenuName
->Buffer
, sizeof(WCHAR
));
804 ResultPointer
= NULL
;
805 ResultLength
= sizeof(LRESULT
);
809 Status
= KeUserModeCallback(USER32_CALLBACK_LOADMENU
,
817 Result
= *(LRESULT
*)ResultPointer
;
819 IntCbFreeMemory(Argument
);
821 if (!NT_SUCCESS(Status
))
826 return (HMENU
)Result
;
831 co_IntClientThreadSetup(VOID
)
834 ULONG ArgumentLength
, ResultLength
;
835 PVOID Argument
, ResultPointer
;
837 ArgumentLength
= ResultLength
= 0;
838 Argument
= ResultPointer
= NULL
;
842 Status
= KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP
,
855 co_IntGetCharsetInfo(LCID Locale
, PCHARSETINFO pCs
)
858 ULONG ArgumentLength
, ResultLength
;
859 PVOID Argument
, ResultPointer
;
860 PGET_CHARSET_INFO Common
;
862 ArgumentLength
= sizeof(GET_CHARSET_INFO
);
864 Argument
= IntCbAllocateMemory(ArgumentLength
);
865 if (NULL
== Argument
)
867 ERR("GetCharsetInfo callback failed: out of memory\n");
870 Common
= (PGET_CHARSET_INFO
) Argument
;
872 Common
->Locale
= Locale
;
874 ResultPointer
= NULL
;
875 ResultLength
= ArgumentLength
;
879 Status
= KeUserModeCallback(USER32_CALLBACK_GETCHARSETINFO
,
887 /* Need to copy into our local buffer */
888 RtlMoveMemory(Argument
, ResultPointer
, ArgumentLength
);
890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
892 ERR("Failed to copy result from user mode!\n");
893 Status
= _SEH2_GetExceptionCode();
899 RtlCopyMemory(pCs
, &Common
->Cs
, sizeof(CHARSETINFO
));
901 IntCbFreeMemory(Argument
);
903 if (!NT_SUCCESS(Status
))
905 ERR("GetCharsetInfo Failed!!\n");