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