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