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