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