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