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