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