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