1 /* $Id: window.c,v 1.16 2002/09/07 15:13:12 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
6 * FILE: subsys/win32k/ntuser/window.c
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 06-06-2001 CSH Created
11 /* INCLUDES ******************************************************************/
13 #include <ddk/ntddk.h>
14 #include <win32k/win32k.h>
15 #include <include/object.h>
16 #include <include/guicheck.h>
17 #include <include/window.h>
18 #include <include/class.h>
19 #include <include/error.h>
20 #include <include/winsta.h>
21 #include <include/winpos.h>
22 #include <include/callback.h>
23 #include <include/msgqueue.h>
24 #include <include/rect.h>
29 /* FUNCTIONS *****************************************************************/
32 NtUserGetAncestor(HWND hWnd
, UINT Flags
)
34 if (W32kIsDesktopWindow(hWnd
))
38 if (Flags
& GA_PARENT
)
40 PWINDOW_OBJECT Window
;
43 Window
= W32kGetWindowObject(hWnd
);
49 if (Window
->Parent
== NULL
)
51 W32kReleaseWindowObject(Window
);
54 hParent
= Window
->Parent
->Self
;
56 W32kReleaseWindowObject(Window
);
68 W32kSetFocusWindow(HWND hWnd
)
73 W32kIsChildWindow(HWND Parent
, HWND Child
)
75 PWINDOW_OBJECT BaseWindow
= W32kGetWindowObject(Child
);
76 PWINDOW_OBJECT Window
= BaseWindow
;
77 while (Window
!= NULL
&& Window
->Style
& WS_CHILD
)
79 if (Window
->Self
== Parent
)
81 W32kReleaseWindowObject(BaseWindow
);
84 Window
= Window
->Parent
;
86 W32kReleaseWindowObject(BaseWindow
);
91 W32kIsWindowVisible(HWND Wnd
)
93 PWINDOW_OBJECT BaseWindow
= W32kGetWindowObject(Wnd
);
94 PWINDOW_OBJECT Window
= BaseWindow
;
95 BOOLEAN Result
= FALSE
;
96 while (Window
!= NULL
&& Window
->Style
& WS_CHILD
)
98 if (!(Window
->Style
& WS_VISIBLE
))
100 W32kReleaseWindowObject(BaseWindow
);
103 Window
= Window
->Parent
;
105 if (Window
!= NULL
&& Window
->Style
& WS_VISIBLE
)
109 W32kReleaseWindowObject(BaseWindow
);
114 W32kIsDesktopWindow(HWND hWnd
)
116 PWINDOW_OBJECT WindowObject
;
118 WindowObject
= W32kGetWindowObject(hWnd
);
119 IsDesktop
= WindowObject
->Parent
== NULL
;
120 W32kReleaseWindowObject(WindowObject
);
124 HWND
W32kGetDesktopWindow()
126 return W32kGetActiveDesktop()->DesktopWindow
;
129 HWND
W32kGetParentWindow(HWND hWnd
)
131 return W32kGetWindowObject(hWnd
)->ParentHandle
;
135 W32kGetWindowObject(HWND hWnd
)
137 PWINDOW_OBJECT WindowObject
;
140 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->
144 (PVOID
*)&WindowObject
);
145 if (!NT_SUCCESS(Status
))
149 return(WindowObject
);
153 W32kReleaseWindowObject(PWINDOW_OBJECT Window
)
155 ObmDereferenceObject(Window
);
159 W32kGetClientRect(PWINDOW_OBJECT WindowObject
, PRECT Rect
)
161 Rect
->left
= Rect
->top
= 0;
162 Rect
->right
= WindowObject
->ClientRect
.right
- WindowObject
->ClientRect
.left
;
164 WindowObject
->ClientRect
.bottom
- WindowObject
->ClientRect
.top
;
168 W32kGetWindowRect(HWND hWnd
, LPRECT Rect
)
170 PWINDOW_OBJECT WindowObject
;
172 WindowObject
= W32kGetWindowObject(hWnd
);
173 if (WindowObject
== NULL
)
177 *Rect
= WindowObject
->WindowRect
;
178 if (WindowObject
->Style
& WS_CHILD
)
182 W32kReleaseWindowObject(WindowObject
);
187 NtUserGetWindowRect(HWND hWnd
, LPRECT Rect
)
189 return(W32kGetWindowRect(hWnd
, Rect
));
193 W32kGetActiveWindow(VOID
)
195 PUSER_MESSAGE_QUEUE Queue
;
196 Queue
= (PUSER_MESSAGE_QUEUE
)W32kGetActiveDesktop()->ActiveMessageQueue
;
203 return(Queue
->ActiveWindow
);
208 W32kGetFocusWindow(VOID
)
210 PUSER_MESSAGE_QUEUE Queue
;
211 Queue
= (PUSER_MESSAGE_QUEUE
)W32kGetActiveDesktop()->ActiveMessageQueue
;
218 return(Queue
->FocusWindow
);
224 W32kGetWindowProc(HWND Wnd
)
226 PWINDOW_OBJECT WindowObject
;
229 WindowObject
= W32kGetWindowObject(Wnd
);
230 WndProc
= WindowObject
->Class
->Class
.lpfnWndProc
;
231 W32kReleaseWindowObject(Wnd
);
238 return(STATUS_SUCCESS
);
242 CleanupWindowImpl(VOID
)
244 return(STATUS_SUCCESS
);
249 NtUserAlterWindowStyle(DWORD Unknown0
,
259 NtUserChildWindowFromPointEx(HWND Parent
,
270 W32kCreateDesktopWindow(PWINSTATION_OBJECT WindowStation
,
271 PWNDCLASS_OBJECT DesktopClass
,
272 ULONG Width
, ULONG Height
)
276 PWINDOW_OBJECT WindowObject
;
278 /* Create the window object. */
279 WindowObject
= (PWINDOW_OBJECT
)ObmCreateObject(WindowStation
->HandleTable
,
282 sizeof(WINDOW_OBJECT
));
289 * Fill out the structure describing it.
291 WindowObject
->Class
= DesktopClass
;
292 WindowObject
->ExStyle
= 0;
293 WindowObject
->Style
= WS_VISIBLE
;
296 WindowObject
->Width
= Width
;
297 WindowObject
->Height
= Height
;
298 WindowObject
->ParentHandle
= NULL
;
299 WindowObject
->Parent
= NULL
;
300 WindowObject
->Menu
= NULL
;
301 WindowObject
->Instance
= NULL
;
302 WindowObject
->Parameters
= NULL
;
303 WindowObject
->Self
= Handle
;
304 WindowObject
->MessageQueue
= NULL
;
305 WindowObject
->ExtraData
= NULL
;
306 WindowObject
->ExtraDataSize
= 0;
307 WindowObject
->WindowRect
.left
= 0;
308 WindowObject
->WindowRect
.top
= 0;
309 WindowObject
->WindowRect
.right
= Width
;
310 WindowObject
->WindowRect
.bottom
= Height
;
311 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
312 InitializeListHead(&WindowObject
->ChildrenListHead
);
314 WindowName
= ExAllocatePool(NonPagedPool
, sizeof(L
"DESKTOP"));
315 wcscpy(WindowName
, L
"DESKTOP");
316 RtlInitUnicodeString(&WindowObject
->WindowName
, WindowName
);
322 NtUserCreateWindowEx(DWORD dwExStyle
,
323 PUNICODE_STRING lpClassName
,
324 PUNICODE_STRING lpWindowName
,
336 PWINSTATION_OBJECT WinStaObject
;
337 PWNDCLASS_OBJECT ClassObject
;
338 PWINDOW_OBJECT WindowObject
;
339 PWINDOW_OBJECT ParentWindow
;
340 UNICODE_STRING WindowName
;
343 POINT MaxSize
, MaxPos
, MinTrack
, MaxTrack
;
347 DPRINT("NtUserCreateWindowEx\n");
349 /* Initialize gui state if necessary. */
352 if (!RtlCreateUnicodeString(&WindowName
, lpWindowName
->Buffer
))
354 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
358 if (hWndParent
!= NULL
)
360 ParentWindow
= W32kGetWindowObject(hWndParent
);
364 hWndParent
= PsGetWin32Thread()->Desktop
->DesktopWindow
;
365 ParentWindow
= W32kGetWindowObject(hWndParent
);
368 /* Check the class. */
369 Status
= ClassReferenceClassByNameOrAtom(&ClassObject
, lpClassName
->Buffer
);
370 if (!NT_SUCCESS(Status
))
372 RtlFreeUnicodeString(&WindowName
);
376 /* Check the window station. */
377 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
378 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
379 Status
= ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
383 if (!NT_SUCCESS(Status
))
385 RtlFreeUnicodeString(&WindowName
);
386 ObmDereferenceObject(ClassObject
);
387 DPRINT("Validation of window station handle (0x%X) failed\n",
388 PROCESS_WINDOW_STATION());
392 /* Create the window object. */
393 WindowObject
= (PWINDOW_OBJECT
)
394 ObmCreateObject(PsGetWin32Process()->WindowStation
->HandleTable
, &Handle
,
395 otWindow
, sizeof(WINDOW_OBJECT
));
396 DPRINT("Created object with handle %X\n", Handle
);
399 ObDereferenceObject(WinStaObject
);
400 ObmDereferenceObject(ClassObject
);
401 RtlFreeUnicodeString(&WindowName
);
402 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
405 ObDereferenceObject(WinStaObject
);
408 * Fill out the structure describing it.
410 WindowObject
->Class
= ClassObject
;
411 WindowObject
->ExStyle
= dwExStyle
;
412 WindowObject
->Style
= dwStyle
;
415 WindowObject
->Width
= nWidth
;
416 WindowObject
->Height
= nHeight
;
417 WindowObject
->ParentHandle
= hWndParent
;
418 WindowObject
->Menu
= hMenu
;
419 WindowObject
->Instance
= hInstance
;
420 WindowObject
->Parameters
= lpParam
;
421 WindowObject
->Self
= Handle
;
422 WindowObject
->MessageQueue
= PsGetWin32Thread()->MessageQueue
;
423 WindowObject
->Parent
= ParentWindow
;
424 InsertHeadList(&ParentWindow
->ChildrenListHead
,
425 &WindowObject
->SiblingListEntry
);
426 InitializeListHead(&WindowObject
->ChildrenListHead
);
427 InitializeListHead(&WindowObject
->PropListHead
);
429 RtlInitUnicodeString(&WindowObject
->WindowName
, WindowName
.Buffer
);
430 RtlFreeUnicodeString(&WindowName
);
432 if (ClassObject
->Class
.cbWndExtra
!= 0)
434 WindowObject
->ExtraData
=
435 ExAllocatePool(PagedPool
,
436 ClassObject
->Class
.cbWndExtra
* sizeof(DWORD
));
437 WindowObject
->ExtraDataSize
= ClassObject
->Class
.cbWndExtra
;
441 WindowObject
->ExtraData
= NULL
;
442 WindowObject
->ExtraDataSize
= 0;
445 /* Correct the window style. */
446 if (!(dwStyle
& WS_CHILD
))
448 WindowObject
->Style
|= WS_CLIPSIBLINGS
;
449 if (!(dwStyle
& WS_POPUP
))
451 WindowObject
->Style
|= WS_CAPTION
;
452 /* FIXME: Note the window needs a size. */
456 /* Insert the window into the process's window list. */
457 ExAcquireFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock
);
458 InsertTailList (&PsGetWin32Thread()->WindowListHead
,
459 &WindowObject
->ThreadListEntry
);
460 ExReleaseFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock
);
463 * Insert the window into the list of windows associated with the thread's
466 InsertTailList(&PsGetWin32Thread()->Desktop
->WindowListHead
,
467 &WindowObject
->DesktopListEntry
);
469 /* FIXME: Maybe allocate a DCE for this window. */
471 /* Initialize the window dimensions. */
472 WindowObject
->WindowRect
.left
= x
;
473 WindowObject
->WindowRect
.top
= y
;
474 WindowObject
->WindowRect
.right
= x
+ nWidth
;
475 WindowObject
->WindowRect
.bottom
= y
+ nHeight
;
476 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
479 * Get the size and position of the window.
481 if ((dwStyle
& WS_THICKFRAME
) || !(dwStyle
& (WS_POPUP
| WS_CHILD
)))
483 WinPosGetMinMaxInfo(WindowObject
, &MaxSize
, &MaxPos
, &MinTrack
,
485 x
= min(MaxSize
.x
, y
);
486 y
= min(MaxSize
.y
, y
);
487 x
= max(MinTrack
.x
, x
);
488 y
= max(MinTrack
.y
, y
);
491 WindowObject
->WindowRect
.left
= x
;
492 WindowObject
->WindowRect
.top
= y
;
493 WindowObject
->WindowRect
.right
= x
+ nWidth
;
494 WindowObject
->WindowRect
.bottom
= y
+ nHeight
;
495 WindowObject
->ClientRect
= WindowObject
->WindowRect
;
497 /* FIXME: Initialize the window menu. */
499 /* Send a NCCREATE message. */
500 Cs
.lpCreateParams
= lpParam
;
501 Cs
.hInstance
= hInstance
;
503 Cs
.hwndParent
= hWndParent
;
509 Cs
.lpszName
= lpWindowName
->Buffer
;
510 Cs
.lpszClass
= lpClassName
->Buffer
;
511 Cs
.dwExStyle
= dwExStyle
;
512 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
513 Result
= W32kSendNCCREATEMessage(WindowObject
->Self
, &Cs
);
516 /* FIXME: Cleanup. */
517 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
521 /* Calculate the non-client size. */
522 MaxPos
.x
= WindowObject
->WindowRect
.left
;
523 MaxPos
.y
= WindowObject
->WindowRect
.top
;
524 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
525 Result
= WinPosGetNonClientSize(WindowObject
->Self
,
526 &WindowObject
->WindowRect
,
527 &WindowObject
->ClientRect
);
528 W32kOffsetRect(&WindowObject
->WindowRect
,
529 MaxPos
.x
- WindowObject
->WindowRect
.left
,
530 MaxPos
.y
- WindowObject
->WindowRect
.top
);
532 /* Send the CREATE message. */
533 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
534 Result
= W32kSendCREATEMessage(WindowObject
->Self
, &Cs
);
535 if (Result
== (LRESULT
)-1)
537 /* FIXME: Cleanup. */
538 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
542 /* Send move and size messages. */
543 if (!(WindowObject
->Flags
& WINDOWOBJECT_NEED_SIZE
))
548 MAKE_LONG(WindowObject
->ClientRect
.right
-
549 WindowObject
->ClientRect
.left
,
550 WindowObject
->ClientRect
.bottom
-
551 WindowObject
->ClientRect
.top
);
552 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
553 W32kCallWindowProc(NULL
, WindowObject
->Self
, WM_SIZE
, SIZE_RESTORED
,
556 MAKE_LONG(WindowObject
->ClientRect
.left
,
557 WindowObject
->ClientRect
.top
);
558 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
559 W32kCallWindowProc(NULL
, WindowObject
->Self
, WM_MOVE
, 0, lParam
);
562 /* Show or maybe minimize or maximize the window. */
563 if (WindowObject
->Style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
568 SwFlag
= (WindowObject
->Style
& WS_MINIMIZE
) ? SW_MINIMIZE
:
570 WinPosMinMaximize(WindowObject
, SwFlag
, &NewPos
);
572 ((WindowObject
->Style
& WS_CHILD
) || W32kGetActiveWindow()) ?
573 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
:
574 SWP_NOZORDER
| SWP_FRAMECHANGED
;
575 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
576 WinPosSetWindowPos(WindowObject
->Self
, 0, NewPos
.left
, NewPos
.top
,
577 NewPos
.right
, NewPos
.bottom
, SwFlag
);
580 /* Notify the parent window of a new child. */
581 if ((WindowObject
->Style
& WS_CHILD
) ||
582 (!(WindowObject
->ExStyle
& WS_EX_NOPARENTNOTIFY
)))
584 DPRINT("NtUserCreateWindow(): About to notify parent\n");
585 W32kCallWindowProc(NULL
, WindowObject
->Parent
->Self
,
587 MAKEWPARAM(WM_CREATE
, WindowObject
->IDMenu
),
588 (LPARAM
)WindowObject
->Self
);
591 if (dwStyle
& WS_VISIBLE
)
593 DPRINT("NtUserCreateWindow(): About to show window\n");
594 WinPosShowWindow(WindowObject
->Self
, dwShowMode
);
597 DPRINT("NtUserCreateWindow(): = %X\n", Handle
);
598 return((HWND
)Handle
);
602 NtUserDeferWindowPos(HDWP WinPosInfo
,
617 NtUserDestroyWindow(HWND Wnd
)
625 NtUserEndDeferWindowPosEx(DWORD Unknown0
,
634 NtUserFillWindow(DWORD Unknown0
,
645 NtUserFindWindowEx(HWND hwndParent
,
647 PUNICODE_STRING ucClassName
,
648 PUNICODE_STRING ucWindowName
,
654 PWINDOW_OBJECT windowObject
;
655 PLIST_ENTRY currentEntry
;
656 PWNDCLASS_OBJECT classObject
;
660 status
= ClassReferenceClassByNameOrAtom(&classObject
, ucClassName
->Buffer
);
661 if (!NT_SUCCESS(status
))
666 ExAcquireFastMutexUnsafe (&PsGetWin32Process()->WindowListLock
);
667 currentEntry
= PsGetWin32Process()->WindowListHead
.Flink
;
668 while (currentEntry
!= &PsGetWin32Process()->WindowListHead
)
670 windowObject
= CONTAINING_RECORD (currentEntry
, WINDOW_OBJECT
,
673 if (classObject
== windowObject
->Class
&&
674 RtlCompareUnicodeString (ucWindowName
, &windowObject
->WindowName
,
677 ObmCreateHandle(PsGetWin32Process()->HandleTable
,
680 ExReleaseFastMutexUnsafe (&PsGetWin32Process()->WindowListLock
);
681 ObmDereferenceObject (classObject
);
685 currentEntry
= currentEntry
->Flink
;
687 ExReleaseFastMutexUnsafe (&PsGetWin32Process()->WindowListLock
);
689 ObmDereferenceObject (classObject
);
696 NtUserFlashWindowEx(DWORD Unknown0
)
704 NtUserGetForegroundWindow(VOID
)
712 NtUserGetInternalWindowPos(DWORD Unknown0
,
722 NtUserGetOpenClipboardWindow(VOID
)
730 NtUserGetWindowDC(DWORD Unknown0
)
738 NtUserGetWindowPlacement(DWORD Unknown0
,
747 NtUserInternalGetWindowText(DWORD Unknown0
,
757 NtUserLockWindowUpdate(DWORD Unknown0
)
765 NtUserMoveWindow(DWORD Unknown0
,
778 NtUserQueryWindow(DWORD Unknown0
,
787 NtUserRealChildWindowFromPoint(DWORD Unknown0
,
797 NtUserRedrawWindow(DWORD Unknown0
,
808 NtUserRegisterWindowMessage(LPCWSTR MessageName
)
816 NtUserScrollWindowEx(DWORD Unknown0
,
831 NtUserSetActiveWindow(DWORD Unknown0
)
839 NtUserSetImeOwnerWindow(DWORD Unknown0
,
848 NtUserSetInternalWindowPos(DWORD Unknown0
,
860 NtUserSetLayeredWindowAttributes(DWORD Unknown0
,
871 NtUserSetLogonNotifyWindow(DWORD Unknown0
)
879 NtUserSetShellWindowEx(DWORD Unknown0
,
888 NtUserSetWindowFNID(DWORD Unknown0
,
897 NtUserGetWindowLong(HWND hWnd
, DWORD Index
)
899 PWINDOW_OBJECT WindowObject
;
903 DPRINT("NtUserGetWindowLong(hWnd %X, Index %d)\n", hWnd
, Index
);
908 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->HandleTable
,
911 (PVOID
*)&WindowObject
);
912 if (!NT_SUCCESS(Status
))
914 DPRINT("NtUserGetWindowLong(): Bad handle.\n");
922 Result
= (DWORD
)WindowObject
->ExStyle
;
928 Result
= (DWORD
)WindowObject
->Style
;
934 Result
= (DWORD
)WindowObject
->Class
->Class
.lpfnWndProc
;
940 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index
);
946 ObmDereferenceObject(WindowObject
);
947 DPRINT("NtUserGetWindowLong(): %X\n", Result
);
952 NtUserSetWindowLong(DWORD Unknown0
,
963 NtUserSetWindowPlacement(DWORD Unknown0
,
972 NtUserSetWindowPos(DWORD Unknown0
,
986 NtUserSetWindowRgn(DWORD Unknown0
,
996 NtUserSetWindowWord(DWORD Unknown0
,
1006 NtUserShowWindow(HWND hWnd
,
1011 return(WinPosShowWindow(hWnd
, nCmdShow
));
1015 NtUserShowWindowAsync(DWORD Unknown0
,
1024 NtUserUpdateLayeredWindow(DWORD Unknown0
,
1040 NtUserWindowFromPoint(DWORD Unknown0
,