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