ReactOS  0.4.15-dev-5137-g826bd41
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)
2057  {
2058  HWND hImeWnd;
2060  UserRefObjectCo(pwndDefaultIme, &Ref);
2061 
2062  hImeWnd = UserHMGetHandle(pwndDefaultIme);
2063 
2065 
2066  if (pti->pClientInfo->CI_flags & CI_IMMACTIVATE)
2067  {
2068  HKL hKL = pti->KeyboardLayout->hkl;
2070  pti->pClientInfo->CI_flags &= ~CI_IMMACTIVATE;
2071  }
2072 
2073  UserDerefObjectCo(pwndDefaultIme);
2074  }
2075  }
2076 
2077  /* Correct the window style. */
2078  if ((pWnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2079  {
2080  pWnd->style |= WS_CLIPSIBLINGS;
2081  if (!(pWnd->style & WS_POPUP))
2082  {
2083  pWnd->style |= WS_CAPTION;
2084  }
2085  }
2086 
2087  /* WS_EX_WINDOWEDGE depends on some other styles */
2088  if (pWnd->ExStyle & WS_EX_DLGMODALFRAME)
2089  pWnd->ExStyle |= WS_EX_WINDOWEDGE;
2090  else if (pWnd->style & (WS_DLGFRAME | WS_THICKFRAME))
2091  {
2092  if (!((pWnd->ExStyle & WS_EX_STATICEDGE) &&
2093  (pWnd->style & (WS_CHILD | WS_POPUP))))
2094  pWnd->ExStyle |= WS_EX_WINDOWEDGE;
2095  }
2096  else
2097  pWnd->ExStyle &= ~WS_EX_WINDOWEDGE;
2098 
2099  if (!(pWnd->style & (WS_CHILD | WS_POPUP)))
2100  pWnd->state |= WNDS_SENDSIZEMOVEMSGS;
2101 
2102  /* Set the window menu */
2103  if ((Cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2104  {
2105  if (Cs->hMenu)
2106  {
2107  IntSetMenu(pWnd, Cs->hMenu, &MenuChanged);
2108  }
2109  else if (pWnd->pcls->lpszMenuName) // Take it from the parent.
2110  {
2111  UNICODE_STRING MenuName;
2112  HMENU hMenu;
2113 
2114  if (IS_INTRESOURCE(pWnd->pcls->lpszMenuName))
2115  {
2116  MenuName.Length = 0;
2117  MenuName.MaximumLength = 0;
2118  MenuName.Buffer = pWnd->pcls->lpszMenuName;
2119  }
2120  else
2121  {
2122  RtlInitUnicodeString( &MenuName, pWnd->pcls->lpszMenuName);
2123  }
2124  hMenu = co_IntCallLoadMenu( pWnd->pcls->hModule, &MenuName);
2125  if (hMenu) IntSetMenu(pWnd, hMenu, &MenuChanged);
2126  }
2127  }
2128  else // Not a child
2129  pWnd->IDMenu = (UINT_PTR)Cs->hMenu;
2130 
2131 
2132  if ( ParentWindow &&
2133  ParentWindow != ParentWindow->head.rpdesk->spwndMessage &&
2134  ParentWindow != ParentWindow->head.rpdesk->pDeskInfo->spwnd )
2135  {
2136  PWND Owner = IntGetNonChildAncestor(ParentWindow);
2137 
2138  if (!IntValidateOwnerDepth(pWnd, Owner))
2139  {
2141  goto Error;
2142  }
2143  if ( pWnd->spwndOwner &&
2144  pWnd->spwndOwner->ExStyle & WS_EX_TOPMOST )
2145  {
2146  pWnd->ExStyle |= WS_EX_TOPMOST;
2147  }
2148  if ( pWnd->spwndOwner &&
2149  Class->atomClassName != gpsi->atomSysClass[ICLS_IME] &&
2150  pti != pWnd->spwndOwner->head.pti)
2151  {
2152  //ERR("CreateWindow Owner in.\n");
2153  UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE);
2154  }
2155  }
2156 
2157  /* Insert the window into the thread's window list. */
2159 
2160  /* Handle "CS_CLASSDC", it is tested first. */
2161  if ( (pWnd->pcls->style & CS_CLASSDC) && !(pWnd->pcls->pdce) )
2162  { /* One DCE per class to have CLASS. */
2163  pWnd->pcls->pdce = DceAllocDCE( pWnd, DCE_CLASS_DC );
2164  }
2165  else if ( pWnd->pcls->style & CS_OWNDC)
2166  { /* Allocate a DCE for this window. */
2167  DceAllocDCE(pWnd, DCE_WINDOW_DC);
2168  }
2169 
2170  return pWnd;
2171 
2172 AllocError:
2173  ERR("IntCreateWindow Allocation Error.\n");
2175 Error:
2176  if(pWnd)
2177  UserDereferenceObject(pWnd);
2178  return NULL;
2179 }
2180 
2181 /*
2182  * @implemented
2183  */
2184 PWND FASTCALL
2186  PUNICODE_STRING ClassName,
2187  PLARGE_STRING WindowName,
2188  PVOID acbiBuffer,
2189  DWORD dwVer )
2190 {
2191  ULONG style;
2192  PWND Window = NULL, ParentWindow = NULL, OwnerWindow;
2193  HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter;
2194  PWINSTATION_OBJECT WinSta;
2195  PCLS Class = NULL;
2196  SIZE Size;
2197  POINT MaxSize, MaxPos, MinTrack, MaxTrack;
2198  CBT_CREATEWNDW * pCbtCreate;
2199  LRESULT Result;
2200  USER_REFERENCE_ENTRY ParentRef, Ref;
2201  PTHREADINFO pti;
2202  DWORD dwShowMode = SW_SHOW;
2203  CREATESTRUCTW *pCsw = NULL;
2204  PVOID pszClass = NULL, pszName = NULL;
2205  PWND ret = NULL;
2206 
2207  /* Get the current window station and reference it */
2208  pti = GetW32ThreadInfo();
2209  if (pti == NULL || pti->rpdesk == NULL)
2210  {
2211  ERR("Thread is not attached to a desktop! Cannot create window!\n");
2212  return NULL; // There is nothing to cleanup.
2213  }
2214  WinSta = pti->rpdesk->rpwinstaParent;
2216 
2217  pCsw = NULL;
2218  pCbtCreate = NULL;
2219 
2220  /* Get the class and reference it */
2221  Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
2222  if(!Class)
2223  {
2225  ERR("Failed to find class %wZ\n", ClassName);
2226  goto cleanup;
2227  }
2228 
2229  /* Now find the parent and the owner window */
2230  hWndParent = pti->rpdesk->pDeskInfo->spwnd->head.h;
2231  hWndOwner = NULL;
2232 
2233  if (Cs->hwndParent == HWND_MESSAGE)
2234  {
2235  Cs->hwndParent = hWndParent = pti->rpdesk->spwndMessage->head.h;
2236  }
2237  else if (Cs->hwndParent)
2238  {
2239  if ((Cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
2240  hWndOwner = Cs->hwndParent;
2241  else
2242  hWndParent = Cs->hwndParent;
2243  }
2244  else if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2245  {
2246  ERR("Cannot create a child window without a parent!\n");
2248  goto cleanup; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
2249  }
2251  (IS_INTRESOURCE(Cs->lpszClass) ||
2252  Cs->lpszClass != (LPCWSTR)MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]) ||
2253  _wcsicmp(Cs->lpszClass, L"Message") != 0))
2254  {
2255  if (pti->ppi->dwLayout & LAYOUT_RTL)
2256  {
2257  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
2258  }
2259  }
2260 
2261  ParentWindow = hWndParent ? UserGetWindowObject(hWndParent): NULL;
2262  OwnerWindow = hWndOwner ? UserGetWindowObject(hWndOwner): NULL;
2263 
2264  if (hWndParent && !ParentWindow)
2265  {
2266  ERR("Got invalid parent window handle\n");
2267  goto cleanup;
2268  }
2269  else if (hWndOwner && !OwnerWindow)
2270  {
2271  ERR("Got invalid owner window handle\n");
2272  ParentWindow = NULL;
2273  goto cleanup;
2274  }
2275 
2276  if(OwnerWindow)
2277  {
2278  if (IntIsDesktopWindow(OwnerWindow)) OwnerWindow = NULL;
2279  else if (ParentWindow && !IntIsDesktopWindow(ParentWindow))
2280  {
2281  ERR("an owned window must be created as top-level\n");
2283  goto cleanup;
2284  }
2285  else /* owner must be a top-level window */
2286  {
2287  while ((OwnerWindow->style & (WS_POPUP|WS_CHILD)) == WS_CHILD && !IntIsDesktopWindow(OwnerWindow->spwndParent))
2288  OwnerWindow = OwnerWindow->spwndParent;
2289  }
2290  }
2291 
2292  /* Fix the position and the size of the window */
2293  if (ParentWindow)
2294  {
2295  UserRefObjectCo(ParentWindow, &ParentRef);
2296  IntFixWindowCoordinates(Cs, ParentWindow, &dwShowMode);
2297  }
2298 
2299  /* Allocate and initialize the new window */
2300  Window = IntCreateWindow(Cs,
2301  WindowName,
2302  Class,
2303  ParentWindow,
2304  OwnerWindow,
2305  acbiBuffer,
2306  NULL,
2307  dwVer );
2308  if(!Window)
2309  {
2310  ERR("IntCreateWindow failed!\n");
2311  goto cleanup;
2312  }
2313 
2315  hwndInsertAfter = HWND_TOP;
2316 
2317  UserRefObjectCo(Window, &Ref);
2319  ObDereferenceObject(WinSta);
2320 
2321  /* NCCREATE, WM_NCCALCSIZE and Hooks need the original values */
2322  Cs->lpszName = (LPCWSTR) WindowName;
2323  Cs->lpszClass = (LPCWSTR) ClassName;
2324 
2326  if ( ISITHOOKED(WH_CBT) || (pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)) )
2327  {
2328  // Allocate the calling structures Justin Case this goes Global.
2331  if (!pCsw || !pCbtCreate)
2332  {
2333  ERR("UserHeapAlloc() failed!\n");
2334  goto cleanup;
2335  }
2336 
2337  if (!IntMsgCreateStructW( Window, pCsw, Cs, &pszClass, &pszName ) )
2338  {
2339  ERR("IntMsgCreateStructW() failed!\n");
2340  goto cleanup;
2341  }
2342 
2343  pCbtCreate->lpcs = pCsw;
2344  pCbtCreate->hwndInsertAfter = hwndInsertAfter;
2345 
2348  if (Result != 0)
2349  {
2350  ERR("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
2351  goto cleanup;
2352  }
2353  // Write back changes.
2354  Cs->cx = pCsw->cx;
2355  Cs->cy = pCsw->cy;
2356  Cs->x = pCsw->x;
2357  Cs->y = pCsw->y;
2358  hwndInsertAfter = pCbtCreate->hwndInsertAfter;
2359  }
2360 
2361  if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2362  {
2363  if (ParentWindow != co_GetDesktopWindow(Window))
2364  {
2365  Cs->x += ParentWindow->rcClient.left;
2366  Cs->y += ParentWindow->rcClient.top;
2367  }
2368  }
2369 
2370  /* Send the WM_GETMINMAXINFO message */
2371  Size.cx = Cs->cx;
2372  Size.cy = Cs->cy;
2373 
2374  if ((Cs->style & WS_THICKFRAME) || !(Cs->style & (WS_POPUP | WS_CHILD)))
2375  {
2376  co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack, &MaxTrack);
2377  if (Size.cx > MaxTrack.x) Size.cx = MaxTrack.x;
2378  if (Size.cy > MaxTrack.y) Size.cy = MaxTrack.y;
2379  if (Size.cx < MinTrack.x) Size.cx = MinTrack.x;
2380  if (Size.cy < MinTrack.y) Size.cy = MinTrack.y;
2381  }
2382 
2383  Window->rcWindow.left = Cs->x;
2384  Window->rcWindow.top = Cs->y;
2385  Window->rcWindow.right = Cs->x + Size.cx;
2386  Window->rcWindow.bottom = Cs->y + Size.cy;
2387  /*
2388  if (0 != (Window->style & WS_CHILD) && ParentWindow)
2389  {
2390  ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
2391  RECTL_vOffsetRect(&Window->rcWindow,
2392  ParentWindow->rcClient.left,
2393  ParentWindow->rcClient.top);
2394  }
2395  */
2396  /* correct child window coordinates if mirroring on parent is enabled */
2397  if (ParentWindow != NULL)
2398  {
2399  if ( ((Cs->style & WS_CHILD) == WS_CHILD) &&
2400  ((ParentWindow->ExStyle & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL))
2401  {
2402  Window->rcWindow.right = ParentWindow->rcClient.right - (Window->rcWindow.left - ParentWindow->rcClient.left);
2403  Window->rcWindow.left = Window->rcWindow.right - Size.cx;
2404  }
2405  }
2406 
2407  Window->rcClient = Window->rcWindow;
2408 
2409  if (Window->spwndNext || Window->spwndPrev)
2410  {
2411  ERR("Window 0x%p has been linked too early!\n", Window);
2412  }
2413 
2414  if (!(Window->state2 & WNDS2_WIN31COMPAT))
2415  {
2416  if (Class->style & CS_PARENTDC && !(ParentWindow->style & WS_CLIPCHILDREN))
2417  Window->style &= ~(WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
2418  }
2419 
2420  if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2421  {
2422  if ( !IntIsTopLevelWindow(Window) )
2423  {
2424  if (pti != ParentWindow->head.pti)
2425  {
2426  //ERR("CreateWindow Parent in.\n");
2427  UserAttachThreadInput(pti, ParentWindow->head.pti, TRUE);
2428  }
2429  }
2430  }
2431 
2432  /* Send the NCCREATE message */
2434  if (!Result)
2435  {
2436  ERR("co_UserCreateWindowEx(): NCCREATE message failed\n");
2437  goto cleanup;
2438  }
2439 
2440  /* Link the window */
2441  if (ParentWindow != NULL)
2442  {
2443  /* Link the window into the siblings list */
2444  if ((Cs->style & (WS_CHILD | WS_MAXIMIZE)) == WS_CHILD)
2446  else
2447  IntLinkHwnd(Window, hwndInsertAfter);
2448  }
2449 
2450  /* Send the WM_NCCALCSIZE message */
2451  {
2452  // RECT rc;
2453  MaxPos.x = Window->rcWindow.left;
2454  MaxPos.y = Window->rcWindow.top;
2455 
2456  Result = co_WinPosGetNonClientSize(Window, &Window->rcWindow, &Window->rcClient);
2457  //rc = Window->rcWindow;
2458  //Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM)&rc);
2459  //Window->rcClient = rc;
2460 
2461  RECTL_vOffsetRect(&Window->rcWindow, MaxPos.x - Window->rcWindow.left,
2462  MaxPos.y - Window->rcWindow.top);
2463  }
2464 
2465  /* Send the WM_CREATE message. */
2467  if (Result == (LRESULT)-1)
2468  {
2469  ERR("co_UserCreateWindowEx(): WM_CREATE message failed\n");
2470  goto cleanup;
2471  }
2472 
2473  /* Send the EVENT_OBJECT_CREATE event */
2474  IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2475 
2476  /* By setting the flag below it can be examined to determine if the window
2477  was created successfully and a valid pwnd was passed back to caller since
2478  from here the function has to succeed. */
2480 
2481  /* Send the WM_SIZE and WM_MOVE messages. */
2482  if (!(Window->state & WNDS_SENDSIZEMOVEMSGS))
2483  {
2485  }
2486 
2487  /* Show or maybe minimize or maximize the window. */
2488 
2490  if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2491  {
2492  RECTL NewPos;
2493  UINT SwFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
2494 
2495  SwFlag = co_WinPosMinMaximize(Window, SwFlag, &NewPos);
2496  SwFlag |= SWP_NOZORDER|SWP_FRAMECHANGED; /* Frame always gets changed */
2497  if (!(style & WS_VISIBLE) || (style & WS_CHILD) || UserGetActiveWindow() ||
2498  (Window->ExStyle & WS_EX_NOACTIVATE))
2499  {
2500  SwFlag |= SWP_NOACTIVATE;
2501  }
2502  co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top,
2503  NewPos.right, NewPos.bottom, SwFlag);
2504  }
2505 
2506  /* Send the WM_PARENTNOTIFY message */
2508 
2509  /* Notify the shell that a new window was created */
2510  if (Window->spwndOwner == NULL ||
2511  !(Window->spwndOwner->style & WS_VISIBLE) ||
2512  (Window->spwndOwner->ExStyle & WS_EX_TOOLWINDOW))
2513  {
2514  if (UserIsDesktopWindow(Window->spwndParent) &&
2515  (Window->style & WS_VISIBLE) &&
2516  (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
2517  (Window->ExStyle & WS_EX_APPWINDOW)))
2518  {
2520  }
2521  }
2522 
2523  /* Initialize and show the window's scrollbars */
2524  if (Window->style & WS_VSCROLL)
2525  {
2527  }
2528  if (Window->style & WS_HSCROLL)
2529  {
2531  }
2532 
2533  /* Show the new window */
2534  if (Cs->style & WS_VISIBLE)
2535  {
2536  if (Window->style & WS_MAXIMIZE)
2537  dwShowMode = SW_SHOW;
2538  else if (Window->style & WS_MINIMIZE)
2539  dwShowMode = SW_SHOWMINIMIZED;
2540 
2541  co_WinPosShowWindow(Window, dwShowMode);
2542 
2543  if (Window->ExStyle & WS_EX_MDICHILD)
2544  {
2545  ASSERT(ParentWindow);
2546  if(!ParentWindow)
2547  goto cleanup;
2548  co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
2549  /* ShowWindow won't activate child windows */
2551  }
2552  }
2553 
2554  if (Class->atomClassName == gaGuiConsoleWndClass)
2555  {
2556  /* Count only console windows manually */
2558  }
2559 
2560  TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
2561  ret = Window;
2562 
2563 cleanup:
2564  if (!ret)
2565  {
2566  TRACE("co_UserCreateWindowEx(): Error Created window!\n");
2567  /* If the window was created, the class will be dereferenced by co_UserDestroyWindow */
2568  if (Window)
2570  else if (Class)
2571  IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
2572  }
2573 
2574  if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
2575  if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
2576  if (pszName) UserHeapFree(pszName);
2577  if (pszClass) UserHeapFree(pszClass);
2578 
2579  if (Window)
2580  {
2582  }
2583  if (ParentWindow) UserDerefObjectCo(ParentWindow);
2584 
2585  // See CORE-13717, not setting error on success.
2586  if (ret)
2588 
2589  return ret;
2590 }
2591 
2592 NTSTATUS
2593 NTAPI
2595  OUT PLARGE_STRING plstrSafe,
2596  IN PLARGE_STRING plstrUnsafe)
2597 {
2598  LARGE_STRING lstrTemp;
2599  PVOID pvBuffer = NULL;
2600 
2601  _SEH2_TRY
2602  {
2603  /* Probe and copy the string */
2604  ProbeForRead(plstrUnsafe, sizeof(LARGE_STRING), sizeof(ULONG));
2605  lstrTemp = *plstrUnsafe;
2606  }
2608  {
2609  /* Fail */
2611  }
2612  _SEH2_END
2613 
2614  if (lstrTemp.Length != 0)
2615  {
2616  /* Allocate a buffer from paged pool */
2617  pvBuffer = ExAllocatePoolWithTag(PagedPool, lstrTemp.Length, TAG_STRING);
2618  if (!pvBuffer)
2619  {
2620  return STATUS_NO_MEMORY;
2621  }
2622 
2623  _SEH2_TRY
2624  {
2625  /* Probe and copy the buffer */
2626  ProbeForRead(lstrTemp.Buffer, lstrTemp.Length, sizeof(WCHAR));
2627  RtlCopyMemory(pvBuffer, lstrTemp.Buffer, lstrTemp.Length);
2628  }
2630  {
2631  /* Cleanup and fail */
2632  ExFreePoolWithTag(pvBuffer, TAG_STRING);
2634  }
2635  _SEH2_END
2636  }
2637 
2638  /* Set the output string */
2639  plstrSafe->Buffer = pvBuffer;
2640  plstrSafe->Length = lstrTemp.Length;
2641  plstrSafe->MaximumLength = lstrTemp.Length;
2642 
2643  return STATUS_SUCCESS;
2644 }
2645 
2649 HWND
2650 NTAPI
2652  DWORD dwExStyle,
2653  PLARGE_STRING plstrClassName,
2654  PLARGE_STRING plstrClsVersion,
2655  PLARGE_STRING plstrWindowName,
2656  DWORD dwStyle,
2657  int x,
2658  int y,
2659  int nWidth,
2660  int nHeight,
2661  HWND hWndParent,
2662  HMENU hMenu,
2664  LPVOID lpParam,
2665  DWORD dwFlags,
2666  PVOID acbiBuffer)
2667 {
2668  NTSTATUS Status;
2669  LARGE_STRING lstrWindowName;
2670  LARGE_STRING lstrClassName;
2671  LARGE_STRING lstrClsVersion;
2672  UNICODE_STRING ustrClassName;
2673  UNICODE_STRING ustrClsVersion;
2674  CREATESTRUCTW Cs;
2675  HWND hwnd = NULL;
2676  PWND pwnd;
2677 
2678  lstrWindowName.Buffer = NULL;
2679  lstrClassName.Buffer = NULL;
2680  lstrClsVersion.Buffer = NULL;
2681 
2682  if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2683  {
2684  /* check hMenu is valid handle */
2685  if (hMenu && !UserGetMenuObject(hMenu))
2686  {
2687  ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
2689  return NULL;
2690  }
2691  }
2692 
2693  /* Copy the window name to kernel mode */
2694  Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
2695  if (!NT_SUCCESS(Status))
2696  {
2697  ERR("NtUserCreateWindowEx: failed to capture plstrWindowName\n");
2699  return NULL;
2700  }
2701 
2702  plstrWindowName = &lstrWindowName;
2703 
2704  /* Check if the class is an atom */
2705  if (IS_ATOM(plstrClassName))
2706  {
2707  /* It is, pass the atom in the UNICODE_STRING */
2708  ustrClassName.Buffer = (PVOID)plstrClassName;
2709  ustrClassName.Length = 0;
2710  ustrClassName.MaximumLength = 0;
2711  }
2712  else
2713  {
2714  /* It's not, capture the class name */
2715  Status = ProbeAndCaptureLargeString(&lstrClassName, plstrClassName);
2716  if (!NT_SUCCESS(Status))
2717  {
2718  ERR("NtUserCreateWindowEx: failed to capture plstrClassName\n");
2719  /* Set last error, cleanup and return */
2721  goto cleanup;
2722  }
2723 
2724  /* We pass it on as a UNICODE_STRING */
2725  ustrClassName.Buffer = lstrClassName.Buffer;
2726  ustrClassName.Length = (USHORT)min(lstrClassName.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2727  ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
2728  }
2729 
2730  /* Check if the class version is an atom */
2731  if (IS_ATOM(plstrClsVersion))
2732  {
2733  /* It is, pass the atom in the UNICODE_STRING */
2734  ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
2735  ustrClsVersion.Length = 0;
2736  ustrClsVersion.MaximumLength = 0;
2737  }
2738  else
2739  {
2740  /* It's not, capture the class name */
2741  Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
2742  if (!NT_SUCCESS(Status))
2743  {
2744  ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
2745  /* Set last error, cleanup and return */
2747  goto cleanup;
2748  }
2749 
2750  /* We pass it on as a UNICODE_STRING */
2751  ustrClsVersion.Buffer = lstrClsVersion.Buffer;
2752  ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2753  ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
2754  }
2755 
2756  /* Fill the CREATESTRUCTW */
2757  /* we will keep here the original parameters */
2758  Cs.style = dwStyle;
2759  Cs.lpCreateParams = lpParam;
2760  Cs.hInstance = hInstance;
2761  Cs.hMenu = hMenu;
2762  Cs.hwndParent = hWndParent;
2763  Cs.cx = nWidth;
2764  Cs.cy = nHeight;
2765  Cs.x = x;
2766  Cs.y = y;
2767  Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer;
2768  Cs.lpszClass = ustrClassName.Buffer;
2769  Cs.dwExStyle = dwExStyle;
2770 
2772 
2773  /* Call the internal function */
2774  pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer, dwFlags);
2775 
2776  if(!pwnd)
2777  {
2778  ERR("co_UserCreateWindowEx failed!\n");
2779  }
2780  hwnd = pwnd ? UserHMGetHandle(pwnd) : NULL;
2781 
2782  UserLeave();
2783 
2784 cleanup:
2785  if (lstrWindowName.Buffer)
2786  {
2787  ExFreePoolWithTag(lstrWindowName.Buffer, TAG_STRING);
2788  }
2789  if (lstrClassName.Buffer)
2790  {
2791  ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
2792  }
2793  if (lstrClsVersion.Buffer)
2794  {
2795  ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
2796  }
2797 
2798  return hwnd;
2799 }
2800 
2801 // Win: xxxDW_DestroyOwnedWindows
2803 {
2804  HWND* List;
2805  HWND* phWnd;
2806  PWND pWnd;
2807  PTHREADINFO pti = Window->head.pti;
2809 
2811  if (!List)
2812  return;
2813 
2814  for (phWnd = List; *phWnd; ++phWnd)
2815  {
2816  pWnd = ValidateHwndNoErr(*phWnd);
2817  if (pWnd == NULL)
2818  continue;
2819  ASSERT(pWnd->spwndOwner == Window);
2820  ASSERT(pWnd != Window);
2821 
2822  if (IS_IMM_MODE() && !(pti->TIF_flags & TIF_INCLEANUP) &&
2823  pWnd == pti->spwndDefaultIme)
2824  {
2825  continue;
2826  }
2827 
2828  pWnd->spwndOwner = NULL;
2830  {
2831  UserRefObjectCo(pWnd, &Ref); // Temp HACK?
2832  co_UserDestroyWindow(pWnd);
2833  UserDerefObjectCo(pWnd); // Temp HACK?
2834  }
2835  else
2836  {
2837  ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
2838  }
2839  }
2840 
2842 }
2843 
2844 // Win: xxxDestroyWindow
2846 {
2847  HWND hWnd;
2848  PWND pwndTemp;
2849  PTHREADINFO ti;
2850  MSG msg;
2851  PWND Window = Object;
2852 
2853  ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
2854 
2855  hWnd = Window->head.h;
2857 
2858  TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
2859 
2860  /* Check for owner thread */
2861  if (Window->head.pti != ti)
2862  {
2863  /* Check if we are destroying the desktop window */
2864  if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
2865  {
2867  return FALSE;
2868  }
2869  }
2870 
2871  /* If window was created successfully and it is hooked */
2872  if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
2873  {
2875  {
2876  ERR("Destroy Window WH_CBT Call Hook return!\n");
2877  return FALSE;
2878  }
2879  }
2880 
2881  if (Window->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME])
2882  {
2883  if ((Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2884  {
2885  if (Window->spwndOwner)
2886  {
2887  //ERR("DestroyWindow Owner out.\n");
2888  UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE);
2889  }
2890  }
2891  }
2892 
2893  /* Inform the parent */
2894  if (Window->style & WS_CHILD)
2895  {
2897  }
2898 
2899  if (!Window->spwndOwner && !IntGetParent(Window))
2900  {
2902  }
2903 
2904  /* Hide the window */
2905  if (Window->style & WS_VISIBLE)
2906  {
2907  if (Window->style & WS_CHILD)
2908  {
2909  /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
2911  }
2912  else
2913  {
2915  }
2916  }
2917 
2918  /* Adjust last active */
2919  if ((pwndTemp = Window->spwndOwner))
2920  {
2921  while (pwndTemp->spwndOwner)
2922  pwndTemp = pwndTemp->spwndOwner;
2923 
2924  if (pwndTemp->spwndLastActive == Window)
2925  pwndTemp->spwndLastActive = Window->spwndOwner;
2926  }
2927 
2928  if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))
2929  {
2930  if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
2931  {
2933  {
2934  //ERR("DestroyWindow Parent out.\n");
2935  UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE);
2936  }
2937  }
2938  }
2939 
2940  if (Window->head.pti->MessageQueue->spwndActive == Window)
2941  Window->head.pti->MessageQueue->spwndActive = NULL;
2942  if (Window->head.pti->MessageQueue->spwndFocus == Window)
2943  Window->head.pti->MessageQueue->spwndFocus = NULL;
2944  if (Window->head.pti->MessageQueue->spwndActivePrev == Window)
2945  Window->head.pti->MessageQueue->spwndActivePrev = NULL;
2946  if (Window->head.pti->MessageQueue->spwndCapture == Window)
2947  Window->head.pti->MessageQueue->spwndCapture = NULL;
2948 
2949  /*
2950  * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL
2951  */
2952 
2953  if ((ti != NULL) && (ti->pDeskInfo != NULL))
2954  {
2955  if (ti->pDeskInfo->hShellWindow == hWnd)
2956  {
2957  ERR("Destroying the ShellWindow!\n");
2958  ti->pDeskInfo->hShellWindow = NULL;
2959  }
2960  }
2961 
2963 
2965  {
2966  return TRUE;
2967  }
2968 
2969  /* Recursively destroy owned windows */
2970  if (!(Window->style & WS_CHILD))
2971  {
2973  }
2974 
2975  /* Generate mouse move message for the next window */
2976  msg.message = WM_MOUSEMOVE;
2977  msg.wParam = UserGetMouseButtonsState();
2978  msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2979  msg.pt = gpsi->ptCursor;
2981 
2982  IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2983 
2984  /* Send destroy messages */
2986 
2987  // Destroy the default IME window if necessary
2988  if (IS_IMM_MODE() && !(ti->TIF_flags & TIF_INCLEANUP) &&
2989  ti->spwndDefaultIme && !IS_WND_IMELIKE(Window) && !(Window->state & WNDS_DESTROYED))
2990  {
2991  if (IS_WND_CHILD(Window))
2992  {
2995  }
2996  else
2997  {
3000  }
3001  }
3002 
3004  {
3005  return TRUE;
3006  }
3007 
3008  /* Destroy the window storage */
3010 
3011  return TRUE;
3012 }
3013 
3014 
3015 /*
3016  * @implemented
3017  */
3020 {
3021  PWND Window;
3023  BOOLEAN ret;
3025 
3026  TRACE("Enter NtUserDestroyWindow\n");
3028 
3029  if (!(Window = UserGetWindowObject(Wnd)))
3030  {
3031  RETURN(FALSE);
3032  }
3033 
3034  UserRefObjectCo(Window, &Ref); // FIXME: Dunno if win should be reffed during destroy...
3036  UserDerefObjectCo(Window); // FIXME: Dunno if win should be reffed during destroy...
3037 
3038  RETURN(ret);
3039 
3040 CLEANUP:
3041  TRACE("Leave NtUserDestroyWindow, ret=%u\n", _ret_);
3042  UserLeave();
3043  END_CLEANUP;
3044 }
3045 
3046 
3047 HWND FASTCALL
3049  PWND ChildAfter,
3050  RTL_ATOM ClassAtom,
3051  PUNICODE_STRING WindowName)
3052 {
3053  BOOL CheckWindowName;
3054  HWND *List, *phWnd;
3055  HWND Ret = NULL;
3056  UNICODE_STRING CurrentWindowName;
3057 
3058  ASSERT(Parent);
3059 
3060  CheckWindowName = WindowName->Buffer != 0;
3061 
3062  if((List = IntWinListChildren(Parent)))
3063  {
3064  phWnd = List;
3065  if(ChildAfter)
3066  {
3067  /* skip handles before and including ChildAfter */
3068  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
3069  ;
3070  }
3071 
3072  /* search children */
3073  while(*phWnd)
3074  {
3075  PWND Child;
3076  if(!(Child = UserGetWindowObject(*(phWnd++))))
3077  {
3078  continue;
3079  }
3080 
3081  /* Do not send WM_GETTEXT messages in the kernel mode version!
3082  The user mode version however calls GetWindowText() which will
3083  send WM_GETTEXT messages to windows belonging to its processes */
3084  if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
3085  {
3086  // FIXME: LARGE_STRING truncated
3087  CurrentWindowName.Buffer = Child->strName.Buffer;
3088  CurrentWindowName.Length = (USHORT)min(Child->strName.Length, MAXUSHORT);
3089  CurrentWindowName.MaximumLength = (USHORT)min(Child->strName.MaximumLength, MAXUSHORT);
3090  if(!CheckWindowName ||
3091  (Child->strName.Length < 0xFFFF &&
3092  !RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
3093  {
3094  Ret = Child->head.h;
3095  break;
3096  }
3097  }
3098  }
3100  }
3101 
3102  return Ret;
3103 }
3104 
3105 /*
3106  * FUNCTION:
3107  * Searches a window's children for a window with the specified
3108  * class and name
3109  * ARGUMENTS:
3110  * hwndParent = The window whose childs are to be searched.
3111  * NULL = desktop
3112  * HWND_MESSAGE = message-only windows
3113  *
3114  * hwndChildAfter = Search starts after this child window.
3115  * NULL = start from beginning
3116  *
3117  * ucClassName = Class name to search for
3118  * Reguired parameter.
3119  *
3120  * ucWindowName = Window name
3121  * ->Buffer == NULL = don't care
3122  *
3123  * RETURNS:
3124  * The HWND of the window if it was found, otherwise NULL
3125  */
3126 /*
3127  * @implemented
3128  */
3129 HWND APIENTRY
3131  HWND hwndChildAfter,
3132  PUNICODE_STRING ucClassName,
3133  PUNICODE_STRING ucWindowName,
3134  DWORD dwUnknown)
3135 {
3136  PWND Parent, ChildAfter;
3137  UNICODE_STRING ClassName = {0}, WindowName = {0};
3138  HWND Desktop, Ret = NULL;
3139  BOOL DoMessageWnd = FALSE;
3140  RTL_ATOM ClassAtom = (RTL_ATOM)0;
3142 
3143  TRACE("Enter NtUserFindWindowEx\n");
3144  UserEnterShared();
3145 
3146  if (ucClassName != NULL || ucWindowName != NULL)
3147  {
3148  _SEH2_TRY
3149  {
3150  if (ucClassName != NULL)
3151  {
3152  ClassName = ProbeForReadUnicodeString(ucClassName);
3153  if (ClassName.Length != 0)
3154  {
3155  ProbeForRead(ClassName.Buffer,
3156  ClassName.Length,
3157  sizeof(WCHAR));
3158  }
3159  else if (!IS_ATOM(ClassName.Buffer))
3160  {
3162  _SEH2_LEAVE;
3163  }
3164 
3165  if (!IntGetAtomFromStringOrAtom(&ClassName,
3166  &ClassAtom))
3167  {
3169  _SEH2_LEAVE;
3170  }
3171  }
3172 
3173  if (ucWindowName != NULL)
3174  {
3175  WindowName = ProbeForReadUnicodeString(ucWindowName);
3176  if (WindowName.Length != 0)
3177  {
3178  ProbeForRead(WindowName.Buffer,
3179  WindowName.Length,
3180  sizeof(WCHAR));
3181  }
3182  }
3183  }
3185  {
3188  }
3189  _SEH2_END;
3190 
3191  if (ucClassName != NULL)
3192  {
3193  if (ClassName.Length == 0 && ClassName.Buffer != NULL &&
3194  !IS_ATOM(ClassName.Buffer))
3195  {
3197  RETURN(NULL);
3198  }
3199  else if (ClassAtom == (RTL_ATOM)0)
3200  {
3201  /* LastError code was set by IntGetAtomFromStringOrAtom */
3202  RETURN(NULL);
3203  }
3204  }
3205  }
3206 
3208 
3209  if(hwndParent == NULL)
3210  {
3211  hwndParent = Desktop;
3212  DoMessageWnd = TRUE;
3213  }
3214  else if(hwndParent == HWND_MESSAGE)
3215  {
3217  }
3218 
3220  {
3221  RETURN( NULL);
3222  }
3223 
3224  ChildAfter = NULL;
3225  if(hwndChildAfter && !(ChildAfter = UserGetWindowObject(hwndChildAfter)))
3226  {
3227  RETURN( NULL);
3228  }
3229 
3230  _SEH2_TRY
3231  {
3232  if(Parent->head.h == Desktop)
3233  {
3234  HWND *List, *phWnd;
3235  PWND TopLevelWindow;
3236  BOOLEAN CheckWindowName;
3237  BOOLEAN WindowMatches;
3238  BOOLEAN ClassMatches;
3239 
3240  /* windows searches through all top-level windows if the parent is the desktop
3241  window */
3242 
3243  if((List = IntWinListChildren(Parent)))
3244  {
3245  phWnd = List;
3246 
3247  if(ChildAfter)
3248  {
3249  /* skip handles before and including ChildAfter */
3250  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
3251  ;
3252  }
3253 
3254  CheckWindowName = WindowName.Buffer != 0;
3255 
3256  /* search children */
3257  while(*phWnd)
3258  {
3259  UNICODE_STRING ustr;
3260 
3261  if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
3262  {
3263  continue;
3264  }
3265 
3266  /* Do not send WM_GETTEXT messages in the kernel mode version!
3267  The user mode version however calls GetWindowText() which will
3268  send WM_GETTEXT messages to windows belonging to its processes */
3269  ustr.Buffer = TopLevelWindow->strName.Buffer;
3270  ustr.Length = (USHORT)min(TopLevelWindow->strName.Length, MAXUSHORT); // FIXME:LARGE_STRING truncated
3271  ustr.MaximumLength = (USHORT)min(TopLevelWindow->strName.MaximumLength, MAXUSHORT);
3272  WindowMatches = !CheckWindowName ||
3273  (TopLevelWindow->strName.Length < 0xFFFF &&
3274  !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
3275  ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
3276  ClassAtom == TopLevelWindow->pcls->atomNVClassName;
3277 
3278  if (WindowMatches && ClassMatches)
3279  {
3280  Ret = TopLevelWindow->head.h;
3281  break;
3282  }
3283 
3284  if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
3285  {
3286  /* window returns the handle of the top-level window, in case it found
3287  the child window */
3288  Ret = TopLevelWindow->head.h;
3289  break;
3290  }
3291 
3292  }
3294  }
3295  }
3296  else
3297  {
3298  TRACE("FindWindowEx: Not Desktop Parent!\n");
3299  Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
3300  }
3301 
3302  if (Ret == NULL && DoMessageWnd)
3303  {
3304  PWND MsgWindows;
3305 
3306  if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
3307  {
3308  Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
3309  }
3310  }
3311  }
3313  {
3315  Ret = NULL;
3316  }
3317  _SEH2_END;
3318 
3319  RETURN( Ret);
3320 
3321 CLEANUP:
3322  TRACE("Leave NtUserFindWindowEx, ret %p\n", _ret_);
3323  UserLeave();
3324  END_CLEANUP;
3325 }
3326 
3327 
3328 /*
3329  * @implemented
3330  */
3332 {
3333  PWND WndAncestor, Parent;
3334 
3335  if (Wnd->head.h == IntGetDesktopWindow())
3336  {
3337  return NULL;
3338  }
3339 
3340  switch (Type)
3341  {
3342  case GA_PARENT:
3343  {
3344  WndAncestor = Wnd->spwndParent;
3345  break;
3346  }
3347 
3348  case GA_ROOT:
3349  {
3350  WndAncestor = Wnd;
3351  Parent = NULL;
3352 
3353  for(;;)
3354  {
3355  if(!(Parent = WndAncestor->spwndParent))
3356  {
3357  break;
3358  }
3360  {
3361  break;
3362  }
3363 
3364  WndAncestor = Parent;
3365  }
3366  break;
3367  }
3368 
3369  case GA_ROOTOWNER:
3370  {
3371  WndAncestor = Wnd;
3372 
3373  for (;;)
3374  {
3375  Parent = IntGetParent(WndAncestor);
3376 
3377  if (!Parent)
3378  {
3379  break;
3380  }
3381 
3382  WndAncestor = Parent;
3383  }
3384  break;
3385  }
3386 
3387  default:
3388  {
3389  return NULL;
3390  }
3391  }
3392 
3393  return WndAncestor;
3394 }
3395 
3396 /*
3397  * @implemented
3398  */
3399 HWND APIENTRY
3401 {
3402  PWND Window, Ancestor;
3404 
3405  TRACE("Enter NtUserGetAncestor\n");
3407 
3408  if (!(Window = UserGetWindowObject(hWnd)))
3409  {
3410  RETURN(NULL);
3411  }
3412 
3413  Ancestor = UserGetAncestor(Window, Type);
3414  /* faxme: can UserGetAncestor ever return NULL for a valid window? */
3415 
3416  RETURN(Ancestor ? Ancestor->head.h : NULL);
3417 
3418 CLEANUP:
3419  TRACE("Leave NtUserGetAncestor, ret=%p\n", _ret_);
3420  UserLeave();
3421  END_CLEANUP;
3422 }
3423 
3427 /* combo state struct */
3428 typedef struct
3429 {
3430  HWND self;
3431  HWND owner;
3432  UINT dwStyle;
3433  HWND hWndEdit;
3434  HWND hWndLBox;
3435  UINT wState;
3436  HFONT hFont;
3437  RECT textRect;
3438  RECT buttonRect;
3439  RECT droppedRect;
3440  INT droppedIndex;
3441  INT fixedOwnerDrawHeight;
3442  INT droppedWidth; /* last two are not used unless set */
3443  INT editHeight; /* explicitly */
3446 
3447 // Window Extra data container.
3448 typedef struct _WND2CBOX
3449 {
3452 } WND2CBOX, *PWND2CBOX;
3453 
3454 #define CBF_BUTTONDOWN 0x0002
3455 BOOL
3459 APIENTRY
3461  HWND hWnd,
3462  PCOMBOBOXINFO pcbi)
3463 {
3464  PWND Wnd;
3465  PPROCESSINFO ppi;
3466  BOOL NotSameppi = FALSE;
3467  BOOL Ret = TRUE;
3469 
3470  TRACE("Enter NtUserGetComboBoxInfo\n");
3471  UserEnterShared();
3472 
3473  if (!(Wnd = UserGetWindowObject(hWnd)))
3474  {
3475  RETURN( FALSE );
3476  }
3477  _SEH2_TRY
3478  {
3479  ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
3480  }
3482  {
3485  }
3486  _SEH2_END;
3487 
3488  if (pcbi->cbSize < sizeof(COMBOBOXINFO))
3489  {
3491  RETURN(FALSE);
3492  }
3493 
3494  // Pass the user pointer, it was already probed.
3495  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_COMBOBOX]) && Wnd->fnid != FNID_COMBOBOX)
3496  {
3497  RETURN( (BOOL) co_IntSendMessage( Wnd->head.h, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
3498  }
3499 
3501  NotSameppi = ppi != Wnd->head.pti->ppi;
3502  if (NotSameppi)
3503  {
3504  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3505  }
3506 
3507  _SEH2_TRY
3508  {
3509  LPHEADCOMBO lphc = ((PWND2CBOX)Wnd)->pCBox;
3510  pcbi->rcItem = lphc->textRect;
3511  pcbi->rcButton = lphc->buttonRect;
3512  pcbi->stateButton = 0;
3513  if (lphc->wState & CBF_BUTTONDOWN)
3515  if (RECTL_bIsEmptyRect(&lphc->buttonRect))
3517  pcbi->hwndCombo = lphc->self;
3518  pcbi->hwndItem = lphc->hWndEdit;
3519  pcbi->hwndList = lphc->hWndLBox;
3520  }
3522  {
3523  Ret = FALSE;
3525  }
3526  _SEH2_END;
3527 
3528  RETURN( Ret);
3529 
3530 CLEANUP:
3531  if (NotSameppi) KeDetachProcess();
3532  TRACE("Leave NtUserGetComboBoxInfo, ret=%i\n",_ret_);
3533  UserLeave();
3534  END_CLEANUP;
3535 }
3536 
3540 /* Listbox structure */
3541 typedef struct
3542 {
3543  HWND self; /* Our own window handle */
3544  HWND owner; /* Owner window to send notifications to */
3545  UINT style; /* Window style */
3546  INT width; /* Window width */
3547  INT height; /* Window height */
3548  VOID *items; /* Array of items */
3549  INT nb_items; /* Number of items */
3550  INT top_item; /* Top visible item */
3551  INT selected_item; /* Selected item */
3552  INT focus_item; /* Item that has the focus */
3553  INT anchor_item; /* Anchor item for extended selection */
3554  INT item_height; /* Default item height */
3555  INT page_size; /* Items per listbox page */
3556  INT column_width; /* Column width for multi-column listboxes */
3557 } LB_DESCR;
3558 
3559 // Window Extra data container.
3560 typedef struct _WND2LB
3561 {
3564 } WND2LB, *PWND2LB;
3568 DWORD
3569 APIENTRY
3571  HWND hWnd)
3572 {
3573  PWND Wnd;
3574  PPROCESSINFO ppi;
3575  BOOL NotSameppi = FALSE;
3576  DWORD Ret = 0;
3578 
3579  TRACE("Enter NtUserGetListBoxInfo\n");
3580  UserEnterShared();
3581 
3582  if (!(Wnd = UserGetWindowObject(hWnd)))
3583  {
3584  RETURN( 0 );
3585  }
3586 
3587  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_LISTBOX]) && Wnd->fnid != FNID_LISTBOX)
3588  {
3589  RETURN( (DWORD) co_IntSendMessage( Wnd->head.h, LB_GETLISTBOXINFO, 0, 0 ));
3590  }
3591 
3592  // wine lisbox:test_GetListBoxInfo lb_getlistboxinfo = 0, should not send a message!
3594  NotSameppi = ppi != Wnd->head.pti->ppi;
3595  if (NotSameppi)
3596  {
3597  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3598  }
3599 
3600  _SEH2_TRY
3601  {
3602  LB_DESCR *descr = ((PWND2LB)Wnd)->pLBiv;
3603  // See Controls ListBox.c:LB_GETLISTBOXINFO must match...
3604  Ret = descr->page_size;
3605  }
3607  {
3608  Ret = 0;
3610  }
3611  _SEH2_END;
3612 
3613  RETURN( Ret);
3614 
3615 CLEANUP:
3616  if (NotSameppi) KeDetachProcess();
3617  TRACE("Leave NtUserGetListBoxInfo, ret=%lu\n", _ret_);
3618  UserLeave();
3619  END_CLEANUP;
3620 }
3621 
3622 /*
3623  * NtUserSetParent
3624  *
3625  * The NtUserSetParent function changes the parent window of the specified
3626  * child window.
3627  *
3628  * Remarks
3629  * The new parent window and the child window must belong to the same
3630  * application. If the window identified by the hWndChild parameter is
3631  * visible, the system performs the appropriate redrawing and repainting.
3632  * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
3633  * or WS_POPUP window styles of the window whose parent is being changed.
3634  *
3635  * Status
3636  * @implemented
3637  */
3638 
3639 HWND APIENTRY
3641 {
3643 
3644  TRACE("Enter NtUserSetParent\n");
3646 
3647  /*
3648  Check Parent first from user space, set it here.
3649  */
3650  if (!hWndNewParent)
3651  {
3652  hWndNewParent = IntGetDesktopWindow();
3653  }
3654  else if (hWndNewParent == HWND_MESSAGE)
3655  {
3656  hWndNewParent = IntGetMessageWindow();
3657  }
3658 
3659  RETURN( co_UserSetParent(hWndChild, hWndNewParent));
3660 
3661 CLEANUP:
3662  TRACE("Leave NtUserSetParent, ret=%p\n", _ret_);
3663  UserLeave();
3664  END_CLEANUP;
3665 }
3666 
3667 /*
3668  * UserGetShellWindow
3669  *
3670  * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3671  *
3672  * Status
3673  * @implemented
3674  */
3676 {
3677  PWINSTATION_OBJECT WinStaObject;
3678  HWND Ret;
3679 
3681  UserMode,
3682  0,
3683  &WinStaObject,
3684  0);
3685 
3686  if (!NT_SUCCESS(Status))
3687  {
3689  return( (HWND)0);
3690  }
3691 
3692  Ret = (HWND)WinStaObject->ShellWindow;
3693 
3694  ObDereferenceObject(WinStaObject);
3695  return( Ret);
3696 }
3697 
3698 /*
3699  * NtUserSetShellWindowEx
3700  *
3701  * This is undocumented function to set global shell window. The global
3702  * shell window has special handling of window position.
3703  *
3704  * Status
3705  * @implemented
3706  */
3707 BOOL APIENTRY
3709 {
3710  PWINSTATION_OBJECT WinStaObject;
3711  PWND WndShell, WndListView;
3714  NTSTATUS Status;
3715  PTHREADINFO ti;
3716 
3717  TRACE("Enter NtUserSetShellWindowEx\n");
3719 
3720  if (!(WndShell = UserGetWindowObject(hwndShell)))
3721  {
3722  RETURN(FALSE);
3723  }
3724 
3725  if (!(WndListView = UserGetWindowObject(hwndListView)))
3726  {
3727  RETURN(FALSE);
3728  }
3729 
3731  UserMode,
3732  0,
3733  &WinStaObject,
3734  0);
3735 
3736  if (!NT_SUCCESS(Status))
3737  {
3739  RETURN( FALSE);
3740  }
3741 
3742  /*
3743  * Test if we are permitted to change the shell window.
3744  */
3745  if (WinStaObject->ShellWindow)
3746  {
3747  ObDereferenceObject(WinStaObject);
3748  RETURN( FALSE);
3749  }
3750 
3751  /*
3752  * Move shell window into background.
3753  */
3754  if (hwndListView && hwndListView != hwndShell)
3755  {
3756  /*
3757  * Disabled for now to get Explorer working.
3758  * -- Filip, 01/nov/2003
3759  */
3760 #if 0
3762 #endif
3763 
3764  if (WndListView->ExStyle & WS_EX_TOPMOST)
3765  {
3766  ObDereferenceObject(WinStaObject);
3767  RETURN( FALSE);
3768  }
3769  }
3770 
3771  if (WndShell->ExStyle & WS_EX_TOPMOST)
3772  {
3773  ObDereferenceObject(WinStaObject);
3774  RETURN( FALSE);
3775  }
3776 
3777  UserRefObjectCo(WndShell, &Ref);
3778  WndShell->state2 |= WNDS2_BOTTOMMOST;
3780 
3781  WinStaObject->ShellWindow = hwndShell;
3782  WinStaObject->ShellListView = hwndListView;
3783 
3784  ti = GetW32ThreadInfo();
3785  if (ti->pDeskInfo)
3786  {
3787  ti->pDeskInfo->hShellWindow = hwndShell;
3788  ti->pDeskInfo->spwndShell = WndShell;
3789  ti->pDeskInfo->spwndBkGnd = WndListView;
3790  ti->pDeskInfo->ppiShellProcess = ti->ppi;
3791  }
3792 
3794 
3795  UserDerefObjectCo(WndShell);
3796 
3797  ObDereferenceObject(WinStaObject);
3798  RETURN( TRUE);
3799 
3800 CLEANUP:
3801  TRACE("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
3802  UserLeave();
3803  END_CLEANUP;
3804 }
3805 
3806 // Fixes wine Win test_window_styles and todo tests...
3807 static BOOL FASTCALL
3809 {
3811  return TRUE;
3812  else if (!(ExStyle & WS_EX_STATICEDGE) && (Style & (WS_DLGFRAME | WS_THICKFRAME)))
3813  return TRUE;
3814  else
3815  return FALSE;
3816 }
3817 
3818 static LONG_PTR
3820 {
3821  PWND Window, Parent;
3822  PWINSTATION_OBJECT WindowStation;
3823  LONG_PTR OldValue;
3825 
3826  if (!(Window = UserGetWindowObject(hWnd)))
3827  {
3828  return( 0);
3829  }
3830 
3831  if ((INT)Index >= 0)
3832  {
3833  if ((Index + Size) > Window->cbwndExtra)
3834  {
3836  return( 0);
3837  }
3838 
3839 #ifdef _WIN64
3840  if (Size == sizeof(LONG))
3841  {
3842  OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
3843  *((LONG*)((PCHAR)(Window + 1) + Index)) = (LONG)NewValue;
3844  }
3845  else
3846 #endif
3847  {
3848  OldValue = *((LONG_PTR *)((PCHAR)(Window + 1) + Index));
3849  /*
3850  if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
3851  {
3852  OldValue = (LONG_PTR)IntSetWindowProc( Wnd, (WNDPROC)NewValue, Ansi);
3853  if (!OldValue) return 0;
3854  }
3855  */
3856  *((LONG_PTR*)((PCHAR)(Window + 1) + Index)) = NewValue;
3857  }
3858 
3859  }
3860  else
3861  {
3862 #ifdef _WIN64
3863  if (Size == sizeof(LONG))
3864  {
3865  if ((Index != GWL_STYLE) &&
3866  (Index != GWL_EXSTYLE) &&
3867  (Index != GWL_ID) &&
3868  (Index != GWL_USERDATA))
3869  {
3870  ERR("NtUserSetWindowLong(): Index requires pointer size: %lu\n", Index);
3872  return 0;
3873  }
3874  }
3875 #endif
3876 
3877  switch (Index)
3878  {
3879  case GWL_EXSTYLE: // LONG
3880  OldValue = (LONG) Window->ExStyle;
3881  Style.styleOld = OldValue;
3882  Style.styleNew = NewValue;
3883 
3884  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3885 
3886  /*
3887  * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3888  */
3889  WindowStation = Window->head.pti->rpdesk->rpwinstaParent;
3890  if(WindowStation)
3891  {
3892  if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3893  Style.styleNew &= ~WS_EX_TOPMOST;
3894  }
3895  /* WS_EX_WINDOWEDGE depends on some other styles */
3896  if (IntCheckFrameEdge(Window->style, NewValue))
3897  Style.styleNew |= WS_EX_WINDOWEDGE;
3898  else
3899  Style.styleNew &= ~WS_EX_WINDOWEDGE;
3900 
3901  if (!(Window->ExStyle & WS_EX_LAYERED))
3902  {
3904  }
3905 
3906  Window->ExStyle = (DWORD)Style.styleNew;
3907 
3908  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3909  break;
3910 
3911  case GWL_STYLE: // LONG
3912  OldValue = (LONG) Window->style;
3913  Style.styleOld = OldValue;
3914  Style.styleNew = NewValue;
3915 
3916  if (!bAlter)
3917  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3918 
3919  /* WS_CLIPSIBLINGS can't be reset on top-level windows */
3920  if (UserIsDesktopWindow(Window->spwndParent)) Style.styleNew |= WS_CLIPSIBLINGS;
3921  /* WS_MINIMIZE can't be reset */
3922  if (OldValue & WS_MINIMIZE) Style.styleNew |= WS_MINIMIZE;
3923  /* Fixes wine FIXME: changing WS_DLGFRAME | WS_THICKFRAME is supposed to change WS_EX_WINDOWEDGE too */
3924  if (IntCheckFrameEdge(NewValue, Window->ExStyle))
3925  Window->ExStyle |= WS_EX_WINDOWEDGE;
3926  else
3927  Window->ExStyle &= ~WS_EX_WINDOWEDGE;
3928 
3929  if ((OldValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3930  {
3931  if ((NewValue & (WS_CHILD | WS_POPUP)) != WS_CHILD)
3932  {
3934  ERR("IDMenu going null! %d\n",Window->IDMenu);
3935  Window->IDMenu = 0; // Window->spmenu = 0;
3936  }
3937  }
3938  else
3939  {
3940  if ((NewValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3941  {
3942  PMENU pMenu = UserGetMenuObject(UlongToHandle(Window->IDMenu));
3943  Window->state &= ~WNDS_HASMENU;
3944  if (pMenu)
3945  {
3946  ERR("IDMenu released 0x%p\n",pMenu);
3947  // ROS may not hold a lock after setting menu to window. But it should!
3948  //IntReleaseMenuObject(pMenu);
3949  }
3950  }
3951  }
3952 
3953  if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
3954  {
3955  if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
3956  if (Style.styleNew & WS_VISIBLE) Window->head.pti->cVisWindows++;
3958  }
3959  Window->style = (DWORD)Style.styleNew;
3960 
3961  if (!bAlter)
3962  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3963  break;
3964 
3965  case GWLP_WNDPROC: // LONG_PTR
3966  {
3967  if ( Window->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
3968  Window->fnid & FNID_FREED)
3969  {
3971  return( 0);
3972  }
3973  OldValue = (LONG_PTR)IntSetWindowProc(Window,
3974  (WNDPROC)NewValue,
3975  Ansi);
3976  break;
3977  }
3978 
3979  case GWLP_HINSTANCE: // LONG_PTR
3980  OldValue = (LONG_PTR) Window->hModule;
3981  Window->hModule = (HINSTANCE) NewValue;
3982  break;
3983 
3984  case GWLP_HWNDPARENT: // LONG_PTR
3985  Parent = Window->spwndParent;
3986  if (Parent && (Parent->head.h == IntGetDesktopWindow()))
3987  OldValue = (LONG_PTR) IntSetOwner(Window->head.h, (HWND) NewValue);
3988  else
3989  OldValue = (LONG_PTR) co_UserSetParent(Window->head.h, (HWND) NewValue);
3990  break;
3991 
3992  case GWLP_ID: // LONG
3993  OldValue = (LONG) Window->IDMenu;
3994  Window->IDMenu = (UINT) NewValue;
3995  break;
3996 
3997  case GWLP_USERDATA: // LONG or LONG_PTR
3998  OldValue = Window->dwUserData;
3999  Window->dwUserData = NewValue;
4000  break;
4001 
4002  default:
4003  ERR("NtUserSetWindowLong(): Unsupported index %lu\n", Index);
4005  OldValue = 0;
4006  break;
4007  }
4008  }
4009 
4010  return( OldValue);
4011 }
4012 
4013 LONG FASTCALL
4015 {
4016  return (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
4017 }
4018 
4021 {
4022  return co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
4023 }
4024 
4025 /*
4026  * NtUserSetWindowLong
4027  *
4028  * The NtUserSetWindowLong function changes an attribute of the specified
4029  * window. The function also sets the 32-bit (long) value at the specified
4030  * offset into the extra window memory.
4031  *
4032  * Status
4033  * @implemented
4034  */
4035 
4036 LONG APIENTRY
4038 {
4039  LONG ret;
4040 
4042 
4043  if (hWnd == IntGetDesktopWindow())
4044  {
4046  UserLeave();
4047  return 0;
4048  }
4049 
4050  ret = (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
4051 
4052  UserLeave();
4053 
4054  return ret;
4055 }
4056 
4057 #ifdef _WIN64
4060 {
4061  LONG_PTR ret;
4062 
4064 
4065  if (hWnd == IntGetDesktopWindow())
4066  {
4068  UserLeave();
4069  return 0;
4070  }
4071 
4072  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
4073 
4074  UserLeave();
4075 
4076  return ret;
4077 }
4078 #endif // _WIN64
4079 
4082 {
4083  LONG ret;
4084 
4086 
4087  if (hWnd == IntGetDesktopWindow())
4088  {
4090  UserLeave();
4091  return 0;
4092  }
4093 
4094  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, FALSE, sizeof(LONG), TRUE);
4095 
4096  UserLeave();
4097 
4098  return ret;
4099 }
4100 
4101 
4102 /*
4103  * NtUserSetWindowWord
4104  *
4105  * Legacy function similar to NtUserSetWindowLong.
4106  *
4107  * Status
4108  * @implemented
4109  */
4110 
4111 WORD APIENTRY
4113 {
4114  PWND Window;
4115  WORD OldValue;
4117 
4118  TRACE("Enter NtUserSetWindowWord\n");
4120 
4121  if (hWnd == IntGetDesktopWindow())
4122  {
4124  RETURN( 0);
4125  }
4126 
4127  if (!(Window = UserGetWindowObject(hWnd)))
4128  {
4129  RETURN( 0);
4130  }
4131 
4132  switch (Index)
4133  {
4134  case GWL_ID:
4135  case GWL_HINSTANCE:
4136  case GWL_HWNDPARENT:
4138  default:
4139  if (Index < 0)
4140  {
4142  RETURN( 0);
4143  }
4144  }
4145 
4146  if ((ULONG)Index > (Window->cbwndExtra - sizeof(WORD)))
4147  {
4149  RETURN( 0);
4150  }
4151 
4152  OldValue = *((WORD *)((PCHAR)(Window + 1) + Index));
4153  *((WORD *)((PCHAR)(Window + 1) + Index)) = NewValue;
4154 
4155  RETURN( OldValue);
4156 
4157 CLEANUP:
4158  TRACE("Leave NtUserSetWindowWord, ret=%u\n", _ret_);
4159  UserLeave();
4160  END_CLEANUP;
4161 }
4162 
4163 /*
4164  QueryWindow based on KJK::Hyperion and James Tabor.
4165 
4166  0 = QWUniqueProcessId
4167  1 = QWUniqueThreadId
4168  2 = QWActiveWindow
4169  3 = QWFocusWindow
4170  4 = QWIsHung Implements IsHungAppWindow found
4171  by KJK::Hyperion.
4172 
4173  9 = QWKillWindow When I called this with hWnd ==
4174  DesktopWindow, it shutdown the system
4175  and rebooted.
4176 */
4177 /*
4178  * @implemented
4179  */
4182 {
4183 /* Console Leader Process CID Window offsets */
4184 #define GWLP_CONSOLE_LEADER_PID 0
4185 #define GWLP_CONSOLE_LEADER_TID 4
4186 
4187  DWORD_PTR Result;
4188  PWND pWnd, pwndActive;
4189  PTHREADINFO pti, ptiActive;
4191 
4192  TRACE("Enter NtUserQueryWindow\n");
4193  UserEnterShared();
4194 
4195  if (!(pWnd = UserGetWindowObject(hWnd)))
4196  {
4197  RETURN( 0);
4198  }
4199 
4200  switch(Index)
4201  {
4203  {
4204  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
4206  {
4207  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
4208  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
4209  }
4210  else
4211  {
4213  }
4214  break;
4215  }
4216 
4218  {
4219  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
4221  {
4222  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
4223  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
4224  }
4225  else
4226  {
4228  }
4229  break;
4230  }
4231 
4232  case QUERY_WINDOW_ACTIVE:
4233  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
4234  break;
4235 
4236  case QUERY_WINDOW_FOCUS:
4237  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
4238  break;
4239 
4240  case QUERY_WINDOW_ISHUNG:
4241  Result = (pWnd->fnid == FNID_GHOST) || MsqIsHung(pWnd->head.pti, MSQ_HUNG);
4242  break;
4243 
4244  case QUERY_WINDOW_REAL_ID:
4245  Result = (DWORD_PTR)pWnd->head.pti->pEThread->Cid.UniqueProcess;
4246  break;
4247 
4249  Result = (pWnd->head.pti->MessageQueue == gpqForeground);
4250  break;
4251 
4252  case QUERY_WINDOW_DEFAULT_IME: /* default IME window */
4253  if (pWnd->head.pti->spwndDefaultIme)
4254  Result = (DWORD_PTR)UserHMGetHandle(pWnd->head.pti->spwndDefaultIme);
4255  else
4256  Result = 0;
4257  break;
4258 
4259  case QUERY_WINDOW_DEFAULT_ICONTEXT: /* default input context handle */
4260  if (pWnd->head.pti->spDefaultImc)
4261  Result = (DWORD_PTR)UserHMGetHandle(pWnd->head.pti->spDefaultImc);
4262  else
4263  Result = 0;
4264  break;
4265 
4267  Result = 0;
4269  {
4270  pwndActive = gpqForeground->spwndActive;
4272  if (pti->rpdesk == pwndActive->head.rpdesk)
4273  {
4274  ptiActive = pwndActive->head.pti;
4275  if (ptiActive->spwndDefaultIme)
4277  }
4278  }
4279  break;
4280 
4281  default:
4282  Result = 0;
4283  break;
4284  }
4285 
4286  RETURN( Result);
4287 
4288 CLEANUP:
4289  TRACE("Leave NtUserQueryWindow, ret=%u\n", _ret_);
4290  UserLeave();
4291  END_CLEANUP;
4292 }
4293 
4294 /*
4295  * @implemented
4296  */
4297 UINT APIENTRY
4299 {
4300  UNICODE_STRING SafeMessageName;
4301  NTSTATUS Status;
4302  UINT Ret;
4304 
4305  TRACE("Enter NtUserRegisterWindowMessage\n");
4307 
4308  if(MessageNameUnsafe == NULL)
4309  {
4311  RETURN( 0);
4312  }
4313 
4314  Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
4315  if(!NT_SUCCESS(Status))
4316  {
4318  RETURN( 0);
4319  }
4320 
4321  Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
4322  if (SafeMessageName.Buffer)
4323  ExFreePoolWithTag(SafeMessageName.Buffer, TAG_STRING);
4324  RETURN( Ret);
4325 
4326 CLEANUP:
4327  TRACE("Leave NtUserRegisterWindowMessage, ret=%u\n", _ret_);
4328  UserLeave();
4329  END_CLEANUP;
4330 }
4331 
4332 /*
4333  * @implemented
4334  */
4335 BOOL APIENTRY
4337  WORD fnID)
4338 {
4339  PWND Wnd;
4341 
4342  TRACE("Enter NtUserSetWindowFNID\n");
4344 
4345  if (!(Wnd = UserGetWindowObject(hWnd)))
4346  {
4347  RETURN( FALSE);
4348  }
4349 
4350  if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process())
4351  {
4353  RETURN( FALSE);
4354  }
4355 
4356  // From user land we only set these.
4357  if (fnID != FNID_DESTROY)
4358  {
4359  /* HACK: The minimum should be FNID_BUTTON, but menu code relies on this */
4360  if (fnID < FNID_FIRST || fnID > FNID_GHOST ||
4361  Wnd->fnid != 0)
4362  {
4364  RETURN( FALSE);
4365  }
4366  }
4367 
4368  Wnd->fnid |= fnID;
4369  RETURN( TRUE);
4370 
4371 CLEANUP:
4372  TRACE("Leave NtUserSetWindowFNID\n");
4373  UserLeave();
4374  END_CLEANUP;
4375 }
4376 
4377 BOOL APIENTRY
4378 DefSetText(PWND Wnd, PCWSTR WindowText)
4379 {
4381  BOOL Ret = FALSE;
4382 
4383  RtlInitUnicodeString(&UnicodeString, WindowText);
4384 
4385  if (UnicodeString.Length != 0)
4386  {
4387  if (Wnd->strName.MaximumLength > 0 &&
4388  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4389  {
4390  ASSERT(Wnd->strName.Buffer != NULL);
4391 
4392  Wnd->strName.Length = UnicodeString.Length;
4393  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4395  UnicodeString.Buffer,
4396  UnicodeString.Length);
4397  }
4398  else
4399  {
4400  PWCHAR buf;
4401  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4402  buf = Wnd->strName.Buffer;
4403  Wnd->strName.Buffer = NULL;
4404  if (buf != NULL)
4405  {
4406  DesktopHeapFree(Wnd->head.rpdesk, buf);
4407  }
4408 
4410  UnicodeString.Length + sizeof(UNICODE_NULL));
4411  if (Wnd->strName.Buffer != NULL)
4412  {
4413  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4415  UnicodeString.Buffer,
4416  UnicodeString.Length);
4417  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4418  Wnd->strName.Length = UnicodeString.Length;
4419  }
4420  else
4421  {
4423  goto Exit;
4424  }
4425  }
4426  }
4427  else
4428  {
4429  Wnd->strName.Length = 0;
4430  if (Wnd->strName.Buffer != NULL)
4431  Wnd->strName.Buffer[0] = L'\0';
4432  }
4433 
4434  // FIXME: HAX! Windows does not do this in here!
4435  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4436  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4437  /* Send shell notifications */
4438  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4439  {
4440  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
4441  }
4442 
4443  Ret = TRUE;
4444 Exit:
4446  return Ret;
4447 }
4448 
4449 /*
4450  * NtUserDefSetText
4451  *
4452  * Undocumented function that is called from DefWindowProc to set
4453  * window text.
4454  *
4455  * Status
4456  * @implemented
4457  */
4458 BOOL APIENTRY
4460 {
4461  PWND Wnd;
4462  LARGE_STRING SafeText;
4464  BOOL Ret = TRUE;
4465 
4466  TRACE("Enter NtUserDefSetText\n");
4467 
4468  if (WindowText != NULL)
4469  {
4470  _SEH2_TRY
4471  {
4472  SafeText = ProbeForReadLargeString(WindowText);
4473  }
4475  {
4476  Ret = FALSE;
4478  }
4479  _SEH2_END;
4480 
4481  if (!Ret)
4482  return FALSE;
4483  }
4484  else
4485  return TRUE;
4486 
4488 
4489  if(!(Wnd = UserGetWindowObject(hWnd)))
4490  {
4491  UserLeave();
4492  return FALSE;
4493  }
4494 
4495  // ReactOS uses Unicode and not mixed. Up/Down converting will take time.
4496  // Brought to you by: The Wine Project! Dysfunctional Thought Processes!
4497  // Now we know what the bAnsi is for.
4499  if (SafeText.Buffer)
4500  {
4501  _SEH2_TRY
4502  {
4503  if (SafeText.bAnsi)
4504  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(CHAR));
4505  else
4506  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(WCHAR));
4507  Ret = RtlLargeStringToUnicodeString(&UnicodeString, &SafeText);
4508  }
4510  {
4511  Ret = FALSE;
4513  }
4514  _SEH2_END;
4515  if (!Ret) goto Exit;
4516  }
4517 
4518  if (UnicodeString.Length != 0)
4519  {
4520  if (Wnd->strName.MaximumLength > 0 &&
4521  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4522  {
4523  ASSERT(Wnd->strName.Buffer != NULL);
4524 
4525  Wnd->strName.Length = UnicodeString.Length;
4526  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4528  UnicodeString.Buffer,
4529  UnicodeString.Length);
4530  }
4531  else
4532  {
4533  PWCHAR buf;
4534  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4535  buf = Wnd->strName.Buffer;
4536  Wnd->strName.Buffer = NULL;
4537  if (buf != NULL)
4538  {
4539  DesktopHeapFree(Wnd->head.rpdesk, buf);
4540  }
4541 
4543  UnicodeString.Length + sizeof(UNICODE_NULL));
4544  if (Wnd->strName.Buffer != NULL)
4545  {
4546  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4548  UnicodeString.Buffer,
4549  UnicodeString.Length);
4550  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4551  Wnd->strName.Length = UnicodeString.Length;
4552  }
4553  else
4554  {
4556  Ret = FALSE;
4557  goto Exit;
4558  }
4559  }
4560  }
4561  else
4562  {
4563  Wnd->strName.Length = 0;
4564  if (Wnd->strName.Buffer != NULL)
4565  Wnd->strName.Buffer[0] = L'\0';
4566  }
4567 
4568  // FIXME: HAX! Windows does not do this in here!
4569  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4570  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4571  /* Send shell notifications */
4572  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4573  {
4574  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing?
4575  }
4576 
4577  Ret = TRUE;
4578 Exit:
4580  TRACE("Leave NtUserDefSetText, ret=%i\n", Ret);
4581  UserLeave();
4582  return Ret;
4583 }
4584 
4585 /*
4586  * NtUserInternalGetWindowText
4587  *
4588  * Status
4589  * @implemented
4590  */
4591 
4592 INT APIENTRY
4594 {
4595  PWND Wnd;
4596  NTSTATUS Status;
4597  INT Result;
4599 
4600  TRACE("Enter NtUserInternalGetWindowText\n");
4601  UserEnterShared();
4602 
4603  if(lpString && (nMaxCount <= 1))
4604  {
4606  RETURN( 0);
4607  }
4608 
4609  if(!(Wnd = UserGetWindowObject(hWnd)))
4610  {
4611  RETURN( 0);
4612  }
4613 
4614  Result = Wnd->strName.Length / sizeof(WCHAR);
4615  if(lpString)
4616  {
4617  const WCHAR Terminator = L'\0';
4618  INT Copy;
4619  WCHAR *Buffer = (WCHAR*)lpString;
4620 
4621  Copy = min(nMaxCount - 1, Result);
4622  if(Copy > 0)
4623  {
4624  Status = MmCopyToCaller(Buffer, Wnd->strName.Buffer, Copy * sizeof(WCHAR));
4625  if(!NT_SUCCESS(Status))
4626  {
4628  RETURN( 0);
4629  }
4630  Buffer += Copy;
4631  }
4632 
4633  Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
4634  if(!NT_SUCCESS(Status))
4635  {
4637  RETURN( 0);
4638  }
4639 
4640  Result = Copy;
4641  }
4642 
4643  RETURN( Result);
4644 
4645 CLEANUP:
4646  TRACE("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
4647  UserLeave();
4648  END_CLEANUP;
4649 }
4650 
4651 /*
4652  API Call
4653 */
4654 BOOL
4655 FASTCALL
4656 IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
4657 {
4658  int count = 0;
4659  PWND pWnd;
4660  HWND *win_array;
4661 
4662 // ASSERT(OwnerWnd);
4663 
4664  TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
4665 
4666  /* NOTE: Popups are not children */
4667  win_array = IntWinListOwnedPopups(OwnerWnd);
4668 
4669  if (!win_array)
4670  return TRUE;
4671 
4672  while (win_array[count])
4673  count++;
4674  while (--count >= 0)
4675  {
4676  if (!(pWnd = ValidateHwndNoErr( win_array[count] )))
4677  continue;
4678  if (pWnd->spwndOwner != OwnerWnd)
4679  continue;
4680 
4681  if (fShow)
4682  {
4683  if (pWnd->state & WNDS_HIDDENPOPUP)
4684  {
4685  /* In Windows, ShowOwnedPopups(TRUE) generates
4686  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4687  * regardless of the state of the owner
4688  */
4690  pWnd->state &= ~WNDS_HIDDENPOPUP;
4691  continue;
4692  }
4693  }
4694  else
4695  {
4696  if (pWnd->style & WS_VISIBLE)
4697  {
4698  /* In Windows, ShowOwnedPopups(FALSE) generates
4699  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4700  * regardless of the state of the owner
4701  */
4703  pWnd->state |= WNDS_HIDDENPOPUP;
4704  continue;
4705  }
4706  }
4707  }
4709  TRACE("Leave ShowOwnedPopups\n");
4710  return TRUE;
4711 }
4712 
4713 /* 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:3708
_SEH2_TRY
Definition: create.c:4226
#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:2651
#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:3400
#define GA_ROOT
Definition: winuser.h:2779
#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:107
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:4037
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:2923
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:3999
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:2922
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:128
#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:3460
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:1314
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
#define CBF_BUTTONDOWN
Definition: window.c:3454
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:2928
BOOL FASTCALL IntReleaseCapture(VOID)
Definition: focus.c:1530
#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:2594
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
BOOL APIENTRY DefSetText(PWND Wnd, PCWSTR WindowText)
Definition: window.c:4378
#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:151
HWND FASTCALL UserGetActiveWindow(VOID)
Definition: focus.c:1429
HINSTANCE hModule
Definition: ntuser.h:687
#define IS_IMM_MODE()
Definition: ntuser.h:1204
#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:2965
#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:91
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define QUERY_WINDOW_REAL_ID
Definition: ntuser.h:2927
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:3998
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:1748
LONG NTSTATUS
Definition: precomp.h:26
#define ICLS_EDIT
Definition: ntuser.h:892
struct _WND::@4901 InternalPos
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