ReactOS 0.4.15-dev-8028-g8e799e2
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>
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
18static 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
27CODE_SEG("INIT")
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 */
51DCE*
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
70static
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);
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
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 {
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
144static 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
169static 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
190VOID
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, UserHMGetHandle(Window), 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
237noparent:
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
278static 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);
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
411 if (Flags & DCX_WINDOW) Flags &= ~DCX_CLIPCHILDREN;
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 {
435 Flags &= ~DCX_CLIPCHILDREN;
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 ? UserHMGetHandle(Wnd) : 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 {
489 }
490 if (Dce == NULL) return NULL;
491
492 Dce->hwndCurrent = (Wnd ? UserHMGetHandle(Wnd) : 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 == UserHMGetHandle(Wnd))
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 * https://reactos.org/archives/public/ros-dev/2008-July/010498.html
550 * https://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 */
632void 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 {
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 */
685void 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 == UserHMGetHandle(Window) &&
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", UserHMGetHandle(Window));
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
761void 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
779void 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 (UserHMGetHandle(Window) == 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 }
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;
977 HDC Ret = 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 goto Exit; // Return NULL
986 }
987 Ret = UserGetDCEx(Wnd, ClipRegion, Flags);
988
989Exit:
990 TRACE("Leave NtUserGetDCEx, ret=%p\n", Ret);
991 UserLeave();
992 return Ret;
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 */
1009{
1011}
1012
1015{
1016 TRACE("NtUGetDC -> %p:%x\n", hWnd, !hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
1017
1019}
1020
1032HPALETTE
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 */
static HDC hDC
Definition: 3dtext.c:33
#define CODE_SEG(...)
#define DCX_USESTYLE
Definition: GetDCEx.c:10
unsigned char BOOLEAN
Type
Definition: Type.h:7
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx 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:732
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: debug.h:113
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1417
VOID FASTCALL GdiSelectVisRgn(HDC hdc, PREGION prgn)
Definition: cliprgn.c:57
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:238
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL)
Definition: dclife.c:892
BOOL NTAPI GreSetDCOwner(HDC hdc, ULONG ulOwner)
Definition: dclife.c:455
HPALETTE NTAPI GdiSelectPalette(_In_ HDC hDC, _In_ HPALETTE hpal, _In_ BOOL ForceBackground)
VOID FASTCALL DCU_SetDcUndeletable(HDC)
Definition: dcutil.c:322
BOOL FASTCALL IntGdiCleanDC(HDC hDC)
Definition: dcstate.c:73
@ DC_DIRTY_RAO
Definition: dc.h:23
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:220
#define DCX_INDESTROY
Definition: dce.h:42
#define DCX_DCEEMPTY
Definition: dce.h:35
struct tagDCE * PDCE
#define DCX_NOCLIPCHILDREN
Definition: dce.h:40
#define DCX_DCEDIRTY
Definition: dce.h:37
#define DCX_DCEBUSY
Definition: dce.h:36
void FASTCALL DceEmptyCache(void)
Definition: windc.c:801
DCE_TYPE
Definition: dce.h:11
@ DCE_CLASS_DC
Definition: dce.h:13
@ DCE_WINDOW_DC
Definition: dce.h:14
@ DCE_CACHE_DC
Definition: dce.h:12
HDC FASTCALL IntGdiCreateDC(PUNICODE_STRING Driver, PUNICODE_STRING pustrDevice, PVOID pUMdhpdev, CONST PDEVMODEW pdmInit, BOOL CreateAsIC)
Definition: dclife.c:1040
WORD APIENTRY IntGdiSetHookFlags(HDC hDC, WORD Flags)
Definition: dcutil.c:422
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
HWND hWndChild[NUM_TABS]
Definition: main.h:74
VOID FASTCALL IntEngWindowChanged(_In_ struct _WND *Window, _In_ FLONG flChanged)
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
unsigned int BOOL
Definition: ntddk_ex.h:94
#define DCHF_INVALIDATEVISRGN
Definition: gdi_driver.h:267
#define DCHF_VALIDATEVISRGN
Definition: gdi_driver.h:268
BOOL FASTCALL co_IntGraphicsCheck(BOOL Create)
Definition: guicheck.c:52
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
#define USER_VERSION
Definition: ntuser.h:1149
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:805
#define HRGN_WINDOW
Definition: ntuser.h:361
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
static const WCHAR dc[]
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:92
#define FASTCALL
Definition: nt_native.h:50
BOOL WINAPI GreSetDCOrg(_In_ HDC hdc, _In_ LONG x, _In_ LONG y, _In_opt_ PRECTL Rect)
Definition: coord.c:1357
__kernel_entry W32KAPI DWORD APIENTRY NtGdiSetLayout(_In_ HDC hdc, _In_ LONG wox, _In_ DWORD dwLayout)
__kernel_entry W32KAPI HRGN APIENTRY NtGdiCreateRectRgn(_In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
__kernel_entry W32KAPI INT APIENTRY NtGdiOffsetRgn(_In_ HRGN hrgn, _In_ INT cx, _In_ INT cy)
Definition: region.c:3961
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
#define GDI_OBJ_HMGR_NONE
Definition: ntgdihdl.h:118
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
ATOM AtomWndObj
Definition: ntuser.c:20
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:251
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:242
#define L(x)
Definition: ntvdm.h:50
#define WS_CHILD
Definition: pedump.c:617
#define WS_MINIMIZE
Definition: pedump.c:622
#define WS_VISIBLE
Definition: pedump.c:620
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
#define WS_CLIPCHILDREN
Definition: pedump.c:619
#define IntSysCreateRectpRgnIndirect(prc)
Definition: region.h:93
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
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: polytest.cpp:41
Implementation of the Explorer desktop window.
Definition: desktop.h:52
Definition: window.c:28
HWND Hwnd
Definition: engobjects.h:101
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: region.h:8
Definition: ntuser.h:694
RECT rcClient
Definition: ntuser.h:717
RECT rcWindow
Definition: ntuser.h:716
Definition: dce.h:18
HRGN hrgnClip
Definition: dce.h:25
LIST_ENTRY List
Definition: dce.h:19
DWORD DCXFlags
Definition: dce.h:28
HRGN hrgnClipPublic
Definition: dce.h:26
PWND pwndClip
Definition: dce.h:23
HDC hDC
Definition: dce.h:20
PWND pwndOrg
Definition: dce.h:22
HRGN hrgnSavedVis
Definition: dce.h:27
PPROCESSINFO ppiOwner
Definition: dce.h:30
PTHREADINFO ptiOwner
Definition: dce.h:29
HWND hwndCurrent
Definition: dce.h:21
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define DCX_KEEPCLIPRGN
Definition: undocuser.h:68
#define DCX_KEEPLAYOUT
Definition: undocuser.h:69
#define DCX_PROCESSOWNED
Definition: undocuser.h:70
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:122
PREGION FASTCALL VIS_ComputeVisibleRegion(PWND Wnd, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings)
Definition: vis.c:13
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define W32PF_OWNDCCLEANUP
Definition: win32.h:13
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1192
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1146
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2449
PREGION FASTCALL REGION_LockRgn(_In_ HRGN hrgn)
Definition: region.c:2358
VOID FASTCALL REGION_UnlockRgn(_In_ PREGION prgn)
Definition: region.c:2373
PREGION FASTCALL IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
Definition: region.c:2407
BOOL FASTCALL REGION_bOffsetRgn(_Inout_ PREGION prgn, _In_ INT cx, _In_ INT cy)
Definition: region.c:2707
INT FASTCALL IntGdiCombineRgn(PREGION prgnDest, PREGION prgnSrc1, PREGION prgnSrc2, INT iCombineMode)
Definition: region.c:2487
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1374
HANDLE FASTCALL UserGetProp(_In_ PWND Window, _In_ ATOM Atom, _In_ BOOLEAN SystemProp)
Definition: prop.c:46
#define USERTAG_DCE
Definition: tags.h:221
BOOL FASTCALL IntIsChildWindow(PWND Parent, PWND BaseWindow)
Definition: window.c:927
static VOID FASTCALL DceDeleteClipRgn(DCE *Dce)
Definition: windc.c:170
HDC APIENTRY NtUserGetWindowDC(HWND hWnd)
Definition: windc.c:1008
DCE *FASTCALL DceGetDceFromDC(HDC hdc)
Definition: windc.c:53
HWND FASTCALL IntWindowFromDC(HDC hDc)
Definition: windc.c:894
void FASTCALL DceFreeWindowDCE(PWND Window)
Definition: windc.c:686
void FASTCALL DceFreeDCE(PDCE pdce, BOOLEAN Force)
Definition: windc.c:633
static INT DCECount
Definition: windc.c:18
#define DCX_CACHECOMPAREMASK
Definition: windc.c:20
void FASTCALL DceFreeClassDCE(PDCE pdceClass)
Definition: windc.c:762
static LIST_ENTRY LEDce
Definition: windc.c:17
HDC FASTCALL DceCreateDisplayDC(VOID)
Definition: windc.c:40
HDC FASTCALL UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
Definition: windc.c:345
void FASTCALL DceFreeThreadDCE(PTHREADINFO pti)
Definition: windc.c:780
HDC FASTCALL UserGetWindowDC(PWND Wnd)
Definition: windc.c:947
HWND FASTCALL UserGethWnd(HDC hdc, PWNDOBJ *pwndo)
Definition: windc.c:953
VOID FASTCALL DceResetActiveDCEs(PWND Window)
Definition: windc.c:816
VOID FASTCALL DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
Definition: windc.c:192
HPALETTE APIENTRY NtUserSelectPalette(HDC hDC, HPALETTE hpal, BOOL ForceBackground)
Definition: windc.c:1034
NTSTATUS NTAPI InitDCEImpl(VOID)
Definition: windc.c:30
static VOID APIENTRY DceSetDrawable(PWND Window OPTIONAL, HDC hDC, ULONG Flags, BOOL SetClipOrigin)
Definition: windc.c:145
HDC APIENTRY NtUserGetDCEx(HWND hWnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
Definition: windc.c:974
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:918
static INT FASTCALL DceReleaseDC(DCE *dce, BOOL EndPaint)
Definition: windc.c:279
PDCE FASTCALL DceAllocDCE(PWND Window OPTIONAL, DCE_TYPE Type)
Definition: windc.c:86
static PREGION FASTCALL DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
Definition: windc.c:72
HDC APIENTRY NtUserGetDC(HWND hWnd)
Definition: windc.c:1014
struct _WNDOBJ * PWNDOBJ
#define WOC_RGN_CLIENT
Definition: winddi.h:1265
#define RGN_DIFF
Definition: wingdi.h:358
#define RGN_AND
Definition: wingdi.h:356
#define LAYOUT_RTL
Definition: wingdi.h:1371
#define WS_EX_LAYOUTRTL
Definition: winuser.h:390
#define DCX_CACHE
Definition: winuser.h:2114
#define DCX_WINDOW
Definition: winuser.h:2113
#define DCX_CLIPCHILDREN
Definition: winuser.h:2117
#define DCX_CLIPSIBLINGS
Definition: winuser.h:2116
#define DCX_INTERSECTRGN
Definition: winuser.h:2122
#define DCX_PARENTCLIP
Definition: winuser.h:2115
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define CS_OWNDC
Definition: winuser.h:655
#define CS_CLASSDC
Definition: winuser.h:650
#define DCX_EXCLUDERGN
Definition: winuser.h:2121
#define DCX_INTERSECTUPDATE
Definition: winuser.h:2119
#define CS_PARENTDC
Definition: winuser.h:656
#define DCX_NORESETATTRS
Definition: winuser.h:2118
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170