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