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