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