sync with trunk (r47268)
[reactos.git] / 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 Wnd->style = dwStyle & ~WS_VISIBLE;
2002
2003 /* Correct the window style. */
2004 if ((Wnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2005 {
2006 Wnd->style |= WS_CLIPSIBLINGS;
2007 DPRINT("3: Style is now %lx\n", dwStyle);
2008 if (!(Wnd->style & WS_POPUP))
2009 {
2010 Wnd->style |= WS_CAPTION;
2011 Window->state |= WINDOWOBJECT_NEED_SIZE;
2012 DPRINT("4: Style is now %lx\n", dwStyle);
2013 }
2014 }
2015
2016 /* create system menu */
2017 if((dwStyle & WS_SYSMENU) )//&& (dwStyle & WS_CAPTION) == WS_CAPTION)
2018 {
2019 SystemMenu = IntGetSystemMenu(Window, TRUE, TRUE);
2020 if(SystemMenu)
2021 {
2022 Window->SystemMenu = SystemMenu->MenuInfo.Self;
2023 IntReleaseMenuObject(SystemMenu);
2024 }
2025 }
2026
2027 /* Set the window menu */
2028 if ((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2029 {
2030 if (hMenu)
2031 IntSetMenu(Window, hMenu, &MenuChanged);
2032 else if (Wnd->pcls->lpszMenuName) // Take it from the parent.
2033 {
2034 UNICODE_STRING MenuName;
2035 if (IS_INTRESOURCE(Wnd->pcls->lpszMenuName))
2036 {
2037 MenuName.Length = 0;
2038 MenuName.MaximumLength = 0;
2039 MenuName.Buffer = Wnd->pcls->lpszMenuName;
2040 }
2041 else
2042 {
2043 RtlInitUnicodeString( &MenuName, Wnd->pcls->lpszMenuName);
2044 }
2045 hMenu = co_IntCallLoadMenu( Wnd->pcls->hModule, &MenuName);
2046 if (hMenu) IntSetMenu(Window, hMenu, &MenuChanged);
2047 }
2048 }
2049 else // Not a child
2050 Wnd->IDMenu = (UINT) hMenu;
2051
2052 /* Insert the window into the thread's window list. */
2053 InsertTailList (&pti->WindowListHead, &Window->ThreadListEntry);
2054
2055 /* Handle "CS_CLASSDC", it is tested first. */
2056 if ( (Wnd->pcls->style & CS_CLASSDC) && !(Wnd->pcls->pdce) )
2057 { /* One DCE per class to have CLASS. */
2058 Wnd->pcls->pdce = DceAllocDCE( Window, DCE_CLASS_DC );
2059 }
2060 else if ( Wnd->pcls->style & CS_OWNDC)
2061 { /* Allocate a DCE for this window. */
2062 DceAllocDCE(Window, DCE_WINDOW_DC);
2063 }
2064
2065 Pos.x = x;
2066 Pos.y = y;
2067 Size.cx = nWidth;
2068 Size.cy = nHeight;
2069
2070 Wnd->ExStyle = dwExStyle;
2071
2072 /* call hook */
2073 Cs.lpCreateParams = lpParam;
2074 Cs.hInstance = hInstance;
2075 Cs.hMenu = hMenu;
2076 Cs.hwndParent = hWndParent; //Pass the original Parent handle!
2077 Cs.cx = Size.cx;
2078 Cs.cy = Size.cy;
2079 Cs.x = Pos.x;
2080 Cs.y = Pos.y;
2081 Cs.style = Wnd->style;
2082 // Cs.lpszName = (LPCWSTR) WindowName->Buffer;
2083 // Cs.lpszClass = (LPCWSTR) ClassName->Buffer;
2084 Cs.lpszName = (LPCWSTR) WindowName;
2085 Cs.lpszClass = (LPCWSTR) ClassName;
2086 Cs.dwExStyle = dwExStyle;
2087 CbtCreate.lpcs = &Cs;
2088 CbtCreate.hwndInsertAfter = HWND_TOP;
2089 if (ISITHOOKED(WH_CBT))
2090 {
2091 if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))
2092 {
2093 /* FIXME - Delete window object and remove it from the thread windows list */
2094 /* FIXME - delete allocated DCE */
2095 DPRINT1("CBT-hook returned !0\n");
2096 RETURN( (PWND) NULL);
2097 }
2098 }
2099 x = Cs.x;
2100 y = Cs.y;
2101 nWidth = Cs.cx;
2102 nHeight = Cs.cy;
2103
2104 Cs.style = dwStyle;
2105 // FIXME: Need to set the Z order in the window link list if the hook callback changed it!
2106 // hwndInsertAfter = CbtCreate.hwndInsertAfter;
2107
2108 /* default positioning for overlapped windows */
2109 if(!(Wnd->style & (WS_POPUP | WS_CHILD)))
2110 {
2111 RECTL rc, WorkArea;
2112 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
2113 BOOL CalculatedDefPosSize = FALSE;
2114
2115 IntGetDesktopWorkArea(Window->pti->rpdesk, &WorkArea);
2116
2117 rc = WorkArea;
2118 ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;
2119
2120 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
2121 {
2122 CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, &rc, TRUE);
2123
2124 if(ProcessParams->WindowFlags & STARTF_USEPOSITION)
2125 {
2126 ProcessParams->WindowFlags &= ~STARTF_USEPOSITION;
2127 Pos.x = WorkArea.left + ProcessParams->StartingX;
2128 Pos.y = WorkArea.top + ProcessParams->StartingY;
2129 }
2130 else
2131 {
2132 Pos.x = rc.left;
2133 Pos.y = rc.top;
2134 }
2135
2136 /*
2137 According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
2138 y is something else. and Quote!
2139 */
2140
2141 /* Never believe Microsoft's documentation... CreateWindowEx doc says
2142 * that if an overlapped window is created with WS_VISIBLE style bit
2143 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
2144 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
2145 * reveals that
2146 *
2147 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
2148 * 2) it does not ignore the y parameter as the docs claim; instead, it
2149 * uses it as second parameter to ShowWindow() unless y is either
2150 * CW_USEDEFAULT or CW_USEDEFAULT16.
2151 *
2152 * The fact that we didn't do 2) caused bogus windows pop up when wine
2153 * was running apps that were using this obscure feature. Example -
2154 * calc.exe that comes with Win98 (only Win98, it's different from
2155 * the one that comes with Win95 and NT)
2156 */
2157 if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16)
2158 {
2159 dwShowMode = y;
2160 }
2161 }
2162 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
2163 {
2164 if(!CalculatedDefPosSize)
2165 {
2166 IntCalcDefPosSize(ParentWindow, &rc, FALSE);
2167 }
2168 if(ProcessParams->WindowFlags & STARTF_USESIZE)
2169 {
2170 ProcessParams->WindowFlags &= ~STARTF_USESIZE;
2171 Size.cx = ProcessParams->CountX;
2172 Size.cy = ProcessParams->CountY;
2173 }
2174 else
2175 {
2176 Size.cx = rc.right - rc.left;
2177 Size.cy = rc.bottom - rc.top;
2178 }
2179
2180 /* move the window if necessary */
2181 if(Pos.x > rc.left)
2182 Pos.x = max(rc.left, 0);
2183 if(Pos.y > rc.top)
2184 Pos.y = max(rc.top, 0);
2185 }
2186 }
2187 else
2188 {
2189 /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
2190 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
2191 {
2192 Pos.x = 0;
2193 Pos.y = 0;
2194 }
2195 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
2196 {
2197 Size.cx = 0;
2198 Size.cy = 0;
2199 }
2200 }
2201
2202 /* Initialize the window dimensions. */
2203 Wnd->rcWindow.left = Pos.x;
2204 Wnd->rcWindow.top = Pos.y;
2205 Wnd->rcWindow.right = Pos.x + Size.cx;
2206 Wnd->rcWindow.bottom = Pos.y + Size.cy;
2207 if (0 != (Wnd->style & WS_CHILD) && ParentWindow)
2208 {
2209 RECTL_vOffsetRect(&(Wnd->rcWindow), ParentWindow->Wnd->rcClient.left,
2210 ParentWindow->Wnd->rcClient.top);
2211 }
2212 Wnd->rcClient = Wnd->rcWindow;
2213
2214 /*
2215 * Get the size and position of the window.
2216 */
2217 if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
2218 {
2219 POINT MaxSize, MaxPos, MinTrack, MaxTrack;
2220
2221 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
2222 co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack,
2223 &MaxTrack);
2224 if (MaxSize.x < Size.cx)
2225 Size.cx = MaxSize.x;
2226 if (MaxSize.y < Size.cy)
2227 Size.cy = MaxSize.y;
2228 if (Size.cx < MinTrack.x )
2229 Size.cx = MinTrack.x;
2230 if (Size.cy < MinTrack.y )
2231 Size.cy = MinTrack.y;
2232 if (Size.cx < 0)
2233 Size.cx = 0;
2234 if (Size.cy < 0)
2235 Size.cy = 0;
2236 }
2237
2238 Wnd->rcWindow.left = Pos.x;
2239 Wnd->rcWindow.top = Pos.y;
2240 Wnd->rcWindow.right = Pos.x + Size.cx;
2241 Wnd->rcWindow.bottom = Pos.y + Size.cy;
2242 if (0 != (Wnd->style & WS_CHILD) && ParentWindow)
2243 {
2244 RECTL_vOffsetRect(&(Wnd->rcWindow), ParentWindow->Wnd->rcClient.left,
2245 ParentWindow->Wnd->rcClient.top);
2246 }
2247 Wnd->rcClient = Wnd->rcWindow;
2248
2249 /* FIXME: Initialize the window menu. */
2250
2251 /* Send a NCCREATE message. */
2252 DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
2253 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, Size.cx, Size.cy);
2254 DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
2255 Result = co_IntSendMessage(Window->hSelf, WM_NCCREATE, 0, (LPARAM) &Cs);
2256 if (!Result)
2257 {
2258 /* FIXME: Cleanup. */
2259 DPRINT1("IntCreateWindowEx(): NCCREATE message failed. No cleanup performed!\n");
2260 RETURN((PWND)0);
2261 }
2262
2263 /* Calculate the non-client size. */
2264 MaxPos.x = Window->Wnd->rcWindow.left;
2265 MaxPos.y = Window->Wnd->rcWindow.top;
2266
2267
2268 DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
2269 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
2270 Result = co_WinPosGetNonClientSize(Window,
2271 &Window->Wnd->rcWindow,
2272 &Window->Wnd->rcClient);
2273
2274 RECTL_vOffsetRect(&Window->Wnd->rcWindow,
2275 MaxPos.x - Window->Wnd->rcWindow.left,
2276 MaxPos.y - Window->Wnd->rcWindow.top);
2277
2278
2279 if (NULL != ParentWindow)
2280 {
2281 /* link the window into the parent's child list */
2282 if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
2283 {
2284 PWINDOW_OBJECT PrevSibling;
2285
2286 PrevSibling = ParentWindow->spwndChild;
2287
2288 if(PrevSibling)
2289 {
2290 while (PrevSibling->spwndNext)
2291 PrevSibling = PrevSibling->spwndNext;
2292 }
2293
2294 /* link window as bottom sibling */
2295 IntLinkWindow(Window, ParentWindow, PrevSibling /*prev sibling*/);
2296 }
2297 else
2298 {
2299 /* link window as top sibling (but after topmost siblings) */
2300 PWINDOW_OBJECT InsertAfter, Sibling;
2301 if (!(dwExStyle & WS_EX_TOPMOST))
2302 {
2303 InsertAfter = NULL;
2304 Sibling = ParentWindow->spwndChild;
2305 while (Sibling && (Sibling->Wnd->ExStyle & WS_EX_TOPMOST))
2306 {
2307 InsertAfter = Sibling;
2308 Sibling = Sibling->spwndNext;
2309 }
2310 }
2311 else
2312 {
2313 InsertAfter = NULL;
2314 }
2315
2316 IntLinkWindow(Window, ParentWindow, InsertAfter /* prev sibling */);
2317 }
2318 }
2319
2320 /* Send the WM_CREATE message. */
2321 DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
2322 Result = co_IntSendMessage(Window->hSelf, WM_CREATE, 0, (LPARAM) &Cs);
2323
2324 if (Result == (LRESULT)-1)
2325 {
2326 /* FIXME: Cleanup. */
2327 DPRINT1("IntCreateWindowEx(): send CREATE message failed. No cleanup performed!\n");
2328 IntUnlinkWindow(Window);
2329 RETURN((PWND)0);
2330 }
2331
2332 IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window->Wnd, OBJID_WINDOW, 0);
2333
2334 /* By setting the flag below it can be examined to determine if the window
2335 was created successfully and a valid pwnd was passed back to caller since
2336 from here the function has to succeed. */
2337 Window->Wnd->state2 |= WNDS2_WMCREATEMSGPROCESSED;
2338
2339 /* Send move and size messages. */
2340 if (!(Window->state & WINDOWOBJECT_NEED_SIZE))
2341 {
2342 LONG lParam;
2343
2344 DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
2345
2346 if ((Window->Wnd->rcClient.right - Window->Wnd->rcClient.left) < 0 ||
2347 (Window->Wnd->rcClient.bottom - Window->Wnd->rcClient.top) < 0)
2348 {
2349 DPRINT("Sending bogus WM_SIZE\n");
2350 }
2351
2352 lParam = MAKE_LONG(Window->Wnd->rcClient.right -
2353 Window->Wnd->rcClient.left,
2354 Window->Wnd->rcClient.bottom -
2355 Window->Wnd->rcClient.top);
2356 co_IntSendMessage(Window->hSelf, WM_SIZE, SIZE_RESTORED,
2357 lParam);
2358
2359 DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
2360
2361 if (0 != (Wnd->style & WS_CHILD) && ParentWindow)
2362 {
2363 lParam = MAKE_LONG(Wnd->rcClient.left - ParentWindow->Wnd->rcClient.left,
2364 Wnd->rcClient.top - ParentWindow->Wnd->rcClient.top);
2365 }
2366 else
2367 {
2368 lParam = MAKE_LONG(Wnd->rcClient.left,
2369 Wnd->rcClient.top);
2370 }
2371
2372 co_IntSendMessage(Window->hSelf, WM_MOVE, 0, lParam);
2373
2374 /* Call WNDOBJ change procs */
2375 IntEngWindowChanged(Window, WOC_RGN_CLIENT);
2376 }
2377
2378 /* Show or maybe minimize or maximize the window. */
2379 if (Wnd->style & (WS_MINIMIZE | WS_MAXIMIZE))
2380 {
2381 RECTL NewPos;
2382 UINT16 SwFlag;
2383
2384 SwFlag = (Wnd->style & WS_MINIMIZE) ? SW_MINIMIZE :
2385 SW_MAXIMIZE;
2386
2387 co_WinPosMinMaximize(Window, SwFlag, &NewPos);
2388
2389 SwFlag = ((Wnd->style & WS_CHILD) || UserGetActiveWindow()) ?
2390 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :
2391 SWP_NOZORDER | SWP_FRAMECHANGED;
2392
2393 DPRINT("IntCreateWindow(): About to minimize/maximize\n");
2394 DPRINT("%d,%d %dx%d\n", NewPos.left, NewPos.top, NewPos.right, NewPos.bottom);
2395 co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top,
2396 NewPos.right, NewPos.bottom, SwFlag);
2397 }
2398
2399 /* Notify the parent window of a new child. */
2400 if ((Wnd->style & WS_CHILD) &&
2401 (!(Wnd->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow)
2402 {
2403 DPRINT("IntCreateWindow(): About to notify parent\n");
2404 co_IntSendMessage(ParentWindow->hSelf,
2405 WM_PARENTNOTIFY,
2406 MAKEWPARAM(WM_CREATE, Wnd->IDMenu),
2407 (LPARAM)Window->hSelf);
2408 }
2409
2410 if ((!hWndParent) && (!HasOwner))
2411 {
2412 DPRINT("Sending CREATED notify\n");
2413 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)hWnd);
2414 }
2415 else
2416 {
2417 DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow, HasOwner);
2418 }
2419
2420 /* Initialize and show the window's scrollbars */
2421 if (Wnd->style & WS_VSCROLL)
2422 {
2423 co_UserShowScrollBar(Window, SB_VERT, TRUE);
2424 }
2425 if (Wnd->style & WS_HSCROLL)
2426 {
2427 co_UserShowScrollBar(Window, SB_HORZ, TRUE);
2428 }
2429
2430 if (dwStyle & WS_VISIBLE)
2431 {
2432 if (Wnd->style & WS_MAXIMIZE)
2433 dwShowMode = SW_SHOW;
2434 else if (Wnd->style & WS_MINIMIZE)
2435 dwShowMode = SW_SHOWMINIMIZED;
2436
2437 DPRINT("IntCreateWindow(): About to show window\n");
2438 co_WinPosShowWindow(Window, dwShowMode);
2439
2440 if (Wnd->ExStyle & WS_EX_MDICHILD)
2441 {
2442 co_IntSendMessage(ParentWindow->hSelf, WM_MDIREFRESHMENU, 0, 0);
2443 /* ShowWindow won't activate child windows */
2444 co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
2445 }
2446 }
2447
2448 /* BugBoy Comments: if the window being created is a edit control, ATOM 0xCxxx,
2449 then my testing shows that windows (2k and XP) creates a CallProc for it immediately
2450 Dont understand why it does this. */
2451 if (ClassAtom == gpsi->atomSysClass[ICLS_EDIT])
2452 {
2453 PCALLPROCDATA CallProc;
2454 //CallProc = CreateCallProc(NULL, Wnd->lpfnWndProc, bUnicodeWindow, Wnd->ti->ppi);
2455 CallProc = CreateCallProc(NULL, Wnd->lpfnWndProc, Wnd->Unicode , Wnd->head.pti->ppi);
2456
2457 if (!CallProc)
2458 {
2459 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
2460 DPRINT1("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %x\n",hWnd);
2461 }
2462 else
2463 {
2464 UserAddCallProcToClass(Wnd->pcls, CallProc);
2465 }
2466 }
2467
2468 DPRINT("IntCreateWindow(): = %X\n", hWnd);
2469 DPRINT("WindowObject->SystemMenu = 0x%x\n", Window->SystemMenu);
2470 RETURN( Wnd);
2471
2472 CLEANUP:
2473 if (!_ret_ && Window && Window->Wnd && ti)
2474 co_UserDestroyWindow(Window);
2475 // UserFreeWindowInfo(ti, Window);
2476 if (Window)
2477 {
2478 UserDerefObjectCo(Window);
2479 UserDereferenceObject(Window);
2480 }
2481 if (ParentWindow) UserDerefObjectCo(ParentWindow);
2482 if (!_ret_ && ti != NULL)
2483 {
2484 if (Class != NULL)
2485 {
2486 IntDereferenceClass(Class,
2487 ti->pDeskInfo,
2488 ti->ppi);
2489 }
2490 }
2491 END_CLEANUP;
2492 }
2493
2494 HWND APIENTRY
2495 NtUserCreateWindowEx(DWORD dwExStyle,
2496 PUNICODE_STRING UnsafeClassName,
2497 PUNICODE_STRING UnsafeWindowName,
2498 DWORD dwStyle,
2499 LONG x,
2500 LONG y,
2501 LONG nWidth,
2502 LONG nHeight,
2503 HWND hWndParent,
2504 HMENU hMenu,
2505 HINSTANCE hInstance,
2506 LPVOID lpParam,
2507 DWORD dwShowMode,
2508 BOOL bUnicodeWindow,
2509 DWORD dwUnknown)
2510 {
2511 NTSTATUS Status;
2512 UNICODE_STRING WindowName;
2513 UNICODE_STRING ClassName;
2514 HWND NewWindow = NULL;
2515 PWND pNewWindow;
2516 DECLARE_RETURN(HWND);
2517
2518 DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
2519 UserEnterExclusive();
2520
2521 /* Get the class name (string or atom) */
2522 Status = MmCopyFromCaller(&ClassName, UnsafeClassName, sizeof(UNICODE_STRING));
2523 if (! NT_SUCCESS(Status))
2524 {
2525 SetLastNtError(Status);
2526 RETURN( NULL);
2527 }
2528 if (ClassName.Length != 0)
2529 {
2530 Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName);
2531 if (! NT_SUCCESS(Status))
2532 {
2533 SetLastNtError(Status);
2534 RETURN( NULL);
2535 }
2536 }
2537 else if (! IS_ATOM(ClassName.Buffer))
2538 {
2539 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2540 RETURN(NULL);
2541 }
2542
2543 /* safely copy the window name */
2544 if (NULL != UnsafeWindowName)
2545 {
2546 Status = IntSafeCopyUnicodeString(&WindowName, UnsafeWindowName);
2547 if (! NT_SUCCESS(Status))
2548 {
2549 if (! IS_ATOM(ClassName.Buffer))
2550 {
2551 ExFreePoolWithTag(ClassName.Buffer, TAG_STRING);
2552 }
2553 SetLastNtError(Status);
2554 RETURN( NULL);
2555 }
2556 }
2557 else
2558 {
2559 RtlInitUnicodeString(&WindowName, NULL);
2560 }
2561
2562 pNewWindow = co_IntCreateWindowEx( dwExStyle,
2563 &ClassName,
2564 &WindowName,
2565 dwStyle,
2566 x,
2567 y,
2568 nWidth,
2569 nHeight,
2570 hWndParent,
2571 hMenu,
2572 hInstance,
2573 lpParam,
2574 dwShowMode,
2575 bUnicodeWindow);
2576
2577 if (pNewWindow) NewWindow = UserHMGetHandle(pNewWindow);
2578
2579 if (WindowName.Buffer)
2580 {
2581 ExFreePoolWithTag(WindowName.Buffer, TAG_STRING);
2582 }
2583 if (! IS_ATOM(ClassName.Buffer))
2584 {
2585 ExFreePoolWithTag(ClassName.Buffer, TAG_STRING);
2586 }
2587
2588 RETURN( NewWindow);
2589
2590 CLEANUP:
2591 DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_);
2592 UserLeave();
2593 END_CLEANUP;
2594 }
2595
2596 /*
2597 * @unimplemented
2598 */
2599 HDWP APIENTRY
2600 NtUserDeferWindowPos(HDWP WinPosInfo,
2601 HWND Wnd,
2602 HWND WndInsertAfter,
2603 int x,
2604 int y,
2605 int cx,
2606 int cy,
2607 UINT Flags)
2608 {
2609 UNIMPLEMENTED
2610
2611 return 0;
2612 }
2613
2614
2615 BOOLEAN FASTCALL co_UserDestroyWindow(PWINDOW_OBJECT Window)
2616 {
2617 BOOLEAN isChild;
2618 PWND Wnd;
2619 HWND hWnd;
2620 PTHREADINFO ti;
2621
2622 ASSERT_REFS_CO(Window); // FIXME: temp hack?
2623
2624 hWnd = Window->hSelf;
2625
2626 Wnd = Window->Wnd;
2627
2628 if (!Wnd) return TRUE; // FIXME: Need to finish object rewrite or lock the thread when killing the window!
2629
2630 DPRINT("co_UserDestroyWindow \n");
2631
2632 /* Check for owner thread */
2633 if ( (Window->pti->pEThread != PsGetCurrentThread()) ||
2634 Wnd->head.pti != PsGetCurrentThreadWin32Thread() )
2635 {
2636 SetLastWin32Error(ERROR_ACCESS_DENIED);
2637 return FALSE;
2638 }
2639
2640 /* If window was created successfully and it is hooked */
2641 if ((Wnd->state2 & WNDS2_WMCREATEMSGPROCESSED) && (ISITHOOKED(WH_CBT)))
2642 {
2643 if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0)) return FALSE;
2644 }
2645
2646 /* Look whether the focus is within the tree of windows we will
2647 * be destroying.
2648 */
2649 if (!co_WinPosShowWindow(Window, SW_HIDE))
2650 {
2651 if (UserGetActiveWindow() == Window->hSelf)
2652 {
2653 co_WinPosActivateOtherWindow(Window);
2654 }
2655 }
2656
2657 if (Window->pti->MessageQueue->ActiveWindow == Window->hSelf)
2658 Window->pti->MessageQueue->ActiveWindow = NULL;
2659 if (Window->pti->MessageQueue->FocusWindow == Window->hSelf)
2660 Window->pti->MessageQueue->FocusWindow = NULL;
2661 if (Window->pti->MessageQueue->CaptureWindow == Window->hSelf)
2662 Window->pti->MessageQueue->CaptureWindow = NULL;
2663
2664 /*
2665 * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL
2666 */
2667
2668 ti = PsGetCurrentThreadWin32Thread();
2669
2670 if ((ti != NULL) & (ti->pDeskInfo != NULL))
2671 {
2672 if (ti->pDeskInfo->hShellWindow == hWnd)
2673 {
2674 DPRINT1("Destroying the ShellWindow!\n");
2675 ti->pDeskInfo->hShellWindow = NULL;
2676 }
2677 }
2678
2679 IntDereferenceMessageQueue(Window->pti->MessageQueue);
2680
2681 IntEngWindowChanged(Window, WOC_DELETE);
2682 isChild = (0 != (Wnd->style & WS_CHILD));
2683
2684 #if 0 /* FIXME */
2685
2686 if (isChild)
2687 {
2688 if (! USER_IsExitingThread(GetCurrentThreadId()))
2689 {
2690 send_parent_notify(hwnd, WM_DESTROY);
2691 }
2692 }
2693 else if (NULL != GetWindow(Wnd, GW_OWNER))
2694 {
2695 co_HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
2696 /* FIXME: clean up palette - see "Internals" p.352 */
2697 }
2698 #endif
2699
2700 if (!IntIsWindow(Window->hSelf))
2701 {
2702 return TRUE;
2703 }
2704
2705 /* Recursively destroy owned windows */
2706 if (! isChild)
2707 {
2708 for (;;)
2709 {
2710 BOOL GotOne = FALSE;
2711 HWND *Children;
2712 HWND *ChildHandle;
2713 PWINDOW_OBJECT Child, Desktop;
2714
2715 Desktop = IntIsDesktopWindow(Window) ? Window :
2716 UserGetWindowObject(IntGetDesktopWindow());
2717 Children = IntWinListChildren(Desktop);
2718
2719 if (Children)
2720 {
2721 for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
2722 {
2723 Child = UserGetWindowObject(*ChildHandle);
2724 if (Child == NULL)
2725 continue;
2726 if (Child->hOwner != Window->hSelf)
2727 {
2728 continue;
2729 }
2730
2731 if (IntWndBelongsToThread(Child, PsGetCurrentThreadWin32Thread()))
2732 {
2733 USER_REFERENCE_ENTRY ChildRef;
2734 UserRefObjectCo(Child, &ChildRef);//temp hack?
2735 co_UserDestroyWindow(Child);
2736 UserDerefObjectCo(Child);//temp hack?
2737
2738 GotOne = TRUE;
2739 continue;
2740 }
2741
2742 if (Child->hOwner != NULL)
2743 {
2744 Child->hOwner = NULL;
2745 Child->Wnd->spwndOwner = NULL;
2746 }
2747
2748 }
2749 ExFreePool(Children);
2750 }
2751 if (! GotOne)
2752 {
2753 break;
2754 }
2755 }
2756 }
2757
2758 if (!IntIsWindow(Window->hSelf))
2759 {
2760 return TRUE;
2761 }
2762
2763 /* Destroy the window storage */
2764 co_UserFreeWindow(Window, PsGetCurrentProcessWin32Process(), PsGetCurrentThreadWin32Thread(), TRUE);
2765
2766 return TRUE;
2767 }
2768
2769
2770 /*
2771 * @implemented
2772 */
2773 BOOLEAN APIENTRY
2774 NtUserDestroyWindow(HWND Wnd)
2775 {
2776 PWINDOW_OBJECT Window;
2777 DECLARE_RETURN(BOOLEAN);
2778 BOOLEAN ret;
2779 USER_REFERENCE_ENTRY Ref;
2780
2781 DPRINT("Enter NtUserDestroyWindow\n");
2782 UserEnterExclusive();
2783
2784 if (!(Window = UserGetWindowObject(Wnd)))
2785 {
2786 RETURN(FALSE);
2787 }
2788
2789 UserRefObjectCo(Window, &Ref);//faxme: dunno if win should be reffed during destroy..
2790 ret = co_UserDestroyWindow(Window);
2791 UserDerefObjectCo(Window);//faxme: dunno if win should be reffed during destroy..
2792
2793 RETURN(ret);
2794
2795 CLEANUP:
2796 DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_);
2797 UserLeave();
2798 END_CLEANUP;
2799 }
2800
2801
2802
2803 /*
2804 * @unimplemented
2805 */
2806 DWORD
2807 APIENTRY
2808 NtUserDrawMenuBarTemp(
2809 HWND hWnd,
2810 HDC hDC,
2811 PRECT hRect,
2812 HMENU hMenu,
2813 HFONT hFont)
2814 {
2815 /* we'll use this function just for caching the menu bar */
2816 UNIMPLEMENTED
2817 return 0;
2818 }
2819
2820
2821 /*
2822 * @unimplemented
2823 */
2824 DWORD APIENTRY
2825 NtUserEndDeferWindowPosEx(DWORD Unknown0,
2826 DWORD Unknown1)
2827 {
2828 UNIMPLEMENTED
2829
2830 return 0;
2831 }
2832
2833
2834 /*
2835 * FillWindow: Called from User; Dialog, Edit and ListBox procs during a WM_ERASEBKGND.
2836 */
2837 /*
2838 * @unimplemented
2839 */
2840 BOOL APIENTRY
2841 NtUserFillWindow(HWND hWndPaint,
2842 HWND hWndPaint1,
2843 HDC hDC,
2844 HBRUSH hBrush)
2845 {
2846 UNIMPLEMENTED
2847
2848 return 0;
2849 }
2850
2851
2852 static HWND FASTCALL
2853 IntFindWindow(PWINDOW_OBJECT Parent,
2854 PWINDOW_OBJECT ChildAfter,
2855 RTL_ATOM ClassAtom,
2856 PUNICODE_STRING WindowName)
2857 {
2858 BOOL CheckWindowName;
2859 HWND *List, *phWnd;
2860 HWND Ret = NULL;
2861
2862 ASSERT(Parent);
2863
2864 CheckWindowName = WindowName->Length != 0;
2865
2866 if((List = IntWinListChildren(Parent)))
2867 {
2868 phWnd = List;
2869 if(ChildAfter)
2870 {
2871 /* skip handles before and including ChildAfter */
2872 while(*phWnd && (*(phWnd++) != ChildAfter->hSelf))
2873 ;
2874 }
2875
2876 /* search children */
2877 while(*phWnd)
2878 {
2879 PWINDOW_OBJECT Child;
2880 if(!(Child = UserGetWindowObject(*(phWnd++))))
2881 {
2882 continue;
2883 }
2884
2885 /* Do not send WM_GETTEXT messages in the kernel mode version!
2886 The user mode version however calls GetWindowText() which will
2887 send WM_GETTEXT messages to windows belonging to its processes */
2888 if((!CheckWindowName || !RtlCompareUnicodeString(WindowName, &(Child->Wnd->strName), TRUE)) &&
2889 (!ClassAtom || Child->Wnd->pcls->atomClassName == ClassAtom))
2890 {
2891 Ret = Child->hSelf;
2892 break;
2893 }
2894
2895 }
2896 ExFreePool(List);
2897 }
2898
2899 return Ret;
2900 }
2901
2902 /*
2903 * FUNCTION:
2904 * Searches a window's children for a window with the specified
2905 * class and name
2906 * ARGUMENTS:
2907 * hwndParent = The window whose childs are to be searched.
2908 * NULL = desktop
2909 * HWND_MESSAGE = message-only windows
2910 *
2911 * hwndChildAfter = Search starts after this child window.
2912 * NULL = start from beginning
2913 *
2914 * ucClassName = Class name to search for
2915 * Reguired parameter.
2916 *
2917 * ucWindowName = Window name
2918 * ->Buffer == NULL = don't care
2919 *
2920 * RETURNS:
2921 * The HWND of the window if it was found, otherwise NULL
2922 */
2923 /*
2924 * @implemented
2925 */
2926 HWND APIENTRY
2927 NtUserFindWindowEx(HWND hwndParent,
2928 HWND hwndChildAfter,
2929 PUNICODE_STRING ucClassName,
2930 PUNICODE_STRING ucWindowName,
2931 DWORD dwUnknown)
2932 {
2933 PWINDOW_OBJECT Parent, ChildAfter;
2934 UNICODE_STRING ClassName = {0}, WindowName = {0};
2935 HWND Desktop, Ret = NULL;
2936 RTL_ATOM ClassAtom = (RTL_ATOM)0;
2937 DECLARE_RETURN(HWND);
2938
2939 DPRINT("Enter NtUserFindWindowEx\n");
2940 UserEnterShared();
2941
2942 if (ucClassName != NULL || ucWindowName != NULL)
2943 {
2944 _SEH2_TRY
2945 {
2946 if (ucClassName != NULL)
2947 {
2948 ClassName = ProbeForReadUnicodeString(ucClassName);
2949 if (ClassName.Length != 0)
2950 {
2951 ProbeForRead(ClassName.Buffer,
2952 ClassName.Length,
2953 sizeof(WCHAR));
2954 }
2955 else if (!IS_ATOM(ClassName.Buffer))
2956 {
2957 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2958 _SEH2_LEAVE;
2959 }
2960
2961 if (!IntGetAtomFromStringOrAtom(&ClassName,
2962 &ClassAtom))
2963 {
2964 _SEH2_LEAVE;
2965 }
2966 }
2967
2968 if (ucWindowName != NULL)
2969 {
2970 WindowName = ProbeForReadUnicodeString(ucWindowName);
2971 if (WindowName.Length != 0)
2972 {
2973 ProbeForRead(WindowName.Buffer,
2974 WindowName.Length,
2975 sizeof(WCHAR));
2976 }
2977 }
2978 }
2979 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2980 {
2981 SetLastNtError(_SEH2_GetExceptionCode());
2982 _SEH2_YIELD(RETURN(NULL));
2983 }
2984 _SEH2_END;
2985
2986 if (ucClassName != NULL)
2987 {
2988 if (ClassName.Length == 0 && ClassName.Buffer != NULL &&
2989 !IS_ATOM(ClassName.Buffer))
2990 {
2991 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2992 RETURN(NULL);
2993 }
2994 else if (ClassAtom == (RTL_ATOM)0)
2995 {
2996 /* LastError code was set by IntGetAtomFromStringOrAtom */
2997 RETURN(NULL);
2998 }
2999 }
3000 }
3001
3002 Desktop = IntGetCurrentThreadDesktopWindow();
3003
3004 if(hwndParent == NULL)
3005 hwndParent = Desktop;
3006 else if(hwndParent == HWND_MESSAGE)
3007 {
3008 hwndParent = IntGetMessageWindow();
3009 }
3010
3011 if(!(Parent = UserGetWindowObject(hwndParent)))
3012 {
3013 RETURN( NULL);
3014 }
3015
3016 ChildAfter = NULL;
3017 if(hwndChildAfter && !(ChildAfter = UserGetWindowObject(hwndChildAfter)))
3018 {
3019 RETURN( NULL);
3020 }
3021
3022 _SEH2_TRY
3023 {
3024 if(Parent->hSelf == Desktop)
3025 {
3026 HWND *List, *phWnd;
3027 PWINDOW_OBJECT TopLevelWindow;
3028 BOOLEAN CheckWindowName;
3029 BOOLEAN WindowMatches;
3030 BOOLEAN ClassMatches;
3031
3032 /* windows searches through all top-level windows if the parent is the desktop
3033 window */
3034
3035 if((List = IntWinListChildren(Parent)))
3036 {
3037 phWnd = List;
3038
3039 if(ChildAfter)
3040 {
3041 /* skip handles before and including ChildAfter */
3042 while(*phWnd && (*(phWnd++) != ChildAfter->hSelf))
3043 ;
3044 }
3045
3046 CheckWindowName = WindowName.Length != 0;
3047
3048 /* search children */
3049 while(*phWnd)
3050 {
3051 if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
3052 {
3053 continue;
3054 }
3055
3056 /* Do not send WM_GETTEXT messages in the kernel mode version!
3057 The user mode version however calls GetWindowText() which will
3058 send WM_GETTEXT messages to windows belonging to its processes */
3059 WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
3060 &WindowName, &TopLevelWindow->Wnd->strName, TRUE);
3061 ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
3062 ClassAtom == TopLevelWindow->Wnd->pcls->atomClassName;
3063
3064 if (WindowMatches && ClassMatches)
3065 {
3066 Ret = TopLevelWindow->hSelf;
3067 break;
3068 }
3069
3070 if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
3071 {
3072 /* window returns the handle of the top-level window, in case it found
3073 the child window */
3074 Ret = TopLevelWindow->hSelf;
3075 break;
3076 }
3077
3078 }
3079 ExFreePool(List);
3080 }
3081 }
3082 else
3083 Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
3084
3085 #if 0
3086
3087 if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
3088 {
3089 /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
3090 search the message-only windows. Should this also be done if
3091 Parent is the desktop window??? */
3092 PWINDOW_OBJECT MsgWindows;
3093
3094 if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
3095 {
3096 Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
3097 }
3098 }
3099 #endif
3100 }
3101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3102 {
3103 SetLastNtError(_SEH2_GetExceptionCode());
3104 Ret = NULL;
3105 }
3106 _SEH2_END;
3107
3108 RETURN( Ret);
3109
3110 CLEANUP:
3111 DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_);
3112 UserLeave();
3113 END_CLEANUP;
3114 }
3115
3116
3117 /*
3118 * @unimplemented
3119 */
3120 BOOL APIENTRY
3121 NtUserFlashWindowEx(IN PFLASHWINFO pfwi)
3122 {
3123 UNIMPLEMENTED
3124
3125 return 0;
3126 }
3127
3128
3129 /*
3130 * @implemented
3131 */
3132 PWINDOW_OBJECT FASTCALL UserGetAncestor(PWINDOW_OBJECT Wnd, UINT Type)
3133 {
3134 PWINDOW_OBJECT WndAncestor, Parent;
3135
3136 if (Wnd->hSelf == IntGetDesktopWindow())
3137 {
3138 return NULL;
3139 }
3140
3141 switch (Type)
3142 {
3143 case GA_PARENT:
3144 {
3145 WndAncestor = Wnd->spwndParent;
3146 break;
3147 }
3148
3149 case GA_ROOT:
3150 {
3151 WndAncestor = Wnd;
3152 Parent = NULL;
3153
3154 for(;;)
3155 {
3156 if(!(Parent = WndAncestor->spwndParent))
3157 {
3158 break;
3159 }
3160 if(IntIsDesktopWindow(Parent))
3161 {
3162 break;
3163 }
3164
3165 WndAncestor = Parent;
3166 }
3167 break;
3168 }
3169
3170 case GA_ROOTOWNER:
3171 {
3172 WndAncestor = Wnd;
3173
3174 for (;;)
3175 {
3176 PWINDOW_OBJECT Parent, Old;
3177
3178 Old = WndAncestor;
3179 Parent = IntGetParent(WndAncestor);
3180
3181 if (!Parent)
3182 {
3183 break;
3184 }
3185
3186 //temp hack
3187 // UserDereferenceObject(Parent);
3188
3189 WndAncestor = Parent;
3190 }
3191 break;
3192 }
3193
3194 default:
3195 {
3196 return NULL;
3197 }
3198 }
3199
3200 return WndAncestor;
3201 }
3202
3203 /*
3204 * @implemented
3205 */
3206 HWND APIENTRY
3207 NtUserGetAncestor(HWND hWnd, UINT Type)
3208 {
3209 PWINDOW_OBJECT Window, Ancestor;
3210 DECLARE_RETURN(HWND);
3211
3212 DPRINT("Enter NtUserGetAncestor\n");
3213 UserEnterExclusive();
3214
3215 if (!(Window = UserGetWindowObject(hWnd)))
3216 {
3217 RETURN(NULL);
3218 }
3219
3220 Ancestor = UserGetAncestor(Window, Type);
3221 /* faxme: can UserGetAncestor ever return NULL for a valid window? */
3222
3223 RETURN(Ancestor ? Ancestor->hSelf : NULL);
3224
3225 CLEANUP:
3226 DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_);
3227 UserLeave();
3228 END_CLEANUP;
3229 }
3230
3231
3232 BOOL
3233 APIENTRY
3234 NtUserGetComboBoxInfo(
3235 HWND hWnd,
3236 PCOMBOBOXINFO pcbi)
3237 {
3238 PWINDOW_OBJECT Wnd;
3239 DECLARE_RETURN(BOOL);
3240
3241 DPRINT("Enter NtUserGetComboBoxInfo\n");
3242 UserEnterShared();
3243
3244 if (!(Wnd = UserGetWindowObject(hWnd)))
3245 {
3246 RETURN( FALSE );
3247 }
3248 _SEH2_TRY
3249 {
3250 if(pcbi)
3251 {
3252 ProbeForWrite(pcbi,
3253 sizeof(COMBOBOXINFO),
3254 1);
3255 }
3256 }
3257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3258 {
3259 SetLastNtError(_SEH2_GetExceptionCode());
3260 _SEH2_YIELD(RETURN(FALSE));
3261 }
3262 _SEH2_END;
3263
3264 // Pass the user pointer, it was already probed.
3265 RETURN( (BOOL) co_IntSendMessage( Wnd->hSelf, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
3266
3267 CLEANUP:
3268 DPRINT("Leave NtUserGetComboBoxInfo, ret=%i\n",_ret_);
3269 UserLeave();
3270 END_CLEANUP;
3271 }
3272
3273
3274 /*
3275 * @implemented
3276 */
3277 DWORD APIENTRY
3278 NtUserGetInternalWindowPos( HWND hWnd,
3279 LPRECT rectWnd,
3280 LPPOINT ptIcon)
3281 {
3282 PWINDOW_OBJECT Window;
3283 PWND Wnd;
3284 DWORD Ret = 0;
3285 BOOL Hit = FALSE;
3286 WINDOWPLACEMENT wndpl;
3287
3288 UserEnterShared();
3289
3290 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
3291 {
3292 Hit = FALSE;
3293 goto Exit;
3294 }
3295 Wnd = Window->Wnd;
3296
3297 _SEH2_TRY
3298 {
3299 if(rectWnd)
3300 {
3301 ProbeForWrite(rectWnd,
3302 sizeof(RECT),
3303 1);
3304 }
3305 if(ptIcon)
3306 {
3307 ProbeForWrite(ptIcon,
3308 sizeof(POINT),
3309 1);
3310 }
3311
3312 }
3313 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3314 {
3315 SetLastNtError(_SEH2_GetExceptionCode());
3316 Hit = TRUE;
3317 }
3318 _SEH2_END;
3319
3320 wndpl.length = sizeof(WINDOWPLACEMENT);
3321
3322 if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
3323 {
3324 _SEH2_TRY
3325 {
3326 if (rectWnd)
3327 {
3328 RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
3329 }
3330 if (ptIcon)
3331 {
3332 RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
3333 }
3334
3335 }
3336 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3337 {
3338 SetLastNtError(_SEH2_GetExceptionCode());
3339 Hit = TRUE;
3340 }
3341 _SEH2_END;
3342
3343 if (!Hit) Ret = wndpl.showCmd;
3344 }
3345 Exit:
3346 UserLeave();
3347 return Ret;
3348 }
3349
3350 DWORD
3351 APIENTRY
3352 NtUserGetListBoxInfo(
3353 HWND hWnd)
3354 {
3355 PWINDOW_OBJECT Wnd;
3356 DECLARE_RETURN(DWORD);
3357
3358 DPRINT("Enter NtUserGetListBoxInfo\n");
3359 UserEnterShared();
3360
3361 if (!(Wnd = UserGetWindowObject(hWnd)))
3362 {
3363 RETURN( 0 );
3364 }
3365
3366 RETURN( (DWORD) co_IntSendMessage( Wnd->hSelf, LB_GETLISTBOXINFO, 0, 0 ));
3367
3368 CLEANUP:
3369 DPRINT("Leave NtUserGetListBoxInfo, ret=%i\n",_ret_);
3370 UserLeave();
3371 END_CLEANUP;
3372 }
3373
3374
3375 HWND FASTCALL
3376 co_UserSetParent(HWND hWndChild, HWND hWndNewParent)
3377 {
3378 PWINDOW_OBJECT Wnd = NULL, WndParent = NULL, WndOldParent;
3379 HWND hWndOldParent = NULL;
3380 USER_REFERENCE_ENTRY Ref, ParentRef;
3381
3382 if (IntIsBroadcastHwnd(hWndChild) || IntIsBroadcastHwnd(hWndNewParent))
3383 {
3384 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3385 return( NULL);
3386 }
3387
3388 if (hWndChild == IntGetDesktopWindow())
3389 {
3390 SetLastWin32Error(ERROR_ACCESS_DENIED);
3391 return( NULL);
3392 }
3393
3394 if (hWndNewParent)
3395 {
3396 if (!(WndParent = UserGetWindowObject(hWndNewParent)))
3397 {
3398 return( NULL);
3399 }
3400 }
3401 else
3402 {
3403 if (!(WndParent = UserGetWindowObject(IntGetDesktopWindow())))
3404 {
3405 return( NULL);
3406 }
3407 }
3408
3409 if (!(Wnd = UserGetWindowObject(hWndChild)))
3410 {
3411 return( NULL);
3412 }
3413
3414 UserRefObjectCo(Wnd, &Ref);
3415 UserRefObjectCo(WndParent, &ParentRef);
3416
3417 WndOldParent = co_IntSetParent(Wnd, WndParent);
3418
3419 UserDerefObjectCo(WndParent);
3420 UserDerefObjectCo(Wnd);
3421
3422 if (WndOldParent)
3423 {
3424 hWndOldParent = WndOldParent->hSelf;
3425 UserDereferenceObject(WndOldParent);
3426 }
3427
3428 return( hWndOldParent);
3429 }
3430
3431 /*
3432 * NtUserSetParent
3433 *
3434 * The NtUserSetParent function changes the parent window of the specified
3435 * child window.
3436 *
3437 * Remarks
3438 * The new parent window and the child window must belong to the same
3439 * application. If the window identified by the hWndChild parameter is
3440 * visible, the system performs the appropriate redrawing and repainting.
3441 * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
3442 * or WS_POPUP window styles of the window whose parent is being changed.
3443 *
3444 * Status
3445 * @implemented
3446 */
3447
3448 HWND APIENTRY
3449 NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
3450 {
3451 DECLARE_RETURN(HWND);
3452
3453 DPRINT("Enter NtUserSetParent\n");
3454 UserEnterExclusive();
3455
3456 /*
3457 Check Parent first from user space, set it here.
3458 */
3459 if (!hWndNewParent)
3460 {
3461 hWndNewParent = IntGetDesktopWindow();
3462 }
3463 else if (hWndNewParent == HWND_MESSAGE)
3464 {
3465 hWndNewParent = IntGetMessageWindow();
3466 }
3467
3468 RETURN( co_UserSetParent(hWndChild, hWndNewParent));
3469
3470 CLEANUP:
3471 DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_);
3472 UserLeave();
3473 END_CLEANUP;
3474 }
3475
3476 /*
3477 * UserGetShellWindow
3478 *
3479 * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3480 *
3481 * Status
3482 * @implemented
3483 */
3484 HWND FASTCALL UserGetShellWindow(VOID)
3485 {
3486 PWINSTATION_OBJECT WinStaObject;
3487 HWND Ret;
3488
3489 NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
3490 KernelMode,
3491 0,
3492 &WinStaObject);
3493
3494 if (!NT_SUCCESS(Status))
3495 {
3496 SetLastNtError(Status);
3497 return( (HWND)0);
3498 }
3499
3500 Ret = (HWND)WinStaObject->ShellWindow;
3501
3502 ObDereferenceObject(WinStaObject);
3503 return( Ret);
3504 }
3505
3506 /*
3507 * NtUserSetShellWindowEx
3508 *
3509 * This is undocumented function to set global shell window. The global
3510 * shell window has special handling of window position.
3511 *
3512 * Status
3513 * @implemented
3514 */
3515 BOOL APIENTRY
3516 NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
3517 {
3518 PWINSTATION_OBJECT WinStaObject;
3519 PWINDOW_OBJECT WndShell;
3520 DECLARE_RETURN(BOOL);
3521 USER_REFERENCE_ENTRY Ref;
3522 NTSTATUS Status;
3523 PTHREADINFO ti;
3524
3525 DPRINT("Enter NtUserSetShellWindowEx\n");
3526 UserEnterExclusive();
3527
3528 if (!(WndShell = UserGetWindowObject(hwndShell)))
3529 {
3530 RETURN(FALSE);
3531 }
3532
3533 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
3534 KernelMode,
3535 0,
3536 &WinStaObject);
3537
3538 if (!NT_SUCCESS(Status))
3539 {
3540 SetLastNtError(Status);
3541 RETURN( FALSE);
3542 }
3543
3544 /*
3545 * Test if we are permitted to change the shell window.
3546 */
3547 if (WinStaObject->ShellWindow)
3548 {
3549 ObDereferenceObject(WinStaObject);
3550 RETURN( FALSE);
3551 }
3552
3553 /*
3554 * Move shell window into background.
3555 */
3556 if (hwndListView && hwndListView != hwndShell)
3557 {
3558 /*
3559 * Disabled for now to get Explorer working.
3560 * -- Filip, 01/nov/2003
3561 */
3562 #if 0
3563 co_WinPosSetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
3564 #endif
3565
3566 if (UserGetWindowLong(hwndListView, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
3567 {
3568 ObDereferenceObject(WinStaObject);
3569 RETURN( FALSE);
3570 }
3571 }
3572
3573 if (UserGetWindowLong(hwndShell, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
3574 {
3575 ObDereferenceObject(WinStaObject);
3576 RETURN( FALSE);
3577 }
3578
3579 UserRefObjectCo(WndShell, &Ref);
3580 co_WinPosSetWindowPos(WndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
3581
3582 WinStaObject->ShellWindow = hwndShell;
3583 WinStaObject->ShellListView = hwndListView;
3584
3585 ti = GetW32ThreadInfo();
3586 if (ti->pDeskInfo) ti->pDeskInfo->hShellWindow = hwndShell;
3587
3588 UserDerefObjectCo(WndShell);
3589
3590 ObDereferenceObject(WinStaObject);
3591 RETURN( TRUE);
3592
3593 CLEANUP:
3594 DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
3595 UserLeave();
3596 END_CLEANUP;
3597 }
3598
3599 /*
3600 * NtUserGetSystemMenu
3601 *
3602 * The NtUserGetSystemMenu function allows the application to access the
3603 * window menu (also known as the system menu or the control menu) for
3604 * copying and modifying.
3605 *
3606 * Parameters
3607 * hWnd
3608 * Handle to the window that will own a copy of the window menu.
3609 * bRevert
3610 * Specifies the action to be taken. If this parameter is FALSE,
3611 * NtUserGetSystemMenu returns a handle to the copy of the window menu
3612 * currently in use. The copy is initially identical to the window menu
3613 * but it can be modified.
3614 * If this parameter is TRUE, GetSystemMenu resets the window menu back
3615 * to the default state. The previous window menu, if any, is destroyed.
3616 *
3617 * Return Value
3618 * If the bRevert parameter is FALSE, the return value is a handle to a
3619 * copy of the window menu. If the bRevert parameter is TRUE, the return
3620 * value is NULL.
3621 *
3622 * Status
3623 * @implemented
3624 */
3625
3626 HMENU APIENTRY
3627 NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
3628 {
3629 PWINDOW_OBJECT Window;
3630 PMENU_OBJECT Menu;
3631 DECLARE_RETURN(HMENU);
3632
3633 DPRINT("Enter NtUserGetSystemMenu\n");
3634 UserEnterShared();
3635
3636 if (!(Window = UserGetWindowObject(hWnd)))
3637 {
3638 RETURN(NULL);
3639 }
3640
3641 if (!(Menu = IntGetSystemMenu(Window, bRevert, FALSE)))
3642 {
3643 RETURN(NULL);
3644 }
3645
3646 RETURN(Menu->MenuInfo.Self);
3647
3648 CLEANUP:
3649 DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_);
3650 UserLeave();
3651 END_CLEANUP;
3652 }
3653
3654 /*
3655 * NtUserSetSystemMenu
3656 *
3657 * Status
3658 * @implemented
3659 */
3660
3661 BOOL APIENTRY
3662 NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
3663 {
3664 BOOL Result = FALSE;
3665 PWINDOW_OBJECT Window;
3666 PMENU_OBJECT Menu;
3667 DECLARE_RETURN(BOOL);
3668
3669 DPRINT("Enter NtUserSetSystemMenu\n");
3670 UserEnterExclusive();
3671
3672 if (!(Window = UserGetWindowObject(hWnd)))
3673 {
3674 RETURN( FALSE);
3675 }
3676
3677 if (hMenu)
3678 {
3679 /*
3680 * Assign new menu handle.
3681 */
3682 if (!(Menu = UserGetMenuObject(hMenu)))
3683 {
3684 RETURN( FALSE);
3685 }
3686
3687 Result = IntSetSystemMenu(Window, Menu);
3688 }
3689
3690 RETURN( Result);
3691
3692 CLEANUP:
3693 DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_);
3694 UserLeave();
3695 END_CLEANUP;
3696 }
3697
3698 HWND FASTCALL
3699 UserGetWindow(HWND hWnd, UINT Relationship)
3700 {
3701 PWINDOW_OBJECT Parent, Window;
3702 HWND hWndResult = NULL;
3703
3704 if (!(Window = UserGetWindowObject(hWnd)))
3705 return NULL;
3706
3707 switch (Relationship)
3708 {
3709 case GW_HWNDFIRST:
3710 if((Parent = Window->spwndParent))
3711 {
3712 if (Parent->spwndChild)
3713 hWndResult = Parent->spwndChild->hSelf;
3714 }
3715 break;
3716
3717 case GW_HWNDLAST:
3718 if((Parent = Window->spwndParent))
3719 {
3720 if (Parent->spwndChild)
3721 {
3722 Window = Parent->spwndChild;
3723 if(Window)
3724 {
3725 while(Window->spwndNext)
3726 Window = Window->spwndNext;
3727 }
3728 hWndResult = Window->hSelf;
3729 }
3730 }
3731 break;
3732
3733 case GW_HWNDNEXT:
3734 if (Window->spwndNext)
3735 hWndResult = Window->spwndNext->hSelf;
3736 break;
3737
3738 case GW_HWNDPREV:
3739 if (Window->spwndPrev)
3740 hWndResult = Window->spwndPrev->hSelf;
3741 break;
3742
3743 case GW_OWNER:
3744 if((Parent = UserGetWindowObject(Window->hOwner)))
3745 {
3746 hWndResult = Parent->hSelf;
3747 }
3748 break;
3749 case GW_CHILD:
3750 if (Window->spwndChild)
3751 hWndResult = Window->spwndChild->hSelf;
3752 break;
3753 }
3754
3755 return hWndResult;
3756 }
3757
3758 /*
3759 * NtUserGetWindowLong
3760 *
3761 * The NtUserGetWindowLong function retrieves information about the specified
3762 * window. The function also retrieves the 32-bit (long) value at the
3763 * specified offset into the extra window memory.
3764 *
3765 * Status
3766 * @implemented
3767 */
3768
3769 LONG FASTCALL
3770 UserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
3771 {
3772 PWINDOW_OBJECT Window, Parent;
3773 PWND Wnd;
3774 LONG Result = 0;
3775
3776 DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
3777
3778 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
3779 {
3780 return 0;
3781 }
3782
3783 Wnd = Window->Wnd;
3784
3785 /*
3786 * WndProc is only available to the owner process
3787 */
3788 if (GWL_WNDPROC == Index
3789 && Window->pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
3790 {
3791 SetLastWin32Error(ERROR_ACCESS_DENIED);
3792 return 0;
3793 }
3794
3795 if ((INT)Index >= 0)
3796 {
3797 if ((Index + sizeof(LONG)) > Window->Wnd->cbwndExtra)
3798 {
3799 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3800 return 0;
3801 }
3802 Result = *((LONG *)((PCHAR)(Window->Wnd + 1) + Index));
3803 }
3804 else
3805 {
3806 switch (Index)
3807 {
3808 case GWL_EXSTYLE:
3809 Result = Wnd->ExStyle;
3810 break;
3811
3812 case GWL_STYLE:
3813 Result = Wnd->style;
3814 break;
3815
3816 case GWL_WNDPROC:
3817 Result = (LONG)IntGetWindowProc(Wnd, Ansi);
3818 break;
3819
3820 case GWL_HINSTANCE:
3821 Result = (LONG) Wnd->hModule;
3822 break;
3823
3824 case GWL_HWNDPARENT:
3825 Parent = Window->spwndParent;
3826 if(Parent)
3827 {
3828 if (Parent && Parent->hSelf == IntGetDesktopWindow())
3829 Result = (LONG) UserGetWindow(Window->hSelf, GW_OWNER);
3830 else
3831 Result = (LONG) Parent->hSelf;
3832 }
3833 break;
3834
3835 case GWL_ID:
3836 Result = (LONG) Wnd->IDMenu;
3837 break;
3838
3839 case GWL_USERDATA:
3840 Result = Wnd->dwUserData;
3841 break;
3842
3843 default:
3844 DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
3845 SetLastWin32Error(ERROR_INVALID_PARAMETER);
3846 Result = 0;
3847 break;
3848 }
3849 }
3850
3851 return Result;
3852 }
3853
3854 LONG FASTCALL
3855 co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
3856 {
3857 PWINDOW_OBJECT Window, Parent;
3858 PWND Wnd;
3859 PWINSTATION_OBJECT WindowStation;
3860 LONG OldValue;
3861 STYLESTRUCT Style;
3862
3863 if (hWnd == IntGetDesktopWindow())
3864 {
3865 SetLastWin32Error(STATUS_ACCESS_DENIED);
3866 return( 0);
3867 }
3868
3869 if (!(Window = UserGetWindowObject(hWnd)))
3870 {
3871 return( 0);
3872 }
3873
3874 Wnd = Window->Wnd;
3875
3876 if (!Wnd) return 0; // No go on zero.
3877
3878 if ((INT)Index >= 0)
3879 {
3880 if ((Index + sizeof(LONG)) > Wnd->cbwndExtra)
3881 {
3882 SetLastWin32Error(ERROR_INVALID_INDEX);
3883 return( 0);
3884 }
3885
3886 OldValue = *((LONG *)((PCHAR)(Wnd + 1) + Index));
3887 /*
3888 if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
3889 {
3890 OldValue = (LONG)IntSetWindowProc( Wnd,
3891 (WNDPROC)NewValue,
3892 Ansi);
3893 if (!OldValue) return 0;
3894 }
3895 */
3896 *((LONG *)((PCHAR)(Wnd + 1) + Index)) = NewValue;
3897 }
3898 else
3899 {
3900 switch (Index)
3901 {
3902 case GWL_EXSTYLE:
3903 OldValue = (LONG) Wnd->ExStyle;
3904 Style.styleOld = OldValue;
3905 Style.styleNew = NewValue;
3906
3907 /*
3908 * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3909 */
3910 WindowStation = Window->pti->rpdesk->rpwinstaParent;
3911 if(WindowStation)
3912 {
3913 if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3914 Style.styleNew &= ~WS_EX_TOPMOST;
3915 }
3916
3917 co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3918 Wnd->ExStyle = (DWORD)Style.styleNew;
3919 co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3920 break;
3921
3922 case GWL_STYLE:
3923 OldValue = (LONG) Wnd->style;
3924 Style.styleOld = OldValue;
3925 Style.styleNew = NewValue;
3926 co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3927 Wnd->style = (DWORD)Style.styleNew;
3928 co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3929 break;
3930
3931 case GWL_WNDPROC:
3932 {
3933 if ( Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
3934 Wnd->fnid & FNID_FREED)
3935 {
3936 SetLastWin32Error(ERROR_ACCESS_DENIED);
3937 return( 0);
3938 }
3939 OldValue = (LONG)IntSetWindowProc(Wnd,
3940 (WNDPROC)NewValue,
3941 Ansi);
3942 break;
3943 }
3944
3945 case GWL_HINSTANCE:
3946 OldValue = (LONG) Wnd->hModule;
3947 Wnd->hModule = (HINSTANCE) NewValue;
3948 break;
3949
3950 case GWL_HWNDPARENT:
3951 Parent = Window->spwndParent;
3952 if (Parent && (Parent->hSelf == IntGetDesktopWindow()))
3953 OldValue = (LONG) IntSetOwner(Window->hSelf, (HWND) NewValue);
3954 else
3955 OldValue = (LONG) co_UserSetParent(Window->hSelf, (HWND) NewValue);
3956 break;
3957
3958 case GWL_ID:
3959 OldValue = (LONG) Wnd->IDMenu;
3960 Wnd->IDMenu = (UINT) NewValue;
3961 break;
3962
3963 case GWL_USERDATA:
3964 OldValue = Wnd->dwUserData;
3965 Wnd->dwUserData = NewValue;
3966 break;
3967
3968 default:
3969 DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
3970 SetLastWin32Error(ERROR_INVALID_INDEX);
3971 OldValue = 0;
3972 break;
3973 }
3974 }
3975
3976 return( OldValue);
3977 }
3978
3979 /*
3980 * NtUserSetWindowLong
3981 *
3982 * The NtUserSetWindowLong function changes an attribute of the specified
3983 * window. The function also sets the 32-bit (long) value at the specified
3984 * offset into the extra window memory.
3985 *
3986 * Status
3987 * @implemented
3988 */
3989
3990 LONG APIENTRY
3991 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
3992 {
3993 DECLARE_RETURN(LONG);
3994
3995 DPRINT("Enter NtUserSetWindowLong\n");
3996 UserEnterExclusive();
3997
3998 RETURN( co_UserSetWindowLong(hWnd, Index, NewValue, Ansi));
3999
4000 CLEANUP:
4001 DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_);
4002 UserLeave();
4003 END_CLEANUP;
4004 }
4005
4006 /*
4007 * NtUserSetWindowWord
4008 *
4009 * Legacy function similar to NtUserSetWindowLong.
4010 *
4011 * Status
4012 * @implemented
4013 */
4014
4015 WORD APIENTRY
4016 NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
4017 {
4018 PWINDOW_OBJECT Window;
4019 WORD OldValue;
4020 DECLARE_RETURN(WORD);
4021
4022 DPRINT("Enter NtUserSetWindowWord\n");
4023 UserEnterExclusive();
4024
4025 if (!(Window = UserGetWindowObject(hWnd)))
4026 {
4027 RETURN( 0);
4028 }
4029
4030 switch (Index)
4031 {
4032 case GWL_ID:
4033 case GWL_HINSTANCE:
4034 case GWL_HWNDPARENT:
4035 RETURN( co_UserSetWindowLong(Window->hSelf, Index, (UINT)NewValue, TRUE));
4036 default:
4037 if (Index < 0)
4038 {
4039 SetLastWin32Error(ERROR_INVALID_INDEX);
4040 RETURN( 0);
4041 }
4042 }
4043
4044 if (Index > Window->Wnd->cbwndExtra - sizeof(WORD))
4045 {
4046 SetLastWin32Error(ERROR_INVALID_PARAMETER);
4047 RETURN( 0);
4048 }
4049
4050 OldValue = *((WORD *)((PCHAR)(Window->Wnd + 1) + Index));
4051 *((WORD *)((PCHAR)(Window->Wnd + 1) + Index)) = NewValue;
4052
4053 RETURN( OldValue);
4054
4055 CLEANUP:
4056 DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_);
4057 UserLeave();
4058 END_CLEANUP;
4059 }
4060
4061 /*
4062 * @implemented
4063 */
4064 BOOL APIENTRY
4065 NtUserGetWindowPlacement(HWND hWnd,
4066 WINDOWPLACEMENT *lpwndpl)
4067 {
4068 PWINDOW_OBJECT Window;
4069 PWND Wnd;
4070 POINT Size;
4071 WINDOWPLACEMENT Safepl;
4072 NTSTATUS Status;
4073 DECLARE_RETURN(BOOL);
4074
4075 DPRINT("Enter NtUserGetWindowPlacement\n");
4076 UserEnterShared();
4077
4078 if (!(Window = UserGetWindowObject(hWnd)))
4079 {
4080 RETURN( FALSE);
4081 }
4082 Wnd = Window->Wnd;
4083
4084 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
4085 if(!NT_SUCCESS(Status))
4086 {
4087 SetLastNtError(Status);
4088 RETURN( FALSE);
4089 }
4090 if(Safepl.length != sizeof(WINDOWPLACEMENT))
4091 {
4092 RETURN( FALSE);
4093 }
4094
4095 Safepl.flags = 0;
4096 if (0 == (Wnd->style & WS_VISIBLE))
4097 {
4098 Safepl.showCmd = SW_HIDE;
4099 }
4100 else if ((0 != (Window->state & WINDOWOBJECT_RESTOREMAX) ||
4101 0 != (Wnd->style & WS_MAXIMIZE)) &&
4102 0 == (Wnd->style & WS_MINIMIZE))
4103 {
4104 Safepl.showCmd = SW_SHOWMAXIMIZED;
4105 }
4106 else if (0 != (Wnd->style & WS_MINIMIZE))
4107 {
4108 Safepl.showCmd = SW_SHOWMINIMIZED;
4109 }
4110 else if (0 != (Wnd->style & WS_VISIBLE))
4111 {
4112 Safepl.showCmd = SW_SHOWNORMAL;
4113 }
4114
4115 Size.x = Wnd->rcWindow.left;
4116 Size.y = Wnd->rcWindow.top;
4117 WinPosInitInternalPos(Window, &Size,
4118 &Wnd->rcWindow);
4119
4120 Safepl.rcNormalPosition = Wnd->InternalPos.NormalRect;
4121 Safepl.ptMinPosition = Wnd->InternalPos.IconPos;
4122 Safepl.ptMaxPosition = Wnd->InternalPos.MaxPos;
4123
4124 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
4125 if(!NT_SUCCESS(Status))
4126 {
4127 SetLastNtError(Status);
4128 RETURN( FALSE);
4129 }
4130
4131 RETURN( TRUE);
4132
4133 CLEANUP:
4134 DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
4135 UserLeave();
4136 END_CLEANUP;
4137 }
4138
4139
4140 /*
4141 * @unimplemented
4142 */
4143 BOOL APIENTRY
4144 NtUserLockWindowUpdate(HWND hWnd)
4145 {
4146 UNIMPLEMENTED
4147
4148 return 0;
4149 }
4150
4151
4152 /*
4153 * @implemented
4154 */
4155 BOOL APIENTRY
4156 NtUserMoveWindow(
4157 HWND hWnd,
4158 int X,
4159 int Y,
4160 int nWidth,
4161 int nHeight,
4162 BOOL bRepaint)
4163 {
4164 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
4165 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
4166 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
4167 }
4168
4169 /*
4170 QueryWindow based on KJK::Hyperion and James Tabor.
4171
4172 0 = QWUniqueProcessId
4173 1 = QWUniqueThreadId
4174 2 = QWActiveWindow
4175 3 = QWFocusWindow
4176 4 = QWIsHung Implements IsHungAppWindow found
4177 by KJK::Hyperion.
4178
4179 9 = QWKillWindow When I called this with hWnd ==
4180 DesktopWindow, it shutdown the system
4181 and rebooted.
4182 */
4183 /*
4184 * @implemented
4185 */
4186 DWORD APIENTRY
4187 NtUserQueryWindow(HWND hWnd, DWORD Index)
4188 {
4189 PWINDOW_OBJECT Window;
4190 PWND pWnd;
4191 DWORD Result;
4192 DECLARE_RETURN(UINT);
4193
4194 DPRINT("Enter NtUserQueryWindow\n");
4195 UserEnterShared();
4196
4197 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
4198 {
4199 RETURN( 0);
4200 }
4201
4202 pWnd = Window->Wnd;
4203
4204 switch(Index)
4205 {
4206 case QUERY_WINDOW_UNIQUE_PROCESS_ID:
4207 Result = (DWORD)IntGetWndProcessId(Window);
4208 break;
4209
4210 case QUERY_WINDOW_UNIQUE_THREAD_ID:
4211 Result = (DWORD)IntGetWndThreadId(Window);
4212 break;
4213
4214 case QUERY_WINDOW_ACTIVE:
4215 Result = (DWORD)UserGetActiveWindow();
4216 break;
4217
4218 case QUERY_WINDOW_FOCUS:
4219 Result = (DWORD)IntGetFocusWindow();
4220 break;
4221
4222 case QUERY_WINDOW_ISHUNG:
4223 Result = (DWORD)MsqIsHung(Window->pti->MessageQueue);
4224 break;
4225
4226 case QUERY_WINDOW_REAL_ID:
4227 Result = (DWORD)pWnd->head.pti->pEThread->Cid.UniqueProcess;
4228
4229 default:
4230 Result = (DWORD)NULL;
4231 break;
4232 }
4233
4234 RETURN( Result);
4235
4236 CLEANUP:
4237 DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_);
4238 UserLeave();
4239 END_CLEANUP;
4240 }
4241
4242
4243 /*
4244 * @unimplemented
4245 */
4246 DWORD APIENTRY
4247 NtUserRealChildWindowFromPoint(DWORD Unknown0,
4248 DWORD Unknown1,
4249 DWORD Unknown2)
4250 {
4251 UNIMPLEMENTED
4252
4253 return 0;
4254 }
4255
4256
4257 /*
4258 * @implemented
4259 */
4260 UINT APIENTRY
4261 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
4262 {
4263 UNICODE_STRING SafeMessageName;
4264 NTSTATUS Status;
4265 UINT Ret;
4266 DECLARE_RETURN(UINT);
4267
4268 DPRINT("Enter NtUserRegisterWindowMessage\n");
4269 UserEnterExclusive();
4270
4271 if(MessageNameUnsafe == NULL)
4272 {
4273 SetLastWin32Error(ERROR_INVALID_PARAMETER);
4274 RETURN( 0);
4275 }
4276
4277 Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
4278 if(!NT_SUCCESS(Status))
4279 {
4280 SetLastNtError(Status);
4281 RETURN( 0);
4282 }
4283
4284 Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
4285 if (SafeMessageName.Buffer)
4286 ExFreePoolWithTag(SafeMessageName.Buffer, TAG_STRING);
4287 RETURN( Ret);
4288
4289 CLEANUP:
4290 DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_);
4291 UserLeave();
4292 END_CLEANUP;
4293 }
4294
4295
4296 /*
4297 * @unimplemented
4298 */
4299 DWORD APIENTRY
4300 NtUserSetImeOwnerWindow(DWORD Unknown0,
4301 DWORD Unknown1)
4302 {
4303 UNIMPLEMENTED
4304
4305 return 0;
4306 }
4307
4308
4309 /*
4310 * @unimplemented
4311 */
4312 DWORD APIENTRY
4313 NtUserSetInternalWindowPos(
4314 HWND hwnd,
4315 UINT showCmd,
4316 LPRECT rect,
4317 LPPOINT pt)
4318 {
4319 UNIMPLEMENTED
4320
4321 return 0;
4322
4323 }
4324
4325
4326 /*
4327 * @unimplemented
4328 */
4329 BOOL APIENTRY
4330 NtUserSetLayeredWindowAttributes(HWND hwnd,
4331 COLORREF crKey,
4332 BYTE bAlpha,
4333 DWORD dwFlags)
4334 {
4335 UNIMPLEMENTED;
4336 return FALSE;
4337 }
4338
4339
4340 /*
4341 * @unimplemented
4342 */
4343 BOOL APIENTRY
4344 NtUserSetLogonNotifyWindow(HWND hWnd)
4345 {
4346 UNIMPLEMENTED
4347
4348 return 0;
4349 }
4350
4351
4352 /*
4353 * @implemented
4354 */
4355 BOOL APIENTRY
4356 NtUserSetMenu(
4357 HWND hWnd,
4358 HMENU Menu,
4359 BOOL Repaint)
4360 {
4361 PWINDOW_OBJECT Window;
4362 BOOL Changed;
4363 DECLARE_RETURN(BOOL);
4364
4365 DPRINT("Enter NtUserSetMenu\n");
4366 UserEnterExclusive();
4367
4368 if (!(Window = UserGetWindowObject(hWnd)))
4369 {
4370 RETURN( FALSE);
4371 }
4372
4373 if (! IntSetMenu(Window, Menu, &Changed))
4374 {
4375 RETURN( FALSE);
4376 }
4377
4378 if (Changed && Repaint)
4379 {
4380 USER_REFERENCE_ENTRY Ref;
4381
4382 UserRefObjectCo(Window, &Ref);
4383 co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4384 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
4385
4386 UserDerefObjectCo(Window);
4387 }
4388
4389 RETURN( TRUE);
4390
4391 CLEANUP:
4392 DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_);
4393 UserLeave();
4394 END_CLEANUP;
4395 }
4396
4397
4398 /*
4399 * @implemented
4400 */
4401 BOOL APIENTRY
4402 NtUserSetWindowFNID(HWND hWnd,
4403 WORD fnID)
4404 {
4405 PWINDOW_OBJECT Window;
4406 PWND Wnd;
4407 DECLARE_RETURN(BOOL);
4408
4409 DPRINT("Enter NtUserSetWindowFNID\n");
4410 UserEnterExclusive();
4411
4412 if (!(Window = UserGetWindowObject(hWnd)))
4413 {
4414 RETURN( FALSE);
4415 }
4416 Wnd = Window->Wnd;
4417
4418 if (Wnd->pcls)
4419 { // From user land we only set these.
4420 if ((fnID != FNID_DESTROY) || ((fnID < FNID_BUTTON) && (fnID > FNID_IME)) )
4421 {
4422 RETURN( FALSE);
4423 }
4424 else
4425 Wnd->pcls->fnid |= fnID;
4426 }
4427 RETURN( TRUE);
4428
4429 CLEANUP:
4430 DPRINT("Leave NtUserSetWindowFNID\n");
4431 UserLeave();
4432 END_CLEANUP;
4433 }
4434
4435
4436 /*
4437 * @implemented
4438 */
4439 BOOL APIENTRY
4440 NtUserSetWindowPlacement(HWND hWnd,
4441 WINDOWPLACEMENT *lpwndpl)
4442 {
4443 PWINDOW_OBJECT Window;
4444 PWND Wnd;
4445 WINDOWPLACEMENT Safepl;
4446 NTSTATUS Status;
4447 DECLARE_RETURN(BOOL);
4448 USER_REFERENCE_ENTRY Ref;
4449
4450 DPRINT("Enter NtUserSetWindowPlacement\n");
4451 UserEnterExclusive();
4452
4453 if (!(Window = UserGetWindowObject(hWnd)))
4454 {
4455 RETURN( FALSE);
4456 }
4457 Wnd = Window->Wnd;
4458
4459 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
4460 if(!NT_SUCCESS(Status))
4461 {
4462 SetLastNtError(Status);
4463 RETURN( FALSE);
4464 }
4465 if(Safepl.length != sizeof(WINDOWPLACEMENT))
4466 {
4467 RETURN( FALSE);
4468 }
4469
4470 UserRefObjectCo(Window, &Ref);
4471
4472 if ((Wnd->style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
4473 {
4474 co_WinPosSetWindowPos(Window, NULL,
4475 Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
4476 Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
4477 Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
4478 SWP_NOZORDER | SWP_NOACTIVATE);
4479 }
4480
4481 /* FIXME - change window status */
4482 co_WinPosShowWindow(Window, Safepl.showCmd);
4483
4484 Wnd->InternalPosInitialized = TRUE;
4485 Wnd->InternalPos.NormalRect = Safepl.rcNormalPosition;
4486 Wnd->InternalPos.IconPos = Safepl.ptMinPosition;
4487 Wnd->InternalPos.MaxPos = Safepl.ptMaxPosition;
4488
4489 UserDerefObjectCo(Window);
4490 RETURN(TRUE);
4491
4492 CLEANUP:
4493 DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
4494 UserLeave();
4495 END_CLEANUP;
4496 }
4497
4498
4499 /*
4500 * @implemented
4501 */
4502 BOOL APIENTRY
4503 NtUserSetWindowPos(
4504 HWND hWnd,
4505 HWND hWndInsertAfter,
4506 int X,
4507 int Y,
4508 int cx,
4509 int cy,
4510 UINT uFlags)
4511 {
4512 DECLARE_RETURN(BOOL);
4513 PWINDOW_OBJECT Window;
4514 BOOL ret;
4515 USER_REFERENCE_ENTRY Ref;
4516
4517 DPRINT("Enter NtUserSetWindowPos\n");
4518 UserEnterExclusive();
4519
4520 if (!(Window = UserGetWindowObject(hWnd)))
4521 {
4522 RETURN(FALSE);
4523 }
4524
4525 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
4526 if (!(uFlags & SWP_NOMOVE))
4527 {
4528 if (X < -32768) X = -32768;
4529 else if (X > 32767) X = 32767;
4530 if (Y < -32768) Y = -32768;
4531 else if (Y > 32767) Y = 32767;
4532 }
4533 if (!(uFlags & SWP_NOSIZE))
4534 {
4535 if (cx < 0) cx = 0;
4536 else if (cx > 32767) cx = 32767;
4537 if (cy < 0) cy = 0;
4538 else if (cy > 32767) cy = 32767;
4539 }
4540
4541 UserRefObjectCo(Window, &Ref);
4542 ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags);
4543 UserDerefObjectCo(Window);
4544
4545 RETURN(ret);
4546
4547 CLEANUP:
4548 DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
4549 UserLeave();
4550 END_CLEANUP;
4551 }
4552
4553
4554 INT FASTCALL
4555 IntGetWindowRgn(PWINDOW_OBJECT Window, HRGN hRgn)
4556 {
4557 INT Ret;
4558 HRGN VisRgn;
4559 ROSRGNDATA *pRgn;
4560 PWND Wnd;
4561
4562 if(!Window)
4563 {
4564 return ERROR;
4565 }
4566 if(!hRgn)
4567 {
4568 return ERROR;
4569 }
4570
4571 Wnd = Window->Wnd;
4572
4573 /* Create a new window region using the window rectangle */
4574 VisRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcWindow);
4575 NtGdiOffsetRgn(VisRgn, -Window->Wnd->rcWindow.left, -Window->Wnd->rcWindow.top);
4576 /* if there's a region assigned to the window, combine them both */
4577 if(Window->hrgnClip && !(Wnd->style & WS_MINIMIZE))
4578 NtGdiCombineRgn(VisRgn, VisRgn, Window->hrgnClip, RGN_AND);
4579 /* Copy the region into hRgn */
4580 NtGdiCombineRgn(hRgn, VisRgn, NULL, RGN_COPY);
4581
4582 if((pRgn = RGNOBJAPI_Lock(hRgn, NULL)))
4583 {
4584 Ret = pRgn->rdh.iType;
4585 RGNOBJAPI_Unlock(pRgn);
4586 }
4587 else
4588 Ret = ERROR;
4589
4590 REGION_FreeRgnByHandle(VisRgn);
4591
4592 return Ret;
4593 }
4594
4595 INT FASTCALL
4596 IntGetWindowRgnBox(PWINDOW_OBJECT Window, RECTL *Rect)
4597 {
4598 INT Ret;
4599 HRGN VisRgn;
4600 ROSRGNDATA *pRgn;
4601 PWND Wnd;
4602
4603 if(!Window)
4604 {
4605 return ERROR;
4606 }
4607 if(!Rect)
4608 {
4609 return ERROR;
4610 }
4611
4612 Wnd = Window->Wnd;
4613
4614 /* Create a new window region using the window rectangle */
4615 VisRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcWindow);
4616 NtGdiOffsetRgn(VisRgn, -Window->Wnd->rcWindow.left, -Window->Wnd->rcWindow.top);
4617 /* if there's a region assigned to the window, combine them both */
4618 if(Window->hrgnClip && !(Wnd->style & WS_MINIMIZE))
4619 NtGdiCombineRgn(VisRgn, VisRgn, Window->hrgnClip, RGN_AND);
4620
4621 if((pRgn = RGNOBJAPI_Lock(VisRgn, NULL)))
4622 {
4623 Ret = pRgn->rdh.iType;
4624 *Rect = pRgn->rdh.rcBound;
4625 RGNOBJAPI_Unlock(pRgn);
4626 }
4627 else
4628 Ret = ERROR;
4629
4630 REGION_FreeRgnByHandle(VisRgn);
4631
4632 return Ret;
4633 }
4634
4635
4636 /*
4637 * @implemented
4638 */
4639 INT APIENTRY
4640 NtUserSetWindowRgn(
4641 HWND hWnd,
4642 HRGN hRgn,
4643 BOOL bRedraw)
4644 {
4645 HRGN hrgnCopy;
4646 PWINDOW_OBJECT Window;
4647 DECLARE_RETURN(INT);
4648
4649 DPRINT("Enter NtUserSetWindowRgn\n");
4650 UserEnterExclusive();
4651
4652 if (!(Window = UserGetWindowObject(hWnd)))
4653 {
4654 RETURN( 0);
4655 }
4656
4657 if (hRgn) // The region will be deleted in user32.
4658 {
4659 if (GDIOBJ_ValidateHandle(hRgn, GDI_OBJECT_TYPE_REGION))
4660 {
4661 hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0);
4662 NtGdiCombineRgn(hrgnCopy, hRgn, 0, RGN_COPY);
4663 }
4664 else
4665 RETURN( 0);
4666 }
4667 else
4668 hrgnCopy = (HRGN) 1;
4669
4670 if (Window->hrgnClip)
4671 {
4672 /* Delete no longer needed region handle */
4673 GreDeleteObject(Window->hrgnClip);
4674 }
4675 Window->hrgnClip = hrgnCopy;
4676
4677 /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
4678
4679 if(bRedraw)
4680 {
4681 USER_REFERENCE_ENTRY Ref;
4682 UserRefObjectCo(Window, &Ref);
4683 co_UserRedrawWindow(Window, NULL, NULL, RDW_INVALIDATE);
4684 UserDerefObjectCo(Window);
4685 }
4686
4687 RETURN( (INT)hRgn);
4688
4689 CLEANUP:
4690 DPRINT("Leave NtUserSetWindowRgn, ret=%i\n",_ret_);
4691 UserLeave();
4692 END_CLEANUP;
4693 }
4694
4695
4696 /*
4697 * @implemented
4698 */
4699 BOOL APIENTRY
4700 NtUserShowWindow(HWND hWnd, LONG nCmdShow)
4701 {
4702 PWINDOW_OBJECT Window;
4703 BOOL ret;
4704 DECLARE_RETURN(BOOL);
4705 USER_REFERENCE_ENTRY Ref;
4706
4707 DPRINT("Enter NtUserShowWindow\n");
4708 UserEnterExclusive();
4709
4710 if (!(Window = UserGetWindowObject(hWnd)))
4711 {
4712 RETURN(FALSE);
4713 }
4714
4715 UserRefObjectCo(Window, &Ref);
4716 ret = co_WinPosShowWindow(Window, nCmdShow);
4717 UserDerefObjectCo(Window);
4718
4719 RETURN(ret);
4720
4721 CLEANUP:
4722 DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_);
4723 UserLeave();
4724 END_CLEANUP;
4725 }
4726
4727
4728 /*
4729 * @unimplemented
4730 */
4731 BOOL APIENTRY
4732 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
4733 {
4734 #if 0
4735 UNIMPLEMENTED
4736 return 0;
4737 #else
4738 return NtUserShowWindow(hWnd, nCmdShow);
4739 #endif
4740 }
4741
4742
4743 /*
4744 * @unimplemented
4745 */
4746 BOOL
4747 APIENTRY
4748 NtUserUpdateLayeredWindow(
4749 HWND hwnd,
4750 HDC hdcDst,
4751 POINT *pptDst,
4752 SIZE *psize,
4753 HDC hdcSrc,
4754 POINT *pptSrc,
4755 COLORREF crKey,
4756 BLENDFUNCTION *pblend,
4757 DWORD dwFlags,
4758 RECT *prcDirty)
4759 {
4760 UNIMPLEMENTED
4761
4762 return 0;
4763 }
4764
4765 /*
4766 * @unimplemented
4767 */
4768 HWND APIENTRY
4769 NtUserWindowFromPhysicalPoint(POINT Point)
4770 {
4771 UNIMPLEMENTED
4772
4773 return NULL;
4774 }
4775
4776 /*
4777 * @implemented
4778 */
4779 HWND APIENTRY
4780 NtUserWindowFromPoint(LONG X, LONG Y)
4781 {
4782 POINT pt;
4783 HWND Ret;
4784 PWINDOW_OBJECT DesktopWindow = NULL, Window = NULL;
4785 DECLARE_RETURN(HWND);
4786 USER_REFERENCE_ENTRY Ref;
4787
4788 DPRINT("Enter NtUserWindowFromPoint\n");
4789 UserEnterExclusive();
4790
4791 if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
4792 {
4793 PTHREADINFO pti;
4794 USHORT Hit;
4795
4796 pt.x = X;
4797 pt.y = Y;
4798
4799 //hmm... threads live on desktops thus we have a reference on the desktop and indirectly the desktop window
4800 //its possible this referencing is useless, thou it shouldnt hurt...
4801 UserRefObjectCo(DesktopWindow, &Ref);
4802
4803 pti = PsGetCurrentThreadWin32Thread();
4804 Hit = co_WinPosWindowFromPoint(DesktopWindow, pti->MessageQueue, &pt, &Window);
4805
4806 if(Window)
4807 {
4808 Ret = Window->hSelf;
4809
4810 RETURN( Ret);
4811 }
4812 }
4813
4814 RETURN( NULL);
4815
4816 CLEANUP:
4817 if (Window) UserDereferenceObject(Window);
4818 if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
4819
4820 DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
4821 UserLeave();
4822 END_CLEANUP;
4823
4824 }
4825
4826
4827 /*
4828 * NtUserDefSetText
4829 *
4830 * Undocumented function that is called from DefWindowProc to set
4831 * window text.
4832 *
4833 * Status
4834 * @implemented
4835 */
4836 BOOL APIENTRY
4837 NtUserDefSetText(HWND hWnd, PLARGE_STRING WindowText)
4838 {
4839 PWINDOW_OBJECT Window;
4840 PWND Wnd;
4841 LARGE_STRING SafeText;
4842 UNICODE_STRING UnicodeString;
4843 BOOL Ret = TRUE;
4844
4845 DPRINT("Enter NtUserDefSetText\n");
4846
4847 if (WindowText != NULL)
4848 {
4849 _SEH2_TRY
4850 {
4851 SafeText = ProbeForReadLargeString(WindowText);
4852 }
4853 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4854 {
4855 Ret = FALSE;
4856 SetLastNtError(_SEH2_GetExceptionCode());
4857 }
4858 _SEH2_END;
4859
4860 if (!Ret)
4861 return FALSE;
4862 }
4863 else
4864 return TRUE;
4865
4866 UserEnterExclusive();
4867
4868 if(!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
4869 {
4870 UserLeave();
4871 return FALSE;
4872 }
4873 Wnd = Window->Wnd;
4874
4875 // ReactOS uses Unicode and not mixed. Up/Down converting will take time.
4876 // Brought to you by: The Wine Project! Dysfunctional Thought Processes!
4877 // Now we know what the bAnsi is for.
4878 RtlInitUnicodeString(&UnicodeString, NULL);
4879 if (SafeText.Buffer)
4880 {
4881 _SEH2_TRY
4882 {
4883 if (SafeText.bAnsi)
4884 ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(CHAR));
4885 else
4886 ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(WCHAR));
4887 Ret = RtlLargeStringToUnicodeString(&UnicodeString, &SafeText);
4888 }
4889 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4890 {
4891 Ret = FALSE;
4892 SetLastNtError(_SEH2_GetExceptionCode());
4893 }
4894 _SEH2_END;
4895 if (!Ret) goto Exit;
4896 }
4897
4898 if (UnicodeString.Length != 0)
4899 {
4900 if (Wnd->strName.MaximumLength > 0 &&
4901 UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4902 {
4903 ASSERT(Wnd->strName.Buffer != NULL);
4904
4905 Wnd->strName.Length = UnicodeString.Length;
4906 Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4907 RtlCopyMemory(Wnd->strName.Buffer,
4908 UnicodeString.Buffer,
4909 UnicodeString.Length);
4910 }
4911 else
4912 {
4913 PWCHAR buf;
4914 Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4915 buf = Wnd->strName.Buffer;
4916 Wnd->strName.Buffer = NULL;
4917 if (buf != NULL)
4918 {
4919 DesktopHeapFree(Wnd->head.rpdesk, buf);
4920 }
4921
4922 Wnd->strName.Buffer = DesktopHeapAlloc(Wnd->head.rpdesk,
4923 UnicodeString.Length + sizeof(UNICODE_NULL));
4924 if (Wnd->strName.Buffer != NULL)
4925 {
4926 Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4927 RtlCopyMemory(Wnd->strName.Buffer,
4928 UnicodeString.Buffer,
4929 UnicodeString.Length);
4930 Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4931 Wnd->strName.Length = UnicodeString.Length;
4932 }
4933 else
4934 {
4935 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
4936 Ret = FALSE;
4937 goto Exit;
4938 }
4939 }
4940 }
4941 else
4942 {
4943 Wnd->strName.Length = 0;
4944 if (Wnd->strName.Buffer != NULL)
4945 Wnd->strName.Buffer[0] = L'\0';
4946 }
4947
4948 // HAX! FIXME! Windows does not do this in here!
4949 // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4950 // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4951 /* Send shell notifications */
4952 if (!IntGetOwner(Window) && !IntGetParent(Window))
4953 {
4954 co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd);
4955 }
4956
4957 Ret = TRUE;
4958 Exit:
4959 if (UnicodeString.Buffer) RtlFreeUnicodeString(&UnicodeString);
4960 DPRINT("Leave NtUserDefSetText, ret=%i\n", Ret);
4961 UserLeave();
4962 return Ret;
4963 }
4964
4965 /*
4966 * NtUserInternalGetWindowText
4967 *
4968 * Status
4969 * @implemented
4970 */
4971
4972 INT APIENTRY
4973 NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
4974 {
4975 PWINDOW_OBJECT Window;
4976 PWND Wnd;
4977 NTSTATUS Status;
4978 INT Result;
4979 DECLARE_RETURN(INT);
4980
4981 DPRINT("Enter NtUserInternalGetWindowText\n");
4982 UserEnterShared();
4983
4984 if(lpString && (nMaxCount <= 1))
4985 {
4986 SetLastWin32Error(ERROR_INVALID_PARAMETER);
4987 RETURN( 0);
4988 }
4989
4990 if(!(Window = UserGetWindowObject(hWnd)))
4991 {
4992 RETURN( 0);
4993 }
4994 Wnd = Window->Wnd;
4995
4996 Result = Wnd->strName.Length / sizeof(WCHAR);
4997 if(lpString)
4998 {
4999 const WCHAR Terminator = L'\0';
5000 INT Copy;
5001 WCHAR *Buffer = (WCHAR*)lpString;
5002
5003 Copy = min(nMaxCount - 1, Result);
5004 if(Copy > 0)
5005 {
5006 Status = MmCopyToCaller(Buffer, Wnd->strName.Buffer, Copy * sizeof(WCHAR));
5007 if(!NT_SUCCESS(Status))
5008 {
5009 SetLastNtError(Status);
5010 RETURN( 0);
5011 }
5012 Buffer += Copy;
5013 }
5014
5015 Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
5016 if(!NT_SUCCESS(Status))
5017 {
5018 SetLastNtError(Status);
5019 RETURN( 0);
5020 }
5021
5022 Result = Copy;
5023 }
5024
5025 RETURN( Result);
5026
5027 CLEANUP:
5028 DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
5029 UserLeave();
5030 END_CLEANUP;
5031 }
5032
5033
5034 BOOL
5035 FASTCALL
5036 IntShowOwnedPopups(PWINDOW_OBJECT OwnerWnd, BOOL fShow )
5037 {
5038 int count = 0;
5039 PWINDOW_OBJECT pWnd;
5040 HWND *win_array;
5041
5042 // ASSERT(OwnerWnd);
5043
5044 win_array = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
5045
5046 if (!win_array)
5047 return TRUE;
5048
5049 while (win_array[count])
5050 count++;
5051 while (--count >= 0)
5052 {
5053 if (UserGetWindow( win_array[count], GW_OWNER ) != OwnerWnd->hSelf)
5054 continue;
5055 if (!(pWnd = UserGetWindowObject( win_array[count] )))
5056 continue;
5057 // if (pWnd == WND_OTHER_PROCESS) continue;
5058
5059 if (fShow)
5060 {
5061 if (pWnd->Wnd->state & WNDS_HIDDENPOPUP)
5062 {
5063 /* In Windows, ShowOwnedPopups(TRUE) generates
5064 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
5065 * regardless of the state of the owner
5066 */
5067 co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
5068 continue;
5069 }
5070 }
5071 else
5072 {
5073 if (pWnd->Wnd->style & WS_VISIBLE)
5074 {
5075 /* In Windows, ShowOwnedPopups(FALSE) generates
5076 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
5077 * regardless of the state of the owner
5078 */
5079 co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
5080 continue;
5081 }
5082 }
5083
5084 }
5085 ExFreePool( win_array );
5086 return TRUE;
5087 }
5088
5089 /*
5090 * NtUserValidateHandleSecure
5091 *
5092 * Status
5093 * @implemented
5094 */
5095
5096 BOOL
5097 APIENTRY
5098 NtUserValidateHandleSecure(
5099 HANDLE handle,
5100 BOOL Restricted)
5101 {
5102 if(!Restricted)
5103 {
5104 UINT uType;
5105 {
5106 PUSER_HANDLE_ENTRY entry;
5107 if (!(entry = handle_to_entry(gHandleTable, handle )))
5108 {
5109 SetLastWin32Error(ERROR_INVALID_HANDLE);
5110 return FALSE;
5111 }
5112 uType = entry->type;
5113 }
5114 switch (uType)
5115 {
5116 case otWindow:
5117 {
5118 PWINDOW_OBJECT Window;
5119 if ((Window = UserGetWindowObject((HWND) handle))) return TRUE;
5120 return FALSE;
5121 }
5122 case otMenu:
5123 {
5124 PMENU_OBJECT Menu;
5125 if ((Menu = UserGetMenuObject((HMENU) handle))) return TRUE;
5126 return FALSE;
5127 }
5128 case otAccel:
5129 {
5130 PACCELERATOR_TABLE Accel;
5131 if ((Accel = UserGetAccelObject((HACCEL) handle))) return TRUE;
5132 return FALSE;
5133 }
5134 case otCursorIcon:
5135 {
5136 PCURICON_OBJECT Cursor;
5137 if ((Cursor = UserGetCurIconObject((HCURSOR) handle))) return TRUE;
5138 return FALSE;
5139 }
5140 case otHook:
5141 {
5142 PHOOK Hook;
5143 if ((Hook = IntGetHookObject((HHOOK) handle))) return TRUE;
5144 return FALSE;
5145 }
5146 case otMonitor:
5147 {
5148 PMONITOR Monitor;
5149 if ((Monitor = UserGetMonitorObject((HMONITOR) handle))) return TRUE;
5150 return FALSE;
5151 }
5152 case otCallProc:
5153 {
5154 WNDPROC_INFO Proc;
5155 return UserGetCallProcInfo( handle, &Proc );
5156 }
5157 default:
5158 SetLastWin32Error(ERROR_INVALID_HANDLE);
5159 }
5160 }
5161 else
5162 { /* Is handle entry restricted? */
5163 UNIMPLEMENTED
5164 }
5165 return FALSE;
5166 }
5167
5168
5169 /* EOF */