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