assign even more styles for overlapped windows
[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.228 2004/05/08 16:06:54 weiden 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/desktop.h>
41 #include <include/winpos.h>
42 #include <include/callback.h>
43 #include <include/msgqueue.h>
44 #include <include/rect.h>
45 #include <include/dce.h>
46 #include <include/paint.h>
47 #include <include/painting.h>
48 #include <include/scroll.h>
49 #include <include/intgdi.h>
50 #include <include/menu.h>
51 #include <include/hotkey.h>
52 #include <include/focus.h>
53 #include <include/hook.h>
54 #include <include/useratom.h>
55 #include <include/tags.h>
56 #include <include/timer.h>
57 #include <include/cleanup.h>
58
59 #define NDEBUG
60 #include <win32k/debug1.h>
61 #include <debug.h>
62
63 static WndProcHandle *WndProcHandlesArray = 0;
64 static WORD WndProcHandlesArraySize = 0;
65 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
66
67 /* dialog resources appear to pass this in 16 bits, handle them properly */
68 #define CW_USEDEFAULT16 (0x8000)
69
70 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
71
72 /* PRIVATE FUNCTIONS **********************************************************/
73
74 /*
75 * InitWindowImpl
76 *
77 * Initialize windowing implementation.
78 */
79
80 NTSTATUS FASTCALL
81 InitWindowImpl(VOID)
82 {
83 WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,WPH_SIZE * sizeof(WndProcHandle), TAG_WINPROCLST);
84 WndProcHandlesArraySize = WPH_SIZE;
85 return STATUS_SUCCESS;
86 }
87
88 /*
89 * CleanupWindowImpl
90 *
91 * Cleanup windowing implementation.
92 */
93
94 NTSTATUS FASTCALL
95 CleanupWindowImpl(VOID)
96 {
97 ExFreePool(WndProcHandlesArray);
98 WndProcHandlesArray = 0;
99 WndProcHandlesArraySize = 0;
100 return STATUS_SUCCESS;
101 }
102
103 /* HELPER FUNCTIONS ***********************************************************/
104
105 /*
106 * IntIsWindow
107 *
108 * The function determines whether the specified window handle identifies
109 * an existing window.
110 *
111 * Parameters
112 * hWnd
113 * Handle to the window to test.
114 *
115 * Return Value
116 * If the window handle identifies an existing window, the return value
117 * is TRUE. If the window handle does not identify an existing window,
118 * the return value is FALSE.
119 */
120
121 BOOL FASTCALL
122 IntIsWindow(HWND hWnd)
123 {
124 PWINDOW_OBJECT Window;
125
126 if (!(Window = IntGetWindowObject(hWnd)))
127 return FALSE;
128
129 IntReleaseWindowObject(Window);
130 return TRUE;
131 }
132
133 /*
134 * IntGetProcessWindowObject
135 *
136 * Get window object from handle of specified process.
137 */
138
139 PWINDOW_OBJECT FASTCALL
140 IntGetProcessWindowObject(PW32PROCESS ProcessData, HWND hWnd)
141 {
142 PWINDOW_OBJECT WindowObject;
143 NTSTATUS Status;
144
145 Status = ObmReferenceObjectByHandle(ProcessData->WindowStation->HandleTable,
146 hWnd, otWindow, (PVOID*)&WindowObject);
147 if (!NT_SUCCESS(Status))
148 {
149 return NULL;
150 }
151 return WindowObject;
152 }
153
154
155 PWINDOW_OBJECT FASTCALL
156 IntGetParent(PWINDOW_OBJECT Wnd)
157 {
158 HWND hWnd;
159
160 if (Wnd->Style & WS_POPUP)
161 {
162 IntLockRelatives(Wnd);
163 hWnd = Wnd->Owner;
164 IntUnLockRelatives(Wnd);
165 return IntGetWindowObject(hWnd);
166 }
167 else if (Wnd->Style & WS_CHILD)
168 {
169 IntLockRelatives(Wnd);
170 hWnd = Wnd->Parent;
171 IntUnLockRelatives(Wnd);
172 return IntGetWindowObject(hWnd);
173 }
174
175 return NULL;
176 }
177
178
179 PWINDOW_OBJECT FASTCALL
180 IntGetParentObject(PWINDOW_OBJECT Wnd)
181 {
182 HWND hParent;
183
184 IntLockRelatives(Wnd);
185 hParent = Wnd->Parent;
186 IntUnLockRelatives(Wnd);
187 return IntGetWindowObject(hParent);
188 }
189
190 /*
191 * IntWinListChildren
192 *
193 * Compile a list of all child window handles from given window.
194 *
195 * Remarks
196 * This function is similar to Wine WIN_ListChildren. The caller
197 * must free the returned list with ExFreePool.
198 */
199
200 HWND* FASTCALL
201 IntWinListChildren(PWINDOW_OBJECT Window)
202 {
203 PWINDOW_OBJECT Child;
204 HWND *List;
205 UINT Index, NumChildren = 0;
206
207 IntLockRelatives(Window);
208
209 for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
210 ++NumChildren;
211
212 List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), TAG_WINLIST);
213 if(!List)
214 {
215 DPRINT1("Failed to allocate memory for children array\n");
216 IntUnLockRelatives(Window);
217 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
218 return NULL;
219 }
220 for (Child = Window->FirstChild, Index = 0;
221 Child != NULL;
222 Child = Child->NextSibling, ++Index)
223 List[Index] = Child->Self;
224 List[Index] = NULL;
225
226 IntUnLockRelatives(Window);
227
228 return List;
229 }
230
231 /***********************************************************************
232 * IntSendDestroyMsg
233 */
234 static void IntSendDestroyMsg(HWND Wnd)
235 {
236 #if 0 /* FIXME */
237 GUITHREADINFO info;
238
239 if (GetGUIThreadInfo(GetCurrentThreadId(), &info))
240 {
241 if (Wnd == info.hwndCaret)
242 {
243 DestroyCaret();
244 }
245 }
246 #endif
247
248 /*
249 * Send the WM_DESTROY to the window.
250 */
251 IntSendMessage(Wnd, WM_DESTROY, 0, 0);
252
253 /*
254 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
255 * make sure that the window still exists when we come back.
256 */
257 #if 0 /* FIXME */
258 if (IsWindow(Wnd))
259 {
260 HWND* pWndArray;
261 int i;
262
263 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
264
265 /* start from the end (FIXME: is this needed?) */
266 for (i = 0; pWndArray[i]; i++) ;
267
268 while (--i >= 0)
269 {
270 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
271 }
272 HeapFree(GetProcessHeap(), 0, pWndArray);
273 }
274 else
275 {
276 DPRINT("destroyed itself while in WM_DESTROY!\n");
277 }
278 #endif
279 }
280
281 /***********************************************************************
282 * IntDestroyWindow
283 *
284 * Destroy storage associated to a window. "Internals" p.358
285 */
286 static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
287 PW32PROCESS ProcessData,
288 PW32THREAD ThreadData,
289 BOOLEAN SendMessages)
290 {
291 HWND *Children;
292 HWND *ChildHandle;
293 PWINDOW_OBJECT Child;
294 PMENU_OBJECT Menu;
295 BOOL BelongsToThreadData;
296
297 ASSERT(Window);
298
299 RemoveTimersWindow(Window->Self);
300
301 IntLockThreadWindows(Window->OwnerThread->Win32Thread);
302 if(Window->Status & WINDOWSTATUS_DESTROYING)
303 {
304 IntUnLockThreadWindows(Window->OwnerThread->Win32Thread);
305 DPRINT("Tried to call IntDestroyWindow() twice\n");
306 return 0;
307 }
308 Window->Status |= WINDOWSTATUS_DESTROYING;
309 /* remove the window already at this point from the thread window list so we
310 don't get into trouble when destroying the thread windows while we're still
311 in IntDestroyWindow() */
312 RemoveEntryList(&Window->ThreadListEntry);
313 IntUnLockThreadWindows(Window->OwnerThread->Win32Thread);
314
315 BelongsToThreadData = IntWndBelongsToThread(Window, ThreadData);
316
317 if(SendMessages)
318 {
319 /* Send destroy messages */
320 IntSendDestroyMsg(Window->Self);
321 }
322
323 /* free child windows */
324 Children = IntWinListChildren(Window);
325 if (Children)
326 {
327 for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
328 {
329 if ((Child = IntGetWindowObject(*ChildHandle)))
330 {
331 if(!IntWndBelongsToThread(Child, ThreadData))
332 {
333 /* send WM_DESTROY messages to windows not belonging to the same thread */
334 IntSendDestroyMsg(Child->Self);
335 }
336 else
337 IntDestroyWindow(Child, ProcessData, ThreadData, SendMessages);
338 IntReleaseWindowObject(Child);
339 }
340 }
341 ExFreePool(Children);
342 }
343
344 if (SendMessages)
345 {
346 /*
347 * Clear the update region to make sure no WM_PAINT messages will be
348 * generated for this window while processing the WM_NCDESTROY.
349 */
350 IntRedrawWindow(Window, NULL, 0,
351 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
352 RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
353
354 /*
355 * Send the WM_NCDESTROY to the window being destroyed.
356 */
357 if(BelongsToThreadData)
358 IntSendMessage(Window->Self, WM_NCDESTROY, 0, 0);
359 }
360
361 /* reset shell window handles */
362 if(ProcessData->WindowStation)
363 {
364 if (Window->Self == ProcessData->WindowStation->ShellWindow)
365 ProcessData->WindowStation->ShellWindow = NULL;
366
367 if (Window->Self == ProcessData->WindowStation->ShellListView)
368 ProcessData->WindowStation->ShellListView = NULL;
369 }
370
371 /* Unregister hot keys */
372 UnregisterWindowHotKeys (Window);
373
374 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
375
376 #if 0 /* FIXME */
377 WinPosCheckInternalPos(Window->Self);
378 if (Window->Self == GetCapture())
379 {
380 ReleaseCapture();
381 }
382
383 /* free resources associated with the window */
384 TIMER_RemoveWindowTimers(Window->Self);
385 #endif
386
387 if (!(Window->Style & WS_CHILD) && Window->IDMenu
388 && (Menu = IntGetMenuObject((HMENU)Window->IDMenu)))
389 {
390 IntDestroyMenuObject(Menu, TRUE, TRUE);
391 Window->IDMenu = 0;
392 IntReleaseMenuObject(Menu);
393 }
394
395 if(Window->SystemMenu
396 && (Menu = IntGetMenuObject(Window->SystemMenu)))
397 {
398 IntDestroyMenuObject(Menu, TRUE, TRUE);
399 Window->SystemMenu = (HMENU)0;
400 IntReleaseMenuObject(Menu);
401 }
402
403 DceFreeWindowDCE(Window); /* Always do this to catch orphaned DCs */
404 #if 0 /* FIXME */
405 WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);
406 CLASS_RemoveWindow(Window->Class);
407 #endif
408
409 IntUnlinkWindow(Window);
410
411 IntReferenceWindowObject(Window);
412 ObmCloseHandle(ProcessData->WindowStation->HandleTable, Window->Self);
413
414 IntDestroyScrollBars(Window);
415
416 IntLockThreadWindows(Window->OwnerThread->Win32Thread);
417 Window->Status |= WINDOWSTATUS_DESTROYED;
418 /* don't remove the WINDOWSTATUS_DESTROYING bit */
419 IntUnLockThreadWindows(Window->OwnerThread->Win32Thread);
420
421 ObmDereferenceObject(Window->Class);
422 Window->Class = NULL;
423
424 if(Window->WindowRegion)
425 {
426 NtGdiDeleteObject(Window->WindowRegion);
427 }
428
429 RtlFreeUnicodeString(&Window->WindowName);
430
431 IntReleaseWindowObject(Window);
432
433 return 0;
434 }
435
436 VOID FASTCALL
437 IntGetWindowBorderMeasures(PWINDOW_OBJECT WindowObject, INT *cx, INT *cy)
438 {
439 if(HAS_DLGFRAME(WindowObject->Style, WindowObject->ExStyle) && !(WindowObject->Style & WS_MINIMIZE))
440 {
441 *cx = NtUserGetSystemMetrics(SM_CXDLGFRAME);
442 *cy = NtUserGetSystemMetrics(SM_CYDLGFRAME);
443 }
444 else
445 {
446 if(HAS_THICKFRAME(WindowObject->Style, WindowObject->ExStyle)&& !(WindowObject->Style & WS_MINIMIZE))
447 {
448 *cx = NtUserGetSystemMetrics(SM_CXFRAME);
449 *cy = NtUserGetSystemMetrics(SM_CYFRAME);
450 }
451 else if(HAS_THINFRAME(WindowObject->Style, WindowObject->ExStyle))
452 {
453 *cx = NtUserGetSystemMetrics(SM_CXBORDER);
454 *cy = NtUserGetSystemMetrics(SM_CYBORDER);
455 }
456 else
457 {
458 *cx = *cy = 0;
459 }
460 }
461 }
462
463 BOOL FASTCALL
464 IntGetWindowInfo(PWINDOW_OBJECT WindowObject, PWINDOWINFO pwi)
465 {
466 pwi->cbSize = sizeof(WINDOWINFO);
467 pwi->rcWindow = WindowObject->WindowRect;
468 pwi->rcClient = WindowObject->ClientRect;
469 pwi->dwStyle = WindowObject->Style;
470 pwi->dwExStyle = WindowObject->ExStyle;
471 pwi->dwWindowStatus = (NtUserGetForegroundWindow() == WindowObject->Self); /* WS_ACTIVECAPTION */
472 IntGetWindowBorderMeasures(WindowObject, &pwi->cxWindowBorders, &pwi->cyWindowBorders);
473 pwi->atomWindowType = (WindowObject->Class ? WindowObject->Class->Atom : 0);
474 pwi->wCreatorVersion = 0x400; /* FIXME - return a real version number */
475 return TRUE;
476 }
477
478 static BOOL FASTCALL
479 IntSetMenu(
480 PWINDOW_OBJECT WindowObject,
481 HMENU Menu,
482 BOOL *Changed)
483 {
484 PMENU_OBJECT OldMenuObject, NewMenuObject;
485
486 *Changed = (WindowObject->IDMenu != (UINT) Menu);
487 if (! *Changed)
488 {
489 return TRUE;
490 }
491
492 if (0 != WindowObject->IDMenu)
493 {
494 OldMenuObject = IntGetMenuObject((HMENU) WindowObject->IDMenu);
495 ASSERT(NULL == OldMenuObject || OldMenuObject->MenuInfo.Wnd == WindowObject->Self);
496 }
497 else
498 {
499 OldMenuObject = NULL;
500 }
501
502 if (NULL != Menu)
503 {
504 NewMenuObject = IntGetMenuObject(Menu);
505 if (NULL == NewMenuObject)
506 {
507 if (NULL != OldMenuObject)
508 {
509 IntReleaseMenuObject(OldMenuObject);
510 }
511 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
512 return FALSE;
513 }
514 if (NULL != NewMenuObject->MenuInfo.Wnd)
515 {
516 /* Can't use the same menu for two windows */
517 if (NULL != OldMenuObject)
518 {
519 IntReleaseMenuObject(OldMenuObject);
520 }
521 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
522 return FALSE;
523 }
524
525 }
526
527 WindowObject->IDMenu = (UINT) Menu;
528 if (NULL != NewMenuObject)
529 {
530 NewMenuObject->MenuInfo.Wnd = WindowObject->Self;
531 IntReleaseMenuObject(NewMenuObject);
532 }
533 if (NULL != OldMenuObject)
534 {
535 OldMenuObject->MenuInfo.Wnd = NULL;
536 IntReleaseMenuObject(OldMenuObject);
537 }
538
539 return TRUE;
540 }
541
542
543 /* INTERNAL ******************************************************************/
544
545
546 VOID FASTCALL
547 DestroyThreadWindows(struct _ETHREAD *Thread)
548 {
549 PLIST_ENTRY Current;
550 PW32PROCESS Win32Process;
551 PW32THREAD Win32Thread;
552 PWINDOW_OBJECT *List, *pWnd;
553 ULONG Cnt = 0;
554
555 Win32Thread = Thread->Win32Thread;
556 Win32Process = Thread->ThreadsProcess->Win32Process;
557
558 IntLockThreadWindows(Win32Thread);
559 Current = Win32Thread->WindowListHead.Flink;
560 while (Current != &(Win32Thread->WindowListHead))
561 {
562 Cnt++;
563 Current = Current->Flink;
564 }
565
566 if(Cnt > 0)
567 {
568 List = ExAllocatePool(PagedPool, (Cnt + 1) * sizeof(PWINDOW_OBJECT));
569 if(!List)
570 {
571 DPRINT("Not enough memory to allocate window handle list\n");
572 IntUnLockThreadWindows(Win32Thread);
573 return;
574 }
575 pWnd = List;
576 Current = Win32Thread->WindowListHead.Flink;
577 while (Current != &(Win32Thread->WindowListHead))
578 {
579 *pWnd = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);
580 IntReferenceWindowObject(*pWnd);
581 pWnd++;
582 Current = Current->Flink;
583 }
584 IntUnLockThreadWindows(Win32Thread);
585 *pWnd = NULL;
586
587 for(pWnd = List; *pWnd; pWnd++)
588 {
589 NtUserDestroyWindow((*pWnd)->Self);
590 IntReleaseWindowObject(*pWnd);
591 }
592 ExFreePool(List);
593 return;
594 }
595
596 IntUnLockThreadWindows(Win32Thread);
597 }
598
599
600 /*!
601 * Internal function.
602 * Returns client window rectangle relative to the upper-left corner of client area.
603 *
604 * \note Does not check the validity of the parameters
605 */
606 VOID FASTCALL
607 IntGetClientRect(PWINDOW_OBJECT WindowObject, PRECT Rect)
608 {
609 ASSERT( WindowObject );
610 ASSERT( Rect );
611
612 Rect->left = Rect->top = 0;
613 Rect->right = WindowObject->ClientRect.right - WindowObject->ClientRect.left;
614 Rect->bottom = WindowObject->ClientRect.bottom - WindowObject->ClientRect.top;
615 }
616
617
618 #if 0
619 HWND FASTCALL
620 IntGetFocusWindow(VOID)
621 {
622 PUSER_MESSAGE_QUEUE Queue;
623 PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
624
625 if( !pdo )
626 return NULL;
627
628 Queue = (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
629
630 if (Queue == NULL)
631 return(NULL);
632 else
633 return(Queue->FocusWindow);
634 }
635 #endif
636
637 PMENU_OBJECT FASTCALL
638 IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert, BOOL RetMenu)
639 {
640 PMENU_OBJECT MenuObject, NewMenuObject, SysMenuObject, ret = NULL;
641 PW32PROCESS W32Process;
642 HMENU NewMenu, SysMenu;
643 ROSMENUITEMINFO ItemInfo;
644
645 if(bRevert)
646 {
647 W32Process = PsGetWin32Process();
648
649 if(!W32Process->WindowStation)
650 return NULL;
651
652 if(WindowObject->SystemMenu)
653 {
654 MenuObject = IntGetMenuObject(WindowObject->SystemMenu);
655 if(MenuObject)
656 {
657 IntDestroyMenuObject(MenuObject, FALSE, TRUE);
658 WindowObject->SystemMenu = (HMENU)0;
659 IntReleaseMenuObject(MenuObject);
660 }
661 }
662
663 if(W32Process->WindowStation->SystemMenuTemplate)
664 {
665 /* clone system menu */
666 MenuObject = IntGetMenuObject(W32Process->WindowStation->SystemMenuTemplate);
667 if(!MenuObject)
668 return NULL;
669
670 NewMenuObject = IntCloneMenu(MenuObject);
671 if(NewMenuObject)
672 {
673 WindowObject->SystemMenu = NewMenuObject->MenuInfo.Self;
674 NewMenuObject->MenuInfo.Flags |= MF_SYSMENU;
675 NewMenuObject->MenuInfo.Wnd = WindowObject->Self;
676 ret = NewMenuObject;
677 //IntReleaseMenuObject(NewMenuObject);
678 }
679 IntReleaseMenuObject(MenuObject);
680 }
681 else
682 {
683 SysMenu = NtUserCreateMenu(FALSE);
684 if (NULL == SysMenu)
685 {
686 return NULL;
687 }
688 SysMenuObject = IntGetMenuObject(SysMenu);
689 if (NULL == SysMenuObject)
690 {
691 NtUserDestroyMenu(SysMenu);
692 return NULL;
693 }
694 SysMenuObject->MenuInfo.Flags |= MF_SYSMENU;
695 SysMenuObject->MenuInfo.Wnd = WindowObject->Self;
696 NewMenu = IntLoadSysMenuTemplate();
697 if(!NewMenu)
698 {
699 IntReleaseMenuObject(SysMenuObject);
700 NtUserDestroyMenu(SysMenu);
701 return NULL;
702 }
703 MenuObject = IntGetMenuObject(NewMenu);
704 if(!MenuObject)
705 {
706 IntReleaseMenuObject(SysMenuObject);
707 NtUserDestroyMenu(SysMenu);
708 return NULL;
709 }
710
711 NewMenuObject = IntCloneMenu(MenuObject);
712 if(NewMenuObject)
713 {
714 NewMenuObject->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP;
715 IntReleaseMenuObject(NewMenuObject);
716 NtUserSetMenuDefaultItem(NewMenuObject->MenuInfo.Self, SC_CLOSE, FALSE);
717
718 ItemInfo.cbSize = sizeof(MENUITEMINFOW);
719 ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
720 ItemInfo.fType = MF_POPUP;
721 ItemInfo.fState = MFS_ENABLED;
722 ItemInfo.dwTypeData = NULL;
723 ItemInfo.cch = 0;
724 ItemInfo.hSubMenu = NewMenuObject->MenuInfo.Self;
725 IntInsertMenuItem(SysMenuObject, (UINT) -1, TRUE, &ItemInfo);
726
727 WindowObject->SystemMenu = SysMenuObject->MenuInfo.Self;
728
729 ret = SysMenuObject;
730 }
731 IntDestroyMenuObject(MenuObject, FALSE, TRUE);
732 IntReleaseMenuObject(MenuObject);
733 }
734 if(RetMenu)
735 return ret;
736 else
737 return NULL;
738 }
739 else
740 {
741 if(WindowObject->SystemMenu)
742 return IntGetMenuObject((HMENU)WindowObject->SystemMenu);
743 else
744 return NULL;
745 }
746 }
747
748
749 BOOL FASTCALL
750 IntIsChildWindow(HWND Parent, HWND Child)
751 {
752 PWINDOW_OBJECT BaseWindow, Window, Old;
753
754 if(!(BaseWindow = IntGetWindowObject(Child)))
755 {
756 return FALSE;
757 }
758
759 Window = BaseWindow;
760 while (Window)
761 {
762 if (Window->Self == Parent)
763 {
764 if(Window != BaseWindow)
765 IntReleaseWindowObject(Window);
766 IntReleaseWindowObject(BaseWindow);
767 return(TRUE);
768 }
769 if(!(Window->Style & WS_CHILD))
770 {
771 if(Window != BaseWindow)
772 IntReleaseWindowObject(Window);
773 break;
774 }
775 Old = Window;
776 Window = IntGetParentObject(Window);
777 if(Old != BaseWindow)
778 IntReleaseWindowObject(Old);
779 }
780
781 IntReleaseWindowObject(BaseWindow);
782 return(FALSE);
783 }
784
785 BOOL FASTCALL
786 IntIsWindowVisible(HWND hWnd)
787 {
788 PWINDOW_OBJECT BaseWindow, Window, Old;
789
790 if(!(BaseWindow = IntGetWindowObject(hWnd)))
791 {
792 return FALSE;
793 }
794
795 Window = BaseWindow;
796 while(Window)
797 {
798 if(!(Window->Style & WS_CHILD))
799 {
800 break;
801 }
802 if(!(Window->Style & WS_VISIBLE))
803 {
804 if(Window != BaseWindow)
805 IntReleaseWindowObject(Window);
806 IntReleaseWindowObject(BaseWindow);
807 return FALSE;
808 }
809 Old = Window;
810 Window = IntGetParentObject(Window);
811 if(Old != BaseWindow)
812 IntReleaseWindowObject(Old);
813 }
814
815 if(Window)
816 {
817 if(Window->Style & WS_VISIBLE)
818 {
819 if(Window != BaseWindow)
820 IntReleaseWindowObject(Window);
821 IntReleaseWindowObject(BaseWindow);
822 return TRUE;
823 }
824 if(Window != BaseWindow)
825 IntReleaseWindowObject(Window);
826 }
827 IntReleaseWindowObject(BaseWindow);
828 return FALSE;
829 }
830
831
832 /* link the window into siblings and parent. children are kept in place. */
833 VOID FASTCALL
834 IntLinkWindow(
835 PWINDOW_OBJECT Wnd,
836 PWINDOW_OBJECT WndParent,
837 PWINDOW_OBJECT WndPrevSibling /* set to NULL if top sibling */
838 )
839 {
840 PWINDOW_OBJECT Parent;
841
842 IntLockRelatives(Wnd);
843 Wnd->Parent = WndParent->Self;
844 if ((Wnd->PrevSibling = WndPrevSibling))
845 {
846 /* link after WndPrevSibling */
847 if ((Wnd->NextSibling = WndPrevSibling->NextSibling))
848 Wnd->NextSibling->PrevSibling = Wnd;
849 else if ((Parent = IntGetWindowObject(Wnd->Parent)))
850 {
851 IntLockRelatives(Parent);
852 if(Parent->LastChild == WndPrevSibling)
853 Parent->LastChild = Wnd;
854 IntUnLockRelatives(Parent);
855 IntReleaseWindowObject(Parent);
856 }
857 Wnd->PrevSibling->NextSibling = Wnd;
858 }
859 else
860 {
861 /* link at top */
862 Parent = IntGetWindowObject(Wnd->Parent);
863 if ((Wnd->NextSibling = WndParent->FirstChild))
864 Wnd->NextSibling->PrevSibling = Wnd;
865 else if (Parent)
866 {
867 IntLockRelatives(Parent);
868 Parent->LastChild = Wnd;
869 Parent->FirstChild = Wnd;
870 IntUnLockRelatives(Parent);
871 IntReleaseWindowObject(Parent);
872 IntUnLockRelatives(Wnd);
873 return;
874 }
875 if(Parent)
876 {
877 IntLockRelatives(Parent);
878 Parent->FirstChild = Wnd;
879 IntUnLockRelatives(Parent);
880 IntReleaseWindowObject(Parent);
881 }
882 }
883 IntUnLockRelatives(Wnd);
884 }
885
886 HWND FASTCALL
887 IntSetOwner(HWND hWnd, HWND hWndNewOwner)
888 {
889 PWINDOW_OBJECT Wnd, WndOldOwner, WndNewOwner;
890 HWND ret;
891
892 Wnd = IntGetWindowObject(hWnd);
893 if(!Wnd)
894 return NULL;
895
896 IntLockRelatives(Wnd);
897 WndOldOwner = IntGetWindowObject(Wnd->Owner);
898 if (WndOldOwner)
899 {
900 ret = WndOldOwner->Self;
901 IntReleaseWindowObject(WndOldOwner);
902 }
903 else
904 {
905 ret = 0;
906 }
907
908 if((WndNewOwner = IntGetWindowObject(hWndNewOwner)))
909 {
910 Wnd->Owner = hWndNewOwner;
911 IntReleaseWindowObject(WndNewOwner);
912 }
913 else
914 Wnd->Owner = NULL;
915
916 IntUnLockRelatives(Wnd);
917 IntReleaseWindowObject(Wnd);
918 return ret;
919 }
920
921 PWINDOW_OBJECT FASTCALL
922 IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
923 {
924 PWINDOW_OBJECT WndOldParent, Sibling, InsertAfter;
925 HWND hWnd, hWndNewParent, hWndOldParent;
926 BOOL WasVisible;
927 BOOL MenuChanged;
928
929 ASSERT(Wnd);
930 ASSERT(WndNewParent);
931
932 hWnd = Wnd->Self;
933 hWndNewParent = WndNewParent->Self;
934
935 /*
936 * Windows hides the window first, then shows it again
937 * including the WM_SHOWWINDOW messages and all
938 */
939 WasVisible = WinPosShowWindow(hWnd, SW_HIDE);
940
941 /* Validate that window and parent still exist */
942 if (!IntIsWindow(hWnd) || !IntIsWindow(hWndNewParent))
943 return NULL;
944
945 /* Window must belong to current process */
946 if (Wnd->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
947 return NULL;
948
949 WndOldParent = IntGetParentObject(Wnd);
950 hWndOldParent = (WndOldParent ? WndOldParent->Self : NULL);
951
952 if (WndNewParent != WndOldParent)
953 {
954 IntUnlinkWindow(Wnd);
955 InsertAfter = NULL;
956 if (0 == (Wnd->ExStyle & WS_EX_TOPMOST))
957 {
958 /* Not a TOPMOST window, put after TOPMOSTs of new parent */
959 IntLockRelatives(WndNewParent);
960 Sibling = WndNewParent->FirstChild;
961 while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
962 {
963 InsertAfter = Sibling;
964 Sibling = Sibling->NextSibling;
965 }
966 IntUnLockRelatives(WndNewParent);
967 }
968 if (NULL == InsertAfter)
969 {
970 IntLinkWindow(Wnd, WndNewParent, InsertAfter /*prev sibling*/);
971 }
972 else
973 {
974 IntReferenceWindowObject(InsertAfter);
975 IntLinkWindow(Wnd, WndNewParent, InsertAfter /*prev sibling*/);
976 IntReleaseWindowObject(InsertAfter);
977 }
978
979 if (WndNewParent->Self != IntGetDesktopWindow()) /* a child window */
980 {
981 if (!(Wnd->Style & WS_CHILD))
982 {
983 //if ( Wnd->Menu ) DestroyMenu ( Wnd->menu );
984 IntSetMenu(Wnd, NULL, &MenuChanged);
985 }
986 }
987 }
988
989 /*
990 * SetParent additionally needs to make hwnd the top window
991 * in the z-order and send the expected WM_WINDOWPOSCHANGING and
992 * WM_WINDOWPOSCHANGED notification messages.
993 */
994 WinPosSetWindowPos(hWnd, (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST),
995 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
996 | (WasVisible ? SWP_SHOWWINDOW : 0));
997
998 /*
999 * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1000 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
1001 */
1002
1003 /*
1004 * Validate that the old parent still exist, since it migth have been
1005 * destroyed during the last callbacks to user-mode
1006 */
1007 if(WndOldParent)
1008 {
1009 if(!IntIsWindow(WndOldParent->Self))
1010 {
1011 IntReleaseWindowObject(WndOldParent);
1012 return NULL;
1013 }
1014
1015 /* don't dereference the window object here, it must be done by the caller
1016 of IntSetParent() */
1017 return WndOldParent;
1018 }
1019 return NULL;
1020 }
1021
1022 BOOL FASTCALL
1023 IntSetSystemMenu(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject)
1024 {
1025 PMENU_OBJECT OldMenuObject;
1026 if(WindowObject->SystemMenu)
1027 {
1028 OldMenuObject = IntGetMenuObject(WindowObject->SystemMenu);
1029 if(OldMenuObject)
1030 {
1031 OldMenuObject->MenuInfo.Flags &= ~ MF_SYSMENU;
1032 IntReleaseMenuObject(OldMenuObject);
1033 }
1034 }
1035
1036 if(MenuObject)
1037 {
1038 /* FIXME check window style, propably return FALSE ? */
1039 WindowObject->SystemMenu = MenuObject->MenuInfo.Self;
1040 MenuObject->MenuInfo.Flags |= MF_SYSMENU;
1041 }
1042 else
1043 WindowObject->SystemMenu = (HMENU)0;
1044
1045 return TRUE;
1046 }
1047
1048
1049 /* unlink the window from siblings and parent. children are kept in place. */
1050 VOID FASTCALL
1051 IntUnlinkWindow(PWINDOW_OBJECT Wnd)
1052 {
1053 PWINDOW_OBJECT WndParent;
1054
1055 IntLockRelatives(Wnd);
1056 if((WndParent = IntGetWindowObject(Wnd->Parent)))
1057 {
1058 IntLockRelatives(WndParent);
1059 }
1060
1061 if (Wnd->NextSibling) Wnd->NextSibling->PrevSibling = Wnd->PrevSibling;
1062 else if (WndParent && WndParent->LastChild == Wnd) WndParent->LastChild = Wnd->PrevSibling;
1063
1064 if (Wnd->PrevSibling) Wnd->PrevSibling->NextSibling = Wnd->NextSibling;
1065 else if (WndParent && WndParent->FirstChild == Wnd) WndParent->FirstChild = Wnd->NextSibling;
1066
1067 if(WndParent)
1068 {
1069 IntUnLockRelatives(WndParent);
1070 IntReleaseWindowObject(WndParent);
1071 }
1072 Wnd->PrevSibling = Wnd->NextSibling = Wnd->Parent = NULL;
1073 IntUnLockRelatives(Wnd);
1074 }
1075
1076 BOOL FASTCALL
1077 IntAnyPopup(VOID)
1078 {
1079 PWINDOW_OBJECT Window, Child;
1080
1081 if(!(Window = IntGetWindowObject(IntGetDesktopWindow())))
1082 {
1083 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1084 return FALSE;
1085 }
1086
1087 IntLockRelatives(Window);
1088 for(Child = Window->FirstChild; Child; Child = Child->NextSibling)
1089 {
1090 if(Child->Owner && Child->Style & WS_VISIBLE)
1091 {
1092 /*
1093 * The desktop has a popup window if one of them has
1094 * an owner window and is visible
1095 */
1096 IntUnLockRelatives(Window);
1097 IntReleaseWindowObject(Window);
1098 return TRUE;
1099 }
1100 }
1101 IntUnLockRelatives(Window);
1102 IntReleaseWindowObject(Window);
1103 return FALSE;
1104 }
1105
1106 BOOL FASTCALL
1107 IntIsWindowInDestroy(PWINDOW_OBJECT Window)
1108 {
1109 return ((Window->Status & WINDOWSTATUS_DESTROYING) == WINDOWSTATUS_DESTROYING);
1110 }
1111
1112 /* FUNCTIONS *****************************************************************/
1113
1114 /*
1115 * @unimplemented
1116 */
1117 DWORD STDCALL
1118 NtUserAlterWindowStyle(DWORD Unknown0,
1119 DWORD Unknown1,
1120 DWORD Unknown2)
1121 {
1122 UNIMPLEMENTED
1123
1124 return(0);
1125 }
1126
1127
1128 /*
1129 * As best as I can figure, this function is used by EnumWindows,
1130 * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1131 *
1132 * It's supposed to build a list of HWNDs to return to the caller.
1133 * We can figure out what kind of list by what parameters are
1134 * passed to us.
1135 */
1136 /*
1137 * @implemented
1138 */
1139 ULONG
1140 STDCALL
1141 NtUserBuildHwndList(
1142 HDESK hDesktop,
1143 HWND hwndParent,
1144 BOOLEAN bChildren,
1145 ULONG dwThreadId,
1146 ULONG lParam,
1147 HWND* pWnd,
1148 ULONG nBufSize)
1149 {
1150 NTSTATUS Status;
1151 ULONG dwCount = 0;
1152
1153 /* FIXME handle bChildren */
1154
1155 if(hwndParent)
1156 {
1157 PWINDOW_OBJECT Window, Child;
1158 if(!(Window = IntGetWindowObject(hwndParent)))
1159 {
1160 SetLastWin32Error(ERROR_INVALID_HANDLE);
1161 return 0;
1162 }
1163
1164 IntLockRelatives(Window);
1165 for(Child = Window->FirstChild; Child != NULL; Child = Child->NextSibling)
1166 {
1167 if(dwCount++ < nBufSize && pWnd)
1168 {
1169 Status = MmCopyToCaller(pWnd++, &Child->Self, sizeof(HWND));
1170 if(!NT_SUCCESS(Status))
1171 {
1172 SetLastNtError(Status);
1173 break;
1174 }
1175 }
1176 }
1177 IntUnLockRelatives(Window);
1178
1179 IntReleaseWindowObject(Window);
1180 }
1181 else if(dwThreadId)
1182 {
1183 PETHREAD Thread;
1184 PW32THREAD W32Thread;
1185 PLIST_ENTRY Current;
1186 PWINDOW_OBJECT *Window;
1187
1188 Status = PsLookupThreadByThreadId((PVOID)dwThreadId, &Thread);
1189 if(!NT_SUCCESS(Status))
1190 {
1191 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1192 return 0;
1193 }
1194 if(!(W32Thread = Thread->Win32Thread))
1195 {
1196 ObDereferenceObject(Thread);
1197 DPRINT1("Thread is not a GUI Thread!\n");
1198 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1199 return 0;
1200 }
1201
1202 IntLockThreadWindows(W32Thread);
1203 Current = W32Thread->WindowListHead.Flink;
1204 while(Current != &(W32Thread->WindowListHead))
1205 {
1206 *Window = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);
1207 ASSERT(*Window);
1208
1209 if(dwCount < nBufSize && pWnd && ((*Window)->Style & WS_CHILD))
1210 {
1211 Status = MmCopyToCaller(pWnd++, &(*Window)->Self, sizeof(HWND));
1212 if(!NT_SUCCESS(Status))
1213 {
1214 SetLastNtError(Status);
1215 break;
1216 }
1217 }
1218
1219 if(!((*Window)->Style & WS_CHILD))
1220 {
1221 dwCount++;
1222 }
1223
1224 Current = Current->Flink;
1225 }
1226 IntUnLockThreadWindows(W32Thread);
1227
1228 ObDereferenceObject(Thread);
1229 }
1230 else
1231 {
1232 PDESKTOP_OBJECT Desktop;
1233 PWINDOW_OBJECT Window, Child;
1234
1235 if(hDesktop == NULL && !(Desktop = IntGetActiveDesktop()))
1236 {
1237 SetLastWin32Error(ERROR_INVALID_HANDLE);
1238 return 0;
1239 }
1240
1241 if(hDesktop)
1242 {
1243 Status = IntValidateDesktopHandle(hDesktop,
1244 UserMode,
1245 0,
1246 &Desktop);
1247 if(!NT_SUCCESS(Status))
1248 {
1249 SetLastWin32Error(ERROR_INVALID_HANDLE);
1250 return 0;
1251 }
1252 }
1253 if(!(Window = IntGetWindowObject(Desktop->DesktopWindow)))
1254 {
1255 if(hDesktop)
1256 ObDereferenceObject(Desktop);
1257 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1258 return 0;
1259 }
1260
1261 IntLockRelatives(Window);
1262 for(Child = Window->FirstChild; Child != NULL; Child = Child->NextSibling)
1263 {
1264 if(dwCount++ < nBufSize && pWnd)
1265 {
1266 Status = MmCopyToCaller(pWnd++, &Child->Self, sizeof(HWND));
1267 if(!NT_SUCCESS(Status))
1268 {
1269 SetLastNtError(Status);
1270 break;
1271 }
1272 }
1273 }
1274 IntUnLockRelatives(Window);
1275
1276 IntReleaseWindowObject(Window);
1277 if(hDesktop)
1278 ObDereferenceObject(Desktop);
1279 }
1280
1281 return dwCount;
1282 }
1283
1284
1285 /*
1286 * @implemented
1287 */
1288 HWND STDCALL
1289 NtUserChildWindowFromPointEx(HWND hwndParent,
1290 LONG x,
1291 LONG y,
1292 UINT uiFlags)
1293 {
1294 PWINDOW_OBJECT Parent;
1295 POINTL Pt;
1296 HWND Ret;
1297 HWND *List, *phWnd;
1298
1299 if(!(Parent = IntGetWindowObject(hwndParent)))
1300 {
1301 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1302 return NULL;
1303 }
1304
1305 Pt.x = x;
1306 Pt.y = y;
1307
1308 if(Parent->Self != IntGetDesktopWindow())
1309 {
1310 Pt.x += Parent->ClientRect.left;
1311 Pt.y += Parent->ClientRect.top;
1312 }
1313
1314 if(!IntPtInWindow(Parent, Pt.x, Pt.y))
1315 {
1316 IntReleaseWindowObject(Parent);
1317 return NULL;
1318 }
1319
1320 Ret = Parent->Self;
1321 if((List = IntWinListChildren(Parent)))
1322 {
1323 for(phWnd = List; *phWnd; phWnd++)
1324 {
1325 PWINDOW_OBJECT Child;
1326 if((Child = IntGetWindowObject(*phWnd)))
1327 {
1328 if(!(Child->Style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE))
1329 {
1330 IntReleaseWindowObject(Child);
1331 continue;
1332 }
1333 if((Child->Style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED))
1334 {
1335 IntReleaseWindowObject(Child);
1336 continue;
1337 }
1338 if((Child->ExStyle & WS_EX_TRANSPARENT) && (uiFlags & CWP_SKIPTRANSPARENT))
1339 {
1340 IntReleaseWindowObject(Child);
1341 continue;
1342 }
1343 if(IntPtInWindow(Child, Pt.x, Pt.y))
1344 {
1345 Ret = Child->Self;
1346 IntReleaseWindowObject(Child);
1347 break;
1348 }
1349 IntReleaseWindowObject(Child);
1350 }
1351 }
1352 ExFreePool(List);
1353 }
1354
1355 IntReleaseWindowObject(Parent);
1356 return Ret;
1357 }
1358
1359
1360 /*
1361 * calculates the default position of a window
1362 */
1363 BOOL FASTCALL
1364 IntCalcDefPosSize(PWINDOW_OBJECT Parent, PWINDOW_OBJECT WindowObject, RECT *rc, BOOL IncPos)
1365 {
1366 SIZE Sz;
1367 POINT Pos;
1368
1369 if(Parent != NULL)
1370 {
1371 NtGdiIntersectRect(rc, rc, &Parent->ClientRect);
1372
1373 if(IncPos)
1374 {
1375 Pos.x = Parent->TiledCounter * (NtUserGetSystemMetrics(SM_CXSIZE) + NtUserGetSystemMetrics(SM_CXFRAME));
1376 Pos.y = Parent->TiledCounter * (NtUserGetSystemMetrics(SM_CYSIZE) + NtUserGetSystemMetrics(SM_CYFRAME));
1377 if(Pos.x > ((rc->right - rc->left) / 4) ||
1378 Pos.y > ((rc->bottom - rc->top) / 4))
1379 {
1380 /* reset counter and position */
1381 Pos.x = 0;
1382 Pos.y = 0;
1383 Parent->TiledCounter = 0;
1384 }
1385 Parent->TiledCounter++;
1386 }
1387 Pos.x += rc->left;
1388 Pos.y += rc->top;
1389 }
1390 else
1391 {
1392 Pos.x = rc->left;
1393 Pos.y = rc->top;
1394 }
1395
1396 Sz.cx = EngMulDiv(rc->right - rc->left, 3, 4);
1397 Sz.cy = EngMulDiv(rc->bottom - rc->top, 3, 4);
1398
1399 rc->left = Pos.x;
1400 rc->top = Pos.y;
1401 rc->right = rc->left + Sz.cx;
1402 rc->bottom = rc->top + Sz.cy;
1403 return TRUE;
1404 }
1405
1406
1407 /*
1408 * @implemented
1409 */
1410 HWND STDCALL
1411 NtUserCreateWindowEx(DWORD dwExStyle,
1412 PUNICODE_STRING lpClassName,
1413 PUNICODE_STRING lpWindowName,
1414 DWORD dwStyle,
1415 LONG x,
1416 LONG y,
1417 LONG nWidth,
1418 LONG nHeight,
1419 HWND hWndParent,
1420 HMENU hMenu,
1421 HINSTANCE hInstance,
1422 LPVOID lpParam,
1423 DWORD dwShowMode,
1424 BOOL bUnicodeWindow)
1425 {
1426 PWINSTATION_OBJECT WinStaObject;
1427 PWNDCLASS_OBJECT ClassObject;
1428 PWINDOW_OBJECT WindowObject;
1429 PWINDOW_OBJECT ParentWindow, OwnerWindow;
1430 HWND ParentWindowHandle;
1431 HWND OwnerWindowHandle;
1432 PMENU_OBJECT SystemMenu;
1433 UNICODE_STRING WindowName;
1434 NTSTATUS Status;
1435 HANDLE Handle;
1436 POINT Pos;
1437 SIZE Size;
1438 #if 0
1439 POINT MaxSize, MaxPos, MinTrack, MaxTrack;
1440 #else
1441 POINT MaxPos;
1442 #endif
1443 CREATESTRUCTW Cs;
1444 CBT_CREATEWNDW CbtCreate;
1445 LRESULT Result;
1446 BOOL MenuChanged;
1447 LPWSTR OrigWindowName = NULL;
1448
1449 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
1450
1451 /* safely copy the window name */
1452 if(lpWindowName)
1453 {
1454 Status = MmCopyFromCaller(&WindowName, lpWindowName, sizeof(UNICODE_STRING));
1455 if (!NT_SUCCESS(Status))
1456 {
1457 SetLastNtError(Status);
1458 return((HWND)0);
1459 }
1460 if(WindowName.Buffer)
1461 {
1462 /* safe the original pointer to the window name */
1463 OrigWindowName = WindowName.Buffer;
1464
1465 if(!(WindowName.Buffer = ExAllocatePoolWithTag(NonPagedPool, WindowName.MaximumLength, TAG_STRING)))
1466 {
1467 SetLastNtError(STATUS_NO_MEMORY);
1468 return((HWND)0);
1469 }
1470
1471 Status = MmCopyFromCaller(WindowName.Buffer, OrigWindowName, WindowName.MaximumLength);
1472 if(!NT_SUCCESS(Status))
1473 {
1474 ExFreePool(WindowName.Buffer);
1475 SetLastNtError(Status);
1476 return((HWND)0);
1477 }
1478 }
1479
1480 if(!WindowName.Buffer)
1481 RtlInitUnicodeString(&WindowName, NULL);
1482 }
1483 else
1484 RtlInitUnicodeString(&WindowName, NULL);
1485
1486 ParentWindowHandle = PsGetWin32Thread()->Desktop->DesktopWindow;
1487 OwnerWindowHandle = NULL;
1488
1489 if (hWndParent == HWND_MESSAGE)
1490 {
1491 /*
1492 * native ole32.OleInitialize uses HWND_MESSAGE to create the
1493 * message window (style: WS_POPUP|WS_DISABLED)
1494 */
1495 UNIMPLEMENTED;
1496 }
1497 else if (hWndParent)
1498 {
1499 if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD)
1500 ParentWindowHandle = hWndParent;
1501 else
1502 OwnerWindowHandle = NtUserGetAncestor(hWndParent, GA_ROOT);
1503 }
1504 else if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD)
1505 {
1506 RtlFreeUnicodeString(&WindowName);
1507 return (HWND)0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1508 }
1509
1510 if (NULL != ParentWindowHandle)
1511 {
1512 ParentWindow = IntGetWindowObject(ParentWindowHandle);
1513 }
1514 else
1515 {
1516 ParentWindow = NULL;
1517 }
1518
1519 /* FIXME: parent must belong to the current process */
1520
1521 /* Check the class. */
1522 Status = ClassReferenceClassByNameOrAtom(&ClassObject, lpClassName->Buffer);
1523 if (!NT_SUCCESS(Status))
1524 {
1525 RtlFreeUnicodeString(&WindowName);
1526 if (NULL != ParentWindow)
1527 {
1528 IntReleaseWindowObject(ParentWindow);
1529 }
1530 return((HWND)0);
1531 }
1532
1533 /* Check the window station. */
1534 DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
1535 DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
1536 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1537 KernelMode,
1538 0,
1539 &WinStaObject);
1540 if (!NT_SUCCESS(Status))
1541 {
1542 ObmDereferenceObject(ClassObject);
1543 RtlFreeUnicodeString(&WindowName);
1544 if (NULL != ParentWindow)
1545 {
1546 IntReleaseWindowObject(ParentWindow);
1547 }
1548 DPRINT("Validation of window station handle (0x%X) failed\n",
1549 PROCESS_WINDOW_STATION());
1550 return (HWND)0;
1551 }
1552
1553 /* Create the window object. */
1554 WindowObject = (PWINDOW_OBJECT)
1555 ObmCreateObject(PsGetWin32Process()->WindowStation->HandleTable, &Handle,
1556 otWindow, sizeof(WINDOW_OBJECT) + ClassObject->cbWndExtra
1557 );
1558
1559 DPRINT("Created object with handle %X\n", Handle);
1560 if (!WindowObject)
1561 {
1562 ObDereferenceObject(WinStaObject);
1563 ObmDereferenceObject(ClassObject);
1564 RtlFreeUnicodeString(&WindowName);
1565 if (NULL != ParentWindow)
1566 {
1567 IntReleaseWindowObject(ParentWindow);
1568 }
1569 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
1570 return (HWND)0;
1571 }
1572 ObDereferenceObject(WinStaObject);
1573
1574 if (NULL == PsGetWin32Thread()->Desktop->DesktopWindow)
1575 {
1576 /* If there is no desktop window yet, we must be creating it */
1577 PsGetWin32Thread()->Desktop->DesktopWindow = Handle;
1578 }
1579
1580 /*
1581 * Fill out the structure describing it.
1582 */
1583 WindowObject->Class = ClassObject;
1584 WindowObject->ExStyle = dwExStyle;
1585 WindowObject->Style = dwStyle & ~WS_VISIBLE;
1586 DPRINT("1: Style is now %d\n", WindowObject->Style);
1587
1588 WindowObject->SystemMenu = (HMENU)0;
1589 WindowObject->ContextHelpId = 0;
1590 WindowObject->IDMenu = 0;
1591 WindowObject->Instance = hInstance;
1592 WindowObject->Self = Handle;
1593 if (0 != (dwStyle & WS_CHILD))
1594 {
1595 WindowObject->IDMenu = (UINT) hMenu;
1596 }
1597 else
1598 {
1599 IntSetMenu(WindowObject, hMenu, &MenuChanged);
1600 }
1601 WindowObject->MessageQueue = PsGetWin32Thread()->MessageQueue;
1602 WindowObject->Parent = (ParentWindow ? ParentWindow->Self : NULL);
1603 if((OwnerWindow = IntGetWindowObject(OwnerWindowHandle)))
1604 {
1605 WindowObject->Owner = OwnerWindowHandle;
1606 IntReleaseWindowObject(OwnerWindow);
1607 }
1608 else
1609 WindowObject->Owner = NULL;
1610 WindowObject->UserData = 0;
1611 if ((((DWORD)ClassObject->lpfnWndProcA & 0xFFFF0000) != 0xFFFF0000)
1612 && (((DWORD)ClassObject->lpfnWndProcW & 0xFFFF0000) != 0xFFFF0000))
1613 {
1614 WindowObject->Unicode = bUnicodeWindow;
1615 }
1616 else
1617 {
1618 WindowObject->Unicode = ClassObject->Unicode;
1619 }
1620 WindowObject->WndProcA = ClassObject->lpfnWndProcA;
1621 WindowObject->WndProcW = ClassObject->lpfnWndProcW;
1622 WindowObject->OwnerThread = PsGetCurrentThread();
1623 WindowObject->FirstChild = NULL;
1624 WindowObject->LastChild = NULL;
1625 WindowObject->PrevSibling = NULL;
1626 WindowObject->NextSibling = NULL;
1627
1628 /* extra window data */
1629 if (ClassObject->cbWndExtra != 0)
1630 {
1631 WindowObject->ExtraData = (PCHAR)(WindowObject + 1);
1632 WindowObject->ExtraDataSize = ClassObject->cbWndExtra;
1633 RtlZeroMemory(WindowObject->ExtraData, WindowObject->ExtraDataSize);
1634 }
1635 else
1636 {
1637 WindowObject->ExtraData = NULL;
1638 WindowObject->ExtraDataSize = 0;
1639 }
1640
1641 InitializeListHead(&WindowObject->PropListHead);
1642 ExInitializeFastMutex(&WindowObject->PropListLock);
1643 ExInitializeFastMutex(&WindowObject->RelativesLock);
1644 ExInitializeFastMutex(&WindowObject->UpdateLock);
1645
1646 WindowObject->WindowName = WindowName;
1647
1648 /* Correct the window style. */
1649 if (!(dwStyle & WS_CHILD))
1650 {
1651 WindowObject->Style |= WS_CLIPSIBLINGS;
1652 DPRINT("3: Style is now %d\n", WindowObject->Style);
1653 if (!(dwStyle & WS_POPUP))
1654 {
1655 WindowObject->Style |= WS_CAPTION;
1656 WindowObject->Flags |= WINDOWOBJECT_NEED_SIZE;
1657 DPRINT("4: Style is now %d\n", WindowObject->Style);
1658 /* FIXME: Note the window needs a size. */
1659 }
1660 }
1661
1662 if(!(WindowObject->Style & (WS_POPUP | WS_CHILD)))
1663 {
1664 /* Automatically assign the overlapped window style. Also always
1665 clip siblings for overlapped windows. */
1666 WindowObject->Style |= (WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS);
1667 }
1668
1669 /* create system menu */
1670 if((WindowObject->Style & WS_SYSMENU) && (WindowObject->Style & WS_CAPTION))
1671 {
1672 SystemMenu = IntGetSystemMenu(WindowObject, TRUE, TRUE);
1673 if(SystemMenu)
1674 {
1675 WindowObject->SystemMenu = SystemMenu->MenuInfo.Self;
1676 IntReleaseMenuObject(SystemMenu);
1677 }
1678 }
1679
1680 /* Insert the window into the thread's window list. */
1681 IntLockThreadWindows(PsGetWin32Thread());
1682 InsertTailList (&PsGetWin32Thread()->WindowListHead,
1683 &WindowObject->ThreadListEntry);
1684 IntUnLockThreadWindows(PsGetWin32Thread());
1685
1686 /* Allocate a DCE for this window. */
1687 if (dwStyle & CS_OWNDC)
1688 {
1689 WindowObject->Dce = DceAllocDCE(WindowObject->Self, DCE_WINDOW_DC);
1690 }
1691 /* FIXME: Handle "CS_CLASSDC" */
1692
1693 Pos.x = x;
1694 Pos.y = y;
1695 Size.cx = nWidth;
1696 Size.cy = nHeight;
1697
1698 /* call hook */
1699 Cs.lpCreateParams = lpParam;
1700 Cs.hInstance = hInstance;
1701 Cs.hMenu = hMenu;
1702 Cs.hwndParent = ParentWindowHandle;
1703 Cs.cx = Size.cx;
1704 Cs.cy = Size.cy;
1705 Cs.x = Pos.x;
1706 Cs.y = Pos.y;
1707 Cs.style = dwStyle;
1708 Cs.lpszName = OrigWindowName; /* pass the original pointer to usermode! */
1709 Cs.lpszClass = lpClassName->Buffer;
1710 Cs.dwExStyle = dwExStyle;
1711 CbtCreate.lpcs = &Cs;
1712 CbtCreate.hwndInsertAfter = HWND_TOP;
1713 if (HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) Handle, (LPARAM) &CbtCreate))
1714 {
1715 if (NULL != ParentWindow)
1716 {
1717 IntReleaseWindowObject(ParentWindow);
1718 }
1719
1720 /* FIXME - Delete window object and remove it from the thread windows list */
1721 /* FIXME - delete allocated DCE */
1722
1723 DPRINT1("CBT-hook returned !0\n");
1724 return (HWND) NULL;
1725 }
1726
1727 x = Cs.x;
1728 y = Cs.y;
1729 nWidth = Cs.cx;
1730 nHeight = Cs.cy;
1731
1732 /* default positioning for overlapped windows */
1733 if(!(WindowObject->Style & (WS_POPUP | WS_CHILD)))
1734 {
1735 RECT rc, WorkArea;
1736 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
1737 BOOL CalculatedDefPosSize = FALSE;
1738
1739 IntGetDesktopWorkArea(WindowObject->OwnerThread->Win32Thread->Desktop, &WorkArea);
1740
1741 rc = WorkArea;
1742 ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;
1743
1744 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
1745 {
1746 CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, WindowObject, &rc, TRUE);
1747
1748 if(ProcessParams->dwFlags & STARTF_USEPOSITION)
1749 {
1750 ProcessParams->dwFlags &= ~STARTF_USEPOSITION;
1751 Pos.x = WorkArea.left + ProcessParams->dwX;
1752 Pos.y = WorkArea.top + ProcessParams->dwY;
1753 }
1754 else
1755 {
1756 Pos.x = rc.left;
1757 Pos.y = rc.top;
1758 }
1759
1760 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1761 y is something else */
1762 if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16)
1763 {
1764 dwShowMode = y;
1765 }
1766 }
1767 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
1768 {
1769 if(!CalculatedDefPosSize)
1770 {
1771 IntCalcDefPosSize(ParentWindow, WindowObject, &rc, FALSE);
1772 }
1773 if(ProcessParams->dwFlags & STARTF_USESIZE)
1774 {
1775 ProcessParams->dwFlags &= ~STARTF_USESIZE;
1776 Size.cx = ProcessParams->dwXSize;
1777 Size.cy = ProcessParams->dwYSize;
1778 }
1779 else
1780 {
1781 Size.cx = rc.right - rc.left;
1782 Size.cy = rc.bottom - rc.top;
1783 }
1784
1785 /* move the window if necessary */
1786 if(Pos.x > rc.left)
1787 Pos.x = max(rc.left, 0);
1788 if(Pos.y > rc.top)
1789 Pos.y = max(rc.top, 0);
1790 }
1791 }
1792 else
1793 {
1794 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1795 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
1796 {
1797 Pos.x = 0;
1798 Pos.y = 0;
1799 }
1800 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
1801 {
1802 Size.cx = 0;
1803 Size.cy = 0;
1804 }
1805 }
1806
1807 /* Initialize the window dimensions. */
1808 WindowObject->WindowRect.left = Pos.x;
1809 WindowObject->WindowRect.top = Pos.y;
1810 WindowObject->WindowRect.right = Pos.x + Size.cx;
1811 WindowObject->WindowRect.bottom = Pos.y + Size.cy;
1812 if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
1813 {
1814 NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left,
1815 ParentWindow->ClientRect.top);
1816 }
1817 WindowObject->ClientRect = WindowObject->WindowRect;
1818
1819 /*
1820 * Get the size and position of the window.
1821 */
1822 if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
1823 {
1824 POINT MaxSize, MaxPos, MinTrack, MaxTrack;
1825
1826 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1827 WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack,
1828 &MaxTrack);
1829 if (MaxSize.x < nWidth) nWidth = MaxSize.x;
1830 if (MaxSize.y < nHeight) nHeight = MaxSize.y;
1831 if (nWidth < MinTrack.x ) nWidth = MinTrack.x;
1832 if (nHeight < MinTrack.y ) nHeight = MinTrack.y;
1833 if (nWidth < 0) nWidth = 0;
1834 if (nHeight < 0) nHeight = 0;
1835 }
1836
1837 WindowObject->WindowRect.left = Pos.x;
1838 WindowObject->WindowRect.top = Pos.y;
1839 WindowObject->WindowRect.right = Pos.x + Size.cx;
1840 WindowObject->WindowRect.bottom = Pos.y + Size.cy;
1841 if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
1842 {
1843 NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left,
1844 ParentWindow->ClientRect.top);
1845 }
1846 WindowObject->ClientRect = WindowObject->WindowRect;
1847
1848 /* FIXME: Initialize the window menu. */
1849
1850 /* Send a NCCREATE message. */
1851 Cs.cx = Size.cx;
1852 Cs.cy = Size.cy;
1853 Cs.x = Pos.x;
1854 Cs.y = Pos.y;
1855
1856 DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
1857 DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
1858 DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
1859 Result = IntSendMessage(WindowObject->Self, WM_NCCREATE, 0, (LPARAM) &Cs);
1860 if (!Result)
1861 {
1862 /* FIXME: Cleanup. */
1863 if (NULL != ParentWindow)
1864 {
1865 IntReleaseWindowObject(ParentWindow);
1866 }
1867 DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
1868 return((HWND)0);
1869 }
1870
1871 /* Calculate the non-client size. */
1872 MaxPos.x = WindowObject->WindowRect.left;
1873 MaxPos.y = WindowObject->WindowRect.top;
1874 DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
1875 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1876 Result = WinPosGetNonClientSize(WindowObject->Self,
1877 &WindowObject->WindowRect,
1878 &WindowObject->ClientRect);
1879 NtGdiOffsetRect(&WindowObject->WindowRect,
1880 MaxPos.x - WindowObject->WindowRect.left,
1881 MaxPos.y - WindowObject->WindowRect.top);
1882
1883 if (NULL != ParentWindow)
1884 {
1885 /* link the window into the parent's child list */
1886 if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1887 {
1888 PWINDOW_OBJECT PrevSibling;
1889 IntLockRelatives(ParentWindow);
1890 if((PrevSibling = ParentWindow->LastChild))
1891 IntReferenceWindowObject(PrevSibling);
1892 IntUnLockRelatives(ParentWindow);
1893 /* link window as bottom sibling */
1894 IntLinkWindow(WindowObject, ParentWindow, PrevSibling /*prev sibling*/);
1895 if(PrevSibling)
1896 IntReleaseWindowObject(PrevSibling);
1897 }
1898 else
1899 {
1900 /* link window as top sibling (but after topmost siblings) */
1901 PWINDOW_OBJECT InsertAfter, Sibling;
1902 if (0 == (dwExStyle & WS_EX_TOPMOST))
1903 {
1904 IntLockRelatives(ParentWindow);
1905 InsertAfter = NULL;
1906 Sibling = ParentWindow->FirstChild;
1907 while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
1908 {
1909 InsertAfter = Sibling;
1910 Sibling = Sibling->NextSibling;
1911 }
1912 IntUnLockRelatives(ParentWindow);
1913 }
1914 else
1915 {
1916 InsertAfter = NULL;
1917 }
1918 if (NULL != InsertAfter)
1919 {
1920 IntReferenceWindowObject(InsertAfter);
1921 }
1922 IntLinkWindow(WindowObject, ParentWindow, InsertAfter /* prev sibling */);
1923 if (NULL != InsertAfter)
1924 {
1925 IntReleaseWindowObject(InsertAfter);
1926 }
1927 }
1928 }
1929
1930 /* Send the WM_CREATE message. */
1931 DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
1932 Result = IntSendMessage(WindowObject->Self, WM_CREATE, 0, (LPARAM) &Cs);
1933 if (Result == (LRESULT)-1)
1934 {
1935 /* FIXME: Cleanup. */
1936 if (NULL != ParentWindow)
1937 {
1938 IntReleaseWindowObject(ParentWindow);
1939 }
1940 DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
1941 return((HWND)0);
1942 }
1943
1944 /* Send move and size messages. */
1945 if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE))
1946 {
1947 LONG lParam;
1948
1949 DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
1950
1951 if ((WindowObject->ClientRect.right - WindowObject->ClientRect.left) < 0 ||
1952 (WindowObject->ClientRect.bottom - WindowObject->ClientRect.top) < 0)
1953 DPRINT("Sending bogus WM_SIZE\n");
1954
1955 lParam = MAKE_LONG(WindowObject->ClientRect.right -
1956 WindowObject->ClientRect.left,
1957 WindowObject->ClientRect.bottom -
1958 WindowObject->ClientRect.top);
1959 IntSendMessage(WindowObject->Self, WM_SIZE, SIZE_RESTORED,
1960 lParam);
1961
1962 DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
1963
1964 if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
1965 {
1966 lParam = MAKE_LONG(WindowObject->ClientRect.left - ParentWindow->ClientRect.left,
1967 WindowObject->ClientRect.top - ParentWindow->ClientRect.top);
1968 }
1969 else
1970 {
1971 lParam = MAKE_LONG(WindowObject->ClientRect.left,
1972 WindowObject->ClientRect.top);
1973 }
1974 IntSendMessage(WindowObject->Self, WM_MOVE, 0, lParam);
1975 }
1976
1977 /* Show or maybe minimize or maximize the window. */
1978 if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE))
1979 {
1980 RECT NewPos;
1981 UINT16 SwFlag;
1982
1983 SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE :
1984 SW_MAXIMIZE;
1985 WinPosMinMaximize(WindowObject, SwFlag, &NewPos);
1986 SwFlag =
1987 ((WindowObject->Style & WS_CHILD) || NtUserGetActiveWindow()) ?
1988 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :
1989 SWP_NOZORDER | SWP_FRAMECHANGED;
1990 DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
1991 DPRINT("%d,%d %dx%d\n", NewPos.left, NewPos.top, NewPos.right, NewPos.bottom);
1992 WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top,
1993 NewPos.right, NewPos.bottom, SwFlag);
1994 }
1995
1996 /* Notify the parent window of a new child. */
1997 if ((WindowObject->Style & WS_CHILD) &&
1998 (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow)
1999 {
2000 DPRINT("NtUserCreateWindow(): About to notify parent\n");
2001 IntSendMessage(ParentWindow->Self,
2002 WM_PARENTNOTIFY,
2003 MAKEWPARAM(WM_CREATE, WindowObject->IDMenu),
2004 (LPARAM)WindowObject->Self);
2005 }
2006
2007 if (NULL != ParentWindow)
2008 {
2009 IntReleaseWindowObject(ParentWindow);
2010 }
2011
2012 /* Initialize and show the window's scrollbars */
2013 if (WindowObject->Style & WS_VSCROLL)
2014 {
2015 NtUserShowScrollBar(WindowObject->Self, SB_VERT, TRUE);
2016 }
2017 if (WindowObject->Style & WS_HSCROLL)
2018 {
2019 NtUserShowScrollBar(WindowObject->Self, SB_HORZ, TRUE);
2020 }
2021
2022 if (dwStyle & WS_VISIBLE)
2023 {
2024 DPRINT("NtUserCreateWindow(): About to show window\n");
2025 WinPosShowWindow(WindowObject->Self, dwShowMode);
2026 }
2027
2028 DPRINT("NtUserCreateWindow(): = %X\n", Handle);
2029 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject->SystemMenu);
2030 return((HWND)Handle);
2031 }
2032
2033
2034 /*
2035 * @unimplemented
2036 */
2037 HDWP STDCALL
2038 NtUserDeferWindowPos(HDWP WinPosInfo,
2039 HWND Wnd,
2040 HWND WndInsertAfter,
2041 int x,
2042 int y,
2043 int cx,
2044 int cy,
2045 UINT Flags)
2046 {
2047 UNIMPLEMENTED
2048
2049 return 0;
2050 }
2051
2052
2053 /*
2054 * @implemented
2055 */
2056 BOOLEAN STDCALL
2057 NtUserDestroyWindow(HWND Wnd)
2058 {
2059 PWINDOW_OBJECT Window;
2060 BOOLEAN isChild;
2061
2062 Window = IntGetWindowObject(Wnd);
2063 if (Window == NULL)
2064 {
2065 return FALSE;
2066 }
2067
2068 /* Check for owner thread and desktop window */
2069 if ((Window->OwnerThread != PsGetCurrentThread()) || IntIsDesktopWindow(Window))
2070 {
2071 IntReleaseWindowObject(Window);
2072 SetLastWin32Error(ERROR_ACCESS_DENIED);
2073 return FALSE;
2074 }
2075
2076 /* Look whether the focus is within the tree of windows we will
2077 * be destroying.
2078 */
2079 if (!WinPosShowWindow(Wnd, SW_HIDE))
2080 {
2081 if (NtUserGetActiveWindow() == Wnd)
2082 {
2083 WinPosActivateOtherWindow(Window);
2084 }
2085 }
2086 IntLockMessageQueue(Window->MessageQueue);
2087 if (Window->MessageQueue->ActiveWindow == Window->Self)
2088 Window->MessageQueue->ActiveWindow = NULL;
2089 if (Window->MessageQueue->FocusWindow == Window->Self)
2090 Window->MessageQueue->FocusWindow = NULL;
2091 if (Window->MessageQueue->CaptureWindow == Window->Self)
2092 Window->MessageQueue->CaptureWindow = NULL;
2093 IntUnLockMessageQueue(Window->MessageQueue);
2094
2095 /* Call hooks */
2096 #if 0 /* FIXME */
2097 if (HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hwnd, 0, TRUE))
2098 {
2099 return FALSE;
2100 }
2101 #endif
2102
2103 isChild = (0 != (Window->Style & WS_CHILD));
2104
2105 #if 0 /* FIXME */
2106 if (isChild)
2107 {
2108 if (! USER_IsExitingThread(GetCurrentThreadId()))
2109 {
2110 send_parent_notify(hwnd, WM_DESTROY);
2111 }
2112 }
2113 else if (NULL != GetWindow(Wnd, GW_OWNER))
2114 {
2115 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
2116 /* FIXME: clean up palette - see "Internals" p.352 */
2117 }
2118
2119 if (! IsWindow(Wnd))
2120 {
2121 return TRUE;
2122 }
2123 #endif
2124
2125 if (!IntIsWindow(Wnd))
2126 {
2127 return TRUE;
2128 }
2129
2130 /* Recursively destroy owned windows */
2131 if (! isChild)
2132 {
2133 for (;;)
2134 {
2135 BOOL GotOne = FALSE;
2136 HWND *Children;
2137 HWND *ChildHandle;
2138 PWINDOW_OBJECT Child, Desktop;
2139
2140 Desktop = IntGetWindowObject(IntGetDesktopWindow());
2141 Children = IntWinListChildren(Desktop);
2142 IntReleaseWindowObject(Desktop);
2143 if (Children)
2144 {
2145 for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
2146 {
2147 Child = IntGetWindowObject(*ChildHandle);
2148 if (Child == NULL)
2149 {
2150 continue;
2151 }
2152 if(Child->Self == Wnd)
2153 {
2154 IntReleaseWindowObject(Child);
2155 continue;
2156 }
2157 IntLockRelatives(Child);
2158 if (Child->Parent != Window->Self)
2159 {
2160 IntUnLockRelatives(Child);
2161 IntReleaseWindowObject(Child);
2162 continue;
2163 }
2164 IntUnLockRelatives(Child);
2165 if (IntWndBelongsToThread(Child, PsGetWin32Thread()))
2166 {
2167 IntReleaseWindowObject(Child);
2168 NtUserDestroyWindow(*ChildHandle);
2169 GotOne = TRUE;
2170 continue;
2171 }
2172 IntLockRelatives(Child);
2173 if (Child->Owner != NULL)
2174 {
2175 Child->Owner = NULL;
2176 }
2177 IntUnLockRelatives(Child);
2178 IntReleaseWindowObject(Child);
2179 }
2180 ExFreePool(Children);
2181 }
2182 if (! GotOne)
2183 {
2184 break;
2185 }
2186 }
2187 }
2188
2189 if (!IntIsWindow(Wnd))
2190 {
2191 IntReleaseWindowObject(Window);
2192 return TRUE;
2193 }
2194
2195 /* Destroy the window storage */
2196 IntDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
2197
2198 IntReleaseWindowObject(Window);
2199 return TRUE;
2200 }
2201
2202
2203 /*
2204 * @unimplemented
2205 */
2206 DWORD
2207 STDCALL
2208 NtUserDrawMenuBarTemp(
2209 HWND hWnd,
2210 HDC hDC,
2211 PRECT hRect,
2212 HMENU hMenu,
2213 HFONT hFont)
2214 {
2215 /* we'll use this function just for caching the menu bar */
2216 UNIMPLEMENTED
2217 return 0;
2218 }
2219
2220
2221 /*
2222 * @unimplemented
2223 */
2224 DWORD STDCALL
2225 NtUserEndDeferWindowPosEx(DWORD Unknown0,
2226 DWORD Unknown1)
2227 {
2228 UNIMPLEMENTED
2229
2230 return 0;
2231 }
2232
2233
2234 /*
2235 * @unimplemented
2236 */
2237 DWORD STDCALL
2238 NtUserFillWindow(DWORD Unknown0,
2239 DWORD Unknown1,
2240 DWORD Unknown2,
2241 DWORD Unknown3)
2242 {
2243 UNIMPLEMENTED
2244
2245 return 0;
2246 }
2247
2248
2249 HWND FASTCALL
2250 IntFindWindow(PWINDOW_OBJECT Parent,
2251 PWINDOW_OBJECT ChildAfter,
2252 PWNDCLASS_OBJECT ClassObject,
2253 PUNICODE_STRING WindowName)
2254 {
2255 BOOL CheckWindowName;
2256 HWND *List, *phWnd;
2257 HWND Ret = NULL;
2258
2259 ASSERT(Parent);
2260
2261 CheckWindowName = (WindowName && (WindowName->Length > 0));
2262
2263 if((List = IntWinListChildren(Parent)))
2264 {
2265 phWnd = List;
2266 if(ChildAfter)
2267 {
2268 /* skip handles before and including ChildAfter */
2269 while(*phWnd && (*(phWnd++) != ChildAfter->Self));
2270 }
2271
2272 /* search children */
2273 while(*phWnd)
2274 {
2275 PWINDOW_OBJECT Child;
2276 if(!(Child = IntGetWindowObject(*(phWnd++))))
2277 {
2278 continue;
2279 }
2280
2281 /* Do not send WM_GETTEXT messages in the kernel mode version!
2282 The user mode version however calls GetWindowText() which will
2283 send WM_GETTEXT messages to windows belonging to its processes */
2284 if(((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(WindowName, &(Child->WindowName), FALSE))) &&
2285 (!ClassObject || (ClassObject && (Child->Class == ClassObject))))
2286 ||
2287 ((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(WindowName, &(Child->WindowName), FALSE))) &&
2288 (!ClassObject || (ClassObject && (Child->Class == ClassObject)))))
2289 {
2290 Ret = Child->Self;
2291 IntReleaseWindowObject(Child);
2292 break;
2293 }
2294
2295 IntReleaseWindowObject(Child);
2296 }
2297 ExFreePool(List);
2298 }
2299
2300 return Ret;
2301 }
2302
2303 /*
2304 * FUNCTION:
2305 * Searches a window's children for a window with the specified
2306 * class and name
2307 * ARGUMENTS:
2308 * hwndParent = The window whose childs are to be searched.
2309 * NULL = desktop
2310 * HWND_MESSAGE = message-only windows
2311 *
2312 * hwndChildAfter = Search starts after this child window.
2313 * NULL = start from beginning
2314 *
2315 * ucClassName = Class name to search for
2316 * Reguired parameter.
2317 *
2318 * ucWindowName = Window name
2319 * ->Buffer == NULL = don't care
2320 *
2321 * RETURNS:
2322 * The HWND of the window if it was found, otherwise NULL
2323 */
2324 /*
2325 * @implemented
2326 */
2327 HWND STDCALL
2328 NtUserFindWindowEx(HWND hwndParent,
2329 HWND hwndChildAfter,
2330 PUNICODE_STRING ucClassName,
2331 PUNICODE_STRING ucWindowName)
2332 {
2333 PWINDOW_OBJECT Parent, ChildAfter;
2334 UNICODE_STRING ClassName, WindowName;
2335 NTSTATUS Status;
2336 HWND Desktop, Ret = NULL;
2337 PWNDCLASS_OBJECT ClassObject = NULL;
2338
2339 Desktop = IntGetDesktopWindow();
2340
2341 if(hwndParent == NULL)
2342 hwndParent = Desktop;
2343 /* FIXME
2344 else if(hwndParent == HWND_MESSAGE)
2345 {
2346 hwndParent = IntGetMessageWindow();
2347 }
2348 */
2349
2350 if(!(Parent = IntGetWindowObject(hwndParent)))
2351 {
2352 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2353 return NULL;
2354 }
2355
2356 ChildAfter = NULL;
2357 if(hwndChildAfter && !(ChildAfter = IntGetWindowObject(hwndChildAfter)))
2358 {
2359 IntReleaseWindowObject(hwndParent);
2360 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2361 return NULL;
2362 }
2363
2364 /* copy the window name */
2365 Status = IntSafeCopyUnicodeString(&WindowName, ucWindowName);
2366 if(!NT_SUCCESS(Status))
2367 {
2368 SetLastNtError(Status);
2369 goto Cleanup3;
2370 }
2371
2372 /* safely copy the class name */
2373 Status = MmCopyFromCaller(&ClassName, ucClassName, sizeof(UNICODE_STRING));
2374 if(!NT_SUCCESS(Status))
2375 {
2376 SetLastNtError(Status);
2377 goto Cleanup2;
2378 }
2379 if(ClassName.Length > 0 && ClassName.Buffer)
2380 {
2381 WCHAR *buf;
2382 /* safely copy the class name string (NULL terminated because class-lookup
2383 depends on it... */
2384 buf = ExAllocatePoolWithTag(NonPagedPool, ClassName.Length + sizeof(WCHAR), TAG_STRING);
2385 if(!buf)
2386 {
2387 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES);
2388 goto Cleanup2;
2389 }
2390 Status = MmCopyFromCaller(buf, ClassName.Buffer, ClassName.Length);
2391 if(!NT_SUCCESS(Status))
2392 {
2393 ExFreePool(buf);
2394 SetLastNtError(Status);
2395 goto Cleanup2;
2396 }
2397 ClassName.Buffer = buf;
2398 /* make sure the string is null-terminated */
2399 buf += ClassName.Length / sizeof(WCHAR);
2400 *buf = L'\0';
2401 }
2402
2403 /* find the class object */
2404 if(ClassName.Buffer)
2405 {
2406 /* this expects the string in ClassName to be NULL-terminated! */
2407 Status = ClassReferenceClassByNameOrAtom(&ClassObject, ClassName.Buffer);
2408 if(!NT_SUCCESS(Status))
2409 {
2410 DPRINT1("Window class not found\n");
2411 /* windows returns ERROR_FILE_NOT_FOUND !? */
2412 SetLastWin32Error(ERROR_FILE_NOT_FOUND);
2413 goto Cleanup;
2414 }
2415 }
2416
2417 if(Parent->Self == Desktop)
2418 {
2419 HWND *List, *phWnd;
2420 PWINDOW_OBJECT TopLevelWindow;
2421 BOOL CheckWindowName;
2422
2423 /* windows searches through all top-level windows if the parent is the desktop
2424 window */
2425
2426 if((List = IntWinListChildren(Parent)))
2427 {
2428 phWnd = List;
2429
2430 if(ChildAfter)
2431 {
2432 /* skip handles before and including ChildAfter */
2433 while(*phWnd && (*(phWnd++) != ChildAfter->Self));
2434 }
2435
2436 CheckWindowName = WindowName.Length > 0;
2437
2438 /* search children */
2439 while(*phWnd)
2440 {
2441 if(!(TopLevelWindow = IntGetWindowObject(*(phWnd++))))
2442 {
2443 continue;
2444 }
2445
2446 /* Do not send WM_GETTEXT messages in the kernel mode version!
2447 The user mode version however calls GetWindowText() which will
2448 send WM_GETTEXT messages to windows belonging to its processes */
2449 if(((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(&WindowName, &(TopLevelWindow->WindowName), FALSE))) &&
2450 (!ClassObject || (ClassObject && (TopLevelWindow->Class == ClassObject))))
2451 ||
2452 ((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(&WindowName, &(TopLevelWindow->WindowName), FALSE))) &&
2453 (!ClassObject || (ClassObject && (TopLevelWindow->Class == ClassObject)))))
2454 {
2455 Ret = TopLevelWindow->Self;
2456 IntReleaseWindowObject(TopLevelWindow);
2457 break;
2458 }
2459
2460 if(IntFindWindow(TopLevelWindow, NULL, ClassObject, &WindowName))
2461 {
2462 /* window returns the handle of the top-level window, in case it found
2463 the child window */
2464 Ret = TopLevelWindow->Self;
2465 IntReleaseWindowObject(TopLevelWindow);
2466 break;
2467 }
2468
2469 IntReleaseWindowObject(TopLevelWindow);
2470 }
2471 ExFreePool(List);
2472 }
2473 }
2474 else
2475 Ret = IntFindWindow(Parent, ChildAfter, ClassObject, &WindowName);
2476
2477 #if 0
2478 if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
2479 {
2480 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2481 search the message-only windows. Should this also be done if
2482 Parent is the desktop window??? */
2483 PWINDOW_OBJECT MsgWindows;
2484
2485 if((MsgWindows = IntGetWindowObject(IntGetMessageWindow())))
2486 {
2487 Ret = IntFindWindow(MsgWindows, ChildAfter, ClassObject, &WindowName);
2488 IntReleaseWindowObject(MsgWindows);
2489 }
2490 }
2491 #endif
2492
2493 Cleanup:
2494 if(ClassName.Length > 0 && ClassName.Buffer)
2495 ExFreePool(ClassName.Buffer);
2496
2497 Cleanup2:
2498 RtlFreeUnicodeString(&WindowName);
2499
2500 Cleanup3:
2501 if(ChildAfter)
2502 IntReleaseWindowObject(ChildAfter);
2503 IntReleaseWindowObject(Parent);
2504
2505 return Ret;
2506 }
2507
2508
2509 /*
2510 * @unimplemented
2511 */
2512 DWORD STDCALL
2513 NtUserFlashWindowEx(DWORD Unknown0)
2514 {
2515 UNIMPLEMENTED
2516
2517 return 0;
2518 }
2519
2520
2521 /*
2522 * @implemented
2523 */
2524 HWND STDCALL
2525 NtUserGetAncestor(HWND hWnd, UINT Type)
2526 {
2527 PWINDOW_OBJECT Wnd, WndAncestor, Parent;
2528 HWND hWndAncestor;
2529
2530 if (hWnd == IntGetDesktopWindow())
2531 {
2532 return NULL;
2533 }
2534
2535 if (!(Wnd = IntGetWindowObject(hWnd)))
2536 {
2537 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2538 return NULL;
2539 }
2540
2541 switch (Type)
2542 {
2543 case GA_PARENT:
2544 {
2545 WndAncestor = IntGetParentObject(Wnd);
2546 break;
2547 }
2548
2549 case GA_ROOT:
2550 {
2551 PWINDOW_OBJECT tmp;
2552 WndAncestor = Wnd;
2553 Parent = NULL;
2554
2555 for(;;)
2556 {
2557 tmp = Parent;
2558 if(!(Parent = IntGetParentObject(WndAncestor)))
2559 {
2560 break;
2561 }
2562 if(IntIsDesktopWindow(Parent))
2563 {
2564 IntReleaseWindowObject(Parent);
2565 break;
2566 }
2567 if(tmp)
2568 IntReleaseWindowObject(tmp);
2569 WndAncestor = Parent;
2570 }
2571 break;
2572 }
2573
2574 case GA_ROOTOWNER:
2575 {
2576 WndAncestor = Wnd;
2577 IntReferenceWindowObject(WndAncestor);
2578 for (;;)
2579 {
2580 PWINDOW_OBJECT Old;
2581 Old = WndAncestor;
2582 Parent = IntGetParent(WndAncestor);
2583 IntReleaseWindowObject(Old);
2584 if (!Parent)
2585 {
2586 break;
2587 }
2588 WndAncestor = Parent;
2589 }
2590 break;
2591 }
2592
2593 default:
2594 {
2595 IntReleaseWindowObject(Wnd);
2596 return NULL;
2597 }
2598 }
2599
2600 hWndAncestor = (WndAncestor ? WndAncestor->Self : NULL);
2601 IntReleaseWindowObject(Wnd);
2602
2603 if(WndAncestor && (WndAncestor != Wnd))
2604 IntReleaseWindowObject(WndAncestor);
2605
2606 return hWndAncestor;
2607 }
2608
2609
2610 /*!
2611 * Returns client window rectangle relative to the upper-left corner of client area.
2612 *
2613 * \param hWnd window handle.
2614 * \param Rect pointer to the buffer where the coordinates are returned.
2615 *
2616 */
2617 /*
2618 * @implemented
2619 */
2620 BOOL STDCALL
2621 NtUserGetClientRect(HWND hWnd, LPRECT Rect)
2622 {
2623 PWINDOW_OBJECT WindowObject;
2624 RECT SafeRect;
2625
2626 if(!(WindowObject = IntGetWindowObject(hWnd)))
2627 {
2628 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2629 return FALSE;
2630 }
2631
2632 IntGetClientRect(WindowObject, &SafeRect);
2633 IntReleaseWindowObject(WindowObject);
2634
2635 if(!NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
2636 {
2637 return FALSE;
2638 }
2639 return TRUE;
2640 }
2641
2642
2643 /*
2644 * @implemented
2645 */
2646 HWND STDCALL
2647 NtUserGetDesktopWindow()
2648 {
2649 return IntGetDesktopWindow();
2650 }
2651
2652
2653 /*
2654 * @unimplemented
2655 */
2656 DWORD STDCALL
2657 NtUserGetInternalWindowPos(DWORD Unknown0,
2658 DWORD Unknown1,
2659 DWORD Unknown2)
2660 {
2661 UNIMPLEMENTED
2662
2663 return 0;
2664 }
2665
2666
2667 /*
2668 * @unimplemented
2669 */
2670 HWND STDCALL
2671 NtUserGetLastActivePopup(HWND hWnd)
2672 {
2673 /*
2674 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2675 * not changed anywhere.
2676 * -- Filip, 01/nov/2003
2677 */
2678 #if 0
2679 PWINDOW_OBJECT Wnd;
2680 HWND hWndLastPopup;
2681
2682 IntAcquireWinLockShared();
2683
2684 if (!(Wnd = IntGetWindowObject(hWnd)))
2685 {
2686 IntReleaseWinLock();
2687 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2688 return NULL;
2689 }
2690
2691 hWndLastPopup = Wnd->hWndLastPopup;
2692
2693 IntReleaseWinLock();
2694
2695 return hWndLastPopup;
2696 #else
2697 return NULL;
2698 #endif
2699 }
2700
2701 /*
2702 * NtUserGetParent
2703 *
2704 * The NtUserGetParent function retrieves a handle to the specified window's
2705 * parent or owner.
2706 *
2707 * Remarks
2708 * Note that, despite its name, this function can return an owner window
2709 * instead of a parent window.
2710 *
2711 * Status
2712 * @implemented
2713 */
2714
2715 HWND STDCALL
2716 NtUserGetParent(HWND hWnd)
2717 {
2718 PWINDOW_OBJECT Wnd, WndParent;
2719 HWND hWndParent = NULL;
2720
2721 if (!(Wnd = IntGetWindowObject(hWnd)))
2722 {
2723 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2724 return NULL;
2725 }
2726
2727 WndParent = IntGetParent(Wnd);
2728 if (WndParent)
2729 {
2730 hWndParent = WndParent->Self;
2731 IntReleaseWindowObject(WndParent);
2732 }
2733
2734 IntReleaseWindowObject(Wnd);
2735
2736 return hWndParent;
2737 }
2738
2739 /*
2740 * NtUserSetParent
2741 *
2742 * The NtUserSetParent function changes the parent window of the specified
2743 * child window.
2744 *
2745 * Remarks
2746 * The new parent window and the child window must belong to the same
2747 * application. If the window identified by the hWndChild parameter is
2748 * visible, the system performs the appropriate redrawing and repainting.
2749 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2750 * or WS_POPUP window styles of the window whose parent is being changed.
2751 *
2752 * Status
2753 * @implemented
2754 */
2755
2756 HWND STDCALL
2757 NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
2758 {
2759 PWINDOW_OBJECT Wnd = NULL, WndParent = NULL, WndOldParent;
2760 HWND hWndOldParent = NULL;
2761
2762 if (IntIsBroadcastHwnd(hWndChild) || IntIsBroadcastHwnd(hWndNewParent))
2763 {
2764 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2765 return NULL;
2766 }
2767
2768 if (hWndChild == IntGetDesktopWindow())
2769 {
2770 SetLastWin32Error(ERROR_ACCESS_DENIED);
2771 return NULL;
2772 }
2773
2774 if (hWndNewParent)
2775 {
2776 if (!(WndParent = IntGetWindowObject(hWndNewParent)))
2777 {
2778 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2779 return NULL;
2780 }
2781 }
2782 else
2783 {
2784 if (!(WndParent = IntGetWindowObject(IntGetDesktopWindow())))
2785 {
2786 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2787 return NULL;
2788 }
2789 }
2790
2791 if (!(Wnd = IntGetWindowObject(hWndChild)))
2792 {
2793 IntReleaseWindowObject(WndParent);
2794 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2795 return NULL;
2796 }
2797
2798 WndOldParent = IntSetParent(Wnd, WndParent);
2799
2800 if (WndOldParent)
2801 {
2802 hWndOldParent = WndOldParent->Self;
2803 IntReleaseWindowObject(WndOldParent);
2804 }
2805
2806 IntReleaseWindowObject(Wnd);
2807 IntReleaseWindowObject(WndParent);
2808
2809 return hWndOldParent;
2810 }
2811
2812 /*
2813 * NtUserGetShellWindow
2814 *
2815 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2816 *
2817 * Status
2818 * @implemented
2819 */
2820
2821 HWND STDCALL
2822 NtUserGetShellWindow()
2823 {
2824 PWINSTATION_OBJECT WinStaObject;
2825 HWND Ret;
2826
2827 NTSTATUS Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2828 KernelMode,
2829 0,
2830 &WinStaObject);
2831
2832 if (!NT_SUCCESS(Status))
2833 {
2834 SetLastNtError(Status);
2835 return (HWND)0;
2836 }
2837
2838 Ret = (HWND)WinStaObject->ShellWindow;
2839
2840 ObDereferenceObject(WinStaObject);
2841 return Ret;
2842 }
2843
2844 /*
2845 * NtUserSetShellWindowEx
2846 *
2847 * This is undocumented function to set global shell window. The global
2848 * shell window has special handling of window position.
2849 *
2850 * Status
2851 * @implemented
2852 */
2853
2854 BOOL STDCALL
2855 NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
2856 {
2857 PWINSTATION_OBJECT WinStaObject;
2858
2859 NTSTATUS Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
2860 KernelMode,
2861 0,
2862 &WinStaObject);
2863
2864 if (!NT_SUCCESS(Status))
2865 {
2866 SetLastNtError(Status);
2867 return FALSE;
2868 }
2869
2870 /*
2871 * Test if we are permitted to change the shell window.
2872 */
2873 if (WinStaObject->ShellWindow)
2874 {
2875 ObDereferenceObject(WinStaObject);
2876 return FALSE;
2877 }
2878
2879 /*
2880 * Move shell window into background.
2881 */
2882 if (hwndListView && hwndListView != hwndShell)
2883 {
2884 /*
2885 * Disabled for now to get Explorer working.
2886 * -- Filip, 01/nov/2003
2887 */
2888 #if 0
2889 WinPosSetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
2890 #endif
2891
2892 if (NtUserGetWindowLong(hwndListView, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
2893 {
2894 ObDereferenceObject(WinStaObject);
2895 return FALSE;
2896 }
2897 }
2898
2899 if (NtUserGetWindowLong(hwndShell, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
2900 {
2901 ObDereferenceObject(WinStaObject);
2902 return FALSE;
2903 }
2904
2905 WinPosSetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
2906
2907 WinStaObject->ShellWindow = hwndShell;
2908 WinStaObject->ShellListView = hwndListView;
2909
2910 ObDereferenceObject(WinStaObject);
2911 return TRUE;
2912 }
2913
2914 /*
2915 * NtUserGetSystemMenu
2916 *
2917 * The NtUserGetSystemMenu function allows the application to access the
2918 * window menu (also known as the system menu or the control menu) for
2919 * copying and modifying.
2920 *
2921 * Parameters
2922 * hWnd
2923 * Handle to the window that will own a copy of the window menu.
2924 * bRevert
2925 * Specifies the action to be taken. If this parameter is FALSE,
2926 * NtUserGetSystemMenu returns a handle to the copy of the window menu
2927 * currently in use. The copy is initially identical to the window menu
2928 * but it can be modified.
2929 * If this parameter is TRUE, GetSystemMenu resets the window menu back
2930 * to the default state. The previous window menu, if any, is destroyed.
2931 *
2932 * Return Value
2933 * If the bRevert parameter is FALSE, the return value is a handle to a
2934 * copy of the window menu. If the bRevert parameter is TRUE, the return
2935 * value is NULL.
2936 *
2937 * Status
2938 * @implemented
2939 */
2940
2941 HMENU STDCALL
2942 NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
2943 {
2944 HMENU Result = 0;
2945 PWINDOW_OBJECT WindowObject;
2946 PMENU_OBJECT MenuObject;
2947
2948 WindowObject = IntGetWindowObject((HWND)hWnd);
2949 if (WindowObject == NULL)
2950 {
2951 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2952 return 0;
2953 }
2954
2955 MenuObject = IntGetSystemMenu(WindowObject, bRevert, FALSE);
2956 if (MenuObject)
2957 {
2958 Result = MenuObject->MenuInfo.Self;
2959 IntReleaseMenuObject(MenuObject);
2960 }
2961
2962 IntReleaseWindowObject(WindowObject);
2963 return Result;
2964 }
2965
2966 /*
2967 * NtUserSetSystemMenu
2968 *
2969 * Status
2970 * @implemented
2971 */
2972
2973 BOOL STDCALL
2974 NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
2975 {
2976 BOOL Result = FALSE;
2977 PWINDOW_OBJECT WindowObject;
2978 PMENU_OBJECT MenuObject;
2979
2980 WindowObject = IntGetWindowObject(hWnd);
2981 if (!WindowObject)
2982 {
2983 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2984 return FALSE;
2985 }
2986
2987 if (hMenu)
2988 {
2989 /*
2990 * Assign new menu handle.
2991 */
2992 MenuObject = IntGetMenuObject(hMenu);
2993 if (!MenuObject)
2994 {
2995 IntReleaseWindowObject(WindowObject);
2996 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
2997 return FALSE;
2998 }
2999
3000 Result = IntSetSystemMenu(WindowObject, MenuObject);
3001
3002 IntReleaseMenuObject(MenuObject);
3003 }
3004
3005 IntReleaseWindowObject(WindowObject);
3006
3007 return Result;
3008 }
3009
3010 /*
3011 * NtUserGetWindow
3012 *
3013 * The NtUserGetWindow function retrieves a handle to a window that has the
3014 * specified relationship (Z order or owner) to the specified window.
3015 *
3016 * Status
3017 * @implemented
3018 */
3019
3020 HWND STDCALL
3021 NtUserGetWindow(HWND hWnd, UINT Relationship)
3022 {
3023 PWINDOW_OBJECT WindowObject, Parent;
3024 HWND hWndResult = NULL;
3025
3026 if (!(WindowObject = IntGetWindowObject(hWnd)))
3027 {
3028 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3029 return NULL;
3030 }
3031
3032 switch (Relationship)
3033 {
3034 case GW_HWNDFIRST:
3035 if((Parent = IntGetParentObject(WindowObject)))
3036 {
3037 IntLockRelatives(Parent);
3038 if (Parent->FirstChild)
3039 hWndResult = Parent->FirstChild->Self;
3040 IntUnLockRelatives(Parent);
3041 IntReleaseWindowObject(Parent);
3042 }
3043 break;
3044
3045 case GW_HWNDLAST:
3046 if((Parent = IntGetParentObject(WindowObject)))
3047 {
3048 IntLockRelatives(Parent);
3049 if (Parent->LastChild)
3050 hWndResult = Parent->LastChild->Self;
3051 IntUnLockRelatives(Parent);
3052 IntReleaseWindowObject(Parent);
3053 }
3054 break;
3055
3056 case GW_HWNDNEXT:
3057 IntLockRelatives(WindowObject);
3058 if (WindowObject->NextSibling)
3059 hWndResult = WindowObject->NextSibling->Self;
3060 IntUnLockRelatives(WindowObject);
3061 break;
3062
3063 case GW_HWNDPREV:
3064 IntLockRelatives(WindowObject);
3065 if (WindowObject->PrevSibling)
3066 hWndResult = WindowObject->PrevSibling->Self;
3067 IntUnLockRelatives(WindowObject);
3068 break;
3069
3070 case GW_OWNER:
3071 IntLockRelatives(WindowObject);
3072 if((Parent = IntGetWindowObject(WindowObject->Owner)))
3073 {
3074 hWndResult = Parent->Self;
3075 IntReleaseWindowObject(Parent);
3076 }
3077 IntUnLockRelatives(WindowObject);
3078 break;
3079 case GW_CHILD:
3080 IntLockRelatives(WindowObject);
3081 if (WindowObject->FirstChild)
3082 hWndResult = WindowObject->FirstChild->Self;
3083 IntUnLockRelatives(WindowObject);
3084 break;
3085 }
3086
3087 IntReleaseWindowObject(WindowObject);
3088
3089 return hWndResult;
3090 }
3091
3092 /*
3093 * NtUserGetWindowLong
3094 *
3095 * The NtUserGetWindowLong function retrieves information about the specified
3096 * window. The function also retrieves the 32-bit (long) value at the
3097 * specified offset into the extra window memory.
3098 *
3099 * Status
3100 * @implemented
3101 */
3102
3103 LONG STDCALL
3104 NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
3105 {
3106 PWINDOW_OBJECT WindowObject, Parent;
3107 LONG Result;
3108
3109 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
3110
3111 WindowObject = IntGetWindowObject(hWnd);
3112 if (WindowObject == NULL)
3113 {
3114 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3115 return 0;
3116 }
3117
3118 /*
3119 * Only allow CSRSS to mess with the desktop window
3120 */
3121 if (hWnd == IntGetDesktopWindow()
3122 && WindowObject->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
3123 {
3124 SetLastWin32Error(STATUS_ACCESS_DENIED);
3125 return 0;
3126 }
3127
3128 if ((INT)Index >= 0)
3129 {
3130 if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
3131 {
3132 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3133 return 0;
3134 }
3135 Result = *((LONG *)(WindowObject->ExtraData + Index));
3136 }
3137 else
3138 {
3139 switch (Index)
3140 {
3141 case GWL_EXSTYLE:
3142 Result = WindowObject->ExStyle;
3143 break;
3144
3145 case GWL_STYLE:
3146 Result = WindowObject->Style;
3147 break;
3148
3149 case GWL_WNDPROC:
3150 if (Ansi)
3151 Result = (LONG) WindowObject->WndProcA;
3152 else
3153 Result = (LONG) WindowObject->WndProcW;
3154 break;
3155
3156 case GWL_HINSTANCE:
3157 Result = (LONG) WindowObject->Instance;
3158 break;
3159
3160 case GWL_HWNDPARENT:
3161 IntLockRelatives(WindowObject);
3162 Parent = IntGetWindowObject(WindowObject->Parent);
3163 IntUnLockRelatives(WindowObject);
3164 if(Parent)
3165 {
3166 if (Parent && Parent->Self == IntGetDesktopWindow())
3167 Result = (LONG) NtUserGetWindow(WindowObject->Self, GW_OWNER);
3168 else
3169 Result = (LONG) Parent->Self;
3170 IntReleaseWindowObject(Parent);
3171 }
3172 break;
3173
3174 case GWL_ID:
3175 Result = (LONG) WindowObject->IDMenu;
3176 break;
3177
3178 case GWL_USERDATA:
3179 Result = WindowObject->UserData;
3180 break;
3181
3182 default:
3183 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
3184 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3185 Result = 0;
3186 break;
3187 }
3188 }
3189
3190 IntReleaseWindowObject(WindowObject);
3191
3192 return Result;
3193 }
3194
3195 /*
3196 * NtUserSetWindowLong
3197 *
3198 * The NtUserSetWindowLong function changes an attribute of the specified
3199 * window. The function also sets the 32-bit (long) value at the specified
3200 * offset into the extra window memory.
3201 *
3202 * Status
3203 * @implemented
3204 */
3205
3206 LONG STDCALL
3207 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
3208 {
3209 PWINDOW_OBJECT WindowObject, Parent;
3210 PW32PROCESS Process;
3211 PWINSTATION_OBJECT WindowStation;
3212 LONG OldValue;
3213 STYLESTRUCT Style;
3214
3215 if (hWnd == IntGetDesktopWindow())
3216 {
3217 SetLastWin32Error(STATUS_ACCESS_DENIED);
3218 return 0;
3219 }
3220
3221 WindowObject = IntGetWindowObject(hWnd);
3222 if (WindowObject == NULL)
3223 {
3224 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3225 return 0;
3226 }
3227
3228 if ((INT)Index >= 0)
3229 {
3230 if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
3231 {
3232 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3233 IntReleaseWindowObject(WindowObject);
3234 return 0;
3235 }
3236 OldValue = *((LONG *)(WindowObject->ExtraData + Index));
3237 *((LONG *)(WindowObject->ExtraData + Index)) = NewValue;
3238 }
3239 else
3240 {
3241 switch (Index)
3242 {
3243 case GWL_EXSTYLE:
3244 OldValue = (LONG) WindowObject->ExStyle;
3245 Style.styleOld = OldValue;
3246 Style.styleNew = NewValue;
3247
3248 /*
3249 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3250 */
3251 Process = WindowObject->OwnerThread->ThreadsProcess->Win32Process;
3252 WindowStation = Process->WindowStation;
3253 if(WindowStation)
3254 {
3255 if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3256 Style.styleNew &= ~WS_EX_TOPMOST;
3257 }
3258
3259 IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3260 WindowObject->ExStyle = (DWORD)Style.styleNew;
3261 IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3262 break;
3263
3264 case GWL_STYLE:
3265 OldValue = (LONG) WindowObject->Style;
3266 Style.styleOld = OldValue;
3267 Style.styleNew = NewValue;
3268 IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3269 WindowObject->Style = (DWORD)Style.styleNew;
3270 IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3271 break;
3272
3273 case GWL_WNDPROC:
3274 /* FIXME: should check if window belongs to current process */
3275 if (Ansi)
3276 {
3277 OldValue = (LONG) WindowObject->WndProcA;
3278 WindowObject->WndProcA = (WNDPROC) NewValue;
3279 WindowObject->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE);
3280 WindowObject->Unicode = FALSE;
3281 }
3282 else
3283 {
3284 OldValue = (LONG) WindowObject->WndProcW;
3285 WindowObject->WndProcW = (WNDPROC) NewValue;
3286 WindowObject->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE);
3287 WindowObject->Unicode = TRUE;
3288 }
3289 break;
3290
3291 case GWL_HINSTANCE:
3292 OldValue = (LONG) WindowObject->Instance;
3293 WindowObject->Instance = (HINSTANCE) NewValue;
3294 break;
3295
3296 case GWL_HWNDPARENT:
3297 Parent = IntGetParentObject(WindowObject);
3298 if (Parent && (Parent->Self == IntGetDesktopWindow()))
3299 OldValue = (LONG) IntSetOwner(WindowObject->Self, (HWND) NewValue);
3300 else
3301 OldValue = (LONG) NtUserSetParent(WindowObject->Self, (HWND) NewValue);
3302 if(Parent)
3303 IntReleaseWindowObject(Parent);
3304 break;
3305
3306 case GWL_ID:
3307 OldValue = (LONG) WindowObject->IDMenu;
3308 WindowObject->IDMenu = (UINT) NewValue;
3309 break;
3310
3311 case GWL_USERDATA:
3312 OldValue = WindowObject->UserData;
3313 WindowObject->UserData = NewValue;
3314 break;
3315
3316 default:
3317 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
3318 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3319 OldValue = 0;
3320 break;
3321 }
3322 }
3323
3324 IntReleaseWindowObject(WindowObject);
3325
3326 return OldValue;
3327 }
3328
3329 /*
3330 * NtUserSetWindowWord
3331 *
3332 * Legacy function similar to NtUserSetWindowLong.
3333 *
3334 * Status
3335 * @implemented
3336 */
3337
3338 WORD STDCALL
3339 NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
3340 {
3341 PWINDOW_OBJECT WindowObject;
3342 WORD OldValue;
3343
3344 switch (Index)
3345 {
3346 case GWL_ID:
3347 case GWL_HINSTANCE:
3348 case GWL_HWNDPARENT:
3349 return NtUserSetWindowLong(hWnd, Index, (UINT)NewValue, TRUE);
3350 default:
3351 if (Index < 0)
3352 {
3353 SetLastWin32Error(ERROR_INVALID_INDEX);
3354 return 0;
3355 }
3356 }
3357
3358 WindowObject = IntGetWindowObject(hWnd);
3359 if (WindowObject == NULL)
3360 {
3361 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3362 return 0;
3363 }
3364
3365 if (Index > WindowObject->ExtraDataSize - sizeof(WORD))
3366 {
3367 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3368 IntReleaseWindowObject(WindowObject);
3369 return 0;
3370 }
3371
3372 OldValue = *((WORD *)(WindowObject->ExtraData + Index));
3373 *((WORD *)(WindowObject->ExtraData + Index)) = NewValue;
3374
3375 IntReleaseWindowObject(WindowObject);
3376
3377 return OldValue;
3378 }
3379
3380 /*
3381 * @implemented
3382 */
3383 BOOL STDCALL
3384 NtUserGetWindowPlacement(HWND hWnd,
3385 WINDOWPLACEMENT *lpwndpl)
3386 {
3387 PWINDOW_OBJECT WindowObject;
3388 PINTERNALPOS InternalPos;
3389 POINT Size;
3390 WINDOWPLACEMENT Safepl;
3391 NTSTATUS Status;
3392
3393 WindowObject = IntGetWindowObject(hWnd);
3394 if (WindowObject == NULL)
3395 {
3396 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3397 return FALSE;
3398 }
3399
3400 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3401 if(!NT_SUCCESS(Status))
3402 {
3403 SetLastNtError(Status);
3404 IntReleaseWindowObject(WindowObject);
3405 return FALSE;
3406 }
3407 if(Safepl.length != sizeof(WINDOWPLACEMENT))
3408 {
3409 IntReleaseWindowObject(WindowObject);
3410 return FALSE;
3411 }
3412
3413 Safepl.flags = 0;
3414 Safepl.showCmd = ((WindowObject->Flags & WINDOWOBJECT_RESTOREMAX) ? SW_MAXIMIZE : SW_SHOWNORMAL);
3415
3416 Size.x = WindowObject->WindowRect.left;
3417 Size.y = WindowObject->WindowRect.top;
3418 InternalPos = WinPosInitInternalPos(WindowObject, &Size,
3419 &WindowObject->WindowRect);
3420 if (InternalPos)
3421 {
3422 Safepl.rcNormalPosition = InternalPos->NormalRect;
3423 Safepl.ptMinPosition = InternalPos->IconPos;
3424 Safepl.ptMaxPosition = InternalPos->MaxPos;
3425 }
3426 else
3427 {
3428 IntReleaseWindowObject(WindowObject);
3429 return FALSE;
3430 }
3431
3432 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
3433 if(!NT_SUCCESS(Status))
3434 {
3435 SetLastNtError(Status);
3436 IntReleaseWindowObject(WindowObject);
3437 return FALSE;
3438 }
3439
3440 IntReleaseWindowObject(WindowObject);
3441 return TRUE;
3442 }
3443
3444
3445 /*!
3446 * Return the dimension of the window in the screen coordinates.
3447 * \param hWnd window handle.
3448 * \param Rect pointer to the buffer where the coordinates are returned.
3449 */
3450 /*
3451 * @implemented
3452 */
3453 BOOL STDCALL
3454 NtUserGetWindowRect(HWND hWnd, LPRECT Rect)
3455 {
3456 PWINDOW_OBJECT Wnd;
3457 NTSTATUS Status;
3458
3459 if (!(Wnd = IntGetWindowObject(hWnd)))
3460 {
3461 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3462 return FALSE;
3463 }
3464 Status = MmCopyToCaller(Rect, &Wnd->WindowRect, sizeof(RECT));
3465 if (!NT_SUCCESS(Status))
3466 {
3467 IntReleaseWindowObject(Wnd);
3468 SetLastNtError(Status);
3469 return FALSE;
3470 }
3471
3472 IntReleaseWindowObject(Wnd);
3473 return TRUE;
3474 }
3475
3476
3477 /*
3478 * @implemented
3479 */
3480 DWORD STDCALL
3481 NtUserGetWindowThreadProcessId(HWND hWnd, LPDWORD UnsafePid)
3482 {
3483 PWINDOW_OBJECT Wnd;
3484 DWORD tid, pid;
3485
3486 if (!(Wnd = IntGetWindowObject(hWnd)))
3487 {
3488 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3489 return 0;
3490 }
3491
3492 tid = (DWORD)IntGetWndThreadId(Wnd);
3493 pid = (DWORD)IntGetWndProcessId(Wnd);
3494
3495 if (UnsafePid) MmCopyToCaller(UnsafePid, &pid, sizeof(DWORD));
3496
3497 return tid;
3498 }
3499
3500
3501 /*
3502 * @unimplemented
3503 */
3504 DWORD STDCALL
3505 NtUserLockWindowUpdate(DWORD Unknown0)
3506 {
3507 UNIMPLEMENTED
3508
3509 return 0;
3510 }
3511
3512
3513 /*
3514 * @implemented
3515 */
3516 BOOL STDCALL
3517 NtUserMoveWindow(
3518 HWND hWnd,
3519 int X,
3520 int Y,
3521 int nWidth,
3522 int nHeight,
3523 BOOL bRepaint)
3524 {
3525 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
3526 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
3527 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
3528 }
3529
3530 /*
3531 QueryWindow based on KJK::Hyperion and James Tabor.
3532
3533 0 = QWUniqueProcessId
3534 1 = QWUniqueThreadId
3535 4 = QWIsHung Implements IsHungAppWindow found
3536 by KJK::Hyperion.
3537
3538 9 = QWKillWindow When I called this with hWnd ==
3539 DesktopWindow, it shutdown the system
3540 and rebooted.
3541 */
3542 /*
3543 * @implemented
3544 */
3545 DWORD STDCALL
3546 NtUserQueryWindow(HWND hWnd, DWORD Index)
3547 {
3548 PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
3549 DWORD Result;
3550
3551 if (Window == NULL)
3552 {
3553 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3554 return 0;
3555 }
3556
3557 switch(Index)
3558 {
3559 case QUERY_WINDOW_UNIQUE_PROCESS_ID:
3560 Result = (DWORD)IntGetWndProcessId(Window);
3561 break;
3562
3563 case QUERY_WINDOW_UNIQUE_THREAD_ID:
3564 Result = (DWORD)IntGetWndThreadId(Window);
3565 break;
3566
3567 case QUERY_WINDOW_ISHUNG:
3568 Result = (DWORD)MsqIsHung(Window->MessageQueue);
3569 break;
3570
3571 default:
3572 Result = (DWORD)NULL;
3573 break;
3574 }
3575
3576 IntReleaseWindowObject(Window);
3577
3578 return Result;
3579 }
3580
3581
3582 /*
3583 * @unimplemented
3584 */
3585 DWORD STDCALL
3586 NtUserRealChildWindowFromPoint(DWORD Unknown0,
3587 DWORD Unknown1,
3588 DWORD Unknown2)
3589 {
3590 UNIMPLEMENTED
3591
3592 return 0;
3593 }
3594
3595
3596 /*
3597 * @implemented
3598 */
3599 UINT STDCALL
3600 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
3601 {
3602 #if 0
3603 PLIST_ENTRY Current;
3604 PREGISTERED_MESSAGE NewMsg, RegMsg;
3605 UINT Msg = REGISTERED_MESSAGE_MIN;
3606 UNICODE_STRING MessageName;
3607 NTSTATUS Status;
3608
3609 Status = MmCopyFromCaller(&MessageName, MessageNameUnsafe, sizeof(UNICODE_STRING));
3610 if (! NT_SUCCESS(Status))
3611 {
3612 SetLastNtError(Status);
3613 return 0;
3614 }
3615
3616 NewMsg = ExAllocatePoolWithTag(PagedPool,
3617 sizeof(REGISTERED_MESSAGE) +
3618 MessageName.Length,
3619 TAG_WNAM);
3620 if (NULL == NewMsg)
3621 {
3622 SetLastNtError(STATUS_NO_MEMORY);
3623 return 0;
3624 }
3625
3626 Status = MmCopyFromCaller(NewMsg->MessageName, MessageName.Buffer, MessageName.Length);
3627 if (! NT_SUCCESS(Status))
3628 {
3629 ExFreePool(NewMsg);
3630 SetLastNtError(Status);
3631 return 0;
3632 }
3633 NewMsg->MessageName[MessageName.Length / sizeof(WCHAR)] = L'\0';
3634 if (wcslen(NewMsg->MessageName) != MessageName.Length / sizeof(WCHAR))
3635 {
3636 ExFreePool(NewMsg);
3637 SetLastNtError(STATUS_INVALID_PARAMETER);
3638 return 0;
3639 }
3640
3641 Current = RegisteredMessageListHead.Flink;
3642 while (Current != &RegisteredMessageListHead)
3643 {
3644 RegMsg = CONTAINING_RECORD(Current, REGISTERED_MESSAGE, ListEntry);
3645 if (0 == wcscmp(NewMsg->MessageName, RegMsg->MessageName))
3646 {
3647 ExFreePool(NewMsg);
3648 return Msg;
3649 }
3650 Msg++;
3651 Current = Current->Flink;
3652 }
3653
3654 if (REGISTERED_MESSAGE_MAX < Msg)
3655 {
3656 ExFreePool(NewMsg);
3657 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
3658 return 0;
3659 }
3660
3661 InsertTailList(&RegisteredMessageListHead, &(NewMsg->ListEntry));
3662
3663 return Msg;
3664 #else
3665 /*
3666 * Notes:
3667 * - There's no need to call MmSafe*, because it should be done in kernel.
3668 * - The passed UNICODE_STRING is expected to be NULL-terminated.
3669 */
3670 return (UINT)IntAddAtom(MessageNameUnsafe->Buffer);
3671 #endif
3672 }
3673
3674
3675 /*
3676 * @unimplemented
3677 */
3678 DWORD STDCALL
3679 NtUserSetImeOwnerWindow(DWORD Unknown0,
3680 DWORD Unknown1)
3681 {
3682 UNIMPLEMENTED
3683
3684 return 0;
3685 }
3686
3687
3688 /*
3689 * @unimplemented
3690 */
3691 DWORD STDCALL
3692 NtUserSetInternalWindowPos(DWORD Unknown0,
3693 DWORD Unknown1,
3694 DWORD Unknown2,
3695 DWORD Unknown3)
3696 {
3697 UNIMPLEMENTED
3698
3699 return 0;
3700
3701 }
3702
3703
3704 /*
3705 * @unimplemented
3706 */
3707 DWORD STDCALL
3708 NtUserSetLayeredWindowAttributes(DWORD Unknown0,
3709 DWORD Unknown1,
3710 DWORD Unknown2,
3711 DWORD Unknown3)
3712 {
3713 UNIMPLEMENTED
3714
3715 return 0;
3716 }
3717
3718
3719 /*
3720 * @unimplemented
3721 */
3722 DWORD STDCALL
3723 NtUserSetLogonNotifyWindow(DWORD Unknown0)
3724 {
3725 UNIMPLEMENTED
3726
3727 return 0;
3728 }
3729
3730
3731 /*
3732 * @implemented
3733 */
3734 BOOL STDCALL
3735 NtUserSetMenu(
3736 HWND Wnd,
3737 HMENU Menu,
3738 BOOL Repaint)
3739 {
3740 PWINDOW_OBJECT WindowObject;
3741 BOOL Changed;
3742
3743 WindowObject = IntGetWindowObject((HWND) Wnd);
3744 if (NULL == WindowObject)
3745 {
3746 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3747 return FALSE;
3748 }
3749
3750 if (! IntSetMenu(WindowObject, Menu, &Changed))
3751 {
3752 IntReleaseWindowObject(WindowObject);
3753 return FALSE;
3754 }
3755
3756 IntReleaseWindowObject(WindowObject);
3757
3758 if (Changed && Repaint)
3759 {
3760 WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
3761 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
3762 }
3763
3764 return TRUE;
3765 }
3766
3767
3768 /*
3769 * @unimplemented
3770 */
3771 DWORD STDCALL
3772 NtUserSetWindowFNID(DWORD Unknown0,
3773 DWORD Unknown1)
3774 {
3775 UNIMPLEMENTED
3776
3777 return 0;
3778 }
3779
3780
3781
3782 /*
3783 * @implemented
3784 */
3785 BOOL STDCALL
3786 NtUserSetWindowPlacement(HWND hWnd,
3787 WINDOWPLACEMENT *lpwndpl)
3788 {
3789 PWINDOW_OBJECT WindowObject;
3790 WINDOWPLACEMENT Safepl;
3791 NTSTATUS Status;
3792
3793 WindowObject = IntGetWindowObject(hWnd);
3794 if (WindowObject == NULL)
3795 {
3796 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3797 return FALSE;
3798 }
3799 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3800 if(!NT_SUCCESS(Status))
3801 {
3802 SetLastNtError(Status);
3803 IntReleaseWindowObject(WindowObject);
3804 return FALSE;
3805 }
3806 if(Safepl.length != sizeof(WINDOWPLACEMENT))
3807 {
3808 IntReleaseWindowObject(WindowObject);
3809 return FALSE;
3810 }
3811
3812 if ((WindowObject->Style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
3813 {
3814 WinPosSetWindowPos(WindowObject->Self, NULL,
3815 Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
3816 Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
3817 Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
3818 SWP_NOZORDER | SWP_NOACTIVATE);
3819 }
3820
3821 /* FIXME - change window status */
3822 WinPosShowWindow(WindowObject->Self, Safepl.showCmd);
3823
3824 if (WindowObject->InternalPos == NULL)
3825 WindowObject->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
3826 WindowObject->InternalPos->NormalRect = Safepl.rcNormalPosition;
3827 WindowObject->InternalPos->IconPos = Safepl.ptMinPosition;
3828 WindowObject->InternalPos->MaxPos = Safepl.ptMaxPosition;
3829
3830 IntReleaseWindowObject(WindowObject);
3831 return TRUE;
3832 }
3833
3834
3835 /*
3836 * @implemented
3837 */
3838 BOOL STDCALL
3839 NtUserSetWindowPos(
3840 HWND hWnd,
3841 HWND hWndInsertAfter,
3842 int X,
3843 int Y,
3844 int cx,
3845 int cy,
3846 UINT uFlags)
3847 {
3848 return WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
3849 }
3850
3851
3852 INT FASTCALL
3853 IntGetWindowRgn(HWND hWnd, HRGN hRgn)
3854 {
3855 INT Ret;
3856 PWINDOW_OBJECT WindowObject;
3857 HRGN VisRgn;
3858 ROSRGNDATA *pRgn;
3859
3860 if(!(WindowObject = IntGetWindowObject(hWnd)))
3861 {
3862 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3863 return ERROR;
3864 }
3865 if(!hRgn)
3866 {
3867 IntReleaseWindowObject(WindowObject);
3868 return ERROR;
3869 }
3870
3871 /* Create a new window region using the window rectangle */
3872 VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
3873 NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
3874 /* if there's a region assigned to the window, combine them both */
3875 if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
3876 NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
3877 /* Copy the region into hRgn */
3878 NtGdiCombineRgn(hRgn, VisRgn, NULL, RGN_COPY);
3879
3880 if((pRgn = RGNDATA_LockRgn(hRgn)))
3881 {
3882 Ret = pRgn->rdh.iType;
3883 RGNDATA_UnlockRgn(hRgn);
3884 }
3885 else
3886 Ret = ERROR;
3887
3888 NtGdiDeleteObject(VisRgn);
3889
3890 IntReleaseWindowObject(WindowObject);
3891 return Ret;
3892 }
3893
3894 INT FASTCALL
3895 IntGetWindowRgnBox(HWND hWnd, RECT *Rect)
3896 {
3897 INT Ret;
3898 PWINDOW_OBJECT WindowObject;
3899 HRGN VisRgn;
3900 ROSRGNDATA *pRgn;
3901
3902 if(!(WindowObject = IntGetWindowObject(hWnd)))
3903 {
3904 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3905 return ERROR;
3906 }
3907 if(!Rect)
3908 {
3909 IntReleaseWindowObject(WindowObject);
3910 return ERROR;
3911 }
3912
3913 /* Create a new window region using the window rectangle */
3914 VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
3915 NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
3916 /* if there's a region assigned to the window, combine them both */
3917 if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
3918 NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
3919
3920 if((pRgn = RGNDATA_LockRgn(VisRgn)))
3921 {
3922 Ret = pRgn->rdh.iType;
3923 *Rect = pRgn->rdh.rcBound;
3924 RGNDATA_UnlockRgn(VisRgn);
3925 }
3926 else
3927 Ret = ERROR;
3928
3929 NtGdiDeleteObject(VisRgn);
3930
3931 IntReleaseWindowObject(WindowObject);
3932 return Ret;
3933 }
3934
3935
3936 /*
3937 * @implemented
3938 */
3939 INT STDCALL
3940 NtUserSetWindowRgn(
3941 HWND hWnd,
3942 HRGN hRgn,
3943 BOOL bRedraw)
3944 {
3945 PWINDOW_OBJECT WindowObject;
3946
3947 WindowObject = IntGetWindowObject(hWnd);
3948 if (WindowObject == NULL)
3949 {
3950 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3951 return 0;
3952 }
3953
3954 /* FIXME - Verify if hRgn is a valid handle!!!!
3955 Propably make this operation thread-safe, but maybe it's not necessary */
3956
3957 if(WindowObject->WindowRegion)
3958 {
3959 /* Delete no longer needed region handle */
3960 NtGdiDeleteObject(WindowObject->WindowRegion);
3961 }
3962 WindowObject->WindowRegion = hRgn;
3963
3964 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
3965
3966 if(bRedraw)
3967 {
3968 IntRedrawWindow(WindowObject, NULL, NULL, RDW_INVALIDATE);
3969 }
3970
3971 IntReleaseWindowObject(WindowObject);
3972 return (INT)hRgn;
3973 }
3974
3975
3976 /*
3977 * @implemented
3978 */
3979 BOOL STDCALL
3980 NtUserShowWindow(HWND hWnd,
3981 LONG nCmdShow)
3982 {
3983 return WinPosShowWindow(hWnd, nCmdShow);
3984 }
3985
3986
3987 /*
3988 * @unimplemented
3989 */
3990 DWORD STDCALL
3991 NtUserShowWindowAsync(DWORD Unknown0,
3992 DWORD Unknown1)
3993 {
3994 UNIMPLEMENTED
3995
3996 return 0;
3997 }
3998
3999
4000 /*
4001 * @unimplemented
4002 */
4003 DWORD STDCALL
4004 NtUserUpdateLayeredWindow(DWORD Unknown0,
4005 DWORD Unknown1,
4006 DWORD Unknown2,
4007 DWORD Unknown3,
4008 DWORD Unknown4,
4009 DWORD Unknown5,
4010 DWORD Unknown6,
4011 DWORD Unknown7,
4012 DWORD Unknown8)
4013 {
4014 UNIMPLEMENTED
4015
4016 return 0;
4017 }
4018
4019
4020 /*
4021 * @implemented
4022 */
4023 VOID STDCALL
4024 NtUserValidateRect(HWND hWnd, const RECT* Rect)
4025 {
4026 return (VOID)NtUserRedrawWindow(hWnd, Rect, 0, RDW_VALIDATE | RDW_NOCHILDREN);
4027 }
4028
4029
4030 /*
4031 * @implemented
4032 */
4033 HWND STDCALL
4034 NtUserWindowFromPoint(LONG X, LONG Y)
4035 {
4036 POINT pt;
4037 HWND Ret;
4038 PWINDOW_OBJECT DesktopWindow, Window = NULL;
4039
4040 if ((DesktopWindow = IntGetWindowObject(IntGetDesktopWindow())))
4041 {
4042 USHORT Hit;
4043
4044 pt.x = X;
4045 pt.y = Y;
4046
4047 Hit = WinPosWindowFromPoint(DesktopWindow, PsGetWin32Thread()->MessageQueue, &pt, &Window);
4048
4049 if(Window)
4050 {
4051 Ret = Window->Self;
4052 IntReleaseWindowObject(Window);
4053 IntReleaseWindowObject(DesktopWindow);
4054 return Ret;
4055 }
4056
4057 IntReleaseWindowObject(DesktopWindow);
4058 }
4059
4060 return NULL;
4061 }
4062
4063
4064 /*
4065 * NtUserDefSetText
4066 *
4067 * Undocumented function that is called from DefWindowProc to set
4068 * window text.
4069 *
4070 * Status
4071 * @implemented
4072 */
4073
4074 BOOL STDCALL
4075 NtUserDefSetText(HWND WindowHandle, PUNICODE_STRING WindowText)
4076 {
4077 PWINDOW_OBJECT WindowObject;
4078 UNICODE_STRING SafeText;
4079 NTSTATUS Status;
4080
4081 WindowObject = IntGetWindowObject(WindowHandle);
4082 if(!WindowObject)
4083 {
4084 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4085 return FALSE;
4086 }
4087
4088 if(WindowText)
4089 {
4090 Status = IntSafeCopyUnicodeString(&SafeText, WindowText);
4091 if(!NT_SUCCESS(Status))
4092 {
4093 SetLastNtError(Status);
4094 IntReleaseWindowObject(WindowObject);
4095 return FALSE;
4096 }
4097 }
4098 else
4099 {
4100 RtlInitUnicodeString(&SafeText, NULL);
4101 }
4102
4103 /* FIXME - do this thread-safe! otherwise one could crash here! */
4104 RtlFreeUnicodeString(&WindowObject->WindowName);
4105
4106 WindowObject->WindowName = SafeText;
4107
4108 IntReleaseWindowObject(WindowObject);
4109 return TRUE;
4110 }
4111
4112 /*
4113 * NtUserInternalGetWindowText
4114 *
4115 * Status
4116 * @implemented
4117 */
4118
4119 INT STDCALL
4120 NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
4121 {
4122 PWINDOW_OBJECT WindowObject;
4123 NTSTATUS Status;
4124 INT Result;
4125
4126 if(lpString && (nMaxCount <= 1))
4127 {
4128 SetLastWin32Error(ERROR_INVALID_PARAMETER);
4129 return 0;
4130 }
4131
4132 WindowObject = IntGetWindowObject(hWnd);
4133 if(!WindowObject)
4134 {
4135 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4136 return 0;
4137 }
4138
4139 /* FIXME - do this thread-safe! otherwise one could crash here! */
4140 Result = WindowObject->WindowName.Length / sizeof(WCHAR);
4141 if(lpString)
4142 {
4143 const WCHAR Terminator = L'\0';
4144 INT Copy;
4145 WCHAR *Buffer = (WCHAR*)lpString;
4146
4147 Copy = min(nMaxCount - 1, Result);
4148 if(Copy > 0)
4149 {
4150 Status = MmCopyToCaller(Buffer, WindowObject->WindowName.Buffer, Copy * sizeof(WCHAR));
4151 if(!NT_SUCCESS(Status))
4152 {
4153 SetLastNtError(Status);
4154 IntReleaseWindowObject(WindowObject);
4155 return 0;
4156 }
4157 Buffer += Copy;
4158 }
4159
4160 Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
4161 if(!NT_SUCCESS(Status))
4162 {
4163 SetLastNtError(Status);
4164 IntReleaseWindowObject(WindowObject);
4165 return 0;
4166 }
4167
4168 Result = Copy;
4169 }
4170
4171 IntReleaseWindowObject(WindowObject);
4172 return Result;
4173 }
4174
4175 DWORD STDCALL
4176 NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data)
4177 {
4178 WndProcHandle Entry;
4179 if (((DWORD)wpHandle & 0xFFFF0000) == 0xFFFF0000)
4180 {
4181 Entry = WndProcHandlesArray[(DWORD)wpHandle & 0x0000FFFF];
4182 Data->WindowProc = Entry.WindowProc;
4183 Data->IsUnicode = Entry.IsUnicode;
4184 Data->ProcessID = Entry.ProcessID;
4185 return TRUE;
4186 } else {
4187 return FALSE;
4188 }
4189 return FALSE;
4190 }
4191
4192 DWORD
4193 IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode)
4194 {
4195 WORD i;
4196 WORD FreeSpot;
4197 BOOL found;
4198 WndProcHandle *OldArray;
4199 WORD OldArraySize;
4200 found = FALSE;
4201 for (i = 0;i < WndProcHandlesArraySize;i++)
4202 {
4203 if (WndProcHandlesArray[i].WindowProc == NULL)
4204 {
4205 FreeSpot = i;
4206 found = TRUE;
4207 }
4208 }
4209 if (!found)
4210 {
4211 OldArray = WndProcHandlesArray;
4212 OldArraySize = WndProcHandlesArraySize;
4213 WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,(OldArraySize + WPH_SIZE) * sizeof(WndProcHandle), TAG_WINPROCLST);
4214 WndProcHandlesArraySize = OldArraySize + WPH_SIZE;
4215 RtlCopyMemory(WndProcHandlesArray,OldArray,OldArraySize * sizeof(WndProcHandle));
4216 ExFreePool(OldArray);
4217 FreeSpot = OldArraySize + 1;
4218 }
4219 WndProcHandlesArray[FreeSpot].WindowProc = WindowProc;
4220 WndProcHandlesArray[FreeSpot].IsUnicode = IsUnicode;
4221 WndProcHandlesArray[FreeSpot].ProcessID = PsGetCurrentProcessId();
4222 return FreeSpot + 0xFFFF0000;
4223 }
4224
4225 DWORD
4226 IntRemoveWndProcHandle(WNDPROC Handle)
4227 {
4228 WORD position;
4229 position = (DWORD)Handle & 0x0000FFFF;
4230 if (position > WndProcHandlesArraySize)
4231 {
4232 return FALSE;
4233 }
4234 WndProcHandlesArray[position].WindowProc = NULL;
4235 WndProcHandlesArray[position].IsUnicode = FALSE;
4236 WndProcHandlesArray[position].ProcessID = NULL;
4237 return TRUE;
4238 }
4239
4240 DWORD
4241 IntRemoveProcessWndProcHandles(HANDLE ProcessID)
4242 {
4243 WORD i;
4244 for (i = 0;i < WndProcHandlesArraySize;i++)
4245 {
4246 if (WndProcHandlesArray[i].ProcessID == ProcessID)
4247 {
4248 WndProcHandlesArray[i].WindowProc = NULL;
4249 WndProcHandlesArray[i].IsUnicode = FALSE;
4250 WndProcHandlesArray[i].ProcessID = NULL;
4251 }
4252 }
4253 return TRUE;
4254 }
4255
4256 /* EOF */