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