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