Remove window timers when window is destroyed
[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.205 2004/03/31 18:37:12 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 IntLockRelatives(WindowObject);
2620 switch (Relationship)
2621 {
2622 case GW_HWNDFIRST:
2623 if((Parent = IntGetParentObject(WindowObject)))
2624 {
2625 IntLockRelatives(Parent);
2626 if (Parent->FirstChild)
2627 hWndResult = Parent->FirstChild->Self;
2628 IntUnLockRelatives(Parent);
2629 IntReleaseWindowObject(Parent);
2630 }
2631 break;
2632
2633 case GW_HWNDLAST:
2634 if((Parent = IntGetParentObject(WindowObject)))
2635 {
2636 IntLockRelatives(Parent);
2637 if (Parent->LastChild)
2638 hWndResult = Parent->LastChild->Self;
2639 IntUnLockRelatives(Parent);
2640 IntReleaseWindowObject(Parent);
2641 }
2642 break;
2643
2644 case GW_HWNDNEXT:
2645 if (WindowObject->NextSibling)
2646 hWndResult = WindowObject->NextSibling->Self;
2647 break;
2648
2649 case GW_HWNDPREV:
2650 if (WindowObject->PrevSibling)
2651 hWndResult = WindowObject->PrevSibling->Self;
2652 break;
2653
2654 case GW_OWNER:
2655 if((Parent = IntGetWindowObject(WindowObject->Owner)))
2656 {
2657 hWndResult = Parent->Self;
2658 IntReleaseWindowObject(Parent);
2659 }
2660 break;
2661 case GW_CHILD:
2662 if (WindowObject->FirstChild)
2663 hWndResult = WindowObject->FirstChild->Self;
2664 break;
2665 }
2666 IntUnLockRelatives(WindowObject);
2667
2668 IntReleaseWindowObject(WindowObject);
2669
2670 return hWndResult;
2671 }
2672
2673 /*
2674 * NtUserGetWindowDC
2675 *
2676 * The NtUserGetWindowDC function retrieves the device context (DC) for the
2677 * entire window, including title bar, menus, and scroll bars. A window device
2678 * context permits painting anywhere in a window, because the origin of the
2679 * device context is the upper-left corner of the window instead of the client
2680 * area.
2681 *
2682 * Status
2683 * @implemented
2684 */
2685
2686 DWORD STDCALL
2687 NtUserGetWindowDC(HWND hWnd)
2688 {
2689 return (DWORD)NtUserGetDCEx(hWnd, 0, DCX_USESTYLE | DCX_WINDOW);
2690 }
2691
2692 /*
2693 * NtUserGetWindowLong
2694 *
2695 * The NtUserGetWindowLong function retrieves information about the specified
2696 * window. The function also retrieves the 32-bit (long) value at the
2697 * specified offset into the extra window memory.
2698 *
2699 * Status
2700 * @implemented
2701 */
2702
2703 LONG STDCALL
2704 NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
2705 {
2706 PWINDOW_OBJECT WindowObject, Parent;
2707 LONG Result;
2708
2709 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
2710
2711 WindowObject = IntGetWindowObject(hWnd);
2712 if (WindowObject == NULL)
2713 {
2714 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2715 return 0;
2716 }
2717
2718 /*
2719 * Only allow CSRSS to mess with the desktop window
2720 */
2721 if (hWnd == IntGetDesktopWindow()
2722 && WindowObject->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
2723 {
2724 SetLastWin32Error(STATUS_ACCESS_DENIED);
2725 return 0;
2726 }
2727
2728 if ((INT)Index >= 0)
2729 {
2730 if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
2731 {
2732 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2733 return 0;
2734 }
2735 Result = *((LONG *)(WindowObject->ExtraData + Index));
2736 }
2737 else
2738 {
2739 switch (Index)
2740 {
2741 case GWL_EXSTYLE:
2742 Result = WindowObject->ExStyle;
2743 break;
2744
2745 case GWL_STYLE:
2746 Result = WindowObject->Style;
2747 break;
2748
2749 case GWL_WNDPROC:
2750 if (Ansi)
2751 Result = (LONG) WindowObject->WndProcA;
2752 else
2753 Result = (LONG) WindowObject->WndProcW;
2754 break;
2755
2756 case GWL_HINSTANCE:
2757 Result = (LONG) WindowObject->Instance;
2758 break;
2759
2760 case GWL_HWNDPARENT:
2761 IntLockRelatives(WindowObject);
2762 Parent = IntGetWindowObject(WindowObject->Parent);
2763 IntUnLockRelatives(WindowObject);
2764 if(Parent)
2765 {
2766 if (Parent && Parent->Self == IntGetDesktopWindow())
2767 Result = (LONG) NtUserGetWindow(WindowObject->Self, GW_OWNER);
2768 else
2769 Result = (LONG) Parent->Self;
2770 IntReleaseWindowObject(Parent);
2771 }
2772 break;
2773
2774 case GWL_ID:
2775 Result = (LONG) WindowObject->IDMenu;
2776 break;
2777
2778 case GWL_USERDATA:
2779 Result = WindowObject->UserData;
2780 break;
2781
2782 default:
2783 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
2784 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2785 Result = 0;
2786 break;
2787 }
2788 }
2789
2790 IntReleaseWindowObject(WindowObject);
2791
2792 return Result;
2793 }
2794
2795 /*
2796 * NtUserSetWindowLong
2797 *
2798 * The NtUserSetWindowLong function changes an attribute of the specified
2799 * window. The function also sets the 32-bit (long) value at the specified
2800 * offset into the extra window memory.
2801 *
2802 * Status
2803 * @implemented
2804 */
2805
2806 LONG STDCALL
2807 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
2808 {
2809 PWINDOW_OBJECT WindowObject, Parent;
2810 PW32PROCESS Process;
2811 PWINSTATION_OBJECT WindowStation;
2812 LONG OldValue;
2813 STYLESTRUCT Style;
2814
2815 if (hWnd == IntGetDesktopWindow())
2816 {
2817 SetLastWin32Error(STATUS_ACCESS_DENIED);
2818 return 0;
2819 }
2820
2821 WindowObject = IntGetWindowObject(hWnd);
2822 if (WindowObject == NULL)
2823 {
2824 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2825 return 0;
2826 }
2827
2828 if ((INT)Index >= 0)
2829 {
2830 if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
2831 {
2832 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2833 IntReleaseWindowObject(WindowObject);
2834 return 0;
2835 }
2836 OldValue = *((LONG *)(WindowObject->ExtraData + Index));
2837 *((LONG *)(WindowObject->ExtraData + Index)) = NewValue;
2838 }
2839 else
2840 {
2841 switch (Index)
2842 {
2843 case GWL_EXSTYLE:
2844 OldValue = (LONG) WindowObject->ExStyle;
2845 Style.styleOld = OldValue;
2846 Style.styleNew = NewValue;
2847
2848 /*
2849 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
2850 */
2851 Process = WindowObject->OwnerThread->ThreadsProcess->Win32Process;
2852 WindowStation = Process->WindowStation;
2853 if(WindowStation)
2854 {
2855 if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
2856 Style.styleNew &= ~WS_EX_TOPMOST;
2857 }
2858
2859 IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
2860 WindowObject->ExStyle = (DWORD)Style.styleNew;
2861 IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
2862 break;
2863
2864 case GWL_STYLE:
2865 OldValue = (LONG) WindowObject->Style;
2866 Style.styleOld = OldValue;
2867 Style.styleNew = NewValue;
2868 IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
2869 WindowObject->Style = (DWORD)Style.styleNew;
2870 IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
2871 break;
2872
2873 case GWL_WNDPROC:
2874 /* FIXME: should check if window belongs to current process */
2875 if (Ansi)
2876 {
2877 OldValue = (LONG) WindowObject->WndProcA;
2878 WindowObject->WndProcA = (WNDPROC) NewValue;
2879 WindowObject->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE);
2880 WindowObject->Unicode = FALSE;
2881 }
2882 else
2883 {
2884 OldValue = (LONG) WindowObject->WndProcW;
2885 WindowObject->WndProcW = (WNDPROC) NewValue;
2886 WindowObject->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE);
2887 WindowObject->Unicode = TRUE;
2888 }
2889 break;
2890
2891 case GWL_HINSTANCE:
2892 OldValue = (LONG) WindowObject->Instance;
2893 WindowObject->Instance = (HINSTANCE) NewValue;
2894 break;
2895
2896 case GWL_HWNDPARENT:
2897 Parent = IntGetParentObject(WindowObject);
2898 if (Parent && (Parent->Self == IntGetDesktopWindow()))
2899 OldValue = (LONG) IntSetOwner(WindowObject->Self, (HWND) NewValue);
2900 else
2901 OldValue = (LONG) NtUserSetParent(WindowObject->Self, (HWND) NewValue);
2902 if(Parent)
2903 IntReleaseWindowObject(Parent);
2904 break;
2905
2906 case GWL_ID:
2907 OldValue = (LONG) WindowObject->IDMenu;
2908 WindowObject->IDMenu = (UINT) NewValue;
2909 break;
2910
2911 case GWL_USERDATA:
2912 OldValue = WindowObject->UserData;
2913 WindowObject->UserData = NewValue;
2914 break;
2915
2916 default:
2917 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
2918 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2919 OldValue = 0;
2920 break;
2921 }
2922 }
2923
2924 IntReleaseWindowObject(WindowObject);
2925
2926 return OldValue;
2927 }
2928
2929 /*
2930 * NtUserSetWindowWord
2931 *
2932 * Legacy function similar to NtUserSetWindowLong.
2933 *
2934 * Status
2935 * @implemented
2936 */
2937
2938 WORD STDCALL
2939 NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
2940 {
2941 PWINDOW_OBJECT WindowObject;
2942 WORD OldValue;
2943
2944 switch (Index)
2945 {
2946 case GWL_ID:
2947 case GWL_HINSTANCE:
2948 case GWL_HWNDPARENT:
2949 return NtUserSetWindowLong(hWnd, Index, (UINT)NewValue, TRUE);
2950 default:
2951 if (Index < 0)
2952 {
2953 SetLastWin32Error(ERROR_INVALID_INDEX);
2954 return 0;
2955 }
2956 }
2957
2958 WindowObject = IntGetWindowObject(hWnd);
2959 if (WindowObject == NULL)
2960 {
2961 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2962 return 0;
2963 }
2964
2965 if (Index > WindowObject->ExtraDataSize - sizeof(WORD))
2966 {
2967 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2968 IntReleaseWindowObject(WindowObject);
2969 return 0;
2970 }
2971
2972 OldValue = *((WORD *)(WindowObject->ExtraData + Index));
2973 *((WORD *)(WindowObject->ExtraData + Index)) = NewValue;
2974
2975 IntReleaseWindowObject(WindowObject);
2976
2977 return OldValue;
2978 }
2979
2980 /*
2981 * @implemented
2982 */
2983 BOOL STDCALL
2984 NtUserGetWindowPlacement(HWND hWnd,
2985 WINDOWPLACEMENT *lpwndpl)
2986 {
2987 PWINDOW_OBJECT WindowObject;
2988 PINTERNALPOS InternalPos;
2989 POINT Size;
2990 WINDOWPLACEMENT Safepl;
2991 NTSTATUS Status;
2992
2993 WindowObject = IntGetWindowObject(hWnd);
2994 if (WindowObject == NULL)
2995 {
2996 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
2997 return FALSE;
2998 }
2999
3000 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3001 if(!NT_SUCCESS(Status))
3002 {
3003 SetLastNtError(Status);
3004 IntReleaseWindowObject(WindowObject);
3005 return FALSE;
3006 }
3007 if(Safepl.length != sizeof(WINDOWPLACEMENT))
3008 {
3009 IntReleaseWindowObject(WindowObject);
3010 return FALSE;
3011 }
3012
3013 Safepl.flags = 0;
3014 Safepl.showCmd = ((WindowObject->Flags & WINDOWOBJECT_RESTOREMAX) ? SW_MAXIMIZE : SW_SHOWNORMAL);
3015
3016 Size.x = WindowObject->WindowRect.left;
3017 Size.y = WindowObject->WindowRect.top;
3018 InternalPos = WinPosInitInternalPos(WindowObject, &Size,
3019 &WindowObject->WindowRect);
3020 if (InternalPos)
3021 {
3022 Safepl.rcNormalPosition = InternalPos->NormalRect;
3023 Safepl.ptMinPosition = InternalPos->IconPos;
3024 Safepl.ptMaxPosition = InternalPos->MaxPos;
3025 }
3026 else
3027 {
3028 IntReleaseWindowObject(WindowObject);
3029 return FALSE;
3030 }
3031
3032 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
3033 if(!NT_SUCCESS(Status))
3034 {
3035 SetLastNtError(Status);
3036 IntReleaseWindowObject(WindowObject);
3037 return FALSE;
3038 }
3039
3040 IntReleaseWindowObject(WindowObject);
3041 return TRUE;
3042 }
3043
3044
3045 /*!
3046 * Return the dimension of the window in the screen coordinates.
3047 * \param hWnd window handle.
3048 * \param Rect pointer to the buffer where the coordinates are returned.
3049 */
3050 /*
3051 * @implemented
3052 */
3053 BOOL STDCALL
3054 NtUserGetWindowRect(HWND hWnd, LPRECT Rect)
3055 {
3056 PWINDOW_OBJECT Wnd;
3057 NTSTATUS Status;
3058
3059 if (!(Wnd = IntGetWindowObject(hWnd)))
3060 {
3061 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3062 return FALSE;
3063 }
3064 Status = MmCopyToCaller(Rect, &Wnd->WindowRect, sizeof(RECT));
3065 if (!NT_SUCCESS(Status))
3066 {
3067 IntReleaseWindowObject(Wnd);
3068 SetLastNtError(Status);
3069 return FALSE;
3070 }
3071
3072 IntReleaseWindowObject(Wnd);
3073 return TRUE;
3074 }
3075
3076
3077 /*
3078 * @implemented
3079 */
3080 DWORD STDCALL
3081 NtUserGetWindowThreadProcessId(HWND hWnd, LPDWORD UnsafePid)
3082 {
3083 PWINDOW_OBJECT Wnd;
3084 DWORD tid, pid;
3085
3086 if (!(Wnd = IntGetWindowObject(hWnd)))
3087 {
3088 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3089 return 0;
3090 }
3091
3092 tid = (DWORD)IntGetWndThreadId(Wnd);
3093 pid = (DWORD)IntGetWndProcessId(Wnd);
3094
3095 if (UnsafePid) MmCopyToCaller(UnsafePid, &pid, sizeof(DWORD));
3096
3097 return tid;
3098 }
3099
3100
3101 /*
3102 * @unimplemented
3103 */
3104 DWORD STDCALL
3105 NtUserLockWindowUpdate(DWORD Unknown0)
3106 {
3107 UNIMPLEMENTED
3108
3109 return 0;
3110 }
3111
3112
3113 /*
3114 * @implemented
3115 */
3116 BOOL STDCALL
3117 NtUserMoveWindow(
3118 HWND hWnd,
3119 int X,
3120 int Y,
3121 int nWidth,
3122 int nHeight,
3123 BOOL bRepaint)
3124 {
3125 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
3126 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
3127 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
3128 }
3129
3130 /*
3131 QueryWindow based on KJK::Hyperion and James Tabor.
3132
3133 0 = QWUniqueProcessId
3134 1 = QWUniqueThreadId
3135 4 = QWIsHung Implements IsHungAppWindow found
3136 by KJK::Hyperion.
3137
3138 9 = QWKillWindow When I called this with hWnd ==
3139 DesktopWindow, it shutdown the system
3140 and rebooted.
3141 */
3142 /*
3143 * @implemented
3144 */
3145 DWORD STDCALL
3146 NtUserQueryWindow(HWND hWnd, DWORD Index)
3147 {
3148 PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
3149 DWORD Result;
3150
3151 if (Window == NULL)
3152 {
3153 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3154 return 0;
3155 }
3156
3157 switch(Index)
3158 {
3159 case 0x00:
3160 Result = (DWORD)IntGetWndProcessId(Window);
3161 break;
3162
3163 case 0x01:
3164 Result = (DWORD)IntGetWndThreadId(Window);
3165 break;
3166
3167 default:
3168 Result = (DWORD)NULL;
3169 break;
3170 }
3171
3172 IntReleaseWindowObject(Window);
3173
3174 return Result;
3175 }
3176
3177
3178 /*
3179 * @unimplemented
3180 */
3181 DWORD STDCALL
3182 NtUserRealChildWindowFromPoint(DWORD Unknown0,
3183 DWORD Unknown1,
3184 DWORD Unknown2)
3185 {
3186 UNIMPLEMENTED
3187
3188 return 0;
3189 }
3190
3191
3192 /*
3193 * @implemented
3194 */
3195 UINT STDCALL
3196 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
3197 {
3198 #if 0
3199 PLIST_ENTRY Current;
3200 PREGISTERED_MESSAGE NewMsg, RegMsg;
3201 UINT Msg = REGISTERED_MESSAGE_MIN;
3202 UNICODE_STRING MessageName;
3203 NTSTATUS Status;
3204
3205 Status = MmCopyFromCaller(&MessageName, MessageNameUnsafe, sizeof(UNICODE_STRING));
3206 if (! NT_SUCCESS(Status))
3207 {
3208 SetLastNtError(Status);
3209 return 0;
3210 }
3211
3212 NewMsg = ExAllocatePoolWithTag(PagedPool,
3213 sizeof(REGISTERED_MESSAGE) +
3214 MessageName.Length,
3215 TAG_WNAM);
3216 if (NULL == NewMsg)
3217 {
3218 SetLastNtError(STATUS_NO_MEMORY);
3219 return 0;
3220 }
3221
3222 Status = MmCopyFromCaller(NewMsg->MessageName, MessageName.Buffer, MessageName.Length);
3223 if (! NT_SUCCESS(Status))
3224 {
3225 ExFreePool(NewMsg);
3226 SetLastNtError(Status);
3227 return 0;
3228 }
3229 NewMsg->MessageName[MessageName.Length / sizeof(WCHAR)] = L'\0';
3230 if (wcslen(NewMsg->MessageName) != MessageName.Length / sizeof(WCHAR))
3231 {
3232 ExFreePool(NewMsg);
3233 SetLastNtError(STATUS_INVALID_PARAMETER);
3234 return 0;
3235 }
3236
3237 Current = RegisteredMessageListHead.Flink;
3238 while (Current != &RegisteredMessageListHead)
3239 {
3240 RegMsg = CONTAINING_RECORD(Current, REGISTERED_MESSAGE, ListEntry);
3241 if (0 == wcscmp(NewMsg->MessageName, RegMsg->MessageName))
3242 {
3243 ExFreePool(NewMsg);
3244 return Msg;
3245 }
3246 Msg++;
3247 Current = Current->Flink;
3248 }
3249
3250 if (REGISTERED_MESSAGE_MAX < Msg)
3251 {
3252 ExFreePool(NewMsg);
3253 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
3254 return 0;
3255 }
3256
3257 InsertTailList(&RegisteredMessageListHead, &(NewMsg->ListEntry));
3258
3259 return Msg;
3260 #else
3261 /*
3262 * Notes:
3263 * - There's no need to call MmSafe*, because it should be done in kernel.
3264 * - The passed UNICODE_STRING is expected to be NULL-terminated.
3265 */
3266 return (UINT)IntAddAtom(MessageNameUnsafe->Buffer);
3267 #endif
3268 }
3269
3270
3271 /*
3272 * @unimplemented
3273 */
3274 DWORD STDCALL
3275 NtUserSetImeOwnerWindow(DWORD Unknown0,
3276 DWORD Unknown1)
3277 {
3278 UNIMPLEMENTED
3279
3280 return 0;
3281 }
3282
3283
3284 /*
3285 * @unimplemented
3286 */
3287 DWORD STDCALL
3288 NtUserSetInternalWindowPos(DWORD Unknown0,
3289 DWORD Unknown1,
3290 DWORD Unknown2,
3291 DWORD Unknown3)
3292 {
3293 UNIMPLEMENTED
3294
3295 return 0;
3296
3297 }
3298
3299
3300 /*
3301 * @unimplemented
3302 */
3303 DWORD STDCALL
3304 NtUserSetLayeredWindowAttributes(DWORD Unknown0,
3305 DWORD Unknown1,
3306 DWORD Unknown2,
3307 DWORD Unknown3)
3308 {
3309 UNIMPLEMENTED
3310
3311 return 0;
3312 }
3313
3314
3315 /*
3316 * @unimplemented
3317 */
3318 DWORD STDCALL
3319 NtUserSetLogonNotifyWindow(DWORD Unknown0)
3320 {
3321 UNIMPLEMENTED
3322
3323 return 0;
3324 }
3325
3326
3327 /*
3328 * @implemented
3329 */
3330 BOOL STDCALL
3331 NtUserSetMenu(
3332 HWND Wnd,
3333 HMENU Menu,
3334 BOOL Repaint)
3335 {
3336 PWINDOW_OBJECT WindowObject;
3337 BOOL Changed;
3338
3339 WindowObject = IntGetWindowObject((HWND) Wnd);
3340 if (NULL == WindowObject)
3341 {
3342 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3343 return FALSE;
3344 }
3345
3346 if (! IntSetMenu(WindowObject, Menu, &Changed))
3347 {
3348 IntReleaseWindowObject(WindowObject);
3349 return FALSE;
3350 }
3351
3352 IntReleaseWindowObject(WindowObject);
3353
3354 if (Changed && Repaint)
3355 {
3356 WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
3357 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
3358 }
3359
3360 return TRUE;
3361 }
3362
3363
3364 /*
3365 * @unimplemented
3366 */
3367 DWORD STDCALL
3368 NtUserSetWindowFNID(DWORD Unknown0,
3369 DWORD Unknown1)
3370 {
3371 UNIMPLEMENTED
3372
3373 return 0;
3374 }
3375
3376
3377
3378 /*
3379 * @implemented
3380 */
3381 BOOL STDCALL
3382 NtUserSetWindowPlacement(HWND hWnd,
3383 WINDOWPLACEMENT *lpwndpl)
3384 {
3385 PWINDOW_OBJECT WindowObject;
3386 WINDOWPLACEMENT Safepl;
3387 NTSTATUS Status;
3388
3389 WindowObject = IntGetWindowObject(hWnd);
3390 if (WindowObject == NULL)
3391 {
3392 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3393 return FALSE;
3394 }
3395 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3396 if(!NT_SUCCESS(Status))
3397 {
3398 SetLastNtError(Status);
3399 IntReleaseWindowObject(WindowObject);
3400 return FALSE;
3401 }
3402 if(Safepl.length != sizeof(WINDOWPLACEMENT))
3403 {
3404 IntReleaseWindowObject(WindowObject);
3405 return FALSE;
3406 }
3407
3408 if ((WindowObject->Style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
3409 {
3410 WinPosSetWindowPos(WindowObject->Self, NULL,
3411 Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
3412 Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
3413 Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
3414 SWP_NOZORDER | SWP_NOACTIVATE);
3415 }
3416
3417 /* FIXME - change window status */
3418 WinPosShowWindow(WindowObject->Self, Safepl.showCmd);
3419
3420 if (WindowObject->InternalPos == NULL)
3421 WindowObject->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
3422 WindowObject->InternalPos->NormalRect = Safepl.rcNormalPosition;
3423 WindowObject->InternalPos->IconPos = Safepl.ptMinPosition;
3424 WindowObject->InternalPos->MaxPos = Safepl.ptMaxPosition;
3425
3426 IntReleaseWindowObject(WindowObject);
3427 return TRUE;
3428 }
3429
3430
3431 /*
3432 * @implemented
3433 */
3434 BOOL STDCALL
3435 NtUserSetWindowPos(
3436 HWND hWnd,
3437 HWND hWndInsertAfter,
3438 int X,
3439 int Y,
3440 int cx,
3441 int cy,
3442 UINT uFlags)
3443 {
3444 return WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
3445 }
3446
3447
3448 INT FASTCALL
3449 IntGetWindowRgn(HWND hWnd, HRGN hRgn)
3450 {
3451 INT Ret;
3452 PWINDOW_OBJECT WindowObject;
3453 HRGN VisRgn;
3454 ROSRGNDATA *pRgn;
3455
3456 if(!(WindowObject = IntGetWindowObject(hWnd)))
3457 {
3458 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3459 return ERROR;
3460 }
3461 if(!hRgn)
3462 {
3463 IntReleaseWindowObject(WindowObject);
3464 return ERROR;
3465 }
3466
3467 /* Create a new window region using the window rectangle */
3468 VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
3469 NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
3470 /* if there's a region assigned to the window, combine them both */
3471 if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
3472 NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
3473 /* Copy the region into hRgn */
3474 NtGdiCombineRgn(hRgn, VisRgn, NULL, RGN_COPY);
3475
3476 if((pRgn = RGNDATA_LockRgn(hRgn)))
3477 {
3478 Ret = pRgn->rdh.iType;
3479 RGNDATA_UnlockRgn(hRgn);
3480 }
3481 else
3482 Ret = ERROR;
3483
3484 NtGdiDeleteObject(VisRgn);
3485
3486 IntReleaseWindowObject(WindowObject);
3487 return Ret;
3488 }
3489
3490 INT FASTCALL
3491 IntGetWindowRgnBox(HWND hWnd, RECT *Rect)
3492 {
3493 INT Ret;
3494 PWINDOW_OBJECT WindowObject;
3495 HRGN VisRgn;
3496 ROSRGNDATA *pRgn;
3497
3498 if(!(WindowObject = IntGetWindowObject(hWnd)))
3499 {
3500 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3501 return ERROR;
3502 }
3503 if(!Rect)
3504 {
3505 IntReleaseWindowObject(WindowObject);
3506 return ERROR;
3507 }
3508
3509 /* Create a new window region using the window rectangle */
3510 VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
3511 NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
3512 /* if there's a region assigned to the window, combine them both */
3513 if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
3514 NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
3515
3516 if((pRgn = RGNDATA_LockRgn(VisRgn)))
3517 {
3518 Ret = pRgn->rdh.iType;
3519 *Rect = pRgn->rdh.rcBound;
3520 RGNDATA_UnlockRgn(VisRgn);
3521 }
3522 else
3523 Ret = ERROR;
3524
3525 NtGdiDeleteObject(VisRgn);
3526
3527 IntReleaseWindowObject(WindowObject);
3528 return Ret;
3529 }
3530
3531
3532 /*
3533 * @implemented
3534 */
3535 INT STDCALL
3536 NtUserSetWindowRgn(
3537 HWND hWnd,
3538 HRGN hRgn,
3539 BOOL bRedraw)
3540 {
3541 PWINDOW_OBJECT WindowObject;
3542
3543 WindowObject = IntGetWindowObject(hWnd);
3544 if (WindowObject == NULL)
3545 {
3546 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3547 return 0;
3548 }
3549
3550 /* FIXME - Verify if hRgn is a valid handle!!!!
3551 Propably make this operation thread-safe, but maybe it's not necessary */
3552
3553 if(WindowObject->WindowRegion)
3554 {
3555 /* Delete no longer needed region handle */
3556 NtGdiDeleteObject(WindowObject->WindowRegion);
3557 }
3558 WindowObject->WindowRegion = hRgn;
3559
3560 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
3561
3562 if(bRedraw)
3563 {
3564 IntRedrawWindow(WindowObject, NULL, NULL, RDW_INVALIDATE);
3565 }
3566
3567 IntReleaseWindowObject(WindowObject);
3568 return (INT)hRgn;
3569 }
3570
3571
3572 /*
3573 * @implemented
3574 */
3575 BOOL STDCALL
3576 NtUserShowWindow(HWND hWnd,
3577 LONG nCmdShow)
3578 {
3579 return WinPosShowWindow(hWnd, nCmdShow);
3580 }
3581
3582
3583 /*
3584 * @unimplemented
3585 */
3586 DWORD STDCALL
3587 NtUserShowWindowAsync(DWORD Unknown0,
3588 DWORD Unknown1)
3589 {
3590 UNIMPLEMENTED
3591
3592 return 0;
3593 }
3594
3595
3596 /*
3597 * @unimplemented
3598 */
3599 DWORD STDCALL
3600 NtUserUpdateLayeredWindow(DWORD Unknown0,
3601 DWORD Unknown1,
3602 DWORD Unknown2,
3603 DWORD Unknown3,
3604 DWORD Unknown4,
3605 DWORD Unknown5,
3606 DWORD Unknown6,
3607 DWORD Unknown7,
3608 DWORD Unknown8)
3609 {
3610 UNIMPLEMENTED
3611
3612 return 0;
3613 }
3614
3615
3616 /*
3617 * @implemented
3618 */
3619 VOID STDCALL
3620 NtUserValidateRect(HWND hWnd, const RECT* Rect)
3621 {
3622 return (VOID)NtUserRedrawWindow(hWnd, Rect, 0, RDW_VALIDATE | RDW_NOCHILDREN);
3623 }
3624
3625
3626 /*
3627 * @implemented
3628 */
3629 HWND STDCALL
3630 NtUserWindowFromPoint(LONG X, LONG Y)
3631 {
3632 POINT pt;
3633 HWND Ret;
3634 PWINDOW_OBJECT DesktopWindow, Window = NULL;
3635
3636 if ((DesktopWindow = IntGetWindowObject(IntGetDesktopWindow())))
3637 {
3638 USHORT Hit;
3639
3640 pt.x = X;
3641 pt.y = Y;
3642
3643 Hit = WinPosWindowFromPoint(DesktopWindow, TRUE, &pt, &Window);
3644
3645 if(Window)
3646 {
3647 Ret = Window->Self;
3648 IntReleaseWindowObject(Window);
3649 IntReleaseWindowObject(DesktopWindow);
3650 return Ret;
3651 }
3652
3653 IntReleaseWindowObject(DesktopWindow);
3654 }
3655
3656 return NULL;
3657 }
3658
3659
3660 /*
3661 * NtUserDefSetText
3662 *
3663 * Undocumented function that is called from DefWindowProc to set
3664 * window text.
3665 *
3666 * FIXME: Call this from user32.dll!
3667 *
3668 * Status
3669 * @unimplemented
3670 */
3671
3672 BOOL STDCALL
3673 NtUserDefSetText(HWND WindowHandle, PANSI_STRING Text)
3674 {
3675 PWINDOW_OBJECT WindowObject;
3676 UNICODE_STRING NewWindowName;
3677 BOOL Result = FALSE;
3678
3679 WindowObject = IntGetWindowObject(WindowHandle);
3680 if (!WindowObject)
3681 {
3682 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3683 return FALSE;
3684 }
3685
3686 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NewWindowName, Text, TRUE)))
3687 {
3688 RtlFreeUnicodeString(&WindowObject->WindowName);
3689 WindowObject->WindowName.Buffer = NewWindowName.Buffer;
3690 WindowObject->WindowName.Length = NewWindowName.Length;
3691 WindowObject->WindowName.MaximumLength = NewWindowName.MaximumLength;
3692 Result = TRUE;
3693 }
3694
3695 IntReleaseWindowObject(WindowObject);
3696
3697 return Result;
3698 }
3699
3700 /*
3701 * NtUserInternalGetWindowText
3702 *
3703 * FIXME: Call this from user32.dll!
3704 *
3705 * Status
3706 * @implemented
3707 */
3708
3709 DWORD STDCALL
3710 NtUserInternalGetWindowText(HWND WindowHandle, LPWSTR Text, INT MaxCount)
3711 {
3712 PWINDOW_OBJECT WindowObject;
3713 DWORD Result;
3714
3715 WindowObject = IntGetWindowObject(WindowHandle);
3716 if (!WindowObject)
3717 {
3718 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
3719 return 0;
3720 }
3721
3722 Result = WindowObject->WindowName.Length / sizeof(WCHAR);
3723 if (Text)
3724 {
3725 /* FIXME: Shouldn't it be always NULL terminated? */
3726 wcsncpy(Text, WindowObject->WindowName.Buffer, MaxCount);
3727 if (MaxCount < Result)
3728 {
3729 Result = MaxCount;
3730 }
3731 }
3732
3733 IntReleaseWindowObject(WindowObject);
3734
3735 return Result;
3736 }
3737
3738 DWORD STDCALL
3739 NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data)
3740 {
3741 WndProcHandle Entry;
3742 if (((DWORD)wpHandle & 0xFFFF0000) == 0xFFFF0000)
3743 {
3744 Entry = WndProcHandlesArray[(DWORD)wpHandle & 0x0000FFFF];
3745 Data->WindowProc = Entry.WindowProc;
3746 Data->IsUnicode = Entry.IsUnicode;
3747 Data->ProcessID = Entry.ProcessID;
3748 return TRUE;
3749 } else {
3750 return FALSE;
3751 }
3752 return FALSE;
3753 }
3754
3755 DWORD
3756 IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode)
3757 {
3758 WORD i;
3759 WORD FreeSpot;
3760 BOOL found;
3761 WndProcHandle *OldArray;
3762 WORD OldArraySize;
3763 found = FALSE;
3764 for (i = 0;i < WndProcHandlesArraySize;i++)
3765 {
3766 if (WndProcHandlesArray[i].WindowProc == NULL)
3767 {
3768 FreeSpot = i;
3769 found = TRUE;
3770 }
3771 }
3772 if (!found)
3773 {
3774 OldArray = WndProcHandlesArray;
3775 OldArraySize = WndProcHandlesArraySize;
3776 WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,(OldArraySize + WPH_SIZE) * sizeof(WndProcHandle), TAG_WINPROCLST);
3777 WndProcHandlesArraySize = OldArraySize + WPH_SIZE;
3778 RtlCopyMemory(WndProcHandlesArray,OldArray,OldArraySize * sizeof(WndProcHandle));
3779 ExFreePool(OldArray);
3780 FreeSpot = OldArraySize + 1;
3781 }
3782 WndProcHandlesArray[FreeSpot].WindowProc = WindowProc;
3783 WndProcHandlesArray[FreeSpot].IsUnicode = IsUnicode;
3784 WndProcHandlesArray[FreeSpot].ProcessID = PsGetCurrentProcessId();
3785 return FreeSpot + 0xFFFF0000;
3786 }
3787
3788 DWORD
3789 IntRemoveWndProcHandle(WNDPROC Handle)
3790 {
3791 WORD position;
3792 position = (DWORD)Handle & 0x0000FFFF;
3793 if (position > WndProcHandlesArraySize)
3794 {
3795 return FALSE;
3796 }
3797 WndProcHandlesArray[position].WindowProc = NULL;
3798 WndProcHandlesArray[position].IsUnicode = FALSE;
3799 WndProcHandlesArray[position].ProcessID = NULL;
3800 return TRUE;
3801 }
3802
3803 DWORD
3804 IntRemoveProcessWndProcHandles(HANDLE ProcessID)
3805 {
3806 WORD i;
3807 for (i = 0;i < WndProcHandlesArraySize;i++)
3808 {
3809 if (WndProcHandlesArray[i].ProcessID == ProcessID)
3810 {
3811 WndProcHandlesArray[i].WindowProc = NULL;
3812 WndProcHandlesArray[i].IsUnicode = FALSE;
3813 WndProcHandlesArray[i].ProcessID = NULL;
3814 }
3815 }
3816 return TRUE;
3817 }
3818
3819 /* EOF */