[WIN32K]
[reactos.git] / subsystems / win32 / win32k / objects / dcstate.c
index 05656af..560ef34 100644 (file)
 
 VOID
 FASTCALL
-DC_vCopyState(PDC pdcSrc, PDC pdcDst)
+DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
 {
+    DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc->BaseObject.hHmgr, pdcDst->BaseObject.hHmgr);
+
     /* Copy full DC attribute */
     *pdcDst->pdcattr = *pdcSrc->pdcattr;
 
@@ -22,7 +24,7 @@ DC_vCopyState(PDC pdcSrc, PDC pdcDst)
     /* The VisRectRegion field needs to be set to a valid state */
 
     /* Mark some fields as dirty */
-    pdcDst->pdcattr->ulDirty_ |= 0x0012001f;
+    pdcDst->pdcattr->ulDirty_ |= 0x0012001f; // Note: Use if, To is FALSE....
 
     /* Copy DC level */
     pdcDst->dclevel.pColorSpace     = pdcSrc->dclevel.pColorSpace;
@@ -53,8 +55,20 @@ DC_vCopyState(PDC pdcSrc, PDC pdcDst)
         pdcDst->rosdc.bitsPerPixel = pdcSrc->rosdc.bitsPerPixel;
     }
 
-    GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
-
+    /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
+    if (To) // Copy "To" SaveDC state.
+    {
+        if (pdcSrc->rosdc.hClipRgn)
+        {
+           pdcDst->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
+           NtGdiCombineRgn(pdcDst->rosdc.hClipRgn, pdcSrc->rosdc.hClipRgn, 0, RGN_COPY);
+        }
+        // FIXME! Handle prgnMeta!
+    }
+    else // Copy "!To" RestoreDC state.
+    {  /* The VisRectRegion field needs to be set to a valid state */
+       GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
+    }
 }
 
 
@@ -66,7 +80,7 @@ IntGdiCleanDC(HDC hDC)
     dc = DC_LockDc(hDC);
     if (!dc) return FALSE;
     // Clean the DC
-    if (defaultDCstate) DC_vCopyState(defaultDCstate, dc);
+    if (defaultDCstate) DC_vCopyState(defaultDCstate, dc, FALSE);
 
     if (dc->dctype != DC_TYPE_MEMORY)
     {
@@ -93,41 +107,18 @@ NtGdiResetDC(
 }
 
 
-BOOL
-APIENTRY
-NtGdiRestoreDC(
-    HDC hdc,
+VOID
+NTAPI
+DC_vRestoreDC(
+    IN PDC pdc,
     INT iSaveLevel)
 {
-    PDC pdc, pdcSave;
-    HDC hdcSave;
     PEPROCESS pepCurrentProcess;
+    HDC hdcSave;
+    PDC pdcSave;
 
-    DPRINT("NtGdiRestoreDC(%lx, %d)\n", hdc, iSaveLevel);
-
-    /* Lock the original DC */
-    pdc = DC_LockDc(hdc);
-    if (!pdc)
-    {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
-        return FALSE;
-    }
-
-    ASSERT(pdc->dclevel.lSaveDepth > 0);
-
-    /* Negative values are relative to the stack top */
-    if (iSaveLevel < 0)
-        iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
-
-    /* Check if we have a valid instance */
-    if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
-    {
-        DPRINT("Illegal save level, requested: %ld, current: %ld\n",
-               iSaveLevel, pdc->dclevel.lSaveDepth);
-        DC_UnlockDc(pdc);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
+    ASSERT(iSaveLevel > 0);
+    DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc->BaseObject.hHmgr, iSaveLevel);
 
     /* Get current process */
     pepCurrentProcess = PsGetCurrentProcess();
@@ -136,14 +127,15 @@ NtGdiRestoreDC(
     while (pdc->dclevel.lSaveDepth > iSaveLevel)
     {
         hdcSave = pdc->dclevel.hdcSave;
+        DPRINT("RestoreDC = %p\n", hdcSave);
 
         /* Set us as the owner */
         if (!GDIOBJ_SetOwnership(hdcSave, pepCurrentProcess))
         {
             /* Could not get ownership. That's bad! */
-            DPRINT1("Could not get ownership of saved DC (%p) for dc %p!\n",
-                    hdcSave, hdc);
-            return FALSE;
+            DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
+                    hdcSave, pdc->BaseObject.hHmgr);
+            return;// FALSE;
         }
 
         /* Lock the saved dc */
@@ -152,9 +144,8 @@ NtGdiRestoreDC(
         {
             /* WTF? Internal error! */
             DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
-                    hdcSave, hdc);
-            DC_UnlockDc(pdc);
-            return FALSE;
+                    hdcSave, pdc->BaseObject.hHmgr);
+            return;// FALSE;
         }
 
         /* Remove the saved dc from the queue */
@@ -167,7 +158,7 @@ NtGdiRestoreDC(
         if (pdc->dclevel.lSaveDepth == iSaveLevel)
         {
             /* Copy the state back */
-            DC_vCopyState(pdcSave, pdc);
+            DC_vCopyState(pdcSave, pdc, FALSE);
 
             // Restore Path by removing it, if the Save flag is set.
             // BeginPath will takecare of the rest.
@@ -179,13 +170,58 @@ NtGdiRestoreDC(
             }
         }
 
+        /* Prevent save dc from being restored */
+        pdcSave->dclevel.lSaveDepth = 1;
+
         /* Delete the saved dc */
-        DC_FreeDC(hdcSave);
+        GreDeleteObject(hdcSave);
     }
 
+    DPRINT("Leave DC_vRestoreDC()\n");
+}
+
+
+
+BOOL
+APIENTRY
+NtGdiRestoreDC(
+    HDC hdc,
+    INT iSaveLevel)
+{
+    PDC pdc;
+
+    DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc, iSaveLevel);
+
+    /* Lock the original DC */
+    pdc = DC_LockDc(hdc);
+    if (!pdc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    ASSERT(pdc->dclevel.lSaveDepth > 0);
+
+    /* Negative values are relative to the stack top */
+    if (iSaveLevel < 0)
+        iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
+
+    /* Check if we have a valid instance */
+    if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
+    {
+        DPRINT("Illegal save level, requested: %ld, current: %ld\n",
+               iSaveLevel, pdc->dclevel.lSaveDepth);
+        DC_UnlockDc(pdc);
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* Call the internal function */
+    DC_vRestoreDC(pdc, iSaveLevel);
+
     DC_UnlockDc(pdc);
 
-    DPRINT("Leaving NtGdiRestoreDC\n");
+    DPRINT("Leave NtGdiRestoreDC\n");
     return TRUE;
 }
 
@@ -199,7 +235,7 @@ NtGdiSaveDC(
     PDC pdc, pdcSave;
     INT lSaveDepth;
 
-    DPRINT("NtGdiSaveDC(%lx)\n", hDC);
+    DPRINT("NtGdiSaveDC(%p)\n", hDC);
 
     /* Lock the original dc */
     pdc = DC_LockDc(hDC);
@@ -211,7 +247,7 @@ NtGdiSaveDC(
     }
 
     /* Allocate a new dc */
-    pdcSave = DC_AllocDC(NULL);
+    pdcSave = DC_AllocDcWithHandle();
     if (pdcSave == NULL)
     {
         DPRINT("Could not allocate a new DC\n");
@@ -220,12 +256,15 @@ NtGdiSaveDC(
     }
     hdcSave = pdcSave->BaseObject.hHmgr;
 
+    InterlockedIncrement(&pdc->ppdev->cPdevRefs);
+    DC_vInitDc(pdcSave, DCTYPE_MEMORY, pdc->ppdev);
+
     /* Make it a kernel handle
        (FIXME: windows handles this different, see wiki)*/
     GDIOBJ_SetOwnership(hdcSave, NULL);
 
     /* Copy the current state */
-    DC_vCopyState(pdc, pdcSave);
+    DC_vCopyState(pdc, pdcSave, TRUE);
 
     /* Copy path. FIXME: why this way? */
     pdcSave->dclevel.hPath = pdc->dclevel.hPath;
@@ -242,7 +281,7 @@ NtGdiSaveDC(
     DC_UnlockDc(pdcSave);
     DC_UnlockDc(pdc);
 
-    DPRINT("Leave NtGdiSaveDC: %ld\n", lSaveDepth);
+    DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
     return lSaveDepth;
 }