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