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