ReactOS  0.4.15-dev-4927-gfe8f806
windc.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Win32k subsystem
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: win32ss/user/ntuser/windc.c
5  * PURPOSE: Window DC management
6  * COPYRIGHT: Copyright 2007 ReactOS Team
7  */
8 
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserDce);
11 
12 /* GLOBALS *******************************************************************/
13 
14 /* NOTE: I think we should store this per window station (including GDI objects) */
15 /* Answer: No, use the DCE pMonitor to compare with! */
16 
18 static INT DCECount = 0; // Count of DCE in system.
19 
20 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
21  DCX_NORESETATTRS | DCX_LOCKWINDOWUPDATE | \
22  DCX_LAYEREDWIN | DCX_CACHE | DCX_WINDOW | \
23  DCX_PARENTCLIP)
24 
25 /* FUNCTIONS *****************************************************************/
26 
27 CODE_SEG("INIT")
29 NTAPI
31 {
33  return STATUS_SUCCESS;
34 }
35 
36 //
37 // This should be moved to dc.c or dcutil.c.
38 //
41 {
42  UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
43 
45  KeBugCheckEx(VIDEO_DRIVER_INIT_FAILURE, 0, 0, 0, USER_VERSION);
46 
47  return IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
48 }
49 
50 /* Returns the DCE pointer from the HDC handle */
51 DCE*
54 {
55  PLIST_ENTRY ListEntry;
56  DCE* dce;
57 
58  ListEntry = LEDce.Flink;
59  while (ListEntry != &LEDce)
60  {
61  dce = CONTAINING_RECORD(ListEntry, DCE, List);
62  ListEntry = ListEntry->Flink;
63  if (dce->hDC == hdc)
64  return dce;
65  }
66 
67  return NULL;
68 }
69 
70 static
73 {
74  PREGION Rgn;
76  0 == (Flags & DCX_WINDOW),
77  0 != (Flags & DCX_CLIPCHILDREN),
78  0 != (Flags & DCX_CLIPSIBLINGS));
79  /* Caller expects a non-null region */
80  if (!Rgn)
81  Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
82  return Rgn;
83 }
84 
87 {
88  PDCE pDce;
89 
91  if(!pDce)
92  return NULL;
93 
94  pDce->hDC = DceCreateDisplayDC();
95  if (!pDce->hDC)
96  {
98  return NULL;
99  }
100  DCECount++;
101  TRACE("Alloc DCE's! %d\n",DCECount);
102  pDce->hwndCurrent = (Window ? Window->head.h : NULL);
103  pDce->pwndOrg = Window;
104  pDce->pwndClip = Window;
105  pDce->hrgnClip = NULL;
106  pDce->hrgnClipPublic = NULL;
107  pDce->hrgnSavedVis = NULL;
108  pDce->ppiOwner = NULL;
109 
110  InsertTailList(&LEDce, &pDce->List);
111 
112  DCU_SetDcUndeletable(pDce->hDC);
113 
114  if (Type == DCE_WINDOW_DC || Type == DCE_CLASS_DC) // Window DCE have ownership.
115  {
116  pDce->ptiOwner = GetW32ThreadInfo();
117  }
118  else
119  {
120  TRACE("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %p\n", pDce->hDC);
122  pDce->ptiOwner = NULL;
123  }
124 
125  if (Type == DCE_CACHE_DC)
126  {
127  pDce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;
128  }
129  else
130  {
131  pDce->DCXFlags = DCX_DCEBUSY;
132  if (Window)
133  {
134  if (Type == DCE_WINDOW_DC)
135  {
136  if (Window->style & WS_CLIPCHILDREN) pDce->DCXFlags |= DCX_CLIPCHILDREN;
137  if (Window->style & WS_CLIPSIBLINGS) pDce->DCXFlags |= DCX_CLIPSIBLINGS;
138  }
139  }
140  }
141  return(pDce);
142 }
143 
144 static VOID APIENTRY
146  HDC hDC,
147  ULONG Flags,
148  BOOL SetClipOrigin)
149 {
150  RECTL rect = {0,0,0,0};
151 
152  if (Window)
153  {
154  if (Flags & DCX_WINDOW)
155  {
156  rect = Window->rcWindow;
157  }
158  else
159  {
160  rect = Window->rcClient;
161  }
162  }
163 
164  /* Set DC Origin and Window Rectangle */
165  GreSetDCOrg( hDC, rect.left, rect.top, &rect);
166 }
167 
168 
169 static VOID FASTCALL
171 {
173 
174  if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
175  {
176  Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
177  }
178  else if (Dce->hrgnClip != NULL)
179  {
181  }
182 
183  Dce->hrgnClip = NULL;
184 
185  /* Make it dirty so that the vis rgn gets recomputed next time */
186  Dce->DCXFlags |= DCX_DCEDIRTY;
188 }
189 
190 VOID
191 FASTCALL
193 {
194  PREGION RgnVisible = NULL;
195  ULONG DcxFlags;
197 
198  if (Flags & DCX_PARENTCLIP)
199  {
200  PWND Parent;
201 
202  Parent = Window->spwndParent;
203  if (!Parent)
204  {
205  RgnVisible = NULL;
206  goto noparent;
207  }
208 
209  if (Parent->style & WS_CLIPSIBLINGS)
210  {
211  DcxFlags = DCX_CLIPSIBLINGS |
213  }
214  else
215  {
217  }
218  RgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->head.h, Flags);
219  }
220  else if (Window == NULL)
221  {
223  if (NULL != DesktopWindow)
224  {
225  RgnVisible = IntSysCreateRectpRgnIndirect(&DesktopWindow->rcWindow);
226  }
227  else
228  {
229  RgnVisible = NULL;
230  }
231  }
232  else
233  {
234  RgnVisible = DceGetVisRgn(Window, Flags, 0, 0);
235  }
236 
237 noparent:
238  if (Flags & DCX_INTERSECTRGN)
239  {
240  PREGION RgnClip = NULL;
241 
242  if (Dce->hrgnClip != NULL)
243  RgnClip = REGION_LockRgn(Dce->hrgnClip);
244 
245  if (RgnClip)
246  {
247  IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND);
248  REGION_UnlockRgn(RgnClip);
249  }
250  else
251  {
252  if (RgnVisible != NULL)
253  {
254  REGION_Delete(RgnVisible);
255  }
256  RgnVisible = IntSysCreateRectpRgn(0, 0, 0, 0);
257  }
258  }
259  else if ((Flags & DCX_EXCLUDERGN) && Dce->hrgnClip != NULL)
260  {
261  PREGION RgnClip = REGION_LockRgn(Dce->hrgnClip);
262  IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_DIFF);
263  REGION_UnlockRgn(RgnClip);
264  }
265 
266  Dce->DCXFlags &= ~DCX_DCEDIRTY;
267  GdiSelectVisRgn(Dce->hDC, RgnVisible);
268  /* Tell GDI driver */
269  if (Window)
271 
272  if (RgnVisible != NULL)
273  {
274  REGION_Delete(RgnVisible);
275  }
276 }
277 
278 static INT FASTCALL
280 {
282  {
283  return 0;
284  }
285 
286  /* Restore previous visible region */
287  if (EndPaint)
288  {
289  DceUpdateVisRgn(dce, dce->pwndOrg, dce->DCXFlags);
290  }
291 
292  if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
293  ((dce->DCXFlags & DCX_CACHE) || EndPaint))
294  {
295  DceDeleteClipRgn(dce);
296  }
297 
298  if (dce->DCXFlags & DCX_CACHE)
299  {
300  if (!(dce->DCXFlags & DCX_NORESETATTRS))
301  {
302  // Clean the DC
303  if (!IntGdiCleanDC(dce->hDC)) return 0;
304 
305  if (dce->DCXFlags & DCX_DCEDIRTY)
306  {
307  /* Don't keep around invalidated entries
308  * because SetDCState() disables hVisRgn updates
309  * by removing dirty bit. */
310  dce->hwndCurrent = 0;
311  dce->pwndOrg = NULL;
312  dce->pwndClip = NULL;
313  dce->DCXFlags &= DCX_CACHE;
314  dce->DCXFlags |= DCX_DCEEMPTY;
315  }
316  }
317  dce->DCXFlags &= ~DCX_DCEBUSY;
318  TRACE("Exit!!!!! DCX_CACHE!!!!!! hDC-> %p \n", dce->hDC);
319  if (!GreSetDCOwner(dce->hDC, GDI_OBJ_HMGR_NONE))
320  return 0;
321  dce->ptiOwner = NULL; // Reset ownership.
322  dce->ppiOwner = NULL;
323 
324 #if 0 // Need to research and fix before this is a "growing" issue.
325  if (++DCECache > 32)
326  {
327  ListEntry = LEDce.Flink;
328  while (ListEntry != &LEDce)
329  {
330  pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
331  ListEntry = ListEntry->Flink;
332  if (!(pDCE->DCXFlags & DCX_DCEBUSY))
333  { /* Free the unused cache DCEs. */
334  DceFreeDCE(pDCE, TRUE);
335  }
336  }
337  }
338 #endif
339  }
340  return 1; // Released!
341 }
342 
343 
346 {
347  PWND Parent;
348  ULONG DcxFlags;
349  DCE* Dce = NULL;
350  BOOL UpdateClipOrigin = FALSE;
351  BOOL bUpdateVisRgn = TRUE;
352  HDC hDC = NULL;
353  PPROCESSINFO ppi;
354  PLIST_ENTRY ListEntry;
355 
356  if (NULL == Wnd)
357  {
358  Flags &= ~DCX_USESTYLE;
359  Flags |= DCX_CACHE;
360  }
361 
363 
364  // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set.
365  if (Flags & DCX_USESTYLE)
366  {
368  if (!(Flags & DCX_WINDOW)) // Not window rectangle
369  {
370  if (Wnd->pcls->style & CS_PARENTDC)
371  {
373  }
374 
375  if (!(Flags & DCX_CACHE) && // Not on the cheap wine list.
376  !(Wnd->pcls->style & CS_OWNDC) )
377  {
378  if (!(Wnd->pcls->style & CS_CLASSDC))
379  // The window is not POWNED or has any CLASS, so we are looking for cheap wine.
380  Flags |= DCX_CACHE;
381  else
382  {
383  if (Wnd->pcls->pdce) hDC = ((PDCE)Wnd->pcls->pdce)->hDC;
384  TRACE("We have CLASS!!\n");
385  }
386  }
387 
388  if (Wnd->style & WS_CLIPSIBLINGS)
389  {
391  }
392 
393  if (Wnd->style & WS_CLIPCHILDREN &&
394  !(Wnd->style & WS_MINIMIZE))
395  {
397  }
398  /* If minized with icon in the set, we are forced to be cheap! */
399  if (Wnd->style & WS_MINIMIZE && Wnd->pcls->spicn)
400  {
401  Flags |= DCX_CACHE;
402  }
403  }
404  else
405  {
406  if (Wnd->style & WS_CLIPSIBLINGS) Flags |= DCX_CLIPSIBLINGS;
407  Flags |= DCX_CACHE;
408  }
409  }
410 
412 
414  {
415  Flags |= DCX_CACHE;
417  }
418 
419  Parent = (Wnd ? Wnd->spwndParent : NULL);
420 
421  if (NULL == Wnd || !(Wnd->style & WS_CHILD) || NULL == Parent)
422  {
423  Flags &= ~DCX_PARENTCLIP;
425  }
426 
427  /* It seems parent clip is ignored when clipping siblings or children */
429 
430  if (Flags & DCX_PARENTCLIP)
431  {
432  if ((Wnd->style & WS_VISIBLE) &&
433  (Parent->style & WS_VISIBLE))
434  {
436  if (Parent->style & WS_CLIPSIBLINGS)
437  {
439  }
440  }
441  }
442 
443  // Window nz, check to see if we still own this or it is just cheap wine tonight.
444  if (!(Flags & DCX_CACHE))
445  {
446  if ( Wnd->head.pti != GetW32ThreadInfo())
447  Flags |= DCX_CACHE; // Ah~ Not Powned! Forced to be cheap~
448  }
449 
450  DcxFlags = Flags & DCX_CACHECOMPAREMASK;
451 
452  if (Flags & DCX_CACHE)
453  { // Scan the cheap wine list for our match.
454  DCE* DceEmpty = NULL;
455  DCE* DceUnused = NULL;
457  ListEntry = LEDce.Flink;
458  while (ListEntry != &LEDce)
459  {
460  Dce = CONTAINING_RECORD(ListEntry, DCE, List);
461  ListEntry = ListEntry->Flink;
462 //
463 // The way I understand this, you can have more than one DC per window.
464 // Only one Owned if one was requested and saved and one Cached.
465 //
466  if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)
467  {
468  DceUnused = Dce;
469  if (Dce->DCXFlags & DCX_DCEEMPTY)
470  {
471  DceEmpty = Dce;
472  }
473  else if (Dce->hwndCurrent == (Wnd ? Wnd->head.h : NULL) &&
474  ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))
475  {
476  UpdateClipOrigin = TRUE;
477  break;
478  }
479  }
480  Dce = NULL; // Loop issue?
481  }
483 
484  Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
485 
486  if (Dce == NULL)
487  {
488  Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
489  }
490  if (Dce == NULL) return NULL;
491 
492  Dce->hwndCurrent = (Wnd ? Wnd->head.h : NULL);
493  Dce->pwndOrg = Dce->pwndClip = Wnd;
494  }
495  else // If we are here, we are POWNED or having CLASS.
496  {
498  ListEntry = LEDce.Flink;
499  while (ListEntry != &LEDce)
500  {
501  Dce = CONTAINING_RECORD(ListEntry, DCE, List);
502  ListEntry = ListEntry->Flink;
503 
504  // Skip Cache DCE entries.
505  if (!(Dce->DCXFlags & DCX_CACHE))
506  {
507  // Check for Window handle than HDC match for CLASS.
508  if (Dce->hwndCurrent == Wnd->head.h)
509  {
510  bUpdateVisRgn = FALSE;
511  break;
512  }
513  else if (Dce->hDC == hDC) break;
514  }
515  Dce = NULL; // Loop issue?
516  }
518 
519  if (Dce == NULL)
520  {
521  return(NULL);
522  }
523 
526  {
527  DceDeleteClipRgn(Dce);
528  }
529  }
530 // First time use hax, need to use DceAllocDCE during window display init.
531  if (NULL == Dce)
532  {
533  return(NULL);
534  }
535 
536  if (!GreIsHandleValid(Dce->hDC))
537  {
538  ERR("FIXME: Got DCE with invalid hDC! %p\n", Dce->hDC);
539  Dce->hDC = DceCreateDisplayDC();
540  /* FIXME: Handle error */
541  }
542 
543  Dce->DCXFlags = Flags | DCX_DCEBUSY;
544 
545  /*
546  * Bump it up! This prevents the random errors in wine dce tests and with
547  * proper bits set in DCX_CACHECOMPAREMASK.
548  * Reference:
549  * http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html
550  * http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html
551  */
552  RemoveEntryList(&Dce->List);
553  InsertHeadList(&LEDce, &Dce->List);
554 
555  /* Introduced in rev 6691 and modified later. */
556  if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion )
557  {
560  ClipRegion = Wnd->hrgnUpdate;
561  bUpdateVisRgn = TRUE;
562  }
563 
564  if (ClipRegion == HRGN_WINDOW)
565  {
566  if (!(Flags & DCX_WINDOW))
567  {
569  Wnd->rcClient.left,
570  Wnd->rcClient.top,
571  Wnd->rcClient.right,
572  Wnd->rcClient.bottom);
573  }
574  else
575  {
577  Wnd->rcWindow.left,
578  Wnd->rcWindow.top,
579  Wnd->rcWindow.right,
580  Wnd->rcWindow.bottom);
581  }
582  Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
583  bUpdateVisRgn = TRUE;
584  }
585  else if (ClipRegion != NULL)
586  {
587  if (Dce->hrgnClip != NULL)
588  {
589  ERR("Should not be called!!\n");
591  Dce->hrgnClip = NULL;
592  }
593  Dce->hrgnClip = ClipRegion;
594  bUpdateVisRgn = TRUE;
595  }
596 
597  if (IntGdiSetHookFlags(Dce->hDC, DCHF_VALIDATEVISRGN)) bUpdateVisRgn = TRUE;
598 
599  DceSetDrawable(Wnd, Dce->hDC, Flags, UpdateClipOrigin);
600 
601  if (bUpdateVisRgn) DceUpdateVisRgn(Dce, Wnd, Flags);
602 
603  if (Dce->DCXFlags & DCX_CACHE)
604  {
605  TRACE("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %p\n", Dce->hDC);
606  // Need to set ownership so Sync dcattr will work.
608  Dce->ptiOwner = GetW32ThreadInfo(); // Set the temp owning
609  }
610 
611  if ( Wnd &&
612  Wnd->ExStyle & WS_EX_LAYOUTRTL &&
613  !(Flags & DCX_KEEPLAYOUT) )
614  {
615  NtGdiSetLayout(Dce->hDC, -1, LAYOUT_RTL);
616  }
617 
618  if (Dce->DCXFlags & DCX_PROCESSOWNED)
619  {
621  ppi->W32PF_flags |= W32PF_OWNDCCLEANUP;
622  Dce->ptiOwner = NULL;
623  Dce->ppiOwner = ppi;
624  }
625 
626  return(Dce->hDC);
627 }
628 
629 /***********************************************************************
630  * DceFreeDCE
631  */
632 void FASTCALL
634 {
635  BOOL Hit = FALSE;
636 
637  ASSERT(pdce != NULL);
638  if (NULL == pdce) return;
639 
640  pdce->DCXFlags |= DCX_INDESTROY;
641 
642  if (Force &&
644  {
645  TRACE("Change ownership for DCE! -> %p\n" , pdce);
646  // NOTE: Windows sets W32PF_OWNDCCLEANUP and moves on.
647  if (GreIsHandleValid(pdce->hDC))
648  {
650  }
651  else
652  {
653  ERR("Attempted to change ownership of an DCEhDC %p currently being destroyed!!!\n",
654  pdce->hDC);
655  Hit = TRUE;
656  }
657  }
658  else
659  {
662  }
663 
664  if (!Hit) IntGdiDeleteDC(pdce->hDC, TRUE);
665 
666  if (pdce->hrgnClip && !(pdce->DCXFlags & DCX_KEEPCLIPRGN))
667  {
668  GreDeleteObject(pdce->hrgnClip);
669  pdce->hrgnClip = NULL;
670  }
671 
672  RemoveEntryList(&pdce->List);
673 
675 
676  DCECount--;
677  TRACE("Freed DCE's! %d \n", DCECount);
678 }
679 
680 /***********************************************************************
681  * DceFreeWindowDCE
682  *
683  * Remove owned DCE and reset unreleased cache DCEs.
684  */
685 void FASTCALL
687 {
688  PDCE pDCE;
689  PLIST_ENTRY ListEntry;
690 
691  if (DCECount <= 0)
692  {
693  ERR("FreeWindowDCE No Entry! %d\n",DCECount);
694  return;
695  }
696 
697  ListEntry = LEDce.Flink;
698  while (ListEntry != &LEDce)
699  {
700  pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
701  ListEntry = ListEntry->Flink;
702  if ( pDCE->hwndCurrent == Window->head.h &&
703  !(pDCE->DCXFlags & DCX_DCEEMPTY) )
704  {
705  if (!(pDCE->DCXFlags & DCX_CACHE)) /* Owned or Class DCE */
706  {
707  if (Window->pcls->style & CS_CLASSDC) /* Test Class first */
708  {
709  if (pDCE->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) /* Class DCE */
710  DceDeleteClipRgn(pDCE);
711  // Update and reset Vis Rgn and clear the dirty bit.
712  // Should release VisRgn than reset it to default.
713  DceUpdateVisRgn(pDCE, Window, pDCE->DCXFlags);
715  pDCE->hwndCurrent = 0;
716  pDCE->pwndOrg = pDCE->pwndClip = NULL;
717 
718  TRACE("POWNED DCE going Cheap!! DCX_CACHE!! hDC-> %p \n",
719  pDCE->hDC);
720  if (!GreSetDCOwner( pDCE->hDC, GDI_OBJ_HMGR_NONE))
721  {
722  ERR("Fail Owner Switch hDC-> %p \n", pDCE->hDC);
723  break;
724  }
725  /* Do not change owner so thread can clean up! */
726  }
727  else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */
728  {
729  DceFreeDCE(pDCE, FALSE);
730  continue;
731  }
732  else
733  {
734  ERR("Not POWNED or CLASSDC hwndCurrent -> %p \n",
735  pDCE->hwndCurrent);
736  // ASSERT(FALSE); /* bug 5320 */
737  }
738  }
739  else
740  {
741  if (pDCE->DCXFlags & DCX_DCEBUSY) /* Shared cache DCE */
742  {
743  /* FIXME: AFAICS we are doing the right thing here so
744  * this should be a TRACE. But this is best left as an ERR
745  * because the 'application error' is likely to come from
746  * another part of Wine (i.e. it's our fault after all).
747  * We should change this to TRACE when ReactOS is more stable
748  * (for 1.0?).
749  */
750  ERR("[%p] GetDC() without ReleaseDC()!\n", Window->head.h);
751  DceReleaseDC(pDCE, FALSE);
752  }
753  pDCE->DCXFlags |= DCX_DCEEMPTY;
754  pDCE->hwndCurrent = 0;
755  pDCE->pwndOrg = pDCE->pwndClip = NULL;
756  }
757  }
758  }
759 }
760 
761 void FASTCALL
763 {
764  PDCE pDCE;
765  PLIST_ENTRY ListEntry;
766 
767  ListEntry = LEDce.Flink;
768  while (ListEntry != &LEDce)
769  {
770  pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
771  ListEntry = ListEntry->Flink;
772  if (pDCE == pdceClass)
773  {
774  DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
775  }
776  }
777 }
778 
779 void FASTCALL
781 {
782  PDCE pDCE;
783  PLIST_ENTRY ListEntry;
784 
785  ListEntry = LEDce.Flink;
786  while (ListEntry != &LEDce)
787  {
788  pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
789  ListEntry = ListEntry->Flink;
790  if (pDCE->ptiOwner == pti)
791  {
792  if (pDCE->DCXFlags & DCX_CACHE)
793  {
794  DceFreeDCE(pDCE, TRUE);
795  }
796  }
797  }
798 }
799 
802 {
803  PDCE pDCE;
804  PLIST_ENTRY ListEntry;
805 
806  ListEntry = LEDce.Flink;
807  while (ListEntry != &LEDce)
808  {
809  pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
810  ListEntry = ListEntry->Flink;
811  DceFreeDCE(pDCE, TRUE);
812  }
813 }
814 
817 {
818  DCE *pDCE;
819  PDC dc;
820  PWND CurrentWindow;
821  INT DeltaX;
822  INT DeltaY;
823  PLIST_ENTRY ListEntry;
824 
825  if (NULL == Window)
826  {
827  return;
828  }
829 
830  ListEntry = LEDce.Flink;
831  while (ListEntry != &LEDce)
832  {
833  pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
834  ListEntry = ListEntry->Flink;
835  if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY)))
836  {
837  if (Window->head.h == pDCE->hwndCurrent)
838  {
839  CurrentWindow = Window;
840  }
841  else
842  {
843  if (!pDCE->hwndCurrent)
844  CurrentWindow = NULL;
845  else
846  CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
847  if (NULL == CurrentWindow)
848  {
849  continue;
850  }
851  }
852 
853  if (!GreIsHandleValid(pDCE->hDC) ||
854  (dc = DC_LockDc(pDCE->hDC)) == NULL)
855  {
856  continue;
857  }
858  if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow))
859  {
860  if (pDCE->DCXFlags & DCX_WINDOW)
861  {
862  DeltaX = CurrentWindow->rcWindow.left - dc->ptlDCOrig.x;
863  DeltaY = CurrentWindow->rcWindow.top - dc->ptlDCOrig.y;
864  dc->ptlDCOrig.x = CurrentWindow->rcWindow.left;
865  dc->ptlDCOrig.y = CurrentWindow->rcWindow.top;
866  }
867  else
868  {
869  DeltaX = CurrentWindow->rcClient.left - dc->ptlDCOrig.x;
870  DeltaY = CurrentWindow->rcClient.top - dc->ptlDCOrig.y;
871  dc->ptlDCOrig.x = CurrentWindow->rcClient.left;
872  dc->ptlDCOrig.y = CurrentWindow->rcClient.top;
873  }
874 
875  if (NULL != dc->dclevel.prgnClip)
876  {
877  REGION_bOffsetRgn(dc->dclevel.prgnClip, DeltaX, DeltaY);
878  dc->fs |= DC_DIRTY_RAO;
879  }
880  if (NULL != pDCE->hrgnClip)
881  {
882  NtGdiOffsetRgn(pDCE->hrgnClip, DeltaX, DeltaY);
883  }
884  }
885  DC_UnlockDc(dc);
886 
887  DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
889  }
890  }
891 }
892 
895 {
896  DCE *Dce;
897  PLIST_ENTRY ListEntry;
898  HWND Ret = NULL;
899 
900  ListEntry = LEDce.Flink;
901  while (ListEntry != &LEDce)
902  {
903  Dce = CONTAINING_RECORD(ListEntry, DCE, List);
904  ListEntry = ListEntry->Flink;
905  if (Dce->hDC == hDc)
906  {
907  if (Dce->DCXFlags & DCX_INDESTROY)
908  Ret = NULL;
909  else
910  Ret = Dce->hwndCurrent;
911  break;
912  }
913  }
914  return Ret;
915 }
916 
919 {
920  PDCE dce;
921  PLIST_ENTRY ListEntry;
922  INT nRet = 0;
923  BOOL Hit = FALSE;
924 
925  TRACE("%p %p\n", Window, hDc);
926  ListEntry = LEDce.Flink;
927  while (ListEntry != &LEDce)
928  {
929  dce = CONTAINING_RECORD(ListEntry, DCE, List);
930  ListEntry = ListEntry->Flink;
931  if (dce->hDC == hDc)
932  {
933  Hit = TRUE;
934  break;
935  }
936  }
937 
938  if ( Hit && (dce->DCXFlags & DCX_DCEBUSY))
939  {
940  nRet = DceReleaseDC(dce, EndPaint);
941  }
942 
943  return nRet;
944 }
945 
948 {
949  return UserGetDCEx(Wnd, 0, DCX_USESTYLE | DCX_WINDOW);
950 }
951 
954 {
955  EWNDOBJ* Clip;
956  PWND Wnd;
957  HWND hWnd;
958 
960 
961  if (hWnd && (Wnd = UserGetWindowObject(hWnd)))
962  {
963  Clip = (EWNDOBJ*)UserGetProp(Wnd, AtomWndObj, TRUE);
964 
965  if ( Clip && Clip->Hwnd == hWnd )
966  {
967  if (pwndo) *pwndo = (PWNDOBJ)Clip;
968  }
969  }
970  return hWnd;
971 }
972 
975 {
976  PWND Wnd=NULL;
978 
979  TRACE("Enter NtUserGetDCEx: hWnd %p, ClipRegion %p, Flags %x.\n",
980  hWnd, ClipRegion, Flags);
982 
983  if (hWnd && !(Wnd = UserGetWindowObject(hWnd)))
984  {
985  RETURN(NULL);
986  }
987  RETURN( UserGetDCEx(Wnd, ClipRegion, Flags));
988 
989 CLEANUP:
990  TRACE("Leave NtUserGetDCEx, ret=%p\n", _ret_);
991  UserLeave();
992  END_CLEANUP;
993 }
994 
995 /*
996  * NtUserGetWindowDC
997  *
998  * The NtUserGetWindowDC function retrieves the device context (DC) for the
999  * entire window, including title bar, menus, and scroll bars. A window device
1000  * context permits painting anywhere in a window, because the origin of the
1001  * device context is the upper-left corner of the window instead of the client
1002  * area.
1003  *
1004  * Status
1005  * @implemented
1006  */
1007 HDC APIENTRY
1009 {
1010  return NtUserGetDCEx(hWnd, 0, DCX_USESTYLE | DCX_WINDOW);
1011 }
1012 
1013 HDC APIENTRY
1015 {
1016  TRACE("NtUGetDC -> %p:%x\n", hWnd, !hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
1017 
1019 }
1020 
1032 HPALETTE
1033 APIENTRY
1035  HPALETTE hpal,
1036  BOOL ForceBackground)
1037 {
1038  HPALETTE oldPal;
1040  // Implement window checks
1041  oldPal = GdiSelectPalette( hDC, hpal, ForceBackground);
1042  UserLeave();
1043  return oldPal;
1044 }
1045 
1046 /* EOF */
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
HWND Hwnd
Definition: engobjects.h:98
__kernel_entry W32KAPI HRGN APIENTRY NtGdiCreateRectRgn(_In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
struct tagDCE * PDCE
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
#define DCX_CLIPSIBLINGS
Definition: winuser.h:2103
#define CLEANUP
Definition: ntuser.h:5
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1146
#define DCX_CLIPCHILDREN
Definition: winuser.h:2104
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:217
VOID FASTCALL GdiSelectVisRgn(HDC hdc, PREGION prgn)
Definition: cliprgn.c:57
PTHREADINFO ptiOwner
Definition: dce.h:29
#define LAYOUT_RTL
Definition: wingdi.h:1371
#define DCX_KEEPLAYOUT
Definition: undocuser.h:68
#define DCX_DCEBUSY
Definition: dce.h:36
BOOL FASTCALL IntGdiCleanDC(HDC hDC)
Definition: dcstate.c:73
#define TRUE
Definition: types.h:120
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL)
Definition: dclife.c:892
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
HDC APIENTRY NtUserGetDCEx(HWND hWnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
Definition: windc.c:974
LONG NTSTATUS
Definition: precomp.h:26
static HDC
Definition: imagelist.c:92
HWND hWnd
Definition: settings.c:17
LONG top
Definition: windef.h:307
#define WS_EX_LAYOUTRTL
Definition: winuser.h:390
HDC hDC
Definition: dce.h:20
static LIST_ENTRY LEDce
Definition: windc.c:17
#define DCX_USESTYLE
Definition: GetDCEx.c:10
__kernel_entry W32KAPI DWORD APIENTRY NtGdiSetLayout(_In_ HDC hdc, _In_ LONG wox, _In_ DWORD dwLayout)
#define USER_VERSION
Definition: ntuser.h:1116
HDC APIENTRY NtUserGetWindowDC(HWND hWnd)
Definition: windc.c:1008
BOOL FASTCALL REGION_bOffsetRgn(_Inout_ PREGION prgn, _In_ INT cx, _In_ INT cy)
Definition: region.c:2727
#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
RECT rcClient
Definition: ntuser.h:696
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1192
DCE *FASTCALL DceGetDceFromDC(HDC hdc)
Definition: windc.c:53
LONG left
Definition: windef.h:306
HDC FASTCALL DceCreateDisplayDC(VOID)
Definition: windc.c:40
#define CS_OWNDC
Definition: winuser.h:650
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define InsertTailList(ListHead, Entry)
#define WS_CLIPCHILDREN
Definition: pedump.c:619
PREGION FASTCALL REGION_LockRgn(_In_ HRGN hrgn)
Definition: region.c:2377
#define FASTCALL
Definition: nt_native.h:50
int32_t INT
Definition: typedefs.h:58
#define DCX_NORESETATTRS
Definition: winuser.h:2105
& rect
Definition: startmenu.cpp:1413
#define DCX_INTERSECTRGN
Definition: winuser.h:2109
#define RETURN(x)
HPALETTE APIENTRY NtUserSelectPalette(HDC hDC, HPALETTE hpal, BOOL ForceBackground)
Definition: windc.c:1034
#define DCX_WINDOW
Definition: winuser.h:2100
HWND hwndCurrent
Definition: dce.h:21
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:801
static VOID FASTCALL DceDeleteClipRgn(DCE *Dce)
Definition: windc.c:170
#define DCX_CACHECOMPAREMASK
Definition: windc.c:20
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define RGN_AND
Definition: wingdi.h:356
void FASTCALL DceFreeThreadDCE(PTHREADINFO pti)
Definition: windc.c:780
PWND pwndClip
Definition: dce.h:23
PPROCESSINFO ppiOwner
Definition: dce.h:30
Definition: window.c:28
static INT FASTCALL DceReleaseDC(DCE *dce, BOOL EndPaint)
Definition: windc.c:279
#define L(x)
Definition: ntvdm.h:50
PREGION FASTCALL IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
Definition: region.c:2426
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
DWORD DCXFlags
Definition: dce.h:28
#define WS_MINIMIZE
Definition: pedump.c:622
HRGN hrgnClipPublic
Definition: dce.h:26
unsigned int BOOL
Definition: ntddk_ex.h:94
#define DCX_DCEEMPTY
Definition: dce.h:35
unsigned char BOOLEAN
#define DCX_KEEPCLIPRGN
Definition: undocuser.h:67
#define HRGN_WINDOW
Definition: ntuser.h:344
#define DCX_NOCLIPCHILDREN
Definition: dce.h:40
Definition: region.h:7
#define WOC_RGN_CLIENT
Definition: winddi.h:1265
HRGN hrgnSavedVis
Definition: dce.h:27
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:126
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
INT FASTCALL IntGdiCombineRgn(PREGION prgnDest, PREGION prgnSrc1, PREGION prgnSrc2, INT iCombineMode)
Definition: region.c:2506
HDC FASTCALL UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
Definition: windc.c:345
HRGN hrgnClip
Definition: dce.h:25
HWND FASTCALL IntWindowFromDC(HDC hDc)
Definition: windc.c:894
HDC FASTCALL UserGetWindowDC(PWND Wnd)
Definition: windc.c:947
#define IntSysCreateRectpRgnIndirect(prc)
Definition: region.h:93
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
WORD APIENTRY IntGdiSetHookFlags(HDC hDC, WORD Flags)
Definition: dcutil.c:422
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
Definition: polytest.cpp:40
#define USERTAG_DCE
Definition: tags.h:221
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
static INT DCECount
Definition: windc.c:18
#define ASSERT(a)
Definition: mode.c:44
Implementation of the Explorer desktop window.
Definition: desktop.h:51
HANDLE FASTCALL UserGetProp(_In_ PWND Window, _In_ ATOM Atom, _In_ BOOLEAN SystemProp)
Definition: prop.c:46
Type
Definition: Type.h:6
VOID FASTCALL DceResetActiveDCEs(PWND Window)
Definition: windc.c:816
#define DECLARE_RETURN(type)
Definition: ntuser.h:3
BOOL WINAPI GreSetDCOrg(_In_ HDC hdc, _In_ LONG x, _In_ LONG y, _In_opt_ PRECTL Rect)
Definition: coord.c:1357
int Window
Definition: x11stubs.h:26
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
__kernel_entry W32KAPI INT APIENTRY NtGdiOffsetRgn(_In_ HRGN hrgn, _In_ INT cx, _In_ INT cy)
Definition: region.c:3981
VOID FASTCALL DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
Definition: windc.c:192
HDC hdc
Definition: main.c:9
BOOL FASTCALL co_IntGraphicsCheck(BOOL Create)
Definition: guicheck.c:52
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
RECT rcWindow
Definition: ntuser.h:695
void FASTCALL DceFreeWindowDCE(PWND Window)
Definition: windc.c:686
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
#define DCX_INDESTROY
Definition: dce.h:42
Definition: typedefs.h:119
VOID FASTCALL DCU_SetDcUndeletable(HDC)
Definition: dcutil.c:322
ATOM AtomWndObj
Definition: ntuser.c:20
DCE_TYPE
Definition: dce.h:10
#define CS_CLASSDC
Definition: winuser.h:645
#define ERR(fmt,...)
Definition: debug.h:110
Definition: ntuser.h:672
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1374
static HDC hDC
Definition: 3dtext.c:33
#define DCX_CACHE
Definition: winuser.h:2101
#define DCX_PARENTCLIP
Definition: winuser.h:2102
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define DCX_INTERSECTUPDATE
Definition: winuser.h:2106
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:235
#define RGN_DIFF
Definition: wingdi.h:358
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
void FASTCALL DceFreeDCE(PDCE pdce, BOOLEAN Force)
Definition: windc.c:633
HDC FASTCALL IntGdiCreateDC(PUNICODE_STRING Driver, PUNICODE_STRING pustrDevice, PVOID pUMdhpdev, CONST PDEVMODEW pdmInit, BOOL CreateAsIC)
Definition: dclife.c:1040
HWND FASTCALL UserGethWnd(HDC hdc, PWNDOBJ *pwndo)
Definition: windc.c:953
PDCE FASTCALL DceAllocDCE(PWND Window OPTIONAL, DCE_TYPE Type)
Definition: windc.c:86
BOOL NTAPI GreSetDCOwner(HDC hdc, ULONG ulOwner)
Definition: dclife.c:455
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
#define NULL
Definition: types.h:112
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
VOID FASTCALL IntEngWindowChanged(_In_ struct _WND *Window, _In_ FLONG flChanged)
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:918
Definition: dce.h:17
PREGION FASTCALL VIS_ComputeVisibleRegion(PWND Wnd, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings)
Definition: vis.c:13
#define DCX_DCEDIRTY
Definition: dce.h:37
VOID FASTCALL REGION_UnlockRgn(_In_ PREGION prgn)
Definition: region.c:2392
DBG_DEFAULT_CHANNEL(UserDce)
#define W32PF_OWNDCCLEANUP
Definition: win32.h:13
#define GDI_OBJ_HMGR_NONE
Definition: ntgdihdl.h:118
unsigned int ULONG
Definition: retypes.h:1
#define DCHF_INVALIDATEVISRGN
Definition: gdi_driver.h:267
static const WCHAR dc[]
LIST_ENTRY List
Definition: dce.h:19
BOOL FASTCALL IntIsChildWindow(PWND Parent, PWND BaseWindow)
Definition: window.c:916
#define DCX_PROCESSOWNED
Definition: undocuser.h:69
HDC APIENTRY NtUserGetDC(HWND hWnd)
Definition: windc.c:1014
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _WNDOBJ * PWNDOBJ
NTSTATUS NTAPI InitDCEImpl(VOID)
Definition: windc.c:30
PWND pwndOrg
Definition: dce.h:22
HWND hWndChild[NUM_TABS]
Definition: main.h:75
#define WS_VISIBLE
Definition: pedump.c:620
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2468
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
VOID FASTCALL DceEmptyCache(VOID)
Definition: windc.c:801
static VOID APIENTRY DceSetDrawable(PWND Window OPTIONAL, HDC hDC, ULONG Flags, BOOL SetClipOrigin)
Definition: windc.c:145
#define DCHF_VALIDATEVISRGN
Definition: gdi_driver.h:268
#define CS_PARENTDC
Definition: winuser.h:651
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
void FASTCALL DceFreeClassDCE(PDCE pdceClass)
Definition: windc.c:762
HPALETTE NTAPI GdiSelectPalette(_In_ HDC hDC, _In_ HPALETTE hpal, _In_ BOOL ForceBackground)
#define APIENTRY
Definition: api.h:79
#define END_CLEANUP
Definition: ntuser.h:6
static PREGION FASTCALL DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
Definition: windc.c:72
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1415
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define DCX_EXCLUDERGN
Definition: winuser.h:2108
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68