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;
/* 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;
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);
+ }
}
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)
{
}
-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();
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 */
{
/* 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 */
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.
}
}
+ /* 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;
}
PDC pdc, pdcSave;
INT lSaveDepth;
- DPRINT("NtGdiSaveDC(%lx)\n", hDC);
+ DPRINT("NtGdiSaveDC(%p)\n", hDC);
/* Lock the original dc */
pdc = DC_LockDc(hDC);
}
/* Allocate a new dc */
- pdcSave = DC_AllocDC(NULL);
+ pdcSave = DC_AllocDcWithHandle();
if (pdcSave == NULL)
{
DPRINT("Could not allocate a new DC\n");
}
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;
DC_UnlockDc(pdcSave);
DC_UnlockDc(pdc);
- DPRINT("Leave NtGdiSaveDC: %ld\n", lSaveDepth);
+ DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
return lSaveDepth;
}