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