ReactOS  0.4.15-dev-4614-ga5a6101
window.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Win32k subsystem
4  * PURPOSE: Windows
5  * FILE: win32ss/user/ntuser/window.c
6  * PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8  */
9 
10 #include <win32k.h>
11 #include <ddk/immdev.h>
12 DBG_DEFAULT_CHANNEL(UserWnd);
13 
15 
18 
19 /* HELPER FUNCTIONS ***********************************************************/
20 
24  PVOID pOld,
25  SIZE_T cbOld,
26  SIZE_T cbNew,
27  ULONG Tag)
28 {
29  PVOID pNew = ExAllocatePoolWithTag(PoolType, cbNew, Tag);
30  if (!pNew)
31  return NULL;
32 
33  RtlCopyMemory(pNew, pOld, min(cbOld, cbNew));
34  ExFreePoolWithTag(pOld, Tag);
35  return pNew;
36 }
37 
39 {
42 
43  if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
44  {
46  return FALSE;
47  }
48 
49  switch (Action)
50  {
51  case UIS_INITIALIZE:
53  return FALSE;
54 
55  case UIS_SET:
56  if (Flags & UISF_HIDEFOCUS)
57  Wnd->HideFocus = TRUE;
58  if (Flags & UISF_HIDEACCEL)
59  Wnd->HideAccel = TRUE;
60  break;
61 
62  case UIS_CLEAR:
63  if (Flags & UISF_HIDEFOCUS)
64  Wnd->HideFocus = FALSE;
65  if (Flags & UISF_HIDEACCEL)
66  Wnd->HideAccel = FALSE;
67  break;
68  }
69 
70  return TRUE;
71 }
72 
74 {
75  PWND Window;
76 
77  if (!hWnd) return NULL;
78 
80  if (Window)
81  Window->head.cLockObj++;
82 
83  return Window;
84 }
85 
87 {
88  HWND hWnd;
89  UINT State, State2;
90  ULONG Error;
91 
92  if (!pWnd) return NULL;
93 
95 
96  _SEH2_TRY
97  {
98  hWnd = UserHMGetHandle(pWnd);
99  State = pWnd->state;
100  State2 = pWnd->state2;
101  }
103  {
105  _SEH2_YIELD(return NULL);
106  }
107  _SEH2_END
108 
109  if ( UserObjectInDestroy(hWnd) ||
110  State & WNDS_DESTROYED ||
111  State2 & WNDS2_INDESTROY )
112  pWnd = NULL;
113 
115  return pWnd;
116 }
117 
119 {
121  return NULL;
122 }
123 
124 /* Temp HACK */
125 // Win: ValidateHwnd
127 {
128  PWND Window;
129 
130  if (!hWnd)
131  {
133  return NULL;
134  }
135 
137  if (!Window || 0 != (Window->state & WNDS_DESTROYED))
138  {
140  return NULL;
141  }
142 
143  return Window;
144 }
145 
147 IntSetStyle( PWND pwnd, ULONG set_bits, ULONG clear_bits )
148 {
149  ULONG styleOld, styleNew;
150  styleOld = pwnd->style;
151  styleNew = (pwnd->style | set_bits) & ~clear_bits;
152  if (styleNew == styleOld) return styleNew;
153  pwnd->style = styleNew;
154  if ((styleOld ^ styleNew) & WS_VISIBLE) // State Change.
155  {
156  if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--;
157  if (styleNew & WS_VISIBLE) pwnd->head.pti->cVisWindows++;
158  DceResetActiveDCEs( pwnd );
159  }
160  return styleOld;
161 }
162 
163 /*
164  * IntIsWindow
165  *
166  * The function determines whether the specified window handle identifies
167  * an existing window.
168  *
169  * Parameters
170  * hWnd
171  * Handle to the window to test.
172  *
173  * Return Value
174  * If the window handle identifies an existing window, the return value
175  * is TRUE. If the window handle does not identify an existing window,
176  * the return value is FALSE.
177  */
178 
181 {
182  PWND Window;
183 
184  if (!(Window = UserGetWindowObject(hWnd)))
185  {
186  return FALSE;
187  }
188 
189  return TRUE;
190 }
191 
194 {
195  PWND Temp = Wnd;
196  for (;;)
197  {
198  if (!Temp) return TRUE;
199  if (!(Temp->style & WS_VISIBLE)) break;
200  if (Temp->style & WS_MINIMIZE && Temp != Wnd) break;
201  if (Temp->fnid == FNID_DESKTOP) return TRUE;
202  Temp = Temp->spwndParent;
203  }
204  return FALSE;
205 }
206 
209 {
210  if (Wnd->style & WS_POPUP)
211  {
212  return Wnd->spwndOwner;
213  }
214  else if (Wnd->style & WS_CHILD)
215  {
216  return Wnd->spwndParent;
217  }
218 
219  return NULL;
220 }
221 
222 BOOL
223 FASTCALL
225 {
226  BOOL Update;
227  PWND pWnd;
228  UINT bIsDisabled;
229 
230  if(!(pWnd = UserGetWindowObject(hWnd)))
231  {
232  return FALSE;
233  }
234 
235  /* check if updating is needed */
236  bIsDisabled = !!(pWnd->style & WS_DISABLED);
237  Update = bIsDisabled;
238 
239  if (bEnable)
240  {
241  IntSetStyle( pWnd, 0, WS_DISABLED );
242  }
243  else
244  {
245  Update = !bIsDisabled;
246 
248 
249  /* Remove keyboard focus from that window if it had focus */
250  if (hWnd == IntGetThreadFocusWindow())
251  {
252  TRACE("IntEnableWindow SF NULL\n");
254  }
255  IntSetStyle( pWnd, WS_DISABLED, 0 );
256  }
257 
258  if (Update)
259  {
260  IntNotifyWinEvent(EVENT_OBJECT_STATECHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, 0);
262  }
263  // Return nonzero if it was disabled, or zero if it wasn't:
264  return bIsDisabled;
265 }
266 
267 /*
268  * IntWinListChildren
269  *
270  * Compile a list of all child window handles from given window.
271  *
272  * Remarks
273  * This function is similar to Wine WIN_ListChildren. The caller
274  * must free the returned list with ExFreePool.
275  */
276 
277 HWND* FASTCALL
279 {
280  PWND Child;
281  HWND *List;
282  UINT Index, NumChildren = 0;
283 
284  if (!Window) return NULL;
285 
286  for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
287  {
288  ++NumChildren;
289  }
290 
291  List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
292  if(!List)
293  {
294  ERR("Failed to allocate memory for children array\n");
296  return NULL;
297  }
298 
299  Index = 0;
300  for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
301  {
302  List[Index++] = Child->head.h;
303  }
304  List[Index] = NULL;
305 
306  return List;
307 }
308 
309 HWND* FASTCALL
311 {
312  PWND Child, Desktop;
313  HWND *List;
314  UINT Index, NumOwned = 0;
315 
317  if (!Desktop)
318  return NULL;
319 
320  for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
321  {
322  if (Child->spwndOwner == Window)
323  ++NumOwned;
324  }
325 
326  List = ExAllocatePoolWithTag(PagedPool, (NumOwned + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
327  if (!List)
328  {
329  ERR("Failed to allocate memory for children array\n");
331  return NULL;
332  }
333 
334  Index = 0;
335  for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
336  {
337  if (Child->spwndOwner == Window)
338  List[Index++] = Child->head.h;
339  }
340  List[Index] = NULL;
341 
342  return List;
343 }
344 
347 {
348  while(pWnd && (pWnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
349  pWnd = pWnd->spwndParent;
350  return pWnd;
351 }
352 
355 {
356  if ( pWnd->spwndParent &&
357  pWnd->spwndParent == co_GetDesktopWindow(pWnd) ) return TRUE;
358  return FALSE;
359 }
360 
363 {
364  INT Depth = 1;
365  for (;;)
366  {
367  if ( !Owner ) return gNestedWindowLimit >= Depth;
368  if (Owner == Wnd) break;
369  Owner = Owner->spwndOwner;
370  Depth++;
371  }
372  return FALSE;
373 }
374 
377  UINT uCmd)
378 {
379  PWND Wnd, FoundWnd;
380  HWND Ret = NULL;
381 
382  Wnd = ValidateHwndNoErr(hWnd);
383  if (!Wnd)
384  return NULL;
385 
386  FoundWnd = NULL;
387  switch (uCmd)
388  {
389  case GW_OWNER:
390  if (Wnd->spwndOwner != NULL)
391  FoundWnd = Wnd->spwndOwner;
392  break;
393 
394  case GW_HWNDFIRST:
395  if(Wnd->spwndParent != NULL)
396  {
397  FoundWnd = Wnd->spwndParent;
398  if (FoundWnd->spwndChild != NULL)
399  FoundWnd = FoundWnd->spwndChild;
400  }
401  break;
402  case GW_HWNDNEXT:
403  if (Wnd->spwndNext != NULL)
404  FoundWnd = Wnd->spwndNext;
405  break;
406 
407  case GW_HWNDPREV:
408  if (Wnd->spwndPrev != NULL)
409  FoundWnd = Wnd->spwndPrev;
410  break;
411 
412  case GW_CHILD:
413  if (Wnd->spwndChild != NULL)
414  FoundWnd = Wnd->spwndChild;
415  break;
416 
417  case GW_HWNDLAST:
418  FoundWnd = Wnd;
419  while ( FoundWnd->spwndNext != NULL)
420  FoundWnd = FoundWnd->spwndNext;
421  break;
422 
423  default:
424  Wnd = NULL;
425  break;
426  }
427 
428  if (FoundWnd != NULL)
429  Ret = UserHMGetHandle(FoundWnd);
430  return Ret;
431 }
432 
434 {
435  DWORD HelpId;
436 
437  do
438  {
440  if (!HelpId) break;
441  pWnd = IntGetParent(pWnd);
442  }
443  while (pWnd && pWnd->fnid != FNID_DESKTOP);
444  return HelpId;
445 }
446 
447 
448 VOID
449 FASTCALL
451  PDESKTOP pDesk);
452 
453 /***********************************************************************
454  * IntSendDestroyMsg
455  */
457 {
458  PTHREADINFO ti;
459  PWND Window;
460 
463 
464  if (Window)
465  {
466  /*
467  * Look whether the focus is within the tree of windows
468  * we will be destroying.
469  */
470  // Rule #1
471  if ( ti->MessageQueue->spwndActive == Window || // Fixes CORE-106 RegSvr32 exit and return focus to CMD.
472  (ti->MessageQueue->spwndActive == NULL && ti->MessageQueue == IntGetFocusMessageQueue()) )
473  {
475  }
476 
477  /* Fixes CMD properties closing and returning focus to CMD */
478  if (ti->MessageQueue->spwndFocus == Window)
479  {
480  if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
481  {
482  co_UserSetFocus(Window->spwndParent);
483  }
484  else
485  {
487  }
488  }
489 
490  if (ti->MessageQueue->CaretInfo.hWnd == UserHMGetHandle(Window))
491  {
492  co_IntDestroyCaret(ti);
493  }
494 
495  /* If the window being destroyed is currently tracked... */
496  if (ti->rpdesk->spwndTrack == Window)
497  {
499  }
500  }
501 
502  /* If the window being destroyed is the current clipboard owner... */
503  if (ti->ppi->prpwinsta != NULL && Window == ti->ppi->prpwinsta->spwndClipOwner)
504  {
505  /* ... make it release the clipboard */
507  }
508 
509  /* Send the WM_DESTROY to the window */
511 
512  /*
513  * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
514  * make sure that the window still exists when we come back.
515  */
516  if (IntIsWindow(hWnd))
517  {
518  HWND* pWndArray;
519  int i;
520 
521  if (!(pWndArray = IntWinListChildren( Window ))) return;
522 
523  for (i = 0; pWndArray[i]; i++)
524  {
525  if (IntIsWindow( pWndArray[i] )) IntSendDestroyMsg( pWndArray[i] );
526  }
528  }
529  else
530  {
531  TRACE("destroyed itself while in WM_DESTROY!\n");
532  }
533 }
534 
535 static VOID
537 {
539 
540  if (!Wnd) return;
541 
542  if (ClientInfo->CallbackWnd.pWnd == DesktopHeapAddressToUser(Wnd))
543  {
544  ClientInfo->CallbackWnd.hWnd = NULL;
545  ClientInfo->CallbackWnd.pWnd = NULL;
546  }
547 
548  if (Wnd->strName.Buffer != NULL)
549  {
550  Wnd->strName.Length = 0;
551  Wnd->strName.MaximumLength = 0;
553  Wnd->strName.Buffer);
554  Wnd->strName.Buffer = NULL;
555  }
556 
557 // DesktopHeapFree(Wnd->head.rpdesk, Wnd);
558 // WindowObject->hWnd = NULL;
559 }
560 
561 /***********************************************************************
562  * co_UserFreeWindow
563  *
564  * Destroy storage associated to a window. "Internals" p.358
565  *
566  * This is the "functional" DestroyWindows function i.e. all stuff
567  * done in CreateWindow is undone here and not in DestroyWindow :-P
568  */
570  PPROCESSINFO ProcessData,
572  BOOLEAN SendMessages)
573 {
574  HWND *Children;
575  HWND *ChildHandle;
576  PWND Child;
577  PMENU Menu;
578  BOOLEAN BelongsToThreadData;
579 
580  ASSERT(Window);
581 
582  if(Window->state2 & WNDS2_INDESTROY)
583  {
584  TRACE("Tried to call co_UserFreeWindow() twice\n");
585  return 0;
586  }
587  Window->state2 |= WNDS2_INDESTROY;
588  Window->style &= ~WS_VISIBLE;
589  Window->head.pti->cVisWindows--;
590 
591 
592  /* remove the window already at this point from the thread window list so we
593  don't get into trouble when destroying the thread windows while we're still
594  in co_UserFreeWindow() */
595  RemoveEntryList(&Window->ThreadListEntry);
596 
597  BelongsToThreadData = IntWndBelongsToThread(Window, ThreadData);
598 
600 
601  /* free child windows */
602  Children = IntWinListChildren(Window);
603  if (Children)
604  {
605  for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
606  {
607  if ((Child = IntGetWindowObject(*ChildHandle)))
608  {
610  {
611  /* send WM_DESTROY messages to windows not belonging to the same thread */
613  }
614  else
615  co_UserFreeWindow(Child, ProcessData, ThreadData, SendMessages);
616 
618  }
619  }
621  }
622 
623  if (SendMessages)
624  {
625  /*
626  * Clear the update region to make sure no WM_PAINT messages will be
627  * generated for this window while processing the WM_NCDESTROY.
628  */
632  if (BelongsToThreadData)
634  }
635 
637 
639 
640  /* Unregister hot keys */
642 
643  /* flush the message queue */
645 
646  /* from now on no messages can be sent to this window anymore */
647  Window->state |= WNDS_DESTROYED;
648  Window->fnid |= FNID_FREED;
649 
650  /* don't remove the WINDOWSTATUS_DESTROYING bit */
651 
652  /* reset shell window handles */
653  if (ThreadData->rpdesk)
654  {
655  if (Window->head.h == ThreadData->rpdesk->rpwinstaParent->ShellWindow)
656  ThreadData->rpdesk->rpwinstaParent->ShellWindow = NULL;
657 
658  if (Window->head.h == ThreadData->rpdesk->rpwinstaParent->ShellListView)
659  ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
660  }
661 
662  if (ThreadData->spwndDefaultIme &&
663  ThreadData->spwndDefaultIme->spwndOwner == Window)
664  {
665  ThreadData->spwndDefaultIme->spwndOwner = NULL;
666  }
667 
668  if (IS_IMM_MODE() && Window == ThreadData->spwndDefaultIme)
669  {
670  UserAssignmentUnlock((PVOID*)&(ThreadData->spwndDefaultIme));
671  }
672 
673  /* Fixes dialog test_focus breakage due to r66237. */
674  if (ThreadData->MessageQueue->spwndFocus == Window)
675  ThreadData->MessageQueue->spwndFocus = NULL;
676 
677  if (ThreadData->MessageQueue->spwndActive == Window)
678  ThreadData->MessageQueue->spwndActive = NULL;
679 
680  if (ThreadData->MessageQueue->spwndCapture == Window)
681  {
683  }
684 
686  if ( Window->hrgnUpdate != NULL || Window->state & WNDS_INTERNALPAINT )
687  {
688  MsqDecPaintCountQueue(Window->head.pti);
689  if (Window->hrgnUpdate > HRGN_WINDOW && GreIsHandleValid(Window->hrgnUpdate))
690  {
692  GreDeleteObject(Window->hrgnUpdate);
693  }
694  Window->hrgnUpdate = NULL;
695  Window->state &= ~WNDS_INTERNALPAINT;
696  }
697 
699  {
701  }
702 
703  if ( ((Window->style & (WS_CHILD|WS_POPUP)) != WS_CHILD) &&
704  Window->IDMenu &&
705  (Menu = UserGetMenuObject((HMENU)Window->IDMenu)))
706  {
707  TRACE("UFW: IDMenu %p\n",Window->IDMenu);
708  IntDestroyMenuObject(Menu, TRUE);
709  Window->IDMenu = 0;
710  }
711 
712  if (Window->SystemMenu
713  && (Menu = UserGetMenuObject(Window->SystemMenu)))
714  {
715  IntDestroyMenuObject(Menu, TRUE);
716  Window->SystemMenu = (HMENU)0;
717  }
718 
719  DceFreeWindowDCE(Window); /* Always do this to catch orphaned DCs */
720 
722 
723  if (Window->PropListItems)
724  {
726  TRACE("Window->PropListItems %lu\n",Window->PropListItems);
727  ASSERT(Window->PropListItems==0);
728  }
729 
732 
734 
735  if (Window->pcls->atomClassName == gaGuiConsoleWndClass)
736  {
737  /* Count only console windows manually */
739  }
740 
741  /* dereference the class */
742  NT_ASSERT(Window->head.pti != NULL);
744  Window->head.pti->pDeskInfo,
745  Window->head.pti->ppi);
746  Window->pcls = NULL;
747 
748  if (Window->hrgnClip)
749  {
751  GreDeleteObject(Window->hrgnClip);
752  Window->hrgnClip = NULL;
753  }
754  Window->head.pti->cWindows--;
755 
756 // ASSERT(Window != NULL);
757  UserFreeWindowInfo(Window->head.pti, Window);
758 
761 
762  return 0;
763 }
764 
765 //
766 // Same as User32:IntGetWndProc.
767 //
770  BOOL Ansi)
771 {
772  INT i;
773  PCLS Class;
774  WNDPROC gcpd, Ret = 0;
775 
777 
778  Class = pWnd->pcls;
779 
780  if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC)
781  {
782  for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
783  {
784  if (GETPFNSERVER(i) == pWnd->lpfnWndProc)
785  {
786  if (Ansi)
787  Ret = GETPFNCLIENTA(i);
788  else
789  Ret = GETPFNCLIENTW(i);
790  }
791  }
792  return Ret;
793  }
794 
795  if (Class->fnid == FNID_EDIT)
796  Ret = pWnd->lpfnWndProc;
797  else
798  {
799  Ret = pWnd->lpfnWndProc;
800 
801  if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
802  {
803  if (Ansi)
804  {
805  if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc)
806  Ret = GETPFNCLIENTA(Class->fnid);
807  }
808  else
809  {
810  if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc)
811  Ret = GETPFNCLIENTW(Class->fnid);
812  }
813  }
814  if ( Ret != pWnd->lpfnWndProc)
815  return Ret;
816  }
817  if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) )
818  return Ret;
819 
820  gcpd = (WNDPROC)UserGetCPD(
821  pWnd,
823  (ULONG_PTR)Ret);
824 
825  return (gcpd ? gcpd : Ret);
826 }
827 
828 static WNDPROC
830  WNDPROC NewWndProc,
831  BOOL Ansi)
832 {
833  INT i;
834  PCALLPROCDATA CallProc;
835  PCLS Class;
836  WNDPROC Ret, chWndProc = NULL;
837 
838  // Retrieve previous window proc.
839  Ret = IntGetWindowProc(pWnd, Ansi);
840 
841  Class = pWnd->pcls;
842 
843  if (IsCallProcHandle(NewWndProc))
844  {
845  CallProc = UserGetObject(gHandleTable, NewWndProc, TYPE_CALLPROC);
846  if (CallProc)
847  { // Reset new WndProc.
848  NewWndProc = CallProc->pfnClientPrevious;
849  // Reset Ansi from CallProc handle. This is expected with wine "deftest".
850  Ansi = !!(CallProc->wType & UserGetCPDU2A);
851  }
852  }
853  // Switch from Client Side call to Server Side call if match. Ref: "deftest".
854  for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
855  {
856  if (GETPFNCLIENTW(i) == NewWndProc)
857  {
858  chWndProc = GETPFNSERVER(i);
859  break;
860  }
861  if (GETPFNCLIENTA(i) == NewWndProc)
862  {
863  chWndProc = GETPFNSERVER(i);
864  break;
865  }
866  }
867  // If match, set/reset to Server Side and clear ansi.
868  if (chWndProc)
869  {
870  pWnd->lpfnWndProc = chWndProc;
871  pWnd->Unicode = TRUE;
872  pWnd->state &= ~WNDS_ANSIWINDOWPROC;
874  }
875  else
876  {
877  pWnd->Unicode = !Ansi;
878  // Handle the state change in here.
879  if (Ansi)
880  pWnd->state |= WNDS_ANSIWINDOWPROC;
881  else
882  pWnd->state &= ~WNDS_ANSIWINDOWPROC;
883 
884  if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC)
886 
887  if (!NewWndProc) NewWndProc = pWnd->lpfnWndProc;
888 
889  if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
890  {
891  if (Ansi)
892  {
893  if (GETPFNCLIENTW(Class->fnid) == NewWndProc)
894  chWndProc = GETPFNCLIENTA(Class->fnid);
895  }
896  else
897  {
898  if (GETPFNCLIENTA(Class->fnid) == NewWndProc)
899  chWndProc = GETPFNCLIENTW(Class->fnid);
900  }
901  }
902  // Now set the new window proc.
903  pWnd->lpfnWndProc = (chWndProc ? chWndProc : NewWndProc);
904  }
905  return Ret;
906 }
907 
908 
909 /* INTERNAL ******************************************************************/
910 
912 // This fixes a check for children messages that need paint while searching the parents messages!
913 // Fixes wine msg:test_paint_messages:WmParentErasePaint ..
917 {
919  do
920  {
921  if ( Window == NULL || (Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD )
922  return FALSE;
923 
924  Window = Window->spwndParent;
925  }
926  while(Parent != Window);
927  return TRUE;
928 }
930 
931 /* Link the window into siblings list. Children and parent are kept in place. */
934  PWND Wnd,
935  PWND WndInsertAfter /* Set to NULL if top sibling */
936 )
937 {
938  if (Wnd == WndInsertAfter)
939  {
940  ERR("IntLinkWindow -- Trying to link window 0x%p to itself!!\n", Wnd);
941  return;
942  }
943 
944  Wnd->spwndPrev = WndInsertAfter;
945  if (Wnd->spwndPrev)
946  {
947  /* Link after WndInsertAfter */
948  ASSERT(Wnd != WndInsertAfter->spwndNext);
949  Wnd->spwndNext = WndInsertAfter->spwndNext;
950  if (Wnd->spwndNext)
951  Wnd->spwndNext->spwndPrev = Wnd;
952 
953  ASSERT(Wnd != Wnd->spwndPrev);
954  Wnd->spwndPrev->spwndNext = Wnd;
955  }
956  else
957  {
958  /* Link at the top */
959  ASSERT(Wnd != Wnd->spwndParent->spwndChild);
960  Wnd->spwndNext = Wnd->spwndParent->spwndChild;
961  if (Wnd->spwndNext)
962  Wnd->spwndNext->spwndPrev = Wnd;
963 
964  Wnd->spwndParent->spwndChild = Wnd;
965  }
966 }
967 
968 /*
969  Note: Wnd->spwndParent can be null if it is the desktop.
970 */
972 {
973  if (hWndPrev == HWND_NOTOPMOST)
974  {
975  if (!(Wnd->ExStyle & WS_EX_TOPMOST) && (Wnd->ExStyle2 & WS_EX2_LINKED))
976  return; /* nothing to do */
977  Wnd->ExStyle &= ~WS_EX_TOPMOST;
978  hWndPrev = HWND_TOP; /* fallback to the HWND_TOP case */
979  }
980 
981  IntUnlinkWindow(Wnd); /* unlink it from the previous location */
982 
983  if (hWndPrev == HWND_BOTTOM)
984  {
985  /* Link in the bottom of the list */
986  PWND WndInsertAfter;
987 
988  WndInsertAfter = Wnd->spwndParent->spwndChild;
989  while (WndInsertAfter && WndInsertAfter->spwndNext)
990  {
991  WndInsertAfter = WndInsertAfter->spwndNext;
992  }
993 
994  IntLinkWindow(Wnd, WndInsertAfter);
995  Wnd->ExStyle &= ~WS_EX_TOPMOST;
996  }
997  else if (hWndPrev == HWND_TOPMOST)
998  {
999  /* Link in the top of the list */
1000  IntLinkWindow(Wnd, NULL);
1001  Wnd->ExStyle |= WS_EX_TOPMOST;
1002  }
1003  else if (hWndPrev == HWND_TOP)
1004  {
1005  /* Link it after the last topmost window */
1006  PWND WndInsertBefore;
1007 
1008  WndInsertBefore = Wnd->spwndParent->spwndChild;
1009 
1010  if (!(Wnd->ExStyle & WS_EX_TOPMOST)) /* put it above the first non-topmost window */
1011  {
1012  while (WndInsertBefore != NULL && WndInsertBefore->spwndNext != NULL)
1013  {
1014  if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST))
1015  break;
1016 
1017  if (WndInsertBefore == Wnd->spwndOwner) /* keep it above owner */
1018  {
1019  Wnd->ExStyle |= WS_EX_TOPMOST;
1020  break;
1021  }
1022  WndInsertBefore = WndInsertBefore->spwndNext;
1023  }
1024  }
1025 
1026  IntLinkWindow(Wnd, WndInsertBefore ? WndInsertBefore->spwndPrev : NULL);
1027  }
1028  else
1029  {
1030  /* Link it after hWndPrev */
1031  PWND WndInsertAfter;
1032 
1033  WndInsertAfter = UserGetWindowObject(hWndPrev);
1034  /* Are we called with an erroneous handle */
1035  if (WndInsertAfter == NULL)
1036  {
1037  /* Link in a default position */
1038  IntLinkHwnd(Wnd, HWND_TOP);
1039  return;
1040  }
1041 
1042  if (Wnd == WndInsertAfter)
1043  ERR("IntLinkHwnd -- Trying to link window 0x%p to itself!!\n", Wnd);
1044  IntLinkWindow(Wnd, WndInsertAfter);
1045 
1046  /* Fix the WS_EX_TOPMOST flag */
1047  if (!(WndInsertAfter->ExStyle & WS_EX_TOPMOST))
1048  {
1049  Wnd->ExStyle &= ~WS_EX_TOPMOST;
1050  }
1051  else
1052  {
1053  if (WndInsertAfter->spwndNext &&
1054  (WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST))
1055  {
1056  Wnd->ExStyle |= WS_EX_TOPMOST;
1057  }
1058  }
1059  }
1060  Wnd->ExStyle2 |= WS_EX2_LINKED;
1061 }
1062 
1063 VOID FASTCALL
1064 IntProcessOwnerSwap(PWND Wnd, PWND WndNewOwner, PWND WndOldOwner)
1065 {
1066  if (WndOldOwner)
1067  {
1068  if (Wnd->head.pti != WndOldOwner->head.pti)
1069  {
1070  if (!WndNewOwner ||
1071  Wnd->head.pti == WndNewOwner->head.pti ||
1072  WndOldOwner->head.pti != WndNewOwner->head.pti )
1073  {
1074  //ERR("ProcessOwnerSwap Old out.\n");
1075  UserAttachThreadInput(Wnd->head.pti, WndOldOwner->head.pti, FALSE);
1076  }
1077  }
1078  }
1079  if (WndNewOwner)
1080  {
1081  if (Wnd->head.pti != WndNewOwner->head.pti)
1082  {
1083  if (!WndOldOwner ||
1084  WndOldOwner->head.pti != WndNewOwner->head.pti )
1085  {
1086  //ERR("ProcessOwnerSwap New in.\n");
1087  UserAttachThreadInput(Wnd->head.pti, WndNewOwner->head.pti, TRUE);
1088  }
1089  }
1090  }
1091  // FIXME: System Tray checks.
1092 }
1093 
1094 HWND FASTCALL
1095 IntSetOwner(HWND hWnd, HWND hWndNewOwner)
1096 {
1097  PWND Wnd, WndOldOwner, WndNewOwner;
1098  HWND ret;
1099 
1100  Wnd = IntGetWindowObject(hWnd);
1101  if(!Wnd)
1102  return NULL;
1103 
1104  WndOldOwner = Wnd->spwndOwner;
1105 
1106  ret = WndOldOwner ? UserHMGetHandle(WndOldOwner) : 0;
1107  WndNewOwner = UserGetWindowObject(hWndNewOwner);
1108 
1109  if (!WndNewOwner && hWndNewOwner)
1110  {
1112  ret = NULL;
1113  goto Error;
1114  }
1115 
1116  /* if parent belongs to a different thread and the window isn't */
1117  /* top-level, attach the two threads */
1118  IntProcessOwnerSwap(Wnd, WndNewOwner, WndOldOwner);
1119 
1120  if (IntValidateOwnerDepth(Wnd, WndNewOwner))
1121  {
1122  if (WndNewOwner)
1123  {
1124  Wnd->spwndOwner= WndNewOwner;
1125  }
1126  else
1127  {
1128  Wnd->spwndOwner = NULL;
1129  }
1130  }
1131  else
1132  {
1133  IntProcessOwnerSwap(Wnd, WndOldOwner, WndNewOwner);
1135  ret = NULL;
1136  }
1137 Error:
1138  UserDereferenceObject(Wnd);
1139  return ret;
1140 }
1141 
1142 PWND FASTCALL
1143 co_IntSetParent(PWND Wnd, PWND WndNewParent)
1144 {
1145  PWND WndOldParent, pWndExam;
1146  BOOL WasVisible;
1147  POINT pt;
1148  int swFlags = SWP_NOSIZE|SWP_NOZORDER;
1149 
1150  ASSERT(Wnd);
1151  ASSERT(WndNewParent);
1152  ASSERT_REFS_CO(Wnd);
1153  ASSERT_REFS_CO(WndNewParent);
1154 
1155  if (Wnd == Wnd->head.rpdesk->spwndMessage)
1156  {
1158  return( NULL);
1159  }
1160 
1161  /* Some applications try to set a child as a parent */
1162  if (IntIsChildWindow(Wnd, WndNewParent))
1163  {
1164  TRACE("IntSetParent try to set a child as a parent.\n");
1166  return NULL;
1167  }
1168 
1169  pWndExam = WndNewParent; // Load parent Window to examine.
1170  // Now test for set parent to parent hit.
1171  while (pWndExam)
1172  {
1173  if (Wnd == pWndExam)
1174  {
1175  TRACE("IntSetParent Failed Test for set parent to parent!\n");
1177  return NULL;
1178  }
1179  pWndExam = pWndExam->spwndParent;
1180  }
1181 
1182  /*
1183  * Windows hides the window first, then shows it again
1184  * including the WM_SHOWWINDOW messages and all
1185  */
1186  WasVisible = co_WinPosShowWindow(Wnd, SW_HIDE);
1187 
1188  /* Window must belong to current process */
1189  if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process())
1190  {
1191  ERR("IntSetParent Window must belong to current process!\n");
1192  return NULL;
1193  }
1194 
1195  WndOldParent = Wnd->spwndParent;
1196 
1197  if ( WndOldParent &&
1198  WndOldParent->ExStyle & WS_EX_LAYOUTRTL)
1199  pt.x = Wnd->rcWindow.right;
1200  else
1201  pt.x = Wnd->rcWindow.left;
1202  pt.y = Wnd->rcWindow.top;
1203 
1204  IntScreenToClient(WndOldParent, &pt);
1205 
1206  if (WndOldParent) UserReferenceObject(WndOldParent); /* Caller must deref */
1207 
1208  if (WndNewParent != WndOldParent)
1209  {
1210  /* Unlink the window from the siblings list */
1211  IntUnlinkWindow(Wnd);
1212  Wnd->ExStyle2 &= ~WS_EX2_LINKED;
1213 
1214  /* Set the new parent */
1215  Wnd->spwndParent = WndNewParent;
1216 
1217  if ( Wnd->style & WS_CHILD &&
1218  Wnd->spwndOwner &&
1219  Wnd->spwndOwner->ExStyle & WS_EX_TOPMOST )
1220  {
1221  ERR("SetParent Top Most from Pop up!\n");
1222  Wnd->ExStyle |= WS_EX_TOPMOST;
1223  }
1224 
1225  /* Link the window with its new siblings */
1226  IntLinkHwnd( Wnd,
1227  ((0 == (Wnd->ExStyle & WS_EX_TOPMOST) &&
1228  UserIsDesktopWindow(WndNewParent) ) ? HWND_TOP : HWND_TOPMOST ) );
1229  }
1230 
1231  if ( WndNewParent == co_GetDesktopWindow(Wnd) &&
1232  !(Wnd->style & WS_CLIPSIBLINGS) )
1233  {
1234  Wnd->style |= WS_CLIPSIBLINGS;
1235  DceResetActiveDCEs(Wnd);
1236  }
1237 
1238  /* if parent belongs to a different thread and the window isn't */
1239  /* top-level, attach the two threads */
1240  if ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1241  {
1242  if ( Wnd->spwndParent != co_GetDesktopWindow(Wnd))
1243  {
1244  if (WndOldParent && (Wnd->head.pti != WndOldParent->head.pti))
1245  {
1246  //ERR("SetParent Old out.\n");
1247  UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE);
1248  }
1249  }
1250  if ( WndNewParent != co_GetDesktopWindow(Wnd))
1251  {
1252  if (Wnd->head.pti != WndNewParent->head.pti)
1253  {
1254  //ERR("SetParent New in.\n");
1255  UserAttachThreadInput(Wnd->head.pti, WndNewParent->head.pti, TRUE);
1256  }
1257  }
1258  }
1259 
1260  if (UserIsMessageWindow(WndOldParent) || UserIsMessageWindow(WndNewParent))
1261  swFlags |= SWP_NOACTIVATE;
1262 
1263  IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1264  /*
1265  * SetParent additionally needs to make hwnd the top window
1266  * in the z-order and send the expected WM_WINDOWPOSCHANGING and
1267  * WM_WINDOWPOSCHANGED notification messages.
1268  */
1269  //ERR("IntSetParent SetWindowPos 1\n");
1270  co_WinPosSetWindowPos( Wnd,
1271  (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST),
1272  pt.x, pt.y, 0, 0, swFlags);
1273  //ERR("IntSetParent SetWindowPos 2 X %d Y %d\n",pt.x, pt.y);
1274  if (WasVisible) co_WinPosShowWindow(Wnd, SW_SHOWNORMAL);
1275 
1276  return WndOldParent;
1277 }
1278 
1279 // Win: xxxSetParent
1280 HWND FASTCALL
1282 {
1283  PWND Wnd = NULL, WndParent = NULL, WndOldParent;
1284  HWND hWndOldParent = NULL;
1285  USER_REFERENCE_ENTRY Ref, ParentRef;
1286 
1287  if (IntIsBroadcastHwnd(hWndChild) || IntIsBroadcastHwnd(hWndNewParent))
1288  {
1290  return( NULL);
1291  }
1292 
1293  if (hWndChild == IntGetDesktopWindow())
1294  {
1295  ERR("UserSetParent Access Denied!\n");
1297  return( NULL);
1298  }
1299 
1300  if (hWndNewParent)
1301  {
1302  if (!(WndParent = UserGetWindowObject(hWndNewParent)))
1303  {
1304  ERR("UserSetParent Bad New Parent!\n");
1305  return( NULL);
1306  }
1307  }
1308  else
1309  {
1310  if (!(WndParent = UserGetWindowObject(IntGetDesktopWindow())))
1311  {
1312  return( NULL);
1313  }
1314  }
1315 
1316  if (!(Wnd = UserGetWindowObject(hWndChild)))
1317  {
1318  ERR("UserSetParent Bad Child!\n");
1319  return( NULL);
1320  }
1321 
1322  UserRefObjectCo(Wnd, &Ref);
1323  UserRefObjectCo(WndParent, &ParentRef);
1324  //ERR("Enter co_IntSetParent\n");
1325  WndOldParent = co_IntSetParent(Wnd, WndParent);
1326  //ERR("Leave co_IntSetParent\n");
1327  UserDerefObjectCo(WndParent);
1328  UserDerefObjectCo(Wnd);
1329 
1330  if (WndOldParent)
1331  {
1332  hWndOldParent = WndOldParent->head.h;
1333  UserDereferenceObject(WndOldParent);
1334  }
1335 
1336  return( hWndOldParent);
1337 }
1338 
1339 /* Unlink the window from siblings. Children and parent are kept in place. */
1340 VOID FASTCALL
1342 {
1343  ASSERT(Wnd != Wnd->spwndNext);
1344  ASSERT(Wnd != Wnd->spwndPrev);
1345 
1346  if (Wnd->spwndNext)
1347  Wnd->spwndNext->spwndPrev = Wnd->spwndPrev;
1348 
1349  if (Wnd->spwndPrev)
1350  Wnd->spwndPrev->spwndNext = Wnd->spwndNext;
1351 
1352  if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd)
1353  Wnd->spwndParent->spwndChild = Wnd->spwndNext;
1354 
1355  Wnd->spwndPrev = Wnd->spwndNext = NULL;
1356 }
1357 
1358 // Win: ExpandWindowList
1360 {
1361  PWINDOWLIST pwlOld, pwlNew;
1362  SIZE_T ibOld, ibNew;
1363 
1364 #define GROW_COUNT 8
1365  pwlOld = *ppwl;
1366  ibOld = (LPBYTE)pwlOld->phwndLast - (LPBYTE)pwlOld;
1367  ibNew = ibOld + GROW_COUNT * sizeof(HWND);
1368 #undef GROW_COUNT
1369  pwlNew = IntReAllocatePoolWithTag(PagedPool, pwlOld, ibOld, ibNew, USERTAG_WINDOWLIST);
1370  if (!pwlNew)
1371  return FALSE;
1372 
1373  pwlNew->phwndLast = (HWND *)((LPBYTE)pwlNew + ibOld);
1374  pwlNew->phwndEnd = (HWND *)((LPBYTE)pwlNew + ibNew);
1375  *ppwl = pwlNew;
1376  return TRUE;
1377 }
1378 
1379 // Win: InternalBuildHwndList
1381 {
1382  ASSERT(!WL_IS_BAD(pwl));
1383 
1384  for (; pwnd; pwnd = pwnd->spwndNext)
1385  {
1386  if (!pwl->pti || pwl->pti == pwnd->head.pti)
1387  {
1388  *(pwl->phwndLast) = UserHMGetHandle(pwnd);
1389  ++(pwl->phwndLast);
1390 
1391  if (pwl->phwndLast == pwl->phwndEnd && !IntGrowHwndList(&pwl))
1392  break;
1393  }
1394 
1395  if ((dwFlags & IACE_CHILDREN) && pwnd->spwndChild)
1396  {
1398  if (WL_IS_BAD(pwl))
1399  break;
1400  }
1401 
1402  if (!(dwFlags & IACE_LIST))
1403  break;
1404  }
1405 
1406  return pwl;
1407 }
1408 
1409 // Win: BuildHwndList
1411 {
1412  PWINDOWLIST pwl;
1413  DWORD cbWL;
1414 
1415  if (gpwlCache)
1416  {
1417  pwl = gpwlCache;
1418  gpwlCache = NULL;
1419  }
1420  else
1421  {
1422 #define INITIAL_COUNT 32
1423  cbWL = sizeof(WINDOWLIST) + (INITIAL_COUNT - 1) * sizeof(HWND);
1425  if (!pwl)
1426  return NULL;
1427 
1428  pwl->phwndEnd = &pwl->ahwnd[INITIAL_COUNT];
1429 #undef INITIAL_COUNT
1430  }
1431 
1432  pwl->pti = pti;
1433  pwl->phwndLast = pwl->ahwnd;
1434  pwl = IntPopulateHwndList(pwl, pwnd, dwFlags);
1435  if (WL_IS_BAD(pwl))
1436  {
1438  return NULL;
1439  }
1440 
1441  *(pwl->phwndLast) = HWND_TERMINATOR;
1442 
1443  if (dwFlags & 0x8)
1444  {
1445  // TODO:
1446  }
1447 
1448  pwl->pti = GetW32ThreadInfo();
1449  pwl->pNextList = gpwlList;
1450  gpwlList = pwl;
1451 
1452  return pwl;
1453 }
1454 
1455 // Win: FreeHwndList
1457 {
1458  PWINDOWLIST pwl, *ppwl;
1459 
1460  for (ppwl = &gpwlList; *ppwl; ppwl = &(*ppwl)->pNextList)
1461  {
1462  if (*ppwl != pwlTarget)
1463  continue;
1464 
1465  *ppwl = pwlTarget->pNextList;
1466 
1467  if (gpwlCache)
1468  {
1469  if (WL_CAPACITY(pwlTarget) > WL_CAPACITY(gpwlCache))
1470  {
1471  pwl = gpwlCache;
1472  gpwlCache = pwlTarget;
1474  }
1475  else
1476  {
1478  }
1479  }
1480  else
1481  {
1482  gpwlCache = pwlTarget;
1483  }
1484 
1485  break;
1486  }
1487 }
1488 
1489 /* FUNCTIONS *****************************************************************/
1490 
1491 /*
1492  * As best as I can figure, this function is used by EnumWindows,
1493  * EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
1494  *
1495  * It's supposed to build a list of HWNDs to return to the caller.
1496  * We can figure out what kind of list by what parameters are
1497  * passed to us.
1498  */
1499 /*
1500  * @implemented
1501  */
1502 NTSTATUS
1503 NTAPI
1505  HDESK hDesktop,
1506  HWND hwndParent,
1507  BOOLEAN bChildren,
1508  ULONG dwThreadId,
1509  ULONG cHwnd,
1510  HWND* phwndList,
1511  ULONG* pcHwndNeeded)
1512 {
1513  NTSTATUS Status;
1514  ULONG dwCount = 0;
1515 
1516  if (pcHwndNeeded == NULL)
1517  return STATUS_INVALID_PARAMETER;
1518 
1520 
1521  if (hwndParent || !dwThreadId)
1522  {
1523  PDESKTOP Desktop;
1524  PWND Parent, Window;
1525 
1526  if(!hwndParent)
1527  {
1528  if(hDesktop == NULL && !(Desktop = IntGetActiveDesktop()))
1529  {
1531  goto Quit;
1532  }
1533 
1534  if(hDesktop)
1535  {
1536  Status = IntValidateDesktopHandle(hDesktop,
1537  UserMode,
1538  0,
1539  &Desktop);
1540  if(!NT_SUCCESS(Status))
1541  {
1543  goto Quit;
1544  }
1545  }
1546  hwndParent = Desktop->DesktopWindow;
1547  }
1548  else
1549  {
1550  hDesktop = 0;
1551  }
1552 
1554  (Window = Parent->spwndChild))
1555  {
1556  BOOL bGoDown = TRUE;
1557 
1559  while(TRUE)
1560  {
1561  if (bGoDown)
1562  {
1563  if (dwCount++ < cHwnd && phwndList)
1564  {
1565  _SEH2_TRY
1566  {
1567  ProbeForWrite(phwndList, sizeof(HWND), 1);
1568  *phwndList = Window->head.h;
1569  phwndList++;
1570  }
1572  {
1574  }
1575  _SEH2_END
1576  if(!NT_SUCCESS(Status))
1577  {
1578  break;
1579  }
1580  }
1581  if (Window->spwndChild && bChildren)
1582  {
1583  Window = Window->spwndChild;
1584  continue;
1585  }
1586  bGoDown = FALSE;
1587  }
1588  if (Window->spwndNext)
1589  {
1590  Window = Window->spwndNext;
1591  bGoDown = TRUE;
1592  continue;
1593  }
1594  Window = Window->spwndParent;
1595  if (Window == Parent)
1596  {
1597  break;
1598  }
1599  }
1600  }
1601 
1602  if(hDesktop)
1603  {
1605  }
1606  }
1607  else // Build EnumThreadWindows list!
1608  {
1609  PETHREAD Thread;
1610  PTHREADINFO W32Thread;
1611  PWND Window;
1612  HWND *List = NULL;
1613 
1615  if (!NT_SUCCESS(Status))
1616  {
1617  ERR("Thread Id is not valid!\n");
1619  goto Quit;
1620  }
1621  if (!(W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread))
1622  {
1624  TRACE("Tried to enumerate windows of a non gui thread\n");
1626  goto Quit;
1627  }
1628 
1629  // Do not use Thread link list due to co_UserFreeWindow!!!
1630  // Current = W32Thread->WindowListHead.Flink;
1631  // Fixes Api:CreateWindowEx tests!!!
1633  if (List)
1634  {
1635  int i;
1636  for (i = 0; List[i]; i++)
1637  {
1639  if (Window && Window->head.pti == W32Thread)
1640  {
1641  if (dwCount < cHwnd && phwndList)
1642  {
1643  _SEH2_TRY
1644  {
1645  ProbeForWrite(phwndList, sizeof(HWND), 1);
1646  *phwndList = Window->head.h;
1647  phwndList++;
1648  }
1650  {
1652  }
1653  _SEH2_END
1654  if (!NT_SUCCESS(Status))
1655  {
1656  ERR("Failure to build window list!\n");
1657  break;
1658  }
1659  }
1660  dwCount++;
1661  }
1662  }
1664  }
1665 
1667  }
1668 
1669  *pcHwndNeeded = dwCount;
1671 
1672 Quit:
1674  UserLeave();
1675  return Status;
1676 }
1677 
1678 static void IntSendParentNotify( PWND pWindow, UINT msg )
1679 {
1680  if ( (pWindow->style & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
1681  !(pWindow->ExStyle & WS_EX_NOPARENTNOTIFY))
1682  {
1683  if (VerifyWnd(pWindow->spwndParent) && !UserIsDesktopWindow(pWindow->spwndParent))
1684  {
1686  UserRefObjectCo(pWindow->spwndParent, &Ref);
1687  co_IntSendMessage( pWindow->spwndParent->head.h,
1689  MAKEWPARAM( msg, pWindow->IDMenu),
1690  (LPARAM)pWindow->head.h );
1691  UserDerefObjectCo(pWindow->spwndParent);
1692  }
1693  }
1694 }
1695 
1696 void FASTCALL
1697 IntFixWindowCoordinates(CREATESTRUCTW* Cs, PWND ParentWindow, DWORD* dwShowMode)
1698 {
1699 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == (SHORT)0x8000)
1700 
1701  /* default positioning for overlapped windows */
1702  if(!(Cs->style & (WS_POPUP | WS_CHILD)))
1703  {
1704  PMONITOR pMonitor;
1705  PRTL_USER_PROCESS_PARAMETERS ProcessParams;
1706 
1707  pMonitor = UserGetPrimaryMonitor();
1708 
1709  /* Check if we don't have a monitor attached yet */
1710  if(pMonitor == NULL)
1711  {
1712  Cs->x = Cs->y = 0;
1713  Cs->cx = 800;
1714  Cs->cy = 600;
1715  return;
1716  }
1717 
1718  ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;
1719 
1720  if (IS_DEFAULT(Cs->x))
1721  {
1722  if (!IS_DEFAULT(Cs->y)) *dwShowMode = Cs->y;
1723 
1724  if(ProcessParams->WindowFlags & STARTF_USEPOSITION)
1725  {
1726  Cs->x = ProcessParams->StartingX;
1727  Cs->y = ProcessParams->StartingY;
1728  }
1729  else
1730  {
1733  if (Cs->x > ((pMonitor->rcWork.right - pMonitor->rcWork.left) / 4) ||
1734  Cs->y > ((pMonitor->rcWork.bottom - pMonitor->rcWork.top) / 4))
1735  {
1736  /* reset counter and position */
1737  Cs->x = 0;
1738  Cs->y = 0;
1739  pMonitor->cWndStack = 0;
1740  }
1741  pMonitor->cWndStack++;
1742  }
1743  }
1744 
1745  if (IS_DEFAULT(Cs->cx))
1746  {
1747  if (ProcessParams->WindowFlags & STARTF_USEPOSITION)
1748  {
1749  Cs->cx = ProcessParams->CountX;
1750  Cs->cy = ProcessParams->CountY;
1751  }
1752  else
1753  {
1754  Cs->cx = (pMonitor->rcWork.right - pMonitor->rcWork.left) * 3 / 4;
1755  Cs->cy = (pMonitor->rcWork.bottom - pMonitor->rcWork.top) * 3 / 4;
1756  }
1757  }
1758  /* neither x nor cx are default. Check the y values .
1759  * In the trace we see Outlook and Outlook Express using
1760  * cy set to CW_USEDEFAULT when opening the address book.
1761  */
1762  else if (IS_DEFAULT(Cs->cy))
1763  {
1764  TRACE("Strange use of CW_USEDEFAULT in nHeight\n");
1765  Cs->cy = (pMonitor->rcWork.bottom - pMonitor->rcWork.top) * 3 / 4;
1766  }
1767  }
1768  else
1769  {
1770  /* if CW_USEDEFAULT is set for non-overlapped windows, both values are set to zero */
1771  if(IS_DEFAULT(Cs->x))
1772  {
1773  Cs->x = 0;
1774  Cs->y = 0;
1775  }
1776  if(IS_DEFAULT(Cs->cx))
1777  {
1778  Cs->cx = 0;
1779  Cs->cy = 0;
1780  }
1781  }
1782 
1783 #undef IS_DEFAULT
1784 }
1785 
1786 /* Allocates and initializes a window */
1788  PLARGE_STRING WindowName,
1789  PCLS Class,
1790  PWND ParentWindow,
1791  PWND OwnerWindow,
1792  PVOID acbiBuffer,
1793  PDESKTOP pdeskCreated,
1794  DWORD dwVer )
1795 {
1796  PWND pWnd = NULL;
1797  HWND hWnd;
1798  PTHREADINFO pti;
1799  BOOL MenuChanged;
1800  BOOL bUnicodeWindow;
1801  PCALLPROCDATA pcpd;
1802 
1803  pti = pdeskCreated ? gptiDesktopThread : GetW32ThreadInfo();
1804 
1805  if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL))
1806  { // Need both here for wine win.c test_CreateWindow.
1807  //if (Cs->hwndParent && ParentWindow)
1808  if (ParentWindow) // It breaks more tests..... WIP.
1809  {
1810  if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD &&
1811  ParentWindow->ExStyle & WS_EX_LAYOUTRTL &&
1812  !(ParentWindow->ExStyle & WS_EX_NOINHERITLAYOUT) )
1813  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
1814  }
1815  else
1816  { /*
1817  * Note from MSDN <http://msdn.microsoft.com/en-us/library/aa913269.aspx>:
1818  *
1819  * Dialog boxes and message boxes do not inherit layout, so you must
1820  * set the layout explicitly.
1821  */
1822  if ( Class->fnid != FNID_DIALOG )
1823  {
1824  if (pti->ppi->dwLayout & LAYOUT_RTL)
1825  {
1826  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
1827  }
1828  }
1829  }
1830  }
1831 
1832  /* Automatically add WS_EX_WINDOWEDGE */
1833  if ((Cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1834  ((!(Cs->dwExStyle & WS_EX_STATICEDGE)) &&
1835  (Cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1836  Cs->dwExStyle |= WS_EX_WINDOWEDGE;
1837  else
1838  Cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1839 
1840  /* Is it a unicode window? */
1841  bUnicodeWindow =!(Cs->dwExStyle & WS_EX_SETANSICREATOR);
1843 
1844  /* Allocate the new window */
1846  pdeskCreated ? pdeskCreated : pti->rpdesk,
1847  pti,
1848  (PHANDLE)&hWnd,
1849  TYPE_WINDOW,
1850  sizeof(WND) + Class->cbwndExtra);
1851 
1852  if (!pWnd)
1853  {
1854  goto AllocError;
1855  }
1856 
1857  TRACE("Created window object with handle %p\n", hWnd);
1858 
1859  if (pdeskCreated && pdeskCreated->DesktopWindow == NULL )
1860  { /* HACK: Helper for win32csr/desktopbg.c */
1861  /* If there is no desktop window yet, we must be creating it */
1862  TRACE("CreateWindow setting desktop.\n");
1863  pdeskCreated->DesktopWindow = hWnd;
1864  pdeskCreated->pDeskInfo->spwnd = pWnd;
1865  }
1866 
1867  /*
1868  * Fill out the structure describing it.
1869  */
1870  /* Remember, pWnd->head is setup in object.c ... */
1871  pWnd->spwndParent = ParentWindow;
1872  pWnd->spwndOwner = OwnerWindow;
1873  pWnd->fnid = 0;
1874  pWnd->spwndLastActive = pWnd;
1875  // Ramp up compatible version sets.
1876  if ( dwVer >= WINVER_WIN31 )
1877  {
1878  pWnd->state2 |= WNDS2_WIN31COMPAT;
1879  if ( dwVer >= WINVER_WINNT4 )
1880  {
1881  pWnd->state2 |= WNDS2_WIN40COMPAT;
1882  if ( dwVer >= WINVER_WIN2K )
1883  {
1884  pWnd->state2 |= WNDS2_WIN50COMPAT;
1885  }
1886  }
1887  }
1888  pWnd->pcls = Class;
1889  pWnd->hModule = Cs->hInstance;
1890  pWnd->style = Cs->style & ~WS_VISIBLE;
1891  pWnd->ExStyle = Cs->dwExStyle;
1892  pWnd->cbwndExtra = pWnd->pcls->cbwndExtra;
1893  pWnd->pActCtx = acbiBuffer;
1894 
1895  if (pti->spDefaultImc && Class->atomClassName != gpsi->atomSysClass[ICLS_BUTTON])
1896  pWnd->hImc = UserHMGetHandle(pti->spDefaultImc);
1897 
1898  pWnd->InternalPos.MaxPos.x = pWnd->InternalPos.MaxPos.y = -1;
1899  pWnd->InternalPos.IconPos.x = pWnd->InternalPos.IconPos.y = -1;
1900 
1901  if (pWnd->spwndParent != NULL && Cs->hwndParent != 0)
1902  {
1903  pWnd->HideFocus = pWnd->spwndParent->HideFocus;
1904  pWnd->HideAccel = pWnd->spwndParent->HideAccel;
1905  }
1906 
1907  pWnd->head.pti->cWindows++;
1908 
1909  if (Class->spicn && !Class->spicnSm)
1910  {
1911  HICON IconSmHandle = NULL;
1912  if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
1914  {
1915  IconSmHandle = co_IntCopyImage(
1916  UserHMGetHandle(Class->spicn),
1917  IMAGE_ICON,
1921  }
1922  if (!IconSmHandle)
1923  {
1924  /* Retry without copying from resource */
1925  IconSmHandle = co_IntCopyImage(
1926  UserHMGetHandle(Class->spicn),
1927  IMAGE_ICON,
1930  0);
1931  }
1932 
1933  if (IconSmHandle)
1934  {
1935  Class->spicnSm = UserGetCurIconObject(IconSmHandle);
1936  Class->CSF_flags |= CSF_CACHEDSMICON;
1937  }
1938  }
1939 
1940  if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
1942 
1943  /* BugBoy Comments: Comment below say that System classes are always created
1944  as UNICODE. In windows, creating a window with the ANSI version of CreateWindow
1945  sets the window to ansi as verified by testing with IsUnicodeWindow API.
1946 
1947  No where can I see in code or through testing does the window change back
1948  to ANSI after being created as UNICODE in ROS. I didnt do more testing to
1949  see what problems this would cause. */
1950 
1951  // Set WndProc from Class.
1952  if (IsCallProcHandle(pWnd->pcls->lpfnWndProc))
1953  {
1955  if (pcpd)
1956  pWnd->lpfnWndProc = pcpd->pfnClientPrevious;
1957  }
1958  else
1959  {
1960  pWnd->lpfnWndProc = pWnd->pcls->lpfnWndProc;
1961  }
1962 
1963  // GetWindowProc, test for non server side default classes and set WndProc.
1964  if ( pWnd->pcls->fnid <= FNID_GHOST && pWnd->pcls->fnid >= FNID_BUTTON )
1965  {
1966  if (bUnicodeWindow)
1967  {
1968  if (GETPFNCLIENTA(pWnd->pcls->fnid) == pWnd->lpfnWndProc)
1969  pWnd->lpfnWndProc = GETPFNCLIENTW(pWnd->pcls->fnid);
1970  }
1971  else
1972  {
1973  if (GETPFNCLIENTW(pWnd->pcls->fnid) == pWnd->lpfnWndProc)
1974  pWnd->lpfnWndProc = GETPFNCLIENTA(pWnd->pcls->fnid);
1975  }
1976  }
1977 
1978  // If not an Unicode caller, set Ansi creator bit.
1979  if (!bUnicodeWindow) pWnd->state |= WNDS_ANSICREATOR;
1980 
1981  // Clone Class Ansi/Unicode proc type.
1982  if (pWnd->pcls->CSF_flags & CSF_ANSIPROC)
1983  {
1984  pWnd->state |= WNDS_ANSIWINDOWPROC;
1985  pWnd->Unicode = FALSE;
1986  }
1987  else
1988  { /*
1989  * It seems there can be both an Ansi creator and Unicode Class Window
1990  * WndProc, unless the following overriding conditions occur:
1991  */
1992  if ( !bUnicodeWindow &&
1993  ( Class->atomClassName == gpsi->atomSysClass[ICLS_BUTTON] ||
1994  Class->atomClassName == gpsi->atomSysClass[ICLS_COMBOBOX] ||
1995  Class->atomClassName == gpsi->atomSysClass[ICLS_COMBOLBOX] ||
1996  Class->atomClassName == gpsi->atomSysClass[ICLS_DIALOG] ||
1997  Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT] ||
1998  Class->atomClassName == gpsi->atomSysClass[ICLS_IME] ||
1999  Class->atomClassName == gpsi->atomSysClass[ICLS_LISTBOX] ||
2000  Class->atomClassName == gpsi->atomSysClass[ICLS_MDICLIENT] ||
2001  Class->atomClassName == gpsi->atomSysClass[ICLS_STATIC] ) )
2002  { // Override Class and set the window Ansi WndProc.
2003  pWnd->state |= WNDS_ANSIWINDOWPROC;
2004  pWnd->Unicode = FALSE;
2005  }
2006  else
2007  { // Set the window Unicode WndProc.
2008  pWnd->state &= ~WNDS_ANSIWINDOWPROC;
2009  pWnd->Unicode = TRUE;
2010  }
2011  }
2012 
2013  /* BugBoy Comments: if the window being created is a edit control, ATOM 0xCxxx,
2014  then my testing shows that windows (2k and XP) creates a CallProc for it immediately
2015  Dont understand why it does this. */
2016  if (Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT])
2017  {
2018  PCALLPROCDATA CallProc;
2019  CallProc = CreateCallProc(pWnd->head.rpdesk, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
2020 
2021  if (!CallProc)
2022  {
2024  ERR("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %p\n", hWnd);
2025  }
2026  else
2027  {
2028  UserAddCallProcToClass(pWnd->pcls, CallProc);
2029  }
2030  }
2031 
2033  pWnd->PropListItems = 0;
2034 
2035  if ( WindowName->Buffer != NULL && WindowName->Length > 0 )
2036  {
2037  pWnd->strName.Buffer = DesktopHeapAlloc(pWnd->head.rpdesk,
2038  WindowName->Length + sizeof(UNICODE_NULL));
2039  if (pWnd->strName.Buffer == NULL)
2040  {
2041  goto AllocError;
2042  }
2043 
2044  RtlCopyMemory(pWnd->strName.Buffer, WindowName->Buffer, WindowName->Length);
2045  pWnd->strName.Buffer[WindowName->Length / sizeof(WCHAR)] = L'\0';
2046  pWnd->strName.Length = WindowName->Length;
2047  pWnd->strName.MaximumLength = WindowName->Length + sizeof(UNICODE_NULL);
2048  }
2049 
2050  /* Create the IME window for pWnd */
2051  if (IS_IMM_MODE() && !(pti->spwndDefaultIme) && IntWantImeWindow(pWnd))
2052  {
2053  PWND pwndDefaultIme = co_IntCreateDefaultImeWindow(pWnd, pWnd->hModule);
2054  UserAssignmentLock((PVOID*)&(pti->spwndDefaultIme), pwndDefaultIme);
2055 
2056  if (pwndDefaultIme && (pti->pClientInfo->CI_flags & CI_IMMACTIVATE))
2057  {
2059  HKL hKL;
2060 
2061  UserRefObjectCo(pwndDefaultIme, &Ref);
2062 
2063  hKL = pti->KeyboardLayout->hkl;
2065  IMS_ACTIVATELAYOUT, (LPARAM)hKL);
2066  pti->pClientInfo->CI_flags &= ~CI_IMMACTIVATE;
2067 
2068  UserDerefObjectCo(pwndDefaultIme);
2069  }
2070  }
2071 
2072  /* Correct the window style. */
2073  if ((pWnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2074  {
2075  pWnd->style |= WS_CLIPSIBLINGS;
2076  if (!(pWnd->style & WS_POPUP))
2077  {
2078  pWnd->style |= WS_CAPTION;
2079  }
2080  }
2081 
2082  /* WS_EX_WINDOWEDGE depends on some other styles */
2083  if (pWnd->ExStyle & WS_EX_DLGMODALFRAME)
2084  pWnd->ExStyle |= WS_EX_WINDOWEDGE;
2085  else if (pWnd->style & (WS_DLGFRAME | WS_THICKFRAME))
2086  {
2087  if (!((pWnd->ExStyle & WS_EX_STATICEDGE) &&
2088  (pWnd->style & (WS_CHILD | WS_POPUP))))
2089  pWnd->ExStyle |= WS_EX_WINDOWEDGE;
2090  }
2091  else
2092  pWnd->ExStyle &= ~WS_EX_WINDOWEDGE;
2093 
2094  if (!(pWnd->style & (WS_CHILD | WS_POPUP)))
2095  pWnd->state |= WNDS_SENDSIZEMOVEMSGS;
2096 
2097  /* Set the window menu */
2098  if ((Cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2099  {
2100  if (Cs->hMenu)
2101  {
2102  IntSetMenu(pWnd, Cs->hMenu, &MenuChanged);
2103  }
2104  else if (pWnd->pcls->lpszMenuName) // Take it from the parent.
2105  {
2106  UNICODE_STRING MenuName;
2107  HMENU hMenu;
2108 
2109  if (IS_INTRESOURCE(pWnd->pcls->lpszMenuName))
2110  {
2111  MenuName.Length = 0;
2112  MenuName.MaximumLength = 0;
2113  MenuName.Buffer = pWnd->pcls->lpszMenuName;
2114  }
2115  else
2116  {
2117  RtlInitUnicodeString( &MenuName, pWnd->pcls->lpszMenuName);
2118  }
2119  hMenu = co_IntCallLoadMenu( pWnd->pcls->hModule, &MenuName);
2120  if (hMenu) IntSetMenu(pWnd, hMenu, &MenuChanged);
2121  }
2122  }
2123  else // Not a child
2124  pWnd->IDMenu = (UINT_PTR)Cs->hMenu;
2125 
2126 
2127  if ( ParentWindow &&
2128  ParentWindow != ParentWindow->head.rpdesk->spwndMessage &&
2129  ParentWindow != ParentWindow->head.rpdesk->pDeskInfo->spwnd )
2130  {
2131  PWND Owner = IntGetNonChildAncestor(ParentWindow);
2132 
2133  if (!IntValidateOwnerDepth(pWnd, Owner))
2134  {
2136  goto Error;
2137  }
2138  if ( pWnd->spwndOwner &&
2139  pWnd->spwndOwner->ExStyle & WS_EX_TOPMOST )
2140  {
2141  pWnd->ExStyle |= WS_EX_TOPMOST;
2142  }
2143  if ( pWnd->spwndOwner &&
2144  Class->atomClassName != gpsi->atomSysClass[ICLS_IME] &&
2145  pti != pWnd->spwndOwner->head.pti)
2146  {
2147  //ERR("CreateWindow Owner in.\n");
2148  UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE);
2149  }
2150  }
2151 
2152  /* Insert the window into the thread's window list. */
2154 
2155  /* Handle "CS_CLASSDC", it is tested first. */
2156  if ( (pWnd->pcls->style & CS_CLASSDC) && !(pWnd->pcls->pdce) )
2157  { /* One DCE per class to have CLASS. */
2158  pWnd->pcls->pdce = DceAllocDCE( pWnd, DCE_CLASS_DC );
2159  }
2160  else if ( pWnd->pcls->style & CS_OWNDC)
2161  { /* Allocate a DCE for this window. */
2162  DceAllocDCE(pWnd, DCE_WINDOW_DC);
2163  }
2164 
2165  return pWnd;
2166 
2167 AllocError:
2168  ERR("IntCreateWindow Allocation Error.\n");
2170 Error:
2171  if(pWnd)
2172  UserDereferenceObject(pWnd);
2173  return NULL;
2174 }
2175 
2176 /*
2177  * @implemented
2178  */
2179 PWND FASTCALL
2181  PUNICODE_STRING ClassName,
2182  PLARGE_STRING WindowName,
2183  PVOID acbiBuffer,
2184  DWORD dwVer )
2185 {
2186  ULONG style;
2187  PWND Window = NULL, ParentWindow = NULL, OwnerWindow;
2188  HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter;
2189  PWINSTATION_OBJECT WinSta;
2190  PCLS Class = NULL;
2191  SIZE Size;
2192  POINT MaxSize, MaxPos, MinTrack, MaxTrack;
2193  CBT_CREATEWNDW * pCbtCreate;
2194  LRESULT Result;
2195  USER_REFERENCE_ENTRY ParentRef, Ref;
2196  PTHREADINFO pti;
2197  DWORD dwShowMode = SW_SHOW;
2198  CREATESTRUCTW *pCsw = NULL;
2199  PVOID pszClass = NULL, pszName = NULL;
2200  PWND ret = NULL;
2201 
2202  /* Get the current window station and reference it */
2203  pti = GetW32ThreadInfo();
2204  if (pti == NULL || pti->rpdesk == NULL)
2205  {
2206  ERR("Thread is not attached to a desktop! Cannot create window!\n");
2207  return NULL; // There is nothing to cleanup.
2208  }
2209  WinSta = pti->rpdesk->rpwinstaParent;
2211 
2212  pCsw = NULL;
2213  pCbtCreate = NULL;
2214 
2215  /* Get the class and reference it */
2216  Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
2217  if(!Class)
2218  {
2220  ERR("Failed to find class %wZ\n", ClassName);
2221  goto cleanup;
2222  }
2223 
2224  /* Now find the parent and the owner window */
2225  hWndParent = pti->rpdesk->pDeskInfo->spwnd->head.h;
2226  hWndOwner = NULL;
2227 
2228  if (Cs->hwndParent == HWND_MESSAGE)
2229  {
2230  Cs->hwndParent = hWndParent = pti->rpdesk->spwndMessage->head.h;
2231  }
2232  else if (Cs->hwndParent)
2233  {
2234  if ((Cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
2235  hWndOwner = Cs->hwndParent;
2236  else
2237  hWndParent = Cs->hwndParent;
2238  }
2239  else if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2240  {
2241  ERR("Cannot create a child window without a parent!\n");
2243  goto cleanup; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
2244  }
2246  (IS_INTRESOURCE(Cs->lpszClass) ||
2247  Cs->lpszClass != (LPCWSTR)MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]) ||
2248  _wcsicmp(Cs->lpszClass, L"Message") != 0))
2249  {
2250  if (pti->ppi->dwLayout & LAYOUT_RTL)
2251  {
2252  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
2253  }
2254  }
2255 
2256  ParentWindow = hWndParent ? UserGetWindowObject(hWndParent): NULL;
2257  OwnerWindow = hWndOwner ? UserGetWindowObject(hWndOwner): NULL;
2258 
2259  if (hWndParent && !ParentWindow)
2260  {
2261  ERR("Got invalid parent window handle\n");
2262  goto cleanup;
2263  }
2264  else if (hWndOwner && !OwnerWindow)
2265  {
2266  ERR("Got invalid owner window handle\n");
2267  ParentWindow = NULL;
2268  goto cleanup;
2269  }
2270 
2271  if(OwnerWindow)
2272  {
2273  if (IntIsDesktopWindow(OwnerWindow)) OwnerWindow = NULL;
2274  else if (ParentWindow && !IntIsDesktopWindow(ParentWindow))
2275  {
2276  ERR("an owned window must be created as top-level\n");
2278  goto cleanup;
2279  }
2280  else /* owner must be a top-level window */
2281  {
2282  while ((OwnerWindow->style & (WS_POPUP|WS_CHILD)) == WS_CHILD && !IntIsDesktopWindow(OwnerWindow->spwndParent))
2283  OwnerWindow = OwnerWindow->spwndParent;
2284  }
2285  }
2286 
2287  /* Fix the position and the size of the window */
2288  if (ParentWindow)
2289  {
2290  UserRefObjectCo(ParentWindow, &ParentRef);
2291  IntFixWindowCoordinates(Cs, ParentWindow, &dwShowMode);
2292  }
2293 
2294  /* Allocate and initialize the new window */
2295  Window = IntCreateWindow(Cs,
2296  WindowName,
2297  Class,
2298  ParentWindow,
2299  OwnerWindow,
2300  acbiBuffer,
2301  NULL,
2302  dwVer );
2303  if(!Window)
2304  {
2305  ERR("IntCreateWindow failed!\n");
2306  goto cleanup;
2307  }
2308 
2310  hwndInsertAfter = HWND_TOP;
2311 
2312  UserRefObjectCo(Window, &Ref);
2314  ObDereferenceObject(WinSta);
2315 
2316  /* NCCREATE, WM_NCCALCSIZE and Hooks need the original values */
2317  Cs->lpszName = (LPCWSTR) WindowName;
2318  Cs->lpszClass = (LPCWSTR) ClassName;
2319 
2321  if ( ISITHOOKED(WH_CBT) || (pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)) )
2322  {
2323  // Allocate the calling structures Justin Case this goes Global.
2326  if (!pCsw || !pCbtCreate)
2327  {
2328  ERR("UserHeapAlloc() failed!\n");
2329  goto cleanup;
2330  }
2331 
2332  if (!IntMsgCreateStructW( Window, pCsw, Cs, &pszClass, &pszName ) )
2333  {
2334  ERR("IntMsgCreateStructW() failed!\n");
2335  goto cleanup;
2336  }
2337 
2338  pCbtCreate->lpcs = pCsw;
2339  pCbtCreate->hwndInsertAfter = hwndInsertAfter;
2340 
2343  if (Result != 0)
2344  {
2345  ERR("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
2346  goto cleanup;
2347  }
2348  // Write back changes.
2349  Cs->cx = pCsw->cx;
2350  Cs->cy = pCsw->cy;
2351  Cs->x = pCsw->x;
2352  Cs->y = pCsw->y;
2353  hwndInsertAfter = pCbtCreate->hwndInsertAfter;
2354  }
2355 
2356  if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2357  {
2358  if (ParentWindow != co_GetDesktopWindow(Window))
2359  {
2360  Cs->x += ParentWindow->rcClient.left;
2361  Cs->y += ParentWindow->rcClient.top;
2362  }
2363  }
2364 
2365  /* Send the WM_GETMINMAXINFO message */
2366  Size.cx = Cs->cx;
2367  Size.cy = Cs->cy;
2368 
2369  if ((Cs->style & WS_THICKFRAME) || !(Cs->style & (WS_POPUP | WS_CHILD)))
2370  {
2371  co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack, &MaxTrack);
2372  if (Size.cx > MaxTrack.x) Size.cx = MaxTrack.x;
2373  if (Size.cy > MaxTrack.y) Size.cy = MaxTrack.y;
2374  if (Size.cx < MinTrack.x) Size.cx = MinTrack.x;
2375  if (Size.cy < MinTrack.y) Size.cy = MinTrack.y;
2376  }
2377 
2378  Window->rcWindow.left = Cs->x;
2379  Window->rcWindow.top = Cs->y;
2380  Window->rcWindow.right = Cs->x + Size.cx;
2381  Window->rcWindow.bottom = Cs->y + Size.cy;
2382  /*
2383  if (0 != (Window->style & WS_CHILD) && ParentWindow)
2384  {
2385  ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
2386  RECTL_vOffsetRect(&Window->rcWindow,
2387  ParentWindow->rcClient.left,
2388  ParentWindow->rcClient.top);
2389  }
2390  */
2391  /* correct child window coordinates if mirroring on parent is enabled */
2392  if (ParentWindow != NULL)
2393  {
2394  if ( ((Cs->style & WS_CHILD) == WS_CHILD) &&
2395  ((ParentWindow->ExStyle & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL))
2396  {
2397  Window->rcWindow.right = ParentWindow->rcClient.right - (Window->rcWindow.left - ParentWindow->rcClient.left);
2398  Window->rcWindow.left = Window->rcWindow.right - Size.cx;
2399  }
2400  }
2401 
2402  Window->rcClient = Window->rcWindow;
2403 
2404  if (Window->spwndNext || Window->spwndPrev)
2405  {
2406  ERR("Window 0x%p has been linked too early!\n", Window);
2407  }
2408 
2409  if (!(Window->state2 & WNDS2_WIN31COMPAT))
2410  {
2411  if (Class->style & CS_PARENTDC && !(ParentWindow->style & WS_CLIPCHILDREN))
2412  Window->style &= ~(WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
2413  }
2414 
2415  if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2416  {
2417  if ( !IntIsTopLevelWindow(Window) )
2418  {
2419  if (pti != ParentWindow->head.pti)
2420  {
2421  //ERR("CreateWindow Parent in.\n");
2422  UserAttachThreadInput(pti, ParentWindow->head.pti, TRUE);
2423  }
2424  }
2425  }
2426 
2427  /* Send the NCCREATE message */
2429  if (!Result)
2430  {
2431  ERR("co_UserCreateWindowEx(): NCCREATE message failed\n");
2432  goto cleanup;
2433  }
2434 
2435  /* Link the window */
2436  if (ParentWindow != NULL)
2437  {
2438  /* Link the window into the siblings list */
2439  if ((Cs->style & (WS_CHILD | WS_MAXIMIZE)) == WS_CHILD)
2441  else
2442  IntLinkHwnd(Window, hwndInsertAfter);
2443  }
2444 
2445  /* Send the WM_NCCALCSIZE message */
2446  {
2447  // RECT rc;
2448  MaxPos.x = Window->rcWindow.left;
2449  MaxPos.y = Window->rcWindow.top;
2450 
2451  Result = co_WinPosGetNonClientSize(Window, &Window->rcWindow, &Window->rcClient);
2452  //rc = Window->rcWindow;
2453  //Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM)&rc);
2454  //Window->rcClient = rc;
2455 
2456  RECTL_vOffsetRect(&Window->rcWindow, MaxPos.x - Window->rcWindow.left,
2457  MaxPos.y - Window->rcWindow.top);
2458  }
2459 
2460  /* Send the WM_CREATE message. */
2462  if (Result == (LRESULT)-1)
2463  {
2464  ERR("co_UserCreateWindowEx(): WM_CREATE message failed\n");
2465  goto cleanup;
2466  }
2467 
2468  /* Send the EVENT_OBJECT_CREATE event */
2469  IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2470 
2471  /* By setting the flag below it can be examined to determine if the window
2472  was created successfully and a valid pwnd was passed back to caller since
2473  from here the function has to succeed. */
2475 
2476  /* Send the WM_SIZE and WM_MOVE messages. */
2477  if (!(Window->state & WNDS_SENDSIZEMOVEMSGS))
2478  {
2480  }
2481 
2482  /* Show or maybe minimize or maximize the window. */
2483 
2485  if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2486  {
2487  RECTL NewPos;
2488  UINT SwFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
2489 
2490  SwFlag = co_WinPosMinMaximize(Window, SwFlag, &NewPos);
2491  SwFlag |= SWP_NOZORDER|SWP_FRAMECHANGED; /* Frame always gets changed */
2492  if (!(style & WS_VISIBLE) || (style & WS_CHILD) || UserGetActiveWindow()) SwFlag |= SWP_NOACTIVATE;
2493  co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top,
2494  NewPos.right, NewPos.bottom, SwFlag);
2495  }
2496 
2497  /* Send the WM_PARENTNOTIFY message */
2499 
2500  /* Notify the shell that a new window was created */
2501  if (Window->spwndOwner == NULL ||
2502  !(Window->spwndOwner->style & WS_VISIBLE) ||
2503  (Window->spwndOwner->ExStyle & WS_EX_TOOLWINDOW))
2504  {
2505  if (UserIsDesktopWindow(Window->spwndParent) &&
2506  (Window->style & WS_VISIBLE) &&
2507  (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
2508  (Window->ExStyle & WS_EX_APPWINDOW)))
2509  {
2511  }
2512  }
2513 
2514  /* Initialize and show the window's scrollbars */
2515  if (Window->style & WS_VSCROLL)
2516  {
2518  }
2519  if (Window->style & WS_HSCROLL)
2520  {
2522  }
2523 
2524  /* Show the new window */
2525  if (Cs->style & WS_VISIBLE)
2526  {
2527  if (Window->style & WS_MAXIMIZE)
2528  dwShowMode = SW_SHOW;
2529  else if (Window->style & WS_MINIMIZE)
2530  dwShowMode = SW_SHOWMINIMIZED;
2531 
2532  co_WinPosShowWindow(Window, dwShowMode);
2533 
2534  if (Window->ExStyle & WS_EX_MDICHILD)
2535  {
2536  ASSERT(ParentWindow);
2537  if(!ParentWindow)
2538  goto cleanup;
2539  co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
2540  /* ShowWindow won't activate child windows */
2542  }
2543  }
2544 
2545  if (Class->atomClassName == gaGuiConsoleWndClass)
2546  {
2547  /* Count only console windows manually */
2549  }
2550 
2551  TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
2552  ret = Window;
2553 
2554 cleanup:
2555  if (!ret)
2556  {
2557  TRACE("co_UserCreateWindowEx(): Error Created window!\n");
2558  /* If the window was created, the class will be dereferenced by co_UserDestroyWindow */
2559  if (Window)
2561  else if (Class)
2562  IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
2563  }
2564 
2565  if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
2566  if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
2567  if (pszName) UserHeapFree(pszName);
2568  if (pszClass) UserHeapFree(pszClass);
2569 
2570  if (Window)
2571  {
2573  }
2574  if (ParentWindow) UserDerefObjectCo(ParentWindow);
2575 
2576  // See CORE-13717, not setting error on success.
2577  if (ret)
2579 
2580  return ret;
2581 }
2582 
2583 NTSTATUS
2584 NTAPI
2586  OUT PLARGE_STRING plstrSafe,
2587  IN PLARGE_STRING plstrUnsafe)
2588 {
2589  LARGE_STRING lstrTemp;
2590  PVOID pvBuffer = NULL;
2591 
2592  _SEH2_TRY
2593  {
2594  /* Probe and copy the string */
2595  ProbeForRead(plstrUnsafe, sizeof(LARGE_STRING), sizeof(ULONG));
2596  lstrTemp = *plstrUnsafe;
2597  }
2599  {
2600  /* Fail */
2602  }
2603  _SEH2_END
2604 
2605  if (lstrTemp.Length != 0)
2606  {
2607  /* Allocate a buffer from paged pool */
2608  pvBuffer = ExAllocatePoolWithTag(PagedPool, lstrTemp.Length, TAG_STRING);
2609  if (!pvBuffer)
2610  {
2611  return STATUS_NO_MEMORY;
2612  }
2613 
2614  _SEH2_TRY
2615  {
2616  /* Probe and copy the buffer */
2617  ProbeForRead(lstrTemp.Buffer, lstrTemp.Length, sizeof(WCHAR));
2618  RtlCopyMemory(pvBuffer, lstrTemp.Buffer, lstrTemp.Length);
2619  }
2621  {
2622  /* Cleanup and fail */
2623  ExFreePoolWithTag(pvBuffer, TAG_STRING);
2625  }
2626  _SEH2_END
2627  }
2628 
2629  /* Set the output string */
2630  plstrSafe->Buffer = pvBuffer;
2631  plstrSafe->Length = lstrTemp.Length;
2632  plstrSafe->MaximumLength = lstrTemp.Length;
2633 
2634  return STATUS_SUCCESS;
2635 }
2636 
2640 HWND
2641 NTAPI
2643  DWORD dwExStyle,
2644  PLARGE_STRING plstrClassName,
2645  PLARGE_STRING plstrClsVersion,
2646  PLARGE_STRING plstrWindowName,
2647  DWORD dwStyle,
2648  int x,
2649  int y,
2650  int nWidth,
2651  int nHeight,
2652  HWND hWndParent,
2653  HMENU hMenu,
2655  LPVOID lpParam,
2656  DWORD dwFlags,
2657  PVOID acbiBuffer)
2658 {
2659  NTSTATUS Status;
2660  LARGE_STRING lstrWindowName;
2661  LARGE_STRING lstrClassName;
2662  LARGE_STRING lstrClsVersion;
2663  UNICODE_STRING ustrClassName;
2664  UNICODE_STRING ustrClsVersion;
2665  CREATESTRUCTW Cs;
2666  HWND hwnd = NULL;
2667  PWND pwnd;
2668 
2669  lstrWindowName.Buffer = NULL;
2670  lstrClassName.Buffer = NULL;
2671  lstrClsVersion.Buffer = NULL;
2672 
2673  if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2674  {
2675  /* check hMenu is valid handle */
2676  if (hMenu && !UserGetMenuObject(hMenu))
2677  {
2678  ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
2680  return NULL;
2681  }
2682  }
2683 
2684  /* Copy the window name to kernel mode */
2685  Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
2686  if (!NT_SUCCESS(Status))
2687  {
2688  ERR("NtUserCreateWindowEx: failed to capture plstrWindowName\n");
2690  return NULL;
2691  }
2692 
2693  plstrWindowName = &lstrWindowName;
2694 
2695  /* Check if the class is an atom */
2696  if (IS_ATOM(plstrClassName))
2697  {
2698  /* It is, pass the atom in the UNICODE_STRING */
2699  ustrClassName.Buffer = (PVOID)plstrClassName;
2700  ustrClassName.Length = 0;
2701  ustrClassName.MaximumLength = 0;
2702  }
2703  else
2704  {
2705  /* It's not, capture the class name */
2706  Status = ProbeAndCaptureLargeString(&lstrClassName, plstrClassName);
2707  if (!NT_SUCCESS(Status))
2708  {
2709  ERR("NtUserCreateWindowEx: failed to capture plstrClassName\n");
2710  /* Set last error, cleanup and return */
2712  goto cleanup;
2713  }
2714 
2715  /* We pass it on as a UNICODE_STRING */
2716  ustrClassName.Buffer = lstrClassName.Buffer;
2717  ustrClassName.Length = (USHORT)min(lstrClassName.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2718  ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
2719  }
2720 
2721  /* Check if the class version is an atom */
2722  if (IS_ATOM(plstrClsVersion))
2723  {
2724  /* It is, pass the atom in the UNICODE_STRING */
2725  ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
2726  ustrClsVersion.Length = 0;
2727  ustrClsVersion.MaximumLength = 0;
2728  }
2729  else
2730  {
2731  /* It's not, capture the class name */
2732  Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
2733  if (!NT_SUCCESS(Status))
2734  {
2735  ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
2736  /* Set last error, cleanup and return */
2738  goto cleanup;
2739  }
2740 
2741  /* We pass it on as a UNICODE_STRING */
2742  ustrClsVersion.Buffer = lstrClsVersion.Buffer;
2743  ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2744  ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
2745  }
2746 
2747  /* Fill the CREATESTRUCTW */
2748  /* we will keep here the original parameters */
2749  Cs.style = dwStyle;
2750  Cs.lpCreateParams = lpParam;
2751  Cs.hInstance = hInstance;
2752  Cs.hMenu = hMenu;
2753  Cs.hwndParent = hWndParent;
2754  Cs.cx = nWidth;
2755  Cs.cy = nHeight;
2756  Cs.x = x;
2757  Cs.y = y;
2758  Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer;
2759  Cs.lpszClass = ustrClassName.Buffer;
2760  Cs.dwExStyle = dwExStyle;
2761 
2763 
2764  /* Call the internal function */
2765  pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer, dwFlags);
2766 
2767  if(!pwnd)
2768  {
2769  ERR("co_UserCreateWindowEx failed!\n");
2770  }
2771  hwnd = pwnd ? UserHMGetHandle(pwnd) : NULL;
2772 
2773  UserLeave();
2774 
2775 cleanup:
2776  if (lstrWindowName.Buffer)
2777  {
2778  ExFreePoolWithTag(lstrWindowName.Buffer, TAG_STRING);
2779  }
2780  if (lstrClassName.Buffer)
2781  {
2782  ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
2783  }
2784  if (lstrClsVersion.Buffer)
2785  {
2786  ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
2787  }
2788 
2789  return hwnd;
2790 }
2791 
2792 // Win: xxxDW_DestroyOwnedWindows
2794 {
2795  HWND* List;
2796  HWND* phWnd;
2797  PWND pWnd;
2798  PTHREADINFO pti = Window->head.pti;
2800 
2802  if (!List)
2803  return;
2804 
2805  for (phWnd = List; *phWnd; ++phWnd)
2806  {
2807  pWnd = ValidateHwndNoErr(*phWnd);
2808  if (pWnd == NULL)
2809  continue;
2810  ASSERT(pWnd->spwndOwner == Window);
2811  ASSERT(pWnd != Window);
2812 
2813  if (IS_IMM_MODE() && !(pti->TIF_flags & TIF_INCLEANUP) &&
2814  pWnd == pti->spwndDefaultIme)
2815  {
2816  continue;
2817  }
2818 
2819  pWnd->spwndOwner = NULL;
2821  {
2822  UserRefObjectCo(pWnd, &Ref); // Temp HACK?
2823  co_UserDestroyWindow(pWnd);
2824  UserDerefObjectCo(pWnd); // Temp HACK?
2825  }
2826  else
2827  {
2828  ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
2829  }
2830  }
2831 
2833 }
2834 
2835 // Win: xxxDestroyWindow
2837 {
2838  HWND hWnd;
2839  PWND pwndTemp;
2840  PTHREADINFO ti;
2841  MSG msg;
2842  PWND Window = Object;
2843 
2844  ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
2845 
2846  hWnd = Window->head.h;
2848 
2849  TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
2850 
2851  /* Check for owner thread */
2852  if (Window->head.pti != ti)
2853  {
2854  /* Check if we are destroying the desktop window */
2855  if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
2856  {
2858  return FALSE;
2859  }
2860  }
2861 
2862  /* If window was created successfully and it is hooked */
2863  if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
2864  {
2866  {
2867  ERR("Destroy Window WH_CBT Call Hook return!\n");
2868  return FALSE;
2869  }
2870  }
2871 
2872  if (Window->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME])
2873  {
2874  if ((Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2875  {
2876  if (Window->spwndOwner)
2877  {
2878  //ERR("DestroyWindow Owner out.\n");
2879  UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE);
2880  }
2881  }
2882  }
2883 
2884  /* Inform the parent */
2885  if (Window->style & WS_CHILD)
2886  {
2888  }
2889 
2890  if (!Window->spwndOwner && !IntGetParent(Window))
2891  {
2893  }
2894 
2895  /* Hide the window */
2896  if (Window->style & WS_VISIBLE)
2897  {
2898  if (Window->style & WS_CHILD)
2899  {
2900  /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
2902  }
2903  else
2904  {
2906  }
2907  }
2908 
2909  /* Adjust last active */
2910  if ((pwndTemp = Window->spwndOwner))
2911  {
2912  while (pwndTemp->spwndOwner)
2913  pwndTemp = pwndTemp->spwndOwner;
2914 
2915  if (pwndTemp->spwndLastActive == Window)
2916  pwndTemp->spwndLastActive = Window->spwndOwner;
2917  }
2918 
2919  if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))
2920  {
2921  if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
2922  {
2924  {
2925  //ERR("DestroyWindow Parent out.\n");
2926  UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE);
2927  }
2928  }
2929  }
2930 
2931  if (Window->head.pti->MessageQueue->spwndActive == Window)
2932  Window->head.pti->MessageQueue->spwndActive = NULL;
2933  if (Window->head.pti->MessageQueue->spwndFocus == Window)
2934  Window->head.pti->MessageQueue->spwndFocus = NULL;
2935  if (Window->head.pti->MessageQueue->spwndActivePrev == Window)
2936  Window->head.pti->MessageQueue->spwndActivePrev = NULL;
2937  if (Window->head.pti->MessageQueue->spwndCapture == Window)
2938  Window->head.pti->MessageQueue->spwndCapture = NULL;
2939 
2940  /*
2941  * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL
2942  */
2943 
2944  if ((ti != NULL) && (ti->pDeskInfo != NULL))
2945  {
2946  if (ti->pDeskInfo->hShellWindow == hWnd)
2947  {
2948  ERR("Destroying the ShellWindow!\n");
2949  ti->pDeskInfo->hShellWindow = NULL;
2950  }
2951  }
2952 
2954 
2956  {
2957  return TRUE;
2958  }
2959 
2960  /* Recursively destroy owned windows */
2961  if (!(Window->style & WS_CHILD))
2962  {
2964  }
2965 
2966  /* Generate mouse move message for the next window */
2967  msg.message = WM_MOUSEMOVE;
2968  msg.wParam = UserGetMouseButtonsState();
2969  msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2970  msg.pt = gpsi->ptCursor;
2972 
2973  IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2974 
2975  /* Send destroy messages */
2977 
2978  // Destroy the default IME window if necessary
2979  if (IS_IMM_MODE() && !(ti->TIF_flags & TIF_INCLEANUP) &&
2980  ti->spwndDefaultIme && !IS_WND_IMELIKE(Window) && !(Window->state & WNDS_DESTROYED))
2981  {
2982  if (IS_WND_CHILD(Window))
2983  {
2986  }
2987  else
2988  {
2991  }
2992  }
2993 
2995  {
2996  return TRUE;
2997  }
2998 
2999  /* Destroy the window storage */
3001 
3002  return TRUE;
3003 }
3004 
3005 
3006 /*
3007  * @implemented
3008  */
3011 {
3012  PWND Window;
3014  BOOLEAN ret;
3016 
3017  TRACE("Enter NtUserDestroyWindow\n");
3019 
3020  if (!(Window = UserGetWindowObject(Wnd)))
3021  {
3022  RETURN(FALSE);
3023  }
3024 
3025  UserRefObjectCo(Window, &Ref); // FIXME: Dunno if win should be reffed during destroy...
3027  UserDerefObjectCo(Window); // FIXME: Dunno if win should be reffed during destroy...
3028 
3029  RETURN(ret);
3030 
3031 CLEANUP:
3032  TRACE("Leave NtUserDestroyWindow, ret=%u\n", _ret_);
3033  UserLeave();
3034  END_CLEANUP;
3035 }
3036 
3037 
3038 static HWND FASTCALL
3040  PWND ChildAfter,
3041  RTL_ATOM ClassAtom,
3042  PUNICODE_STRING WindowName)
3043 {
3044  BOOL CheckWindowName;
3045  HWND *List, *phWnd;
3046  HWND Ret = NULL;
3047  UNICODE_STRING CurrentWindowName;
3048 
3049  ASSERT(Parent);
3050 
3051  CheckWindowName = WindowName->Buffer != 0;
3052 
3053  if((List = IntWinListChildren(Parent)))
3054  {
3055  phWnd = List;
3056  if(ChildAfter)
3057  {
3058  /* skip handles before and including ChildAfter */
3059  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
3060  ;
3061  }
3062 
3063  /* search children */
3064  while(*phWnd)
3065  {
3066  PWND Child;
3067  if(!(Child = UserGetWindowObject(*(phWnd++))))
3068  {
3069  continue;
3070  }
3071 
3072  /* Do not send WM_GETTEXT messages in the kernel mode version!
3073  The user mode version however calls GetWindowText() which will
3074  send WM_GETTEXT messages to windows belonging to its processes */
3075  if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
3076  {
3077  // FIXME: LARGE_STRING truncated
3078  CurrentWindowName.Buffer = Child->strName.Buffer;
3079  CurrentWindowName.Length = (USHORT)min(Child->strName.Length, MAXUSHORT);
3080  CurrentWindowName.MaximumLength = (USHORT)min(Child->strName.MaximumLength, MAXUSHORT);
3081  if(!CheckWindowName ||
3082  (Child->strName.Length < 0xFFFF &&
3083  !RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
3084  {
3085  Ret = Child->head.h;
3086  break;
3087  }
3088  }
3089  }
3091  }
3092 
3093  return Ret;
3094 }
3095 
3096 /*
3097  * FUNCTION:
3098  * Searches a window's children for a window with the specified
3099  * class and name
3100  * ARGUMENTS:
3101  * hwndParent = The window whose childs are to be searched.
3102  * NULL = desktop
3103  * HWND_MESSAGE = message-only windows
3104  *
3105  * hwndChildAfter = Search starts after this child window.
3106  * NULL = start from beginning
3107  *
3108  * ucClassName = Class name to search for
3109  * Reguired parameter.
3110  *
3111  * ucWindowName = Window name
3112  * ->Buffer == NULL = don't care
3113  *
3114  * RETURNS:
3115  * The HWND of the window if it was found, otherwise NULL
3116  */
3117 /*
3118  * @implemented
3119  */
3120 HWND APIENTRY
3122  HWND hwndChildAfter,
3123  PUNICODE_STRING ucClassName,
3124  PUNICODE_STRING ucWindowName,
3125  DWORD dwUnknown)
3126 {
3127  PWND Parent, ChildAfter;
3128  UNICODE_STRING ClassName = {0}, WindowName = {0};
3129  HWND Desktop, Ret = NULL;
3130  BOOL DoMessageWnd = FALSE;
3131  RTL_ATOM ClassAtom = (RTL_ATOM)0;
3133 
3134  TRACE("Enter NtUserFindWindowEx\n");
3135  UserEnterShared();
3136 
3137  if (ucClassName != NULL || ucWindowName != NULL)
3138  {
3139  _SEH2_TRY
3140  {
3141  if (ucClassName != NULL)
3142  {
3143  ClassName = ProbeForReadUnicodeString(ucClassName);
3144  if (ClassName.Length != 0)
3145  {
3146  ProbeForRead(ClassName.Buffer,
3147  ClassName.Length,
3148  sizeof(WCHAR));
3149  }
3150  else if (!IS_ATOM(ClassName.Buffer))
3151  {
3153  _SEH2_LEAVE;
3154  }
3155 
3156  if (!IntGetAtomFromStringOrAtom(&ClassName,
3157  &ClassAtom))
3158  {
3160  _SEH2_LEAVE;
3161  }
3162  }
3163 
3164  if (ucWindowName != NULL)
3165  {
3166  WindowName = ProbeForReadUnicodeString(ucWindowName);
3167  if (WindowName.Length != 0)
3168  {
3169  ProbeForRead(WindowName.Buffer,
3170  WindowName.Length,
3171  sizeof(WCHAR));
3172  }
3173  }
3174  }
3176  {
3179  }
3180  _SEH2_END;
3181 
3182  if (ucClassName != NULL)
3183  {
3184  if (ClassName.Length == 0 && ClassName.Buffer != NULL &&
3185  !IS_ATOM(ClassName.Buffer))
3186  {
3188  RETURN(NULL);
3189  }
3190  else if (ClassAtom == (RTL_ATOM)0)
3191  {
3192  /* LastError code was set by IntGetAtomFromStringOrAtom */
3193  RETURN(NULL);
3194  }
3195  }
3196  }
3197 
3199 
3200  if(hwndParent == NULL)
3201  {
3202  hwndParent = Desktop;
3203  DoMessageWnd = TRUE;
3204  }
3205  else if(hwndParent == HWND_MESSAGE)
3206  {
3208  }
3209 
3211  {
3212  RETURN( NULL);
3213  }
3214 
3215  ChildAfter = NULL;
3216  if(hwndChildAfter && !(ChildAfter = UserGetWindowObject(hwndChildAfter)))
3217  {
3218  RETURN( NULL);
3219  }
3220 
3221  _SEH2_TRY
3222  {
3223  if(Parent->head.h == Desktop)
3224  {
3225  HWND *List, *phWnd;
3226  PWND TopLevelWindow;
3227  BOOLEAN CheckWindowName;
3228  BOOLEAN WindowMatches;
3229  BOOLEAN ClassMatches;
3230 
3231  /* windows searches through all top-level windows if the parent is the desktop
3232  window */
3233 
3234  if((List = IntWinListChildren(Parent)))
3235  {
3236  phWnd = List;
3237 
3238  if(ChildAfter)
3239  {
3240  /* skip handles before and including ChildAfter */
3241  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
3242  ;
3243  }
3244 
3245  CheckWindowName = WindowName.Buffer != 0;
3246 
3247  /* search children */
3248  while(*phWnd)
3249  {
3250  UNICODE_STRING ustr;
3251 
3252  if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
3253  {
3254  continue;
3255  }
3256 
3257  /* Do not send WM_GETTEXT messages in the kernel mode version!
3258  The user mode version however calls GetWindowText() which will
3259  send WM_GETTEXT messages to windows belonging to its processes */
3260  ustr.Buffer = TopLevelWindow->strName.Buffer;
3261  ustr.Length = (USHORT)min(TopLevelWindow->strName.Length, MAXUSHORT); // FIXME:LARGE_STRING truncated
3262  ustr.MaximumLength = (USHORT)min(TopLevelWindow->strName.MaximumLength, MAXUSHORT);
3263  WindowMatches = !CheckWindowName ||
3264  (TopLevelWindow->strName.Length < 0xFFFF &&
3265  !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
3266  ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
3267  ClassAtom == TopLevelWindow->pcls->atomNVClassName;
3268 
3269  if (WindowMatches && ClassMatches)
3270  {
3271  Ret = TopLevelWindow->head.h;
3272  break;
3273  }
3274 
3275  if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
3276  {
3277  /* window returns the handle of the top-level window, in case it found
3278  the child window */
3279  Ret = TopLevelWindow->head.h;
3280  break;
3281  }
3282 
3283  }
3285  }
3286  }
3287  else
3288  {
3289  TRACE("FindWindowEx: Not Desktop Parent!\n");
3290  Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
3291  }
3292 
3293  if (Ret == NULL && DoMessageWnd)
3294  {
3295  PWND MsgWindows;
3296 
3297  if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
3298  {
3299  Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
3300  }
3301  }
3302  }
3304  {
3306  Ret = NULL;
3307  }
3308  _SEH2_END;
3309 
3310  RETURN( Ret);
3311 
3312 CLEANUP:
3313  TRACE("Leave NtUserFindWindowEx, ret %p\n", _ret_);
3314  UserLeave();
3315  END_CLEANUP;
3316 }
3317 
3318 
3319 /*
3320  * @implemented
3321  */
3323 {
3324  PWND WndAncestor, Parent;
3325 
3326  if (Wnd->head.h == IntGetDesktopWindow())
3327  {
3328  return NULL;
3329  }
3330 
3331  switch (Type)
3332  {
3333  case GA_PARENT:
3334  {
3335  WndAncestor = Wnd->spwndParent;
3336  break;
3337  }
3338 
3339  case GA_ROOT:
3340  {
3341  WndAncestor = Wnd;
3342  Parent = NULL;
3343 
3344  for(;;)
3345  {
3346  if(!(Parent = WndAncestor->spwndParent))
3347  {
3348  break;
3349  }
3351  {
3352  break;
3353  }
3354 
3355  WndAncestor = Parent;
3356  }
3357  break;
3358  }
3359 
3360  case GA_ROOTOWNER:
3361  {
3362  WndAncestor = Wnd;
3363 
3364  for (;;)
3365  {
3366  Parent = IntGetParent(WndAncestor);
3367 
3368  if (!Parent)
3369  {
3370  break;
3371  }
3372 
3373  WndAncestor = Parent;
3374  }
3375  break;
3376  }
3377 
3378  default:
3379  {
3380  return NULL;
3381  }
3382  }
3383 
3384  return WndAncestor;
3385 }
3386 
3387 /*
3388  * @implemented
3389  */
3390 HWND APIENTRY
3392 {
3393  PWND Window, Ancestor;
3395 
3396  TRACE("Enter NtUserGetAncestor\n");
3398 
3399  if (!(Window = UserGetWindowObject(hWnd)))
3400  {
3401  RETURN(NULL);
3402  }
3403 
3404  Ancestor = UserGetAncestor(Window, Type);
3405  /* faxme: can UserGetAncestor ever return NULL for a valid window? */
3406 
3407  RETURN(Ancestor ? Ancestor->head.h : NULL);
3408 
3409 CLEANUP:
3410  TRACE("Leave NtUserGetAncestor, ret=%p\n", _ret_);
3411  UserLeave();
3412  END_CLEANUP;
3413 }
3414 
3418 /* combo state struct */
3419 typedef struct
3420 {
3421  HWND self;
3422  HWND owner;
3423  UINT dwStyle;
3424  HWND hWndEdit;
3425  HWND hWndLBox;
3426  UINT wState;
3427  HFONT hFont;
3428  RECT textRect;
3429  RECT buttonRect;
3430  RECT droppedRect;
3431  INT droppedIndex;
3432  INT fixedOwnerDrawHeight;
3433  INT droppedWidth; /* last two are not used unless set */
3434  INT editHeight; /* explicitly */
3437 
3438 // Window Extra data container.
3439 typedef struct _WND2CBOX
3440 {
3443 } WND2CBOX, *PWND2CBOX;
3444 
3445 #define CBF_BUTTONDOWN 0x0002
3446 BOOL
3450 APIENTRY
3452  HWND hWnd,
3453  PCOMBOBOXINFO pcbi)
3454 {
3455  PWND Wnd;
3456  PPROCESSINFO ppi;
3457  BOOL NotSameppi = FALSE;
3458  BOOL Ret = TRUE;
3460 
3461  TRACE("Enter NtUserGetComboBoxInfo\n");
3462  UserEnterShared();
3463 
3464  if (!(Wnd = UserGetWindowObject(hWnd)))
3465  {
3466  RETURN( FALSE );
3467  }
3468  _SEH2_TRY
3469  {
3470  ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
3471  }
3473  {
3476  }
3477  _SEH2_END;
3478 
3479  if (pcbi->cbSize < sizeof(COMBOBOXINFO))
3480  {
3482  RETURN(FALSE);
3483  }
3484 
3485  // Pass the user pointer, it was already probed.
3486  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_COMBOBOX]) && Wnd->fnid != FNID_COMBOBOX)
3487  {
3488  RETURN( (BOOL) co_IntSendMessage( Wnd->head.h, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
3489  }
3490 
3492  NotSameppi = ppi != Wnd->head.pti->ppi;
3493  if (NotSameppi)
3494  {
3495  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3496  }
3497 
3498  _SEH2_TRY
3499  {
3500  LPHEADCOMBO lphc = ((PWND2CBOX)Wnd)->pCBox;
3501  pcbi->rcItem = lphc->textRect;
3502  pcbi->rcButton = lphc->buttonRect;
3503  pcbi->stateButton = 0;
3504  if (lphc->wState & CBF_BUTTONDOWN)
3506  if (RECTL_bIsEmptyRect(&lphc->buttonRect))
3508  pcbi->hwndCombo = lphc->self;
3509  pcbi->hwndItem = lphc->hWndEdit;
3510  pcbi->hwndList = lphc->hWndLBox;
3511  }
3513  {
3514  Ret = FALSE;
3516  }
3517  _SEH2_END;
3518 
3519  RETURN( Ret);
3520 
3521 CLEANUP:
3522  if (NotSameppi) KeDetachProcess();
3523  TRACE("Leave NtUserGetComboBoxInfo, ret=%i\n",_ret_);
3524  UserLeave();
3525  END_CLEANUP;
3526 }
3527 
3531 /* Listbox structure */
3532 typedef struct
3533 {
3534  HWND self; /* Our own window handle */
3535  HWND owner; /* Owner window to send notifications to */
3536  UINT style; /* Window style */
3537  INT width; /* Window width */
3538  INT height; /* Window height */
3539  VOID *items; /* Array of items */
3540  INT nb_items; /* Number of items */
3541  INT top_item; /* Top visible item */
3542  INT selected_item; /* Selected item */
3543  INT focus_item; /* Item that has the focus */
3544  INT anchor_item; /* Anchor item for extended selection */
3545  INT item_height; /* Default item height */
3546  INT page_size; /* Items per listbox page */
3547  INT column_width; /* Column width for multi-column listboxes */
3548 } LB_DESCR;
3549 
3550 // Window Extra data container.
3551 typedef struct _WND2LB
3552 {
3555 } WND2LB, *PWND2LB;
3559 DWORD
3560 APIENTRY
3562  HWND hWnd)
3563 {
3564  PWND Wnd;
3565  PPROCESSINFO ppi;
3566  BOOL NotSameppi = FALSE;
3567  DWORD Ret = 0;
3569 
3570  TRACE("Enter NtUserGetListBoxInfo\n");
3571  UserEnterShared();
3572 
3573  if (!(Wnd = UserGetWindowObject(hWnd)))
3574  {
3575  RETURN( 0 );
3576  }
3577 
3578  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_LISTBOX]) && Wnd->fnid != FNID_LISTBOX)
3579  {
3580  RETURN( (DWORD) co_IntSendMessage( Wnd->head.h, LB_GETLISTBOXINFO, 0, 0 ));
3581  }
3582 
3583  // wine lisbox:test_GetListBoxInfo lb_getlistboxinfo = 0, should not send a message!
3585  NotSameppi = ppi != Wnd->head.pti->ppi;
3586  if (NotSameppi)
3587  {
3588  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3589  }
3590 
3591  _SEH2_TRY
3592  {
3593  LB_DESCR *descr = ((PWND2LB)Wnd)->pLBiv;
3594  // See Controls ListBox.c:LB_GETLISTBOXINFO must match...
3595  Ret = descr->page_size;
3596  }
3598  {
3599  Ret = 0;
3601  }
3602  _SEH2_END;
3603 
3604  RETURN( Ret);
3605 
3606 CLEANUP:
3607  if (NotSameppi) KeDetachProcess();
3608  TRACE("Leave NtUserGetListBoxInfo, ret=%lu\n", _ret_);
3609  UserLeave();
3610  END_CLEANUP;
3611 }
3612 
3613 /*
3614  * NtUserSetParent
3615  *
3616  * The NtUserSetParent function changes the parent window of the specified
3617  * child window.
3618  *
3619  * Remarks
3620  * The new parent window and the child window must belong to the same
3621  * application. If the window identified by the hWndChild parameter is
3622  * visible, the system performs the appropriate redrawing and repainting.
3623  * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
3624  * or WS_POPUP window styles of the window whose parent is being changed.
3625  *
3626  * Status
3627  * @implemented
3628  */
3629 
3630 HWND APIENTRY
3632 {
3634 
3635  TRACE("Enter NtUserSetParent\n");
3637 
3638  /*
3639  Check Parent first from user space, set it here.
3640  */
3641  if (!hWndNewParent)
3642  {
3643  hWndNewParent = IntGetDesktopWindow();
3644  }
3645  else if (hWndNewParent == HWND_MESSAGE)
3646  {
3647  hWndNewParent = IntGetMessageWindow();
3648  }
3649 
3650  RETURN( co_UserSetParent(hWndChild, hWndNewParent));
3651 
3652 CLEANUP:
3653  TRACE("Leave NtUserSetParent, ret=%p\n", _ret_);
3654  UserLeave();
3655  END_CLEANUP;
3656 }
3657 
3658 /*
3659  * UserGetShellWindow
3660  *
3661  * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3662  *
3663  * Status
3664  * @implemented
3665  */
3667 {
3668  PWINSTATION_OBJECT WinStaObject;
3669  HWND Ret;
3670 
3672  UserMode,
3673  0,
3674  &WinStaObject,
3675  0);
3676 
3677  if (!NT_SUCCESS(Status))
3678  {
3680  return( (HWND)0);
3681  }
3682 
3683  Ret = (HWND)WinStaObject->ShellWindow;
3684 
3685  ObDereferenceObject(WinStaObject);
3686  return( Ret);
3687 }
3688 
3689 /*
3690  * NtUserSetShellWindowEx
3691  *
3692  * This is undocumented function to set global shell window. The global
3693  * shell window has special handling of window position.
3694  *
3695  * Status
3696  * @implemented
3697  */
3698 BOOL APIENTRY
3700 {
3701  PWINSTATION_OBJECT WinStaObject;
3702  PWND WndShell, WndListView;
3705  NTSTATUS Status;
3706  PTHREADINFO ti;
3707 
3708  TRACE("Enter NtUserSetShellWindowEx\n");
3710 
3711  if (!(WndShell = UserGetWindowObject(hwndShell)))
3712  {
3713  RETURN(FALSE);
3714  }
3715 
3716  if (!(WndListView = UserGetWindowObject(hwndListView)))
3717  {
3718  RETURN(FALSE);
3719  }
3720 
3722  UserMode,
3723  0,
3724  &WinStaObject,
3725  0);
3726 
3727  if (!NT_SUCCESS(Status))
3728  {
3730  RETURN( FALSE);
3731  }
3732 
3733  /*
3734  * Test if we are permitted to change the shell window.
3735  */
3736  if (WinStaObject->ShellWindow)
3737  {
3738  ObDereferenceObject(WinStaObject);
3739  RETURN( FALSE);
3740  }
3741 
3742  /*
3743  * Move shell window into background.
3744  */
3745  if (hwndListView && hwndListView != hwndShell)
3746  {
3747  /*
3748  * Disabled for now to get Explorer working.
3749  * -- Filip, 01/nov/2003
3750  */
3751 #if 0
3753 #endif
3754 
3755  if (WndListView->ExStyle & WS_EX_TOPMOST)
3756  {
3757  ObDereferenceObject(WinStaObject);
3758  RETURN( FALSE);
3759  }
3760  }
3761 
3762  if (WndShell->ExStyle & WS_EX_TOPMOST)
3763  {
3764  ObDereferenceObject(WinStaObject);
3765  RETURN( FALSE);
3766  }
3767 
3768  UserRefObjectCo(WndShell, &Ref);
3769  WndShell->state2 |= WNDS2_BOTTOMMOST;
3771 
3772  WinStaObject->ShellWindow = hwndShell;
3773  WinStaObject->ShellListView = hwndListView;
3774 
3775  ti = GetW32ThreadInfo();
3776  if (ti->pDeskInfo)
3777  {
3778  ti->pDeskInfo->hShellWindow = hwndShell;
3779  ti->pDeskInfo->spwndShell = WndShell;
3780  ti->pDeskInfo->spwndBkGnd = WndListView;
3781  ti->pDeskInfo->ppiShellProcess = ti->ppi;
3782  }
3783 
3785 
3786  UserDerefObjectCo(WndShell);
3787 
3788  ObDereferenceObject(WinStaObject);
3789  RETURN( TRUE);
3790 
3791 CLEANUP:
3792  TRACE("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
3793  UserLeave();
3794  END_CLEANUP;
3795 }
3796 
3797 // Fixes wine Win test_window_styles and todo tests...
3798 static BOOL FASTCALL
3800 {
3802  return TRUE;
3803  else if (!(ExStyle & WS_EX_STATICEDGE) && (Style & (WS_DLGFRAME | WS_THICKFRAME)))
3804  return TRUE;
3805  else
3806  return FALSE;
3807 }
3808 
3809 static LONG_PTR
3811 {
3812  PWND Window, Parent;
3813  PWINSTATION_OBJECT WindowStation;
3814  LONG_PTR OldValue;
3816 
3817  if (!(Window = UserGetWindowObject(hWnd)))
3818  {
3819  return( 0);
3820  }
3821 
3822  if ((INT)Index >= 0)
3823  {
3824  if ((Index + Size) > Window->cbwndExtra)
3825  {
3827  return( 0);
3828  }
3829 
3830 #ifdef _WIN64
3831  if (Size == sizeof(LONG))
3832  {
3833  OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
3834  *((LONG*)((PCHAR)(Window + 1) + Index)) = (LONG)NewValue;
3835  }
3836  else
3837 #endif
3838  {
3839  OldValue = *((LONG_PTR *)((PCHAR)(Window + 1) + Index));
3840  /*
3841  if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
3842  {
3843  OldValue = (LONG_PTR)IntSetWindowProc( Wnd, (WNDPROC)NewValue, Ansi);
3844  if (!OldValue) return 0;
3845  }
3846  */
3847  *((LONG_PTR*)((PCHAR)(Window + 1) + Index)) = NewValue;
3848  }
3849 
3850  }
3851  else
3852  {
3853 #ifdef _WIN64
3854  if (Size == sizeof(LONG))
3855  {
3856  if ((Index != GWL_STYLE) &&
3857  (Index != GWL_EXSTYLE) &&
3858  (Index != GWL_ID) &&
3859  (Index != GWL_USERDATA))
3860  {
3861  ERR("NtUserSetWindowLong(): Index requires pointer size: %lu\n", Index);
3863  return 0;
3864  }
3865  }
3866 #endif
3867 
3868  switch (Index)
3869  {
3870  case GWL_EXSTYLE: // LONG
3871  OldValue = (LONG) Window->ExStyle;
3872  Style.styleOld = OldValue;
3873  Style.styleNew = NewValue;
3874 
3875  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3876 
3877  /*
3878  * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3879  */
3880  WindowStation = Window->head.pti->rpdesk->rpwinstaParent;
3881  if(WindowStation)
3882  {
3883  if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3884  Style.styleNew &= ~WS_EX_TOPMOST;
3885  }
3886  /* WS_EX_WINDOWEDGE depends on some other styles */
3887  if (IntCheckFrameEdge(Window->style, NewValue))
3888  Style.styleNew |= WS_EX_WINDOWEDGE;
3889  else
3890  Style.styleNew &= ~WS_EX_WINDOWEDGE;
3891 
3892  if (!(Window->ExStyle & WS_EX_LAYERED))
3893  {
3895  }
3896 
3897  Window->ExStyle = (DWORD)Style.styleNew;
3898 
3899  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3900  break;
3901 
3902  case GWL_STYLE: // LONG
3903  OldValue = (LONG) Window->style;
3904  Style.styleOld = OldValue;
3905  Style.styleNew = NewValue;
3906 
3907  if (!bAlter)
3908  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3909 
3910  /* WS_CLIPSIBLINGS can't be reset on top-level windows */
3911  if (UserIsDesktopWindow(Window->spwndParent)) Style.styleNew |= WS_CLIPSIBLINGS;
3912  /* WS_MINIMIZE can't be reset */
3913  if (OldValue & WS_MINIMIZE) Style.styleNew |= WS_MINIMIZE;
3914  /* Fixes wine FIXME: changing WS_DLGFRAME | WS_THICKFRAME is supposed to change WS_EX_WINDOWEDGE too */
3915  if (IntCheckFrameEdge(NewValue, Window->ExStyle))
3916  Window->ExStyle |= WS_EX_WINDOWEDGE;
3917  else
3918  Window->ExStyle &= ~WS_EX_WINDOWEDGE;
3919 
3920  if ((OldValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3921  {
3922  if ((NewValue & (WS_CHILD | WS_POPUP)) != WS_CHILD)
3923  {
3925  ERR("IDMenu going null! %d\n",Window->IDMenu);
3926  Window->IDMenu = 0; // Window->spmenu = 0;
3927  }
3928  }
3929  else
3930  {
3931  if ((NewValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3932  {
3933  PMENU pMenu = UserGetMenuObject(UlongToHandle(Window->IDMenu));
3934  Window->state &= ~WNDS_HASMENU;
3935  if (pMenu)
3936  {
3937  ERR("IDMenu released 0x%p\n",pMenu);
3938  // ROS may not hold a lock after setting menu to window. But it should!
3939  //IntReleaseMenuObject(pMenu);
3940  }
3941  }
3942  }
3943 
3944  if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
3945  {
3946  if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
3947  if (Style.styleNew & WS_VISIBLE) Window->head.pti->cVisWindows++;
3949  }
3950  Window->style = (DWORD)Style.styleNew;
3951 
3952  if (!bAlter)
3953  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3954  break;
3955 
3956  case GWLP_WNDPROC: // LONG_PTR
3957  {
3958  if ( Window->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
3959  Window->fnid & FNID_FREED)
3960  {
3962  return( 0);
3963  }
3964  OldValue = (LONG_PTR)IntSetWindowProc(Window,
3965  (WNDPROC)NewValue,
3966  Ansi);
3967  break;
3968  }
3969 
3970  case GWLP_HINSTANCE: // LONG_PTR
3971  OldValue = (LONG_PTR) Window->hModule;
3972  Window->hModule = (HINSTANCE) NewValue;
3973  break;
3974 
3975  case GWLP_HWNDPARENT: // LONG_PTR
3976  Parent = Window->spwndParent;
3977  if (Parent && (Parent->head.h == IntGetDesktopWindow()))
3978  OldValue = (LONG_PTR) IntSetOwner(Window->head.h, (HWND) NewValue);
3979  else
3980  OldValue = (LONG_PTR) co_UserSetParent(Window->head.h, (HWND) NewValue);
3981  break;
3982 
3983  case GWLP_ID: // LONG
3984  OldValue = (LONG) Window->IDMenu;
3985  Window->IDMenu = (UINT) NewValue;
3986  break;
3987 
3988  case GWLP_USERDATA: // LONG or LONG_PTR
3989  OldValue = Window->dwUserData;
3990  Window->dwUserData = NewValue;
3991  break;
3992 
3993  default:
3994  ERR("NtUserSetWindowLong(): Unsupported index %lu\n", Index);
3996  OldValue = 0;
3997  break;
3998  }
3999  }
4000 
4001  return( OldValue);
4002 }
4003 
4004 LONG FASTCALL
4006 {
4007  return (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
4008 }
4009 
4012 {
4013  return co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
4014 }
4015 
4016 /*
4017  * NtUserSetWindowLong
4018  *
4019  * The NtUserSetWindowLong function changes an attribute of the specified
4020  * window. The function also sets the 32-bit (long) value at the specified
4021  * offset into the extra window memory.
4022  *
4023  * Status
4024  * @implemented
4025  */
4026 
4027 LONG APIENTRY
4029 {
4030  LONG ret;
4031 
4033 
4034  if (hWnd == IntGetDesktopWindow())
4035  {
4037  UserLeave();
4038  return 0;
4039  }
4040 
4041  ret = (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
4042 
4043  UserLeave();
4044 
4045  return ret;
4046 }
4047 
4048 #ifdef _WIN64
4050 NtUserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
4051 {
4052  LONG_PTR ret;
4053 
4055 
4056  if (hWnd == IntGetDesktopWindow())
4057  {
4059  UserLeave();
4060  return 0;
4061  }
4062 
4063  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
4064 
4065  UserLeave();
4066 
4067  return ret;
4068 }
4069 #endif // _WIN64
4070 
4073 {
4074  LONG ret;
4075 
4077 
4078  if (hWnd == IntGetDesktopWindow())
4079  {
4081  UserLeave();
4082  return 0;
4083  }
4084 
4085  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, FALSE, sizeof(LONG), TRUE);
4086 
4087  UserLeave();
4088 
4089  return ret;
4090 }
4091 
4092 
4093 /*
4094  * NtUserSetWindowWord
4095  *
4096  * Legacy function similar to NtUserSetWindowLong.
4097  *
4098  * Status
4099  * @implemented
4100  */
4101 
4102 WORD APIENTRY
4104 {
4105  PWND Window;
4106  WORD OldValue;
4108 
4109  TRACE("Enter NtUserSetWindowWord\n");
4111 
4112  if (hWnd == IntGetDesktopWindow())
4113  {
4115  RETURN( 0);
4116  }
4117 
4118  if (!(Window = UserGetWindowObject(hWnd)))
4119  {
4120  RETURN( 0);
4121  }
4122 
4123  switch (Index)
4124  {
4125  case GWL_ID:
4126  case GWL_HINSTANCE:
4127  case GWL_HWNDPARENT:
4129  default:
4130  if (Index < 0)
4131  {
4133  RETURN( 0);
4134  }
4135  }
4136 
4137  if ((ULONG)Index > (Window->cbwndExtra - sizeof(WORD)))
4138  {
4140  RETURN( 0);
4141  }
4142 
4143  OldValue = *((WORD *)((PCHAR)(Window + 1) + Index));
4144  *((WORD *)((PCHAR)(Window + 1) + Index)) = NewValue;
4145 
4146  RETURN( OldValue);
4147 
4148 CLEANUP:
4149  TRACE("Leave NtUserSetWindowWord, ret=%u\n", _ret_);
4150  UserLeave();
4151  END_CLEANUP;
4152 }
4153 
4154 /*
4155  QueryWindow based on KJK::Hyperion and James Tabor.
4156 
4157  0 = QWUniqueProcessId
4158  1 = QWUniqueThreadId
4159  2 = QWActiveWindow
4160  3 = QWFocusWindow
4161  4 = QWIsHung Implements IsHungAppWindow found
4162  by KJK::Hyperion.
4163 
4164  9 = QWKillWindow When I called this with hWnd ==
4165  DesktopWindow, it shutdown the system
4166  and rebooted.
4167 */
4168 /*
4169  * @implemented
4170  */
4173 {
4174 /* Console Leader Process CID Window offsets */
4175 #define GWLP_CONSOLE_LEADER_PID 0
4176 #define GWLP_CONSOLE_LEADER_TID 4
4177 
4178  DWORD_PTR Result;
4179  PWND pWnd, pwndActive;
4180  PTHREADINFO pti, ptiActive;
4182 
4183  TRACE("Enter NtUserQueryWindow\n");
4184  UserEnterShared();
4185 
4186  if (!(pWnd = UserGetWindowObject(hWnd)))
4187  {
4188  RETURN( 0);
4189  }
4190 
4191  switch(Index)
4192  {
4194  {
4195  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
4197  {
4198  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
4199  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
4200  }
4201  else
4202  {
4204  }
4205  break;
4206  }
4207 
4209  {
4210  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
4212  {
4213  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
4214  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
4215  }
4216  else
4217  {
4219  }
4220  break;
4221  }
4222 
4223  case QUERY_WINDOW_ACTIVE:
4224  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
4225  break;
4226 
4227  case QUERY_WINDOW_FOCUS:
4228  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
4229  break;
4230 
4231  case QUERY_WINDOW_ISHUNG:
4232  Result = (pWnd->fnid == FNID_GHOST) || MsqIsHung(pWnd->head.pti, MSQ_HUNG);
4233  break;
4234 
4235  case QUERY_WINDOW_REAL_ID:
4236  Result = (DWORD_PTR)pWnd->head.pti->pEThread->Cid.UniqueProcess;
4237  break;
4238 
4240  Result = (pWnd->head.pti->MessageQueue == gpqForeground);
4241  break;
4242 
4243  case QUERY_WINDOW_DEFAULT_IME: /* default IME window */
4244  if (pWnd->head.pti->spwndDefaultIme)
4245  Result = (DWORD_PTR)UserHMGetHandle(pWnd->head.pti->spwndDefaultIme);
4246  else
4247  Result = 0;
4248  break;
4249 
4250  case QUERY_WINDOW_DEFAULT_ICONTEXT: /* default input context handle */
4251  if (pWnd->head.pti->spDefaultImc)
4252  Result = (DWORD_PTR)UserHMGetHandle(pWnd->head.pti->spDefaultImc);
4253  else
4254  Result = 0;
4255  break;
4256 
4258  Result = 0;
4260  {
4261  pwndActive = gpqForeground->spwndActive;
4263  if (pti->rpdesk == pwndActive->head.rpdesk)
4264  {
4265  ptiActive = pwndActive->head.pti;
4266  if (ptiActive->spwndDefaultIme)
4268  }
4269  }
4270  break;
4271 
4272  default:
4273  Result = 0;
4274  break;
4275  }
4276 
4277  RETURN( Result);
4278 
4279 CLEANUP:
4280  TRACE("Leave NtUserQueryWindow, ret=%u\n", _ret_);
4281  UserLeave();
4282  END_CLEANUP;
4283 }
4284 
4285 /*
4286  * @implemented
4287  */
4288 UINT APIENTRY
4290 {
4291  UNICODE_STRING SafeMessageName;
4292  NTSTATUS Status;
4293  UINT Ret;
4295 
4296  TRACE("Enter NtUserRegisterWindowMessage\n");
4298 
4299  if(MessageNameUnsafe == NULL)
4300  {
4302  RETURN( 0);
4303  }
4304 
4305  Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
4306  if(!NT_SUCCESS(Status))
4307  {
4309  RETURN( 0);
4310  }
4311 
4312  Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
4313  if (SafeMessageName.Buffer)
4314  ExFreePoolWithTag(SafeMessageName.Buffer, TAG_STRING);
4315  RETURN( Ret);
4316 
4317 CLEANUP:
4318  TRACE("Leave NtUserRegisterWindowMessage, ret=%u\n", _ret_);
4319  UserLeave();
4320  END_CLEANUP;
4321 }
4322 
4323 /*
4324  * @implemented
4325  */
4326 BOOL APIENTRY
4328  WORD fnID)
4329 {
4330  PWND Wnd;
4332 
4333  TRACE("Enter NtUserSetWindowFNID\n");
4335 
4336  if (!(Wnd = UserGetWindowObject(hWnd)))
4337  {
4338  RETURN( FALSE);
4339  }
4340 
4341  if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process())
4342  {
4344  RETURN( FALSE);
4345  }
4346 
4347  // From user land we only set these.
4348  if (fnID != FNID_DESTROY)
4349  {
4350  /* HACK: The minimum should be FNID_BUTTON, but menu code relies on this */
4351  if (fnID < FNID_FIRST || fnID > FNID_GHOST ||
4352  Wnd->fnid != 0)
4353  {
4355  RETURN( FALSE);
4356  }
4357  }
4358 
4359  Wnd->fnid |= fnID;
4360  RETURN( TRUE);
4361 
4362 CLEANUP:
4363  TRACE("Leave NtUserSetWindowFNID\n");
4364  UserLeave();
4365  END_CLEANUP;
4366 }
4367 
4368 BOOL APIENTRY
4369 DefSetText(PWND Wnd, PCWSTR WindowText)
4370 {
4372  BOOL Ret = FALSE;
4373 
4374  RtlInitUnicodeString(&UnicodeString, WindowText);
4375 
4376  if (UnicodeString.Length != 0)
4377  {
4378  if (Wnd->strName.MaximumLength > 0 &&
4379  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4380  {
4381  ASSERT(Wnd->strName.Buffer != NULL);
4382 
4383  Wnd->strName.Length = UnicodeString.Length;
4384  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4386  UnicodeString.Buffer,
4387  UnicodeString.Length);
4388  }
4389  else
4390  {
4391  PWCHAR buf;
4392  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4393  buf = Wnd->strName.Buffer;
4394  Wnd->strName.Buffer = NULL;
4395  if (buf != NULL)
4396  {
4397  DesktopHeapFree(Wnd->head.rpdesk, buf);
4398  }
4399 
4401  UnicodeString.Length + sizeof(UNICODE_NULL));
4402  if (Wnd->strName.Buffer != NULL)
4403  {
4404  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4406  UnicodeString.Buffer,
4407  UnicodeString.Length);
4408  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4409  Wnd->strName.Length = UnicodeString.Length;
4410  }
4411  else
4412  {
4414  goto Exit;
4415  }
4416  }
4417  }
4418  else
4419  {
4420  Wnd->strName.Length = 0;
4421  if (Wnd->strName.Buffer != NULL)
4422  Wnd->strName.Buffer[0] = L'\0';
4423  }
4424 
4425  // FIXME: HAX! Windows does not do this in here!
4426  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4427  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4428  /* Send shell notifications */
4429  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4430  {
4431  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
4432  }
4433 
4434  Ret = TRUE;
4435 Exit:
4437  return Ret;
4438 }
4439 
4440 /*
4441  * NtUserDefSetText
4442  *
4443  * Undocumented function that is called from DefWindowProc to set
4444  * window text.
4445  *
4446  * Status
4447  * @implemented
4448  */
4449 BOOL APIENTRY
4451 {
4452  PWND Wnd;
4453  LARGE_STRING SafeText;
4455  BOOL Ret = TRUE;
4456 
4457  TRACE("Enter NtUserDefSetText\n");
4458 
4459  if (WindowText != NULL)
4460  {
4461  _SEH2_TRY
4462  {
4463  SafeText = ProbeForReadLargeString(WindowText);
4464  }
4466  {
4467  Ret = FALSE;
4469  }
4470  _SEH2_END;
4471 
4472  if (!Ret)
4473  return FALSE;
4474  }
4475  else
4476  return TRUE;
4477 
4479 
4480  if(!(Wnd = UserGetWindowObject(hWnd)))
4481  {
4482  UserLeave();
4483  return FALSE;
4484  }
4485 
4486  // ReactOS uses Unicode and not mixed. Up/Down converting will take time.
4487  // Brought to you by: The Wine Project! Dysfunctional Thought Processes!
4488  // Now we know what the bAnsi is for.
4490  if (SafeText.Buffer)
4491  {
4492  _SEH2_TRY
4493  {
4494  if (SafeText.bAnsi)
4495  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(CHAR));
4496  else
4497  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(WCHAR));
4498  Ret = RtlLargeStringToUnicodeString(&UnicodeString, &SafeText);
4499  }
4501  {
4502  Ret = FALSE;
4504  }
4505  _SEH2_END;
4506  if (!Ret) goto Exit;
4507  }
4508 
4509  if (UnicodeString.Length != 0)
4510  {
4511  if (Wnd->strName.MaximumLength > 0 &&
4512  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4513  {
4514  ASSERT(Wnd->strName.Buffer != NULL);
4515 
4516  Wnd->strName.Length = UnicodeString.Length;
4517  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4519  UnicodeString.Buffer,
4520  UnicodeString.Length);
4521  }
4522  else
4523  {
4524  PWCHAR buf;
4525  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4526  buf = Wnd->strName.Buffer;
4527  Wnd->strName.Buffer = NULL;
4528  if (buf != NULL)
4529  {
4530  DesktopHeapFree(Wnd->head.rpdesk, buf);
4531  }
4532 
4534  UnicodeString.Length + sizeof(UNICODE_NULL));
4535  if (Wnd->strName.Buffer != NULL)
4536  {
4537  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4539  UnicodeString.Buffer,
4540  UnicodeString.Length);
4541  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4542  Wnd->strName.Length = UnicodeString.Length;
4543  }
4544  else
4545  {
4547  Ret = FALSE;
4548  goto Exit;
4549  }
4550  }
4551  }
4552  else
4553  {
4554  Wnd->strName.Length = 0;
4555  if (Wnd->strName.Buffer != NULL)
4556  Wnd->strName.Buffer[0] = L'\0';
4557  }
4558 
4559  // FIXME: HAX! Windows does not do this in here!
4560  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4561  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4562  /* Send shell notifications */
4563  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4564  {
4565  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing?
4566  }
4567 
4568  Ret = TRUE;
4569 Exit:
4571  TRACE("Leave NtUserDefSetText, ret=%i\n", Ret);
4572  UserLeave();
4573  return Ret;
4574 }
4575 
4576 /*
4577  * NtUserInternalGetWindowText
4578  *
4579  * Status
4580  * @implemented
4581  */
4582 
4583 INT APIENTRY
4585 {
4586  PWND Wnd;
4587  NTSTATUS Status;
4588  INT Result;
4590 
4591  TRACE("Enter NtUserInternalGetWindowText\n");
4592  UserEnterShared();
4593 
4594  if(lpString && (nMaxCount <= 1))
4595  {
4597  RETURN( 0);
4598  }
4599 
4600  if(!(Wnd = UserGetWindowObject(hWnd)))
4601  {
4602  RETURN( 0);
4603  }
4604 
4605  Result = Wnd->strName.Length / sizeof(WCHAR);
4606  if(lpString)
4607  {
4608  const WCHAR Terminator = L'\0';
4609  INT Copy;
4610  WCHAR *Buffer = (WCHAR*)lpString;
4611 
4612  Copy = min(nMaxCount - 1, Result);
4613  if(Copy > 0)
4614  {
4615  Status = MmCopyToCaller(Buffer, Wnd->strName.Buffer, Copy * sizeof(WCHAR));
4616  if(!NT_SUCCESS(Status))
4617  {
4619  RETURN( 0);
4620  }
4621  Buffer += Copy;
4622  }
4623 
4624  Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
4625  if(!NT_SUCCESS(Status))
4626  {
4628  RETURN( 0);
4629  }
4630 
4631  Result = Copy;
4632  }
4633 
4634  RETURN( Result);
4635 
4636 CLEANUP:
4637  TRACE("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
4638  UserLeave();
4639  END_CLEANUP;
4640 }
4641 
4642 /*
4643  API Call
4644 */
4645 BOOL
4646 FASTCALL
4647 IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
4648 {
4649  int count = 0;
4650  PWND pWnd;
4651  HWND *win_array;
4652 
4653 // ASSERT(OwnerWnd);
4654 
4655  TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
4656 
4657  /* NOTE: Popups are not children */
4658  win_array = IntWinListOwnedPopups(OwnerWnd);
4659 
4660  if (!win_array)
4661  return TRUE;
4662 
4663  while (win_array[count])
4664  count++;
4665  while (--count >= 0)
4666  {
4667  if (!(pWnd = ValidateHwndNoErr( win_array[count] )))
4668  continue;
4669  if (pWnd->spwndOwner != OwnerWnd)
4670  continue;
4671 
4672  if (fShow)
4673  {
4674  if (pWnd->state & WNDS_HIDDENPOPUP)
4675  {
4676  /* In Windows, ShowOwnedPopups(TRUE) generates
4677  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4678  * regardless of the state of the owner
4679  */
4681  pWnd->state &= ~WNDS_HIDDENPOPUP;
4682  continue;
4683  }
4684  }
4685  else
4686  {
4687  if (pWnd->style & WS_VISIBLE)
4688  {
4689  /* In Windows, ShowOwnedPopups(FALSE) generates
4690  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4691  * regardless of the state of the owner
4692  */
4694  pWnd->state |= WNDS_HIDDENPOPUP;
4695  continue;
4696  }
4697  }
4698  }
4700  TRACE("Leave ShowOwnedPopups\n");
4701  return TRUE;
4702 }
4703 
4704 /* EOF */
ULONG bAnsi
Definition: ntuser.h:93
#define RDW_NOINTERNALPAINT
Definition: winuser.h:1207
#define GW_HWNDNEXT
Definition: winuser.h:756
BOOL APIENTRY NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
Definition: window.c:3699
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
HWND NTAPI NtUserCreateWindowEx(DWORD dwExStyle, PLARGE_STRING plstrClassName, PLARGE_STRING plstrClsVersion, PLARGE_STRING plstrWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam, DWORD dwFlags, PVOID acbiBuffer)
Definition: window.c:2642
#define RDW_NOCHILDREN
Definition: winuser.h:1212
signed char * PCHAR
Definition: retypes.h:7
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:13
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static const WCHAR Class[]
Definition: cfgmgr.c:42
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
#define WS_DISABLED
Definition: pedump.c:621
HWND APIENTRY NtUserGetAncestor(HWND hWnd, UINT Type)
Definition: window.c:3391
#define GA_ROOT
Definition: winuser.h:2769
#define FNID_EDIT
Definition: ntuser.h:849
#define WS_THICKFRAME
Definition: pedump.c:630
#define HWND_TERMINATOR
Definition: window.h:82
#define IS_WND_CHILD(pWnd)
Definition: window.h:105
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
#define WS_EX_WINDOWEDGE
Definition: winuser.h:407
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define IN
Definition: typedefs.h:39
GLint GLint GLsizei width
Definition: gl.h:1546
#define LONG_PTR
Definition: treelist.c:79
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION _In_ ULONG _In_ SIZE_T _In_ ULONG _In_ USHORT Depth
Definition: exfuncs.h:814
DWORD ExStyle
Definition: ntuser.h:683
#define HOOKID_TO_FLAG(HookId)
Definition: hook.h:5
LONG APIENTRY NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
Definition: window.c:4028
static HICON
Definition: imagelist.c:84
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
#define QUERY_WINDOW_UNIQUE_THREAD_ID
Definition: ntuser.h:2920
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
ENGAPI ULONG APIENTRY EngGetLastError(VOID)
Definition: error.c:12
VOID FASTCALL co_MsqInsertMouseMessage(MSG *Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
Definition: msgqueue.c:580
#define MAKEWPARAM(l, h)
Definition: winuser.h:3989
LRESULT co_UserFreeWindow(PWND Window, PPROCESSINFO ProcessData, PTHREADINFO ThreadData, BOOLEAN SendMessages)
Definition: window.c:569
#define GETPFNSERVER(fnid)
Definition: ntuser.h:888
#define QUERY_WINDOW_UNIQUE_PROCESS_ID
Definition: ntuser.h:2919
UINT HideFocus
Definition: ntuser.h:737
PWND FASTCALL ValidateHwndNoErr(HWND hWnd)
Definition: window.c:118
#define HCBT_CREATEWND
Definition: winuser.h:58
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IMAGE_ICON
Definition: winuser.h:212
HWND FASTCALL IntGetThreadFocusWindow(VOID)
Definition: focus.c:41
#define ICLS_MDICLIENT
Definition: ntuser.h:897
unsigned short RTL_ATOM
Definition: atom.c:42
#define FNID_COMBOBOX
Definition: ntuser.h:846
#define CLEANUP
Definition: ntuser.h:5
LIST_ENTRY ThreadListEntry
Definition: ntuser.h:743
#define SM_CYSIZE
Definition: winuser.h:986
WNDPROC pfnClientPrevious
Definition: ntuser.h:535
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1146
struct _DESKTOP * rpdesk
Definition: ntuser.h:186
BOOL FASTCALL MsqIsHung(PTHREADINFO pti, DWORD TimeOut)
Definition: msgqueue.c:2193
struct _WND2LB * PWND2LB
#define GW_CHILD
Definition: winuser.h:758
VOID FASTCALL IntUnlinkWindow(PWND Wnd)
Definition: window.c:1341
long y
Definition: polytest.cpp:48
struct tagIMC * spDefaultImc
Definition: win32.h:133
#define LAYOUT_RTL
Definition: wingdi.h:1371
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
BOOL APIENTRY NtUserGetComboBoxInfo(HWND hWnd, PCOMBOBOXINFO pcbi)
Definition: window.c:3451
ULONG PropListItems
Definition: ntuser.h:703
DWORD ExStyle2
Definition: ntuser.h:724
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:480
#define TAG_HOOK
Definition: tags.h:5
HWND FASTCALL co_UserSetFocus(PWND Window)
Definition: focus.c:1309
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
#define CBF_BUTTONDOWN
Definition: window.c:3445
PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:481
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define UserIsDesktopWindow(pWnd)
Definition: desktop.h:194
#define WNDS2_BOTTOMMOST
Definition: ntuser.h:629
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:840
#define WS_EX2_LINKED
Definition: ntuser.h:659
long x
Definition: polytest.cpp:48
PVOID Buffer
Definition: ntuser.h:94
#define QUERY_WINDOW_FOREGROUND
Definition: ntuser.h:2925
BOOL FASTCALL IntReleaseCapture(VOID)
Definition: focus.c:1525
#define IntWndBelongsToThread(WndObj, W32Thread)
Definition: window.h:31
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:885
#define SB_VERT
Definition: winuser.h:553
NTSTATUS NTAPI ProbeAndCaptureLargeString(OUT PLARGE_STRING plstrSafe, IN PLARGE_STRING plstrUnsafe)
Definition: window.c:2585
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
BOOL APIENTRY DefSetText(PWND Wnd, PCWSTR WindowText)
Definition: window.c:4369
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define SW_HIDE
Definition: winuser.h:762
#define CURSORF_FROMRESOURCE
Definition: ntuser.h:1166
LIST_ENTRY WindowListHead
Definition: win32.h:156
HWND FASTCALL UserGetActiveWindow(VOID)
Definition: focus.c:1424
HINSTANCE hModule
Definition: ntuser.h:687
#define ASSERT_REFS_CO(_obj_)
Definition: userfuncs.h:14
static __inline BOOL IsCallProcHandle(IN WNDPROC lpWndProc)
Definition: class.h:13
WNDPROC lpfnWndProc
Definition: ntuser.h:697
BOOL FASTCALL IntValidateOwnerDepth(PWND Wnd, PWND Owner)
Definition: window.c:362
LPCREATESTRUCTW lpcs
Definition: winuser.h:2955
#define GWL_ID
Definition: winuser.h:853
struct tagWINDOWLIST * pNextList
Definition: window.h:86
HINSTANCE hModule
Definition: ntuser.h:567
GLuint GLuint GLsizei count
Definition: gl.h:1545
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
char CHAR
Definition: xmlstorage.h:175
FLONG TIF_flags
Definition: win32.h:96
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define QUERY_WINDOW_REAL_ID
Definition: ntuser.h:2924
UINT wState
Definition: comctl32.h:149
#define WNDS_SENDNCPAINT
Definition: ntuser.h:599
#define SB_HORZ
Definition: winuser.h:552
VOID FASTCALL IntNotifyWinEvent(DWORD Event, PWND pWnd, LONG idObject, LONG idChild, DWORD flags)
Definition: event.c:179
#define WINVER_WIN2K
Definition: window.h:55
#define MAKELPARAM(l, h)
Definition: winuser.h:3988
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
BOOLEAN FASTCALL co_WinPosSetWindowPos(PWND Window, HWND WndInsertAfter, INT x, INT y, INT cx, INT cy, UINT flags)
Definition: winpos.c:1721
LONG NTSTATUS
Definition: precomp.h:26
#define ICLS_EDIT
Definition: ntuser.h:892
KTHREAD Tcb
Definition: pstypes.h:1103
PSERVERINFO gpsi
Definition: imm.c:17
#define OBJID_WINDOW
Definition: winable.h:15
LIST_ENTRY PropListHead
Definition: ntuser.h:702
HWND hWnd
Definition: settings.c:17
#define ICLS_DESKTOP
Definition: ntuser.h:908
VOID FASTCALL UserClipboardRelease(PWND pWindow)
Definition: clipboard.c:374
LONG top
Definition: windef.h:307
#define WS_EX_LAYOUTRTL
Definition: winuser.h:390
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:27
struct _WND::@4900 InternalPos
#define HSHELL_WINDOWCREATED
Definition: winuser.h:1245<