[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / dcutil.c
index a640951..0471c7d 100644 (file)
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
-static
-VOID
-CopytoUserDcAttr(PDC dc, PDC_ATTR Dc_Attr, FLONG Dirty)
+COLORREF FASTCALL
+IntGdiSetBkColor(HDC hDC, COLORREF color)
 {
-      Dc_Attr->hpen              = dc->Dc_Attr.hpen;
-      Dc_Attr->hbrush            = dc->Dc_Attr.hbrush;
-      Dc_Attr->hColorSpace       = dc->Dc_Attr.hColorSpace;
-      Dc_Attr->hlfntNew          = dc->Dc_Attr.hlfntNew;
-
-      Dc_Attr->jROP2             = dc->Dc_Attr.jROP2;
-      Dc_Attr->jFillMode         = dc->Dc_Attr.jFillMode;
-      Dc_Attr->jStretchBltMode   = dc->Dc_Attr.jStretchBltMode;
-      Dc_Attr->lRelAbs           = dc->Dc_Attr.lRelAbs;
-      Dc_Attr->jBkMode           = dc->Dc_Attr.jBkMode;
-
-      Dc_Attr->crBackgroundClr   = dc->Dc_Attr.crBackgroundClr;
-      Dc_Attr->ulBackgroundClr   = dc->Dc_Attr.ulBackgroundClr;
-      Dc_Attr->crForegroundClr   = dc->Dc_Attr.crForegroundClr;
-      Dc_Attr->ulForegroundClr   = dc->Dc_Attr.ulForegroundClr;
-
-      Dc_Attr->ulBrushClr        = dc->Dc_Attr.ulBrushClr;
-      Dc_Attr->crBrushClr        = dc->Dc_Attr.crBrushClr;
-
-      Dc_Attr->ulPenClr          = dc->Dc_Attr.ulPenClr;
-      Dc_Attr->crPenClr          = dc->Dc_Attr.crPenClr;
-
-      Dc_Attr->ptlBrushOrigin    = dc->Dc_Attr.ptlBrushOrigin;
-
-      Dc_Attr->lTextAlign        = dc->Dc_Attr.lTextAlign;
-      Dc_Attr->lTextExtra        = dc->Dc_Attr.lTextExtra;
-      Dc_Attr->cBreak            = dc->Dc_Attr.cBreak;
-      Dc_Attr->lBreakExtra       = dc->Dc_Attr.lBreakExtra;
-      Dc_Attr->iMapMode          = dc->Dc_Attr.iMapMode;
-      Dc_Attr->iGraphicsMode     = dc->Dc_Attr.iGraphicsMode;
-
-      Dc_Attr->ptlCurrent        = dc->Dc_Attr.ptlCurrent;
-      Dc_Attr->ptlWindowOrg      = dc->Dc_Attr.ptlWindowOrg;
-      Dc_Attr->szlWindowExt      = dc->Dc_Attr.szlWindowExt;
-      Dc_Attr->ptlViewportOrg    = dc->Dc_Attr.ptlViewportOrg;
-      Dc_Attr->szlViewportExt    = dc->Dc_Attr.szlViewportExt;
-
-      Dc_Attr->ulDirty_          = dc->Dc_Attr.ulDirty_; //Copy flags! We may have set them.
-      
-      XForm2MatrixS( &Dc_Attr->mxWorldToDevice, &dc->w.xformWorld2Vport);
-      XForm2MatrixS( &Dc_Attr->mxDevicetoWorld, &dc->w.xformVport2World);
-      XForm2MatrixS( &Dc_Attr->mxWorldToPage, &dc->w.xformWorld2Wnd);
+    COLORREF oldColor;
+    PDC dc;
+    PDC_ATTR pdcattr;
+    HBRUSH hBrush;
+
+    if (!(dc = DC_LockDc(hDC)))
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return CLR_INVALID;
+    }
+    pdcattr = dc->pdcattr;
+    oldColor = pdcattr->crBackgroundClr;
+    pdcattr->crBackgroundClr = color;
+    pdcattr->ulBackgroundClr = (ULONG)color;
+    pdcattr->ulDirty_ &= ~(DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL); // Clear Flag if set.
+    hBrush = pdcattr->hbrush;
+    DC_UnlockDc(dc);
+    NtGdiSelectBrush(hDC, hBrush);
+    return oldColor;
 }
 
-static
-VOID
-CopyFromUserDcAttr(PDC dc, PDC_ATTR Dc_Attr, FLONG Dirty)
+INT FASTCALL
+IntGdiSetBkMode(HDC hDC, INT Mode)
 {
-      if ( (Dirty & DIRTY_FILL) || (Dc_Attr->ulDirty_ & DIRTY_FILL))
-      {
-        dc->Dc_Attr.ulBrushClr     = Dc_Attr->ulBrushClr;
-        dc->Dc_Attr.crBrushClr     = Dc_Attr->crBrushClr;
-        Dc_Attr->ulDirty_ &= ~DIRTY_FILL;
-      }
-      if ( Dirty & DIRTY_LINE || (Dc_Attr->ulDirty_ & DIRTY_LINE))
-      {
-        dc->Dc_Attr.crBackgroundClr = Dc_Attr->crBackgroundClr;
-        dc->Dc_Attr.ulBackgroundClr = Dc_Attr->ulBackgroundClr;
-        dc->Dc_Attr.ulPenClr        = Dc_Attr->ulPenClr;
-        dc->Dc_Attr.crPenClr        = Dc_Attr->crPenClr;
-        Dc_Attr->ulDirty_ &= ~DIRTY_LINE;
-      }
-      if ( Dirty & DIRTY_TEXT || (Dc_Attr->ulDirty_ & DIRTY_TEXT))
-      {
-        dc->Dc_Attr.crForegroundClr = Dc_Attr->crForegroundClr;
-        dc->Dc_Attr.ulForegroundClr = Dc_Attr->ulForegroundClr;
-        Dc_Attr->ulDirty_ &= ~DIRTY_TEXT;
-      }
-
-      if ( Dirty & (DC_MODE_DIRTY|DC_FONTTEXT_DIRTY) ||
-          (Dc_Attr->ulDirty_ & (DC_MODE_DIRTY|DC_FONTTEXT_DIRTY)))
-      {
-        dc->Dc_Attr.jROP2         = Dc_Attr->jROP2;
-        dc->Dc_Attr.iGraphicsMode = Dc_Attr->iGraphicsMode;
-        dc->Dc_Attr.lFillMode     = Dc_Attr->lFillMode;
-        dc->Dc_Attr.flFontMapper  = Dc_Attr->flFontMapper;
-        dc->Dc_Attr.lBreakExtra   = Dc_Attr->lBreakExtra;
-        dc->Dc_Attr.cBreak        = Dc_Attr->cBreak;
-      }
+    COLORREF oldMode;
+    PDC dc;
+    PDC_ATTR pdcattr;
+
+    if (!(dc = DC_LockDc(hDC)))
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return CLR_INVALID;
+    }
+    pdcattr = dc->pdcattr;
+    oldMode = pdcattr->lBkMode;
+    pdcattr->jBkMode = Mode;
+    pdcattr->lBkMode = Mode;
+    DC_UnlockDc(dc);
+    return oldMode;
 }
 
-static
-BOOL
-ReadWriteVMDcAttr(PDC dc, FLONG Dirty, BOOL Write)
+UINT
+FASTCALL
+IntGdiSetTextAlign(HDC  hDC,
+                   UINT  Mode)
 {
-  BOOL Ret = FALSE;
-  KeEnterCriticalRegion();
+    UINT prevAlign;
+    DC *dc;
+    PDC_ATTR pdcattr;
+
+    dc = DC_LockDc(hDC);
+    if (!dc)
     {
-      INT Index = GDI_HANDLE_GET_INDEX(dc->hHmgr);
-      PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
-      HANDLE ProcessId = (HANDLE)(((ULONG_PTR)(Entry->ProcessId)) & ~1);
-      DC_ATTR lDc_AttrData;
-
-      if(Entry->UserData)
-      {
-         NTSTATUS Status = ZwReadVirtualMemory ( ProcessId,
-                                         &(Entry->UserData),
-                                             &lDc_AttrData,
-                                            sizeof(DC_ATTR),
-                                                      NULL );
-         if (Write)
-         {
-            if (NT_SUCCESS(Status)) CopytoUserDcAttr(dc, &lDc_AttrData, Dirty);
-            Ret = TRUE;
-         }
-         else
-         {
-            if (NT_SUCCESS(Status)) CopyFromUserDcAttr(dc, &lDc_AttrData, Dirty);
-            Ret = TRUE;
-         }
-         if (Write)
-             Status = ZwWriteVirtualMemory ( ProcessId,
-                                     &(Entry->UserData),
-                                         &lDc_AttrData,
-                                        sizeof(DC_ATTR),
-                                                  NULL );
-         if(!NT_SUCCESS(Status))
-         {
-           SetLastNtError(Status);
-           Ret = FALSE;
-         }
-      }
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return GDI_ERROR;
     }
-  KeLeaveCriticalRegion();
-  return Ret;
+    pdcattr = dc->pdcattr;
+    prevAlign = pdcattr->lTextAlign;
+    pdcattr->lTextAlign = Mode;
+    DC_UnlockDc(dc);
+    return  prevAlign;
 }
 
-
-BOOL
+COLORREF
 FASTCALL
-DCU_UpdateUserXForms(PDC pDC, ULONG uMask)
+IntGdiSetTextColor(HDC hDC,
+                   COLORREF color)
 {
-  PDC_ATTR DC_Attr = pDC->pDc_Attr;
-
-  if (!uMask) return FALSE;
+    COLORREF crOldColor;
+    PDC pdc;
+    PDC_ATTR pdcattr;
 
-  if (!DC_Attr) return FALSE;
-  else
-  {
-    NTSTATUS Status = STATUS_SUCCESS;
-    KeEnterCriticalRegion();
-    _SEH_TRY
+    pdc = DC_LockDc(hDC);
+    if (!pdc)
     {
-      ProbeForWrite(DC_Attr,
-            sizeof(DC_ATTR),
-                          1);
-    if (uMask & WORLD_XFORM_CHANGED)
-      XForm2MatrixS( &DC_Attr->mxWorldToDevice, &pDC->w.xformWorld2Vport);
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return CLR_INVALID;
+    }
+    pdcattr = pdc->pdcattr;
 
-    if (uMask & DEVICE_TO_WORLD_INVALID)
-      XForm2MatrixS( &DC_Attr->mxDevicetoWorld, &pDC->w.xformVport2World);
+    // What about ulForegroundClr, like in gdi32?
+    crOldColor = pdcattr->crForegroundClr;
+    pdcattr->crForegroundClr = color;
+    DC_vUpdateTextBrush(pdc);
 
-    if (uMask & WORLD_TO_PAGE_IDENTITY)
-      XForm2MatrixS( &DC_Attr->mxWorldToPage, &pDC->w.xformWorld2Wnd);
-    }
-    _SEH_HANDLE
+    DC_UnlockDc(pdc);
+
+    return  crOldColor;
+}
+
+VOID
+FASTCALL
+DCU_SetDcUndeletable(HDC  hDC)
+{
+    PDC dc = DC_LockDc(hDC);
+    if (!dc)
     {
-      Status = _SEH_GetExceptionCode();
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return;
     }
-    _SEH_END;
-    KeLeaveCriticalRegion();
-    if(!NT_SUCCESS(Status))
+
+    dc->fs |= DC_FLAG_PERMANENT;
+    DC_UnlockDc(dc);
+    return;
+}
+
+#if 0
+BOOL FASTCALL
+IntIsPrimarySurface(SURFOBJ *SurfObj)
+{
+    if (PrimarySurface.pSurface == NULL)
     {
-      SetLastNtError(Status);
-      return FALSE;
+        return FALSE;
     }
-  }
-  return TRUE;
+    return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
 }
+#endif
 
 BOOL
 FASTCALL
-DCU_SyncDcAttrtoUser(PDC dc, FLONG Dirty)
+IntSetDefaultRegion(PDC pdc)
 {
-  BOOL TryHarder = FALSE;
-  PDC_ATTR Dc_Attr = dc->pDc_Attr;
-  if (!Dirty) return FALSE;
-  if (!Dc_Attr) return FALSE;
-  else
-  {
-    NTSTATUS Status = STATUS_SUCCESS;
-    KeEnterCriticalRegion();
-    _SEH_TRY
+    PSURFACE pSurface;
+    PROSRGNDATA prgn;
+    RECTL rclWnd, rclClip;
+
+    IntGdiReleaseRaoRgn(pdc);
+
+    rclWnd.left   = 0;
+    rclWnd.top    = 0;
+    rclWnd.right  = pdc->dclevel.sizl.cx;
+    rclWnd.bottom = pdc->dclevel.sizl.cy;
+    rclClip = rclWnd;
+
+//    EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
+    if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
+    {
+        pSurface = pdc->dclevel.pSurface;
+        if (pSurface && pSurface->flags & PDEV_SURFACE)
+        {
+            rclClip.left   += pdc->ppdev->ptlOrigion.x;
+            rclClip.top    += pdc->ppdev->ptlOrigion.y;
+            rclClip.right  += pdc->ppdev->ptlOrigion.x;
+            rclClip.bottom += pdc->ppdev->ptlOrigion.y;
+        }
+    }
+//    EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
+
+    prgn = pdc->prgnVis;
+
+    if (prgn && prgn != prgnDefault)
+    {
+        REGION_SetRectRgn( prgn,
+                           rclClip.left,
+                           rclClip.top,
+                           rclClip.right ,
+                           rclClip.bottom );
+    }
+    else
     {
-      ProbeForWrite(Dc_Attr,
-            sizeof(DC_ATTR),
-                          1);
-      CopytoUserDcAttr( dc, Dc_Attr, Dirty);
+        prgn = IntSysCreateRectpRgn( rclClip.left,
+                                     rclClip.top,
+                                     rclClip.right ,
+                                     rclClip.bottom );
+        pdc->prgnVis = prgn;
     }
-    _SEH_HANDLE
+
+    if (prgn)
     {
-      Status = _SEH_GetExceptionCode();
+        pdc->ptlDCOrig.x = 0;
+        pdc->ptlDCOrig.y = 0;
+        pdc->erclWindow = rclWnd;
+        pdc->erclClip = rclClip;
+        /* Might be an InitDC or DCE....*/
+        pdc->ptlFillOrigin.x = pdc->dcattr.VisRectRegion.Rect.right;
+        pdc->ptlFillOrigin.y = pdc->dcattr.VisRectRegion.Rect.bottom;
+        return TRUE;
     }
-    _SEH_END;
-    KeLeaveCriticalRegion();
-    if(!NT_SUCCESS(Status)) TryHarder = TRUE;
-    if (TryHarder) return ReadWriteVMDcAttr( dc, Dirty, TRUE);
-  }
-  return TRUE;
+
+    pdc->prgnVis = prgnDefault;
+    return FALSE;
 }
 
-BOOL
-FASTCALL
-DCU_SynchDcAttrtoUser(HDC hDC, FLONG Dirty)
+
+BOOL APIENTRY
+NtGdiCancelDC(HDC  hDC)
 {
-  PDC pDC = DC_LockDc ( hDC );
-  if (!pDC) return FALSE;
-  BOOL Ret = DCU_SyncDcAttrtoUser(pDC, Dirty);
-  DC_UnlockDc( pDC );
-  return Ret;
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+
+WORD APIENTRY
+IntGdiSetHookFlags(HDC hDC, WORD Flags)
+{
+    WORD wRet;
+    DC *dc = DC_LockDc(hDC);
+
+    if (NULL == dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return 0;
+    }
+
+    wRet = dc->fs & DC_FLAG_DIRTY_RAO; // Fixme wrong flag!
+
+    /* "Undocumented Windows" info is slightly confusing.
+     */
+
+    DPRINT("DC %p, Flags %04x\n", hDC, Flags);
+
+    if (Flags & DCHF_INVALIDATEVISRGN)
+    {
+        /* hVisRgn has to be updated */
+        dc->fs |= DC_FLAG_DIRTY_RAO;
+    }
+    else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
+    {
+        dc->fs &= ~DC_FLAG_DIRTY_RAO;
+    }
+
+    DC_UnlockDc(dc);
+
+    return wRet;
 }
 
+
 BOOL
-FASTCALL
-DCU_SyncDcAttrtoW32k(PDC dc, FLONG Dirty)
+APIENTRY
+NtGdiGetDCDword(
+    HDC hDC,
+    UINT u,
+    DWORD *Result)
 {
-  BOOL TryHarder = FALSE;
-  PDC_ATTR Dc_Attr = dc->pDc_Attr;
-  if (!Dirty) return FALSE;
-  if (!Dc_Attr) return FALSE;
-  else
-  {
+    BOOL Ret = TRUE;
+    PDC pdc;
+    PDC_ATTR pdcattr;
+
+    DWORD SafeResult = 0;
     NTSTATUS Status = STATUS_SUCCESS;
-    KeEnterCriticalRegion();
-    _SEH_TRY
+
+    if (!Result)
     {
-      ProbeForRead(Dc_Attr,
-            sizeof(DC_ATTR),
-                         1);
-      CopyFromUserDcAttr( dc, Dc_Attr, Dirty);
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
     }
-    _SEH_HANDLE
+
+    pdc = DC_LockDc(hDC);
+    if (!pdc)
     {
-      Status = _SEH_GetExceptionCode();
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    pdcattr = pdc->pdcattr;
+
+    switch (u)
+    {
+        case GdiGetJournal:
+            break;
+
+        case GdiGetRelAbs:
+            SafeResult = pdcattr->lRelAbs;
+            break;
+
+        case GdiGetBreakExtra:
+            SafeResult = pdcattr->lBreakExtra;
+            break;
+
+        case GdiGerCharBreak:
+            SafeResult = pdcattr->cBreak;
+            break;
+
+        case GdiGetArcDirection:
+            if (pdcattr->dwLayout & LAYOUT_RTL)
+                SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
+            else
+                SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
+            break;
+
+        case GdiGetEMFRestorDc:
+            break;
+
+        case GdiGetFontLanguageInfo:
+            SafeResult = IntGetFontLanguageInfo(pdc);
+            break;
+
+        case GdiGetIsMemDc:
+            SafeResult = pdc->dctype;
+            break;
+
+        case GdiGetMapMode:
+            SafeResult = pdcattr->iMapMode;
+            break;
+
+        case GdiGetTextCharExtra:
+            SafeResult = pdcattr->lTextExtra;
+            break;
+
+        default:
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            Ret = FALSE;
+            break;
+    }
+
+    if (Ret)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(Result, sizeof(DWORD), 1);
+            *Result = SafeResult;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            Ret = FALSE;
+        }
     }
-    _SEH_END;
-    KeLeaveCriticalRegion();
-    if(!NT_SUCCESS(Status)) TryHarder = TRUE;
-    if (TryHarder) return ReadWriteVMDcAttr( dc, Dirty, FALSE);
-  }
-  return TRUE;
+
+    DC_UnlockDc(pdc);
+    return Ret;
 }
 
 BOOL
-FASTCALL
-DCU_SynchDcAttrtoW32k(HDC hDC, FLONG Dirty)
+APIENTRY
+NtGdiGetAndSetDCDword(
+    HDC hDC,
+    UINT u,
+    DWORD dwIn,
+    DWORD *Result)
 {
-  PDC pDC = DC_LockDc ( hDC );
-  if (!pDC) return FALSE;
-  BOOL Ret = DCU_SyncDcAttrtoW32k(pDC, Dirty);
-  DC_UnlockDc( pDC );
-  return Ret;
-}
+    BOOL Ret = TRUE;
+    PDC pdc;
+    PDC_ATTR pdcattr;
+
+    DWORD SafeResult = 0;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (!Result)
+    {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pdc = DC_LockDc(hDC);
+    if (!pdc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    pdcattr = pdc->pdcattr;
+
+    switch (u)
+    {
+        case GdiGetSetCopyCount:
+            SafeResult = pdc->ulCopyCount;
+            pdc->ulCopyCount = dwIn;
+            break;
+
+        case GdiGetSetTextAlign:
+            SafeResult = pdcattr->lTextAlign;
+            pdcattr->lTextAlign = dwIn;
+            // pdcattr->flTextAlign = dwIn; // Flags!
+            break;
 
+        case GdiGetSetRelAbs:
+            SafeResult = pdcattr->lRelAbs;
+            pdcattr->lRelAbs = dwIn;
+            break;
+
+        case GdiGetSetTextCharExtra:
+            SafeResult = pdcattr->lTextExtra;
+            pdcattr->lTextExtra = dwIn;
+            break;
+
+        case GdiGetSetSelectFont:
+            break;
+
+        case GdiGetSetMapperFlagsInternal:
+            if (dwIn & ~1)
+            {
+                SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                Ret = FALSE;
+                break;
+            }
+            SafeResult = pdcattr->flFontMapper;
+            pdcattr->flFontMapper = dwIn;
+            break;
+
+        case GdiGetSetMapMode:
+            SafeResult = IntGdiSetMapMode(pdc, dwIn);
+            break;
+
+        case GdiGetSetArcDirection:
+            if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
+            {
+                SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                Ret = FALSE;
+                break;
+            }
+            if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
+            {
+                SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
+                if (dwIn == AD_CLOCKWISE)
+                {
+                    pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
+                    break;
+                }
+                pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
+            }
+            else // Left to Right
+            {
+                SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
+                             AD_COUNTERCLOCKWISE;
+                if (dwIn == AD_COUNTERCLOCKWISE)
+                {
+                    pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
+                    break;
+                }
+                pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
+            }
+            break;
+
+        default:
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            Ret = FALSE;
+            break;
+    }
+
+    if (Ret)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(Result, sizeof(DWORD), 1);
+            *Result = SafeResult;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            Ret = FALSE;
+        }
+    }
+
+    DC_UnlockDc(pdc);
+    return Ret;
+}