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
, PVOID
* pWnd
)
99 PWINDOW_OBJECT Window
= UserGetWindowObject(*hWnd
);
100 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
102 *hWnd
= ClientInfo
->CallbackWnd
.hWnd
;
103 *pWnd
= ClientInfo
->CallbackWnd
.pvWnd
;
105 ClientInfo
->CallbackWnd
.hWnd
= hWndS
;
106 ClientInfo
->CallbackWnd
.pvWnd
= DesktopHeapAddressToUser(Window
->Wnd
);
110 IntRestoreTebWndCallback (HWND hWnd
, PVOID pWnd
)
112 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
114 ClientInfo
->CallbackWnd
.hWnd
= hWnd
;
115 ClientInfo
->CallbackWnd
.pvWnd
= pWnd
;
118 /* FUNCTIONS *****************************************************************/
121 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback
,
124 ULONG_PTR CompletionCallbackContext
,
127 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments
;
128 PVOID ResultPointer
, pWnd
;
132 Arguments
.Callback
= CompletionCallback
;
133 Arguments
.Wnd
= hWnd
;
135 Arguments
.Context
= CompletionCallbackContext
;
136 Arguments
.Result
= Result
;
138 IntSetTebWndCallback (&hWnd
, &pWnd
);
142 Status
= KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC
,
144 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS
),
150 IntRestoreTebWndCallback (hWnd
, pWnd
);
152 if (!NT_SUCCESS(Status
))
160 co_IntCallWindowProc(WNDPROC Proc
,
166 INT lParamBufferSize
)
168 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments
;
169 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments
;
171 PVOID ResultPointer
, pWnd
;
173 ULONG ArgumentLength
;
176 if (0 < lParamBufferSize
)
178 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
) + lParamBufferSize
;
179 Arguments
= IntCbAllocateMemory(ArgumentLength
);
180 if (NULL
== Arguments
)
182 DPRINT1("Unable to allocate buffer for window proc callback\n");
185 RtlMoveMemory((PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
186 (PVOID
) lParam
, lParamBufferSize
);
190 Arguments
= &StackArguments
;
191 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
);
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
;
203 IntSetTebWndCallback (&Wnd
, &pWnd
);
207 Status
= KeUserModeCallback(USER32_CALLBACK_WINDOWPROC
,
215 /* Simulate old behaviour: copy into our local buffer */
216 RtlMoveMemory(Arguments
, ResultPointer
, ArgumentLength
);
218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
220 Status
= _SEH2_GetExceptionCode();
226 IntRestoreTebWndCallback (Wnd
, pWnd
);
228 if (!NT_SUCCESS(Status
))
230 if (0 < lParamBufferSize
)
232 IntCbFreeMemory(Arguments
);
236 Result
= Arguments
->Result
;
238 if (0 < lParamBufferSize
)
240 RtlMoveMemory((PVOID
) lParam
,
241 (PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
243 IntCbFreeMemory(Arguments
);
250 co_IntLoadSysMenuTemplate()
257 ResultPointer
= NULL
;
258 ResultLength
= sizeof(LRESULT
);
262 Status
= KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE
,
267 if (NT_SUCCESS(Status
))
269 /* Simulate old behaviour: copy into our local buffer */
270 Result
= *(LRESULT
*)ResultPointer
;
275 return (HMENU
)Result
;
279 co_IntLoadDefaultCursors(VOID
)
284 BOOL DefaultCursor
= TRUE
;
286 ResultPointer
= NULL
;
287 ResultLength
= sizeof(LRESULT
);
291 Status
= KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS
,
299 if (!NT_SUCCESS(Status
))
307 co_IntCallHookProc(INT HookId
,
313 PUNICODE_STRING ModuleName
)
315 ULONG ArgumentLength
;
321 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
322 CBT_CREATEWNDW
*CbtCreateWnd
=NULL
;
324 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
325 UNICODE_STRING WindowName
;
326 UNICODE_STRING ClassName
;
327 PANSI_STRING asWindowName
;
328 PANSI_STRING asClassName
;
331 pti
= PsGetCurrentThreadWin32Thread();
332 if (pti
->TIF_flags
& TIF_INCLEANUP
)
334 DPRINT1("Thread is in cleanup and trying to call hook %d\n", Code
);
338 ArgumentLength
= sizeof(HOOKPROC_CALLBACK_ARGUMENTS
) - sizeof(WCHAR
)
339 + ModuleName
->Length
;
346 CbtCreateWnd
= (CBT_CREATEWNDW
*) lParam
;
347 ArgumentLength
+= sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
);
349 asWindowName
= (PANSI_STRING
)&WindowName
;
350 asClassName
= (PANSI_STRING
)&ClassName
;
354 RtlInitAnsiString(asWindowName
, (PCSZ
)CbtCreateWnd
->lpcs
->lpszName
);
355 ArgumentLength
+= WindowName
.Length
+ sizeof(CHAR
);
359 RtlInitUnicodeString(&WindowName
, CbtCreateWnd
->lpcs
->lpszName
);
360 ArgumentLength
+= WindowName
.Length
+ sizeof(WCHAR
);
363 if (! IS_ATOM(CbtCreateWnd
->lpcs
->lpszClass
))
367 RtlInitAnsiString(asClassName
, (PCSZ
)CbtCreateWnd
->lpcs
->lpszClass
);
368 ArgumentLength
+= ClassName
.Length
+ sizeof(CHAR
);
372 RtlInitUnicodeString(&ClassName
, CbtCreateWnd
->lpcs
->lpszClass
);
373 ArgumentLength
+= ClassName
.Length
+ sizeof(WCHAR
);
379 ArgumentLength
+= sizeof(RECTL
);
382 ArgumentLength
+= sizeof(CBTACTIVATESTRUCT
);
384 case HCBT_CLICKSKIPPED
:
385 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
388 case HCBT_KEYSKIPPED
:
391 case HCBT_SYSCOMMAND
:
392 /* These types pass through. */
393 case HCBT_DESTROYWND
:
397 DPRINT1("Trying to call unsupported CBT hook %d\n", Code
);
402 ArgumentLength
+= sizeof(KBDLLHOOKSTRUCT
);
405 ArgumentLength
+= sizeof(MSLLHOOKSTRUCT
);
408 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
411 ArgumentLength
+= sizeof(CWPSTRUCT
);
413 case WH_CALLWNDPROCRET
:
414 ArgumentLength
+= sizeof(CWPRETSTRUCT
);
417 case WH_SYSMSGFILTER
:
419 ArgumentLength
+= sizeof(MSG
);
421 case WH_FOREGROUNDIDLE
:
426 DPRINT1("Trying to call unsupported window hook %d\n", HookId
);
430 Argument
= IntCbAllocateMemory(ArgumentLength
);
431 if (NULL
== Argument
)
433 DPRINT1("HookProc callback failed: out of memory\n");
436 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Argument
;
437 Common
->HookId
= HookId
;
439 Common
->wParam
= wParam
;
440 Common
->lParam
= lParam
;
443 Common
->ModuleNameLength
= ModuleName
->Length
;
444 memcpy(Common
->ModuleName
, ModuleName
->Buffer
, ModuleName
->Length
);
445 Extra
= (PCHAR
) Common
->ModuleName
+ Common
->ModuleNameLength
;
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
;
464 *((CHAR
*) Extra
) = '\0';
465 Extra
+= sizeof(CHAR
);
469 *((WCHAR
*) Extra
) = L
'\0';
470 Extra
+= sizeof(WCHAR
);
473 if (! IS_ATOM(ClassName
.Buffer
))
475 RtlCopyMemory(Extra
, ClassName
.Buffer
, ClassName
.Length
);
476 CbtCreatewndExtra
->Cs
.lpszClass
=
477 (LPCWSTR
) MAKELONG(Extra
- (PCHAR
) CbtCreatewndExtra
, 1);
478 Extra
+= ClassName
.Length
;
481 *((CHAR
*) Extra
) = '\0';
483 *((WCHAR
*) Extra
) = L
'\0';
486 case HCBT_CLICKSKIPPED
:
487 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
488 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
491 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(RECTL
));
492 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
495 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CBTACTIVATESTRUCT
));
496 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
501 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(KBDLLHOOKSTRUCT
));
502 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
505 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MSLLHOOKSTRUCT
));
506 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
509 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
510 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
513 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPSTRUCT
));
514 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
516 case WH_CALLWNDPROCRET
:
517 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPRETSTRUCT
));
518 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
521 case WH_SYSMSGFILTER
:
523 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MSG
));
524 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
525 // DPRINT1("KHOOK Memory: %x\n",Common);
527 case WH_FOREGROUNDIDLE
:
533 ResultPointer
= NULL
;
534 ResultLength
= sizeof(LRESULT
);
538 Status
= KeUserModeCallback(USER32_CALLBACK_HOOKPROC
,
548 ProbeForRead(ResultPointer
, sizeof(LRESULT
), 1);
549 /* Simulate old behaviour: copy into our local buffer */
550 Result
= *(LRESULT
*)ResultPointer
;
552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
558 if (!NT_SUCCESS(Status
))
563 if (HookId
== WH_CBT
&& Code
== HCBT_CREATEWND
)
565 if (CbtCreatewndExtra
)
569 The parameters could have been changed, include the coordinates
570 and dimensions of the window. We copy it back.
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
;
578 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
586 if (Argument
) IntCbFreeMemory(Argument
);
592 // Events are notifications w/o results.
596 co_IntCallEventProc(HWINEVENTHOOK hook
,
607 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
608 ULONG ArgumentLength
, ResultLength
;
609 PVOID Argument
, ResultPointer
;
611 ArgumentLength
= sizeof(EVENTPROC_CALLBACK_ARGUMENTS
);
613 Argument
= IntCbAllocateMemory(ArgumentLength
);
614 if (NULL
== Argument
)
616 DPRINT1("EventProc callback failed: out of memory\n");
619 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Argument
;
621 Common
->event
= event
;
623 Common
->idObject
= idObject
;
624 Common
->idChild
= idChild
;
625 Common
->dwEventThread
= dwEventThread
;
626 Common
->dwmsEventTime
= dwmsEventTime
;
629 ResultPointer
= NULL
;
630 ResultLength
= sizeof(LRESULT
);
634 Status
= KeUserModeCallback(USER32_CALLBACK_EVENTPROC
,
642 IntCbFreeMemory(Argument
);
644 if (!NT_SUCCESS(Status
))
653 // Callback Load Menu and results.
657 co_IntCallLoadMenu( HINSTANCE hModule
,
658 PUNICODE_STRING pMenuName
)
662 PLOADMENU_CALLBACK_ARGUMENTS Common
;
663 ULONG ArgumentLength
, ResultLength
;
664 PVOID Argument
, ResultPointer
;
666 ArgumentLength
= sizeof(LOADMENU_CALLBACK_ARGUMENTS
);
668 ArgumentLength
+= pMenuName
->Length
+ sizeof(WCHAR
);
670 Argument
= IntCbAllocateMemory(ArgumentLength
);
671 if (NULL
== Argument
)
673 DPRINT1("LoadMenu callback failed: out of memory\n");
676 Common
= (PLOADMENU_CALLBACK_ARGUMENTS
) Argument
;
678 // Help Intersource check and MenuName is now 4 bytes + so zero it.
679 RtlZeroMemory(Common
, ArgumentLength
);
681 Common
->hModule
= hModule
;
682 if (pMenuName
->Length
)
683 RtlCopyMemory(&Common
->MenuName
, pMenuName
->Buffer
, pMenuName
->Length
);
685 RtlCopyMemory(&Common
->MenuName
, &pMenuName
->Buffer
, sizeof(WCHAR
));
687 ResultPointer
= NULL
;
688 ResultLength
= sizeof(LRESULT
);
692 Status
= KeUserModeCallback(USER32_CALLBACK_LOADMENU
,
700 Result
= *(LRESULT
*)ResultPointer
;
702 IntCbFreeMemory(Argument
);
704 if (!NT_SUCCESS(Status
))
709 return (HMENU
)Result
;
714 co_IntClientThreadSetup(VOID
)
717 ULONG ArgumentLength
, ResultLength
;
718 PVOID Argument
, ResultPointer
;
720 ArgumentLength
= ResultLength
= 0;
721 Argument
= ResultPointer
= NULL
;
725 Status
= KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP
,