ReactOS  0.4.14-dev-55-g2da92ac
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  DWORD dwVer )
1620 {
1621  PWND pWnd = NULL;
1622  HWND hWnd;
1623  PTHREADINFO pti = NULL;
1624  BOOL MenuChanged;
1625  BOOL bUnicodeWindow;
1626 
1627  pti = pdeskCreated ? gptiDesktopThread : GetW32ThreadInfo();
1628 
1629  if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL))
1630  { // Need both here for wine win.c test_CreateWindow.
1631  //if (Cs->hwndParent && ParentWindow)
1632  if (ParentWindow) // It breaks more tests..... WIP.
1633  {
1634  if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD &&
1635  ParentWindow->ExStyle & WS_EX_LAYOUTRTL &&
1636  !(ParentWindow->ExStyle & WS_EX_NOINHERITLAYOUT) )
1637  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
1638  }
1639  else
1640  { /*
1641  * Note from MSDN <http://msdn.microsoft.com/en-us/library/aa913269.aspx>:
1642  *
1643  * Dialog boxes and message boxes do not inherit layout, so you must
1644  * set the layout explicitly.
1645  */
1646  if ( Class->fnid != FNID_DIALOG )
1647  {
1648  if (pti->ppi->dwLayout & LAYOUT_RTL)
1649  {
1650  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
1651  }
1652  }
1653  }
1654  }
1655 
1656  /* Automatically add WS_EX_WINDOWEDGE */
1657  if ((Cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1658  ((!(Cs->dwExStyle & WS_EX_STATICEDGE)) &&
1659  (Cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1660  Cs->dwExStyle |= WS_EX_WINDOWEDGE;
1661  else
1662  Cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1663 
1664  /* Is it a unicode window? */
1665  bUnicodeWindow =!(Cs->dwExStyle & WS_EX_SETANSICREATOR);
1667 
1668  /* Allocate the new window */
1670  pdeskCreated ? pdeskCreated : pti->rpdesk,
1671  pti,
1672  (PHANDLE)&hWnd,
1673  TYPE_WINDOW,
1674  sizeof(WND) + Class->cbwndExtra);
1675 
1676  if (!pWnd)
1677  {
1678  goto AllocError;
1679  }
1680 
1681  TRACE("Created window object with handle %p\n", hWnd);
1682 
1683  if (pdeskCreated && pdeskCreated->DesktopWindow == NULL )
1684  { /* HACK: Helper for win32csr/desktopbg.c */
1685  /* If there is no desktop window yet, we must be creating it */
1686  TRACE("CreateWindow setting desktop.\n");
1687  pdeskCreated->DesktopWindow = hWnd;
1688  pdeskCreated->pDeskInfo->spwnd = pWnd;
1689  }
1690 
1691  /*
1692  * Fill out the structure describing it.
1693  */
1694  /* Remember, pWnd->head is setup in object.c ... */
1695  pWnd->spwndParent = ParentWindow;
1696  pWnd->spwndOwner = OwnerWindow;
1697  pWnd->fnid = 0;
1698  pWnd->spwndLastActive = pWnd;
1699  // Ramp up compatible version sets.
1700  if ( dwVer >= WINVER_WIN31 )
1701  {
1702  pWnd->state2 |= WNDS2_WIN31COMPAT;
1703  if ( dwVer >= WINVER_WINNT4 )
1704  {
1705  pWnd->state2 |= WNDS2_WIN40COMPAT;
1706  if ( dwVer >= WINVER_WIN2K )
1707  {
1708  pWnd->state2 |= WNDS2_WIN50COMPAT;
1709  }
1710  }
1711  }
1712  pWnd->pcls = Class;
1713  pWnd->hModule = Cs->hInstance;
1714  pWnd->style = Cs->style & ~WS_VISIBLE;
1715  pWnd->ExStyle = Cs->dwExStyle;
1716  pWnd->cbwndExtra = pWnd->pcls->cbwndExtra;
1717  pWnd->pActCtx = acbiBuffer;
1718  pWnd->InternalPos.MaxPos.x = pWnd->InternalPos.MaxPos.y = -1;
1719  pWnd->InternalPos.IconPos.x = pWnd->InternalPos.IconPos.y = -1;
1720 
1721  if (pWnd->spwndParent != NULL && Cs->hwndParent != 0)
1722  {
1723  pWnd->HideFocus = pWnd->spwndParent->HideFocus;
1724  pWnd->HideAccel = pWnd->spwndParent->HideAccel;
1725  }
1726 
1727  pWnd->head.pti->cWindows++;
1728 
1729  if (Class->spicn && !Class->spicnSm)
1730  {
1731  HICON IconSmHandle = NULL;
1732  if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
1734  {
1735  IconSmHandle = co_IntCopyImage(
1736  UserHMGetHandle(Class->spicn),
1737  IMAGE_ICON,
1741  }
1742  if (!IconSmHandle)
1743  {
1744  /* Retry without copying from resource */
1745  IconSmHandle = co_IntCopyImage(
1746  UserHMGetHandle(Class->spicn),
1747  IMAGE_ICON,
1750  0);
1751  }
1752 
1753  if (IconSmHandle)
1754  {
1755  Class->spicnSm = UserGetCurIconObject(IconSmHandle);
1756  Class->CSF_flags |= CSF_CACHEDSMICON;
1757  }
1758  }
1759 
1760  if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
1762 
1763  /* BugBoy Comments: Comment below say that System classes are always created
1764  as UNICODE. In windows, creating a window with the ANSI version of CreateWindow
1765  sets the window to ansi as verified by testing with IsUnicodeWindow API.
1766 
1767  No where can I see in code or through testing does the window change back
1768  to ANSI after being created as UNICODE in ROS. I didnt do more testing to
1769  see what problems this would cause. */
1770 
1771  // Set WndProc from Class.
1772  pWnd->lpfnWndProc = pWnd->pcls->lpfnWndProc;
1773 
1774  // GetWindowProc, test for non server side default classes and set WndProc.
1775  if ( pWnd->pcls->fnid <= FNID_GHOST && pWnd->pcls->fnid >= FNID_BUTTON )
1776  {
1777  if (bUnicodeWindow)
1778  {
1779  if (GETPFNCLIENTA(pWnd->pcls->fnid) == pWnd->lpfnWndProc)
1780  pWnd->lpfnWndProc = GETPFNCLIENTW(pWnd->pcls->fnid);
1781  }
1782  else
1783  {
1784  if (GETPFNCLIENTW(pWnd->pcls->fnid) == pWnd->lpfnWndProc)
1785  pWnd->lpfnWndProc = GETPFNCLIENTA(pWnd->pcls->fnid);
1786  }
1787  }
1788 
1789  // If not an Unicode caller, set Ansi creator bit.
1790  if (!bUnicodeWindow) pWnd->state |= WNDS_ANSICREATOR;
1791 
1792  // Clone Class Ansi/Unicode proc type.
1793  if (pWnd->pcls->CSF_flags & CSF_ANSIPROC)
1794  {
1795  pWnd->state |= WNDS_ANSIWINDOWPROC;
1796  pWnd->Unicode = FALSE;
1797  }
1798  else
1799  { /*
1800  * It seems there can be both an Ansi creator and Unicode Class Window
1801  * WndProc, unless the following overriding conditions occur:
1802  */
1803  if ( !bUnicodeWindow &&
1804  ( Class->atomClassName == gpsi->atomSysClass[ICLS_BUTTON] ||
1805  Class->atomClassName == gpsi->atomSysClass[ICLS_COMBOBOX] ||
1806  Class->atomClassName == gpsi->atomSysClass[ICLS_COMBOLBOX] ||
1807  Class->atomClassName == gpsi->atomSysClass[ICLS_DIALOG] ||
1808  Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT] ||
1809  Class->atomClassName == gpsi->atomSysClass[ICLS_IME] ||
1810  Class->atomClassName == gpsi->atomSysClass[ICLS_LISTBOX] ||
1811  Class->atomClassName == gpsi->atomSysClass[ICLS_MDICLIENT] ||
1812  Class->atomClassName == gpsi->atomSysClass[ICLS_STATIC] ) )
1813  { // Override Class and set the window Ansi WndProc.
1814  pWnd->state |= WNDS_ANSIWINDOWPROC;
1815  pWnd->Unicode = FALSE;
1816  }
1817  else
1818  { // Set the window Unicode WndProc.
1819  pWnd->state &= ~WNDS_ANSIWINDOWPROC;
1820  pWnd->Unicode = TRUE;
1821  }
1822  }
1823 
1824  /* BugBoy Comments: if the window being created is a edit control, ATOM 0xCxxx,
1825  then my testing shows that windows (2k and XP) creates a CallProc for it immediately
1826  Dont understand why it does this. */
1827  if (Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT])
1828  {
1829  PCALLPROCDATA CallProc;
1830  CallProc = CreateCallProc(pWnd->head.rpdesk, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
1831 
1832  if (!CallProc)
1833  {
1835  ERR("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %p\n", hWnd);
1836  }
1837  else
1838  {
1839  UserAddCallProcToClass(pWnd->pcls, CallProc);
1840  }
1841  }
1842 
1844  pWnd->PropListItems = 0;
1845 
1846  if ( WindowName->Buffer != NULL && WindowName->Length > 0 )
1847  {
1848  pWnd->strName.Buffer = DesktopHeapAlloc(pWnd->head.rpdesk,
1849  WindowName->Length + sizeof(UNICODE_NULL));
1850  if (pWnd->strName.Buffer == NULL)
1851  {
1852  goto AllocError;
1853  }
1854 
1855  RtlCopyMemory(pWnd->strName.Buffer, WindowName->Buffer, WindowName->Length);
1856  pWnd->strName.Buffer[WindowName->Length / sizeof(WCHAR)] = L'\0';
1857  pWnd->strName.Length = WindowName->Length;
1858  pWnd->strName.MaximumLength = WindowName->Length + sizeof(UNICODE_NULL);
1859  }
1860 
1861  /* Correct the window style. */
1862  if ((pWnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1863  {
1864  pWnd->style |= WS_CLIPSIBLINGS;
1865  if (!(pWnd->style & WS_POPUP))
1866  {
1867  pWnd->style |= WS_CAPTION;
1868  }
1869  }
1870 
1871  /* WS_EX_WINDOWEDGE depends on some other styles */
1872  if (pWnd->ExStyle & WS_EX_DLGMODALFRAME)
1873  pWnd->ExStyle |= WS_EX_WINDOWEDGE;
1874  else if (pWnd->style & (WS_DLGFRAME | WS_THICKFRAME))
1875  {
1876  if (!((pWnd->ExStyle & WS_EX_STATICEDGE) &&
1877  (pWnd->style & (WS_CHILD | WS_POPUP))))
1878  pWnd->ExStyle |= WS_EX_WINDOWEDGE;
1879  }
1880  else
1881  pWnd->ExStyle &= ~WS_EX_WINDOWEDGE;
1882 
1883  if (!(pWnd->style & (WS_CHILD | WS_POPUP)))
1884  pWnd->state |= WNDS_SENDSIZEMOVEMSGS;
1885 
1886  /* Set the window menu */
1887  if ((Cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1888  {
1889  if (Cs->hMenu)
1890  {
1891  IntSetMenu(pWnd, Cs->hMenu, &MenuChanged);
1892  }
1893  else if (pWnd->pcls->lpszMenuName) // Take it from the parent.
1894  {
1895  UNICODE_STRING MenuName;
1896  HMENU hMenu;
1897 
1898  if (IS_INTRESOURCE(pWnd->pcls->lpszMenuName))
1899  {
1900  MenuName.Length = 0;
1901  MenuName.MaximumLength = 0;
1902  MenuName.Buffer = pWnd->pcls->lpszMenuName;
1903  }
1904  else
1905  {
1906  RtlInitUnicodeString( &MenuName, pWnd->pcls->lpszMenuName);
1907  }
1908  hMenu = co_IntCallLoadMenu( pWnd->pcls->hModule, &MenuName);
1909  if (hMenu) IntSetMenu(pWnd, hMenu, &MenuChanged);
1910  }
1911  }
1912  else // Not a child
1913  pWnd->IDMenu = (UINT_PTR)Cs->hMenu;
1914 
1915 
1916  if ( ParentWindow &&
1917  ParentWindow != ParentWindow->head.rpdesk->spwndMessage &&
1918  ParentWindow != ParentWindow->head.rpdesk->pDeskInfo->spwnd )
1919  {
1920  PWND Owner = IntGetNonChildAncestor(ParentWindow);
1921 
1922  if (!IntValidateOwnerDepth(pWnd, Owner))
1923  {
1925  goto Error;
1926  }
1927  if ( pWnd->spwndOwner &&
1928  pWnd->spwndOwner->ExStyle & WS_EX_TOPMOST )
1929  {
1930  pWnd->ExStyle |= WS_EX_TOPMOST;
1931  }
1932  if ( pWnd->spwndOwner &&
1933  Class->atomClassName != gpsi->atomSysClass[ICLS_IME] &&
1934  pti != pWnd->spwndOwner->head.pti)
1935  {
1936  //ERR("CreateWindow Owner in.\n");
1937  UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE);
1938  }
1939  }
1940 
1941  /* Insert the window into the thread's window list. */
1943 
1944  /* Handle "CS_CLASSDC", it is tested first. */
1945  if ( (pWnd->pcls->style & CS_CLASSDC) && !(pWnd->pcls->pdce) )
1946  { /* One DCE per class to have CLASS. */
1947  pWnd->pcls->pdce = DceAllocDCE( pWnd, DCE_CLASS_DC );
1948  }
1949  else if ( pWnd->pcls->style & CS_OWNDC)
1950  { /* Allocate a DCE for this window. */
1951  DceAllocDCE(pWnd, DCE_WINDOW_DC);
1952  }
1953 
1954  return pWnd;
1955 
1956 AllocError:
1957  ERR("IntCreateWindow Allocation Error.\n");
1959 Error:
1960  if(pWnd)
1961  UserDereferenceObject(pWnd);
1962  return NULL;
1963 }
1964 
1965 /*
1966  * @implemented
1967  */
1968 PWND FASTCALL
1970  PUNICODE_STRING ClassName,
1971  PLARGE_STRING WindowName,
1972  PVOID acbiBuffer,
1973  DWORD dwVer )
1974 {
1975  ULONG style;
1976  PWND Window = NULL, ParentWindow = NULL, OwnerWindow;
1977  HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter;
1978  PWINSTATION_OBJECT WinSta;
1979  PCLS Class = NULL;
1980  SIZE Size;
1981  POINT MaxSize, MaxPos, MinTrack, MaxTrack;
1982  CBT_CREATEWNDW * pCbtCreate;
1983  LRESULT Result;
1984  USER_REFERENCE_ENTRY ParentRef, Ref;
1985  PTHREADINFO pti;
1986  DWORD dwShowMode = SW_SHOW;
1987  CREATESTRUCTW *pCsw = NULL;
1988  PVOID pszClass = NULL, pszName = NULL;
1989  PWND ret = NULL;
1990 
1991  /* Get the current window station and reference it */
1992  pti = GetW32ThreadInfo();
1993  if (pti == NULL || pti->rpdesk == NULL)
1994  {
1995  ERR("Thread is not attached to a desktop! Cannot create window!\n");
1996  return NULL; // There is nothing to cleanup.
1997  }
1998  WinSta = pti->rpdesk->rpwinstaParent;
2000 
2001  pCsw = NULL;
2002  pCbtCreate = NULL;
2003 
2004  /* Get the class and reference it */
2005  Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
2006  if(!Class)
2007  {
2009  ERR("Failed to find class %wZ\n", ClassName);
2010  goto cleanup;
2011  }
2012 
2013  /* Now find the parent and the owner window */
2014  hWndParent = pti->rpdesk->pDeskInfo->spwnd->head.h;
2015  hWndOwner = NULL;
2016 
2017  if (Cs->hwndParent == HWND_MESSAGE)
2018  {
2019  Cs->hwndParent = hWndParent = pti->rpdesk->spwndMessage->head.h;
2020  }
2021  else if (Cs->hwndParent)
2022  {
2023  if ((Cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
2024  hWndOwner = Cs->hwndParent;
2025  else
2026  hWndParent = Cs->hwndParent;
2027  }
2028  else if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2029  {
2030  ERR("Cannot create a child window without a parent!\n");
2032  goto cleanup; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
2033  }
2035  (IS_INTRESOURCE(Cs->lpszClass) ||
2036  Cs->lpszClass != (LPCWSTR)MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]) ||
2037  _wcsicmp(Cs->lpszClass, L"Message") != 0))
2038  {
2039  if (pti->ppi->dwLayout & LAYOUT_RTL)
2040  {
2041  Cs->dwExStyle |= WS_EX_LAYOUTRTL;
2042  }
2043  }
2044 
2045  ParentWindow = hWndParent ? UserGetWindowObject(hWndParent): NULL;
2046  OwnerWindow = hWndOwner ? UserGetWindowObject(hWndOwner): NULL;
2047 
2048  if (hWndParent && !ParentWindow)
2049  {
2050  ERR("Got invalid parent window handle\n");
2051  goto cleanup;
2052  }
2053  else if (hWndOwner && !OwnerWindow)
2054  {
2055  ERR("Got invalid owner window handle\n");
2056  ParentWindow = NULL;
2057  goto cleanup;
2058  }
2059 
2060  if(OwnerWindow)
2061  {
2062  if (IntIsDesktopWindow(OwnerWindow)) OwnerWindow = NULL;
2063  else if (ParentWindow && !IntIsDesktopWindow(ParentWindow))
2064  {
2065  ERR("an owned window must be created as top-level\n");
2067  goto cleanup;
2068  }
2069  else /* owner must be a top-level window */
2070  {
2071  while ((OwnerWindow->style & (WS_POPUP|WS_CHILD)) == WS_CHILD && !IntIsDesktopWindow(OwnerWindow->spwndParent))
2072  OwnerWindow = OwnerWindow->spwndParent;
2073  }
2074  }
2075 
2076  /* Fix the position and the size of the window */
2077  if (ParentWindow)
2078  {
2079  UserRefObjectCo(ParentWindow, &ParentRef);
2080  IntFixWindowCoordinates(Cs, ParentWindow, &dwShowMode);
2081  }
2082 
2083  /* Allocate and initialize the new window */
2084  Window = IntCreateWindow(Cs,
2085  WindowName,
2086  Class,
2087  ParentWindow,
2088  OwnerWindow,
2089  acbiBuffer,
2090  NULL,
2091  dwVer );
2092  if(!Window)
2093  {
2094  ERR("IntCreateWindow failed!\n");
2095  goto cleanup;
2096  }
2097 
2099  hwndInsertAfter = HWND_TOP;
2100 
2101  UserRefObjectCo(Window, &Ref);
2103  ObDereferenceObject(WinSta);
2104 
2106  if ( ISITHOOKED(WH_CBT) || (pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)) )
2107  {
2108  // Allocate the calling structures Justin Case this goes Global.
2111  if (!pCsw || !pCbtCreate)
2112  {
2113  ERR("UserHeapAlloc() failed!\n");
2114  goto cleanup;
2115  }
2116 
2117  /* Fill the new CREATESTRUCTW */
2118  RtlCopyMemory(pCsw, Cs, sizeof(CREATESTRUCTW));
2119  pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */
2120 
2121  // Based on the assumption this is from "unicode source" user32, ReactOS, answer is yes.
2122  if (!IS_ATOM(ClassName->Buffer))
2123  {
2124  if (Window->state & WNDS_ANSICREATOR)
2125  {
2127  AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(ClassName)+sizeof(CHAR);
2128  pszClass = UserHeapAlloc(AnsiString.MaximumLength);
2129  if (!pszClass)
2130  {
2131  ERR("UserHeapAlloc() failed!\n");
2132  goto cleanup;
2133  }
2134  RtlZeroMemory(pszClass, AnsiString.MaximumLength);
2135  AnsiString.Buffer = (PCHAR)pszClass;
2137  }
2138  else
2139  {
2141  UnicodeString.MaximumLength = ClassName->Length + sizeof(UNICODE_NULL);
2142  pszClass = UserHeapAlloc(UnicodeString.MaximumLength);
2143  if (!pszClass)
2144  {
2145  ERR("UserHeapAlloc() failed!\n");
2146  goto cleanup;
2147  }
2148  RtlZeroMemory(pszClass, UnicodeString.MaximumLength);
2149  UnicodeString.Buffer = (PWSTR)pszClass;
2150  RtlCopyUnicodeString(&UnicodeString, ClassName);
2151  }
2152  pCsw->lpszClass = UserHeapAddressToUser(pszClass);
2153  }
2154  if (WindowName->Length)
2155  {
2157  Name.Buffer = WindowName->Buffer;
2158  Name.Length = (USHORT)min(WindowName->Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2159  Name.MaximumLength = (USHORT)min(WindowName->MaximumLength, MAXUSHORT);
2160 
2161  if (Window->state & WNDS_ANSICREATOR)
2162  {
2164  AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&Name) + sizeof(CHAR);
2165  pszName = UserHeapAlloc(AnsiString.MaximumLength);
2166  if (!pszName)
2167  {
2168  ERR("UserHeapAlloc() failed!\n");
2169  goto cleanup;
2170  }
2171  RtlZeroMemory(pszName, AnsiString.MaximumLength);
2172  AnsiString.Buffer = (PCHAR)pszName;
2174  }
2175  else
2176  {
2178  UnicodeString.MaximumLength = Name.Length + sizeof(UNICODE_NULL);
2179  pszName = UserHeapAlloc(UnicodeString.MaximumLength);
2180  if (!pszName)
2181  {
2182  ERR("UserHeapAlloc() failed!\n");
2183  goto cleanup;
2184  }
2185  RtlZeroMemory(pszName, UnicodeString.MaximumLength);
2186  UnicodeString.Buffer = (PWSTR)pszName;
2188  }
2189  pCsw->lpszName = UserHeapAddressToUser(pszName);
2190  }
2191 
2192  pCbtCreate->lpcs = pCsw;
2193  pCbtCreate->hwndInsertAfter = hwndInsertAfter;
2194 
2197  if (Result != 0)
2198  {
2199  ERR("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
2200  goto cleanup;
2201  }
2202  // Write back changes.
2203  Cs->cx = pCsw->cx;
2204  Cs->cy = pCsw->cy;
2205  Cs->x = pCsw->x;
2206  Cs->y = pCsw->y;
2207  hwndInsertAfter = pCbtCreate->hwndInsertAfter;
2208  }
2209 
2210  /* NCCREATE and WM_NCCALCSIZE need the original values */
2211  Cs->lpszName = (LPCWSTR) WindowName;
2212  Cs->lpszClass = (LPCWSTR) ClassName;
2213 
2214  if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2215  {
2216  if (ParentWindow != co_GetDesktopWindow(Window))
2217  {
2218  Cs->x += ParentWindow->rcClient.left;
2219  Cs->y += ParentWindow->rcClient.top;
2220  }
2221  }
2222 
2223  /* Send the WM_GETMINMAXINFO message */
2224  Size.cx = Cs->cx;
2225  Size.cy = Cs->cy;
2226 
2227  if ((Cs->style & WS_THICKFRAME) || !(Cs->style & (WS_POPUP | WS_CHILD)))
2228  {
2229  co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack, &MaxTrack);
2230  if (Size.cx > MaxTrack.x) Size.cx = MaxTrack.x;
2231  if (Size.cy > MaxTrack.y) Size.cy = MaxTrack.y;
2232  if (Size.cx < MinTrack.x) Size.cx = MinTrack.x;
2233  if (Size.cy < MinTrack.y) Size.cy = MinTrack.y;
2234  }
2235 
2236  Window->rcWindow.left = Cs->x;
2237  Window->rcWindow.top = Cs->y;
2238  Window->rcWindow.right = Cs->x + Size.cx;
2239  Window->rcWindow.bottom = Cs->y + Size.cy;
2240  /*
2241  if (0 != (Window->style & WS_CHILD) && ParentWindow)
2242  {
2243  ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
2244  RECTL_vOffsetRect(&Window->rcWindow,
2245  ParentWindow->rcClient.left,
2246  ParentWindow->rcClient.top);
2247  }
2248  */
2249  /* correct child window coordinates if mirroring on parent is enabled */
2250  if (ParentWindow != NULL)
2251  {
2252  if ( ((Cs->style & WS_CHILD) == WS_CHILD) &&
2253  ((ParentWindow->ExStyle & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL))
2254  {
2255  Window->rcWindow.right = ParentWindow->rcClient.right - (Window->rcWindow.left - ParentWindow->rcClient.left);
2256  Window->rcWindow.left = Window->rcWindow.right - Size.cx;
2257  }
2258  }
2259 
2260  Window->rcClient = Window->rcWindow;
2261 
2262  /* Link the window */
2263  if (NULL != ParentWindow)
2264  {
2265  /* Link the window into the siblings list */
2266  if ((Cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
2268  else
2269  IntLinkHwnd(Window, hwndInsertAfter);
2270  }
2271 
2272  if (!(Window->state2 & WNDS2_WIN31COMPAT))
2273  {
2274  if (Class->style & CS_PARENTDC && !(ParentWindow->style & WS_CLIPCHILDREN))
2275  Window->style &= ~(WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
2276  }
2277 
2278  if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2279  {
2280  if ( !IntIsTopLevelWindow(Window) )
2281  {
2282  if (pti != Window->spwndParent->head.pti)
2283  {
2284  //ERR("CreateWindow Parent in.\n");
2285  UserAttachThreadInput(pti, Window->spwndParent->head.pti, TRUE);
2286  }
2287  }
2288  }
2289 
2290  /* Send the NCCREATE message */
2292  if (!Result)
2293  {
2294  ERR("co_UserCreateWindowEx(): NCCREATE message failed\n");
2295  goto cleanup;
2296  }
2297 
2298  /* Send the WM_NCCALCSIZE message */
2299  {
2300  // RECT rc;
2301  MaxPos.x = Window->rcWindow.left;
2302  MaxPos.y = Window->rcWindow.top;
2303 
2304  Result = co_WinPosGetNonClientSize(Window, &Window->rcWindow, &Window->rcClient);
2305  //rc = Window->rcWindow;
2306  //Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM)&rc);
2307  //Window->rcClient = rc;
2308 
2309  RECTL_vOffsetRect(&Window->rcWindow, MaxPos.x - Window->rcWindow.left,
2310  MaxPos.y - Window->rcWindow.top);
2311  }
2312 
2313  /* Send the WM_CREATE message. */
2315  if (Result == (LRESULT)-1)
2316  {
2317  ERR("co_UserCreateWindowEx(): WM_CREATE message failed\n");
2318  goto cleanup;
2319  }
2320 
2321  /* Send the EVENT_OBJECT_CREATE event */
2322  IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2323 
2324  /* By setting the flag below it can be examined to determine if the window
2325  was created successfully and a valid pwnd was passed back to caller since
2326  from here the function has to succeed. */
2328 
2329  /* Send the WM_SIZE and WM_MOVE messages. */
2330  if (!(Window->state & WNDS_SENDSIZEMOVEMSGS))
2331  {
2333  }
2334 
2335  /* Show or maybe minimize or maximize the window. */
2336 
2338  if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2339  {
2340  RECTL NewPos;
2341  UINT SwFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
2342 
2343  SwFlag = co_WinPosMinMaximize(Window, SwFlag, &NewPos);
2344  SwFlag |= SWP_NOZORDER|SWP_FRAMECHANGED; /* Frame always gets changed */
2345  if (!(style & WS_VISIBLE) || (style & WS_CHILD) || UserGetActiveWindow()) SwFlag |= SWP_NOACTIVATE;
2346  co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top,
2347  NewPos.right, NewPos.bottom, SwFlag);
2348  }
2349 
2350  /* Send the WM_PARENTNOTIFY message */
2352 
2353  /* Notify the shell that a new window was created */
2354  if (UserIsDesktopWindow(Window->spwndParent) &&
2355  Window->spwndOwner == NULL &&
2356  (Window->style & WS_VISIBLE) &&
2357  (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
2358  (Window->ExStyle & WS_EX_APPWINDOW)))
2359  {
2361  }
2362 
2363  /* Initialize and show the window's scrollbars */
2364  if (Window->style & WS_VSCROLL)
2365  {
2367  }
2368  if (Window->style & WS_HSCROLL)
2369  {
2371  }
2372 
2373  /* Show the new window */
2374  if (Cs->style & WS_VISIBLE)
2375  {
2376  if (Window->style & WS_MAXIMIZE)
2377  dwShowMode = SW_SHOW;
2378  else if (Window->style & WS_MINIMIZE)
2379  dwShowMode = SW_SHOWMINIMIZED;
2380 
2381  co_WinPosShowWindow(Window, dwShowMode);
2382 
2383  if (Window->ExStyle & WS_EX_MDICHILD)
2384  {
2385  ASSERT(ParentWindow);
2386  if(!ParentWindow)
2387  goto cleanup;
2388  co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
2389  /* ShowWindow won't activate child windows */
2391  }
2392  }
2393 
2394  if (Class->atomClassName == gaGuiConsoleWndClass)
2395  {
2396  /* Count only console windows manually */
2398  }
2399 
2400  TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
2401  ret = Window;
2402 
2403 cleanup:
2404  if (!ret)
2405  {
2406  TRACE("co_UserCreateWindowEx(): Error Created window!\n");
2407  /* If the window was created, the class will be dereferenced by co_UserDestroyWindow */
2408  if (Window)
2410  else if (Class)
2411  IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
2412  }
2413 
2414  if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
2415  if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
2416  if (pszName) UserHeapFree(pszName);
2417  if (pszClass) UserHeapFree(pszClass);
2418 
2419  if (Window)
2420  {
2422  }
2423  if (ParentWindow) UserDerefObjectCo(ParentWindow);
2424 
2425  // See CORE-13717, not setting error on success.
2426  if (ret)
2428 
2429  return ret;
2430 }
2431 
2432 NTSTATUS
2433 NTAPI
2435  OUT PLARGE_STRING plstrSafe,
2436  IN PLARGE_STRING plstrUnsafe)
2437 {
2438  LARGE_STRING lstrTemp;
2439  PVOID pvBuffer = NULL;
2440 
2441  _SEH2_TRY
2442  {
2443  /* Probe and copy the string */
2444  ProbeForRead(plstrUnsafe, sizeof(LARGE_STRING), sizeof(ULONG));
2445  lstrTemp = *plstrUnsafe;
2446  }
2448  {
2449  /* Fail */
2451  }
2452  _SEH2_END
2453 
2454  if (lstrTemp.Length != 0)
2455  {
2456  /* Allocate a buffer from paged pool */
2457  pvBuffer = ExAllocatePoolWithTag(PagedPool, lstrTemp.Length, TAG_STRING);
2458  if (!pvBuffer)
2459  {
2460  return STATUS_NO_MEMORY;
2461  }
2462 
2463  _SEH2_TRY
2464  {
2465  /* Probe and copy the buffer */
2466  ProbeForRead(lstrTemp.Buffer, lstrTemp.Length, sizeof(WCHAR));
2467  RtlCopyMemory(pvBuffer, lstrTemp.Buffer, lstrTemp.Length);
2468  }
2470  {
2471  /* Cleanup and fail */
2472  ExFreePoolWithTag(pvBuffer, TAG_STRING);
2474  }
2475  _SEH2_END
2476  }
2477 
2478  /* Set the output string */
2479  plstrSafe->Buffer = pvBuffer;
2480  plstrSafe->Length = lstrTemp.Length;
2481  plstrSafe->MaximumLength = lstrTemp.Length;
2482 
2483  return STATUS_SUCCESS;
2484 }
2485 
2489 HWND
2490 NTAPI
2492  DWORD dwExStyle,
2493  PLARGE_STRING plstrClassName,
2494  PLARGE_STRING plstrClsVersion,
2495  PLARGE_STRING plstrWindowName,
2496  DWORD dwStyle,
2497  int x,
2498  int y,
2499  int nWidth,
2500  int nHeight,
2501  HWND hWndParent,
2502  HMENU hMenu,
2504  LPVOID lpParam,
2505  DWORD dwFlags,
2506  PVOID acbiBuffer)
2507 {
2508  NTSTATUS Status;
2509  LARGE_STRING lstrWindowName;
2510  LARGE_STRING lstrClassName;
2511  LARGE_STRING lstrClsVersion;
2512  UNICODE_STRING ustrClassName;
2513  UNICODE_STRING ustrClsVersion;
2514  CREATESTRUCTW Cs;
2515  HWND hwnd = NULL;
2516  PWND pwnd;
2517 
2518  lstrWindowName.Buffer = NULL;
2519  lstrClassName.Buffer = NULL;
2520  lstrClsVersion.Buffer = NULL;
2521 
2522  ASSERT(plstrWindowName);
2523 
2524  if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2525  {
2526  /* check hMenu is valid handle */
2527  if (hMenu && !UserGetMenuObject(hMenu))
2528  {
2529  ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
2531  return NULL;
2532  }
2533  }
2534 
2535  /* Copy the window name to kernel mode */
2536  Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
2537  if (!NT_SUCCESS(Status))
2538  {
2539  ERR("NtUserCreateWindowEx: failed to capture plstrWindowName\n");
2541  return NULL;
2542  }
2543 
2544  plstrWindowName = &lstrWindowName;
2545 
2546  /* Check if the class is an atom */
2547  if (IS_ATOM(plstrClassName))
2548  {
2549  /* It is, pass the atom in the UNICODE_STRING */
2550  ustrClassName.Buffer = (PVOID)plstrClassName;
2551  ustrClassName.Length = 0;
2552  ustrClassName.MaximumLength = 0;
2553  }
2554  else
2555  {
2556  /* It's not, capture the class name */
2557  Status = ProbeAndCaptureLargeString(&lstrClassName, plstrClassName);
2558  if (!NT_SUCCESS(Status))
2559  {
2560  ERR("NtUserCreateWindowEx: failed to capture plstrClassName\n");
2561  /* Set last error, cleanup and return */
2563  goto cleanup;
2564  }
2565 
2566  /* We pass it on as a UNICODE_STRING */
2567  ustrClassName.Buffer = lstrClassName.Buffer;
2568  ustrClassName.Length = (USHORT)min(lstrClassName.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2569  ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
2570  }
2571 
2572  /* Check if the class version is an atom */
2573  if (IS_ATOM(plstrClsVersion))
2574  {
2575  /* It is, pass the atom in the UNICODE_STRING */
2576  ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
2577  ustrClsVersion.Length = 0;
2578  ustrClsVersion.MaximumLength = 0;
2579  }
2580  else
2581  {
2582  /* It's not, capture the class name */
2583  Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
2584  if (!NT_SUCCESS(Status))
2585  {
2586  ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
2587  /* Set last error, cleanup and return */
2589  goto cleanup;
2590  }
2591 
2592  /* We pass it on as a UNICODE_STRING */
2593  ustrClsVersion.Buffer = lstrClsVersion.Buffer;
2594  ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2595  ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
2596  }
2597 
2598  /* Fill the CREATESTRUCTW */
2599  /* we will keep here the original parameters */
2600  Cs.style = dwStyle;
2601  Cs.lpCreateParams = lpParam;
2602  Cs.hInstance = hInstance;
2603  Cs.hMenu = hMenu;
2604  Cs.hwndParent = hWndParent;
2605  Cs.cx = nWidth;
2606  Cs.cy = nHeight;
2607  Cs.x = x;
2608  Cs.y = y;
2609  Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer;
2610  Cs.lpszClass = ustrClassName.Buffer;
2611  Cs.dwExStyle = dwExStyle;
2612 
2614 
2615  /* Call the internal function */
2616  pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer, dwFlags);
2617 
2618  if(!pwnd)
2619  {
2620  ERR("co_UserCreateWindowEx failed!\n");
2621  }
2622  hwnd = pwnd ? UserHMGetHandle(pwnd) : NULL;
2623 
2624  UserLeave();
2625 
2626 cleanup:
2627  if (lstrWindowName.Buffer)
2628  {
2629  ExFreePoolWithTag(lstrWindowName.Buffer, TAG_STRING);
2630  }
2631  if (lstrClassName.Buffer)
2632  {
2633  ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
2634  }
2635  if (lstrClsVersion.Buffer)
2636  {
2637  ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
2638  }
2639 
2640  return hwnd;
2641 }
2642 
2643 
2645 {
2646  HWND hWnd;
2647  PWND pwndTemp;
2648  PTHREADINFO ti;
2649  MSG msg;
2650  PWND Window = Object;
2651 
2652  ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
2653 
2654  hWnd = Window->head.h;
2656 
2657  TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
2658 
2659  /* Check for owner thread */
2660  if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
2661  {
2662  /* Check if we are destroying the desktop window */
2663  if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
2664  {
2666  return FALSE;
2667  }
2668  }
2669 
2670  /* If window was created successfully and it is hooked */
2671  if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
2672  {
2674  {
2675  ERR("Destroy Window WH_CBT Call Hook return!\n");
2676  return FALSE;
2677  }
2678  }
2679 
2680  if (Window->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME])
2681  {
2682  if ((Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2683  {
2684  if (Window->spwndOwner)
2685  {
2686  //ERR("DestroyWindow Owner out.\n");
2687  UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE);
2688  }
2689  }
2690  }
2691 
2692  /* Inform the parent */
2693  if (Window->style & WS_CHILD)
2694  {
2696  }
2697 
2698  if (!Window->spwndOwner && !IntGetParent(Window))
2699  {
2701  }
2702 
2703  /* Hide the window */
2704  if (Window->style & WS_VISIBLE)
2705  {
2706  if (Window->style & WS_CHILD)
2707  {
2708  /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
2710  }
2711  else
2712  {
2714  }
2715  }
2716 
2717  /* Adjust last active */
2718  if ((pwndTemp = Window->spwndOwner))
2719  {
2720  while (pwndTemp->spwndOwner)
2721  pwndTemp = pwndTemp->spwndOwner;
2722 
2723  if (pwndTemp->spwndLastActive == Window)
2724  pwndTemp->spwndLastActive = Window->spwndOwner;
2725  }
2726 
2727  if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))
2728  {
2729  if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
2730  {
2732  {
2733  //ERR("DestroyWindow Parent out.\n");
2734  UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE);
2735  }
2736  }
2737  }
2738 
2739  if (Window->head.pti->MessageQueue->spwndActive == Window)
2740  Window->head.pti->MessageQueue->spwndActive = NULL;
2741  if (Window->head.pti->MessageQueue->spwndFocus == Window)
2742  Window->head.pti->MessageQueue->spwndFocus = NULL;
2743  if (Window->head.pti->MessageQueue->spwndActivePrev == Window)
2744  Window->head.pti->MessageQueue->spwndActivePrev = NULL;
2745  if (Window->head.pti->MessageQueue->spwndCapture == Window)
2746  Window->head.pti->MessageQueue->spwndCapture = NULL;
2747 
2748  /*
2749  * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL
2750  */
2751 
2752  if ((ti != NULL) && (ti->pDeskInfo != NULL))
2753  {
2754  if (ti->pDeskInfo->hShellWindow == hWnd)
2755  {
2756  ERR("Destroying the ShellWindow!\n");
2757  ti->pDeskInfo->hShellWindow = NULL;
2758  }
2759  }
2760 
2762 
2764  {
2765  return TRUE;
2766  }
2767 
2768  /* Recursively destroy owned windows */
2769  if (!(Window->style & WS_CHILD))
2770  {
2771  HWND* List;
2772  HWND* phWnd;
2773  PWND pWnd;
2774 
2776  if (List)
2777  {
2778  for (phWnd = List; *phWnd; ++phWnd)
2779  {
2780  pWnd = ValidateHwndNoErr(*phWnd);
2781  if (pWnd == NULL)
2782  continue;
2783  ASSERT(pWnd->spwndOwner == Window);
2784  ASSERT(pWnd != Window);
2785 
2786  pWnd->spwndOwner = NULL;
2788  {
2790  UserRefObjectCo(pWnd, &Ref); // Temp HACK?
2791  co_UserDestroyWindow(pWnd);
2792  UserDerefObjectCo(pWnd); // Temp HACK?
2793  }
2794  else
2795  {
2796  ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
2797  }
2798  }
2799 
2801  }
2802  }
2803 
2804  /* Generate mouse move message for the next window */
2805  msg.message = WM_MOUSEMOVE;
2806  msg.wParam = UserGetMouseButtonsState();
2807  msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2808  msg.pt = gpsi->ptCursor;
2810 
2811  IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2812 
2813  /* Send destroy messages */
2815 
2817  {
2818  return TRUE;
2819  }
2820 
2821  /* Destroy the window storage */
2823 
2824  return TRUE;
2825 }
2826 
2827 
2828 /*
2829  * @implemented
2830  */
2833 {
2834  PWND Window;
2836  BOOLEAN ret;
2838 
2839  TRACE("Enter NtUserDestroyWindow\n");
2841 
2842  if (!(Window = UserGetWindowObject(Wnd)))
2843  {
2844  RETURN(FALSE);
2845  }
2846 
2847  UserRefObjectCo(Window, &Ref); // FIXME: Dunno if win should be reffed during destroy...
2849  UserDerefObjectCo(Window); // FIXME: Dunno if win should be reffed during destroy...
2850 
2851  RETURN(ret);
2852 
2853 CLEANUP:
2854  TRACE("Leave NtUserDestroyWindow, ret=%u\n", _ret_);
2855  UserLeave();
2856  END_CLEANUP;
2857 }
2858 
2859 
2860 static HWND FASTCALL
2862  PWND ChildAfter,
2863  RTL_ATOM ClassAtom,
2864  PUNICODE_STRING WindowName)
2865 {
2866  BOOL CheckWindowName;
2867  HWND *List, *phWnd;
2868  HWND Ret = NULL;
2869  UNICODE_STRING CurrentWindowName;
2870 
2871  ASSERT(Parent);
2872 
2873  CheckWindowName = WindowName->Buffer != 0;
2874 
2875  if((List = IntWinListChildren(Parent)))
2876  {
2877  phWnd = List;
2878  if(ChildAfter)
2879  {
2880  /* skip handles before and including ChildAfter */
2881  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
2882  ;
2883  }
2884 
2885  /* search children */
2886  while(*phWnd)
2887  {
2888  PWND Child;
2889  if(!(Child = UserGetWindowObject(*(phWnd++))))
2890  {
2891  continue;
2892  }
2893 
2894  /* Do not send WM_GETTEXT messages in the kernel mode version!
2895  The user mode version however calls GetWindowText() which will
2896  send WM_GETTEXT messages to windows belonging to its processes */
2897  if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
2898  {
2899  // FIXME: LARGE_STRING truncated
2900  CurrentWindowName.Buffer = Child->strName.Buffer;
2901  CurrentWindowName.Length = (USHORT)min(Child->strName.Length, MAXUSHORT);
2902  CurrentWindowName.MaximumLength = (USHORT)min(Child->strName.MaximumLength, MAXUSHORT);
2903  if(!CheckWindowName ||
2904  (Child->strName.Length < 0xFFFF &&
2905  !RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
2906  {
2907  Ret = Child->head.h;
2908  break;
2909  }
2910  }
2911  }
2913  }
2914 
2915  return Ret;
2916 }
2917 
2918 /*
2919  * FUNCTION:
2920  * Searches a window's children for a window with the specified
2921  * class and name
2922  * ARGUMENTS:
2923  * hwndParent = The window whose childs are to be searched.
2924  * NULL = desktop
2925  * HWND_MESSAGE = message-only windows
2926  *
2927  * hwndChildAfter = Search starts after this child window.
2928  * NULL = start from beginning
2929  *
2930  * ucClassName = Class name to search for
2931  * Reguired parameter.
2932  *
2933  * ucWindowName = Window name
2934  * ->Buffer == NULL = don't care
2935  *
2936  * RETURNS:
2937  * The HWND of the window if it was found, otherwise NULL
2938  */
2939 /*
2940  * @implemented
2941  */
2942 HWND APIENTRY
2944  HWND hwndChildAfter,
2945  PUNICODE_STRING ucClassName,
2946  PUNICODE_STRING ucWindowName,
2947  DWORD dwUnknown)
2948 {
2949  PWND Parent, ChildAfter;
2950  UNICODE_STRING ClassName = {0}, WindowName = {0};
2951  HWND Desktop, Ret = NULL;
2952  BOOL DoMessageWnd = FALSE;
2953  RTL_ATOM ClassAtom = (RTL_ATOM)0;
2955 
2956  TRACE("Enter NtUserFindWindowEx\n");
2957  UserEnterShared();
2958 
2959  if (ucClassName != NULL || ucWindowName != NULL)
2960  {
2961  _SEH2_TRY
2962  {
2963  if (ucClassName != NULL)
2964  {
2965  ClassName = ProbeForReadUnicodeString(ucClassName);
2966  if (ClassName.Length != 0)
2967  {
2968  ProbeForRead(ClassName.Buffer,
2969  ClassName.Length,
2970  sizeof(WCHAR));
2971  }
2972  else if (!IS_ATOM(ClassName.Buffer))
2973  {
2975  _SEH2_LEAVE;
2976  }
2977 
2978  if (!IntGetAtomFromStringOrAtom(&ClassName,
2979  &ClassAtom))
2980  {
2982  _SEH2_LEAVE;
2983  }
2984  }
2985 
2986  if (ucWindowName != NULL)
2987  {
2988  WindowName = ProbeForReadUnicodeString(ucWindowName);
2989  if (WindowName.Length != 0)
2990  {
2991  ProbeForRead(WindowName.Buffer,
2992  WindowName.Length,
2993  sizeof(WCHAR));
2994  }
2995  }
2996  }
2998  {
3001  }
3002  _SEH2_END;
3003 
3004  if (ucClassName != NULL)
3005  {
3006  if (ClassName.Length == 0 && ClassName.Buffer != NULL &&
3007  !IS_ATOM(ClassName.Buffer))
3008  {
3010  RETURN(NULL);
3011  }
3012  else if (ClassAtom == (RTL_ATOM)0)
3013  {
3014  /* LastError code was set by IntGetAtomFromStringOrAtom */
3015  RETURN(NULL);
3016  }
3017  }
3018  }
3019 
3021 
3022  if(hwndParent == NULL)
3023  {
3024  hwndParent = Desktop;
3025  DoMessageWnd = TRUE;
3026  }
3027  else if(hwndParent == HWND_MESSAGE)
3028  {
3030  }
3031 
3033  {
3034  RETURN( NULL);
3035  }
3036 
3037  ChildAfter = NULL;
3038  if(hwndChildAfter && !(ChildAfter = UserGetWindowObject(hwndChildAfter)))
3039  {
3040  RETURN( NULL);
3041  }
3042 
3043  _SEH2_TRY
3044  {
3045  if(Parent->head.h == Desktop)
3046  {
3047  HWND *List, *phWnd;
3048  PWND TopLevelWindow;
3049  BOOLEAN CheckWindowName;
3050  BOOLEAN WindowMatches;
3051  BOOLEAN ClassMatches;
3052 
3053  /* windows searches through all top-level windows if the parent is the desktop
3054  window */
3055 
3056  if((List = IntWinListChildren(Parent)))
3057  {
3058  phWnd = List;
3059 
3060  if(ChildAfter)
3061  {
3062  /* skip handles before and including ChildAfter */
3063  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
3064  ;
3065  }
3066 
3067  CheckWindowName = WindowName.Buffer != 0;
3068 
3069  /* search children */
3070  while(*phWnd)
3071  {
3072  UNICODE_STRING ustr;
3073 
3074  if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
3075  {
3076  continue;
3077  }
3078 
3079  /* Do not send WM_GETTEXT messages in the kernel mode version!
3080  The user mode version however calls GetWindowText() which will
3081  send WM_GETTEXT messages to windows belonging to its processes */
3082  ustr.Buffer = TopLevelWindow->strName.Buffer;
3083  ustr.Length = (USHORT)min(TopLevelWindow->strName.Length, MAXUSHORT); // FIXME:LARGE_STRING truncated
3084  ustr.MaximumLength = (USHORT)min(TopLevelWindow->strName.MaximumLength, MAXUSHORT);
3085  WindowMatches = !CheckWindowName ||
3086  (TopLevelWindow->strName.Length < 0xFFFF &&
3087  !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
3088  ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
3089  ClassAtom == TopLevelWindow->pcls->atomNVClassName;
3090 
3091  if (WindowMatches && ClassMatches)
3092  {
3093  Ret = TopLevelWindow->head.h;
3094  break;
3095  }
3096 
3097  if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
3098  {
3099  /* window returns the handle of the top-level window, in case it found
3100  the child window */
3101  Ret = TopLevelWindow->head.h;
3102  break;
3103  }
3104 
3105  }
3107  }
3108  }
3109  else
3110  {
3111  TRACE("FindWindowEx: Not Desktop Parent!\n");
3112  Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
3113  }
3114 
3115  if (Ret == NULL && DoMessageWnd)
3116  {
3117  PWND MsgWindows;
3118 
3119  if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
3120  {
3121  Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
3122  }
3123  }
3124  }
3126  {
3128  Ret = NULL;
3129  }
3130  _SEH2_END;
3131 
3132  RETURN( Ret);
3133 
3134 CLEANUP:
3135  TRACE("Leave NtUserFindWindowEx, ret %p\n", _ret_);
3136  UserLeave();
3137  END_CLEANUP;
3138 }
3139 
3140 
3141 /*
3142  * @implemented
3143  */
3145 {
3146  PWND WndAncestor, Parent;
3147 
3148  if (Wnd->head.h == IntGetDesktopWindow())
3149  {
3150  return NULL;
3151  }
3152 
3153  switch (Type)
3154  {
3155  case GA_PARENT:
3156  {
3157  WndAncestor = Wnd->spwndParent;
3158  break;
3159  }
3160 
3161  case GA_ROOT:
3162  {
3163  WndAncestor = Wnd;
3164  Parent = NULL;
3165 
3166  for(;;)
3167  {
3168  if(!(Parent = WndAncestor->spwndParent))
3169  {
3170  break;
3171  }
3173  {
3174  break;
3175  }
3176 
3177  WndAncestor = Parent;
3178  }
3179  break;
3180  }
3181 
3182  case GA_ROOTOWNER:
3183  {
3184  WndAncestor = Wnd;
3185 
3186  for (;;)
3187  {
3188  Parent = IntGetParent(WndAncestor);
3189 
3190  if (!Parent)
3191  {
3192  break;
3193  }
3194 
3195  WndAncestor = Parent;
3196  }
3197  break;
3198  }
3199 
3200  default:
3201  {
3202  return NULL;
3203  }
3204  }
3205 
3206  return WndAncestor;
3207 }
3208 
3209 /*
3210  * @implemented
3211  */
3212 HWND APIENTRY
3214 {
3215  PWND Window, Ancestor;
3217 
3218  TRACE("Enter NtUserGetAncestor\n");
3220 
3221  if (!(Window = UserGetWindowObject(hWnd)))
3222  {
3223  RETURN(NULL);
3224  }
3225 
3226  Ancestor = UserGetAncestor(Window, Type);
3227  /* faxme: can UserGetAncestor ever return NULL for a valid window? */
3228 
3229  RETURN(Ancestor ? Ancestor->head.h : NULL);
3230 
3231 CLEANUP:
3232  TRACE("Leave NtUserGetAncestor, ret=%p\n", _ret_);
3233  UserLeave();
3234  END_CLEANUP;
3235 }
3236 
3240 /* combo state struct */
3241 typedef struct
3242 {
3243  HWND self;
3244  HWND owner;
3245  UINT dwStyle;
3246  HWND hWndEdit;
3247  HWND hWndLBox;
3248  UINT wState;
3249  HFONT hFont;
3250  RECT textRect;
3251  RECT buttonRect;
3252  RECT droppedRect;
3253  INT droppedIndex;
3254  INT fixedOwnerDrawHeight;
3255  INT droppedWidth; /* last two are not used unless set */
3256  INT editHeight; /* explicitly */
3259 
3260 // Window Extra data container.
3261 typedef struct _WND2CBOX
3262 {
3265 } WND2CBOX, *PWND2CBOX;
3266 
3267 #define CBF_BUTTONDOWN 0x0002
3268 BOOL
3272 APIENTRY
3274  HWND hWnd,
3275  PCOMBOBOXINFO pcbi)
3276 {
3277  PWND Wnd;
3278  PPROCESSINFO ppi;
3279  BOOL NotSameppi = FALSE;
3280  BOOL Ret = TRUE;
3282 
3283  TRACE("Enter NtUserGetComboBoxInfo\n");
3284  UserEnterShared();
3285 
3286  if (!(Wnd = UserGetWindowObject(hWnd)))
3287  {
3288  RETURN( FALSE );
3289  }
3290  _SEH2_TRY
3291  {
3292  ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
3293  }
3295  {
3298  }
3299  _SEH2_END;
3300 
3301  if (pcbi->cbSize < sizeof(COMBOBOXINFO))
3302  {
3304  RETURN(FALSE);
3305  }
3306 
3307  // Pass the user pointer, it was already probed.
3308  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_COMBOBOX]) && Wnd->fnid != FNID_COMBOBOX)
3309  {
3310  RETURN( (BOOL) co_IntSendMessage( Wnd->head.h, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
3311  }
3312 
3314  NotSameppi = ppi != Wnd->head.pti->ppi;
3315  if (NotSameppi)
3316  {
3317  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3318  }
3319 
3320  _SEH2_TRY
3321  {
3322  LPHEADCOMBO lphc = ((PWND2CBOX)Wnd)->pCBox;
3323  pcbi->rcItem = lphc->textRect;
3324  pcbi->rcButton = lphc->buttonRect;
3325  pcbi->stateButton = 0;
3326  if (lphc->wState & CBF_BUTTONDOWN)
3328  if (RECTL_bIsEmptyRect(&lphc->buttonRect))
3330  pcbi->hwndCombo = lphc->self;
3331  pcbi->hwndItem = lphc->hWndEdit;
3332  pcbi->hwndList = lphc->hWndLBox;
3333  }
3335  {
3336  Ret = FALSE;
3338  }
3339  _SEH2_END;
3340 
3341  RETURN( Ret);
3342 
3343 CLEANUP:
3344  if (NotSameppi) KeDetachProcess();
3345  TRACE("Leave NtUserGetComboBoxInfo, ret=%i\n",_ret_);
3346  UserLeave();
3347  END_CLEANUP;
3348 }
3349 
3353 /* Listbox structure */
3354 typedef struct
3355 {
3356  HWND self; /* Our own window handle */
3357  HWND owner; /* Owner window to send notifications to */
3358  UINT style; /* Window style */
3359  INT width; /* Window width */
3360  INT height; /* Window height */
3361  VOID *items; /* Array of items */
3362  INT nb_items; /* Number of items */
3363  INT top_item; /* Top visible item */
3364  INT selected_item; /* Selected item */
3365  INT focus_item; /* Item that has the focus */
3366  INT anchor_item; /* Anchor item for extended selection */
3367  INT item_height; /* Default item height */
3368  INT page_size; /* Items per listbox page */
3369  INT column_width; /* Column width for multi-column listboxes */
3370 } LB_DESCR;
3371 
3372 // Window Extra data container.
3373 typedef struct _WND2LB
3374 {
3377 } WND2LB, *PWND2LB;
3381 DWORD
3382 APIENTRY
3384  HWND hWnd)
3385 {
3386  PWND Wnd;
3387  PPROCESSINFO ppi;
3388  BOOL NotSameppi = FALSE;
3389  DWORD Ret = 0;
3391 
3392  TRACE("Enter NtUserGetListBoxInfo\n");
3393  UserEnterShared();
3394 
3395  if (!(Wnd = UserGetWindowObject(hWnd)))
3396  {
3397  RETURN( 0 );
3398  }
3399 
3400  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_LISTBOX]) && Wnd->fnid != FNID_LISTBOX)
3401  {
3402  RETURN( (DWORD) co_IntSendMessage( Wnd->head.h, LB_GETLISTBOXINFO, 0, 0 ));
3403  }
3404 
3405  // wine lisbox:test_GetListBoxInfo lb_getlistboxinfo = 0, should not send a message!
3407  NotSameppi = ppi != Wnd->head.pti->ppi;
3408  if (NotSameppi)
3409  {
3410  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3411  }
3412 
3413  _SEH2_TRY
3414  {
3415  LB_DESCR *descr = ((PWND2LB)Wnd)->pLBiv;
3416  // See Controls ListBox.c:LB_GETLISTBOXINFO must match...
3417  if (descr->style & LBS_MULTICOLUMN)
3418  Ret = descr->page_size * descr->column_width;
3419  else
3420  Ret = descr->page_size;
3421  }
3423  {
3424  Ret = 0;
3426  }
3427  _SEH2_END;
3428 
3429  RETURN( Ret);
3430 
3431 CLEANUP:
3432  if (NotSameppi) KeDetachProcess();
3433  TRACE("Leave NtUserGetListBoxInfo, ret=%lu\n", _ret_);
3434  UserLeave();
3435  END_CLEANUP;
3436 }
3437 
3438 /*
3439  * NtUserSetParent
3440  *
3441  * The NtUserSetParent function changes the parent window of the specified
3442  * child window.
3443  *
3444  * Remarks
3445  * The new parent window and the child window must belong to the same
3446  * application. If the window identified by the hWndChild parameter is
3447  * visible, the system performs the appropriate redrawing and repainting.
3448  * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
3449  * or WS_POPUP window styles of the window whose parent is being changed.
3450  *
3451  * Status
3452  * @implemented
3453  */
3454 
3455 HWND APIENTRY
3457 {
3459 
3460  TRACE("Enter NtUserSetParent\n");
3462 
3463  /*
3464  Check Parent first from user space, set it here.
3465  */
3466  if (!hWndNewParent)
3467  {
3468  hWndNewParent = IntGetDesktopWindow();
3469  }
3470  else if (hWndNewParent == HWND_MESSAGE)
3471  {
3472  hWndNewParent = IntGetMessageWindow();
3473  }
3474 
3475  RETURN( co_UserSetParent(hWndChild, hWndNewParent));
3476 
3477 CLEANUP:
3478  TRACE("Leave NtUserSetParent, ret=%p\n", _ret_);
3479  UserLeave();
3480  END_CLEANUP;
3481 }
3482 
3483 /*
3484  * UserGetShellWindow
3485  *
3486  * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3487  *
3488  * Status
3489  * @implemented
3490  */
3492 {
3493  PWINSTATION_OBJECT WinStaObject;
3494  HWND Ret;
3495 
3497  UserMode,
3498  0,
3499  &WinStaObject,
3500  0);
3501 
3502  if (!NT_SUCCESS(Status))
3503  {
3505  return( (HWND)0);
3506  }
3507 
3508  Ret = (HWND)WinStaObject->ShellWindow;
3509 
3510  ObDereferenceObject(WinStaObject);
3511  return( Ret);
3512 }
3513 
3514 /*
3515  * NtUserSetShellWindowEx
3516  *
3517  * This is undocumented function to set global shell window. The global
3518  * shell window has special handling of window position.
3519  *
3520  * Status
3521  * @implemented
3522  */
3523 BOOL APIENTRY
3525 {
3526  PWINSTATION_OBJECT WinStaObject;
3527  PWND WndShell, WndListView;
3530  NTSTATUS Status;
3531  PTHREADINFO ti;
3532 
3533  TRACE("Enter NtUserSetShellWindowEx\n");
3535 
3536  if (!(WndShell = UserGetWindowObject(hwndShell)))
3537  {
3538  RETURN(FALSE);
3539  }
3540 
3541  if (!(WndListView = UserGetWindowObject(hwndListView)))
3542  {
3543  RETURN(FALSE);
3544  }
3545 
3547  UserMode,
3548  0,
3549  &WinStaObject,
3550  0);
3551 
3552  if (!NT_SUCCESS(Status))
3553  {
3555  RETURN( FALSE);
3556  }
3557 
3558  /*
3559  * Test if we are permitted to change the shell window.
3560  */
3561  if (WinStaObject->ShellWindow)
3562  {
3563  ObDereferenceObject(WinStaObject);
3564  RETURN( FALSE);
3565  }
3566 
3567  /*
3568  * Move shell window into background.
3569  */
3570  if (hwndListView && hwndListView != hwndShell)
3571  {
3572  /*
3573  * Disabled for now to get Explorer working.
3574  * -- Filip, 01/nov/2003
3575  */
3576 #if 0
3578 #endif
3579 
3580  if (WndListView->ExStyle & WS_EX_TOPMOST)
3581  {
3582  ObDereferenceObject(WinStaObject);
3583  RETURN( FALSE);
3584  }
3585  }
3586 
3587  if (WndShell->ExStyle & WS_EX_TOPMOST)
3588  {
3589  ObDereferenceObject(WinStaObject);
3590  RETURN( FALSE);
3591  }
3592 
3593  UserRefObjectCo(WndShell, &Ref);
3594  WndShell->state2 |= WNDS2_BOTTOMMOST;
3596 
3597  WinStaObject->ShellWindow = hwndShell;
3598  WinStaObject->ShellListView = hwndListView;
3599 
3600  ti = GetW32ThreadInfo();
3601  if (ti->pDeskInfo)
3602  {
3603  ti->pDeskInfo->hShellWindow = hwndShell;
3604  ti->pDeskInfo->spwndShell = WndShell;
3605  ti->pDeskInfo->spwndBkGnd = WndListView;
3606  ti->pDeskInfo->ppiShellProcess = ti->ppi;
3607  }
3608 
3610 
3611  UserDerefObjectCo(WndShell);
3612 
3613  ObDereferenceObject(WinStaObject);
3614  RETURN( TRUE);
3615 
3616 CLEANUP:
3617  TRACE("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
3618  UserLeave();
3619  END_CLEANUP;
3620 }
3621 
3622 // Fixes wine Win test_window_styles and todo tests...
3623 static BOOL FASTCALL
3625 {
3627  return TRUE;
3628  else if (!(ExStyle & WS_EX_STATICEDGE) && (Style & (WS_DLGFRAME | WS_THICKFRAME)))
3629  return TRUE;
3630  else
3631  return FALSE;
3632 }
3633 
3634 static LONG_PTR
3636 {
3637  PWND Window, Parent;
3638  PWINSTATION_OBJECT WindowStation;
3639  LONG_PTR OldValue;
3641 
3642  if (!(Window = UserGetWindowObject(hWnd)))
3643  {
3644  return( 0);
3645  }
3646 
3647  if ((INT)Index >= 0)
3648  {
3649  if ((Index + Size) > Window->cbwndExtra)
3650  {
3652  return( 0);
3653  }
3654 
3655 #ifdef _WIN64
3656  if (Size == sizeof(LONG))
3657  {
3658  OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
3659  *((LONG*)((PCHAR)(Window + 1) + Index)) = (LONG)NewValue;
3660  }
3661  else
3662 #endif
3663  {
3664  OldValue = *((LONG_PTR *)((PCHAR)(Window + 1) + Index));
3665  /*
3666  if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
3667  {
3668  OldValue = (LONG_PTR)IntSetWindowProc( Wnd, (WNDPROC)NewValue, Ansi);
3669  if (!OldValue) return 0;
3670  }
3671  */
3672  *((LONG_PTR*)((PCHAR)(Window + 1) + Index)) = NewValue;
3673  }
3674 
3675  }
3676  else
3677  {
3678 #ifdef _WIN64
3679  if (Size == sizeof(LONG))
3680  {
3681  if ((Index != GWL_STYLE) &&
3682  (Index != GWL_EXSTYLE) &&
3683  (Index != GWL_ID) &&
3684  (Index != GWL_USERDATA))
3685  {
3686  ERR("NtUserSetWindowLong(): Index requires pointer size: %lu\n", Index);
3688  return 0;
3689  }
3690  }
3691 #endif
3692 
3693  switch (Index)
3694  {
3695  case GWL_EXSTYLE: // LONG
3696  OldValue = (LONG) Window->ExStyle;
3697  Style.styleOld = OldValue;
3698  Style.styleNew = NewValue;
3699 
3700  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3701 
3702  /*
3703  * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3704  */
3705  WindowStation = Window->head.pti->rpdesk->rpwinstaParent;
3706  if(WindowStation)
3707  {
3708  if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3709  Style.styleNew &= ~WS_EX_TOPMOST;
3710  }
3711  /* WS_EX_WINDOWEDGE depends on some other styles */
3712  if (IntCheckFrameEdge(Window->style, NewValue))
3713  Style.styleNew |= WS_EX_WINDOWEDGE;
3714  else
3715  Style.styleNew &= ~WS_EX_WINDOWEDGE;
3716 
3717  if (!(Window->ExStyle & WS_EX_LAYERED))
3718  {
3720  }
3721 
3722  Window->ExStyle = (DWORD)Style.styleNew;
3723 
3724  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3725  break;
3726 
3727  case GWL_STYLE: // LONG
3728  OldValue = (LONG) Window->style;
3729  Style.styleOld = OldValue;
3730  Style.styleNew = NewValue;
3731 
3732  if (!bAlter)
3733  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3734 
3735  /* WS_CLIPSIBLINGS can't be reset on top-level windows */
3736  if (UserIsDesktopWindow(Window->spwndParent)) Style.styleNew |= WS_CLIPSIBLINGS;
3737  /* WS_MINIMIZE can't be reset */
3738  if (OldValue & WS_MINIMIZE) Style.styleNew |= WS_MINIMIZE;
3739  /* Fixes wine FIXME: changing WS_DLGFRAME | WS_THICKFRAME is supposed to change WS_EX_WINDOWEDGE too */
3740  if (IntCheckFrameEdge(NewValue, Window->ExStyle))
3741  Window->ExStyle |= WS_EX_WINDOWEDGE;
3742  else
3743  Window->ExStyle &= ~WS_EX_WINDOWEDGE;
3744 
3745  if ((OldValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3746  {
3747  if ((NewValue & (WS_CHILD | WS_POPUP)) != WS_CHILD)
3748  {
3750  ERR("IDMenu going null! %d\n",Window->IDMenu);
3751  Window->IDMenu = 0; // Window->spmenu = 0;
3752  }
3753  }
3754  else
3755  {
3756  if ((NewValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3757  {
3758  PMENU pMenu = UserGetMenuObject(UlongToHandle(Window->IDMenu));
3759  Window->state &= ~WNDS_HASMENU;
3760  if (pMenu)
3761  {
3762  ERR("IDMenu released 0x%p\n",pMenu);
3763  // ROS may not hold a lock after setting menu to window. But it should!
3764  //IntReleaseMenuObject(pMenu);
3765  }
3766  }
3767  }
3768 
3769  if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
3770  {
3771  if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
3772  if (Style.styleNew & WS_VISIBLE) Window->head.pti->cVisWindows++;
3774  }
3775  Window->style = (DWORD)Style.styleNew;
3776 
3777  if (!bAlter)
3778  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3779  break;
3780 
3781  case GWLP_WNDPROC: // LONG_PTR
3782  {
3783  if ( Window->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
3784  Window->fnid & FNID_FREED)
3785  {
3787  return( 0);
3788  }
3789  OldValue = (LONG_PTR)IntSetWindowProc(Window,
3790  (WNDPROC)NewValue,
3791  Ansi);
3792  break;
3793  }
3794 
3795  case GWLP_HINSTANCE: // LONG_PTR
3796  OldValue = (LONG_PTR) Window->hModule;
3797  Window->hModule = (HINSTANCE) NewValue;
3798  break;
3799 
3800  case GWLP_HWNDPARENT: // LONG_PTR
3801  Parent = Window->spwndParent;
3802  if (Parent && (Parent->head.h == IntGetDesktopWindow()))
3803  OldValue = (LONG_PTR) IntSetOwner(Window->head.h, (HWND) NewValue);
3804  else
3805  OldValue = (LONG_PTR) co_UserSetParent(Window->head.h, (HWND) NewValue);
3806  break;
3807 
3808  case GWLP_ID: // LONG
3809  OldValue = (LONG) Window->IDMenu;
3810  Window->IDMenu = (UINT) NewValue;
3811  break;
3812 
3813  case GWLP_USERDATA: // LONG or LONG_PTR
3814  OldValue = Window->dwUserData;
3815  Window->dwUserData = NewValue;
3816  break;
3817 
3818  default:
3819  ERR("NtUserSetWindowLong(): Unsupported index %lu\n", Index);
3821  OldValue = 0;
3822  break;
3823  }
3824  }
3825 
3826  return( OldValue);
3827 }
3828 
3829 LONG FASTCALL
3831 {
3832  return (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
3833 }
3834 
3837 {
3838  return co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
3839 }
3840 
3841 /*
3842  * NtUserSetWindowLong
3843  *
3844  * The NtUserSetWindowLong function changes an attribute of the specified
3845  * window. The function also sets the 32-bit (long) value at the specified
3846  * offset into the extra window memory.
3847  *
3848  * Status
3849  * @implemented
3850  */
3851 
3852 LONG APIENTRY
3854 {
3855  LONG ret;
3856 
3858 
3859  if (hWnd == IntGetDesktopWindow())
3860  {
3862  UserLeave();
3863  return 0;
3864  }
3865 
3866  ret = (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
3867 
3868  UserLeave();
3869 
3870  return ret;
3871 }
3872 
3873 #ifdef _WIN64
3875 NtUserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
3876 {
3877  LONG_PTR ret;
3878 
3880 
3881  if (hWnd == IntGetDesktopWindow())
3882  {
3884  UserLeave();
3885  return 0;
3886  }
3887 
3888  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
3889 
3890  UserLeave();
3891 
3892  return ret;
3893 }
3894 #endif // _WIN64
3895 
3898 {
3899  LONG ret;
3900 
3902 
3903  if (hWnd == IntGetDesktopWindow())
3904  {
3906  UserLeave();
3907  return 0;
3908  }
3909 
3910  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, FALSE, sizeof(LONG), TRUE);
3911 
3912  UserLeave();
3913 
3914  return ret;
3915 }
3916 
3917 
3918 /*
3919  * NtUserSetWindowWord
3920  *
3921  * Legacy function similar to NtUserSetWindowLong.
3922  *
3923  * Status
3924  * @implemented
3925  */
3926 
3927 WORD APIENTRY
3929 {
3930  PWND Window;
3931  WORD OldValue;
3933 
3934  TRACE("Enter NtUserSetWindowWord\n");
3936 
3937  if (hWnd == IntGetDesktopWindow())
3938  {
3940  RETURN( 0);
3941  }
3942 
3943  if (!(Window = UserGetWindowObject(hWnd)))
3944  {
3945  RETURN( 0);
3946  }
3947 
3948  switch (Index)
3949  {
3950  case GWL_ID:
3951  case GWL_HINSTANCE:
3952  case GWL_HWNDPARENT:
3954  default:
3955  if (Index < 0)
3956  {
3958  RETURN( 0);
3959  }
3960  }
3961 
3962  if ((ULONG)Index > (Window->cbwndExtra - sizeof(WORD)))
3963  {
3965  RETURN( 0);
3966  }
3967 
3968  OldValue = *((WORD *)((PCHAR)(Window + 1) + Index));
3969  *((WORD *)((PCHAR)(Window + 1) + Index)) = NewValue;
3970 
3971  RETURN( OldValue);
3972 
3973 CLEANUP:
3974  TRACE("Leave NtUserSetWindowWord, ret=%u\n", _ret_);
3975  UserLeave();
3976  END_CLEANUP;
3977 }
3978 
3979 /*
3980  QueryWindow based on KJK::Hyperion and James Tabor.
3981 
3982  0 = QWUniqueProcessId
3983  1 = QWUniqueThreadId
3984  2 = QWActiveWindow
3985  3 = QWFocusWindow
3986  4 = QWIsHung Implements IsHungAppWindow found
3987  by KJK::Hyperion.
3988 
3989  9 = QWKillWindow When I called this with hWnd ==
3990  DesktopWindow, it shutdown the system
3991  and rebooted.
3992 */
3993 /*
3994  * @implemented
3995  */
3998 {
3999 /* Console Leader Process CID Window offsets */
4000 #define GWLP_CONSOLE_LEADER_PID 0
4001 #define GWLP_CONSOLE_LEADER_TID 4
4002 
4003  PWND pWnd;
4004  DWORD_PTR Result;
4006 
4007  TRACE("Enter NtUserQueryWindow\n");
4008  UserEnterShared();
4009 
4010  if (!(pWnd = UserGetWindowObject(hWnd)))
4011  {
4012  RETURN( 0);
4013  }
4014 
4015  switch(Index)
4016  {
4018  {
4019  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
4021  {
4022  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
4023  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
4024  }
4025  else
4026  {
4028  }
4029  break;
4030  }
4031 
4033  {
4034  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
4036  {
4037  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
4038  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
4039  }
4040  else
4041  {
4043  }
4044  break;
4045  }
4046 
4047  case QUERY_WINDOW_ACTIVE:
4048  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
4049  break;
4050 
4051  case QUERY_WINDOW_FOCUS:
4052  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
4053  break;
4054 
4055  case QUERY_WINDOW_ISHUNG:
4056  Result = (DWORD_PTR)MsqIsHung(pWnd->head.pti);
4057  break;
4058 
4059  case QUERY_WINDOW_REAL_ID:
4060  Result = (DWORD_PTR)pWnd->head.pti->pEThread->Cid.UniqueProcess;
4061  break;
4062 
4064  Result = (pWnd->head.pti->MessageQueue == gpqForeground);
4065  break;
4066 
4067  default:
4068  Result = 0;
4069  break;
4070  }
4071 
4072  RETURN( Result);
4073 
4074 CLEANUP:
4075  TRACE("Leave NtUserQueryWindow, ret=%u\n", _ret_);
4076  UserLeave();
4077  END_CLEANUP;
4078 }
4079 
4080 /*
4081  * @implemented
4082  */
4083 UINT APIENTRY
4085 {
4086  UNICODE_STRING SafeMessageName;
4087  NTSTATUS Status;
4088  UINT Ret;
4090 
4091  TRACE("Enter NtUserRegisterWindowMessage\n");
4093 
4094  if(MessageNameUnsafe == NULL)
4095  {
4097  RETURN( 0);
4098  }
4099 
4100  Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
4101  if(!NT_SUCCESS(Status))
4102  {
4104  RETURN( 0);
4105  }
4106 
4107  Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
4108  if (SafeMessageName.Buffer)
4109  ExFreePoolWithTag(SafeMessageName.Buffer, TAG_STRING);
4110  RETURN( Ret);
4111 
4112 CLEANUP:
4113  TRACE("Leave NtUserRegisterWindowMessage, ret=%u\n", _ret_);
4114  UserLeave();
4115  END_CLEANUP;
4116 }
4117 
4118 /*
4119  * @implemented
4120  */
4121 BOOL APIENTRY
4123  WORD fnID)
4124 {
4125  PWND Wnd;
4127 
4128  TRACE("Enter NtUserSetWindowFNID\n");
4130 
4131  if (!(Wnd = UserGetWindowObject(hWnd)))
4132  {
4133  RETURN( FALSE);
4134  }
4135 
4136  if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process())
4137  {
4139  RETURN( FALSE);
4140  }
4141 
4142  // From user land we only set these.
4143  if (fnID != FNID_DESTROY)
4144  {
4145  /* HACK: The minimum should be FNID_BUTTON, but menu code relies on this */
4146  if (fnID < FNID_FIRST || fnID > FNID_GHOST ||
4147  Wnd->fnid != 0)
4148  {
4150  RETURN( FALSE);
4151  }
4152  }
4153 
4154  Wnd->fnid |= fnID;
4155  RETURN( TRUE);
4156 
4157 CLEANUP:
4158  TRACE("Leave NtUserSetWindowFNID\n");
4159  UserLeave();
4160  END_CLEANUP;
4161 }
4162 
4163 BOOL APIENTRY
4164 DefSetText(PWND Wnd, PCWSTR WindowText)
4165 {
4167  BOOL Ret = FALSE;
4168 
4169  RtlInitUnicodeString(&UnicodeString, WindowText);
4170 
4171  if (UnicodeString.Length != 0)
4172  {
4173  if (Wnd->strName.MaximumLength > 0 &&
4174  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4175  {
4176  ASSERT(Wnd->strName.Buffer != NULL);
4177 
4178  Wnd->strName.Length = UnicodeString.Length;
4179  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4181  UnicodeString.Buffer,
4182  UnicodeString.Length);
4183  }
4184  else
4185  {
4186  PWCHAR buf;
4187  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4188  buf = Wnd->strName.Buffer;
4189  Wnd->strName.Buffer = NULL;
4190  if (buf != NULL)
4191  {
4192  DesktopHeapFree(Wnd->head.rpdesk, buf);
4193  }
4194 
4196  UnicodeString.Length + sizeof(UNICODE_NULL));
4197  if (Wnd->strName.Buffer != NULL)
4198  {
4199  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4201  UnicodeString.Buffer,
4202  UnicodeString.Length);
4203  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4204  Wnd->strName.Length = UnicodeString.Length;
4205  }
4206  else
4207  {
4209  goto Exit;
4210  }
4211  }
4212  }
4213  else
4214  {
4215  Wnd->strName.Length = 0;
4216  if (Wnd->strName.Buffer != NULL)
4217  Wnd->strName.Buffer[0] = L'\0';
4218  }
4219 
4220  // FIXME: HAX! Windows does not do this in here!
4221  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4222  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4223  /* Send shell notifications */
4224  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4225  {
4226  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
4227  }
4228 
4229  Ret = TRUE;
4230 Exit:
4232  return Ret;
4233 }
4234 
4235 /*
4236  * NtUserDefSetText
4237  *
4238  * Undocumented function that is called from DefWindowProc to set
4239  * window text.
4240  *
4241  * Status
4242  * @implemented
4243  */
4244 BOOL APIENTRY
4246 {
4247  PWND Wnd;
4248  LARGE_STRING SafeText;
4250  BOOL Ret = TRUE;
4251 
4252  TRACE("Enter NtUserDefSetText\n");
4253 
4254  if (WindowText != NULL)
4255  {
4256  _SEH2_TRY
4257  {
4258  SafeText = ProbeForReadLargeString(WindowText);
4259  }
4261  {
4262  Ret = FALSE;
4264  }
4265  _SEH2_END;
4266 
4267  if (!Ret)
4268  return FALSE;
4269  }
4270  else
4271  return TRUE;
4272 
4274 
4275  if(!(Wnd = UserGetWindowObject(hWnd)))
4276  {
4277  UserLeave();
4278  return FALSE;
4279  }
4280 
4281  // ReactOS uses Unicode and not mixed. Up/Down converting will take time.
4282  // Brought to you by: The Wine Project! Dysfunctional Thought Processes!
4283  // Now we know what the bAnsi is for.
4285  if (SafeText.Buffer)
4286  {
4287  _SEH2_TRY
4288  {
4289  if (SafeText.bAnsi)
4290  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(CHAR));
4291  else
4292  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(WCHAR));
4293  Ret = RtlLargeStringToUnicodeString(&UnicodeString, &SafeText);
4294  }
4296  {
4297  Ret = FALSE;
4299  }
4300  _SEH2_END;
4301  if (!Ret) goto Exit;
4302  }
4303 
4304  if (UnicodeString.Length != 0)
4305  {
4306  if (Wnd->strName.MaximumLength > 0 &&
4307  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4308  {
4309  ASSERT(Wnd->strName.Buffer != NULL);
4310 
4311  Wnd->strName.Length = UnicodeString.Length;
4312  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4314  UnicodeString.Buffer,
4315  UnicodeString.Length);
4316  }
4317  else
4318  {
4319  PWCHAR buf;
4320  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4321  buf = Wnd->strName.Buffer;
4322  Wnd->strName.Buffer = NULL;
4323  if (buf != NULL)
4324  {
4325  DesktopHeapFree(Wnd->head.rpdesk, buf);
4326  }
4327 
4329  UnicodeString.Length + sizeof(UNICODE_NULL));
4330  if (Wnd->strName.Buffer != NULL)
4331  {
4332  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4334  UnicodeString.Buffer,
4335  UnicodeString.Length);
4336  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4337  Wnd->strName.Length = UnicodeString.Length;
4338  }
4339  else
4340  {
4342  Ret = FALSE;
4343  goto Exit;
4344  }
4345  }
4346  }
4347  else
4348  {
4349  Wnd->strName.Length = 0;
4350  if (Wnd->strName.Buffer != NULL)
4351  Wnd->strName.Buffer[0] = L'\0';
4352  }
4353 
4354  // FIXME: HAX! Windows does not do this in here!
4355  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4356  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4357  /* Send shell notifications */
4358  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4359  {
4360  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing?
4361  }
4362 
4363  Ret = TRUE;
4364 Exit:
4366  TRACE("Leave NtUserDefSetText, ret=%i\n", Ret);
4367  UserLeave();
4368  return Ret;
4369 }
4370 
4371 /*
4372  * NtUserInternalGetWindowText
4373  *
4374  * Status
4375  * @implemented
4376  */
4377 
4378 INT APIENTRY
4380 {
4381  PWND Wnd;
4382  NTSTATUS Status;
4383  INT Result;
4385 
4386  TRACE("Enter NtUserInternalGetWindowText\n");
4387  UserEnterShared();
4388 
4389  if(lpString && (nMaxCount <= 1))
4390  {
4392  RETURN( 0);
4393  }
4394 
4395  if(!(Wnd = UserGetWindowObject(hWnd)))
4396  {
4397  RETURN( 0);
4398  }
4399 
4400  Result = Wnd->strName.Length / sizeof(WCHAR);
4401  if(lpString)
4402  {
4403  const WCHAR Terminator = L'\0';
4404  INT Copy;
4405  WCHAR *Buffer = (WCHAR*)lpString;
4406 
4407  Copy = min(nMaxCount - 1, Result);
4408  if(Copy > 0)
4409  {
4410  Status = MmCopyToCaller(Buffer, Wnd->strName.Buffer, Copy * sizeof(WCHAR));
4411  if(!NT_SUCCESS(Status))
4412  {
4414  RETURN( 0);
4415  }
4416  Buffer += Copy;
4417  }
4418 
4419  Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
4420  if(!NT_SUCCESS(Status))
4421  {
4423  RETURN( 0);
4424  }
4425 
4426  Result = Copy;
4427  }
4428 
4429  RETURN( Result);
4430 
4431 CLEANUP:
4432  TRACE("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
4433  UserLeave();
4434  END_CLEANUP;
4435 }
4436 
4437 /*
4438  API Call
4439 */
4440 BOOL
4441 FASTCALL
4442 IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
4443 {
4444  int count = 0;
4445  PWND pWnd;
4446  HWND *win_array;
4447 
4448 // ASSERT(OwnerWnd);
4449 
4450  TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
4451 
4452  /* NOTE: Popups are not children */
4453  win_array = IntWinListOwnedPopups(OwnerWnd);
4454 
4455  if (!win_array)
4456  return TRUE;
4457 
4458  while (win_array[count])
4459  count++;
4460  while (--count >= 0)
4461  {
4462  if (!(pWnd = ValidateHwndNoErr( win_array[count] )))
4463  continue;
4464  if (pWnd->spwndOwner != OwnerWnd)
4465  continue;
4466 
4467  if (fShow)
4468  {
4469  if (pWnd->state & WNDS_HIDDENPOPUP)
4470  {
4471  /* In Windows, ShowOwnedPopups(TRUE) generates
4472  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4473  * regardless of the state of the owner
4474  */
4476  pWnd->state &= ~WNDS_HIDDENPOPUP;
4477  continue;
4478  }
4479  }
4480  else
4481  {
4482  if (pWnd->style & WS_VISIBLE)
4483  {
4484  /* In Windows, ShowOwnedPopups(FALSE) generates
4485  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4486  * regardless of the state of the owner
4487  */
4489  pWnd->state |= WNDS_HIDDENPOPUP;
4490  continue;
4491  }
4492  }
4493  }
4495  TRACE("Leave ShowOwnedPopups\n");
4496  return TRUE;
4497 }
4498 
4499 /* 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:3524
#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:2491
#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:39
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:3213
#define GA_ROOT
Definition: winuser.h:2764
#define FNID_EDIT
Definition: ntuser.h:832
#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:3853
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:1155
#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:580
#define MAKEWPARAM(l, h)
Definition: winuser.h:3948
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:1143
*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:1370
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
BOOL APIENTRY NtUserGetComboBoxInfo(HWND hWnd, PCOMBOBOXINFO pcbi)
Definition: window.c:3273
ULONG PropListItems
Definition: ntuser.h:688
DWORD ExStyle2
Definition: ntuser.h:709
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:479
#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:3267
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:2434
#define pt(x, y)
Definition: drawing.c:79
BOOL APIENTRY DefSetText(PWND Wnd, PCWSTR WindowText)
Definition: window.c:4164
#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
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:2949
#define GWL_ID
Definition: winuser.h:853
GLuint GLuint GLsizei count
Definition: gl.h:1545
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:2194
#define SB_HORZ
Definition: winuser.h:552
VOID FASTCALL IntNotifyWinEvent(DWORD Event, PWND pWnd, LONG idObject, LONG idChild, DWORD flags)
Definition: event.c:179
#define WINVER_WIN2K
Definition: window.h:55
#define MAKELPARAM(l, h)
Definition: winuser.h:3947
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:1720
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:374
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:4442
#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:317
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
struct _WND::@4115 InternalPos
LB_DESCR * pLBiv
Definition: window.c:3376
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:2417
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:722
#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:2765
#define SW_SHOWMINIMIZED
Definition: winuser.h:765
#define VK_ESCAPE
Definition: winuser.h:2189
#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:3997
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
#define WINVER_WINNT4
Definition: window.h:56
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:781
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:2950
FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
Definition: userfuncs.h:3
GETCPD wType
Definition: ntuser.h:521
#define SC_TASKLIST
Definition: winuser.h:2574
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
CLIENT_DATA ClientInfo
LONG UIState
Definition: window.c:3257
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:522
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: