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