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