2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/wndproc.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
28 * 06-06-2001 CSH Created
29 * NOTES: Please use the Callback Memory Management functions for
30 * callbacks to make sure, the memory is freed on thread
34 /* INCLUDES ******************************************************************/
41 /* CALLBACK MEMORY MANAGEMENT ************************************************/
43 typedef struct _INT_CALLBACK_HEADER
45 /* list entry in the THREADINFO structure */
48 INT_CALLBACK_HEADER
, *PINT_CALLBACK_HEADER
;
51 IntCbAllocateMemory(ULONG Size
)
53 PINT_CALLBACK_HEADER Mem
;
54 PTHREADINFO W32Thread
;
56 if(!(Mem
= ExAllocatePoolWithTag(PagedPool
, Size
+ sizeof(INT_CALLBACK_HEADER
),
62 W32Thread
= PsGetCurrentThreadWin32Thread();
65 /* insert the callback memory into the thread's callback list */
67 InsertTailList(&W32Thread
->W32CallbackListHead
, &Mem
->ListEntry
);
73 IntCbFreeMemory(PVOID Data
)
75 PINT_CALLBACK_HEADER Mem
;
76 PTHREADINFO W32Thread
;
80 Mem
= ((PINT_CALLBACK_HEADER
)Data
- 1);
82 W32Thread
= PsGetCurrentThreadWin32Thread();
85 /* remove the memory block from the thread's callback list */
86 RemoveEntryList(&Mem
->ListEntry
);
89 ExFreePoolWithTag(Mem
, TAG_CALLBACK
);
93 IntCleanupThreadCallbacks(PTHREADINFO W32Thread
)
95 PLIST_ENTRY CurrentEntry
;
96 PINT_CALLBACK_HEADER Mem
;
98 while (!IsListEmpty(&W32Thread
->W32CallbackListHead
))
100 CurrentEntry
= RemoveHeadList(&W32Thread
->W32CallbackListHead
);
101 Mem
= CONTAINING_RECORD(CurrentEntry
, INT_CALLBACK_HEADER
,
111 // Pass the Current Window handle and pointer to the Client Callback.
112 // This will help user space programs speed up read access with the window object.
115 IntSetTebWndCallback (HWND
* hWnd
, PVOID
* pWnd
)
118 PWINDOW_OBJECT Window
= UserGetWindowObject(*hWnd
);
119 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
121 *hWnd
= ClientInfo
->CallbackWnd
.hWnd
;
122 *pWnd
= ClientInfo
->CallbackWnd
.pvWnd
;
124 ClientInfo
->CallbackWnd
.hWnd
= hWndS
;
125 ClientInfo
->CallbackWnd
.pvWnd
= DesktopHeapAddressToUser(Window
->Wnd
);
129 IntRestoreTebWndCallback (HWND hWnd
, PVOID pWnd
)
131 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
133 ClientInfo
->CallbackWnd
.hWnd
= hWnd
;
134 ClientInfo
->CallbackWnd
.pvWnd
= pWnd
;
137 /* FUNCTIONS *****************************************************************/
140 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback
,
143 ULONG_PTR CompletionCallbackContext
,
146 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments
;
147 PVOID ResultPointer
, pWnd
;
151 Arguments
.Callback
= CompletionCallback
;
152 Arguments
.Wnd
= hWnd
;
154 Arguments
.Context
= CompletionCallbackContext
;
155 Arguments
.Result
= Result
;
157 IntSetTebWndCallback (&hWnd
, &pWnd
);
161 Status
= KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC
,
163 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS
),
169 IntRestoreTebWndCallback (hWnd
, pWnd
);
171 if (!NT_SUCCESS(Status
))
179 co_IntCallWindowProc(WNDPROC Proc
,
185 INT lParamBufferSize
)
187 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments
;
188 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments
;
190 PVOID ResultPointer
, pWnd
;
192 ULONG ArgumentLength
;
195 if (0 < lParamBufferSize
)
197 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
) + lParamBufferSize
;
198 Arguments
= IntCbAllocateMemory(ArgumentLength
);
199 if (NULL
== Arguments
)
201 DPRINT1("Unable to allocate buffer for window proc callback\n");
204 RtlMoveMemory((PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
205 (PVOID
) lParam
, lParamBufferSize
);
209 Arguments
= &StackArguments
;
210 ArgumentLength
= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
);
212 Arguments
->Proc
= Proc
;
213 Arguments
->IsAnsiProc
= IsAnsiProc
;
214 Arguments
->Wnd
= Wnd
;
215 Arguments
->Msg
= Message
;
216 Arguments
->wParam
= wParam
;
217 Arguments
->lParam
= lParam
;
218 Arguments
->lParamBufferSize
= lParamBufferSize
;
219 ResultPointer
= NULL
;
220 ResultLength
= ArgumentLength
;
222 IntSetTebWndCallback (&Wnd
, &pWnd
);
226 Status
= KeUserModeCallback(USER32_CALLBACK_WINDOWPROC
,
234 /* Simulate old behaviour: copy into our local buffer */
235 RtlMoveMemory(Arguments
, ResultPointer
, ArgumentLength
);
237 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
239 Status
= _SEH2_GetExceptionCode();
245 IntRestoreTebWndCallback (Wnd
, pWnd
);
247 if (!NT_SUCCESS(Status
))
249 if (0 < lParamBufferSize
)
251 IntCbFreeMemory(Arguments
);
255 Result
= Arguments
->Result
;
257 if (0 < lParamBufferSize
)
259 RtlMoveMemory((PVOID
) lParam
,
260 (PVOID
) ((char *) Arguments
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)),
262 IntCbFreeMemory(Arguments
);
269 co_IntLoadSysMenuTemplate()
276 ResultPointer
= NULL
;
277 ResultLength
= sizeof(LRESULT
);
281 Status
= KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE
,
287 /* Simulate old behaviour: copy into our local buffer */
288 Result
= *(LRESULT
*)ResultPointer
;
292 if (!NT_SUCCESS(Status
))
296 return (HMENU
)Result
;
300 co_IntLoadDefaultCursors(VOID
)
306 BOOL DefaultCursor
= TRUE
;
308 ResultPointer
= NULL
;
309 ResultLength
= sizeof(LRESULT
);
313 Status
= KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS
,
319 /* Simulate old behaviour: copy into our local buffer */
320 Result
= *(LRESULT
*)ResultPointer
;
324 if (!NT_SUCCESS(Status
))
332 co_IntCallHookProc(INT HookId
,
338 PUNICODE_STRING ModuleName
)
340 ULONG ArgumentLength
;
346 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
347 CBT_CREATEWNDW
*CbtCreateWnd
=NULL
;
349 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
350 UNICODE_STRING WindowName
;
351 UNICODE_STRING ClassName
;
352 PANSI_STRING asWindowName
;
353 PANSI_STRING asClassName
;
355 ArgumentLength
= sizeof(HOOKPROC_CALLBACK_ARGUMENTS
) - sizeof(WCHAR
)
356 + ModuleName
->Length
;
363 CbtCreateWnd
= (CBT_CREATEWNDW
*) lParam
;
364 ArgumentLength
+= sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
);
366 asWindowName
= (PANSI_STRING
)&WindowName
;
367 asClassName
= (PANSI_STRING
)&ClassName
;
371 RtlInitAnsiString(asWindowName
, (PCSZ
)CbtCreateWnd
->lpcs
->lpszName
);
372 ArgumentLength
+= WindowName
.Length
+ sizeof(CHAR
);
376 RtlInitUnicodeString(&WindowName
, CbtCreateWnd
->lpcs
->lpszName
);
377 ArgumentLength
+= WindowName
.Length
+ sizeof(WCHAR
);
380 if (! IS_ATOM(CbtCreateWnd
->lpcs
->lpszClass
))
384 RtlInitAnsiString(asClassName
, (PCSZ
)CbtCreateWnd
->lpcs
->lpszClass
);
385 ArgumentLength
+= ClassName
.Length
+ sizeof(CHAR
);
389 RtlInitUnicodeString(&ClassName
, CbtCreateWnd
->lpcs
->lpszClass
);
390 ArgumentLength
+= ClassName
.Length
+ sizeof(WCHAR
);
396 ArgumentLength
+= sizeof(RECTL
);
399 ArgumentLength
+= sizeof(CBTACTIVATESTRUCT
);
401 case HCBT_CLICKSKIPPED
:
402 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
405 case HCBT_KEYSKIPPED
:
408 case HCBT_SYSCOMMAND
:
409 /* These types pass through. */
410 case HCBT_DESTROYWND
:
414 DPRINT1("Trying to call unsupported CBT hook %d\n", Code
);
419 ArgumentLength
+= sizeof(KBDLLHOOKSTRUCT
);
422 ArgumentLength
+= sizeof(MSLLHOOKSTRUCT
);
425 ArgumentLength
+= sizeof(MOUSEHOOKSTRUCT
);
428 ArgumentLength
+= sizeof(CWPSTRUCT
);
430 case WH_CALLWNDPROCRET
:
431 ArgumentLength
+= sizeof(CWPRETSTRUCT
);
434 case WH_SYSMSGFILTER
:
436 ArgumentLength
+= sizeof(MSG
);
438 case WH_FOREGROUNDIDLE
:
443 DPRINT1("Trying to call unsupported window hook %d\n", HookId
);
447 Argument
= IntCbAllocateMemory(ArgumentLength
);
448 if (NULL
== Argument
)
450 DPRINT1("HookProc callback failed: out of memory\n");
453 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Argument
;
454 Common
->HookId
= HookId
;
456 Common
->wParam
= wParam
;
457 Common
->lParam
= lParam
;
460 Common
->ModuleNameLength
= ModuleName
->Length
;
461 memcpy(Common
->ModuleName
, ModuleName
->Buffer
, ModuleName
->Length
);
462 Extra
= (PCHAR
) Common
->ModuleName
+ Common
->ModuleNameLength
;
470 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
471 CbtCreatewndExtra
= (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
) Extra
;
472 RtlCopyMemory( &CbtCreatewndExtra
->Cs
, CbtCreateWnd
->lpcs
, sizeof(CREATESTRUCTW
) );
473 CbtCreatewndExtra
->WndInsertAfter
= CbtCreateWnd
->hwndInsertAfter
;
474 Extra
= (PCHAR
) (CbtCreatewndExtra
+ 1);
475 RtlCopyMemory(Extra
, WindowName
.Buffer
, WindowName
.Length
);
476 CbtCreatewndExtra
->Cs
.lpszName
= (LPCWSTR
) (Extra
- (PCHAR
) CbtCreatewndExtra
);
477 CbtCreatewndExtra
->Cs
.lpszClass
= ClassName
.Buffer
;
478 Extra
+= WindowName
.Length
;
481 *((CHAR
*) Extra
) = '\0';
482 Extra
+= sizeof(CHAR
);
486 *((WCHAR
*) Extra
) = L
'\0';
487 Extra
+= sizeof(WCHAR
);
490 if (! IS_ATOM(ClassName
.Buffer
))
492 RtlCopyMemory(Extra
, ClassName
.Buffer
, ClassName
.Length
);
493 CbtCreatewndExtra
->Cs
.lpszClass
=
494 (LPCWSTR
) MAKELONG(Extra
- (PCHAR
) CbtCreatewndExtra
, 1);
495 Extra
+= ClassName
.Length
;
498 *((CHAR
*) Extra
) = '\0';
500 *((WCHAR
*) Extra
) = L
'\0';
503 case HCBT_CLICKSKIPPED
:
504 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
505 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
508 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(RECTL
));
509 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
512 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CBTACTIVATESTRUCT
));
513 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
518 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(KBDLLHOOKSTRUCT
));
519 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
522 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MSLLHOOKSTRUCT
));
523 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
526 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MOUSEHOOKSTRUCT
));
527 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
530 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPSTRUCT
));
531 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
533 case WH_CALLWNDPROCRET
:
534 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(CWPRETSTRUCT
));
535 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
538 case WH_SYSMSGFILTER
:
540 RtlCopyMemory(Extra
, (PVOID
) lParam
, sizeof(MSG
));
541 Common
->lParam
= (LPARAM
) (Extra
- (PCHAR
) Common
);
542 // DPRINT1("KHOOK Memory: %x\n",Common);
544 case WH_FOREGROUNDIDLE
:
550 ResultPointer
= NULL
;
551 ResultLength
= sizeof(LRESULT
);
555 Status
= KeUserModeCallback(USER32_CALLBACK_HOOKPROC
,
565 ProbeForRead(ResultPointer
, sizeof(LRESULT
), 1);
566 /* Simulate old behaviour: copy into our local buffer */
567 Result
= *(LRESULT
*)ResultPointer
;
569 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
575 if (!NT_SUCCESS(Status
))
580 if (HookId
== WH_CBT
&& Code
== HCBT_CREATEWND
)
582 if (CbtCreatewndExtra
)
586 The parameters could have been changed, include the coordinates
587 and dimensions of the window. We copy it back.
589 CbtCreateWnd
->hwndInsertAfter
= CbtCreatewndExtra
->WndInsertAfter
;
590 CbtCreateWnd
->lpcs
->x
= CbtCreatewndExtra
->Cs
.x
;
591 CbtCreateWnd
->lpcs
->y
= CbtCreatewndExtra
->Cs
.y
;
592 CbtCreateWnd
->lpcs
->cx
= CbtCreatewndExtra
->Cs
.cx
;
593 CbtCreateWnd
->lpcs
->cy
= CbtCreatewndExtra
->Cs
.cy
;
595 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
603 if (Argument
) IntCbFreeMemory(Argument
);
609 // Events are notifications w/o results.
613 co_IntCallEventProc(HWINEVENTHOOK hook
,
624 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
625 ULONG ArgumentLength
, ResultLength
;
626 PVOID Argument
, ResultPointer
;
628 ArgumentLength
= sizeof(EVENTPROC_CALLBACK_ARGUMENTS
);
630 Argument
= IntCbAllocateMemory(ArgumentLength
);
631 if (NULL
== Argument
)
633 DPRINT1("EventProc callback failed: out of memory\n");
636 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Argument
;
638 Common
->event
= event
;
640 Common
->idObject
= idObject
;
641 Common
->idChild
= idChild
;
642 Common
->dwEventThread
= dwEventThread
;
643 Common
->dwmsEventTime
= dwmsEventTime
;
646 ResultPointer
= NULL
;
647 ResultLength
= sizeof(LRESULT
);
651 Status
= KeUserModeCallback(USER32_CALLBACK_EVENTPROC
,
659 IntCbFreeMemory(Argument
);
661 if (!NT_SUCCESS(Status
))