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