ReactOS  0.4.15-dev-1018-g0695ecb
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 
2105  /* NCCREATE, WM_NCCALCSIZE and Hooks need the original values */
2106  Cs->lpszName = (LPCWSTR) WindowName;
2107  Cs->lpszClass = (LPCWSTR) ClassName;
2108 
2110  if ( ISITHOOKED(WH_CBT) || (pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)) )
2111  {
2112  // Allocate the calling structures Justin Case this goes Global.
2115  if (!pCsw || !pCbtCreate)
2116  {
2117  ERR("UserHeapAlloc() failed!\n");
2118  goto cleanup;
2119  }
2120 
2121  if (!IntMsgCreateStructW( Window, pCsw, Cs, &pszClass, &pszName ) )
2122  {
2123  ERR("IntMsgCreateStructW() failed!\n");
2124  goto cleanup;
2125  }
2126 
2127  pCbtCreate->lpcs = pCsw;
2128  pCbtCreate->hwndInsertAfter = hwndInsertAfter;
2129 
2132  if (Result != 0)
2133  {
2134  ERR("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
2135  goto cleanup;
2136  }
2137  // Write back changes.
2138  Cs->cx = pCsw->cx;
2139  Cs->cy = pCsw->cy;
2140  Cs->x = pCsw->x;
2141  Cs->y = pCsw->y;
2142  hwndInsertAfter = pCbtCreate->hwndInsertAfter;
2143  }
2144 
2145  if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
2146  {
2147  if (ParentWindow != co_GetDesktopWindow(Window))
2148  {
2149  Cs->x += ParentWindow->rcClient.left;
2150  Cs->y += ParentWindow->rcClient.top;
2151  }
2152  }
2153 
2154  /* Send the WM_GETMINMAXINFO message */
2155  Size.cx = Cs->cx;
2156  Size.cy = Cs->cy;
2157 
2158  if ((Cs->style & WS_THICKFRAME) || !(Cs->style & (WS_POPUP | WS_CHILD)))
2159  {
2160  co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack, &MaxTrack);
2161  if (Size.cx > MaxTrack.x) Size.cx = MaxTrack.x;
2162  if (Size.cy > MaxTrack.y) Size.cy = MaxTrack.y;
2163  if (Size.cx < MinTrack.x) Size.cx = MinTrack.x;
2164  if (Size.cy < MinTrack.y) Size.cy = MinTrack.y;
2165  }
2166 
2167  Window->rcWindow.left = Cs->x;
2168  Window->rcWindow.top = Cs->y;
2169  Window->rcWindow.right = Cs->x + Size.cx;
2170  Window->rcWindow.bottom = Cs->y + Size.cy;
2171  /*
2172  if (0 != (Window->style & WS_CHILD) && ParentWindow)
2173  {
2174  ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
2175  RECTL_vOffsetRect(&Window->rcWindow,
2176  ParentWindow->rcClient.left,
2177  ParentWindow->rcClient.top);
2178  }
2179  */
2180  /* correct child window coordinates if mirroring on parent is enabled */
2181  if (ParentWindow != NULL)
2182  {
2183  if ( ((Cs->style & WS_CHILD) == WS_CHILD) &&
2184  ((ParentWindow->ExStyle & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL))
2185  {
2186  Window->rcWindow.right = ParentWindow->rcClient.right - (Window->rcWindow.left - ParentWindow->rcClient.left);
2187  Window->rcWindow.left = Window->rcWindow.right - Size.cx;
2188  }
2189  }
2190 
2191  Window->rcClient = Window->rcWindow;
2192 
2193  /* Link the window */
2194  if (NULL != ParentWindow)
2195  {
2196  /* Link the window into the siblings list */
2197  if ((Cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
2199  else
2200  IntLinkHwnd(Window, hwndInsertAfter);
2201  }
2202 
2203  if (!(Window->state2 & WNDS2_WIN31COMPAT))
2204  {
2205  if (Class->style & CS_PARENTDC && !(ParentWindow->style & WS_CLIPCHILDREN))
2206  Window->style &= ~(WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
2207  }
2208 
2209  if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2210  {
2211  if ( !IntIsTopLevelWindow(Window) )
2212  {
2213  if (pti != Window->spwndParent->head.pti)
2214  {
2215  //ERR("CreateWindow Parent in.\n");
2216  UserAttachThreadInput(pti, Window->spwndParent->head.pti, TRUE);
2217  }
2218  }
2219  }
2220 
2221  /* Send the NCCREATE message */
2223  if (!Result)
2224  {
2225  ERR("co_UserCreateWindowEx(): NCCREATE message failed\n");
2226  goto cleanup;
2227  }
2228 
2229  /* Send the WM_NCCALCSIZE message */
2230  {
2231  // RECT rc;
2232  MaxPos.x = Window->rcWindow.left;
2233  MaxPos.y = Window->rcWindow.top;
2234 
2235  Result = co_WinPosGetNonClientSize(Window, &Window->rcWindow, &Window->rcClient);
2236  //rc = Window->rcWindow;
2237  //Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM)&rc);
2238  //Window->rcClient = rc;
2239 
2240  RECTL_vOffsetRect(&Window->rcWindow, MaxPos.x - Window->rcWindow.left,
2241  MaxPos.y - Window->rcWindow.top);
2242  }
2243 
2244  /* Send the WM_CREATE message. */
2246  if (Result == (LRESULT)-1)
2247  {
2248  ERR("co_UserCreateWindowEx(): WM_CREATE message failed\n");
2249  goto cleanup;
2250  }
2251 
2252  /* Send the EVENT_OBJECT_CREATE event */
2253  IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2254 
2255  /* By setting the flag below it can be examined to determine if the window
2256  was created successfully and a valid pwnd was passed back to caller since
2257  from here the function has to succeed. */
2259 
2260  /* Send the WM_SIZE and WM_MOVE messages. */
2261  if (!(Window->state & WNDS_SENDSIZEMOVEMSGS))
2262  {
2264  }
2265 
2266  /* Show or maybe minimize or maximize the window. */
2267 
2269  if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2270  {
2271  RECTL NewPos;
2272  UINT SwFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
2273 
2274  SwFlag = co_WinPosMinMaximize(Window, SwFlag, &NewPos);
2275  SwFlag |= SWP_NOZORDER|SWP_FRAMECHANGED; /* Frame always gets changed */
2276  if (!(style & WS_VISIBLE) || (style & WS_CHILD) || UserGetActiveWindow()) SwFlag |= SWP_NOACTIVATE;
2277  co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top,
2278  NewPos.right, NewPos.bottom, SwFlag);
2279  }
2280 
2281  /* Send the WM_PARENTNOTIFY message */
2283 
2284  /* Notify the shell that a new window was created */
2285  if (Window->spwndOwner == NULL ||
2286  !(Window->spwndOwner->style & WS_VISIBLE) ||
2287  (Window->spwndOwner->ExStyle & WS_EX_TOOLWINDOW))
2288  {
2289  if (UserIsDesktopWindow(Window->spwndParent) &&
2290  (Window->style & WS_VISIBLE) &&
2291  (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
2292  (Window->ExStyle & WS_EX_APPWINDOW)))
2293  {
2295  }
2296  }
2297 
2298  /* Initialize and show the window's scrollbars */
2299  if (Window->style & WS_VSCROLL)
2300  {
2302  }
2303  if (Window->style & WS_HSCROLL)
2304  {
2306  }
2307 
2308  /* Show the new window */
2309  if (Cs->style & WS_VISIBLE)
2310  {
2311  if (Window->style & WS_MAXIMIZE)
2312  dwShowMode = SW_SHOW;
2313  else if (Window->style & WS_MINIMIZE)
2314  dwShowMode = SW_SHOWMINIMIZED;
2315 
2316  co_WinPosShowWindow(Window, dwShowMode);
2317 
2318  if (Window->ExStyle & WS_EX_MDICHILD)
2319  {
2320  ASSERT(ParentWindow);
2321  if(!ParentWindow)
2322  goto cleanup;
2323  co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
2324  /* ShowWindow won't activate child windows */
2326  }
2327  }
2328 
2329  if (Class->atomClassName == gaGuiConsoleWndClass)
2330  {
2331  /* Count only console windows manually */
2333  }
2334 
2335  TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
2336  ret = Window;
2337 
2338 cleanup:
2339  if (!ret)
2340  {
2341  TRACE("co_UserCreateWindowEx(): Error Created window!\n");
2342  /* If the window was created, the class will be dereferenced by co_UserDestroyWindow */
2343  if (Window)
2345  else if (Class)
2346  IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
2347  }
2348 
2349  if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
2350  if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
2351  if (pszName) UserHeapFree(pszName);
2352  if (pszClass) UserHeapFree(pszClass);
2353 
2354  if (Window)
2355  {
2357  }
2358  if (ParentWindow) UserDerefObjectCo(ParentWindow);
2359 
2360  // See CORE-13717, not setting error on success.
2361  if (ret)
2363 
2364  return ret;
2365 }
2366 
2367 NTSTATUS
2368 NTAPI
2370  OUT PLARGE_STRING plstrSafe,
2371  IN PLARGE_STRING plstrUnsafe)
2372 {
2373  LARGE_STRING lstrTemp;
2374  PVOID pvBuffer = NULL;
2375 
2376  _SEH2_TRY
2377  {
2378  /* Probe and copy the string */
2379  ProbeForRead(plstrUnsafe, sizeof(LARGE_STRING), sizeof(ULONG));
2380  lstrTemp = *plstrUnsafe;
2381  }
2383  {
2384  /* Fail */
2386  }
2387  _SEH2_END
2388 
2389  if (lstrTemp.Length != 0)
2390  {
2391  /* Allocate a buffer from paged pool */
2392  pvBuffer = ExAllocatePoolWithTag(PagedPool, lstrTemp.Length, TAG_STRING);
2393  if (!pvBuffer)
2394  {
2395  return STATUS_NO_MEMORY;
2396  }
2397 
2398  _SEH2_TRY
2399  {
2400  /* Probe and copy the buffer */
2401  ProbeForRead(lstrTemp.Buffer, lstrTemp.Length, sizeof(WCHAR));
2402  RtlCopyMemory(pvBuffer, lstrTemp.Buffer, lstrTemp.Length);
2403  }
2405  {
2406  /* Cleanup and fail */
2407  ExFreePoolWithTag(pvBuffer, TAG_STRING);
2409  }
2410  _SEH2_END
2411  }
2412 
2413  /* Set the output string */
2414  plstrSafe->Buffer = pvBuffer;
2415  plstrSafe->Length = lstrTemp.Length;
2416  plstrSafe->MaximumLength = lstrTemp.Length;
2417 
2418  return STATUS_SUCCESS;
2419 }
2420 
2424 HWND
2425 NTAPI
2427  DWORD dwExStyle,
2428  PLARGE_STRING plstrClassName,
2429  PLARGE_STRING plstrClsVersion,
2430  PLARGE_STRING plstrWindowName,
2431  DWORD dwStyle,
2432  int x,
2433  int y,
2434  int nWidth,
2435  int nHeight,
2436  HWND hWndParent,
2437  HMENU hMenu,
2439  LPVOID lpParam,
2440  DWORD dwFlags,
2441  PVOID acbiBuffer)
2442 {
2443  NTSTATUS Status;
2444  LARGE_STRING lstrWindowName;
2445  LARGE_STRING lstrClassName;
2446  LARGE_STRING lstrClsVersion;
2447  UNICODE_STRING ustrClassName;
2448  UNICODE_STRING ustrClsVersion;
2449  CREATESTRUCTW Cs;
2450  HWND hwnd = NULL;
2451  PWND pwnd;
2452 
2453  lstrWindowName.Buffer = NULL;
2454  lstrClassName.Buffer = NULL;
2455  lstrClsVersion.Buffer = NULL;
2456 
2457  ASSERT(plstrWindowName);
2458 
2459  if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2460  {
2461  /* check hMenu is valid handle */
2462  if (hMenu && !UserGetMenuObject(hMenu))
2463  {
2464  ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
2466  return NULL;
2467  }
2468  }
2469 
2470  /* Copy the window name to kernel mode */
2471  Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
2472  if (!NT_SUCCESS(Status))
2473  {
2474  ERR("NtUserCreateWindowEx: failed to capture plstrWindowName\n");
2476  return NULL;
2477  }
2478 
2479  plstrWindowName = &lstrWindowName;
2480 
2481  /* Check if the class is an atom */
2482  if (IS_ATOM(plstrClassName))
2483  {
2484  /* It is, pass the atom in the UNICODE_STRING */
2485  ustrClassName.Buffer = (PVOID)plstrClassName;
2486  ustrClassName.Length = 0;
2487  ustrClassName.MaximumLength = 0;
2488  }
2489  else
2490  {
2491  /* It's not, capture the class name */
2492  Status = ProbeAndCaptureLargeString(&lstrClassName, plstrClassName);
2493  if (!NT_SUCCESS(Status))
2494  {
2495  ERR("NtUserCreateWindowEx: failed to capture plstrClassName\n");
2496  /* Set last error, cleanup and return */
2498  goto cleanup;
2499  }
2500 
2501  /* We pass it on as a UNICODE_STRING */
2502  ustrClassName.Buffer = lstrClassName.Buffer;
2503  ustrClassName.Length = (USHORT)min(lstrClassName.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2504  ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
2505  }
2506 
2507  /* Check if the class version is an atom */
2508  if (IS_ATOM(plstrClsVersion))
2509  {
2510  /* It is, pass the atom in the UNICODE_STRING */
2511  ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
2512  ustrClsVersion.Length = 0;
2513  ustrClsVersion.MaximumLength = 0;
2514  }
2515  else
2516  {
2517  /* It's not, capture the class name */
2518  Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
2519  if (!NT_SUCCESS(Status))
2520  {
2521  ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
2522  /* Set last error, cleanup and return */
2524  goto cleanup;
2525  }
2526 
2527  /* We pass it on as a UNICODE_STRING */
2528  ustrClsVersion.Buffer = lstrClsVersion.Buffer;
2529  ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
2530  ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
2531  }
2532 
2533  /* Fill the CREATESTRUCTW */
2534  /* we will keep here the original parameters */
2535  Cs.style = dwStyle;
2536  Cs.lpCreateParams = lpParam;
2537  Cs.hInstance = hInstance;
2538  Cs.hMenu = hMenu;
2539  Cs.hwndParent = hWndParent;
2540  Cs.cx = nWidth;
2541  Cs.cy = nHeight;
2542  Cs.x = x;
2543  Cs.y = y;
2544  Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer;
2545  Cs.lpszClass = ustrClassName.Buffer;
2546  Cs.dwExStyle = dwExStyle;
2547 
2549 
2550  /* Call the internal function */
2551  pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer, dwFlags);
2552 
2553  if(!pwnd)
2554  {
2555  ERR("co_UserCreateWindowEx failed!\n");
2556  }
2557  hwnd = pwnd ? UserHMGetHandle(pwnd) : NULL;
2558 
2559  UserLeave();
2560 
2561 cleanup:
2562  if (lstrWindowName.Buffer)
2563  {
2564  ExFreePoolWithTag(lstrWindowName.Buffer, TAG_STRING);
2565  }
2566  if (lstrClassName.Buffer)
2567  {
2568  ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
2569  }
2570  if (lstrClsVersion.Buffer)
2571  {
2572  ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
2573  }
2574 
2575  return hwnd;
2576 }
2577 
2578 
2580 {
2581  HWND hWnd;
2582  PWND pwndTemp;
2583  PTHREADINFO ti;
2584  MSG msg;
2585  PWND Window = Object;
2586 
2587  ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
2588 
2589  hWnd = Window->head.h;
2591 
2592  TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
2593 
2594  /* Check for owner thread */
2595  if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
2596  {
2597  /* Check if we are destroying the desktop window */
2598  if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
2599  {
2601  return FALSE;
2602  }
2603  }
2604 
2605  /* If window was created successfully and it is hooked */
2606  if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
2607  {
2609  {
2610  ERR("Destroy Window WH_CBT Call Hook return!\n");
2611  return FALSE;
2612  }
2613  }
2614 
2615  if (Window->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME])
2616  {
2617  if ((Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2618  {
2619  if (Window->spwndOwner)
2620  {
2621  //ERR("DestroyWindow Owner out.\n");
2622  UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE);
2623  }
2624  }
2625  }
2626 
2627  /* Inform the parent */
2628  if (Window->style & WS_CHILD)
2629  {
2631  }
2632 
2633  if (!Window->spwndOwner && !IntGetParent(Window))
2634  {
2636  }
2637 
2638  /* Hide the window */
2639  if (Window->style & WS_VISIBLE)
2640  {
2641  if (Window->style & WS_CHILD)
2642  {
2643  /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
2645  }
2646  else
2647  {
2649  }
2650  }
2651 
2652  /* Adjust last active */
2653  if ((pwndTemp = Window->spwndOwner))
2654  {
2655  while (pwndTemp->spwndOwner)
2656  pwndTemp = pwndTemp->spwndOwner;
2657 
2658  if (pwndTemp->spwndLastActive == Window)
2659  pwndTemp->spwndLastActive = Window->spwndOwner;
2660  }
2661 
2662  if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))
2663  {
2664  if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
2665  {
2667  {
2668  //ERR("DestroyWindow Parent out.\n");
2669  UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE);
2670  }
2671  }
2672  }
2673 
2674  if (Window->head.pti->MessageQueue->spwndActive == Window)
2675  Window->head.pti->MessageQueue->spwndActive = NULL;
2676  if (Window->head.pti->MessageQueue->spwndFocus == Window)
2677  Window->head.pti->MessageQueue->spwndFocus = NULL;
2678  if (Window->head.pti->MessageQueue->spwndActivePrev == Window)
2679  Window->head.pti->MessageQueue->spwndActivePrev = NULL;
2680  if (Window->head.pti->MessageQueue->spwndCapture == Window)
2681  Window->head.pti->MessageQueue->spwndCapture = NULL;
2682 
2683  /*
2684  * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL
2685  */
2686 
2687  if ((ti != NULL) && (ti->pDeskInfo != NULL))
2688  {
2689  if (ti->pDeskInfo->hShellWindow == hWnd)
2690  {
2691  ERR("Destroying the ShellWindow!\n");
2692  ti->pDeskInfo->hShellWindow = NULL;
2693  }
2694  }
2695 
2697 
2699  {
2700  return TRUE;
2701  }
2702 
2703  /* Recursively destroy owned windows */
2704  if (!(Window->style & WS_CHILD))
2705  {
2706  HWND* List;
2707  HWND* phWnd;
2708  PWND pWnd;
2709 
2711  if (List)
2712  {
2713  for (phWnd = List; *phWnd; ++phWnd)
2714  {
2715  pWnd = ValidateHwndNoErr(*phWnd);
2716  if (pWnd == NULL)
2717  continue;
2718  ASSERT(pWnd->spwndOwner == Window);
2719  ASSERT(pWnd != Window);
2720 
2721  pWnd->spwndOwner = NULL;
2723  {
2725  UserRefObjectCo(pWnd, &Ref); // Temp HACK?
2726  co_UserDestroyWindow(pWnd);
2727  UserDerefObjectCo(pWnd); // Temp HACK?
2728  }
2729  else
2730  {
2731  ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
2732  }
2733  }
2734 
2736  }
2737  }
2738 
2739  /* Generate mouse move message for the next window */
2740  msg.message = WM_MOUSEMOVE;
2741  msg.wParam = UserGetMouseButtonsState();
2742  msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2743  msg.pt = gpsi->ptCursor;
2745 
2746  IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
2747 
2748  /* Send destroy messages */
2750 
2752  {
2753  return TRUE;
2754  }
2755 
2756  /* Destroy the window storage */
2758 
2759  return TRUE;
2760 }
2761 
2762 
2763 /*
2764  * @implemented
2765  */
2768 {
2769  PWND Window;
2771  BOOLEAN ret;
2773 
2774  TRACE("Enter NtUserDestroyWindow\n");
2776 
2777  if (!(Window = UserGetWindowObject(Wnd)))
2778  {
2779  RETURN(FALSE);
2780  }
2781 
2782  UserRefObjectCo(Window, &Ref); // FIXME: Dunno if win should be reffed during destroy...
2784  UserDerefObjectCo(Window); // FIXME: Dunno if win should be reffed during destroy...
2785 
2786  RETURN(ret);
2787 
2788 CLEANUP:
2789  TRACE("Leave NtUserDestroyWindow, ret=%u\n", _ret_);
2790  UserLeave();
2791  END_CLEANUP;
2792 }
2793 
2794 
2795 static HWND FASTCALL
2797  PWND ChildAfter,
2798  RTL_ATOM ClassAtom,
2799  PUNICODE_STRING WindowName)
2800 {
2801  BOOL CheckWindowName;
2802  HWND *List, *phWnd;
2803  HWND Ret = NULL;
2804  UNICODE_STRING CurrentWindowName;
2805 
2806  ASSERT(Parent);
2807 
2808  CheckWindowName = WindowName->Buffer != 0;
2809 
2810  if((List = IntWinListChildren(Parent)))
2811  {
2812  phWnd = List;
2813  if(ChildAfter)
2814  {
2815  /* skip handles before and including ChildAfter */
2816  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
2817  ;
2818  }
2819 
2820  /* search children */
2821  while(*phWnd)
2822  {
2823  PWND Child;
2824  if(!(Child = UserGetWindowObject(*(phWnd++))))
2825  {
2826  continue;
2827  }
2828 
2829  /* Do not send WM_GETTEXT messages in the kernel mode version!
2830  The user mode version however calls GetWindowText() which will
2831  send WM_GETTEXT messages to windows belonging to its processes */
2832  if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
2833  {
2834  // FIXME: LARGE_STRING truncated
2835  CurrentWindowName.Buffer = Child->strName.Buffer;
2836  CurrentWindowName.Length = (USHORT)min(Child->strName.Length, MAXUSHORT);
2837  CurrentWindowName.MaximumLength = (USHORT)min(Child->strName.MaximumLength, MAXUSHORT);
2838  if(!CheckWindowName ||
2839  (Child->strName.Length < 0xFFFF &&
2840  !RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
2841  {
2842  Ret = Child->head.h;
2843  break;
2844  }
2845  }
2846  }
2848  }
2849 
2850  return Ret;
2851 }
2852 
2853 /*
2854  * FUNCTION:
2855  * Searches a window's children for a window with the specified
2856  * class and name
2857  * ARGUMENTS:
2858  * hwndParent = The window whose childs are to be searched.
2859  * NULL = desktop
2860  * HWND_MESSAGE = message-only windows
2861  *
2862  * hwndChildAfter = Search starts after this child window.
2863  * NULL = start from beginning
2864  *
2865  * ucClassName = Class name to search for
2866  * Reguired parameter.
2867  *
2868  * ucWindowName = Window name
2869  * ->Buffer == NULL = don't care
2870  *
2871  * RETURNS:
2872  * The HWND of the window if it was found, otherwise NULL
2873  */
2874 /*
2875  * @implemented
2876  */
2877 HWND APIENTRY
2879  HWND hwndChildAfter,
2880  PUNICODE_STRING ucClassName,
2881  PUNICODE_STRING ucWindowName,
2882  DWORD dwUnknown)
2883 {
2884  PWND Parent, ChildAfter;
2885  UNICODE_STRING ClassName = {0}, WindowName = {0};
2886  HWND Desktop, Ret = NULL;
2887  BOOL DoMessageWnd = FALSE;
2888  RTL_ATOM ClassAtom = (RTL_ATOM)0;
2890 
2891  TRACE("Enter NtUserFindWindowEx\n");
2892  UserEnterShared();
2893 
2894  if (ucClassName != NULL || ucWindowName != NULL)
2895  {
2896  _SEH2_TRY
2897  {
2898  if (ucClassName != NULL)
2899  {
2900  ClassName = ProbeForReadUnicodeString(ucClassName);
2901  if (ClassName.Length != 0)
2902  {
2903  ProbeForRead(ClassName.Buffer,
2904  ClassName.Length,
2905  sizeof(WCHAR));
2906  }
2907  else if (!IS_ATOM(ClassName.Buffer))
2908  {
2910  _SEH2_LEAVE;
2911  }
2912 
2913  if (!IntGetAtomFromStringOrAtom(&ClassName,
2914  &ClassAtom))
2915  {
2917  _SEH2_LEAVE;
2918  }
2919  }
2920 
2921  if (ucWindowName != NULL)
2922  {
2923  WindowName = ProbeForReadUnicodeString(ucWindowName);
2924  if (WindowName.Length != 0)
2925  {
2926  ProbeForRead(WindowName.Buffer,
2927  WindowName.Length,
2928  sizeof(WCHAR));
2929  }
2930  }
2931  }
2933  {
2936  }
2937  _SEH2_END;
2938 
2939  if (ucClassName != NULL)
2940  {
2941  if (ClassName.Length == 0 && ClassName.Buffer != NULL &&
2942  !IS_ATOM(ClassName.Buffer))
2943  {
2945  RETURN(NULL);
2946  }
2947  else if (ClassAtom == (RTL_ATOM)0)
2948  {
2949  /* LastError code was set by IntGetAtomFromStringOrAtom */
2950  RETURN(NULL);
2951  }
2952  }
2953  }
2954 
2956 
2957  if(hwndParent == NULL)
2958  {
2959  hwndParent = Desktop;
2960  DoMessageWnd = TRUE;
2961  }
2962  else if(hwndParent == HWND_MESSAGE)
2963  {
2965  }
2966 
2968  {
2969  RETURN( NULL);
2970  }
2971 
2972  ChildAfter = NULL;
2973  if(hwndChildAfter && !(ChildAfter = UserGetWindowObject(hwndChildAfter)))
2974  {
2975  RETURN( NULL);
2976  }
2977 
2978  _SEH2_TRY
2979  {
2980  if(Parent->head.h == Desktop)
2981  {
2982  HWND *List, *phWnd;
2983  PWND TopLevelWindow;
2984  BOOLEAN CheckWindowName;
2985  BOOLEAN WindowMatches;
2986  BOOLEAN ClassMatches;
2987 
2988  /* windows searches through all top-level windows if the parent is the desktop
2989  window */
2990 
2991  if((List = IntWinListChildren(Parent)))
2992  {
2993  phWnd = List;
2994 
2995  if(ChildAfter)
2996  {
2997  /* skip handles before and including ChildAfter */
2998  while(*phWnd && (*(phWnd++) != ChildAfter->head.h))
2999  ;
3000  }
3001 
3002  CheckWindowName = WindowName.Buffer != 0;
3003 
3004  /* search children */
3005  while(*phWnd)
3006  {
3007  UNICODE_STRING ustr;
3008 
3009  if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
3010  {
3011  continue;
3012  }
3013 
3014  /* Do not send WM_GETTEXT messages in the kernel mode version!
3015  The user mode version however calls GetWindowText() which will
3016  send WM_GETTEXT messages to windows belonging to its processes */
3017  ustr.Buffer = TopLevelWindow->strName.Buffer;
3018  ustr.Length = (USHORT)min(TopLevelWindow->strName.Length, MAXUSHORT); // FIXME:LARGE_STRING truncated
3019  ustr.MaximumLength = (USHORT)min(TopLevelWindow->strName.MaximumLength, MAXUSHORT);
3020  WindowMatches = !CheckWindowName ||
3021  (TopLevelWindow->strName.Length < 0xFFFF &&
3022  !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
3023  ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
3024  ClassAtom == TopLevelWindow->pcls->atomNVClassName;
3025 
3026  if (WindowMatches && ClassMatches)
3027  {
3028  Ret = TopLevelWindow->head.h;
3029  break;
3030  }
3031 
3032  if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
3033  {
3034  /* window returns the handle of the top-level window, in case it found
3035  the child window */
3036  Ret = TopLevelWindow->head.h;
3037  break;
3038  }
3039 
3040  }
3042  }
3043  }
3044  else
3045  {
3046  TRACE("FindWindowEx: Not Desktop Parent!\n");
3047  Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
3048  }
3049 
3050  if (Ret == NULL && DoMessageWnd)
3051  {
3052  PWND MsgWindows;
3053 
3054  if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
3055  {
3056  Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
3057  }
3058  }
3059  }
3061  {
3063  Ret = NULL;
3064  }
3065  _SEH2_END;
3066 
3067  RETURN( Ret);
3068 
3069 CLEANUP:
3070  TRACE("Leave NtUserFindWindowEx, ret %p\n", _ret_);
3071  UserLeave();
3072  END_CLEANUP;
3073 }
3074 
3075 
3076 /*
3077  * @implemented
3078  */
3080 {
3081  PWND WndAncestor, Parent;
3082 
3083  if (Wnd->head.h == IntGetDesktopWindow())
3084  {
3085  return NULL;
3086  }
3087 
3088  switch (Type)
3089  {
3090  case GA_PARENT:
3091  {
3092  WndAncestor = Wnd->spwndParent;
3093  break;
3094  }
3095 
3096  case GA_ROOT:
3097  {
3098  WndAncestor = Wnd;
3099  Parent = NULL;
3100 
3101  for(;;)
3102  {
3103  if(!(Parent = WndAncestor->spwndParent))
3104  {
3105  break;
3106  }
3108  {
3109  break;
3110  }
3111 
3112  WndAncestor = Parent;
3113  }
3114  break;
3115  }
3116 
3117  case GA_ROOTOWNER:
3118  {
3119  WndAncestor = Wnd;
3120 
3121  for (;;)
3122  {
3123  Parent = IntGetParent(WndAncestor);
3124 
3125  if (!Parent)
3126  {
3127  break;
3128  }
3129 
3130  WndAncestor = Parent;
3131  }
3132  break;
3133  }
3134 
3135  default:
3136  {
3137  return NULL;
3138  }
3139  }
3140 
3141  return WndAncestor;
3142 }
3143 
3144 /*
3145  * @implemented
3146  */
3147 HWND APIENTRY
3149 {
3150  PWND Window, Ancestor;
3152 
3153  TRACE("Enter NtUserGetAncestor\n");
3155 
3156  if (!(Window = UserGetWindowObject(hWnd)))
3157  {
3158  RETURN(NULL);
3159  }
3160 
3161  Ancestor = UserGetAncestor(Window, Type);
3162  /* faxme: can UserGetAncestor ever return NULL for a valid window? */
3163 
3164  RETURN(Ancestor ? Ancestor->head.h : NULL);
3165 
3166 CLEANUP:
3167  TRACE("Leave NtUserGetAncestor, ret=%p\n", _ret_);
3168  UserLeave();
3169  END_CLEANUP;
3170 }
3171 
3175 /* combo state struct */
3176 typedef struct
3177 {
3178  HWND self;
3179  HWND owner;
3180  UINT dwStyle;
3181  HWND hWndEdit;
3182  HWND hWndLBox;
3183  UINT wState;
3184  HFONT hFont;
3185  RECT textRect;
3186  RECT buttonRect;
3187  RECT droppedRect;
3188  INT droppedIndex;
3189  INT fixedOwnerDrawHeight;
3190  INT droppedWidth; /* last two are not used unless set */
3191  INT editHeight; /* explicitly */
3194 
3195 // Window Extra data container.
3196 typedef struct _WND2CBOX
3197 {
3200 } WND2CBOX, *PWND2CBOX;
3201 
3202 #define CBF_BUTTONDOWN 0x0002
3203 BOOL
3207 APIENTRY
3209  HWND hWnd,
3210  PCOMBOBOXINFO pcbi)
3211 {
3212  PWND Wnd;
3213  PPROCESSINFO ppi;
3214  BOOL NotSameppi = FALSE;
3215  BOOL Ret = TRUE;
3217 
3218  TRACE("Enter NtUserGetComboBoxInfo\n");
3219  UserEnterShared();
3220 
3221  if (!(Wnd = UserGetWindowObject(hWnd)))
3222  {
3223  RETURN( FALSE );
3224  }
3225  _SEH2_TRY
3226  {
3227  ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
3228  }
3230  {
3233  }
3234  _SEH2_END;
3235 
3236  if (pcbi->cbSize < sizeof(COMBOBOXINFO))
3237  {
3239  RETURN(FALSE);
3240  }
3241 
3242  // Pass the user pointer, it was already probed.
3243  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_COMBOBOX]) && Wnd->fnid != FNID_COMBOBOX)
3244  {
3245  RETURN( (BOOL) co_IntSendMessage( Wnd->head.h, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
3246  }
3247 
3249  NotSameppi = ppi != Wnd->head.pti->ppi;
3250  if (NotSameppi)
3251  {
3252  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3253  }
3254 
3255  _SEH2_TRY
3256  {
3257  LPHEADCOMBO lphc = ((PWND2CBOX)Wnd)->pCBox;
3258  pcbi->rcItem = lphc->textRect;
3259  pcbi->rcButton = lphc->buttonRect;
3260  pcbi->stateButton = 0;
3261  if (lphc->wState & CBF_BUTTONDOWN)
3263  if (RECTL_bIsEmptyRect(&lphc->buttonRect))
3265  pcbi->hwndCombo = lphc->self;
3266  pcbi->hwndItem = lphc->hWndEdit;
3267  pcbi->hwndList = lphc->hWndLBox;
3268  }
3270  {
3271  Ret = FALSE;
3273  }
3274  _SEH2_END;
3275 
3276  RETURN( Ret);
3277 
3278 CLEANUP:
3279  if (NotSameppi) KeDetachProcess();
3280  TRACE("Leave NtUserGetComboBoxInfo, ret=%i\n",_ret_);
3281  UserLeave();
3282  END_CLEANUP;
3283 }
3284 
3288 /* Listbox structure */
3289 typedef struct
3290 {
3291  HWND self; /* Our own window handle */
3292  HWND owner; /* Owner window to send notifications to */
3293  UINT style; /* Window style */
3294  INT width; /* Window width */
3295  INT height; /* Window height */
3296  VOID *items; /* Array of items */
3297  INT nb_items; /* Number of items */
3298  INT top_item; /* Top visible item */
3299  INT selected_item; /* Selected item */
3300  INT focus_item; /* Item that has the focus */
3301  INT anchor_item; /* Anchor item for extended selection */
3302  INT item_height; /* Default item height */
3303  INT page_size; /* Items per listbox page */
3304  INT column_width; /* Column width for multi-column listboxes */
3305 } LB_DESCR;
3306 
3307 // Window Extra data container.
3308 typedef struct _WND2LB
3309 {
3312 } WND2LB, *PWND2LB;
3316 DWORD
3317 APIENTRY
3319  HWND hWnd)
3320 {
3321  PWND Wnd;
3322  PPROCESSINFO ppi;
3323  BOOL NotSameppi = FALSE;
3324  DWORD Ret = 0;
3326 
3327  TRACE("Enter NtUserGetListBoxInfo\n");
3328  UserEnterShared();
3329 
3330  if (!(Wnd = UserGetWindowObject(hWnd)))
3331  {
3332  RETURN( 0 );
3333  }
3334 
3335  if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_LISTBOX]) && Wnd->fnid != FNID_LISTBOX)
3336  {
3337  RETURN( (DWORD) co_IntSendMessage( Wnd->head.h, LB_GETLISTBOXINFO, 0, 0 ));
3338  }
3339 
3340  // wine lisbox:test_GetListBoxInfo lb_getlistboxinfo = 0, should not send a message!
3342  NotSameppi = ppi != Wnd->head.pti->ppi;
3343  if (NotSameppi)
3344  {
3345  KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
3346  }
3347 
3348  _SEH2_TRY
3349  {
3350  LB_DESCR *descr = ((PWND2LB)Wnd)->pLBiv;
3351  // See Controls ListBox.c:LB_GETLISTBOXINFO must match...
3352  Ret = descr->page_size;
3353  }
3355  {
3356  Ret = 0;
3358  }
3359  _SEH2_END;
3360 
3361  RETURN( Ret);
3362 
3363 CLEANUP:
3364  if (NotSameppi) KeDetachProcess();
3365  TRACE("Leave NtUserGetListBoxInfo, ret=%lu\n", _ret_);
3366  UserLeave();
3367  END_CLEANUP;
3368 }
3369 
3370 /*
3371  * NtUserSetParent
3372  *
3373  * The NtUserSetParent function changes the parent window of the specified
3374  * child window.
3375  *
3376  * Remarks
3377  * The new parent window and the child window must belong to the same
3378  * application. If the window identified by the hWndChild parameter is
3379  * visible, the system performs the appropriate redrawing and repainting.
3380  * For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
3381  * or WS_POPUP window styles of the window whose parent is being changed.
3382  *
3383  * Status
3384  * @implemented
3385  */
3386 
3387 HWND APIENTRY
3389 {
3391 
3392  TRACE("Enter NtUserSetParent\n");
3394 
3395  /*
3396  Check Parent first from user space, set it here.
3397  */
3398  if (!hWndNewParent)
3399  {
3400  hWndNewParent = IntGetDesktopWindow();
3401  }
3402  else if (hWndNewParent == HWND_MESSAGE)
3403  {
3404  hWndNewParent = IntGetMessageWindow();
3405  }
3406 
3407  RETURN( co_UserSetParent(hWndChild, hWndNewParent));
3408 
3409 CLEANUP:
3410  TRACE("Leave NtUserSetParent, ret=%p\n", _ret_);
3411  UserLeave();
3412  END_CLEANUP;
3413 }
3414 
3415 /*
3416  * UserGetShellWindow
3417  *
3418  * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
3419  *
3420  * Status
3421  * @implemented
3422  */
3424 {
3425  PWINSTATION_OBJECT WinStaObject;
3426  HWND Ret;
3427 
3429  UserMode,
3430  0,
3431  &WinStaObject,
3432  0);
3433 
3434  if (!NT_SUCCESS(Status))
3435  {
3437  return( (HWND)0);
3438  }
3439 
3440  Ret = (HWND)WinStaObject->ShellWindow;
3441 
3442  ObDereferenceObject(WinStaObject);
3443  return( Ret);
3444 }
3445 
3446 /*
3447  * NtUserSetShellWindowEx
3448  *
3449  * This is undocumented function to set global shell window. The global
3450  * shell window has special handling of window position.
3451  *
3452  * Status
3453  * @implemented
3454  */
3455 BOOL APIENTRY
3457 {
3458  PWINSTATION_OBJECT WinStaObject;
3459  PWND WndShell, WndListView;
3462  NTSTATUS Status;
3463  PTHREADINFO ti;
3464 
3465  TRACE("Enter NtUserSetShellWindowEx\n");
3467 
3468  if (!(WndShell = UserGetWindowObject(hwndShell)))
3469  {
3470  RETURN(FALSE);
3471  }
3472 
3473  if (!(WndListView = UserGetWindowObject(hwndListView)))
3474  {
3475  RETURN(FALSE);
3476  }
3477 
3479  UserMode,
3480  0,
3481  &WinStaObject,
3482  0);
3483 
3484  if (!NT_SUCCESS(Status))
3485  {
3487  RETURN( FALSE);
3488  }
3489 
3490  /*
3491  * Test if we are permitted to change the shell window.
3492  */
3493  if (WinStaObject->ShellWindow)
3494  {
3495  ObDereferenceObject(WinStaObject);
3496  RETURN( FALSE);
3497  }
3498 
3499  /*
3500  * Move shell window into background.
3501  */
3502  if (hwndListView && hwndListView != hwndShell)
3503  {
3504  /*
3505  * Disabled for now to get Explorer working.
3506  * -- Filip, 01/nov/2003
3507  */
3508 #if 0
3510 #endif
3511 
3512  if (WndListView->ExStyle & WS_EX_TOPMOST)
3513  {
3514  ObDereferenceObject(WinStaObject);
3515  RETURN( FALSE);
3516  }
3517  }
3518 
3519  if (WndShell->ExStyle & WS_EX_TOPMOST)
3520  {
3521  ObDereferenceObject(WinStaObject);
3522  RETURN( FALSE);
3523  }
3524 
3525  UserRefObjectCo(WndShell, &Ref);
3526  WndShell->state2 |= WNDS2_BOTTOMMOST;
3528 
3529  WinStaObject->ShellWindow = hwndShell;
3530  WinStaObject->ShellListView = hwndListView;
3531 
3532  ti = GetW32ThreadInfo();
3533  if (ti->pDeskInfo)
3534  {
3535  ti->pDeskInfo->hShellWindow = hwndShell;
3536  ti->pDeskInfo->spwndShell = WndShell;
3537  ti->pDeskInfo->spwndBkGnd = WndListView;
3538  ti->pDeskInfo->ppiShellProcess = ti->ppi;
3539  }
3540 
3542 
3543  UserDerefObjectCo(WndShell);
3544 
3545  ObDereferenceObject(WinStaObject);
3546  RETURN( TRUE);
3547 
3548 CLEANUP:
3549  TRACE("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
3550  UserLeave();
3551  END_CLEANUP;
3552 }
3553 
3554 // Fixes wine Win test_window_styles and todo tests...
3555 static BOOL FASTCALL
3557 {
3559  return TRUE;
3560  else if (!(ExStyle & WS_EX_STATICEDGE) && (Style & (WS_DLGFRAME | WS_THICKFRAME)))
3561  return TRUE;
3562  else
3563  return FALSE;
3564 }
3565 
3566 static LONG_PTR
3568 {
3569  PWND Window, Parent;
3570  PWINSTATION_OBJECT WindowStation;
3571  LONG_PTR OldValue;
3573 
3574  if (!(Window = UserGetWindowObject(hWnd)))
3575  {
3576  return( 0);
3577  }
3578 
3579  if ((INT)Index >= 0)
3580  {
3581  if ((Index + Size) > Window->cbwndExtra)
3582  {
3584  return( 0);
3585  }
3586 
3587 #ifdef _WIN64
3588  if (Size == sizeof(LONG))
3589  {
3590  OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
3591  *((LONG*)((PCHAR)(Window + 1) + Index)) = (LONG)NewValue;
3592  }
3593  else
3594 #endif
3595  {
3596  OldValue = *((LONG_PTR *)((PCHAR)(Window + 1) + Index));
3597  /*
3598  if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
3599  {
3600  OldValue = (LONG_PTR)IntSetWindowProc( Wnd, (WNDPROC)NewValue, Ansi);
3601  if (!OldValue) return 0;
3602  }
3603  */
3604  *((LONG_PTR*)((PCHAR)(Window + 1) + Index)) = NewValue;
3605  }
3606 
3607  }
3608  else
3609  {
3610 #ifdef _WIN64
3611  if (Size == sizeof(LONG))
3612  {
3613  if ((Index != GWL_STYLE) &&
3614  (Index != GWL_EXSTYLE) &&
3615  (Index != GWL_ID) &&
3616  (Index != GWL_USERDATA))
3617  {
3618  ERR("NtUserSetWindowLong(): Index requires pointer size: %lu\n", Index);
3620  return 0;
3621  }
3622  }
3623 #endif
3624 
3625  switch (Index)
3626  {
3627  case GWL_EXSTYLE: // LONG
3628  OldValue = (LONG) Window->ExStyle;
3629  Style.styleOld = OldValue;
3630  Style.styleNew = NewValue;
3631 
3632  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
3633 
3634  /*
3635  * Remove extended window style bit WS_EX_TOPMOST for shell windows.
3636  */
3637  WindowStation = Window->head.pti->rpdesk->rpwinstaParent;
3638  if(WindowStation)
3639  {
3640  if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
3641  Style.styleNew &= ~WS_EX_TOPMOST;
3642  }
3643  /* WS_EX_WINDOWEDGE depends on some other styles */
3644  if (IntCheckFrameEdge(Window->style, NewValue))
3645  Style.styleNew |= WS_EX_WINDOWEDGE;
3646  else
3647  Style.styleNew &= ~WS_EX_WINDOWEDGE;
3648 
3649  if (!(Window->ExStyle & WS_EX_LAYERED))
3650  {
3652  }
3653 
3654  Window->ExStyle = (DWORD)Style.styleNew;
3655 
3656  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
3657  break;
3658 
3659  case GWL_STYLE: // LONG
3660  OldValue = (LONG) Window->style;
3661  Style.styleOld = OldValue;
3662  Style.styleNew = NewValue;
3663 
3664  if (!bAlter)
3665  co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
3666 
3667  /* WS_CLIPSIBLINGS can't be reset on top-level windows */
3668  if (UserIsDesktopWindow(Window->spwndParent)) Style.styleNew |= WS_CLIPSIBLINGS;
3669  /* WS_MINIMIZE can't be reset */
3670  if (OldValue & WS_MINIMIZE) Style.styleNew |= WS_MINIMIZE;
3671  /* Fixes wine FIXME: changing WS_DLGFRAME | WS_THICKFRAME is supposed to change WS_EX_WINDOWEDGE too */
3672  if (IntCheckFrameEdge(NewValue, Window->ExStyle))
3673  Window->ExStyle |= WS_EX_WINDOWEDGE;
3674  else
3675  Window->ExStyle &= ~WS_EX_WINDOWEDGE;
3676 
3677  if ((OldValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3678  {
3679  if ((NewValue & (WS_CHILD | WS_POPUP)) != WS_CHILD)
3680  {
3682  ERR("IDMenu going null! %d\n",Window->IDMenu);
3683  Window->IDMenu = 0; // Window->spmenu = 0;
3684  }
3685  }
3686  else
3687  {
3688  if ((NewValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
3689  {
3690  PMENU pMenu = UserGetMenuObject(UlongToHandle(Window->IDMenu));
3691  Window->state &= ~WNDS_HASMENU;
3692  if (pMenu)
3693  {
3694  ERR("IDMenu released 0x%p\n",pMenu);
3695  // ROS may not hold a lock after setting menu to window. But it should!
3696  //IntReleaseMenuObject(pMenu);
3697  }
3698  }
3699  }
3700 
3701  if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
3702  {
3703  if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
3704  if (Style.styleNew & WS_VISIBLE) Window->head.pti->cVisWindows++;
3706  }
3707  Window->style = (DWORD)Style.styleNew;
3708 
3709  if (!bAlter)
3710  co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
3711  break;
3712 
3713  case GWLP_WNDPROC: // LONG_PTR
3714  {
3715  if ( Window->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
3716  Window->fnid & FNID_FREED)
3717  {
3719  return( 0);
3720  }
3721  OldValue = (LONG_PTR)IntSetWindowProc(Window,
3722  (WNDPROC)NewValue,
3723  Ansi);
3724  break;
3725  }
3726 
3727  case GWLP_HINSTANCE: // LONG_PTR
3728  OldValue = (LONG_PTR) Window->hModule;
3729  Window->hModule = (HINSTANCE) NewValue;
3730  break;
3731 
3732  case GWLP_HWNDPARENT: // LONG_PTR
3733  Parent = Window->spwndParent;
3734  if (Parent && (Parent->head.h == IntGetDesktopWindow()))
3735  OldValue = (LONG_PTR) IntSetOwner(Window->head.h, (HWND) NewValue);
3736  else
3737  OldValue = (LONG_PTR) co_UserSetParent(Window->head.h, (HWND) NewValue);
3738  break;
3739 
3740  case GWLP_ID: // LONG
3741  OldValue = (LONG) Window->IDMenu;
3742  Window->IDMenu = (UINT) NewValue;
3743  break;
3744 
3745  case GWLP_USERDATA: // LONG or LONG_PTR
3746  OldValue = Window->dwUserData;
3747  Window->dwUserData = NewValue;
3748  break;
3749 
3750  default:
3751  ERR("NtUserSetWindowLong(): Unsupported index %lu\n", Index);
3753  OldValue = 0;
3754  break;
3755  }
3756  }
3757 
3758  return( OldValue);
3759 }
3760 
3761 LONG FASTCALL
3763 {
3764  return (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
3765 }
3766 
3769 {
3770  return co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
3771 }
3772 
3773 /*
3774  * NtUserSetWindowLong
3775  *
3776  * The NtUserSetWindowLong function changes an attribute of the specified
3777  * window. The function also sets the 32-bit (long) value at the specified
3778  * offset into the extra window memory.
3779  *
3780  * Status
3781  * @implemented
3782  */
3783 
3784 LONG APIENTRY
3786 {
3787  LONG ret;
3788 
3790 
3791  if (hWnd == IntGetDesktopWindow())
3792  {
3794  UserLeave();
3795  return 0;
3796  }
3797 
3798  ret = (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
3799 
3800  UserLeave();
3801 
3802  return ret;
3803 }
3804 
3805 #ifdef _WIN64
3807 NtUserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
3808 {
3809  LONG_PTR ret;
3810 
3812 
3813  if (hWnd == IntGetDesktopWindow())
3814  {
3816  UserLeave();
3817  return 0;
3818  }
3819 
3820  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
3821 
3822  UserLeave();
3823 
3824  return ret;
3825 }
3826 #endif // _WIN64
3827 
3830 {
3831  LONG ret;
3832 
3834 
3835  if (hWnd == IntGetDesktopWindow())
3836  {
3838  UserLeave();
3839  return 0;
3840  }
3841 
3842  ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, FALSE, sizeof(LONG), TRUE);
3843 
3844  UserLeave();
3845 
3846  return ret;
3847 }
3848 
3849 
3850 /*
3851  * NtUserSetWindowWord
3852  *
3853  * Legacy function similar to NtUserSetWindowLong.
3854  *
3855  * Status
3856  * @implemented
3857  */
3858 
3859 WORD APIENTRY
3861 {
3862  PWND Window;
3863  WORD OldValue;
3865 
3866  TRACE("Enter NtUserSetWindowWord\n");
3868 
3869  if (hWnd == IntGetDesktopWindow())
3870  {
3872  RETURN( 0);
3873  }
3874 
3875  if (!(Window = UserGetWindowObject(hWnd)))
3876  {
3877  RETURN( 0);
3878  }
3879 
3880  switch (Index)
3881  {
3882  case GWL_ID:
3883  case GWL_HINSTANCE:
3884  case GWL_HWNDPARENT:
3886  default:
3887  if (Index < 0)
3888  {
3890  RETURN( 0);
3891  }
3892  }
3893 
3894  if ((ULONG)Index > (Window->cbwndExtra - sizeof(WORD)))
3895  {
3897  RETURN( 0);
3898  }
3899 
3900  OldValue = *((WORD *)((PCHAR)(Window + 1) + Index));
3901  *((WORD *)((PCHAR)(Window + 1) + Index)) = NewValue;
3902 
3903  RETURN( OldValue);
3904 
3905 CLEANUP:
3906  TRACE("Leave NtUserSetWindowWord, ret=%u\n", _ret_);
3907  UserLeave();
3908  END_CLEANUP;
3909 }
3910 
3911 /*
3912  QueryWindow based on KJK::Hyperion and James Tabor.
3913 
3914  0 = QWUniqueProcessId
3915  1 = QWUniqueThreadId
3916  2 = QWActiveWindow
3917  3 = QWFocusWindow
3918  4 = QWIsHung Implements IsHungAppWindow found
3919  by KJK::Hyperion.
3920 
3921  9 = QWKillWindow When I called this with hWnd ==
3922  DesktopWindow, it shutdown the system
3923  and rebooted.
3924 */
3925 /*
3926  * @implemented
3927  */
3930 {
3931 /* Console Leader Process CID Window offsets */
3932 #define GWLP_CONSOLE_LEADER_PID 0
3933 #define GWLP_CONSOLE_LEADER_TID 4
3934 
3935  PWND pWnd;
3936  DWORD_PTR Result;
3938 
3939  TRACE("Enter NtUserQueryWindow\n");
3940  UserEnterShared();
3941 
3942  if (!(pWnd = UserGetWindowObject(hWnd)))
3943  {
3944  RETURN( 0);
3945  }
3946 
3947  switch(Index)
3948  {
3950  {
3951  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
3953  {
3954  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
3955  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
3956  }
3957  else
3958  {
3960  }
3961  break;
3962  }
3963 
3965  {
3966  if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
3968  {
3969  // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
3970  Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
3971  }
3972  else
3973  {
3975  }
3976  break;
3977  }
3978 
3979  case QUERY_WINDOW_ACTIVE:
3980  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
3981  break;
3982 
3983  case QUERY_WINDOW_FOCUS:
3984  Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
3985  break;
3986 
3987  case QUERY_WINDOW_ISHUNG:
3988  Result = (DWORD_PTR)MsqIsHung(pWnd->head.pti, MSQ_HUNG);
3989  break;
3990 
3991  case QUERY_WINDOW_REAL_ID:
3992  Result = (DWORD_PTR)pWnd->head.pti->pEThread->Cid.UniqueProcess;
3993  break;
3994 
3996  Result = (pWnd->head.pti->MessageQueue == gpqForeground);
3997  break;
3998 
4000  ERR("QUERY_WINDOW_DEFAULT_IME: FIXME\n");
4001  Result = 0;
4002  break;
4003 
4005  ERR("QUERY_WINDOW_DEFAULT_ICONTEXT: FIXME\n");
4006  Result = 0;
4007  break;
4008 
4010  ERR("QUERY_WINDOW_ACTIVE_IME: FIXME\n");
4011  Result = 0;
4012  break;
4013 
4014  default:
4015  Result = 0;
4016  break;
4017  }
4018 
4019  RETURN( Result);
4020 
4021 CLEANUP:
4022  TRACE("Leave NtUserQueryWindow, ret=%u\n", _ret_);
4023  UserLeave();
4024  END_CLEANUP;
4025 }
4026 
4027 /*
4028  * @implemented
4029  */
4030 UINT APIENTRY
4032 {
4033  UNICODE_STRING SafeMessageName;
4034  NTSTATUS Status;
4035  UINT Ret;
4037 
4038  TRACE("Enter NtUserRegisterWindowMessage\n");
4040 
4041  if(MessageNameUnsafe == NULL)
4042  {
4044  RETURN( 0);
4045  }
4046 
4047  Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
4048  if(!NT_SUCCESS(Status))
4049  {
4051  RETURN( 0);
4052  }
4053 
4054  Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
4055  if (SafeMessageName.Buffer)
4056  ExFreePoolWithTag(SafeMessageName.Buffer, TAG_STRING);
4057  RETURN( Ret);
4058 
4059 CLEANUP:
4060  TRACE("Leave NtUserRegisterWindowMessage, ret=%u\n", _ret_);
4061  UserLeave();
4062  END_CLEANUP;
4063 }
4064 
4065 /*
4066  * @implemented
4067  */
4068 BOOL APIENTRY
4070  WORD fnID)
4071 {
4072  PWND Wnd;
4074 
4075  TRACE("Enter NtUserSetWindowFNID\n");
4077 
4078  if (!(Wnd = UserGetWindowObject(hWnd)))
4079  {
4080  RETURN( FALSE);
4081  }
4082 
4083  if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process())
4084  {
4086  RETURN( FALSE);
4087  }
4088 
4089  // From user land we only set these.
4090  if (fnID != FNID_DESTROY)
4091  {
4092  /* HACK: The minimum should be FNID_BUTTON, but menu code relies on this */
4093  if (fnID < FNID_FIRST || fnID > FNID_GHOST ||
4094  Wnd->fnid != 0)
4095  {
4097  RETURN( FALSE);
4098  }
4099  }
4100 
4101  Wnd->fnid |= fnID;
4102  RETURN( TRUE);
4103 
4104 CLEANUP:
4105  TRACE("Leave NtUserSetWindowFNID\n");
4106  UserLeave();
4107  END_CLEANUP;
4108 }
4109 
4110 BOOL APIENTRY
4111 DefSetText(PWND Wnd, PCWSTR WindowText)
4112 {
4114  BOOL Ret = FALSE;
4115 
4116  RtlInitUnicodeString(&UnicodeString, WindowText);
4117 
4118  if (UnicodeString.Length != 0)
4119  {
4120  if (Wnd->strName.MaximumLength > 0 &&
4121  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4122  {
4123  ASSERT(Wnd->strName.Buffer != NULL);
4124 
4125  Wnd->strName.Length = UnicodeString.Length;
4126  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4128  UnicodeString.Buffer,
4129  UnicodeString.Length);
4130  }
4131  else
4132  {
4133  PWCHAR buf;
4134  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4135  buf = Wnd->strName.Buffer;
4136  Wnd->strName.Buffer = NULL;
4137  if (buf != NULL)
4138  {
4139  DesktopHeapFree(Wnd->head.rpdesk, buf);
4140  }
4141 
4143  UnicodeString.Length + sizeof(UNICODE_NULL));
4144  if (Wnd->strName.Buffer != NULL)
4145  {
4146  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4148  UnicodeString.Buffer,
4149  UnicodeString.Length);
4150  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4151  Wnd->strName.Length = UnicodeString.Length;
4152  }
4153  else
4154  {
4156  goto Exit;
4157  }
4158  }
4159  }
4160  else
4161  {
4162  Wnd->strName.Length = 0;
4163  if (Wnd->strName.Buffer != NULL)
4164  Wnd->strName.Buffer[0] = L'\0';
4165  }
4166 
4167  // FIXME: HAX! Windows does not do this in here!
4168  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4169  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4170  /* Send shell notifications */
4171  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4172  {
4173  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
4174  }
4175 
4176  Ret = TRUE;
4177 Exit:
4179  return Ret;
4180 }
4181 
4182 /*
4183  * NtUserDefSetText
4184  *
4185  * Undocumented function that is called from DefWindowProc to set
4186  * window text.
4187  *
4188  * Status
4189  * @implemented
4190  */
4191 BOOL APIENTRY
4193 {
4194  PWND Wnd;
4195  LARGE_STRING SafeText;
4197  BOOL Ret = TRUE;
4198 
4199  TRACE("Enter NtUserDefSetText\n");
4200 
4201  if (WindowText != NULL)
4202  {
4203  _SEH2_TRY
4204  {
4205  SafeText = ProbeForReadLargeString(WindowText);
4206  }
4208  {
4209  Ret = FALSE;
4211  }
4212  _SEH2_END;
4213 
4214  if (!Ret)
4215  return FALSE;
4216  }
4217  else
4218  return TRUE;
4219 
4221 
4222  if(!(Wnd = UserGetWindowObject(hWnd)))
4223  {
4224  UserLeave();
4225  return FALSE;
4226  }
4227 
4228  // ReactOS uses Unicode and not mixed. Up/Down converting will take time.
4229  // Brought to you by: The Wine Project! Dysfunctional Thought Processes!
4230  // Now we know what the bAnsi is for.
4232  if (SafeText.Buffer)
4233  {
4234  _SEH2_TRY
4235  {
4236  if (SafeText.bAnsi)
4237  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(CHAR));
4238  else
4239  ProbeForRead(SafeText.Buffer, SafeText.Length, sizeof(WCHAR));
4240  Ret = RtlLargeStringToUnicodeString(&UnicodeString, &SafeText);
4241  }
4243  {
4244  Ret = FALSE;
4246  }
4247  _SEH2_END;
4248  if (!Ret) goto Exit;
4249  }
4250 
4251  if (UnicodeString.Length != 0)
4252  {
4253  if (Wnd->strName.MaximumLength > 0 &&
4254  UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
4255  {
4256  ASSERT(Wnd->strName.Buffer != NULL);
4257 
4258  Wnd->strName.Length = UnicodeString.Length;
4259  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4261  UnicodeString.Buffer,
4262  UnicodeString.Length);
4263  }
4264  else
4265  {
4266  PWCHAR buf;
4267  Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
4268  buf = Wnd->strName.Buffer;
4269  Wnd->strName.Buffer = NULL;
4270  if (buf != NULL)
4271  {
4272  DesktopHeapFree(Wnd->head.rpdesk, buf);
4273  }
4274 
4276  UnicodeString.Length + sizeof(UNICODE_NULL));
4277  if (Wnd->strName.Buffer != NULL)
4278  {
4279  Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
4281  UnicodeString.Buffer,
4282  UnicodeString.Length);
4283  Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
4284  Wnd->strName.Length = UnicodeString.Length;
4285  }
4286  else
4287  {
4289  Ret = FALSE;
4290  goto Exit;
4291  }
4292  }
4293  }
4294  else
4295  {
4296  Wnd->strName.Length = 0;
4297  if (Wnd->strName.Buffer != NULL)
4298  Wnd->strName.Buffer[0] = L'\0';
4299  }
4300 
4301  // FIXME: HAX! Windows does not do this in here!
4302  // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
4303  // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
4304  /* Send shell notifications */
4305  if (!Wnd->spwndOwner && !IntGetParent(Wnd))
4306  {
4307  co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing?
4308  }
4309 
4310  Ret = TRUE;
4311 Exit:
4313  TRACE("Leave NtUserDefSetText, ret=%i\n", Ret);
4314  UserLeave();
4315  return Ret;
4316 }
4317 
4318 /*
4319  * NtUserInternalGetWindowText
4320  *
4321  * Status
4322  * @implemented
4323  */
4324 
4325 INT APIENTRY
4327 {
4328  PWND Wnd;
4329  NTSTATUS Status;
4330  INT Result;
4332 
4333  TRACE("Enter NtUserInternalGetWindowText\n");
4334  UserEnterShared();
4335 
4336  if(lpString && (nMaxCount <= 1))
4337  {
4339  RETURN( 0);
4340  }
4341 
4342  if(!(Wnd = UserGetWindowObject(hWnd)))
4343  {
4344  RETURN( 0);
4345  }
4346 
4347  Result = Wnd->strName.Length / sizeof(WCHAR);
4348  if(lpString)
4349  {
4350  const WCHAR Terminator = L'\0';
4351  INT Copy;
4352  WCHAR *Buffer = (WCHAR*)lpString;
4353 
4354  Copy = min(nMaxCount - 1, Result);
4355  if(Copy > 0)
4356  {
4357  Status = MmCopyToCaller(Buffer, Wnd->strName.Buffer, Copy * sizeof(WCHAR));
4358  if(!NT_SUCCESS(Status))
4359  {
4361  RETURN( 0);
4362  }
4363  Buffer += Copy;
4364  }
4365 
4366  Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
4367  if(!NT_SUCCESS(Status))
4368  {
4370  RETURN( 0);
4371  }
4372 
4373  Result = Copy;
4374  }
4375 
4376  RETURN( Result);
4377 
4378 CLEANUP:
4379  TRACE("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
4380  UserLeave();
4381  END_CLEANUP;
4382 }
4383 
4384 /*
4385  API Call
4386 */
4387 BOOL
4388 FASTCALL
4389 IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
4390 {
4391  int count = 0;
4392  PWND pWnd;
4393  HWND *win_array;
4394 
4395 // ASSERT(OwnerWnd);
4396 
4397  TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
4398 
4399  /* NOTE: Popups are not children */
4400  win_array = IntWinListOwnedPopups(OwnerWnd);
4401 
4402  if (!win_array)
4403  return TRUE;
4404 
4405  while (win_array[count])
4406  count++;
4407  while (--count >= 0)
4408  {
4409  if (!(pWnd = ValidateHwndNoErr( win_array[count] )))
4410  continue;
4411  if (pWnd->spwndOwner != OwnerWnd)
4412  continue;
4413 
4414  if (fShow)
4415  {
4416  if (pWnd->state & WNDS_HIDDENPOPUP)
4417  {
4418  /* In Windows, ShowOwnedPopups(TRUE) generates
4419  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
4420  * regardless of the state of the owner
4421  */
4423  pWnd->state &= ~WNDS_HIDDENPOPUP;
4424  continue;
4425  }
4426  }
4427  else
4428  {
4429  if (pWnd->style & WS_VISIBLE)
4430  {
4431  /* In Windows, ShowOwnedPopups(FALSE) generates
4432  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
4433  * regardless of the state of the owner
4434  */
4436  pWnd->state |= WNDS_HIDDENPOPUP;
4437  continue;
4438  }
4439  }
4440  }
4442  TRACE("Leave ShowOwnedPopups\n");
4443  return TRUE;
4444 }
4445 
4446 /* 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:3456
#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:2426
#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:101
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:3148
#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:57
#define IN
Definition: typedefs.h:39
GLint GLint GLsizei width
Definition: gl.h:1546
#define LONG_PTR
Definition: treelist.c:79
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION _In_ ULONG _In_ SIZE_T _In_ ULONG _In_ USHORT Depth
Definition: exfuncs.h:814
DWORD ExStyle
Definition: ntuser.h:668
#define HOOKID_TO_FLAG(HookId)
Definition: hook.h:5
LONG APIENTRY NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
Definition: window.c:3785
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:2803
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1155
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:3984
LRESULT co_UserFreeWindow(PWND Window, PPROCESSINFO ProcessData, PTHREADINFO ThreadData, BOOLEAN SendMessages)
Definition: window.c:546
#define GETPFNSERVER(fnid)
Definition: ntuser.h:870
#define QUERY_WINDOW_UNIQUE_PROCESS_ID
Definition: ntuser.h:2802
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:1979
struct _DESKTOP * rpdesk
Definition: ntuser.h:189
BOOL FASTCALL MsqIsHung(PTHREADINFO pti, DWORD TimeOut)
Definition: msgqueue.c:2194
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:3208
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:3202
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:2808
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:2369
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
BOOL APIENTRY DefSetText(PWND Wnd, PCWSTR WindowText)
Definition: window.c:4111
#define SW_HIDE
Definition: winuser.h:762
#define CURSORF_FROMRESOURCE
Definition: ntuser.h:1148
LIST_ENTRY WindowListHead
Definition: win32.h:150
HWND FASTCALL UserGetActiveWindow(VOID)
Definition: focus.c:1311
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:2950
#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:2807
UINT wState
Definition: comctl32.h:142
#define WNDS_SENDNCPAINT
Definition: ntuser.h:584
#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:3983
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
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:1045
struct _WND::@4239 InternalPos
#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:307
#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:19
struct _WND WND
#define MSQ_HUNG
Definition: msgqueue.h:3
HWND hWndEdit
Definition: comctl32.h:140
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:4389
#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:873
#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
LB_DESCR * pLBiv
Definition: window.c:3311
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:145
#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:728
#define GetWin32ClientInfo()
Definition: ntuser.h:320
#define HWND_MESSAGE
Definition: winuser.h:1196
uint16_t * PWCHAR
Definition: typedefs.h:56
LONG left
Definition: windef.h:306
#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
#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:258
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:308
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:3929
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:58
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 RETURN(x)
#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
DWORD dwLayout
Definition: win32.h:271
_SEH2_TRY
Definition: create.c:4226
static __inline PVOID DesktopHeapAddressToUser(PVOID lpMem)
Definition: desktop.h:327
#define SWP_HIDEWINDOW
Definition: winuser.h:1226
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:779
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:2951
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:3192
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:28
#define ICLS_LISTBOX
Definition: ntuser.h:876
DWORD CSF_flags
Definition: ntuser.h:541
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HINSTANCE hInstance
Definition: charmap.c:20
#define WS_EX_MDICHILD
Definition: winuser.h:394
#define CSF_CACHEDSMICON
Definition: ntuser.h:530
LONG_PTR FASTCALL co_UserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
Definition: window.c:3768
#define QUERY_WINDOW_FOCUS
Definition: ntuser.h:2805
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
UINT style
Definition: ntuser.h:548
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:230
VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
Definition: window.c:937
NTSTATUS FASTCALL IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest, PUNICODE_STRING Source)
Definition: misc.c:655
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define TIF_CSRSSTHREAD
Definition: ntuser.h:243
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
BOOL FASTCALL co_IntDestroyCaret(PTHREADINFO Win32Thread)
Definition: caret.c:164
#define WS_MINIMIZE
Definition: pedump.c:622
DWORD fnid
Definition: ntuser.h:673
#define WM_PARENTNOTIFY
Definition: winuser.h:1785
unsigned int BOOL
Definition: ntddk_ex.h:94
static LONG_PTR co_IntSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi, ULONG Size, BOOL bAlter)
Definition: window.c:3567
#define WOC_DELETE
Definition: winddi.h:1269
#define TAG_STRING
Definition: oslist.h:22
long LONG
Definition: pedump.c:60
#define CURSORF_LRSHARED
Definition: ntuser.h:1150
#define FNID_DESKTOP
Definition: ntuser.h:824
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:38
#define HCBT_DESTROYWND
Definition: winuser.h:59
void FASTCALL DceFreeWindowDCE(PWND)
Definition: windc.c:685
HMENU APIENTRY co_IntCallLoadMenu(HINSTANCE hModule, PUNICODE_STRING pMenuName)
Definition: callback.c:903
#define GA_PARENT
Definition: winuser.h:2763
#define FNID_DIALOG
Definition: ntuser.h:831
long top
Definition: polytest.cpp:53
#define ERROR_INVALID_MENU_HANDLE
Definition: winerror.h:882
BOOL FASTCALL UserUpdateUiState(PWND Wnd, WPARAM wParam)
Definition: window.c:16
#define STATE_SYSTEM_PRESSED
Definition: winuser.h:2840
#define CHILDID_SELF
Definition: winable.h:14
#define PsGetCurrentProcess