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