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