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)
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
15 /* INCLUDES ******************************************************************/
22 /* CALLBACK MEMORY MANAGEMENT ************************************************/
24 typedef struct _INT_CALLBACK_HEADER
26 /* list entry in the THREADINFO structure */
29 INT_CALLBACK_HEADER
, *PINT_CALLBACK_HEADER
;
32 IntCbAllocateMemory(ULONG Size
)
34 PINT_CALLBACK_HEADER Mem
;
35 PTHREADINFO W32Thread
;
37 if(!(Mem
= ExAllocatePoolWithTag(PagedPool
, Size
+ sizeof(INT_CALLBACK_HEADER
),
43 W32Thread
= PsGetCurrentThreadWin32Thread();
46 /* insert the callback memory into the thread's callback list */
48 InsertTailList(&W32Thread
->W32CallbackListHead
, &Mem
->ListEntry
);
54 IntCbFreeMemory(PVOID Data
)
56 PINT_CALLBACK_HEADER Mem
;
57 PTHREADINFO W32Thread
;
61 Mem
= ((PINT_CALLBACK_HEADER
)Data
- 1);
63 W32Thread
= PsGetCurrentThreadWin32Thread();
66 /* remove the memory block from the thread's callback list */
67 RemoveEntryList(&Mem
->ListEntry
);
70 ExFreePoolWithTag(Mem
, TAG_CALLBACK
);
74 IntCleanupThreadCallbacks(PTHREADINFO W32Thread
)
76 PLIST_ENTRY CurrentEntry
;
77 PINT_CALLBACK_HEADER Mem
;
79 while (!IsListEmpty(&W32Thread
->W32CallbackListHead
))
81 CurrentEntry
= RemoveHeadList(&W32Thread
->W32CallbackListHead
);
82 Mem
= CONTAINING_RECORD(CurrentEntry
, INT_CALLBACK_HEADER
,
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.
96 IntSetTebWndCallback (HWND
* hWnd
, PWND
* pWnd
)
99 PWND Window
= UserGetWindowObject(*hWnd
);
100 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
102 *hWnd
= ClientInfo
->CallbackWnd
.hWnd
;
103 *pWnd
= ClientInfo
->CallbackWnd
.pWnd
;
105 ClientInfo
->CallbackWnd
.hWnd
= hWndS
;
106 ClientInfo
->CallbackWnd
.pWnd
= DesktopHeapAddressToUser(Window
);
110 IntRestoreTebWndCallback (HWND hWnd
, PWND pWnd
)
112 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
114 ClientInfo
->CallbackWnd
.hWnd
= hWnd
;
115 ClientInfo
->CallbackWnd
.pWnd
= pWnd
;
118 /* FUNCTIONS *****************************************************************/
121 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback
,
124 ULONG_PTR CompletionCallbackContext
,
127 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments
;
133 Arguments
.Callback
= CompletionCallback
;
134 Arguments
.Wnd
= hWnd
;
136 Arguments
.Context
= CompletionCallbackContext
;
137 Arguments
.Result
= Result
;
139 IntSetTebWndCallback (&hWnd
, &pWnd
);
143 Status
= KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC
,
145 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS
),
151 IntRestoreTebWndCallback (hWnd
, pWnd
);
153 if (!NT_SUCCESS(Status
))
161 co_IntCallWindowProc(WNDPROC Proc
,
167 INT lParamBufferSize
)
169 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments
;
170 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments
;
175 ULONG ArgumentLength
;
178 if (0 < lParamBufferSize
)
180 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
) + lParamBufferSize
;
181 Arguments
= IntCbAllocateMemory(ArgumentLength
);
182 if (NULL
== Arguments
)
184 DPRINT1("Unable to allocate buffer for window proc callback\n");
187 RtlMoveMemory((PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
188 (PVOID
) lParam
, lParamBufferSize
);
192 Arguments
= &StackArguments
;
193 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
);
195 Arguments
->Proc
= Proc
;
196 Arguments
->IsAnsiProc
= IsAnsiProc
;
197 Arguments
->Wnd
= Wnd
;
198 Arguments
->Msg
= Message
;
199 Arguments
->wParam
= wParam
;
200 Arguments
->lParam
= lParam
;
201 Arguments
->lParamBufferSize
= lParamBufferSize
;
202 ResultPointer
= NULL
;
203 ResultLength
= ArgumentLength
;
205 IntSetTebWndCallback (&Wnd
, &pWnd
);
209 Status
= KeUserModeCallback(USER32_CALLBACK_WINDOWPROC
,
217 /* Simulate old behaviour: copy into our local buffer */
218 RtlMoveMemory(Arguments
, ResultPointer
, ArgumentLength
);
220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
222 Status
= _SEH2_GetExceptionCode();
228 IntRestoreTebWndCallback (Wnd
, pWnd
);
230 if (!NT_SUCCESS(Status
))
232 if (0 < lParamBufferSize
)
234 IntCbFreeMemory(Arguments
);
238 Result
= Arguments
->Result
;
240 if (0 < lParamBufferSize
)
242 RtlMoveMemory((PVOID
) lParam
,
243 (PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
245 IntCbFreeMemory(Arguments
);
252 co_IntLoadSysMenuTemplate()
259 ResultPointer
= NULL
;
260 ResultLength
= sizeof(LRESULT
);
264 Status
= KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE
,
269 if (NT_SUCCESS(Status
))
271 /* Simulate old behaviour: copy into our local buffer */
274 ProbeForRead(ResultPointer
, sizeof(LRESULT
), 1);
275 Result
= *(LRESULT
*)ResultPointer
;
277 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
286 return (HMENU
)Result
;
290 co_IntLoadDefaultCursors(VOID
)
295 BOOL DefaultCursor
= TRUE
;
297 ResultPointer
= NULL
;
298 ResultLength
= sizeof(LRESULT
);
302 Status
= KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS
,
310 if (!NT_SUCCESS(Status
))
318 co_IntCallHookProc(INT HookId
,
324 PUNICODE_STRING ModuleName
)
326 ULONG ArgumentLength
;
327 PVOID Argument
= NULL
;
332 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
333 CBT_CREATEWNDW
*CbtCreateWnd
= NULL
;
335 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
343 pti
= PsGetCurrentThreadWin32Thread();
344 if (pti
->TIF_flags
& TIF_INCLEANUP
)
346 DPRINT1("Thread is in cleanup and trying to call hook %d\n", Code
);
350 ArgumentLength
= sizeof(HOOKPROC_CALLBACK_ARGUMENTS
);
355 DPRINT("WH_CBT: Code %d\n", Code
);
359 pWnd
= UserGetWindowObject((HWND
) wParam
);
362 DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
365 DPRINT("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd
->state
& WNDS_ANSICREATOR
? "True" : "False", Ansi
? "True" : "False");
366 // Due to KsStudio.exe, just pass the callers original pointers
367 // except class which point to kernel space if not an atom.
368 // Found by, Olaf Siejka
369 CbtCreateWnd
= (CBT_CREATEWNDW
*) lParam
;
370 ArgumentLength
+= sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
);
374 ArgumentLength
+= sizeof(RECTL
);
377 ArgumentLength
+= sizeof(CBTACTIVATESTRUCT
);
379 case HCBT_CLICKSKIPPED
:
380 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
383 case HCBT_KEYSKIPPED
:
386 case HCBT_SYSCOMMAND
:
387 /* These types pass through. */
388 case HCBT_DESTROYWND
:
392 DPRINT1("Trying to call unsupported CBT hook %d\n", Code
);
397 ArgumentLength
+= sizeof(KBDLLHOOKSTRUCT
);
400 ArgumentLength
+= sizeof(MSLLHOOKSTRUCT
);
403 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
406 ArgumentLength
+= sizeof(CWPSTRUCT
);
408 case WH_CALLWNDPROCRET
:
409 ArgumentLength
+= sizeof(CWPRETSTRUCT
);
412 case WH_SYSMSGFILTER
:
414 ArgumentLength
+= sizeof(MSG
);
416 case WH_FOREGROUNDIDLE
:
421 DPRINT1("Trying to call unsupported window hook %d\n", HookId
);
425 Argument
= IntCbAllocateMemory(ArgumentLength
);
426 if (NULL
== Argument
)
428 DPRINT1("HookProc callback failed: out of memory\n");
431 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Argument
;
432 Common
->HookId
= HookId
;
434 Common
->wParam
= wParam
;
435 Common
->lParam
= lParam
;
438 Extra
= (PCHAR
) Common
+ sizeof(HOOKPROC_CALLBACK_ARGUMENTS
);
444 { // Need to remember this is not the first time through! Call Next Hook?
446 CbtCreatewndExtra
= (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
) Extra
;
447 RtlCopyMemory( &CbtCreatewndExtra
->Cs
, CbtCreateWnd
->lpcs
, sizeof(CREATESTRUCTW
) );
448 CbtCreatewndExtra
->WndInsertAfter
= CbtCreateWnd
->hwndInsertAfter
;
449 CbtCreatewndExtra
->Cs
.lpszClass
= CbtCreateWnd
->lpcs
->lpszClass
;
450 CbtCreatewndExtra
->Cs
.lpszName
= CbtCreateWnd
->lpcs
->lpszName
;
451 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
453 case HCBT_CLICKSKIPPED
:
454 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
455 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
458 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(RECTL
));
459 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
462 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CBTACTIVATESTRUCT
));
463 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
468 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(KBDLLHOOKSTRUCT
));
469 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
472 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MSLLHOOKSTRUCT
));
473 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
476 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
477 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
480 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPSTRUCT
));
481 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
483 case WH_CALLWNDPROCRET
:
484 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPRETSTRUCT
));
485 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
488 case WH_SYSMSGFILTER
:
491 RtlCopyMemory(Extra
, (PVOID
) pMsg
, sizeof(MSG
));
492 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
494 case WH_FOREGROUNDIDLE
:
500 ResultPointer
= NULL
;
501 ResultLength
= sizeof(LRESULT
);
505 Status
= KeUserModeCallback(USER32_CALLBACK_HOOKPROC
,
515 ProbeForRead(ResultPointer
, sizeof(LRESULT
), 1);
516 /* Simulate old behaviour: copy into our local buffer */
517 Result
= *(LRESULT
*)ResultPointer
;
519 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
526 if (!NT_SUCCESS(Status
))
528 DPRINT1("Failure to make Callback! Status 0x%x",Status
);
531 /* Support write backs... SEH is in UserCallNextHookEx. */
535 if (Code
== HCBT_CREATEWND
)
537 if (CbtCreatewndExtra
)
539 The parameters could have been changed, include the coordinates
540 and dimensions of the window. We copy it back.
542 CbtCreateWnd
->hwndInsertAfter
= CbtCreatewndExtra
->WndInsertAfter
;
543 CbtCreateWnd
->lpcs
->x
= CbtCreatewndExtra
->Cs
.x
;
544 CbtCreateWnd
->lpcs
->y
= CbtCreatewndExtra
->Cs
.y
;
545 CbtCreateWnd
->lpcs
->cx
= CbtCreatewndExtra
->Cs
.cx
;
546 CbtCreateWnd
->lpcs
->cy
= CbtCreatewndExtra
->Cs
.cy
;
550 // "The GetMsgProc hook procedure can examine or modify the message."
554 RtlCopyMemory((PVOID
) pMsg
, Extra
, sizeof(MSG
));
562 DPRINT1("Exception CallHookProc HookId %d Code %d\n",HookId
,Code
);
564 if (Argument
) IntCbFreeMemory(Argument
);
570 // Events are notifications w/o results.
574 co_IntCallEventProc(HWINEVENTHOOK hook
,
585 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
586 ULONG ArgumentLength
, ResultLength
;
587 PVOID Argument
, ResultPointer
;
589 ArgumentLength
= sizeof(EVENTPROC_CALLBACK_ARGUMENTS
);
591 Argument
= IntCbAllocateMemory(ArgumentLength
);
592 if (NULL
== Argument
)
594 DPRINT1("EventProc callback failed: out of memory\n");
597 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Argument
;
599 Common
->event
= event
;
601 Common
->idObject
= idObject
;
602 Common
->idChild
= idChild
;
603 Common
->dwEventThread
= dwEventThread
;
604 Common
->dwmsEventTime
= dwmsEventTime
;
607 ResultPointer
= NULL
;
608 ResultLength
= sizeof(LRESULT
);
612 Status
= KeUserModeCallback(USER32_CALLBACK_EVENTPROC
,
620 IntCbFreeMemory(Argument
);
622 if (!NT_SUCCESS(Status
))
631 // Callback Load Menu and results.
635 co_IntCallLoadMenu( HINSTANCE hModule
,
636 PUNICODE_STRING pMenuName
)
640 PLOADMENU_CALLBACK_ARGUMENTS Common
;
641 ULONG ArgumentLength
, ResultLength
;
642 PVOID Argument
, ResultPointer
;
644 ArgumentLength
= sizeof(LOADMENU_CALLBACK_ARGUMENTS
);
646 ArgumentLength
+= pMenuName
->Length
+ sizeof(WCHAR
);
648 Argument
= IntCbAllocateMemory(ArgumentLength
);
649 if (NULL
== Argument
)
651 DPRINT1("LoadMenu callback failed: out of memory\n");
654 Common
= (PLOADMENU_CALLBACK_ARGUMENTS
) Argument
;
656 // Help Intersource check and MenuName is now 4 bytes + so zero it.
657 RtlZeroMemory(Common
, ArgumentLength
);
659 Common
->hModule
= hModule
;
660 if (pMenuName
->Length
)
661 RtlCopyMemory(&Common
->MenuName
, pMenuName
->Buffer
, pMenuName
->Length
);
663 RtlCopyMemory(&Common
->MenuName
, &pMenuName
->Buffer
, sizeof(WCHAR
));
665 ResultPointer
= NULL
;
666 ResultLength
= sizeof(LRESULT
);
670 Status
= KeUserModeCallback(USER32_CALLBACK_LOADMENU
,
678 Result
= *(LRESULT
*)ResultPointer
;
680 IntCbFreeMemory(Argument
);
682 if (!NT_SUCCESS(Status
))
687 return (HMENU
)Result
;
692 co_IntClientThreadSetup(VOID
)
695 ULONG ArgumentLength
, ResultLength
;
696 PVOID Argument
, ResultPointer
;
698 ArgumentLength
= ResultLength
= 0;
699 Argument
= ResultPointer
= NULL
;
703 Status
= KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP
,