Changes for multiple window support
[reactos.git] / reactos / subsys / win32k / ntuser / window.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: window.c,v 1.64 2003/07/17 07:49:15 gvg Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Windows
24 * FILE: subsys/win32k/ntuser/window.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * REVISION HISTORY:
27 * 06-06-2001 CSH Created
28 */
29 /* INCLUDES ******************************************************************/
30
31 #include <ddk/ntddk.h>
32 #include <internal/safe.h>
33 #include <win32k/win32k.h>
34 #include <include/object.h>
35 #include <include/guicheck.h>
36 #include <include/window.h>
37 #include <include/class.h>
38 #include <include/error.h>
39 #include <include/winsta.h>
40 #include <include/winpos.h>
41 #include <include/callback.h>
42 #include <include/msgqueue.h>
43 #include <include/rect.h>
44 #include <include/dce.h>
45 #include <include/paint.h>
46 #include <include/painting.h>
47 #include <include/scroll.h>
48 #include <include/vis.h>
49
50 #define NDEBUG
51 #include <win32k/debug1.h>
52 #include <debug.h>
53
54 #define TAG_WNAM TAG('W', 'N', 'A', 'M')
55
56 typedef struct _REGISTERED_MESSAGE
57 {
58 LIST_ENTRY ListEntry;
59 WCHAR MessageName[1];
60 } REGISTERED_MESSAGE, *PREGISTERED_MESSAGE;
61
62 static LIST_ENTRY RegisteredMessageListHead;
63
64 #define REGISTERED_MESSAGE_MIN 0xc000
65 #define REGISTERED_MESSAGE_MAX 0xffff
66
67 /* FUNCTIONS *****************************************************************/
68
69 HWND STDCALL
70 NtUserGetAncestor(HWND hWnd, UINT Flags)
71 {
72 if (W32kIsDesktopWindow(hWnd))
73 {
74 return(NULL);
75 }
76 if (Flags & GA_PARENT)
77 {
78 PWINDOW_OBJECT Window;
79 HWND hParent;
80
81 Window = W32kGetWindowObject(hWnd);
82 if (Window == NULL)
83 {
84 return(NULL);
85 }
86
87 if (Window->Parent == NULL)
88 {
89 W32kReleaseWindowObject(Window);
90 }
91
92 hParent = Window->Parent->Self;
93
94 W32kReleaseWindowObject(Window);
95
96 return(hParent);
97 }
98 else if (Flags & GA_ROOT)
99 {
100 PWINDOW_OBJECT Window;
101 PWINDOW_OBJECT pChainEnumerator;
102 HWND hRoot;
103
104 Window = W32kGetWindowObject(hWnd);
105 if(Window == NULL)
106 {
107 return(NULL);
108 }
109
110 pChainEnumerator = Window;
111 while(pChainEnumerator->Parent != NULL)
112 {
113 pChainEnumerator = pChainEnumerator->Parent;
114 }
115
116 hRoot = pChainEnumerator->Self;
117 W32kReleaseWindowObject(Window);
118
119 return(hRoot);
120 }
121 else
122 {
123 UNIMPLEMENTED;
124 return(NULL);
125 }
126 }
127
128 HWND FASTCALL
129 W32kSetFocusWindow(HWND hWnd)
130 {
131 PUSER_MESSAGE_QUEUE OldMessageQueue;
132 PDESKTOP_OBJECT DesktopObject;
133 PWINDOW_OBJECT WindowObject;
134 HWND hWndOldFocus;
135
136 DPRINT("W32kSetFocusWindow(hWnd 0x%x)\n", hWnd);
137
138 if (hWnd != (HWND)0)
139 {
140 WindowObject = W32kGetWindowObject(hWnd);
141 if (!WindowObject)
142 {
143 DPRINT("Bad window handle 0x%x\n", hWnd);
144 SetLastWin32Error(ERROR_INVALID_HANDLE);
145 return (HWND)0;
146 }
147 }
148 else
149 {
150 WindowObject = NULL;
151 }
152
153 DesktopObject = W32kGetActiveDesktop();
154 if (!DesktopObject)
155 {
156 DPRINT("No active desktop\n");
157 if (WindowObject != NULL)
158 {
159 W32kReleaseWindowObject(WindowObject);
160 }
161 SetLastWin32Error(ERROR_INVALID_HANDLE);
162 return (HWND)0;
163 }
164
165 hWndOldFocus = (HWND)0;
166 OldMessageQueue = (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue;
167 if (OldMessageQueue != NULL)
168 {
169 hWndOldFocus = OldMessageQueue->FocusWindow;
170 }
171
172 if (WindowObject != NULL)
173 {
174 WindowObject->MessageQueue->FocusWindow = hWnd;
175 (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue =
176 WindowObject->MessageQueue;
177 W32kReleaseWindowObject(WindowObject);
178 }
179 else
180 {
181 (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue = NULL;
182 }
183
184 DPRINT("hWndOldFocus = 0x%x\n", hWndOldFocus);
185
186 return hWndOldFocus;
187 }
188
189 BOOL FASTCALL
190 W32kIsChildWindow(HWND Parent, HWND Child)
191 {
192 PWINDOW_OBJECT BaseWindow = W32kGetWindowObject(Child);
193 PWINDOW_OBJECT Window = BaseWindow;
194 while (Window != NULL && Window->Style & WS_CHILD)
195 {
196 if (Window->Self == Parent)
197 {
198 W32kReleaseWindowObject(BaseWindow);
199 return(TRUE);
200 }
201 Window = Window->Parent;
202 }
203 W32kReleaseWindowObject(BaseWindow);
204 return(FALSE);
205 }
206
207 BOOL FASTCALL
208 W32kIsWindowVisible(HWND Wnd)
209 {
210 PWINDOW_OBJECT BaseWindow = W32kGetWindowObject(Wnd);
211 PWINDOW_OBJECT Window = BaseWindow;
212 BOOLEAN Result = FALSE;
213 while (Window != NULL && Window->Style & WS_CHILD)
214 {
215 if (!(Window->Style & WS_VISIBLE))
216 {
217 W32kReleaseWindowObject(BaseWindow);
218 return(FALSE);
219 }
220 Window = Window->Parent;
221 }
222 if (Window != NULL && Window->Style & WS_VISIBLE)
223 {
224 Result = TRUE;
225 }
226 W32kReleaseWindowObject(BaseWindow);
227 return(Result);
228 }
229
230 BOOL FASTCALL
231 W32kIsDesktopWindow(HWND hWnd)
232 {
233 PWINDOW_OBJECT WindowObject;
234 BOOL IsDesktop;
235 WindowObject = W32kGetWindowObject(hWnd);
236 IsDesktop = WindowObject->Parent == NULL;
237 W32kReleaseWindowObject(WindowObject);
238 return(IsDesktop);
239 }
240
241 HWND FASTCALL W32kGetDesktopWindow(VOID)
242 {
243 return W32kGetActiveDesktop()->DesktopWindow;
244 }
245
246 HWND FASTCALL W32kGetParentWindow(HWND hWnd)
247 {
248 return W32kGetWindowObject(hWnd)->ParentHandle;
249 }
250
251 PWINDOW_OBJECT FASTCALL
252 W32kGetWindowObject(HWND hWnd)
253 {
254 PWINDOW_OBJECT WindowObject;
255 NTSTATUS Status;
256 Status =
257 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
258 HandleTable,
259 hWnd,
260 otWindow,
261 (PVOID*)&WindowObject);
262 if (!NT_SUCCESS(Status))
263 {
264 return(NULL);
265 }
266 return(WindowObject);
267 }
268
269 VOID FASTCALL
270 W32kReleaseWindowObject(PWINDOW_OBJECT Window)
271 {
272 ObmDereferenceObject(Window);
273 }
274
275 /*!
276 * Internal function.
277 * Returns client window rectangle relative to the upper-left corner of client area.
278 *
279 * \note Does not check the validity of the parameters
280 */
281 VOID FASTCALL
282 W32kGetClientRect(PWINDOW_OBJECT WindowObject, PRECT Rect)
283 {
284 ASSERT( WindowObject );
285 ASSERT( Rect );
286
287 Rect->left = Rect->top = 0;
288 Rect->right = WindowObject->ClientRect.right - WindowObject->ClientRect.left;
289 Rect->bottom =
290 WindowObject->ClientRect.bottom - WindowObject->ClientRect.top;
291 }
292
293 /*!
294 * Internal Function.
295 * Return the dimension of the window in the screen coordinates.
296 */
297 BOOL STDCALL
298 W32kGetWindowRect(HWND hWnd, LPRECT Rect)
299 {
300 PWINDOW_OBJECT WindowObject;
301
302 ASSERT(NULL != Rect);
303
304 WindowObject = W32kGetWindowObject(hWnd);
305 if (WindowObject == NULL)
306 {
307 return FALSE;
308 }
309 *Rect = WindowObject->WindowRect;
310 W32kReleaseWindowObject(WindowObject);
311
312 return TRUE;
313 }
314
315 /*!
316 * Return the dimension of the window in the screen coordinates.
317 * \param hWnd window handle.
318 * \param Rect pointer to the buffer where the coordinates are returned.
319 */
320 BOOL STDCALL
321 NtUserGetWindowRect(HWND hWnd, LPRECT Rect)
322 {
323 RECT SafeRect;
324 BOOL bRet;
325
326 bRet = W32kGetWindowRect(hWnd, &SafeRect);
327 if (! NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
328 {
329 return FALSE;
330 }
331
332 return bRet;
333 }
334
335 /*!
336 * Returns client window rectangle relative to the upper-left corner of client area.
337 *
338 * \param hWnd window handle.
339 * \param Rect pointer to the buffer where the coordinates are returned.
340 *
341 */
342 BOOL STDCALL
343 NtUserGetClientRect(HWND hWnd, LPRECT Rect)
344 {
345 PWINDOW_OBJECT WindowObject;
346 RECT SafeRect;
347
348 WindowObject = W32kGetWindowObject(hWnd);
349 if (WindowObject == NULL)
350 {
351 return(FALSE);
352 }
353 W32kGetClientRect(WindowObject, &SafeRect);
354 if (! NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
355 {
356 W32kReleaseWindowObject(WindowObject);
357 return(FALSE);
358 }
359
360 W32kReleaseWindowObject(WindowObject);
361 return(TRUE);
362 }
363
364 HWND FASTCALL
365 W32kGetActiveWindow(VOID)
366 {
367 PUSER_MESSAGE_QUEUE Queue;
368 Queue = (PUSER_MESSAGE_QUEUE)W32kGetActiveDesktop()->ActiveMessageQueue;
369 if (Queue == NULL)
370 {
371 return(NULL);
372 }
373 else
374 {
375 return(Queue->ActiveWindow);
376 }
377 }
378
379 HWND FASTCALL
380 W32kGetFocusWindow(VOID)
381 {
382 PUSER_MESSAGE_QUEUE Queue;
383 PDESKTOP_OBJECT pdo = W32kGetActiveDesktop();
384
385 if( !pdo )
386 return NULL;
387
388 Queue = (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
389
390 if (Queue == NULL)
391 return(NULL);
392 else
393 return(Queue->FocusWindow);
394 }
395
396
397 WNDPROC FASTCALL
398 W32kGetWindowProc(HWND Wnd)
399 {
400 PWINDOW_OBJECT WindowObject;
401 WNDPROC WndProc;
402
403 WindowObject = W32kGetWindowObject(Wnd);
404 if( !WindowObject )
405 return NULL;
406
407 WndProc = WindowObject->WndProc;
408 W32kReleaseWindowObject(WindowObject);
409 return(WndProc);
410 }
411
412 NTSTATUS FASTCALL
413 InitWindowImpl(VOID)
414 {
415 InitializeListHead(&RegisteredMessageListHead);
416
417 return(STATUS_SUCCESS);
418 }
419
420 NTSTATUS FASTCALL
421 CleanupWindowImpl(VOID)
422 {
423 return(STATUS_SUCCESS);
424 }
425
426
427 DWORD STDCALL
428 NtUserAlterWindowStyle(DWORD Unknown0,
429 DWORD Unknown1,
430 DWORD Unknown2)
431 {
432 UNIMPLEMENTED
433
434 return(0);
435 }
436
437 DWORD STDCALL
438 NtUserChildWindowFromPointEx(HWND Parent,
439 LONG x,
440 LONG y,
441 UINT Flags)
442 {
443 UNIMPLEMENTED
444
445 return(0);
446 }
447
448 HWND STDCALL
449 W32kCreateDesktopWindow(PWINSTATION_OBJECT WindowStation,
450 PWNDCLASS_OBJECT DesktopClass,
451 ULONG Width, ULONG Height)
452 {
453 PWSTR WindowName;
454 HWND Handle;
455 PWINDOW_OBJECT WindowObject;
456
457 /* Create the window object. */
458 WindowObject = (PWINDOW_OBJECT)ObmCreateObject(WindowStation->HandleTable,
459 &Handle,
460 otWindow,
461 sizeof(WINDOW_OBJECT));
462 if (!WindowObject)
463 {
464 return((HWND)0);
465 }
466
467 /*
468 * Fill out the structure describing it.
469 */
470 WindowObject->Class = DesktopClass;
471 WindowObject->ExStyle = 0;
472 WindowObject->Style = WS_VISIBLE;
473 WindowObject->x = 0;
474 WindowObject->y = 0;
475 WindowObject->Width = Width;
476 WindowObject->Height = Height;
477 WindowObject->ParentHandle = NULL;
478 WindowObject->Parent = NULL;
479 WindowObject->Menu = NULL;
480 WindowObject->Instance = NULL;
481 WindowObject->Parameters = NULL;
482 WindowObject->Self = Handle;
483 WindowObject->MessageQueue = NULL;
484 WindowObject->ExtraData = NULL;
485 WindowObject->ExtraDataSize = 0;
486 WindowObject->WindowRect.left = 0;
487 WindowObject->WindowRect.top = 0;
488 WindowObject->WindowRect.right = Width;
489 WindowObject->WindowRect.bottom = Height;
490 WindowObject->ClientRect = WindowObject->WindowRect;
491 WindowObject->UserData = 0;
492 WindowObject->WndProc = DesktopClass->Class.lpfnWndProc;
493
494 InitializeListHead(&WindowObject->ChildrenListHead);
495 ExInitializeFastMutex(&WindowObject->ChildrenListLock);
496
497 WindowName = ExAllocatePool(NonPagedPool, sizeof(L"DESKTOP"));
498 wcscpy(WindowName, L"DESKTOP");
499 RtlInitUnicodeString(&WindowObject->WindowName, WindowName);
500
501 return(Handle);
502 }
503
504 VOID FASTCALL
505 W32kInitDesktopWindow(ULONG Width, ULONG Height)
506 {
507 PWINDOW_OBJECT DesktopWindow;
508 HRGN DesktopRgn;
509
510 DesktopWindow = W32kGetWindowObject(PsGetWin32Thread()->Desktop->DesktopWindow);
511 if (NULL == DesktopWindow)
512 {
513 return;
514 }
515 DesktopWindow->WindowRect.right = Width;
516 DesktopWindow->WindowRect.bottom = Height;
517 DesktopWindow->ClientRect = DesktopWindow->WindowRect;
518
519 DesktopRgn = UnsafeW32kCreateRectRgnIndirect(&(DesktopWindow->WindowRect));
520 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, DesktopWindow, DesktopRgn);
521 W32kDeleteObject(DesktopRgn);
522 W32kReleaseWindowObject(DesktopWindow);
523 }
524
525 HWND STDCALL
526 NtUserCreateWindowEx(DWORD dwExStyle,
527 PUNICODE_STRING lpClassName,
528 PUNICODE_STRING lpWindowName,
529 DWORD dwStyle,
530 LONG x,
531 LONG y,
532 LONG nWidth,
533 LONG nHeight,
534 HWND hWndParent,
535 HMENU hMenu,
536 HINSTANCE hInstance,
537 LPVOID lpParam,
538 DWORD dwShowMode)
539 {
540 PWINSTATION_OBJECT WinStaObject;
541 PWNDCLASS_OBJECT ClassObject;
542 PWINDOW_OBJECT WindowObject;
543 PWINDOW_OBJECT ParentWindow;
544 UNICODE_STRING WindowName;
545 NTSTATUS Status;
546 HANDLE Handle;
547 POINT MaxSize, MaxPos, MinTrack, MaxTrack;
548 CREATESTRUCTW Cs;
549 LRESULT Result;
550 DPRINT("NtUserCreateWindowEx\n");
551
552 /* Initialize gui state if necessary. */
553 W32kGraphicsCheck(TRUE);
554
555 if (!RtlCreateUnicodeString(&WindowName,
556 NULL == lpWindowName->Buffer ?
557 L"" : lpWindowName->Buffer))
558 {
559 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
560 return((HWND)0);
561 }
562
563 if (hWndParent != NULL)
564 {
565 ParentWindow = W32kGetWindowObject(hWndParent);
566 }
567 else
568 {
569 hWndParent = PsGetWin32Thread()->Desktop->DesktopWindow;
570 ParentWindow = W32kGetWindowObject(hWndParent);
571 }
572
573 /* Check the class. */
574 Status = ClassReferenceClassByNameOrAtom(&ClassObject, lpClassName->Buffer);
575 if (!NT_SUCCESS(Status))
576 {
577 RtlFreeUnicodeString(&WindowName);
578 W32kReleaseWindowObject(ParentWindow);
579 return((HWND)0);
580 }
581
582 /* Check the window station. */
583 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
584 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
585 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
586 KernelMode,
587 0,
588 &WinStaObject);
589 if (!NT_SUCCESS(Status))
590 {
591 RtlFreeUnicodeString(&WindowName);
592 ObmDereferenceObject(ClassObject);
593 W32kReleaseWindowObject(ParentWindow);
594 DPRINT("Validation of window station handle (0x%X) failed\n",
595 PROCESS_WINDOW_STATION());
596 return (HWND)0;
597 }
598
599 /* Create the window object. */
600 WindowObject = (PWINDOW_OBJECT)
601 ObmCreateObject(PsGetWin32Process()->WindowStation->HandleTable, &Handle,
602 otWindow, sizeof(WINDOW_OBJECT));
603 DPRINT("Created object with handle %X\n", Handle);
604 if (!WindowObject)
605 {
606 ObDereferenceObject(WinStaObject);
607 ObmDereferenceObject(ClassObject);
608 RtlFreeUnicodeString(&WindowName);
609 W32kReleaseWindowObject(ParentWindow);
610 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
611 return (HWND)0;
612 }
613 ObDereferenceObject(WinStaObject);
614
615 /*
616 * Fill out the structure describing it.
617 */
618 WindowObject->Class = ClassObject;
619 WindowObject->ExStyle = dwExStyle;
620 WindowObject->Style = dwStyle | WIN_NCACTIVATED;
621 WindowObject->x = x;
622 WindowObject->y = y;
623 WindowObject->Width = nWidth;
624 WindowObject->Height = nHeight;
625 WindowObject->ParentHandle = hWndParent;
626 WindowObject->Menu = hMenu;
627 WindowObject->Instance = hInstance;
628 WindowObject->Parameters = lpParam;
629 WindowObject->Self = Handle;
630 WindowObject->MessageQueue = PsGetWin32Thread()->MessageQueue;
631 WindowObject->Parent = ParentWindow;
632 WindowObject->UserData = 0;
633 WindowObject->WndProc = ClassObject->Class.lpfnWndProc;
634
635 ExAcquireFastMutexUnsafe(&ParentWindow->ChildrenListLock);
636 InsertHeadList(&ParentWindow->ChildrenListHead,
637 &WindowObject->SiblingListEntry);
638 ExReleaseFastMutexUnsafe(&ParentWindow->ChildrenListLock);
639
640 InitializeListHead(&WindowObject->ChildrenListHead);
641 InitializeListHead(&WindowObject->PropListHead);
642 ExInitializeFastMutex(&WindowObject->ChildrenListLock);
643
644 RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer);
645 RtlFreeUnicodeString(&WindowName);
646
647 if (ClassObject->Class.cbWndExtra != 0)
648 {
649 WindowObject->ExtraData =
650 ExAllocatePool(PagedPool,
651 ClassObject->Class.cbWndExtra);
652 WindowObject->ExtraDataSize = ClassObject->Class.cbWndExtra;
653 }
654 else
655 {
656 WindowObject->ExtraData = NULL;
657 WindowObject->ExtraDataSize = 0;
658 }
659
660 /* Correct the window style. */
661 if (!(dwStyle & WS_CHILD))
662 {
663 WindowObject->Style |= WS_CLIPSIBLINGS;
664 if (!(dwStyle & WS_POPUP))
665 {
666 WindowObject->Style |= WS_CAPTION;
667 /* FIXME: Note the window needs a size. */
668 }
669 }
670
671 /* Insert the window into the process's window list. */
672 ExAcquireFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock);
673 InsertTailList (&PsGetWin32Thread()->WindowListHead,
674 &WindowObject->ThreadListEntry);
675 ExReleaseFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock);
676
677 /*
678 * Insert the window into the list of windows associated with the thread's
679 * desktop.
680 */
681 InsertTailList(&PsGetWin32Thread()->Desktop->WindowListHead,
682 &WindowObject->DesktopListEntry);
683 /* Allocate a DCE for this window. */
684 if (dwStyle & CS_OWNDC) WindowObject->Dce = DceAllocDCE(WindowObject->Self,DCE_WINDOW_DC);
685 /* FIXME: Handle "CS_CLASSDC" */
686
687 /* Initialize the window dimensions. */
688 WindowObject->WindowRect.left = x;
689 WindowObject->WindowRect.top = y;
690 WindowObject->WindowRect.right = x + nWidth;
691 WindowObject->WindowRect.bottom = y + nHeight;
692 WindowObject->ClientRect = WindowObject->WindowRect;
693
694 /*
695 * Get the size and position of the window.
696 */
697 if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
698 {
699 WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack,
700 &MaxTrack);
701 x = min(MaxSize.x, y);
702 y = min(MaxSize.y, y);
703 x = max(MinTrack.x, x);
704 y = max(MinTrack.y, y);
705 }
706
707 WindowObject->WindowRect.left = x;
708 WindowObject->WindowRect.top = y;
709 WindowObject->WindowRect.right = x + nWidth;
710 WindowObject->WindowRect.bottom = y + nHeight;
711 WindowObject->ClientRect = WindowObject->WindowRect;
712
713 /* FIXME: Initialize the window menu. */
714
715 /* Initialize the window's scrollbars */
716 if (dwStyle & WS_VSCROLL)
717 SCROLL_CreateScrollBar(WindowObject, SB_VERT);
718 if (dwStyle & WS_HSCROLL)
719 SCROLL_CreateScrollBar(WindowObject, SB_HORZ);
720
721 /* Send a NCCREATE message. */
722 Cs.lpCreateParams = lpParam;
723 Cs.hInstance = hInstance;
724 Cs.hMenu = hMenu;
725 Cs.hwndParent = hWndParent;
726 Cs.cx = nWidth;
727 Cs.cy = nHeight;
728 Cs.x = x;
729 Cs.y = y;
730 Cs.style = dwStyle;
731 Cs.lpszName = lpWindowName->Buffer;
732 Cs.lpszClass = lpClassName->Buffer;
733 Cs.dwExStyle = dwExStyle;
734 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
735 Result = W32kSendNCCREATEMessage(WindowObject->Self, &Cs);
736 if (!Result)
737 {
738 /* FIXME: Cleanup. */
739 W32kReleaseWindowObject(ParentWindow);
740 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
741 return((HWND)0);
742 }
743
744 /* Calculate the non-client size. */
745 MaxPos.x = WindowObject->WindowRect.left;
746 MaxPos.y = WindowObject->WindowRect.top;
747 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
748 Result = WinPosGetNonClientSize(WindowObject->Self,
749 &WindowObject->WindowRect,
750 &WindowObject->ClientRect);
751 W32kOffsetRect(&WindowObject->WindowRect,
752 MaxPos.x - WindowObject->WindowRect.left,
753 MaxPos.y - WindowObject->WindowRect.top);
754
755 /* Send the CREATE message. */
756 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
757 Result = W32kSendCREATEMessage(WindowObject->Self, &Cs);
758 if (Result == (LRESULT)-1)
759 {
760 /* FIXME: Cleanup. */
761 W32kReleaseWindowObject(ParentWindow);
762 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
763 return((HWND)0);
764 }
765
766 /* Send move and size messages. */
767 if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE))
768 {
769 LONG lParam;
770
771 lParam =
772 MAKE_LONG(WindowObject->ClientRect.right -
773 WindowObject->ClientRect.left,
774 WindowObject->ClientRect.bottom -
775 WindowObject->ClientRect.top);
776
777 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
778 W32kCallWindowProc(NULL, WindowObject->Self, WM_SIZE, SIZE_RESTORED,
779 lParam);
780 lParam =
781 MAKE_LONG(WindowObject->ClientRect.left,
782 WindowObject->ClientRect.top);
783 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
784 W32kCallWindowProc(NULL, WindowObject->Self, WM_MOVE, 0, lParam);
785 }
786
787 /* Move from parent-client to screen coordinates */
788 if (0 != (WindowObject->Style & WS_CHILD))
789 {
790 W32kOffsetRect(&WindowObject->WindowRect,
791 ParentWindow->ClientRect.left,
792 ParentWindow->ClientRect.top);
793 W32kOffsetRect(&WindowObject->ClientRect,
794 ParentWindow->ClientRect.left,
795 ParentWindow->ClientRect.top);
796 }
797
798 /* Show or maybe minimize or maximize the window. */
799 if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE))
800 {
801 RECT NewPos;
802 UINT16 SwFlag;
803
804 SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE :
805 SW_MAXIMIZE;
806 WinPosMinMaximize(WindowObject, SwFlag, &NewPos);
807 SwFlag =
808 ((WindowObject->Style & WS_CHILD) || W32kGetActiveWindow()) ?
809 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :
810 SWP_NOZORDER | SWP_FRAMECHANGED;
811 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
812 WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top,
813 NewPos.right, NewPos.bottom, SwFlag);
814 }
815
816 /* Notify the parent window of a new child. */
817 if ((WindowObject->Style & WS_CHILD) ||
818 (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY)))
819 {
820 DPRINT("NtUserCreateWindow(): About to notify parent\n");
821 W32kCallWindowProc(NULL, WindowObject->Parent->Self,
822 WM_PARENTNOTIFY,
823 MAKEWPARAM(WM_CREATE, WindowObject->IDMenu),
824 (LPARAM)WindowObject->Self);
825 }
826
827 if (dwStyle & WS_VISIBLE)
828 {
829 DPRINT("NtUserCreateWindow(): About to show window\n");
830 WinPosShowWindow(WindowObject->Self, dwShowMode);
831 }
832
833 DPRINT("NtUserCreateWindow(): = %X\n", Handle);
834 return((HWND)Handle);
835 }
836
837 DWORD STDCALL
838 NtUserDeferWindowPos(HDWP WinPosInfo,
839 HWND Wnd,
840 HWND WndInsertAfter,
841 LONG x,
842 LONG y,
843 LONG cx,
844 LONG cy,
845 UINT Flags)
846 {
847 UNIMPLEMENTED
848
849 return 0;
850 }
851
852
853 /***********************************************************************
854 * W32kSendDestroyMsg
855 */
856 static void W32kSendDestroyMsg(HWND Wnd)
857 {
858 #if 0 /* FIXME */
859 GUITHREADINFO info;
860
861 if (GetGUIThreadInfo(GetCurrentThreadId(), &info))
862 {
863 if (Wnd == info.hwndCaret)
864 {
865 DestroyCaret();
866 }
867 }
868 #endif
869
870 /*
871 * Send the WM_DESTROY to the window.
872 */
873 NtUserSendMessage(Wnd, WM_DESTROY, 0, 0);
874
875 /*
876 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
877 * make sure that the window still exists when we come back.
878 */
879 #if 0 /* FIXME */
880 if (IsWindow(Wnd))
881 {
882 HWND* pWndArray;
883 int i;
884
885 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
886
887 /* start from the end (FIXME: is this needed?) */
888 for (i = 0; pWndArray[i]; i++) ;
889
890 while (--i >= 0)
891 {
892 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
893 }
894 HeapFree(GetProcessHeap(), 0, pWndArray);
895 }
896 else
897 {
898 DPRINT("destroyed itself while in WM_DESTROY!\n");
899 }
900 #endif
901 }
902
903 static BOOLEAN W32kWndBelongsToThread(PWINDOW_OBJECT Window, PW32THREAD ThreadData)
904 {
905 PLIST_ENTRY Current;
906 PWINDOW_OBJECT ThreadWindow;
907 BOOLEAN Belongs = FALSE;
908
909 ExAcquireFastMutexUnsafe(&ThreadData->WindowListLock);
910 /* If there's no win32k thread data then this thread hasn't created any windows */
911 if (NULL != ThreadData)
912 {
913 Current = ThreadData->WindowListHead.Flink;
914 while (! Belongs && Current != &ThreadData->WindowListHead)
915 {
916 ThreadWindow = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);
917 Belongs = (Window == ThreadWindow);
918 Current = Current->Flink;
919 }
920 }
921 ExReleaseFastMutexUnsafe(&ThreadData->WindowListLock);
922
923 return Belongs;
924 }
925
926 static BOOL BuildChildWindowArray(PWINDOW_OBJECT Window, HWND **Children, unsigned *NumChildren)
927 {
928 PLIST_ENTRY Current;
929 unsigned Index;
930 PWINDOW_OBJECT Child;
931
932 *Children = NULL;
933 *NumChildren = 0;
934 ExAcquireFastMutexUnsafe(&Window->ChildrenListLock);
935 Current = Window->ChildrenListHead.Flink;
936 while (Current != &Window->ChildrenListHead)
937 {
938 (*NumChildren)++;
939 Current = Current->Flink;
940 }
941 if (0 != *NumChildren)
942 {
943 *Children = ExAllocatePoolWithTag(PagedPool, *NumChildren * sizeof(HWND), TAG_WNAM);
944 if (NULL != *Children)
945 {
946 Current = Window->ChildrenListHead.Flink;
947 Index = 0;
948 while (Current != &Window->ChildrenListHead)
949 {
950 Child = CONTAINING_RECORD(Current, WINDOW_OBJECT, SiblingListEntry);
951 (*Children)[Index] = Child->Self;
952 Current = Current->Flink;
953 Index++;
954 }
955 assert(Index == *NumChildren);
956 }
957 else
958 {
959 DPRINT1("Failed to allocate memory for children array\n");
960 }
961 }
962 ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
963
964 return 0 == *NumChildren || NULL != *Children;
965 }
966
967 /***********************************************************************
968 * W32kDestroyWindow
969 *
970 * Destroy storage associated to a window. "Internals" p.358
971 */
972 static LRESULT W32kDestroyWindow(PWINDOW_OBJECT Window,
973 PW32PROCESS ProcessData,
974 PW32THREAD ThreadData,
975 BOOLEAN SendMessages)
976 {
977 HWND *Children;
978 unsigned NumChildren;
979 unsigned Index;
980 PWINDOW_OBJECT Child;
981
982 if (! W32kWndBelongsToThread(Window, ThreadData))
983 {
984 DPRINT1("Window doesn't belong to current thread\n");
985 return 0;
986 }
987
988 /* free child windows */
989 if (! BuildChildWindowArray(Window, &Children, &NumChildren))
990 {
991 return 0;
992 }
993 for (Index = NumChildren; 0 < Index; Index--)
994 {
995 Child = W32kGetWindowObject(Children[Index - 1]);
996 if (NULL != Child)
997 {
998 if (W32kWndBelongsToThread(Child, ThreadData))
999 {
1000 W32kDestroyWindow(Child, ProcessData, ThreadData, SendMessages);
1001 }
1002 #if 0 /* FIXME */
1003 else
1004 {
1005 SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
1006 }
1007 #endif
1008 }
1009 }
1010 if (0 != NumChildren)
1011 {
1012 ExFreePool(Children);
1013 }
1014
1015 if (SendMessages)
1016 {
1017 /*
1018 * Clear the update region to make sure no WM_PAINT messages will be
1019 * generated for this window while processing the WM_NCDESTROY.
1020 */
1021 PaintRedrawWindow(Window->Self, NULL, 0,
1022 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN,
1023 0);
1024
1025 /*
1026 * Send the WM_NCDESTROY to the window being destroyed.
1027 */
1028 NtUserSendMessage(Window->Self, WM_NCDESTROY, 0, 0);
1029 }
1030
1031 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
1032
1033 #if 0 /* FIXME */
1034 WinPosCheckInternalPos(Window->Self);
1035 if (Window->Self == GetCapture())
1036 {
1037 ReleaseCapture();
1038 }
1039
1040 /* free resources associated with the window */
1041 TIMER_RemoveWindowTimers(Window->Self);
1042 #endif
1043
1044 #if 0 /* FIXME */
1045 if (0 == (Window->Style & WS_CHILD))
1046 {
1047 HMENU Menu = (HMENU) NtUserSetWindowLongW(Window->Self, GWL_ID, 0);
1048 if (NULL != Menu)
1049 {
1050 DestroyMenu(Menu);
1051 }
1052 }
1053 if (Window->hSysMenu)
1054 {
1055 DestroyMenu(Window->hSysMenu);
1056 Window->hSysMenu = 0;
1057 }
1058 DCE_FreeWindowDCE(Window->Self); /* Always do this to catch orphaned DCs */
1059 WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);
1060 CLASS_RemoveWindow(Window->Class);
1061 #endif
1062
1063 ExAcquireFastMutexUnsafe(&Window->Parent->ChildrenListLock);
1064 RemoveEntryList(&Window->SiblingListEntry);
1065 ExReleaseFastMutexUnsafe(&Window->Parent->ChildrenListLock);
1066
1067 RemoveEntryList(&Window->DesktopListEntry);
1068
1069 ExAcquireFastMutexUnsafe (&ThreadData->WindowListLock);
1070 RemoveEntryList(&Window->ThreadListEntry);
1071 ExReleaseFastMutexUnsafe (&ThreadData->WindowListLock);
1072
1073 Window->Class = NULL;
1074 ObmCloseHandle(ProcessData->WindowStation->HandleTable, Window->Self);
1075
1076 W32kGraphicsCheck(FALSE);
1077
1078 return 0;
1079 }
1080
1081 BOOLEAN STDCALL
1082 NtUserDestroyWindow(HWND Wnd)
1083 {
1084 PWINDOW_OBJECT Window;
1085 BOOLEAN isChild;
1086 HWND hWndFocus;
1087
1088 Window = W32kGetWindowObject(Wnd);
1089 if (Window == NULL)
1090 {
1091 return FALSE;
1092 }
1093
1094 /* Check for desktop window (has NULL parent) */
1095 if (NULL == Window->Parent)
1096 {
1097 W32kReleaseWindowObject(Window);
1098 SetLastWin32Error(ERROR_ACCESS_DENIED);
1099 return FALSE;
1100 }
1101
1102 /* Look whether the focus is within the tree of windows we will
1103 * be destroying.
1104 */
1105 hWndFocus = W32kGetFocusWindow();
1106 if (hWndFocus == Wnd || W32kIsChildWindow(Wnd, hWndFocus))
1107 {
1108 HWND Parent = NtUserGetAncestor(Wnd, GA_PARENT);
1109 if (Parent == W32kGetDesktopWindow())
1110 {
1111 Parent = NULL;
1112 }
1113 W32kSetFocusWindow(Parent);
1114 }
1115
1116 /* Call hooks */
1117 #if 0 /* FIXME */
1118 if (HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hwnd, 0, TRUE))
1119 {
1120 return FALSE;
1121 }
1122 #endif
1123
1124 isChild = (0 != (Window->Style & WS_CHILD));
1125
1126 #if 0 /* FIXME */
1127 if (isChild)
1128 {
1129 if (! USER_IsExitingThread(GetCurrentThreadId()))
1130 {
1131 send_parent_notify(hwnd, WM_DESTROY);
1132 }
1133 }
1134 else if (NULL != GetWindow(Wnd, GW_OWNER))
1135 {
1136 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1137 /* FIXME: clean up palette - see "Internals" p.352 */
1138 }
1139
1140 if (! IsWindow(Wnd))
1141 {
1142 return TRUE;
1143 }
1144 #endif
1145
1146 /* Hide the window */
1147 if (! WinPosShowWindow(Wnd, SW_HIDE ))
1148 {
1149 #if 0 /* FIXME */
1150 if (hwnd == GetActiveWindow())
1151 {
1152 WINPOS_ActivateOtherWindow( hwnd );
1153 }
1154 #endif
1155 }
1156
1157 #if 0 /* FIXME */
1158 if (! IsWindow(Wnd))
1159 {
1160 return TRUE;
1161 }
1162 #endif
1163
1164 /* Recursively destroy owned windows */
1165 #if 0 /* FIXME */
1166 if (! isChild)
1167 {
1168 for (;;)
1169 {
1170 int i;
1171 BOOL GotOne = FALSE;
1172 HWND *list = WIN_ListChildren(GetDesktopWindow());
1173 if (list)
1174 {
1175 for (i = 0; list[i]; i++)
1176 {
1177 if (GetWindow(list[i], GW_OWNER) != Wnd)
1178 {
1179 continue;
1180 }
1181 if (WIN_IsCurrentThread(list[i]))
1182 {
1183 DestroyWindow(list[i]);
1184 GotOne = TRUE;
1185 continue;
1186 }
1187 WIN_SetOwner(list[i], NULL);
1188 }
1189 HeapFree(GetProcessHeap(), 0, list);
1190 }
1191 if (! GotOne)
1192 {
1193 break;
1194 }
1195 }
1196 }
1197 #endif
1198
1199 /* Send destroy messages */
1200 W32kSendDestroyMsg(Wnd);
1201
1202 #if 0 /* FIXME */
1203 if (!IsWindow(Wnd))
1204 {
1205 return TRUE;
1206 }
1207 #endif
1208
1209 /* Unlink now so we won't bother with the children later on */
1210 #if 0 /* FIXME */
1211 WIN_UnlinkWindow( hwnd );
1212 #endif
1213
1214 /* Destroy the window storage */
1215 W32kDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
1216
1217 return TRUE;
1218 }
1219
1220 VOID FASTCALL
1221 DestroyThreadWindows(struct _ETHREAD *Thread)
1222 {
1223 PLIST_ENTRY LastHead;
1224 PW32PROCESS Win32Process;
1225 PW32THREAD Win32Thread;
1226 PWINDOW_OBJECT Window;
1227
1228 Win32Thread = Thread->Win32Thread;
1229 Win32Process = Thread->ThreadsProcess->Win32Process;
1230 ExAcquireFastMutexUnsafe(&Win32Thread->WindowListLock);
1231 LastHead = NULL;
1232 while (Win32Thread->WindowListHead.Flink != &(Win32Thread->WindowListHead) &&
1233 Win32Thread->WindowListHead.Flink != LastHead)
1234 {
1235 LastHead = Win32Thread->WindowListHead.Flink;
1236 Window = CONTAINING_RECORD(Win32Thread->WindowListHead.Flink, WINDOW_OBJECT, ThreadListEntry);
1237 ExReleaseFastMutexUnsafe(&Win32Thread->WindowListLock);
1238 W32kDestroyWindow(Window, Win32Process, Win32Thread, FALSE);
1239 ExAcquireFastMutexUnsafe(&Win32Thread->WindowListLock);
1240 }
1241 if (Win32Thread->WindowListHead.Flink == LastHead)
1242 {
1243 /* Window at head of list was not removed, should never happen, infinite loop */
1244 KeBugCheck(0);
1245 }
1246 ExReleaseFastMutexUnsafe(&Win32Thread->WindowListLock);
1247 }
1248
1249 DWORD STDCALL
1250 NtUserEndDeferWindowPosEx(DWORD Unknown0,
1251 DWORD Unknown1)
1252 {
1253 UNIMPLEMENTED
1254
1255 return 0;
1256 }
1257
1258 DWORD STDCALL
1259 NtUserFillWindow(DWORD Unknown0,
1260 DWORD Unknown1,
1261 DWORD Unknown2,
1262 DWORD Unknown3)
1263 {
1264 UNIMPLEMENTED
1265
1266 return 0;
1267 }
1268
1269 /*
1270 * FUNCTION:
1271 * Searches a window's children for a window with the specified
1272 * class and name
1273 * ARGUMENTS:
1274 * hwndParent = The window whose childs are to be searched.
1275 * NULL = desktop
1276 *
1277 * hwndChildAfter = Search starts after this child window.
1278 * NULL = start from beginning
1279 *
1280 * ucClassName = Class name to search for
1281 * Reguired parameter.
1282 *
1283 * ucWindowName = Window name
1284 * ->Buffer == NULL = don't care
1285 *
1286 * RETURNS:
1287 * The HWND of the window if it was found, otherwise NULL
1288 *
1289 * FIXME:
1290 * Should use MmCopyFromCaller, we don't want an access violation in here
1291 *
1292 */
1293
1294 HWND STDCALL
1295 NtUserFindWindowEx(HWND hwndParent,
1296 HWND hwndChildAfter,
1297 PUNICODE_STRING ucClassName,
1298 PUNICODE_STRING ucWindowName)
1299 {
1300 NTSTATUS status;
1301 HWND windowHandle;
1302 PWINDOW_OBJECT windowObject;
1303 PWINDOW_OBJECT ParentWindow;
1304 PLIST_ENTRY currentEntry;
1305 PWNDCLASS_OBJECT classObject;
1306
1307 // Get a pointer to the class
1308 status = ClassReferenceClassByNameOrAtom(&classObject, ucClassName->Buffer);
1309 if (!NT_SUCCESS(status))
1310 {
1311 return NULL;
1312 }
1313
1314 // If hwndParent==NULL use the desktop window instead
1315 if(!hwndParent)
1316 hwndParent = PsGetWin32Thread()->Desktop->DesktopWindow;
1317
1318 // Get the object
1319 ParentWindow = W32kGetWindowObject(hwndParent);
1320
1321 if(!ParentWindow)
1322 {
1323 ObmDereferenceObject(classObject);
1324 return NULL;
1325 }
1326
1327 ExAcquireFastMutexUnsafe (&ParentWindow->ChildrenListLock);
1328 currentEntry = ParentWindow->ChildrenListHead.Flink;
1329
1330 if(hwndChildAfter)
1331 {
1332 while (currentEntry != &ParentWindow->ChildrenListHead)
1333 {
1334 windowObject = CONTAINING_RECORD (currentEntry, WINDOW_OBJECT,
1335 SiblingListEntry);
1336
1337 if(windowObject->Self == hwndChildAfter)
1338 {
1339 /* "The search begins with the _next_ child window in the Z order." */
1340 currentEntry = currentEntry->Flink;
1341 break;
1342 }
1343
1344 currentEntry = currentEntry->Flink;
1345 }
1346
1347 /* If the child hwndChildAfter was not found:
1348 currentEntry=&ParentWindow->ChildrenListHead now so the next
1349 block of code will just fall through and the function returns NULL */
1350 }
1351
1352 while (currentEntry != &ParentWindow->ChildrenListHead)
1353 {
1354 windowObject = CONTAINING_RECORD (currentEntry, WINDOW_OBJECT,
1355 SiblingListEntry);
1356
1357 if (classObject == windowObject->Class && (ucWindowName->Buffer==NULL ||
1358 RtlCompareUnicodeString (ucWindowName, &windowObject->WindowName, TRUE) == 0))
1359 {
1360 windowHandle = windowObject->Self;
1361
1362 ExReleaseFastMutexUnsafe (&ParentWindow->ChildrenListLock);
1363 W32kReleaseWindowObject(ParentWindow);
1364 ObmDereferenceObject (classObject);
1365
1366 return windowHandle;
1367 }
1368 currentEntry = currentEntry->Flink;
1369 }
1370
1371 ExReleaseFastMutexUnsafe (&ParentWindow->ChildrenListLock);
1372 W32kReleaseWindowObject(ParentWindow);
1373 ObmDereferenceObject (classObject);
1374
1375 return NULL;
1376 }
1377
1378 DWORD STDCALL
1379 NtUserFlashWindowEx(DWORD Unknown0)
1380 {
1381 UNIMPLEMENTED
1382
1383 return 0;
1384 }
1385
1386 DWORD STDCALL
1387 NtUserGetForegroundWindow(VOID)
1388 {
1389 UNIMPLEMENTED
1390
1391 return 0;
1392 }
1393
1394 DWORD STDCALL
1395 NtUserGetInternalWindowPos(DWORD Unknown0,
1396 DWORD Unknown1,
1397 DWORD Unknown2)
1398 {
1399 UNIMPLEMENTED
1400
1401 return 0;
1402 }
1403
1404 DWORD STDCALL
1405 NtUserGetOpenClipboardWindow(VOID)
1406 {
1407 UNIMPLEMENTED
1408
1409 return 0;
1410 }
1411
1412 DWORD STDCALL
1413 NtUserGetWindowDC(HWND hWnd)
1414 {
1415 return (DWORD) NtUserGetDCEx( hWnd, 0, DCX_USESTYLE | DCX_WINDOW );
1416 }
1417
1418 DWORD STDCALL
1419 NtUserGetWindowPlacement(DWORD Unknown0,
1420 DWORD Unknown1)
1421 {
1422 UNIMPLEMENTED
1423
1424 return 0;
1425 }
1426
1427 DWORD STDCALL
1428 NtUserInternalGetWindowText(DWORD Unknown0,
1429 DWORD Unknown1,
1430 DWORD Unknown2)
1431 {
1432 UNIMPLEMENTED
1433
1434 return 0;
1435 }
1436
1437 DWORD STDCALL
1438 NtUserLockWindowUpdate(DWORD Unknown0)
1439 {
1440 UNIMPLEMENTED
1441
1442 return 0;
1443 }
1444
1445 BOOL STDCALL
1446 NtUserMoveWindow(
1447 HWND hWnd,
1448 int X,
1449 int Y,
1450 int nWidth,
1451 int nHeight,
1452 BOOL bRepaint)
1453 {
1454 PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
1455 ULONG uStyle, uExStyle;
1456 WINDOWPOS pWinPos;
1457
1458 if (!Window) return FALSE;
1459
1460 uStyle = Window->Style;
1461 uExStyle = Window->ExStyle;
1462 pWinPos.hwnd = hWnd;
1463
1464 pWinPos.x = X;
1465 pWinPos.y = Y;
1466 if (nWidth > NtUserGetSystemMetrics(SM_CXMIN))
1467 pWinPos.cx = pWinPos.x + nWidth;
1468 else
1469 pWinPos.cx = pWinPos.x + NtUserGetSystemMetrics(SM_CXMIN);
1470
1471 if (nHeight > NtUserGetSystemMetrics(SM_CYMIN))
1472 pWinPos.cy = pWinPos.x + nHeight;
1473 else
1474 pWinPos.cy = pWinPos.y + NtUserGetSystemMetrics(SM_CYMIN);
1475 W32kSendWINDOWPOSCHANGINGMessage(Window->Self, &pWinPos);
1476
1477 Window->WindowRect.top = Window->ClientRect.top = pWinPos.y;
1478 Window->WindowRect.left = Window->ClientRect.left = pWinPos.x;
1479 Window->WindowRect.bottom = Window->ClientRect.bottom = pWinPos.cy;
1480 Window->WindowRect.right = Window->ClientRect.right = pWinPos.cx;
1481
1482 if (!(uStyle & WS_THICKFRAME))
1483 {
1484 Window->ClientRect.top += NtUserGetSystemMetrics(SM_CYFIXEDFRAME);
1485 Window->ClientRect.bottom -= NtUserGetSystemMetrics(SM_CYFIXEDFRAME);
1486 Window->ClientRect.left += NtUserGetSystemMetrics(SM_CXFIXEDFRAME);
1487 Window->ClientRect.right -= NtUserGetSystemMetrics(SM_CXFIXEDFRAME);
1488 }
1489 else
1490 {
1491 Window->ClientRect.top += NtUserGetSystemMetrics(SM_CYSIZEFRAME);
1492 Window->ClientRect.bottom -= NtUserGetSystemMetrics(SM_CYSIZEFRAME);
1493 Window->ClientRect.left += NtUserGetSystemMetrics(SM_CXSIZEFRAME);
1494 Window->ClientRect.right -= NtUserGetSystemMetrics(SM_CXSIZEFRAME);
1495 }
1496
1497 if (uStyle & WS_CAPTION)
1498 Window->ClientRect.top += NtUserGetSystemMetrics(SM_CYCAPTION) + 1;
1499 if ( Window->Class->Class.lpszMenuName)
1500 {
1501 Window->ClientRect.top += NtUserGetSystemMetrics(SM_CYMENU);
1502 }
1503
1504 W32kSendWINDOWPOSCHANGEDMessage(Window->Self, &pWinPos);
1505
1506 NtUserSendMessage(hWnd, WM_MOVE, 0, MAKEWORD(Window->ClientRect.left,
1507 Window->ClientRect.top));
1508
1509 NtUserSendMessage(hWnd, WM_SIZE, 0, MAKEWORD(Window->ClientRect.right -
1510 Window->ClientRect.left,
1511 Window->ClientRect.bottom -
1512 Window->ClientRect.top));
1513
1514 /* FIXME: Send WM_NCCALCSIZE */
1515 W32kReleaseWindowObject(Window);
1516 if (bRepaint) NtUserSendMessage(hWnd, WM_PAINT, 0, 0);
1517 return TRUE;
1518 }
1519
1520 /*
1521 QueryWindow based on KJK::Hyperion and James Tabor.
1522
1523 0 = QWUniqueProcessId
1524 1 = QWUniqueThreadId
1525 4 = QWIsHung Implements IsHungAppWindow found
1526 by KJK::Hyperion.
1527
1528 9 = QWKillWindow When I called this with hWnd ==
1529 DesktopWindow, it shutdown the system
1530 and rebooted.
1531 */
1532 DWORD STDCALL
1533 NtUserQueryWindow(HWND hWnd, DWORD Index)
1534 {
1535 /*
1536 W32kGetWndObj uses PsGetWin32Process() which came from
1537 PsGetCurrentProcess() made from PsGetCurrentThread().
1538 What would happen if hWnd was under a different EThread
1539 all togeather?
1540 */
1541 PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
1542
1543 if(Window == NULL) return((DWORD)NULL);
1544
1545 W32kReleaseWindowObject(Window);
1546
1547 switch(Index)
1548 {
1549 case 0x00:
1550 return((DWORD)PsGetCurrentProcessId());
1551
1552 case 0x01:
1553 return((DWORD)PsGetCurrentThreadId());
1554
1555 default:
1556 return((DWORD)NULL);
1557 }
1558
1559 }
1560
1561 DWORD STDCALL
1562 NtUserRealChildWindowFromPoint(DWORD Unknown0,
1563 DWORD Unknown1,
1564 DWORD Unknown2)
1565 {
1566 UNIMPLEMENTED
1567
1568 return 0;
1569 }
1570
1571 BOOL
1572 STDCALL
1573 NtUserRedrawWindow
1574 (
1575 HWND hWnd,
1576 CONST RECT *lprcUpdate,
1577 HRGN hrgnUpdate,
1578 UINT flags
1579 )
1580 {
1581 RECT SafeUpdateRect;
1582 NTSTATUS Status;
1583
1584 if(NULL != lprcUpdate)
1585 {
1586 Status = MmCopyFromCaller(&SafeUpdateRect, (PRECT)lprcUpdate, sizeof(RECT));
1587
1588 if(!NT_SUCCESS(Status))
1589 {
1590 /* FIXME: set last error */
1591 return FALSE;
1592 }
1593 }
1594
1595 Status = PaintRedrawWindow
1596 (
1597 hWnd,
1598 NULL == lprcUpdate ? NULL : &SafeUpdateRect,
1599 hrgnUpdate,
1600 flags,
1601 0
1602 );
1603
1604 if(!NT_SUCCESS(Status))
1605 {
1606 /* FIXME: set last error */
1607 return FALSE;
1608 }
1609
1610 return TRUE;
1611 }
1612
1613 UINT STDCALL
1614 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
1615 {
1616 PLIST_ENTRY Current;
1617 PREGISTERED_MESSAGE NewMsg, RegMsg;
1618 UINT Msg = REGISTERED_MESSAGE_MIN;
1619 UNICODE_STRING MessageName;
1620 NTSTATUS Status;
1621
1622 Status = MmCopyFromCaller(&MessageName, MessageNameUnsafe, sizeof(UNICODE_STRING));
1623 if (! NT_SUCCESS(Status))
1624 {
1625 SetLastNtError(Status);
1626 return 0;
1627 }
1628
1629 NewMsg = ExAllocatePoolWithTag(PagedPool,
1630 sizeof(REGISTERED_MESSAGE) +
1631 MessageName.Length,
1632 TAG_WNAM);
1633 if (NULL == NewMsg)
1634 {
1635 SetLastNtError(STATUS_NO_MEMORY);
1636 return 0;
1637 }
1638
1639 Status = MmCopyFromCaller(NewMsg->MessageName, MessageName.Buffer, MessageName.Length);
1640 if (! NT_SUCCESS(Status))
1641 {
1642 ExFreePool(NewMsg);
1643 SetLastNtError(Status);
1644 return 0;
1645 }
1646 NewMsg->MessageName[MessageName.Length / sizeof(WCHAR)] = L'\0';
1647 if (wcslen(NewMsg->MessageName) != MessageName.Length / sizeof(WCHAR))
1648 {
1649 ExFreePool(NewMsg);
1650 SetLastNtError(STATUS_INVALID_PARAMETER);
1651 return 0;
1652 }
1653
1654 Current = RegisteredMessageListHead.Flink;
1655 while (Current != &RegisteredMessageListHead)
1656 {
1657 RegMsg = CONTAINING_RECORD(Current, REGISTERED_MESSAGE, ListEntry);
1658 if (0 == wcscmp(NewMsg->MessageName, RegMsg->MessageName))
1659 {
1660 ExFreePool(NewMsg);
1661 return Msg;
1662 }
1663 Msg++;
1664 Current = Current->Flink;
1665 }
1666
1667 if (REGISTERED_MESSAGE_MAX < Msg)
1668 {
1669 ExFreePool(NewMsg);
1670 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
1671 return 0;
1672 }
1673
1674 InsertTailList(&RegisteredMessageListHead, &(NewMsg->ListEntry));
1675
1676 return Msg;
1677 }
1678
1679 DWORD STDCALL
1680 NtUserScrollWindowEx(DWORD Unknown0,
1681 DWORD Unknown1,
1682 DWORD Unknown2,
1683 DWORD Unknown3,
1684 DWORD Unknown4,
1685 DWORD Unknown5,
1686 DWORD Unknown6,
1687 DWORD Unknown7)
1688 {
1689 UNIMPLEMENTED
1690
1691 return 0;
1692 }
1693
1694 DWORD STDCALL
1695 NtUserSetActiveWindow(DWORD Unknown0)
1696 {
1697 UNIMPLEMENTED
1698
1699 return 0;
1700 }
1701
1702 DWORD STDCALL
1703 NtUserSetImeOwnerWindow(DWORD Unknown0,
1704 DWORD Unknown1)
1705 {
1706 UNIMPLEMENTED
1707
1708 return 0;
1709 }
1710
1711 DWORD STDCALL
1712 NtUserSetInternalWindowPos(DWORD Unknown0,
1713 DWORD Unknown1,
1714 DWORD Unknown2,
1715 DWORD Unknown3)
1716 {
1717 UNIMPLEMENTED
1718
1719 return 0;
1720
1721 }
1722
1723 DWORD STDCALL
1724 NtUserSetLayeredWindowAttributes(DWORD Unknown0,
1725 DWORD Unknown1,
1726 DWORD Unknown2,
1727 DWORD Unknown3)
1728 {
1729 UNIMPLEMENTED
1730
1731 return 0;
1732 }
1733
1734 DWORD STDCALL
1735 NtUserSetLogonNotifyWindow(DWORD Unknown0)
1736 {
1737 UNIMPLEMENTED
1738
1739 return 0;
1740 }
1741
1742 DWORD STDCALL
1743 NtUserSetShellWindowEx(DWORD Unknown0,
1744 DWORD Unknown1)
1745 {
1746 UNIMPLEMENTED
1747
1748 return 0;
1749 }
1750
1751 DWORD STDCALL
1752 NtUserSetWindowFNID(DWORD Unknown0,
1753 DWORD Unknown1)
1754 {
1755 UNIMPLEMENTED
1756
1757 return 0;
1758 }
1759
1760 LONG STDCALL
1761 NtUserGetWindowLong(HWND hWnd, DWORD Index)
1762 {
1763 PWINDOW_OBJECT WindowObject;
1764 NTSTATUS Status;
1765 LONG Result;
1766
1767 Status =
1768 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
1769 hWnd,
1770 otWindow,
1771 (PVOID*)&WindowObject);
1772 if (!NT_SUCCESS(Status))
1773 {
1774 SetLastWin32Error(ERROR_INVALID_HANDLE);
1775 return 0;
1776 }
1777
1778 if (0 <= (int) Index)
1779 {
1780 if (WindowObject->ExtraDataSize - sizeof(LONG) < Index ||
1781 0 != Index % sizeof(LONG))
1782 {
1783 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1784 return 0;
1785 }
1786 Result = WindowObject->ExtraData[Index / sizeof(LONG)];
1787 }
1788 else
1789 {
1790 switch (Index)
1791 {
1792 case GWL_EXSTYLE:
1793 Result = WindowObject->ExStyle;
1794 break;
1795
1796 case GWL_STYLE:
1797 Result = WindowObject->Style;
1798 break;
1799
1800 case GWL_WNDPROC:
1801 Result = (LONG) WindowObject->WndProc;
1802 break;
1803
1804 case GWL_HINSTANCE:
1805 Result = (LONG) WindowObject->Instance;
1806 break;
1807
1808 case GWL_HWNDPARENT:
1809 Result = (LONG) WindowObject->ParentHandle;
1810 break;
1811
1812 case GWL_ID:
1813 Result = (LONG) WindowObject->IDMenu;
1814 break;
1815
1816 case GWL_USERDATA:
1817 Result = WindowObject->UserData;
1818 break;
1819
1820 default:
1821 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
1822 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1823 Result = 0;
1824 break;
1825 }
1826 }
1827
1828 ObmDereferenceObject(WindowObject);
1829
1830 return Result;
1831 }
1832
1833 LONG STDCALL
1834 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
1835 {
1836 PWINDOW_OBJECT WindowObject;
1837 NTSTATUS Status;
1838 LONG OldValue;
1839 STYLESTRUCT Style;
1840
1841 Status =
1842 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
1843 hWnd,
1844 otWindow,
1845 (PVOID*)&WindowObject);
1846 if (!NT_SUCCESS(Status))
1847 {
1848 SetLastWin32Error(ERROR_INVALID_HANDLE);
1849 return(0);
1850 }
1851
1852 if (0 <= (int) Index)
1853 {
1854 if (WindowObject->ExtraDataSize - sizeof(LONG) < Index ||
1855 0 != Index % sizeof(LONG))
1856 {
1857 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1858 return 0;
1859 }
1860 OldValue = WindowObject->ExtraData[Index / sizeof(LONG)];
1861 WindowObject->ExtraData[Index / sizeof(LONG)] = NewValue;
1862 }
1863 else
1864 {
1865 switch (Index)
1866 {
1867 case GWL_EXSTYLE:
1868 OldValue = (LONG) WindowObject->ExStyle;
1869 Style.styleOld = OldValue;
1870 Style.styleNew = NewValue;
1871 W32kSendSTYLECHANGINGMessage(hWnd, GWL_EXSTYLE, &Style);
1872 WindowObject->ExStyle = (DWORD)Style.styleNew;
1873 W32kSendSTYLECHANGEDMessage(hWnd, GWL_EXSTYLE, &Style);
1874 break;
1875
1876 case GWL_STYLE:
1877 OldValue = (LONG) WindowObject->Style;
1878 Style.styleOld = OldValue;
1879 Style.styleNew = NewValue;
1880 W32kSendSTYLECHANGINGMessage(hWnd, GWL_STYLE, &Style);
1881 WindowObject->Style = (DWORD)Style.styleNew;
1882 W32kSendSTYLECHANGEDMessage(hWnd, GWL_STYLE, &Style);
1883 break;
1884
1885 case GWL_WNDPROC:
1886 /* FIXME: should check if window belongs to current process */
1887 OldValue = (LONG) WindowObject->WndProc;
1888 WindowObject->WndProc = (WNDPROC) NewValue;
1889 break;
1890
1891 case GWL_HINSTANCE:
1892 OldValue = (LONG) WindowObject->Instance;
1893 WindowObject->Instance = (HINSTANCE) NewValue;
1894 break;
1895
1896 case GWL_HWNDPARENT:
1897 OldValue = (LONG) WindowObject->ParentHandle;
1898 WindowObject->ParentHandle = (HWND) NewValue;
1899 /* FIXME: Need to update window lists of old and new parent */
1900 UNIMPLEMENTED;
1901 break;
1902
1903 case GWL_ID:
1904 OldValue = (LONG) WindowObject->IDMenu;
1905 WindowObject->IDMenu = (UINT) NewValue;
1906 break;
1907
1908 case GWL_USERDATA:
1909 OldValue = WindowObject->UserData;
1910 WindowObject->UserData = NewValue;
1911 break;
1912
1913 default:
1914 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
1915 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1916 OldValue = 0;
1917 break;
1918 }
1919 }
1920
1921 ObmDereferenceObject(WindowObject);
1922 return(OldValue);
1923 }
1924
1925 DWORD STDCALL
1926 NtUserSetWindowPlacement(DWORD Unknown0,
1927 DWORD Unknown1)
1928 {
1929 UNIMPLEMENTED
1930
1931 return 0;
1932 }
1933
1934 BOOL
1935 STDCALL NtUserSetWindowPos(
1936 HWND hWnd,
1937 HWND hWndInsertAfter,
1938 int X,
1939 int Y,
1940 int cx,
1941 int cy,
1942 UINT uFlags)
1943 {
1944 return WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
1945 }
1946
1947 DWORD STDCALL
1948 NtUserSetWindowRgn(DWORD Unknown0,
1949 DWORD Unknown1,
1950 DWORD Unknown2)
1951 {
1952 UNIMPLEMENTED
1953
1954 return 0;
1955 }
1956
1957 DWORD STDCALL
1958 NtUserSetWindowWord(DWORD Unknown0,
1959 DWORD Unknown1,
1960 DWORD Unknown2)
1961 {
1962 UNIMPLEMENTED
1963
1964 return 0;
1965 }
1966
1967 BOOL STDCALL
1968 NtUserShowWindow(HWND hWnd,
1969 LONG nCmdShow)
1970 {
1971 return(WinPosShowWindow(hWnd, nCmdShow));
1972 }
1973
1974 DWORD STDCALL
1975 NtUserShowWindowAsync(DWORD Unknown0,
1976 DWORD Unknown1)
1977 {
1978 UNIMPLEMENTED
1979
1980 return 0;
1981 }
1982
1983 BOOL STDCALL NtUserUpdateWindow( HWND hWnd )
1984 {
1985 PWINDOW_OBJECT pWindow = W32kGetWindowObject( hWnd);
1986
1987 if (!pWindow)
1988 return FALSE;
1989 if (pWindow->UpdateRegion)
1990 NtUserSendMessage( hWnd, WM_PAINT,0,0);
1991 W32kReleaseWindowObject(pWindow);
1992 return TRUE;
1993 }
1994
1995 DWORD STDCALL
1996 NtUserUpdateLayeredWindow(DWORD Unknown0,
1997 DWORD Unknown1,
1998 DWORD Unknown2,
1999 DWORD Unknown3,
2000 DWORD Unknown4,
2001 DWORD Unknown5,
2002 DWORD Unknown6,
2003 DWORD Unknown7,
2004 DWORD Unknown8)
2005 {
2006 UNIMPLEMENTED
2007
2008 return 0;
2009 }
2010
2011 DWORD STDCALL
2012 NtUserWindowFromPoint(DWORD Unknown0,
2013 DWORD Unknown1)
2014 {
2015 UNIMPLEMENTED
2016
2017 return 0;
2018 }
2019
2020 HWND STDCALL
2021 NtUserGetDesktopWindow()
2022 {
2023 return W32kGetDesktopWindow();
2024 }
2025
2026 /* EOF */