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