remove user handle table lock, cursor locks, message queue locks, hook 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 ExInitializeFastMutex(&WindowObject->UpdateLock);
1582 InitializeListHead(&WindowObject->WndObjListHead);
1583 ExInitializeFastMutex(&WindowObject->WndObjListLock);
1584
1585 if (NULL != WindowName->Buffer)
1586 {
1587 WindowObject->WindowName.MaximumLength = WindowName->MaximumLength;
1588 WindowObject->WindowName.Length = WindowName->Length;
1589 WindowObject->WindowName.Buffer = ExAllocatePoolWithTag(PagedPool, WindowName->MaximumLength,
1590 TAG_STRING);
1591 if (NULL == WindowObject->WindowName.Buffer)
1592 {
1593 ClassDereferenceObject(ClassObject);
1594 DPRINT1("Failed to allocate mem for window name\n");
1595 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1596 return NULL;
1597 }
1598 RtlCopyMemory(WindowObject->WindowName.Buffer, WindowName->Buffer, WindowName->MaximumLength);
1599 }
1600 else
1601 {
1602 RtlInitUnicodeString(&WindowObject->WindowName, NULL);
1603 }
1604
1605
1606 /*
1607 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1608 * tested for WS_POPUP
1609 */
1610 if ((dwExStyle & WS_EX_DLGMODALFRAME) ||
1611 ((!(dwExStyle & WS_EX_STATICEDGE)) &&
1612 (dwStyle & (WS_DLGFRAME | WS_THICKFRAME))))
1613 dwExStyle |= WS_EX_WINDOWEDGE;
1614 else
1615 dwExStyle &= ~WS_EX_WINDOWEDGE;
1616
1617 /* Correct the window style. */
1618 if (!(dwStyle & WS_CHILD))
1619 {
1620 WindowObject->Style |= WS_CLIPSIBLINGS;
1621 DPRINT("3: Style is now %lx\n", WindowObject->Style);
1622 if (!(dwStyle & WS_POPUP))
1623 {
1624 WindowObject->Style |= WS_CAPTION;
1625 WindowObject->Flags |= WINDOWOBJECT_NEED_SIZE;
1626 DPRINT("4: Style is now %lx\n", WindowObject->Style);
1627 }
1628 }
1629
1630 /* create system menu */
1631 if((WindowObject->Style & WS_SYSMENU) &&
1632 (WindowObject->Style & WS_CAPTION) == WS_CAPTION)
1633 {
1634 SystemMenu = IntGetSystemMenu(WindowObject, TRUE, TRUE);
1635 if(SystemMenu)
1636 {
1637 WindowObject->SystemMenu = SystemMenu->MenuInfo.Self;
1638 IntReleaseMenuObject(SystemMenu);
1639 }
1640 }
1641
1642 /* Insert the window into the thread's window list. */
1643 InsertTailList (&PsGetWin32Thread()->WindowListHead,
1644 &WindowObject->ThreadListEntry);
1645
1646 /* Allocate a DCE for this window. */
1647 if (dwStyle & CS_OWNDC)
1648 {
1649 WindowObject->Dce = DceAllocDCE(WindowObject->Self, DCE_WINDOW_DC);
1650 }
1651 /* FIXME: Handle "CS_CLASSDC" */
1652
1653 Pos.x = x;
1654 Pos.y = y;
1655 Size.cx = nWidth;
1656 Size.cy = nHeight;
1657
1658 /* call hook */
1659 Cs.lpCreateParams = lpParam;
1660 Cs.hInstance = hInstance;
1661 Cs.hMenu = hMenu;
1662 Cs.hwndParent = ParentWindowHandle;
1663 Cs.cx = Size.cx;
1664 Cs.cy = Size.cy;
1665 Cs.x = Pos.x;
1666 Cs.y = Pos.y;
1667 Cs.style = dwStyle;
1668 Cs.lpszName = (LPCWSTR) WindowName;
1669 Cs.lpszClass = (LPCWSTR) ClassName;
1670 Cs.dwExStyle = dwExStyle;
1671 CbtCreate.lpcs = &Cs;
1672 CbtCreate.hwndInsertAfter = HWND_TOP;
1673 if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) Handle, (LPARAM) &CbtCreate))
1674 {
1675 if (NULL != ParentWindow)
1676 {
1677 IntReleaseWindowObject(ParentWindow);
1678 }
1679
1680 /* FIXME - Delete window object and remove it from the thread windows list */
1681 /* FIXME - delete allocated DCE */
1682
1683 ClassDereferenceObject(ClassObject);
1684 DPRINT1("CBT-hook returned !0\n");
1685 return (HWND) NULL;
1686 }
1687
1688 x = Cs.x;
1689 y = Cs.y;
1690 nWidth = Cs.cx;
1691 nHeight = Cs.cy;
1692
1693 /* default positioning for overlapped windows */
1694 if(!(WindowObject->Style & (WS_POPUP | WS_CHILD)))
1695 {
1696 RECT rc, WorkArea;
1697 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
1698 BOOL CalculatedDefPosSize = FALSE;
1699
1700 IntGetDesktopWorkArea(WindowObject->OwnerThread->Tcb.Win32Thread->Desktop, &WorkArea);
1701
1702 rc = WorkArea;
1703 ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;
1704
1705 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
1706 {
1707 CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, WindowObject, &rc, TRUE);
1708
1709 if(ProcessParams->WindowFlags & STARTF_USEPOSITION)
1710 {
1711 ProcessParams->WindowFlags &= ~STARTF_USEPOSITION;
1712 Pos.x = WorkArea.left + ProcessParams->StartingX;
1713 Pos.y = WorkArea.top + ProcessParams->StartingY;
1714 }
1715 else
1716 {
1717 Pos.x = rc.left;
1718 Pos.y = rc.top;
1719 }
1720
1721 /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
1722 y is something else */
1723 if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16)
1724 {
1725 dwShowMode = y;
1726 }
1727 }
1728 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
1729 {
1730 if(!CalculatedDefPosSize)
1731 {
1732 IntCalcDefPosSize(ParentWindow, WindowObject, &rc, FALSE);
1733 }
1734 if(ProcessParams->WindowFlags & STARTF_USESIZE)
1735 {
1736 ProcessParams->WindowFlags &= ~STARTF_USESIZE;
1737 Size.cx = ProcessParams->CountX;
1738 Size.cy = ProcessParams->CountY;
1739 }
1740 else
1741 {
1742 Size.cx = rc.right - rc.left;
1743 Size.cy = rc.bottom - rc.top;
1744 }
1745
1746 /* move the window if necessary */
1747 if(Pos.x > rc.left)
1748 Pos.x = max(rc.left, 0);
1749 if(Pos.y > rc.top)
1750 Pos.y = max(rc.top, 0);
1751 }
1752 }
1753 else
1754 {
1755 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
1756 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
1757 {
1758 Pos.x = 0;
1759 Pos.y = 0;
1760 }
1761 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
1762 {
1763 Size.cx = 0;
1764 Size.cy = 0;
1765 }
1766 }
1767
1768 /* Initialize the window dimensions. */
1769 WindowObject->WindowRect.left = Pos.x;
1770 WindowObject->WindowRect.top = Pos.y;
1771 WindowObject->WindowRect.right = Pos.x + Size.cx;
1772 WindowObject->WindowRect.bottom = Pos.y + Size.cy;
1773 if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
1774 {
1775 IntGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left,
1776 ParentWindow->ClientRect.top);
1777 }
1778 WindowObject->ClientRect = WindowObject->WindowRect;
1779
1780 /*
1781 * Get the size and position of the window.
1782 */
1783 if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
1784 {
1785 POINT MaxSize, MaxPos, MinTrack, MaxTrack;
1786
1787 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
1788 co_WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack,
1789 &MaxTrack);
1790 if (MaxSize.x < nWidth) nWidth = MaxSize.x;
1791 if (MaxSize.y < nHeight) nHeight = MaxSize.y;
1792 if (nWidth < MinTrack.x ) nWidth = MinTrack.x;
1793 if (nHeight < MinTrack.y ) nHeight = MinTrack.y;
1794 if (nWidth < 0) nWidth = 0;
1795 if (nHeight < 0) nHeight = 0;
1796 }
1797
1798 WindowObject->WindowRect.left = Pos.x;
1799 WindowObject->WindowRect.top = Pos.y;
1800 WindowObject->WindowRect.right = Pos.x + Size.cx;
1801 WindowObject->WindowRect.bottom = Pos.y + Size.cy;
1802 if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
1803 {
1804 IntGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left,
1805 ParentWindow->ClientRect.top);
1806 }
1807 WindowObject->ClientRect = WindowObject->WindowRect;
1808
1809 /* FIXME: Initialize the window menu. */
1810
1811 /* Send a NCCREATE message. */
1812 Cs.cx = Size.cx;
1813 Cs.cy = Size.cy;
1814 Cs.x = Pos.x;
1815 Cs.y = Pos.y;
1816
1817 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
1818 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
1819 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
1820 Result = co_IntSendMessage(WindowObject->Self, WM_NCCREATE, 0, (LPARAM) &Cs);
1821 if (!Result)
1822 {
1823 /* FIXME: Cleanup. */
1824 if (NULL != ParentWindow)
1825 {
1826 IntReleaseWindowObject(ParentWindow);
1827 }
1828 DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
1829 return((HWND)0);
1830 }
1831
1832 /* Calculate the non-client size. */
1833 MaxPos.x = WindowObject->WindowRect.left;
1834 MaxPos.y = WindowObject->WindowRect.top;
1835 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
1836 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
1837 Result = co_WinPosGetNonClientSize(WindowObject->Self,
1838 &WindowObject->WindowRect,
1839 &WindowObject->ClientRect);
1840 IntGdiOffsetRect(&WindowObject->WindowRect,
1841 MaxPos.x - WindowObject->WindowRect.left,
1842 MaxPos.y - WindowObject->WindowRect.top);
1843
1844 if (NULL != ParentWindow)
1845 {
1846 /* link the window into the parent's child list */
1847 if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1848 {
1849 PWINDOW_OBJECT PrevSibling;
1850 if((PrevSibling = ParentWindow->LastChild))
1851 IntReferenceWindowObject(PrevSibling);
1852 /* link window as bottom sibling */
1853 IntLinkWindow(WindowObject, ParentWindow, PrevSibling /*prev sibling*/);
1854 if(PrevSibling)
1855 IntReleaseWindowObject(PrevSibling);
1856 }
1857 else
1858 {
1859 /* link window as top sibling (but after topmost siblings) */
1860 PWINDOW_OBJECT InsertAfter, Sibling;
1861 if (0 == (dwExStyle & WS_EX_TOPMOST))
1862 {
1863 InsertAfter = NULL;
1864 Sibling = ParentWindow->FirstChild;
1865 while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
1866 {
1867 InsertAfter = Sibling;
1868 Sibling = Sibling->NextSibling;
1869 }
1870 }
1871 else
1872 {
1873 InsertAfter = NULL;
1874 }
1875 if (NULL != InsertAfter)
1876 {
1877 IntReferenceWindowObject(InsertAfter);
1878 }
1879 IntLinkWindow(WindowObject, ParentWindow, InsertAfter /* prev sibling */);
1880 if (NULL != InsertAfter)
1881 {
1882 IntReleaseWindowObject(InsertAfter);
1883 }
1884 }
1885 }
1886
1887 /* Send the WM_CREATE message. */
1888 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
1889 Result = co_IntSendMessage(WindowObject->Self, WM_CREATE, 0, (LPARAM) &Cs);
1890 if (Result == (LRESULT)-1)
1891 {
1892 /* FIXME: Cleanup. */
1893 if (NULL != ParentWindow)
1894 {
1895 IntReleaseWindowObject(ParentWindow);
1896 }
1897 ClassDereferenceObject(ClassObject);
1898 DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
1899 return((HWND)0);
1900 }
1901
1902 /* Send move and size messages. */
1903 if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE))
1904 {
1905 LONG lParam;
1906
1907 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
1908
1909 if ((WindowObject->ClientRect.right - WindowObject->ClientRect.left) < 0 ||
1910 (WindowObject->ClientRect.bottom - WindowObject->ClientRect.top) < 0)
1911 {
1912 DPRINT("Sending bogus WM_SIZE\n");
1913 }
1914
1915 lParam = MAKE_LONG(WindowObject->ClientRect.right -
1916 WindowObject->ClientRect.left,
1917 WindowObject->ClientRect.bottom -
1918 WindowObject->ClientRect.top);
1919 co_IntSendMessage(WindowObject->Self, WM_SIZE, SIZE_RESTORED,
1920 lParam);
1921
1922 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
1923
1924 if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
1925 {
1926 lParam = MAKE_LONG(WindowObject->ClientRect.left - ParentWindow->ClientRect.left,
1927 WindowObject->ClientRect.top - ParentWindow->ClientRect.top);
1928 }
1929 else
1930 {
1931 lParam = MAKE_LONG(WindowObject->ClientRect.left,
1932 WindowObject->ClientRect.top);
1933 }
1934 co_IntSendMessage(WindowObject->Self, WM_MOVE, 0, lParam);
1935
1936 /* Call WNDOBJ change procs */
1937 IntEngWindowChanged(WindowObject, WOC_RGN_CLIENT);
1938 }
1939
1940 /* Show or maybe minimize or maximize the window. */
1941 if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE))
1942 {
1943 RECT NewPos;
1944 UINT16 SwFlag;
1945
1946 SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE :
1947 SW_MAXIMIZE;
1948 co_WinPosMinMaximize(WindowObject, SwFlag, &NewPos);
1949 SwFlag =
1950 ((WindowObject->Style & WS_CHILD) || UserGetActiveWindow()) ?
1951 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :
1952 SWP_NOZORDER | SWP_FRAMECHANGED;
1953 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
1954 DPRINT("%d,%d %dx%d\n", NewPos.left, NewPos.top, NewPos.right, NewPos.bottom);
1955 co_WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top,
1956 NewPos.right, NewPos.bottom, SwFlag);
1957 }
1958
1959 /* Notify the parent window of a new child. */
1960 if ((WindowObject->Style & WS_CHILD) &&
1961 (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow)
1962 {
1963 DPRINT("IntCreateWindow(): About to notify parent\n");
1964 co_IntSendMessage(ParentWindow->Self,
1965 WM_PARENTNOTIFY,
1966 MAKEWPARAM(WM_CREATE, WindowObject->IDMenu),
1967 (LPARAM)WindowObject->Self);
1968 }
1969
1970 if ((!hWndParent) && (!HasOwner)) {
1971 DPRINT("Sending CREATED notify\n");
1972 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Handle);
1973 } else {
1974 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow, HasOwner);
1975 }
1976
1977 if (NULL != ParentWindow)
1978 {
1979 IntReleaseWindowObject(ParentWindow);
1980 }
1981
1982 /* Initialize and show the window's scrollbars */
1983 if (WindowObject->Style & WS_VSCROLL)
1984 {
1985 co_UserShowScrollBar(WindowObject->Self, SB_VERT, TRUE);
1986 }
1987 if (WindowObject->Style & WS_HSCROLL)
1988 {
1989 co_UserShowScrollBar(WindowObject->Self, SB_HORZ, TRUE);
1990 }
1991
1992 if (dwStyle & WS_VISIBLE)
1993 {
1994 DPRINT("IntCreateWindow(): About to show window\n");
1995 co_WinPosShowWindow(WindowObject->Self, dwShowMode);
1996 }
1997
1998 DPRINT("IntCreateWindow(): = %X\n", Handle);
1999 DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject->SystemMenu);
2000 return((HWND)Handle);
2001 }
2002
2003 HWND STDCALL
2004 NtUserCreateWindowEx(DWORD dwExStyle,
2005 PUNICODE_STRING UnsafeClassName,
2006 PUNICODE_STRING UnsafeWindowName,
2007 DWORD dwStyle,
2008 LONG x,
2009 LONG y,
2010 LONG nWidth,
2011 LONG nHeight,
2012 HWND hWndParent,
2013 HMENU hMenu,
2014 HINSTANCE hInstance,
2015 LPVOID lpParam,
2016 DWORD dwShowMode,
2017 BOOL bUnicodeWindow)
2018 {
2019 NTSTATUS Status;
2020 UNICODE_STRING WindowName;
2021 UNICODE_STRING ClassName;
2022 HWND NewWindow;
2023 DECLARE_RETURN(HWND);
2024
2025 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
2026 UserEnterExclusive();
2027
2028 /* Get the class name (string or atom) */
2029 Status = MmCopyFromCaller(&ClassName, UnsafeClassName, sizeof(UNICODE_STRING));
2030 if (! NT_SUCCESS(Status))
2031 {
2032 SetLastNtError(Status);
2033 RETURN( NULL);
2034 }
2035 if (! IS_ATOM(ClassName.Buffer))
2036 {
2037 Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName);
2038 if (! NT_SUCCESS(Status))
2039 {
2040 SetLastNtError(Status);
2041 RETURN( NULL);
2042 }
2043 }
2044
2045 /* safely copy the window name */
2046 if (NULL != UnsafeWindowName)
2047 {
2048 Status = IntSafeCopyUnicodeString(&WindowName, UnsafeWindowName);
2049 if (! NT_SUCCESS(Status))
2050 {
2051 if (! IS_ATOM(ClassName.Buffer))
2052 {
2053 RtlFreeUnicodeString(&ClassName);
2054 }
2055 SetLastNtError(Status);
2056 RETURN( NULL);
2057 }
2058 }
2059 else
2060 {
2061 RtlInitUnicodeString(&WindowName, NULL);
2062 }
2063
2064 NewWindow = co_IntCreateWindowEx(dwExStyle, &ClassName, &WindowName, dwStyle, x, y, nWidth, nHeight,
2065 hWndParent, hMenu, hInstance, lpParam, dwShowMode, bUnicodeWindow);
2066
2067 RtlFreeUnicodeString(&WindowName);
2068 if (! IS_ATOM(ClassName.Buffer))
2069 {
2070 RtlFreeUnicodeString(&ClassName);
2071 }
2072
2073 RETURN( NewWindow);
2074
2075 CLEANUP:
2076 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_);
2077 UserLeave();
2078 END_CLEANUP;
2079 }
2080
2081 /*
2082 * @unimplemented
2083 */
2084 HDWP STDCALL
2085 NtUserDeferWindowPos(HDWP WinPosInfo,
2086 HWND Wnd,
2087 HWND WndInsertAfter,
2088 int x,
2089 int y,
2090 int cx,
2091 int cy,
2092 UINT Flags)
2093 {
2094 UNIMPLEMENTED
2095
2096 return 0;
2097 }
2098
2099
2100 BOOLEAN FASTCALL co_UserDestroyWindow(PWINDOW_OBJECT Window)
2101 {
2102 BOOLEAN isChild;
2103
2104 if (Window == NULL)
2105 {
2106 return FALSE;
2107 }
2108
2109 /* Check for owner thread and desktop window */
2110 if ((Window->OwnerThread != PsGetCurrentThread()) || IntIsDesktopWindow(Window))
2111 {
2112 SetLastWin32Error(ERROR_ACCESS_DENIED);
2113 return FALSE;
2114 }
2115
2116 /* Look whether the focus is within the tree of windows we will
2117 * be destroying.
2118 */
2119 if (!co_WinPosShowWindow(Window->Self, SW_HIDE))
2120 {
2121 if (UserGetActiveWindow() == Window->Self)
2122 {
2123 co_WinPosActivateOtherWindow(Window);
2124 }
2125 }
2126
2127 if (Window->MessageQueue->ActiveWindow == Window->Self)
2128 Window->MessageQueue->ActiveWindow = NULL;
2129 if (Window->MessageQueue->FocusWindow == Window->Self)
2130 Window->MessageQueue->FocusWindow = NULL;
2131 if (Window->MessageQueue->CaptureWindow == Window->Self)
2132 Window->MessageQueue->CaptureWindow = NULL;
2133
2134 IntDereferenceMessageQueue(Window->MessageQueue);
2135 /* Call hooks */
2136 #if 0 /* FIXME */
2137 if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hwnd, 0, TRUE))
2138 {
2139 return FALSE;
2140 }
2141 #endif
2142
2143 IntEngWindowChanged(Window, WOC_DELETE);
2144 isChild = (0 != (Window->Style & WS_CHILD));
2145
2146 #if 0 /* FIXME */
2147 if (isChild)
2148 {
2149 if (! USER_IsExitingThread(GetCurrentThreadId()))
2150 {
2151 send_parent_notify(hwnd, WM_DESTROY);
2152 }
2153 }
2154 else if (NULL != GetWindow(Wnd, GW_OWNER))
2155 {
2156 co_HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
2157 /* FIXME: clean up palette - see "Internals" p.352 */
2158 }
2159 #endif
2160
2161 if (!IntIsWindow(Window->Self))
2162 {
2163 return TRUE;
2164 }
2165
2166 /* Recursively destroy owned windows */
2167 if (! isChild)
2168 {
2169 for (;;)
2170 {
2171 BOOL GotOne = FALSE;
2172 HWND *Children;
2173 HWND *ChildHandle;
2174 PWINDOW_OBJECT Child, Desktop;
2175
2176 Desktop = IntGetWindowObject(IntGetDesktopWindow());
2177 Children = IntWinListChildren(Desktop);
2178 IntReleaseWindowObject(Desktop);
2179 if (Children)
2180 {
2181 for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
2182 {
2183 Child = IntGetWindowObject(*ChildHandle);
2184 if (Child == NULL)
2185 continue;
2186 if (Child->Owner != Window->Self)
2187 {
2188 IntReleaseWindowObject(Child);
2189 continue;
2190 }
2191
2192 if (IntWndBelongsToThread(Child, PsGetWin32Thread()))
2193 {
2194 co_UserDestroyWindow(Child);
2195 IntReleaseWindowObject(Child);
2196 GotOne = TRUE;
2197 continue;
2198 }
2199
2200 if (Child->Owner != NULL)
2201 {
2202 Child->Owner = NULL;
2203 }
2204
2205 IntReleaseWindowObject(Child);
2206 }
2207 ExFreePool(Children);
2208 }
2209 if (! GotOne)
2210 {
2211 break;
2212 }
2213 }
2214 }
2215
2216 if (!IntIsWindow(Window->Self))
2217 {
2218 return TRUE;
2219 }
2220
2221 /* Destroy the window storage */
2222 co_IntDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
2223
2224 return TRUE;
2225 }
2226
2227
2228
2229
2230 /*
2231 * @implemented
2232 */
2233 BOOLEAN STDCALL
2234 NtUserDestroyWindow(HWND Wnd)
2235 {
2236 PWINDOW_OBJECT Window;
2237 DECLARE_RETURN(BOOLEAN);
2238
2239 DPRINT("Enter NtUserDestroyWindow\n");
2240 UserEnterExclusive();
2241
2242 Window = IntGetWindowObject(Wnd);
2243 if (Window == NULL)
2244 {
2245 RETURN(FALSE);
2246 }
2247
2248 RETURN(co_UserDestroyWindow(Window));
2249
2250 CLEANUP:
2251 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_);
2252 UserLeave();
2253 END_CLEANUP;
2254 }
2255
2256
2257
2258 /*
2259 * @unimplemented
2260 */
2261 DWORD
2262 STDCALL
2263 NtUserDrawMenuBarTemp(
2264 HWND hWnd,
2265 HDC hDC,
2266 PRECT hRect,
2267 HMENU hMenu,
2268 HFONT hFont)
2269 {
2270 /* we'll use this function just for caching the menu bar */
2271 UNIMPLEMENTED
2272 return 0;
2273 }
2274
2275
2276 /*
2277 * @unimplemented
2278 */
2279 DWORD STDCALL
2280 NtUserEndDeferWindowPosEx(DWORD Unknown0,
2281 DWORD Unknown1)
2282 {
2283 UNIMPLEMENTED
2284
2285 return 0;
2286 }
2287
2288
2289 /*
2290 * @unimplemented
2291 */
2292 DWORD STDCALL
2293 NtUserFillWindow(DWORD Unknown0,
2294 DWORD Unknown1,
2295 DWORD Unknown2,
2296 DWORD Unknown3)
2297 {
2298 UNIMPLEMENTED
2299
2300 return 0;
2301 }
2302
2303
2304 HWND FASTCALL
2305 IntFindWindow(PWINDOW_OBJECT Parent,
2306 PWINDOW_OBJECT ChildAfter,
2307 RTL_ATOM ClassAtom,
2308 PUNICODE_STRING WindowName)
2309 {
2310 BOOL CheckWindowName;
2311 HWND *List, *phWnd;
2312 HWND Ret = NULL;
2313
2314 ASSERT(Parent);
2315
2316 CheckWindowName = (WindowName && (WindowName->Length > 0));
2317
2318 if((List = IntWinListChildren(Parent)))
2319 {
2320 phWnd = List;
2321 if(ChildAfter)
2322 {
2323 /* skip handles before and including ChildAfter */
2324 while(*phWnd && (*(phWnd++) != ChildAfter->Self));
2325 }
2326
2327 /* search children */
2328 while(*phWnd)
2329 {
2330 PWINDOW_OBJECT Child;
2331 if(!(Child = IntGetWindowObject(*(phWnd++))))
2332 {
2333 continue;
2334 }
2335
2336 /* Do not send WM_GETTEXT messages in the kernel mode version!
2337 The user mode version however calls GetWindowText() which will
2338 send WM_GETTEXT messages to windows belonging to its processes */
2339 if((!CheckWindowName || !RtlCompareUnicodeString(WindowName, &(Child->WindowName), FALSE)) &&
2340 (!ClassAtom || Child->Class->Atom == ClassAtom))
2341 {
2342 Ret = Child->Self;
2343 IntReleaseWindowObject(Child);
2344 break;
2345 }
2346
2347 IntReleaseWindowObject(Child);
2348 }
2349 ExFreePool(List);
2350 }
2351
2352 return Ret;
2353 }
2354
2355 /*
2356 * FUNCTION:
2357 * Searches a window's children for a window with the specified
2358 * class and name
2359 * ARGUMENTS:
2360 * hwndParent = The window whose childs are to be searched.
2361 * NULL = desktop
2362 * HWND_MESSAGE = message-only windows
2363 *
2364 * hwndChildAfter = Search starts after this child window.
2365 * NULL = start from beginning
2366 *
2367 * ucClassName = Class name to search for
2368 * Reguired parameter.
2369 *
2370 * ucWindowName = Window name
2371 * ->Buffer == NULL = don't care
2372 *
2373 * RETURNS:
2374 * The HWND of the window if it was found, otherwise NULL
2375 */
2376 /*
2377 * @implemented
2378 */
2379 HWND STDCALL
2380 NtUserFindWindowEx(HWND hwndParent,
2381 HWND hwndChildAfter,
2382 PUNICODE_STRING ucClassName,
2383 PUNICODE_STRING ucWindowName)
2384 {
2385 PWINDOW_OBJECT Parent, ChildAfter;
2386 UNICODE_STRING ClassName, WindowName;
2387 NTSTATUS Status;
2388 HWND Desktop, Ret = NULL;
2389 RTL_ATOM ClassAtom;
2390 DECLARE_RETURN(HWND);
2391
2392 DPRINT("Enter NtUserFindWindowEx\n");
2393 UserEnterShared();
2394
2395 Desktop = IntGetCurrentThreadDesktopWindow();
2396
2397 if(hwndParent == NULL)
2398 hwndParent = Desktop;
2399 /* FIXME
2400 else if(hwndParent == HWND_MESSAGE)
2401 {
2402 hwndParent = IntGetMessageWindow();
2403 }
2404 */
2405
2406 if(!(Parent = IntGetWindowObject(hwndParent)))
2407 {
2408 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2409 RETURN( NULL);
2410 }
2411
2412 ChildAfter = NULL;
2413 if(hwndChildAfter && !(ChildAfter = IntGetWindowObject(hwndChildAfter)))
2414 {
2415 IntReleaseWindowObject(Parent);
2416 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2417 RETURN( NULL);
2418 }
2419
2420 /* copy the window name */
2421 Status = IntSafeCopyUnicodeString(&WindowName, ucWindowName);
2422 if(!NT_SUCCESS(Status))
2423 {
2424 SetLastNtError(Status);
2425 goto Cleanup3;
2426 }
2427
2428 /* safely copy the class name */
2429 Status = MmCopyFromCaller(&ClassName, ucClassName, sizeof(UNICODE_STRING));
2430 if(!NT_SUCCESS(Status))
2431 {
2432 SetLastNtError(Status);
2433 goto Cleanup2;
2434 }
2435 if(ClassName.Length > 0 && ClassName.Buffer)
2436 {
2437 WCHAR *buf;
2438 /* safely copy the class name string (NULL terminated because class-lookup
2439 depends on it... */
2440 buf = ExAllocatePoolWithTag(PagedPool, ClassName.Length + sizeof(WCHAR), TAG_STRING);
2441 if(!buf)
2442 {
2443 SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES);
2444 goto Cleanup2;
2445 }
2446 Status = MmCopyFromCaller(buf, ClassName.Buffer, ClassName.Length);
2447 if(!NT_SUCCESS(Status))
2448 {
2449 ExFreePool(buf);
2450 SetLastNtError(Status);
2451 goto Cleanup2;
2452 }
2453 ClassName.Buffer = buf;
2454 /* make sure the string is null-terminated */
2455 buf += ClassName.Length / sizeof(WCHAR);
2456 *buf = L'\0';
2457 }
2458
2459 /* find the class object */
2460 if(ClassName.Buffer)
2461 {
2462 PWINSTATION_OBJECT WinStaObject;
2463
2464 if (PsGetWin32Thread()->Desktop == NULL)
2465 {
2466 SetLastWin32Error(ERROR_INVALID_HANDLE);
2467 goto Cleanup;
2468 }
2469
2470 WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
2471
2472 Status = RtlLookupAtomInAtomTable(
2473 WinStaObject->AtomTable,
2474 ClassName.Buffer,
2475 &ClassAtom);
2476
2477 if (!NT_SUCCESS(Status))
2478 {
2479 DPRINT1("Failed to lookup class atom!\n");
2480 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
2481 goto Cleanup;
2482 }
2483 }
2484
2485 if(Parent->Self == Desktop)
2486 {
2487 HWND *List, *phWnd;
2488 PWINDOW_OBJECT TopLevelWindow;
2489 BOOLEAN CheckWindowName;
2490 BOOLEAN CheckClassName;
2491 BOOLEAN WindowMatches;
2492 BOOLEAN ClassMatches;
2493
2494 /* windows searches through all top-level windows if the parent is the desktop
2495 window */
2496
2497 if((List = IntWinListChildren(Parent)))
2498 {
2499 phWnd = List;
2500
2501 if(ChildAfter)
2502 {
2503 /* skip handles before and including ChildAfter */
2504 while(*phWnd && (*(phWnd++) != ChildAfter->Self));
2505 }
2506
2507 CheckWindowName = WindowName.Length > 0;
2508 CheckClassName = ClassName.Buffer != NULL;
2509
2510 /* search children */
2511 while(*phWnd)
2512 {
2513 if(!(TopLevelWindow = IntGetWindowObject(*(phWnd++))))
2514 {
2515 continue;
2516 }
2517
2518 /* Do not send WM_GETTEXT messages in the kernel mode version!
2519 The user mode version however calls GetWindowText() which will
2520 send WM_GETTEXT messages to windows belonging to its processes */
2521 WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
2522 &WindowName, &TopLevelWindow->WindowName, FALSE);
2523 ClassMatches = !CheckClassName ||
2524 ClassAtom == TopLevelWindow->Class->Atom;
2525
2526 if (WindowMatches && ClassMatches)
2527 {
2528 Ret = TopLevelWindow->Self;
2529 IntReleaseWindowObject(TopLevelWindow);
2530 break;
2531 }
2532
2533 if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
2534 {
2535 /* window returns the handle of the top-level window, in case it found
2536 the child window */
2537 Ret = TopLevelWindow->Self;
2538 IntReleaseWindowObject(TopLevelWindow);
2539 break;
2540 }
2541
2542 IntReleaseWindowObject(TopLevelWindow);
2543 }
2544 ExFreePool(List);
2545 }
2546 }
2547 else
2548 Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
2549
2550 #if 0
2551 if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
2552 {
2553 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
2554 search the message-only windows. Should this also be done if
2555 Parent is the desktop window??? */
2556 PWINDOW_OBJECT MsgWindows;
2557
2558 if((MsgWindows = IntGetWindowObject(IntGetMessageWindow())))
2559 {
2560 Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
2561 IntReleaseWindowObject(MsgWindows);
2562 }
2563 }
2564 #endif
2565
2566 Cleanup:
2567 if(ClassName.Length > 0 && ClassName.Buffer)
2568 ExFreePool(ClassName.Buffer);
2569
2570 Cleanup2:
2571 RtlFreeUnicodeString(&WindowName);
2572
2573 Cleanup3:
2574 if(ChildAfter)
2575 IntReleaseWindowObject(ChildAfter);
2576 IntReleaseWindowObject(Parent);
2577
2578 RETURN( Ret);
2579
2580 CLEANUP:
2581 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_);
2582 UserLeave();
2583 END_CLEANUP;
2584 }
2585
2586
2587 /*
2588 * @unimplemented
2589 */
2590 DWORD STDCALL
2591 NtUserFlashWindowEx(DWORD Unknown0)
2592 {
2593 UNIMPLEMENTED
2594
2595 return 0;
2596 }
2597
2598
2599 /*
2600 * @implemented
2601 */
2602 HWND FASTCALL UserGetAncestor(HWND hWnd, UINT Type)
2603 {
2604 PWINDOW_OBJECT Wnd, WndAncestor, Parent;
2605 HWND hWndAncestor;
2606
2607 if (hWnd == IntGetDesktopWindow())
2608 {
2609 return NULL;
2610 }
2611
2612 if (!(Wnd = IntGetWindowObject(hWnd)))
2613 {
2614 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2615 return NULL;
2616 }
2617
2618 switch (Type)
2619 {
2620 case GA_PARENT:
2621 {
2622 WndAncestor = IntGetParentObject(Wnd);
2623 break;
2624 }
2625
2626 case GA_ROOT:
2627 {
2628 PWINDOW_OBJECT tmp;
2629 WndAncestor = Wnd;
2630 Parent = NULL;
2631
2632 for(;;)
2633 {
2634 tmp = Parent;
2635 if(!(Parent = IntGetParentObject(WndAncestor)))
2636 {
2637 break;
2638 }
2639 if(IntIsDesktopWindow(Parent))
2640 {
2641 IntReleaseWindowObject(Parent);
2642 break;
2643 }
2644 if(tmp)
2645 IntReleaseWindowObject(tmp);
2646 WndAncestor = Parent;
2647 }
2648 break;
2649 }
2650
2651 case GA_ROOTOWNER:
2652 {
2653 WndAncestor = Wnd;
2654 IntReferenceWindowObject(WndAncestor);
2655 for (;;)
2656 {
2657 PWINDOW_OBJECT Old;
2658 Old = WndAncestor;
2659 Parent = IntGetParent(WndAncestor);
2660 IntReleaseWindowObject(Old);
2661 if (!Parent)
2662 {
2663 break;
2664 }
2665 WndAncestor = Parent;
2666 }
2667 break;
2668 }
2669
2670 default:
2671 {
2672 IntReleaseWindowObject(Wnd);
2673 return NULL;
2674 }
2675 }
2676
2677 hWndAncestor = (WndAncestor ? WndAncestor->Self : NULL);
2678 IntReleaseWindowObject(Wnd);
2679
2680 if(WndAncestor && (WndAncestor != Wnd))
2681 IntReleaseWindowObject(WndAncestor);
2682
2683 return hWndAncestor;
2684 }
2685
2686
2687
2688 /*
2689 * @implemented
2690 */
2691 HWND STDCALL
2692 NtUserGetAncestor(HWND hWnd, UINT Type)
2693 {
2694 DECLARE_RETURN(HWND);
2695
2696 DPRINT("Enter NtUserGetAncestor\n");
2697 UserEnterExclusive();
2698
2699 RETURN(UserGetAncestor(hWnd, Type));
2700
2701 CLEANUP:
2702 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_);
2703 UserLeave();
2704 END_CLEANUP;
2705 }
2706
2707 /*!
2708 * Returns client window rectangle relative to the upper-left corner of client area.
2709 *
2710 * \param hWnd window handle.
2711 * \param Rect pointer to the buffer where the coordinates are returned.
2712 *
2713 */
2714 /*
2715 * @implemented
2716 */
2717 BOOL STDCALL
2718 NtUserGetClientRect(HWND hWnd, LPRECT Rect)
2719 {
2720 PWINDOW_OBJECT WindowObject;
2721 RECT SafeRect;
2722 DECLARE_RETURN(BOOL);
2723
2724 DPRINT("Enter NtUserGetClientRect\n");
2725 UserEnterShared();
2726
2727 if(!(WindowObject = IntGetWindowObject(hWnd)))
2728 {
2729 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2730 RETURN( FALSE);
2731 }
2732
2733 IntGetClientRect(WindowObject, &SafeRect);
2734 IntReleaseWindowObject(WindowObject);
2735
2736 if(!NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
2737 {
2738 RETURN( FALSE);
2739 }
2740 RETURN( TRUE);
2741
2742 CLEANUP:
2743 DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_);
2744 UserLeave();
2745 END_CLEANUP;
2746 }
2747
2748
2749 /*
2750 * @implemented
2751 */
2752 HWND STDCALL
2753 NtUserGetDesktopWindow()
2754 {
2755 DECLARE_RETURN(HWND);
2756
2757 DPRINT("Enter NtUserGetDesktopWindow\n");
2758 UserEnterShared();
2759
2760 RETURN( IntGetDesktopWindow());
2761
2762 CLEANUP:
2763 DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_);
2764 UserLeave();
2765 END_CLEANUP;
2766 }
2767
2768
2769 /*
2770 * @unimplemented
2771 */
2772 DWORD STDCALL
2773 NtUserGetInternalWindowPos(DWORD Unknown0,
2774 DWORD Unknown1,
2775 DWORD Unknown2)
2776 {
2777 UNIMPLEMENTED
2778
2779 return 0;
2780 }
2781
2782
2783 /*
2784 * @unimplemented
2785 */
2786 HWND STDCALL
2787 NtUserGetLastActivePopup(HWND hWnd)
2788 {
2789 /*
2790 * This code can't work, because hWndLastPopup member of WINDOW_OBJECT is
2791 * not changed anywhere.
2792 * -- Filip, 01/nov/2003
2793 */
2794 #if 0
2795 PWINDOW_OBJECT Wnd;
2796 HWND hWndLastPopup;
2797
2798 IntAcquireWinLockShared();
2799
2800 if (!(Wnd = IntGetWindowObject(hWnd)))
2801 {
2802 IntReleaseWinLock();
2803 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2804 return NULL;
2805 }
2806
2807 hWndLastPopup = Wnd->hWndLastPopup;
2808
2809 IntReleaseWinLock();
2810
2811 return hWndLastPopup;
2812 #else
2813 return NULL;
2814 #endif
2815 }
2816
2817 /*
2818 * NtUserGetParent
2819 *
2820 * The NtUserGetParent function retrieves a handle to the specified window's
2821 * parent or owner.
2822 *
2823 * Remarks
2824 * Note that, despite its name, this function can return an owner window
2825 * instead of a parent window.
2826 *
2827 * Status
2828 * @implemented
2829 */
2830
2831 HWND STDCALL
2832 NtUserGetParent(HWND hWnd)
2833 {
2834 PWINDOW_OBJECT Wnd, WndParent;
2835 HWND hWndParent = NULL;
2836 DECLARE_RETURN(HWND);
2837
2838 DPRINT("Enter NtUserGetParent\n");
2839 UserEnterExclusive();
2840
2841 if (!(Wnd = IntGetWindowObject(hWnd)))
2842 {
2843 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2844 RETURN( NULL);
2845 }
2846
2847 WndParent = IntGetParent(Wnd);
2848 if (WndParent)
2849 {
2850 hWndParent = WndParent->Self;
2851 IntReleaseWindowObject(WndParent);
2852 }
2853
2854 IntReleaseWindowObject(Wnd);
2855
2856 RETURN( hWndParent);
2857
2858 CLEANUP:
2859 DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_);
2860 UserLeave();
2861 END_CLEANUP;
2862 }
2863
2864
2865
2866
2867 HWND FASTCALL
2868 UserSetParent(HWND hWndChild, HWND hWndNewParent)
2869 {
2870 PWINDOW_OBJECT Wnd = NULL, WndParent = NULL, WndOldParent;
2871 HWND hWndOldParent = NULL;
2872
2873 if (IntIsBroadcastHwnd(hWndChild) || IntIsBroadcastHwnd(hWndNewParent))
2874 {
2875 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2876 return( NULL);
2877 }
2878
2879 if (hWndChild == IntGetDesktopWindow())
2880 {
2881 SetLastWin32Error(ERROR_ACCESS_DENIED);
2882 return( NULL);
2883 }
2884
2885 if (hWndNewParent)
2886 {
2887 if (!(WndParent = IntGetWindowObject(hWndNewParent)))
2888 {
2889 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2890 return( NULL);
2891 }
2892 }
2893 else
2894 {
2895 if (!(WndParent = IntGetWindowObject(IntGetDesktopWindow())))
2896 {
2897 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2898 return( NULL);
2899 }
2900 }
2901
2902 if (!(Wnd = IntGetWindowObject(hWndChild)))
2903 {
2904 IntReleaseWindowObject(WndParent);
2905 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2906 return( NULL);
2907 }
2908
2909 WndOldParent = IntSetParent(Wnd, WndParent);
2910
2911 if (WndOldParent)
2912 {
2913 hWndOldParent = WndOldParent->Self;
2914 IntReleaseWindowObject(WndOldParent);
2915 }
2916
2917 IntReleaseWindowObject(Wnd);
2918 IntReleaseWindowObject(WndParent);
2919
2920 return( hWndOldParent);
2921 }
2922
2923
2924
2925 /*
2926 * NtUserSetParent
2927 *
2928 * The NtUserSetParent function changes the parent window of the specified
2929 * child window.
2930 *
2931 * Remarks
2932 * The new parent window and the child window must belong to the same
2933 * application. If the window identified by the hWndChild parameter is
2934 * visible, the system performs the appropriate redrawing and repainting.
2935 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
2936 * or WS_POPUP window styles of the window whose parent is being changed.
2937 *
2938 * Status
2939 * @implemented
2940 */
2941
2942 HWND STDCALL
2943 NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
2944 {
2945 DECLARE_RETURN(HWND);
2946
2947 DPRINT("Enter NtUserSetParent\n");
2948 UserEnterExclusive();
2949
2950 RETURN( UserSetParent(hWndChild, hWndNewParent));
2951
2952 CLEANUP:
2953 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_);
2954 UserLeave();
2955 END_CLEANUP;
2956 }
2957
2958
2959
2960
2961 HWND FASTCALL UserGetShellWindow()
2962 {
2963 PWINSTATION_OBJECT WinStaObject;
2964 HWND Ret;
2965
2966 NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
2967 KernelMode,
2968 0,
2969 &WinStaObject);
2970
2971 if (!NT_SUCCESS(Status))
2972 {
2973 SetLastNtError(Status);
2974 return( (HWND)0);
2975 }
2976
2977 Ret = (HWND)WinStaObject->ShellWindow;
2978
2979 ObDereferenceObject(WinStaObject);
2980 return( Ret);
2981 }
2982
2983
2984 /*
2985 * NtUserGetShellWindow
2986 *
2987 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
2988 *
2989 * Status
2990 * @implemented
2991 */
2992
2993 HWND STDCALL
2994 NtUserGetShellWindow()
2995 {
2996 DECLARE_RETURN(HWND);
2997
2998 DPRINT("Enter NtUserGetShellWindow\n");
2999 UserEnterShared();
3000
3001 RETURN( UserGetShellWindow() );
3002
3003 CLEANUP:
3004 DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_);
3005 UserLeave();
3006 END_CLEANUP;
3007 }
3008
3009 /*
3010 * NtUserSetShellWindowEx
3011 *
3012 * This is undocumented function to set global shell window. The global
3013 * shell window has special handling of window position.
3014 *
3015 * Status
3016 * @implemented
3017 */
3018
3019 BOOL STDCALL
3020 NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
3021 {
3022 PWINSTATION_OBJECT WinStaObject;
3023 DECLARE_RETURN(BOOL);
3024
3025 DPRINT("Enter NtUserSetShellWindowEx\n");
3026 UserEnterExclusive();
3027
3028 NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
3029 KernelMode,
3030 0,
3031 &WinStaObject);
3032
3033 if (!NT_SUCCESS(Status))
3034 {
3035 SetLastNtError(Status);
3036 RETURN( FALSE);
3037 }
3038
3039 /*
3040 * Test if we are permitted to change the shell window.
3041 */
3042 if (WinStaObject->ShellWindow)
3043 {
3044 ObDereferenceObject(WinStaObject);
3045 RETURN( FALSE);
3046 }
3047
3048 /*
3049 * Move shell window into background.
3050 */
3051 if (hwndListView && hwndListView != hwndShell)
3052 {
3053 /*
3054 * Disabled for now to get Explorer working.
3055 * -- Filip, 01/nov/2003
3056 */
3057 #if 0
3058 co_WinPosSetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
3059 #endif
3060
3061 if (UserGetWindowLong(hwndListView, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
3062 {
3063 ObDereferenceObject(WinStaObject);
3064 RETURN( FALSE);
3065 }
3066 }
3067
3068 if (UserGetWindowLong(hwndShell, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
3069 {
3070 ObDereferenceObject(WinStaObject);
3071 RETURN( FALSE);
3072 }
3073
3074 co_WinPosSetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
3075
3076 WinStaObject->ShellWindow = hwndShell;
3077 WinStaObject->ShellListView = hwndListView;
3078
3079 ObDereferenceObject(WinStaObject);
3080 RETURN( TRUE);
3081
3082 CLEANUP:
3083 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
3084 UserLeave();
3085 END_CLEANUP;
3086 }
3087
3088 /*
3089 * NtUserGetSystemMenu
3090 *
3091 * The NtUserGetSystemMenu function allows the application to access the
3092 * window menu (also known as the system menu or the control menu) for
3093 * copying and modifying.
3094 *
3095 * Parameters
3096 * hWnd
3097 * Handle to the window that will own a copy of the window menu.
3098 * bRevert
3099 * Specifies the action to be taken. If this parameter is FALSE,
3100 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3101 * currently in use. The copy is initially identical to the window menu
3102 * but it can be modified.
3103 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3104 * to the default state. The previous window menu, if any, is destroyed.
3105 *
3106 * Return Value
3107 * If the bRevert parameter is FALSE, the return value is a handle to a
3108 * copy of the window menu. If the bRevert parameter is TRUE, the return
3109 * value is NULL.
3110 *
3111 * Status
3112 * @implemented
3113 */
3114
3115 HMENU STDCALL
3116 NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
3117 {
3118 HMENU Result = 0;
3119 PWINDOW_OBJECT WindowObject;
3120 PMENU_OBJECT MenuObject;
3121 DECLARE_RETURN(HMENU);
3122
3123 DPRINT("Enter NtUserGetSystemMenu\n");
3124 UserEnterShared();
3125
3126 WindowObject = IntGetWindowObject((HWND)hWnd);
3127 if (WindowObject == NULL)
3128 {
3129 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3130 RETURN( 0);
3131 }
3132
3133 MenuObject = IntGetSystemMenu(WindowObject, bRevert, FALSE);
3134 if (MenuObject)
3135 {
3136 Result = MenuObject->MenuInfo.Self;
3137 IntReleaseMenuObject(MenuObject);
3138 }
3139
3140 IntReleaseWindowObject(WindowObject);
3141 RETURN( Result);
3142
3143 CLEANUP:
3144 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_);
3145 UserLeave();
3146 END_CLEANUP;
3147 }
3148
3149 /*
3150 * NtUserSetSystemMenu
3151 *
3152 * Status
3153 * @implemented
3154 */
3155
3156 BOOL STDCALL
3157 NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
3158 {
3159 BOOL Result = FALSE;
3160 PWINDOW_OBJECT WindowObject;
3161 PMENU_OBJECT MenuObject;
3162 DECLARE_RETURN(BOOL);
3163
3164 DPRINT("Enter NtUserSetSystemMenu\n");
3165 UserEnterExclusive();
3166
3167 WindowObject = IntGetWindowObject(hWnd);
3168 if (!WindowObject)
3169 {
3170 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3171 RETURN( FALSE);
3172 }
3173
3174 if (hMenu)
3175 {
3176 /*
3177 * Assign new menu handle.
3178 */
3179 MenuObject = IntGetMenuObject(hMenu);
3180 if (!MenuObject)
3181 {
3182 IntReleaseWindowObject(WindowObject);
3183 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
3184 RETURN( FALSE);
3185 }
3186
3187 Result = IntSetSystemMenu(WindowObject, MenuObject);
3188
3189 IntReleaseMenuObject(MenuObject);
3190 }
3191
3192 IntReleaseWindowObject(WindowObject);
3193
3194 RETURN( Result);
3195
3196 CLEANUP:
3197 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_);
3198 UserLeave();
3199 END_CLEANUP;
3200 }
3201
3202
3203
3204
3205 HWND FASTCALL
3206 UserGetWindow(HWND hWnd, UINT Relationship)
3207 {
3208 PWINDOW_OBJECT Parent, WindowObject;
3209 HWND hWndResult = NULL;
3210
3211 if (!(WindowObject = IntGetWindowObject(hWnd))) return NULL;
3212
3213 switch (Relationship)
3214 {
3215 case GW_HWNDFIRST:
3216 if((Parent = IntGetParentObject(WindowObject)))
3217 {
3218 if (Parent->FirstChild)
3219 hWndResult = Parent->FirstChild->Self;
3220
3221 IntReleaseWindowObject(Parent);
3222 }
3223 break;
3224
3225 case GW_HWNDLAST:
3226 if((Parent = IntGetParentObject(WindowObject)))
3227 {
3228 if (Parent->LastChild)
3229 hWndResult = Parent->LastChild->Self;
3230
3231 IntReleaseWindowObject(Parent);
3232 }
3233 break;
3234
3235 case GW_HWNDNEXT:
3236 if (WindowObject->NextSibling)
3237 hWndResult = WindowObject->NextSibling->Self;
3238 break;
3239
3240 case GW_HWNDPREV:
3241 if (WindowObject->PrevSibling)
3242 hWndResult = WindowObject->PrevSibling->Self;
3243 break;
3244
3245 case GW_OWNER:
3246 if((Parent = IntGetWindowObject(WindowObject->Owner)))
3247 {
3248 hWndResult = Parent->Self;
3249 IntReleaseWindowObject(Parent);
3250 }
3251 break;
3252 case GW_CHILD:
3253 if (WindowObject->FirstChild)
3254 hWndResult = WindowObject->FirstChild->Self;
3255 break;
3256 }
3257
3258 IntReleaseWindowObject(WindowObject);
3259
3260 return hWndResult;
3261 }
3262
3263
3264
3265 /*
3266 * NtUserGetWindow
3267 *
3268 * The NtUserGetWindow function retrieves a handle to a window that has the
3269 * specified relationship (Z order or owner) to the specified window.
3270 *
3271 * Status
3272 * @implemented
3273 */
3274
3275 HWND STDCALL
3276 NtUserGetWindow(HWND hWnd, UINT Relationship)
3277 {
3278 DECLARE_RETURN(HWND);
3279
3280 DPRINT("Enter NtUserGetWindow\n");
3281 UserEnterShared();
3282
3283 RETURN(UserGetWindow(hWnd, Relationship));
3284
3285 CLEANUP:
3286 DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_);
3287 UserLeave();
3288 END_CLEANUP;
3289 }
3290
3291
3292
3293
3294 /*
3295 * NtUserGetWindowLong
3296 *
3297 * The NtUserGetWindowLong function retrieves information about the specified
3298 * window. The function also retrieves the 32-bit (long) value at the
3299 * specified offset into the extra window memory.
3300 *
3301 * Status
3302 * @implemented
3303 */
3304
3305 LONG FASTCALL
3306 UserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
3307 {
3308 PWINDOW_OBJECT WindowObject, Parent;
3309 LONG Result = 0;
3310
3311 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
3312
3313 WindowObject = IntGetWindowObject(hWnd);
3314 if (WindowObject == NULL)
3315 {
3316 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3317 return 0;
3318 }
3319
3320 /*
3321 * WndProc is only available to the owner process
3322 */
3323 if (GWL_WNDPROC == Index
3324 && WindowObject->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
3325 {
3326 SetLastWin32Error(ERROR_ACCESS_DENIED);
3327 return 0;
3328 }
3329
3330 if ((INT)Index >= 0)
3331 {
3332 if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
3333 {
3334 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3335 return 0;
3336 }
3337 Result = *((LONG *)(WindowObject->ExtraData + Index));
3338 }
3339 else
3340 {
3341 switch (Index)
3342 {
3343 case GWL_EXSTYLE:
3344 Result = WindowObject->ExStyle;
3345 break;
3346
3347 case GWL_STYLE:
3348 Result = WindowObject->Style;
3349 break;
3350
3351 case GWL_WNDPROC:
3352 if (Ansi)
3353 Result = (LONG) WindowObject->WndProcA;
3354 else
3355 Result = (LONG) WindowObject->WndProcW;
3356 break;
3357
3358 case GWL_HINSTANCE:
3359 Result = (LONG) WindowObject->Instance;
3360 break;
3361
3362 case GWL_HWNDPARENT:
3363 Parent = IntGetWindowObject(WindowObject->Parent);
3364 if(Parent)
3365 {
3366 if (Parent && Parent->Self == IntGetDesktopWindow())
3367 Result = (LONG) UserGetWindow(WindowObject->Self, GW_OWNER);
3368 else
3369 Result = (LONG) Parent->Self;
3370 IntReleaseWindowObject(Parent);
3371 }
3372 break;
3373
3374 case GWL_ID:
3375 Result = (LONG) WindowObject->IDMenu;
3376 break;
3377
3378 case GWL_USERDATA:
3379 Result = WindowObject->UserData;
3380 break;
3381
3382 default:
3383 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
3384 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3385 Result = 0;
3386 break;
3387 }
3388 }
3389
3390 IntReleaseWindowObject(WindowObject);
3391
3392 return Result;
3393 }
3394
3395
3396
3397
3398 /*
3399 * NtUserGetWindowLong
3400 *
3401 * The NtUserGetWindowLong function retrieves information about the specified
3402 * window. The function also retrieves the 32-bit (long) value at the
3403 * specified offset into the extra window memory.
3404 *
3405 * Status
3406 * @implemented
3407 */
3408
3409 LONG STDCALL
3410 NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
3411 {
3412 DECLARE_RETURN(LONG);
3413
3414 DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
3415 UserEnterExclusive();
3416
3417 RETURN(UserGetWindowLong(hWnd, Index, Ansi));
3418
3419 CLEANUP:
3420 DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_);
3421 UserLeave();
3422 END_CLEANUP;
3423 }
3424
3425
3426
3427
3428 LONG FASTCALL
3429 UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
3430 {
3431 PWINDOW_OBJECT WindowObject, Parent;
3432 PWINSTATION_OBJECT WindowStation;
3433 LONG OldValue;
3434 STYLESTRUCT Style;
3435
3436 if (hWnd == IntGetDesktopWindow())
3437 {
3438 SetLastWin32Error(STATUS_ACCESS_DENIED);
3439 return( 0);
3440 }
3441
3442 WindowObject = IntGetWindowObject(hWnd);
3443 if (WindowObject == NULL)
3444 {
3445 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3446 return( 0);
3447 }
3448
3449 if ((INT)Index >= 0)
3450 {
3451 if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
3452 {
3453 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3454 IntReleaseWindowObject(WindowObject);
3455 return( 0);
3456 }
3457 OldValue = *((LONG *)(WindowObject->ExtraData + Index));
3458 *((LONG *)(WindowObject->ExtraData + Index)) = NewValue;
3459 }
3460 else
3461 {
3462 switch (Index)
3463 {
3464 case GWL_EXSTYLE:
3465 OldValue = (LONG) WindowObject->ExStyle;
3466 Style.styleOld = OldValue;
3467 Style.styleNew = NewValue;
3468
3469 /*
3470 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3471 */
3472 WindowStation = WindowObject->OwnerThread->Tcb.Win32Thread->Desktop->WindowStation;
3473 if(WindowStation)
3474 {
3475 if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3476 Style.styleNew &= ~WS_EX_TOPMOST;
3477 }
3478
3479 co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3480 WindowObject->ExStyle = (DWORD)Style.styleNew;
3481 co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3482 break;
3483
3484 case GWL_STYLE:
3485 OldValue = (LONG) WindowObject->Style;
3486 Style.styleOld = OldValue;
3487 Style.styleNew = NewValue;
3488 co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3489 WindowObject->Style = (DWORD)Style.styleNew;
3490 co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3491 break;
3492
3493 case GWL_WNDPROC:
3494 /* FIXME: should check if window belongs to current process */
3495 if (Ansi)
3496 {
3497 OldValue = (LONG) WindowObject->WndProcA;
3498 WindowObject->WndProcA = (WNDPROC) NewValue;
3499 WindowObject->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE);
3500 WindowObject->Unicode = FALSE;
3501 }
3502 else
3503 {
3504 OldValue = (LONG) WindowObject->WndProcW;
3505 WindowObject->WndProcW = (WNDPROC) NewValue;
3506 WindowObject->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE);
3507 WindowObject->Unicode = TRUE;
3508 }
3509 break;
3510
3511 case GWL_HINSTANCE:
3512 OldValue = (LONG) WindowObject->Instance;
3513 WindowObject->Instance = (HINSTANCE) NewValue;
3514 break;
3515
3516 case GWL_HWNDPARENT:
3517 Parent = IntGetParentObject(WindowObject);
3518 if (Parent && (Parent->Self == IntGetDesktopWindow()))
3519 OldValue = (LONG) IntSetOwner(WindowObject->Self, (HWND) NewValue);
3520 else
3521 OldValue = (LONG) UserSetParent(WindowObject->Self, (HWND) NewValue);
3522 if(Parent)
3523 IntReleaseWindowObject(Parent);
3524 break;
3525
3526 case GWL_ID:
3527 OldValue = (LONG) WindowObject->IDMenu;
3528 WindowObject->IDMenu = (UINT) NewValue;
3529 break;
3530
3531 case GWL_USERDATA:
3532 OldValue = WindowObject->UserData;
3533 WindowObject->UserData = NewValue;
3534 break;
3535
3536 default:
3537 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
3538 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3539 OldValue = 0;
3540 break;
3541 }
3542 }
3543
3544 IntReleaseWindowObject(WindowObject);
3545
3546 return( OldValue);
3547 }
3548
3549
3550
3551 /*
3552 * NtUserSetWindowLong
3553 *
3554 * The NtUserSetWindowLong function changes an attribute of the specified
3555 * window. The function also sets the 32-bit (long) value at the specified
3556 * offset into the extra window memory.
3557 *
3558 * Status
3559 * @implemented
3560 */
3561
3562 LONG STDCALL
3563 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
3564 {
3565 DECLARE_RETURN(LONG);
3566
3567 DPRINT("Enter NtUserSetWindowLong\n");
3568 UserEnterExclusive();
3569
3570 RETURN( UserSetWindowLong(hWnd, Index, NewValue, Ansi));
3571
3572 CLEANUP:
3573 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_);
3574 UserLeave();
3575 END_CLEANUP;
3576 }
3577
3578 /*
3579 * NtUserSetWindowWord
3580 *
3581 * Legacy function similar to NtUserSetWindowLong.
3582 *
3583 * Status
3584 * @implemented
3585 */
3586
3587 WORD STDCALL
3588 NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
3589 {
3590 PWINDOW_OBJECT WindowObject;
3591 WORD OldValue;
3592 DECLARE_RETURN(WORD);
3593
3594 DPRINT("Enter NtUserSetWindowWord\n");
3595 UserEnterExclusive();
3596
3597 switch (Index)
3598 {
3599 case GWL_ID:
3600 case GWL_HINSTANCE:
3601 case GWL_HWNDPARENT:
3602 RETURN( UserSetWindowLong(hWnd, Index, (UINT)NewValue, TRUE));
3603 default:
3604 if (Index < 0)
3605 {
3606 SetLastWin32Error(ERROR_INVALID_INDEX);
3607 RETURN( 0);
3608 }
3609 }
3610
3611 WindowObject = IntGetWindowObject(hWnd);
3612 if (WindowObject == NULL)
3613 {
3614 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3615 RETURN( 0);
3616 }
3617
3618 if (Index > WindowObject->ExtraDataSize - sizeof(WORD))
3619 {
3620 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3621 IntReleaseWindowObject(WindowObject);
3622 RETURN( 0);
3623 }
3624
3625 OldValue = *((WORD *)(WindowObject->ExtraData + Index));
3626 *((WORD *)(WindowObject->ExtraData + Index)) = NewValue;
3627
3628 IntReleaseWindowObject(WindowObject);
3629
3630 RETURN( OldValue);
3631
3632 CLEANUP:
3633 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_);
3634 UserLeave();
3635 END_CLEANUP;
3636 }
3637
3638 /*
3639 * @implemented
3640 */
3641 BOOL STDCALL
3642 NtUserGetWindowPlacement(HWND hWnd,
3643 WINDOWPLACEMENT *lpwndpl)
3644 {
3645 PWINDOW_OBJECT WindowObject;
3646 PINTERNALPOS InternalPos;
3647 POINT Size;
3648 WINDOWPLACEMENT Safepl;
3649 NTSTATUS Status;
3650 DECLARE_RETURN(BOOL);
3651
3652 DPRINT("Enter NtUserGetWindowPlacement\n");
3653 UserEnterShared();
3654
3655 WindowObject = IntGetWindowObject(hWnd);
3656 if (WindowObject == NULL)
3657 {
3658 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3659 RETURN( FALSE);
3660 }
3661
3662 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3663 if(!NT_SUCCESS(Status))
3664 {
3665 SetLastNtError(Status);
3666 IntReleaseWindowObject(WindowObject);
3667 RETURN( FALSE);
3668 }
3669 if(Safepl.length != sizeof(WINDOWPLACEMENT))
3670 {
3671 IntReleaseWindowObject(WindowObject);
3672 RETURN( FALSE);
3673 }
3674
3675 Safepl.flags = 0;
3676 Safepl.showCmd = ((WindowObject->Flags & WINDOWOBJECT_RESTOREMAX) ? SW_MAXIMIZE : SW_SHOWNORMAL);
3677
3678 Size.x = WindowObject->WindowRect.left;
3679 Size.y = WindowObject->WindowRect.top;
3680 InternalPos = WinPosInitInternalPos(WindowObject, &Size,
3681 &WindowObject->WindowRect);
3682 if (InternalPos)
3683 {
3684 Safepl.rcNormalPosition = InternalPos->NormalRect;
3685 Safepl.ptMinPosition = InternalPos->IconPos;
3686 Safepl.ptMaxPosition = InternalPos->MaxPos;
3687 }
3688 else
3689 {
3690 IntReleaseWindowObject(WindowObject);
3691 RETURN( FALSE);
3692 }
3693
3694 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
3695 if(!NT_SUCCESS(Status))
3696 {
3697 SetLastNtError(Status);
3698 IntReleaseWindowObject(WindowObject);
3699 RETURN( FALSE);
3700 }
3701
3702 IntReleaseWindowObject(WindowObject);
3703 RETURN( TRUE);
3704
3705 CLEANUP:
3706 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
3707 UserLeave();
3708 END_CLEANUP;
3709 }
3710
3711
3712 /*!
3713 * Return the dimension of the window in the screen coordinates.
3714 * \param hWnd window handle.
3715 * \param Rect pointer to the buffer where the coordinates are returned.
3716 */
3717 /*
3718 * @implemented
3719 */
3720 BOOL STDCALL
3721 NtUserGetWindowRect(HWND hWnd, LPRECT Rect)
3722 {
3723 PWINDOW_OBJECT Wnd;
3724 NTSTATUS Status;
3725 DECLARE_RETURN(BOOL);
3726
3727 DPRINT("Enter NtUserGetWindowRect\n");
3728 UserEnterShared();
3729
3730 if (!(Wnd = IntGetWindowObject(hWnd)))
3731 {
3732 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3733 RETURN(FALSE);
3734 }
3735 Status = MmCopyToCaller(Rect, &Wnd->WindowRect, sizeof(RECT));
3736 if (!NT_SUCCESS(Status))
3737 {
3738 IntReleaseWindowObject(Wnd);
3739 SetLastNtError(Status);
3740 RETURN( FALSE);
3741 }
3742
3743 IntReleaseWindowObject(Wnd);
3744 RETURN( TRUE);
3745
3746 CLEANUP:
3747 DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_);
3748 UserLeave();
3749 END_CLEANUP;
3750 }
3751
3752
3753 /*
3754 * @implemented
3755 */
3756 DWORD STDCALL
3757 NtUserGetWindowThreadProcessId(HWND hWnd, LPDWORD UnsafePid)
3758 {
3759 PWINDOW_OBJECT Wnd;
3760 DWORD tid, pid;
3761 DECLARE_RETURN(DWORD);
3762
3763 DPRINT("Enter NtUserGetWindowThreadProcessId\n");
3764 UserEnterShared();
3765
3766 if (!(Wnd = IntGetWindowObject(hWnd)))
3767 {
3768 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3769 RETURN( 0);
3770 }
3771
3772 tid = (DWORD)IntGetWndThreadId(Wnd);
3773 pid = (DWORD)IntGetWndProcessId(Wnd);
3774
3775 if (UnsafePid) MmCopyToCaller(UnsafePid, &pid, sizeof(DWORD));
3776
3777 RETURN( tid);
3778
3779 CLEANUP:
3780 DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_);
3781 UserLeave();
3782 END_CLEANUP;
3783 }
3784
3785
3786 /*
3787 * @unimplemented
3788 */
3789 DWORD STDCALL
3790 NtUserLockWindowUpdate(DWORD Unknown0)
3791 {
3792 UNIMPLEMENTED
3793
3794 return 0;
3795 }
3796
3797
3798 /*
3799 * @implemented
3800 */
3801 BOOL STDCALL
3802 NtUserMoveWindow(
3803 HWND hWnd,
3804 int X,
3805 int Y,
3806 int nWidth,
3807 int nHeight,
3808 BOOL bRepaint)
3809 {
3810 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
3811 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
3812 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
3813 }
3814
3815 /*
3816 QueryWindow based on KJK::Hyperion and James Tabor.
3817
3818 0 = QWUniqueProcessId
3819 1 = QWUniqueThreadId
3820 4 = QWIsHung Implements IsHungAppWindow found
3821 by KJK::Hyperion.
3822
3823 9 = QWKillWindow When I called this with hWnd ==
3824 DesktopWindow, it shutdown the system
3825 and rebooted.
3826 */
3827 /*
3828 * @implemented
3829 */
3830 DWORD STDCALL
3831 NtUserQueryWindow(HWND hWnd, DWORD Index)
3832 {
3833 PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
3834 DWORD Result;
3835 DECLARE_RETURN(UINT);
3836
3837 DPRINT("Enter NtUserQueryWindow\n");
3838 UserEnterShared();
3839
3840 if (Window == NULL)
3841 {
3842 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3843 RETURN( 0);
3844 }
3845
3846 switch(Index)
3847 {
3848 case QUERY_WINDOW_UNIQUE_PROCESS_ID:
3849 Result = (DWORD)IntGetWndProcessId(Window);
3850 break;
3851
3852 case QUERY_WINDOW_UNIQUE_THREAD_ID:
3853 Result = (DWORD)IntGetWndThreadId(Window);
3854 break;
3855
3856 case QUERY_WINDOW_ISHUNG:
3857 Result = (DWORD)MsqIsHung(Window->MessageQueue);
3858 break;
3859
3860 default:
3861 Result = (DWORD)NULL;
3862 break;
3863 }
3864
3865 IntReleaseWindowObject(Window);
3866
3867 RETURN( Result);
3868
3869
3870 CLEANUP:
3871 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_);
3872 UserLeave();
3873 END_CLEANUP;
3874 }
3875
3876
3877 /*
3878 * @unimplemented
3879 */
3880 DWORD STDCALL
3881 NtUserRealChildWindowFromPoint(DWORD Unknown0,
3882 DWORD Unknown1,
3883 DWORD Unknown2)
3884 {
3885 UNIMPLEMENTED
3886
3887 return 0;
3888 }
3889
3890
3891 /*
3892 * @implemented
3893 */
3894 UINT STDCALL
3895 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
3896 {
3897 UNICODE_STRING SafeMessageName;
3898 NTSTATUS Status;
3899 UINT Ret;
3900 DECLARE_RETURN(UINT);
3901
3902 DPRINT("Enter NtUserRegisterWindowMessage\n");
3903 UserEnterExclusive();
3904
3905 if(MessageNameUnsafe == NULL)
3906 {
3907 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3908 RETURN( 0);
3909 }
3910
3911 Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
3912 if(!NT_SUCCESS(Status))
3913 {
3914 SetLastNtError(Status);
3915 RETURN( 0);
3916 }
3917
3918 Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
3919
3920 RtlFreeUnicodeString(&SafeMessageName);
3921 RETURN( Ret);
3922
3923 CLEANUP:
3924 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_);
3925 UserLeave();
3926 END_CLEANUP;
3927 }
3928
3929
3930 /*
3931 * @unimplemented
3932 */
3933 DWORD STDCALL
3934 NtUserSetImeOwnerWindow(DWORD Unknown0,
3935 DWORD Unknown1)
3936 {
3937 UNIMPLEMENTED
3938
3939 return 0;
3940 }
3941
3942
3943 /*
3944 * @unimplemented
3945 */
3946 DWORD STDCALL
3947 NtUserSetInternalWindowPos(DWORD Unknown0,
3948 DWORD Unknown1,
3949 DWORD Unknown2,
3950 DWORD Unknown3)
3951 {
3952 UNIMPLEMENTED
3953
3954 return 0;
3955
3956 }
3957
3958
3959 /*
3960 * @unimplemented
3961 */
3962 DWORD STDCALL
3963 NtUserSetLayeredWindowAttributes(DWORD Unknown0,
3964 DWORD Unknown1,
3965 DWORD Unknown2,
3966 DWORD Unknown3)
3967 {
3968 UNIMPLEMENTED
3969
3970 return 0;
3971 }
3972
3973
3974 /*
3975 * @unimplemented
3976 */
3977 DWORD STDCALL
3978 NtUserSetLogonNotifyWindow(DWORD Unknown0)
3979 {
3980 UNIMPLEMENTED
3981
3982 return 0;
3983 }
3984
3985
3986 /*
3987 * @implemented
3988 */
3989 BOOL STDCALL
3990 NtUserSetMenu(
3991 HWND Wnd,
3992 HMENU Menu,
3993 BOOL Repaint)
3994 {
3995 PWINDOW_OBJECT WindowObject;
3996 BOOL Changed;
3997 DECLARE_RETURN(BOOL);
3998
3999 DPRINT("Enter NtUserSetMenu\n");
4000 UserEnterExclusive();
4001
4002 WindowObject = IntGetWindowObject((HWND) Wnd);
4003 if (NULL == WindowObject)
4004 {
4005 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4006 RETURN( FALSE);
4007 }
4008
4009 if (! IntSetMenu(WindowObject, Menu, &Changed))
4010 {
4011 IntReleaseWindowObject(WindowObject);
4012 RETURN( FALSE);
4013 }
4014
4015 IntReleaseWindowObject(WindowObject);
4016
4017 if (Changed && Repaint)
4018 {
4019 co_WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4020 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
4021 }
4022
4023 RETURN( TRUE);
4024
4025 CLEANUP:
4026 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_);
4027 UserLeave();
4028 END_CLEANUP;
4029 }
4030
4031
4032 /*
4033 * @unimplemented
4034 */
4035 DWORD STDCALL
4036 NtUserSetWindowFNID(DWORD Unknown0,
4037 DWORD Unknown1)
4038 {
4039 UNIMPLEMENTED
4040
4041 return 0;
4042 }
4043
4044
4045
4046 /*
4047 * @implemented
4048 */
4049 BOOL STDCALL
4050 NtUserSetWindowPlacement(HWND hWnd,
4051 WINDOWPLACEMENT *lpwndpl)
4052 {
4053 PWINDOW_OBJECT WindowObject;
4054 WINDOWPLACEMENT Safepl;
4055 NTSTATUS Status;
4056 DECLARE_RETURN(BOOL);
4057
4058 DPRINT("Enter NtUserSetWindowPlacement\n");
4059 UserEnterExclusive();
4060
4061 WindowObject = IntGetWindowObject(hWnd);
4062 if (WindowObject == NULL)
4063 {
4064 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4065 RETURN( FALSE);
4066 }
4067 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
4068 if(!NT_SUCCESS(Status))
4069 {
4070 SetLastNtError(Status);
4071 IntReleaseWindowObject(WindowObject);
4072 RETURN( FALSE);
4073 }
4074 if(Safepl.length != sizeof(WINDOWPLACEMENT))
4075 {
4076 IntReleaseWindowObject(WindowObject);
4077 RETURN( FALSE);
4078 }
4079
4080 if ((WindowObject->Style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
4081 {
4082 co_WinPosSetWindowPos(WindowObject->Self, NULL,
4083 Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
4084 Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
4085 Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
4086 SWP_NOZORDER | SWP_NOACTIVATE);
4087 }
4088
4089 /* FIXME - change window status */
4090 co_WinPosShowWindow(WindowObject->Self, Safepl.showCmd);
4091
4092 if (WindowObject->InternalPos == NULL)
4093 WindowObject->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
4094 WindowObject->InternalPos->NormalRect = Safepl.rcNormalPosition;
4095 WindowObject->InternalPos->IconPos = Safepl.ptMinPosition;
4096 WindowObject->InternalPos->MaxPos = Safepl.ptMaxPosition;
4097
4098 IntReleaseWindowObject(WindowObject);
4099 RETURN( TRUE);
4100
4101 CLEANUP:
4102 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
4103 UserLeave();
4104 END_CLEANUP;
4105 }
4106
4107
4108 /*
4109 * @implemented
4110 */
4111 BOOL STDCALL
4112 NtUserSetWindowPos(
4113 HWND hWnd,
4114 HWND hWndInsertAfter,
4115 int X,
4116 int Y,
4117 int cx,
4118 int cy,
4119 UINT uFlags)
4120 {
4121 DECLARE_RETURN(BOOL);
4122
4123 DPRINT("Enter NtUserSetWindowPos\n");
4124 UserEnterExclusive();
4125
4126 RETURN( co_WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags));
4127
4128 CLEANUP:
4129 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
4130 UserLeave();
4131 END_CLEANUP;
4132 }
4133
4134
4135 INT FASTCALL
4136 IntGetWindowRgn(HWND hWnd, HRGN hRgn)
4137 {
4138 INT Ret;
4139 PWINDOW_OBJECT WindowObject;
4140 HRGN VisRgn;
4141 ROSRGNDATA *pRgn;
4142
4143 if(!(WindowObject = IntGetWindowObject(hWnd)))
4144 {
4145 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4146 return ERROR;
4147 }
4148 if(!hRgn)
4149 {
4150 IntReleaseWindowObject(WindowObject);
4151 return ERROR;
4152 }
4153
4154 /* Create a new window region using the window rectangle */
4155 VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
4156 NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
4157 /* if there's a region assigned to the window, combine them both */
4158 if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
4159 NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
4160 /* Copy the region into hRgn */
4161 NtGdiCombineRgn(hRgn, VisRgn, NULL, RGN_COPY);
4162
4163 if((pRgn = RGNDATA_LockRgn(hRgn)))
4164 {
4165 Ret = pRgn->rdh.iType;
4166 RGNDATA_UnlockRgn(pRgn);
4167 }
4168 else
4169 Ret = ERROR;
4170
4171 NtGdiDeleteObject(VisRgn);
4172
4173 IntReleaseWindowObject(WindowObject);
4174 return Ret;
4175 }
4176
4177 INT FASTCALL
4178 IntGetWindowRgnBox(HWND hWnd, RECT *Rect)
4179 {
4180 INT Ret;
4181 PWINDOW_OBJECT WindowObject;
4182 HRGN VisRgn;
4183 ROSRGNDATA *pRgn;
4184
4185 if(!(WindowObject = IntGetWindowObject(hWnd)))
4186 {
4187 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4188 return ERROR;
4189 }
4190 if(!Rect)
4191 {
4192 IntReleaseWindowObject(WindowObject);
4193 return ERROR;
4194 }
4195
4196 /* Create a new window region using the window rectangle */
4197 VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
4198 NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
4199 /* if there's a region assigned to the window, combine them both */
4200 if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
4201 NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
4202
4203 if((pRgn = RGNDATA_LockRgn(VisRgn)))
4204 {
4205 Ret = pRgn->rdh.iType;
4206 *Rect = pRgn->rdh.rcBound;
4207 RGNDATA_UnlockRgn(pRgn);
4208 }
4209 else
4210 Ret = ERROR;
4211
4212 NtGdiDeleteObject(VisRgn);
4213
4214 IntReleaseWindowObject(WindowObject);
4215 return Ret;
4216 }
4217
4218
4219 /*
4220 * @implemented
4221 */
4222 INT STDCALL
4223 NtUserSetWindowRgn(
4224 HWND hWnd,
4225 HRGN hRgn,
4226 BOOL bRedraw)
4227 {
4228 PWINDOW_OBJECT WindowObject;
4229 DECLARE_RETURN(INT);
4230
4231 DPRINT("Enter NtUserSetWindowRgn\n");
4232 UserEnterExclusive();
4233
4234 WindowObject = IntGetWindowObject(hWnd);
4235 if (WindowObject == NULL)
4236 {
4237 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4238 RETURN( 0);
4239 }
4240
4241 /* FIXME - Verify if hRgn is a valid handle!!!!
4242 Propably make this operation thread-safe, but maybe it's not necessary */
4243
4244 if(WindowObject->WindowRegion)
4245 {
4246 /* Delete no longer needed region handle */
4247 NtGdiDeleteObject(WindowObject->WindowRegion);
4248 }
4249 WindowObject->WindowRegion = hRgn;
4250
4251 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4252
4253 if(bRedraw)
4254 {
4255 co_UserRedrawWindow(WindowObject, NULL, NULL, RDW_INVALIDATE);
4256 }
4257
4258 IntReleaseWindowObject(WindowObject);
4259 RETURN( (INT)hRgn);
4260
4261 CLEANUP:
4262 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_);
4263 UserLeave();
4264 END_CLEANUP;
4265 }
4266
4267
4268 /*
4269 * @implemented
4270 */
4271 BOOL STDCALL
4272 NtUserShowWindow(HWND hWnd,
4273 LONG nCmdShow)
4274 {
4275 DECLARE_RETURN(BOOL);
4276
4277 DPRINT("Enter NtUserShowWindow\n");
4278 UserEnterExclusive();
4279
4280 RETURN( co_WinPosShowWindow(hWnd, nCmdShow));
4281
4282 CLEANUP:
4283 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_);
4284 UserLeave();
4285 END_CLEANUP;
4286 }
4287
4288
4289 /*
4290 * @unimplemented
4291 */
4292 DWORD STDCALL
4293 NtUserShowWindowAsync(DWORD Unknown0,
4294 DWORD Unknown1)
4295 {
4296 UNIMPLEMENTED
4297
4298 return 0;
4299 }
4300
4301
4302 /*
4303 * @unimplemented
4304 */
4305 DWORD STDCALL
4306 NtUserUpdateLayeredWindow(DWORD Unknown0,
4307 DWORD Unknown1,
4308 DWORD Unknown2,
4309 DWORD Unknown3,
4310 DWORD Unknown4,
4311 DWORD Unknown5,
4312 DWORD Unknown6,
4313 DWORD Unknown7,
4314 DWORD Unknown8)
4315 {
4316 UNIMPLEMENTED
4317
4318 return 0;
4319 }
4320
4321
4322 /*
4323 * @implemented
4324 */
4325 VOID STDCALL
4326 NtUserValidateRect(HWND hWnd, const RECT* Rect)
4327 {
4328 return (VOID)NtUserRedrawWindow(hWnd, Rect, 0, RDW_VALIDATE | RDW_NOCHILDREN);
4329 }
4330
4331
4332 /*
4333 * @implemented
4334 */
4335 HWND STDCALL
4336 NtUserWindowFromPoint(LONG X, LONG Y)
4337 {
4338 POINT pt;
4339 HWND Ret;
4340 PWINDOW_OBJECT DesktopWindow, Window = NULL;
4341 DECLARE_RETURN(HWND);
4342
4343 DPRINT("Enter NtUserWindowFromPoint\n");
4344 UserEnterExclusive();
4345
4346 if ((DesktopWindow = IntGetWindowObject(IntGetDesktopWindow())))
4347 {
4348 USHORT Hit;
4349
4350 pt.x = X;
4351 pt.y = Y;
4352
4353 Hit = co_WinPosWindowFromPoint(DesktopWindow, PsGetWin32Thread()->MessageQueue, &pt, &Window);
4354
4355 if(Window)
4356 {
4357 Ret = Window->Self;
4358 IntReleaseWindowObject(Window);
4359 IntReleaseWindowObject(DesktopWindow);
4360 RETURN( Ret);
4361 }
4362
4363 IntReleaseWindowObject(DesktopWindow);
4364 }
4365
4366 RETURN( NULL);
4367
4368 CLEANUP:
4369 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
4370 UserLeave();
4371 END_CLEANUP;
4372
4373 }
4374
4375
4376 /*
4377 * NtUserDefSetText
4378 *
4379 * Undocumented function that is called from DefWindowProc to set
4380 * window text.
4381 *
4382 * Status
4383 * @implemented
4384 */
4385
4386 BOOL STDCALL
4387 NtUserDefSetText(HWND WindowHandle, PUNICODE_STRING WindowText)
4388 {
4389 PWINDOW_OBJECT WindowObject, Parent, Owner;
4390 UNICODE_STRING SafeText;
4391 NTSTATUS Status;
4392 DECLARE_RETURN(INT);
4393
4394 DPRINT("Enter NtUserDefSetText\n");
4395 UserEnterExclusive();
4396
4397 WindowObject = IntGetWindowObject(WindowHandle);
4398 if(!WindowObject)
4399 {
4400 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4401 RETURN( FALSE);
4402 }
4403
4404 if(WindowText)
4405 {
4406 Status = IntSafeCopyUnicodeString(&SafeText, WindowText);
4407 if(!NT_SUCCESS(Status))
4408 {
4409 SetLastNtError(Status);
4410 IntReleaseWindowObject(WindowObject);
4411 RETURN( FALSE);
4412 }
4413 }
4414 else
4415 {
4416 RtlInitUnicodeString(&SafeText, NULL);
4417 }
4418
4419 /* FIXME - do this thread-safe! otherwise one could crash here! */
4420 RtlFreeUnicodeString(&WindowObject->WindowName);
4421
4422 WindowObject->WindowName = SafeText;
4423
4424 /* Send shell notifications */
4425
4426 Owner = IntGetOwner(WindowObject);
4427 Parent = IntGetParent(WindowObject);
4428
4429 if ((!Owner) && (!Parent))
4430 {
4431 co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) WindowHandle);
4432 }
4433
4434 if (Owner)
4435 {
4436 IntReleaseWindowObject(Owner);
4437 }
4438
4439 if (Parent)
4440 {
4441 IntReleaseWindowObject(Parent);
4442 }
4443
4444 IntReleaseWindowObject(WindowObject);
4445 RETURN( TRUE);
4446
4447 CLEANUP:
4448 DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_);
4449 UserLeave();
4450 END_CLEANUP;
4451 }
4452
4453 /*
4454 * NtUserInternalGetWindowText
4455 *
4456 * Status
4457 * @implemented
4458 */
4459
4460 INT STDCALL
4461 NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
4462 {
4463 PWINDOW_OBJECT WindowObject;
4464 NTSTATUS Status;
4465 INT Result;
4466 DECLARE_RETURN(INT);
4467
4468 DPRINT("Enter NtUserInternalGetWindowText\n");
4469 UserEnterShared();
4470
4471 if(lpString && (nMaxCount <= 1))
4472 {
4473 SetLastWin32Error(ERROR_INVALID_PARAMETER);
4474 RETURN( 0);
4475 }
4476
4477 WindowObject = IntGetWindowObject(hWnd);
4478 if(!WindowObject)
4479 {
4480 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4481 RETURN( 0);
4482 }
4483
4484 /* FIXME - do this thread-safe! otherwise one could crash here! */
4485 Result = WindowObject->WindowName.Length / sizeof(WCHAR);
4486 if(lpString)
4487 {
4488 const WCHAR Terminator = L'\0';
4489 INT Copy;
4490 WCHAR *Buffer = (WCHAR*)lpString;
4491
4492 Copy = min(nMaxCount - 1, Result);
4493 if(Copy > 0)
4494 {
4495 Status = MmCopyToCaller(Buffer, WindowObject->WindowName.Buffer, Copy * sizeof(WCHAR));
4496 if(!NT_SUCCESS(Status))
4497 {
4498 SetLastNtError(Status);
4499 IntReleaseWindowObject(WindowObject);
4500 RETURN( 0);
4501 }
4502 Buffer += Copy;
4503 }
4504
4505 Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
4506 if(!NT_SUCCESS(Status))
4507 {
4508 SetLastNtError(Status);
4509 IntReleaseWindowObject(WindowObject);
4510 RETURN( 0);
4511 }
4512
4513 Result = Copy;
4514 }
4515
4516 IntReleaseWindowObject(WindowObject);
4517 RETURN( Result);
4518
4519 CLEANUP:
4520 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
4521 UserLeave();
4522 END_CLEANUP;
4523 }
4524
4525 DWORD STDCALL
4526 NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data)
4527 {
4528 DECLARE_RETURN(DWORD);
4529
4530 DPRINT("Enter NtUserDereferenceWndProcHandle\n");
4531 UserEnterShared();
4532
4533 WndProcHandle Entry;
4534 if (((DWORD)wpHandle & 0xFFFF0000) == 0xFFFF0000)
4535 {
4536 Entry = WndProcHandlesArray[(DWORD)wpHandle & 0x0000FFFF];
4537 Data->WindowProc = Entry.WindowProc;
4538 Data->IsUnicode = Entry.IsUnicode;
4539 Data->ProcessID = Entry.ProcessID;
4540 RETURN( TRUE);
4541 } else {
4542 RETURN( FALSE);
4543 }
4544 RETURN( FALSE);
4545
4546 CLEANUP:
4547 DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_);
4548 UserLeave();
4549 END_CLEANUP;
4550 }
4551
4552 DWORD
4553 IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode)
4554 {
4555 WORD i;
4556 WORD FreeSpot = 0;
4557 BOOL found;
4558 WndProcHandle *OldArray;
4559 WORD OldArraySize;
4560 found = FALSE;
4561 for (i = 0;i < WndProcHandlesArraySize;i++)
4562 {
4563 if (WndProcHandlesArray[i].WindowProc == NULL)
4564 {
4565 FreeSpot = i;
4566 found = TRUE;
4567 }
4568 }
4569 if (!found)
4570 {
4571 OldArray = WndProcHandlesArray;
4572 OldArraySize = WndProcHandlesArraySize;
4573 WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,(OldArraySize + WPH_SIZE) * sizeof(WndProcHandle), TAG_WINPROCLST);
4574 WndProcHandlesArraySize = OldArraySize + WPH_SIZE;
4575 RtlCopyMemory(WndProcHandlesArray,OldArray,OldArraySize * sizeof(WndProcHandle));
4576 ExFreePool(OldArray);
4577 FreeSpot = OldArraySize + 1;
4578 }
4579 WndProcHandlesArray[FreeSpot].WindowProc = WindowProc;
4580 WndProcHandlesArray[FreeSpot].IsUnicode = IsUnicode;
4581 WndProcHandlesArray[FreeSpot].ProcessID = PsGetCurrentProcessId();
4582 return FreeSpot + 0xFFFF0000;
4583 }
4584
4585 DWORD
4586 IntRemoveWndProcHandle(WNDPROC Handle)
4587 {
4588 WORD position;
4589 position = (DWORD)Handle & 0x0000FFFF;
4590 if (position > WndProcHandlesArraySize)
4591 {
4592 return FALSE;
4593 }
4594 WndProcHandlesArray[position].WindowProc = NULL;
4595 WndProcHandlesArray[position].IsUnicode = FALSE;
4596 WndProcHandlesArray[position].ProcessID = NULL;
4597 return TRUE;
4598 }
4599
4600 DWORD
4601 IntRemoveProcessWndProcHandles(HANDLE ProcessID)
4602 {
4603 WORD i;
4604 for (i = 0;i < WndProcHandlesArraySize;i++)
4605 {
4606 if (WndProcHandlesArray[i].ProcessID == ProcessID)
4607 {
4608 WndProcHandlesArray[i].WindowProc = NULL;
4609 WndProcHandlesArray[i].IsUnicode = FALSE;
4610 WndProcHandlesArray[i].ProcessID = NULL;
4611 }
4612 }
4613 return TRUE;
4614 }
4615
4616 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
4617
4618 BOOL
4619 FASTCALL
4620 IntShowOwnedPopups( HWND owner, BOOL fShow )
4621 {
4622 int count = 0;
4623 PWINDOW_OBJECT Window, pWnd;
4624 HWND *win_array;
4625
4626 if(!(Window = IntGetWindowObject(owner)))
4627 {
4628 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
4629 return FALSE;
4630 }
4631
4632 win_array = IntWinListChildren( Window);
4633 IntReleaseWindowObject(Window);
4634
4635 if (!win_array) return TRUE;
4636
4637 while (win_array[count]) count++;
4638 while (--count >= 0)
4639 {
4640 if (UserGetWindow( win_array[count], GW_OWNER ) != owner) continue;
4641 if (!(pWnd = IntGetWindowObject( win_array[count] ))) continue;
4642 // if (pWnd == WND_OTHER_PROCESS) continue;
4643
4644 if (fShow)
4645 {
4646 if (pWnd->Flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
4647 {
4648 IntReleaseWindowObject( pWnd );
4649 /* In Windows, ShowOwnedPopups(TRUE) generates
4650 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4651 * regardless of the state of the owner
4652 */
4653 co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
4654 continue;
4655 }
4656 }
4657 else
4658 {
4659 if (pWnd->Style & WS_VISIBLE)
4660 {
4661 IntReleaseWindowObject( pWnd );
4662 /* In Windows, ShowOwnedPopups(FALSE) generates
4663 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4664 * regardless of the state of the owner
4665 */
4666 co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
4667 continue;
4668 }
4669 }
4670 IntReleaseWindowObject( pWnd );
4671 }
4672 ExFreePool( win_array );
4673 return TRUE;
4674 }
4675
4676
4677 /* EOF */