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