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