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