Don't hard code viewport extents, they depend on the dc size - highlighted by gdi32...
[reactos.git] / reactos / subsystems / win32 / win32k / objects / coord.c
index 8daf645..a3541b7 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
+/*
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
 void FASTCALL
 IntFixIsotropicMapping(PDC dc)
 {
-  ULONG xdim = EngMulDiv(dc->Dc_Attr.szlViewportExt.cx, dc->GDIInfo->ulHorzSize, dc->GDIInfo->ulHorzRes) / dc->Dc_Attr.szlWindowExt.cx;
-  ULONG ydim = EngMulDiv(dc->Dc_Attr.szlViewportExt.cy, dc->GDIInfo->ulVertSize, dc->GDIInfo->ulVertRes) / dc->Dc_Attr.szlWindowExt.cy;
-
-  if (xdim > ydim)
-  {
-    dc->Dc_Attr.szlViewportExt.cx = dc->Dc_Attr.szlViewportExt.cx * abs(ydim / xdim);
-    if (!dc->Dc_Attr.szlViewportExt.cx) dc->Dc_Attr.szlViewportExt.cx = 1;
-  }
-  else
-  {
-    dc->Dc_Attr.szlViewportExt.cy = dc->Dc_Attr.szlViewportExt.cy * abs(xdim / ydim);
-    if (!dc->Dc_Attr.szlViewportExt.cy) dc->Dc_Attr.szlViewportExt.cy = 1;
-  }
-}
-
-BOOL FASTCALL
-IntGdiCombineTransform(LPXFORM XFormResult,
-                       LPXFORM xform1,
-                       LPXFORM xform2)
-{
-  /* Check for illegal parameters */
-  if (!XFormResult || !xform1 || !xform2)
-  {
-    return  FALSE;
-  }
-
-  /* Create the result in a temporary XFORM, since xformResult may be
-   * equal to xform1 or xform2 */
-  XFormResult->eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
-  XFormResult->eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
-  XFormResult->eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
-  XFormResult->eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
-  XFormResult->eDx  = xform1->eDx  * xform2->eM11 + xform1->eDy  * xform2->eM21 + xform2->eDx;
-  XFormResult->eDy  = xform1->eDx  * xform2->eM12 + xform1->eDy  * xform2->eM22 + xform2->eDy;
-
-  return TRUE;
-}
-
-BOOL STDCALL NtGdiCombineTransform(LPXFORM  UnsafeXFormResult,
-                           CONST LPXFORM  Unsafexform1,
-                           CONST LPXFORM  Unsafexform2)
-{
-  XFORM  xformTemp;
-  XFORM  xform1 = {0}, xform2 = {0};
-  NTSTATUS Status = STATUS_SUCCESS;
-  BOOL Ret;
-
-  _SEH_TRY
-  {
-    ProbeForWrite(UnsafeXFormResult,
-                  sizeof(XFORM),
-                  1);
-    ProbeForRead(Unsafexform1,
-                 sizeof(XFORM),
-                 1);
-    ProbeForRead(Unsafexform2,
-                 sizeof(XFORM),
-                 1);
-    xform1 = *Unsafexform1;
-    xform2 = *Unsafexform2;
-  }
-  _SEH_HANDLE
-  {
-    Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-  if(!NT_SUCCESS(Status))
-  {
-    SetLastNtError(Status);
-    return FALSE;
-  }
-
-  Ret = IntGdiCombineTransform(&xformTemp, &xform1, &xform2);
-
-  /* Copy the result to xformResult */
-  _SEH_TRY
-  {
-    /* pointer was already probed! */
-    *UnsafeXFormResult = xformTemp;
-  }
-  _SEH_HANDLE
-  {
-    Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-  if(!NT_SUCCESS(Status))
-  {
-    SetLastNtError(Status);
-    return FALSE;
-  }
-
-  return Ret;
-}
+    PDC_ATTR pdcattr;
+    LONG fx, fy, s;
 
-VOID FASTCALL
-CoordDPtoLP(PDC Dc, LPPOINT Point)
-{
-FLOAT x, y;
-  x = (FLOAT)Point->x;
-  y = (FLOAT)Point->y;
-  Point->x = x * Dc->w.xformVport2World.eM11 +
-    y * Dc->w.xformVport2World.eM21 + Dc->w.xformVport2World.eDx;
-  Point->y = x * Dc->w.xformVport2World.eM12 +
-    y * Dc->w.xformVport2World.eM22 + Dc->w.xformVport2World.eDy;
-}
+    /* Get a pointer to the DC_ATTR */
+    pdcattr = dc->pdcattr;
 
-VOID
-FASTCALL
-IntDPtoLP ( PDC dc, LPPOINT Points, INT Count )
-{
-  INT i;
+    /* Check if all values are valid */
+    if (pdcattr->szlWindowExt.cx == 0 || pdcattr->szlWindowExt.cy == 0 ||
+        pdcattr->szlViewportExt.cx == 0 || pdcattr->szlViewportExt.cy == 0)
+    {
+        /* Don't recalculate */
+        return;
+    }
 
-  ASSERT ( Points );
+    fx = abs(pdcattr->szlWindowExt.cx * pdcattr->szlViewportExt.cy);
+    fy = abs(pdcattr->szlWindowExt.cy * pdcattr->szlViewportExt.cx);
 
-  for ( i = 0; i < Count; i++ )
-    CoordDPtoLP ( dc, &Points[i] );
+    if (fy > fx)
+    {
+        s = pdcattr->szlWindowExt.cy * pdcattr->szlViewportExt.cx > 0 ? 1 : -1;
+        pdcattr->szlViewportExt.cx = s * fx / pdcattr->szlWindowExt.cy;
+    }
+    else if (fx > fy)
+    {
+        s = pdcattr->szlWindowExt.cx * pdcattr->szlViewportExt.cy > 0 ? 1 : -1;
+        pdcattr->szlViewportExt.cy = s * fy / pdcattr->szlWindowExt.cx;
+    }
 }
 
-int
-FASTCALL
-IntGetGraphicsMode ( PDC dc )
+// FIXME: don't use floating point in the kernel! use XFORMOBJ function
+BOOL FASTCALL
+IntGdiCombineTransform(
+    LPXFORM XFormResult,
+    LPXFORM xform1,
+    LPXFORM xform2)
 {
-  ASSERT ( dc );
-  return dc->Dc_Attr.iGraphicsMode;
-}
+    XFORM xformTemp;
+    /* Check for illegal parameters */
+    if (!XFormResult || !xform1 || !xform2)
+    {
+        return  FALSE;
+    }
 
-BOOL
-FASTCALL
-IntGdiModifyWorldTransform(PDC pDc,
-                           CONST LPXFORM lpXForm,
-                           DWORD Mode)
-{
-   ASSERT(pDc && lpXForm);
-
-   switch(Mode)
-   {
-     case MWT_IDENTITY:
-       pDc->w.xformWorld2Wnd.eM11 = 1.0f;
-       pDc->w.xformWorld2Wnd.eM12 = 0.0f;
-       pDc->w.xformWorld2Wnd.eM21 = 0.0f;
-       pDc->w.xformWorld2Wnd.eM22 = 1.0f;
-       pDc->w.xformWorld2Wnd.eDx  = 0.0f;
-       pDc->w.xformWorld2Wnd.eDy  = 0.0f;
-       break;
-
-     case MWT_LEFTMULTIPLY:
-       IntGdiCombineTransform(&pDc->w.xformWorld2Wnd, lpXForm, &pDc->w.xformWorld2Wnd );
-       break;
-
-     case MWT_RIGHTMULTIPLY:
-       IntGdiCombineTransform(&pDc->w.xformWorld2Wnd, &pDc->w.xformWorld2Wnd, lpXForm);
-       break;
-
-     case MWT_MAX+1: // Must be MWT_SET????
-       pDc->w.xformWorld2Wnd = *lpXForm; // Do it like Wine.
-       break;
-
-     default:
-       SetLastWin32Error(ERROR_INVALID_PARAMETER);
-       return FALSE;
-  }
-
-  DC_UpdateXforms(pDc);
-  return TRUE;
+    /* Create the result in a temporary XFORM, since xformResult may be
+     * equal to xform1 or xform2 */
+    xformTemp.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
+    xformTemp.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
+    xformTemp.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
+    xformTemp.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
+    xformTemp.eDx  = xform1->eDx  * xform2->eM11 + xform1->eDy  * xform2->eM21 + xform2->eDx;
+    xformTemp.eDy  = xform1->eDx  * xform2->eM12 + xform1->eDy  * xform2->eM22 + xform2->eDy;
+    *XFormResult = xformTemp;
+
+    return TRUE;
 }
 
-int
-STDCALL
-NtGdiGetGraphicsMode ( HDC hDC )
+// FIXME: should be XFORML and use XFORMOBJ functions
+BOOL APIENTRY NtGdiCombineTransform(
+    LPXFORM  UnsafeXFormResult,
+    LPXFORM  Unsafexform1,
+    LPXFORM  Unsafexform2)
 {
-  PDC dc;
-  int GraphicsMode; // default to failure
+    BOOL Ret;
 
-  dc = DC_LockDc ( hDC );
-  if (!dc)
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return 0;
-  }
-
-  GraphicsMode = dc->Dc_Attr.iGraphicsMode;
+    _SEH2_TRY
+    {
+        ProbeForWrite(UnsafeXFormResult, sizeof(XFORM), 1);
+        ProbeForRead(Unsafexform1, sizeof(XFORM), 1);
+        ProbeForRead(Unsafexform2, sizeof(XFORM), 1);
+        Ret = IntGdiCombineTransform(UnsafeXFormResult,
+                                     Unsafexform1,
+                                     Unsafexform2);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Ret = FALSE;
+    }
+    _SEH2_END;
 
-  DC_UnlockDc(dc);
-  return GraphicsMode;
+    return Ret;
 }
 
+// FIXME: Don't use floating point in the kernel
 BOOL
-STDCALL
-NtGdiGetTransform(HDC  hDC,
-               DWORD iXform,
-              LPXFORM  XForm)
-{
-  PDC  dc;
-  NTSTATUS Status = STATUS_SUCCESS;
-
-  dc = DC_LockDc ( hDC );
-  if (!dc)
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return FALSE;
-  }
-  if (!XForm)
-  {
-    DC_UnlockDc(dc);
-    SetLastWin32Error(ERROR_INVALID_PARAMETER);
-    return FALSE;
-  }
-
-  _SEH_TRY
-  {
-    ProbeForWrite(XForm,
-                  sizeof(XFORM),
-                  1);
-   switch(iXform)
-   {
-     case GdiWorldSpaceToPageSpace:
-        *XForm = dc->w.xformWorld2Wnd;
-     break;
-     default:
-     break;
-   }
-  }
-  _SEH_HANDLE
-  {
-    Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-  DC_UnlockDc(dc);
-  return NT_SUCCESS(Status);
-}
-
-VOID
 FASTCALL
-CoordLPtoDP ( PDC Dc, LPPOINT Point )
+IntGdiModifyWorldTransform(
+    PDC pDc,
+    CONST LPXFORM lpXForm,
+    DWORD Mode)
 {
-  FLOAT x, y;
-
-  ASSERT ( Dc );
-  ASSERT ( Point );
+    ASSERT(pDc);
+    XFORM xformWorld2Wnd;
 
-  x = (FLOAT)Point->x;
-  y = (FLOAT)Point->y;
-  Point->x = x * Dc->w.xformWorld2Vport.eM11 +
-    y * Dc->w.xformWorld2Vport.eM21 + Dc->w.xformWorld2Vport.eDx;
-  Point->y = x * Dc->w.xformWorld2Vport.eM12 +
-    y * Dc->w.xformWorld2Vport.eM22 + Dc->w.xformWorld2Vport.eDy;
+    switch (Mode)
+    {
+        case MWT_IDENTITY:
+            xformWorld2Wnd.eM11 = 1.0f;
+            xformWorld2Wnd.eM12 = 0.0f;
+            xformWorld2Wnd.eM21 = 0.0f;
+            xformWorld2Wnd.eM22 = 1.0f;
+            xformWorld2Wnd.eDx  = 0.0f;
+            xformWorld2Wnd.eDy  = 0.0f;
+            XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
+            break;
+
+        case MWT_LEFTMULTIPLY:
+            MatrixS2XForm(&xformWorld2Wnd, &pDc->dclevel.mxWorldToPage);
+            IntGdiCombineTransform(&xformWorld2Wnd, lpXForm, &xformWorld2Wnd);
+            XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
+            break;
+
+        case MWT_RIGHTMULTIPLY:
+            MatrixS2XForm(&xformWorld2Wnd, &pDc->dclevel.mxWorldToPage);
+            IntGdiCombineTransform(&xformWorld2Wnd, &xformWorld2Wnd, lpXForm);
+            XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
+            break;
+
+        case MWT_MAX+1: // Must be MWT_SET????
+            XForm2MatrixS(&pDc->dclevel.mxWorldToPage, lpXForm); // Do it like Wine.
+            break;
+
+        default:
+            return FALSE;
+    }
+    DC_UpdateXforms(pDc);
+    return TRUE;
 }
 
-VOID
-FASTCALL
-IntLPtoDP ( PDC dc, LPPOINT Points, INT Count )
+// FIXME: Should be XFORML and use XFORMOBJ functions directly
+BOOL
+APIENTRY
+NtGdiGetTransform(
+    HDC  hDC,
+    DWORD iXform,
+    LPXFORM  XForm)
 {
-  INT i;
+    PDC  dc;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-  ASSERT ( Points );
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!XForm)
+    {
+        DC_UnlockDc(dc);
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-  for ( i = 0; i < Count; i++ )
-    CoordLPtoDP ( dc, &Points[i] );
+    _SEH2_TRY
+    {
+        ProbeForWrite(XForm, sizeof(XFORM), 1);
+        switch (iXform)
+        {
+            case GdiWorldSpaceToPageSpace:
+                MatrixS2XForm(XForm, &dc->dclevel.mxWorldToPage);
+                break;
+
+            default:
+                break;
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    DC_UnlockDc(dc);
+    return NT_SUCCESS(Status);
 }
 
+
 /*!
  * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
  * world transfrom, viewport origin settings for the given device context.
@@ -310,624 +223,1074 @@ IntLPtoDP ( PDC dc, LPPOINT Points, INT Count )
 */
 BOOL
 APIENTRY
-NtGdiTransformPoints( HDC hDC,
-                      PPOINT UnsafePtsIn,
-                      PPOINT UnsafePtOut,
-                      INT Count,
-                      INT iMode )
+NtGdiTransformPoints(
+    HDC hDC,
+    PPOINT UnsafePtsIn,
+    PPOINT UnsafePtOut,
+    INT Count,
+    INT iMode)
 {
-   PDC dc;
-   NTSTATUS Status = STATUS_SUCCESS;
-   LPPOINT Points;
-   ULONG Size;
-
-   dc = DC_LockDc(hDC);
-   if (!dc)
-   {
-     SetLastWin32Error(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
-
-   if (!UnsafePtsIn || !UnsafePtOut || Count <= 0)
-   {
-     DC_UnlockDc(dc);
-     SetLastWin32Error(ERROR_INVALID_PARAMETER);
-     return FALSE;
-   }
-
-   Size = Count * sizeof(POINT);
-
-   Points = (LPPOINT)ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
-   if(!Points)
-   {
-     DC_UnlockDc(dc);
-     SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-     return FALSE;
-   }
-
-   _SEH_TRY
-   {
-      ProbeForWrite(UnsafePtOut,
-                    Size,
-                    1);
-      ProbeForRead(UnsafePtsIn,
-                    Size,
-                    1);
-      RtlCopyMemory(Points,
-                    UnsafePtsIn,
-                    Size);
-   }
-   _SEH_HANDLE
-   {
-      Status = _SEH_GetExceptionCode();
-   }
-   _SEH_END;
-
-   if(!NT_SUCCESS(Status))
-   {
-     DC_UnlockDc(dc);
-     ExFreePool(Points);
-     SetLastNtError(Status);
-     return FALSE;
-   }
-
-   switch (iMode)
-   {
-      case GdiDpToLp:
-        IntDPtoLP(dc, Points, Count);
-        break;
-      case GdiLpToDp:
-        IntLPtoDP(dc, Points, Count);
-        break;
-      case 2: // Not supported yet. Need testing.
-      default:
-      {
+    PDC dc;
+    NTSTATUS Status = STATUS_SUCCESS;
+    LPPOINT Points;
+    ULONG Size;
+
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (!UnsafePtsIn || !UnsafePtOut || Count <= 0)
+    {
         DC_UnlockDc(dc);
-        ExFreePool(Points);
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return FALSE;
-      }
-   }
-
-   _SEH_TRY
-   {
-      /* pointer was already probed! */
-      RtlCopyMemory(UnsafePtOut,
-                    Points,
-                    Size);
-   }
-   _SEH_HANDLE
-   {
-      Status = _SEH_GetExceptionCode();
-   }
-   _SEH_END;
-
-   if(!NT_SUCCESS(Status))
-   {
-     DC_UnlockDc(dc);
-     ExFreePool(Points);
-     SetLastNtError(Status);
-     return FALSE;
-   }
+    }
+
+    Size = Count * sizeof(POINT);
+
+    // FIXME: It would be wise to have a small stack buffer as optimization
+    Points = ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
+    if (!Points)
+    {
+        DC_UnlockDc(dc);
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    _SEH2_TRY
+    {
+        ProbeForWrite(UnsafePtOut, Size, 1);
+        ProbeForRead(UnsafePtsIn, Size, 1);
+        RtlCopyMemory(Points, UnsafePtsIn, Size);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    if (!NT_SUCCESS(Status))
+    {
+        DC_UnlockDc(dc);
+        ExFreePoolWithTag(Points, TAG_COORD);
+        SetLastNtError(Status);
+        return FALSE;
+    }
+
+    switch (iMode)
+    {
+        case GdiDpToLp:
+            IntDPtoLP(dc, Points, Count);
+            break;
+
+        case GdiLpToDp:
+            IntLPtoDP(dc, Points, Count);
+            break;
+
+        case 2: // Not supported yet. Need testing.
+        default:
+        {
+            DC_UnlockDc(dc);
+            ExFreePoolWithTag(Points, TAG_COORD);
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+    }
+
+    _SEH2_TRY
+    {
+        /* pointer was already probed! */
+        RtlCopyMemory(UnsafePtOut, Points, Size);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    if (!NT_SUCCESS(Status))
+    {
+        DC_UnlockDc(dc);
+        ExFreePoolWithTag(Points, TAG_COORD);
+        SetLastNtError(Status);
+        return FALSE;
+    }
 //
 // If we are getting called that means User XForms is a mess!
 //
-   DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-   DC_UnlockDc(dc);
-   ExFreePool(Points);
-   return TRUE;
+    DC_UnlockDc(dc);
+    ExFreePoolWithTag(Points, TAG_COORD);
+    return TRUE;
 }
 
 BOOL
-STDCALL
-NtGdiModifyWorldTransform(HDC hDC,
-                          CONST LPXFORM  UnsafeXForm,
-                          DWORD Mode)
+APIENTRY
+NtGdiModifyWorldTransform(
+    HDC hDC,
+    LPXFORM  UnsafeXForm,
+    DWORD Mode)
 {
-   PDC dc;
-   XFORM SafeXForm;
-   BOOL Ret = FALSE;
-
-   if (!UnsafeXForm)
-   {
-     SetLastWin32Error(ERROR_INVALID_PARAMETER);
-     return FALSE;
-   }
-   
-   dc = DC_LockDc(hDC);
-   if (!dc)
-   {
-     SetLastWin32Error(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
-
-   _SEH_TRY
-   {
-      ProbeForRead(UnsafeXForm, sizeof(XFORM), 1);
-      RtlCopyMemory(&SafeXForm, UnsafeXForm, sizeof(XFORM));
-
-      Ret = IntGdiModifyWorldTransform(dc, &SafeXForm, Mode);
-   }
-   _SEH_HANDLE
-   {
-      SetLastNtError(_SEH_GetExceptionCode());
-   }
-   _SEH_END;
-
-   DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-   DC_UnlockDc(dc);
-   return Ret;
+    PDC dc;
+    XFORM SafeXForm;
+    BOOL Ret = TRUE;
+
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    // The xform is permitted to be NULL for MWT_IDENTITY.
+    // However, if it is not NULL, then it must be valid even though it is not used.
+    if (UnsafeXForm != NULL || Mode != MWT_IDENTITY)
+    {
+        _SEH2_TRY
+        {
+            ProbeForRead(UnsafeXForm, sizeof(XFORM), 1);
+            RtlCopyMemory(&SafeXForm, UnsafeXForm, sizeof(XFORM));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Ret = FALSE;
+        }
+        _SEH2_END;
+    }
+
+    // Safe to handle kernel mode data.
+    if (Ret) Ret = IntGdiModifyWorldTransform(dc, &SafeXForm, Mode);
+    DC_UnlockDc(dc);
+    return Ret;
 }
 
 BOOL
-STDCALL
-NtGdiOffsetViewportOrgEx(HDC hDC,
-                        int XOffset,
-                        int YOffset,
-                        LPPOINT UnsafePoint)
+APIENTRY
+NtGdiOffsetViewportOrgEx(
+    HDC hDC,
+    int XOffset,
+    int YOffset,
+    LPPOINT UnsafePoint)
 {
-  PDC      dc;
-  NTSTATUS Status = STATUS_SUCCESS;
+    PDC      dc;
+    PDC_ATTR pdcattr;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-  dc = DC_LockDc ( hDC );
-  if(!dc)
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return FALSE;
-  }
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    pdcattr = dc->pdcattr;
 
-  if (UnsafePoint)
+    if (UnsafePoint)
     {
-        _SEH_TRY
+        _SEH2_TRY
+        {
+            ProbeForWrite(UnsafePoint, sizeof(POINT), 1);
+            UnsafePoint->x = pdcattr->ptlViewportOrg.x;
+            UnsafePoint->y = pdcattr->ptlViewportOrg.y;
+            if (pdcattr->dwLayout & LAYOUT_RTL)
+            {
+                UnsafePoint->x = -UnsafePoint->x;
+            }
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            ProbeForWrite(UnsafePoint,
-                          sizeof(POINT),
-                          1);
-            UnsafePoint->x = dc->Dc_Attr.ptlViewportOrg.x;
-            UnsafePoint->y = dc->Dc_Attr.ptlViewportOrg.y;
+            Status = _SEH2_GetExceptionCode();
         }
-        _SEH_HANDLE
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
         {
-            Status = _SEH_GetExceptionCode();
+            SetLastNtError(Status);
+            DC_UnlockDc(dc);
+            return FALSE;
         }
-        _SEH_END;
-
-       if ( !NT_SUCCESS(Status) )
-         {
-           SetLastNtError(Status);
-           DC_UnlockDc(dc);
-           return FALSE;
-         }
-    }
-
-  dc->Dc_Attr.ptlViewportOrg.x += XOffset;
-  dc->Dc_Attr.ptlViewportOrg.y += YOffset;
-  DC_UpdateXforms(dc);
-  DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  DC_UnlockDc(dc);
-  return TRUE;
+    }
+
+    if (pdcattr->dwLayout & LAYOUT_RTL)
+    {
+        XOffset = -XOffset;
+    }
+    pdcattr->ptlViewportOrg.x += XOffset;
+    pdcattr->ptlViewportOrg.y += YOffset;
+    DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
+
+    return TRUE;
 }
 
 BOOL
-STDCALL
-NtGdiOffsetWindowOrgEx(HDC  hDC,
-                      int  XOffset,
-                      int  YOffset,
-                      LPPOINT  Point)
+APIENTRY
+NtGdiOffsetWindowOrgEx(
+    HDC hDC,
+    int XOffset,
+    int YOffset,
+    LPPOINT Point)
 {
-  PDC dc;
-
-  dc = DC_LockDc(hDC);
-  if (!dc)
-    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-    }
-
-  if (Point)
-    {
-      NTSTATUS Status = STATUS_SUCCESS;
-      
-      _SEH_TRY
-      {
-         ProbeForWrite(Point,
-                       sizeof(POINT),
-                       1);
-         Point->x = dc->Dc_Attr.ptlWindowOrg.x;
-         Point->y = dc->Dc_Attr.ptlWindowOrg.y;
-      }
-      _SEH_HANDLE
-      {
-         Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
-
-      if(!NT_SUCCESS(Status))
-      {
-        SetLastNtError(Status);
-        DC_UnlockDc(dc);
+    PDC dc;
+    PDC_ATTR pdcattr;
+
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
-      }
+    }
+    pdcattr = dc->pdcattr;
+
+    if (Point)
+    {
+        NTSTATUS Status = STATUS_SUCCESS;
+
+        _SEH2_TRY
+        {
+            ProbeForWrite(Point, sizeof(POINT), 1);
+            Point->x = pdcattr->ptlWindowOrg.x;
+            Point->y = pdcattr->ptlWindowOrg.y;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            DC_UnlockDc(dc);
+            return FALSE;
+        }
     }
 
-  dc->Dc_Attr.ptlWindowOrg.x += XOffset;
-  dc->Dc_Attr.ptlWindowOrg.y += YOffset;
+    pdcattr->ptlWindowOrg.x += XOffset;
+    pdcattr->ptlWindowOrg.y += YOffset;
 
-  DC_UpdateXforms(dc);
-  DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  DC_UnlockDc(dc);
+    DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
 
-  return TRUE;
+    return TRUE;
 }
 
 BOOL
-STDCALL
-NtGdiScaleViewportExtEx(HDC  hDC,
-                             int  Xnum,
-                             int  Xdenom,
-                             int  Ynum,
-                             int  Ydenom,
-                             LPSIZE  Size)
+APIENTRY
+NtGdiScaleViewportExtEx(
+    HDC hDC,
+    int Xnum,
+    int Xdenom,
+    int Ynum,
+    int Ydenom,
+    LPSIZE pSize)
 {
-   UNIMPLEMENTED;
-   return FALSE;
+    PDC pDC;
+    PDC_ATTR pdcattr;
+    BOOL Ret = FALSE;
+    LONG X, Y;
+
+    pDC = DC_LockDc(hDC);
+    if (!pDC)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    pdcattr = pDC->pdcattr;
+
+    if (pSize)
+    {
+        NTSTATUS Status = STATUS_SUCCESS;
+
+        _SEH2_TRY
+        {
+            ProbeForWrite(pSize, sizeof(LPSIZE), 1);
+
+            pSize->cx = pdcattr->szlViewportExt.cx;
+            pSize->cy = pdcattr->szlViewportExt.cy;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            DC_UnlockDc(pDC);
+            return FALSE;
+        }
+    }
+
+    if (pdcattr->iMapMode > MM_TWIPS)
+    {
+        if (Xdenom && Ydenom)
+        {
+            X = Xnum * pdcattr->szlViewportExt.cx / Xdenom;
+            if (X)
+            {
+                Y = Ynum * pdcattr->szlViewportExt.cy / Ydenom;
+                if (Y)
+                {
+                    pdcattr->szlViewportExt.cx = X;
+                    pdcattr->szlViewportExt.cy = Y;
+
+                    IntMirrorWindowOrg(pDC);
+
+                    pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
+                                         INVALIDATE_ATTRIBUTES |
+                                         DEVICE_TO_WORLD_INVALID);
+
+                    if (pdcattr->iMapMode == MM_ISOTROPIC)
+                    {
+                        IntFixIsotropicMapping(pDC);
+                    }
+                    DC_UpdateXforms(pDC);
+
+                    Ret = TRUE;
+                }
+            }
+        }
+    }
+    else
+        Ret = TRUE;
+
+    DC_UnlockDc(pDC);
+    return Ret;
 }
 
 BOOL
-STDCALL
-NtGdiScaleWindowExtEx(HDC  hDC,
-                           int  Xnum,
-                           int  Xdenom,
-                           int  Ynum,
-                           int  Ydenom,
-                           LPSIZE  Size)
+APIENTRY
+NtGdiScaleWindowExtEx(
+    HDC hDC,
+    int Xnum,
+    int Xdenom,
+    int Ynum,
+    int Ydenom,
+    LPSIZE pSize)
 {
-   UNIMPLEMENTED;
-   return FALSE;
-}
+    PDC pDC;
+    PDC_ATTR pdcattr;
+    BOOL Ret = FALSE;
+    LONG X, Y;
 
-int
-STDCALL
-NtGdiSetGraphicsMode(HDC  hDC,
-                    int  Mode)
-{
-  INT ret;
-  PDC dc;
+    pDC = DC_LockDc(hDC);
+    if (!pDC)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    pdcattr = pDC->pdcattr;
 
-  dc = DC_LockDc (hDC);
-  if (!dc)
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return 0;
-  }
+    if (pSize)
+    {
+        NTSTATUS Status = STATUS_SUCCESS;
 
-  /* One would think that setting the graphics mode to GM_COMPATIBLE
-   * would also reset the world transformation matrix to the unity
-   * matrix. However, in Windows, this is not the case. This doesn't
-   * make a lot of sense to me, but that's the way it is.
-   */
+        _SEH2_TRY
+        {
+            ProbeForWrite(pSize, sizeof(LPSIZE), 1);
 
-  if ((Mode != GM_COMPATIBLE) && (Mode != GM_ADVANCED))
+            X = pdcattr->szlWindowExt.cx;
+            if (pdcattr->dwLayout & LAYOUT_RTL) X = -X;
+            pSize->cx = X;
+            pSize->cy = pdcattr->szlWindowExt.cy;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            DC_UnlockDc(pDC);
+            return FALSE;
+        }
+    }
+
+    if (pdcattr->iMapMode > MM_TWIPS)
     {
-      DC_UnlockDc(dc);
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return 0;
+        if (Xdenom && Ydenom)
+        {
+            X = Xnum * pdcattr->szlWindowExt.cx / Xdenom;
+            if (X)
+            {
+                Y = Ynum * pdcattr->szlWindowExt.cy / Ydenom;
+                if (Y)
+                {
+                    pdcattr->szlWindowExt.cx = X;
+                    pdcattr->szlWindowExt.cy = Y;
+
+                    IntMirrorWindowOrg(pDC);
+
+                    pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
+
+                    if (pdcattr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
+                    DC_UpdateXforms(pDC);
+
+                    Ret = TRUE;
+                }
+            }
+        }
     }
+    else
+        Ret = TRUE;
 
-  ret = dc->Dc_Attr.iGraphicsMode;
-  dc->Dc_Attr.iGraphicsMode = Mode;
-  DC_UnlockDc(dc);
-  return  ret;
+    DC_UnlockDc(pDC);
+    return Ret;
 }
 
 int
-STDCALL
-IntGdiSetMapMode(PDC  dc,
-                int  MapMode)
+APIENTRY
+IntGdiSetMapMode(
+    PDC dc,
+    int MapMode)
 {
-  int PrevMapMode;
+    int PrevMapMode;
+    PDC_ATTR pdcattr = dc->pdcattr;
 
-  PrevMapMode = dc->Dc_Attr.iMapMode;
+    PrevMapMode = pdcattr->iMapMode;
 
-  if (MapMode != dc->Dc_Attr.iMapMode || (MapMode != MM_ISOTROPIC && MapMode != MM_ANISOTROPIC))
-  {
-    dc->Dc_Attr.iMapMode = MapMode;
+    pdcattr->iMapMode = MapMode;
 
     switch (MapMode)
     {
-      case MM_TEXT:
-        dc->Dc_Attr.szlWindowExt.cx = 1;
-        dc->Dc_Attr.szlWindowExt.cy = 1;
-        dc->Dc_Attr.szlViewportExt.cx = 1;
-        dc->Dc_Attr.szlViewportExt.cy = 1;
-        break;
-
-      case MM_LOMETRIC:
-      case MM_ISOTROPIC:
-        dc->Dc_Attr.szlWindowExt.cx = dc->GDIInfo->ulHorzSize * 10;
-        dc->Dc_Attr.szlWindowExt.cy = dc->GDIInfo->ulVertSize * 10;
-        dc->Dc_Attr.szlViewportExt.cx = dc->GDIInfo->ulHorzRes;
-        dc->Dc_Attr.szlViewportExt.cy = -dc->GDIInfo->ulVertRes;
-        break;
-
-      case MM_HIMETRIC:
-        dc->Dc_Attr.szlWindowExt.cx = dc->GDIInfo->ulHorzSize * 100;
-        dc->Dc_Attr.szlWindowExt.cy = dc->GDIInfo->ulVertSize * 100;
-        dc->Dc_Attr.szlViewportExt.cx = dc->GDIInfo->ulHorzRes;
-        dc->Dc_Attr.szlViewportExt.cy = -dc->GDIInfo->ulVertRes;
-        break;
-
-      case MM_LOENGLISH:
-        dc->Dc_Attr.szlWindowExt.cx = EngMulDiv(1000, dc->GDIInfo->ulHorzSize, 254);
-        dc->Dc_Attr.szlWindowExt.cy = EngMulDiv(1000, dc->GDIInfo->ulVertSize, 254);
-        dc->Dc_Attr.szlViewportExt.cx = dc->GDIInfo->ulHorzRes;
-        dc->Dc_Attr.szlViewportExt.cy = -dc->GDIInfo->ulVertRes;
-        break;
-
-      case MM_HIENGLISH:
-        dc->Dc_Attr.szlWindowExt.cx = EngMulDiv(10000, dc->GDIInfo->ulHorzSize, 254);
-        dc->Dc_Attr.szlWindowExt.cy = EngMulDiv(10000, dc->GDIInfo->ulVertSize, 254);
-        dc->Dc_Attr.szlViewportExt.cx = dc->GDIInfo->ulHorzRes;
-        dc->Dc_Attr.szlViewportExt.cy = -dc->GDIInfo->ulVertRes;
-        break;
-
-      case MM_TWIPS:
-        dc->Dc_Attr.szlWindowExt.cx = EngMulDiv(14400, dc->GDIInfo->ulHorzSize, 254);
-        dc->Dc_Attr.szlWindowExt.cy = EngMulDiv(14400, dc->GDIInfo->ulVertSize, 254);
-        dc->Dc_Attr.szlViewportExt.cx = dc->GDIInfo->ulHorzRes;
-        dc->Dc_Attr.szlViewportExt.cy = -dc->GDIInfo->ulVertRes;
-        break;
-
-      case MM_ANISOTROPIC:
-        break;
+        case MM_TEXT:
+            pdcattr->szlWindowExt.cx = 1;
+            pdcattr->szlWindowExt.cy = 1;
+            pdcattr->szlViewportExt.cx = 1;
+            pdcattr->szlViewportExt.cy = 1;
+            pdcattr->flXform &= ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
+                                  PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP);
+            pdcattr->flXform |= (PAGE_XLATE_CHANGED|PAGE_TO_DEVICE_SCALE_IDENTITY|
+                                 INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
+            break;
+
+        case MM_ISOTROPIC:
+            pdcattr->flXform |= ISO_OR_ANISO_MAP_MODE;
+            /* Fall through */
+
+        case MM_LOMETRIC:
+            pdcattr->szlWindowExt.cx = dc->ppdev->GDIInfo.ulHorzSize * 10;
+            pdcattr->szlWindowExt.cy = dc->ppdev->GDIInfo.ulVertSize * 10;
+            pdcattr->szlViewportExt.cx = dc->ppdev->GDIInfo.ulHorzRes;
+            pdcattr->szlViewportExt.cy = -dc->ppdev->GDIInfo.ulVertRes;
+            break;
+
+        case MM_HIMETRIC:
+            pdcattr->szlWindowExt.cx = dc->ppdev->GDIInfo.ulHorzSize * 100;
+            pdcattr->szlWindowExt.cy = dc->ppdev->GDIInfo.ulVertSize * 100;
+            pdcattr->szlViewportExt.cx = dc->ppdev->GDIInfo.ulHorzRes;
+            pdcattr->szlViewportExt.cy = -dc->ppdev->GDIInfo.ulVertRes;
+            break;
+
+        case MM_LOENGLISH:
+            pdcattr->szlWindowExt.cx = MulDiv(1000, dc->ppdev->GDIInfo.ulHorzSize, 254);
+            pdcattr->szlWindowExt.cy = MulDiv(1000, dc->ppdev->GDIInfo.ulVertSize, 254);
+            pdcattr->szlViewportExt.cx = dc->ppdev->GDIInfo.ulHorzRes;
+            pdcattr->szlViewportExt.cy = -dc->ppdev->GDIInfo.ulVertRes;
+            break;
+
+        case MM_HIENGLISH:
+            pdcattr->szlWindowExt.cx = MulDiv(10000, dc->ppdev->GDIInfo.ulHorzSize, 254);
+            pdcattr->szlWindowExt.cy = MulDiv(10000, dc->ppdev->GDIInfo.ulVertSize, 254);
+            pdcattr->szlViewportExt.cx = dc->ppdev->GDIInfo.ulHorzRes;
+            pdcattr->szlViewportExt.cy = -dc->ppdev->GDIInfo.ulVertRes;
+            break;
+
+        case MM_TWIPS:
+            pdcattr->szlWindowExt.cx = MulDiv(14400, dc->ppdev->GDIInfo.ulHorzSize, 254);
+            pdcattr->szlWindowExt.cy = MulDiv(14400, dc->ppdev->GDIInfo.ulVertSize, 254);
+            pdcattr->szlViewportExt.cx = dc->ppdev->GDIInfo.ulHorzRes;
+            pdcattr->szlViewportExt.cy = -dc->ppdev->GDIInfo.ulVertRes;
+            break;
+
+        case MM_ANISOTROPIC:
+            pdcattr->flXform &= ~(PAGE_TO_DEVICE_IDENTITY|POSITIVE_Y_IS_UP);
+            pdcattr->flXform |= ISO_OR_ANISO_MAP_MODE;
+            break;
+
+        default:
+            pdcattr->iMapMode = PrevMapMode;
+            PrevMapMode = 0;
     }
-
     DC_UpdateXforms(dc);
-    DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  }
 
-  return PrevMapMode;
+    return PrevMapMode;
 }
 
+
 BOOL
-STDCALL
-NtGdiSetViewportExtEx(HDC  hDC,
-                      int  XExtent,
-                      int  YExtent,
-                      LPSIZE  Size)
+APIENTRY
+NtGdiSetViewportOrgEx(
+    HDC hDC,
+    int X,
+    int Y,
+    LPPOINT Point)
 {
-  PDC dc;
-
-  dc = DC_LockDc(hDC);
-  if ( !dc )
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return FALSE;
-  }
-
-  switch (dc->Dc_Attr.iMapMode)
-    {
-      case MM_HIENGLISH:
-      case MM_HIMETRIC:
-      case MM_LOENGLISH:
-      case MM_LOMETRIC:
-      case MM_TEXT:
-      case MM_TWIPS:
-       DC_UnlockDc(dc);
-       return FALSE;
-
-      case MM_ISOTROPIC:
-       // Here we should (probably) check that SetWindowExtEx *really* has
-       // been called
-       break;
-    }
-
-  if (Size)
-    {
-      NTSTATUS Status = STATUS_SUCCESS;
-
-      _SEH_TRY
-      {
-         ProbeForWrite(Size,
-                       sizeof(SIZE),
-                       1);
-         Size->cx = dc->Dc_Attr.szlViewportExt.cx;
-         Size->cy = dc->Dc_Attr.szlViewportExt.cy;
-
-         dc->Dc_Attr.szlViewportExt.cx = XExtent;
-         dc->Dc_Attr.szlViewportExt.cy = YExtent;
-
-         if (dc->Dc_Attr.iMapMode == MM_ISOTROPIC)
-             IntFixIsotropicMapping(dc);
-      }
-      _SEH_HANDLE
-      {
-         Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
-
-      if(!NT_SUCCESS(Status))
-      {
-        SetLastNtError(Status);
-        DC_UnlockDc(dc);
+    PDC dc;
+    PDC_ATTR pdcattr;
+
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
-      }
     }
+    pdcattr = dc->pdcattr;
 
-  
-  DC_UpdateXforms(dc);
-  DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  DC_UnlockDc(dc);
+    if (Point)
+    {
+        NTSTATUS Status = STATUS_SUCCESS;
+
+        _SEH2_TRY
+        {
+            ProbeForWrite(Point, sizeof(POINT), 1);
+            Point->x = pdcattr->ptlViewportOrg.x;
+            Point->y = pdcattr->ptlViewportOrg.y;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            DC_UnlockDc(dc);
+            return FALSE;
+        }
+    }
+
+    pdcattr->ptlViewportOrg.x = X;
+    pdcattr->ptlViewportOrg.y = Y;
+
+    DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
 
-  return TRUE;
+    return TRUE;
 }
 
 BOOL
-STDCALL
-NtGdiSetViewportOrgEx(HDC  hDC,
-                     int  X,
-                     int  Y,
-                     LPPOINT  Point)
+APIENTRY
+NtGdiSetWindowOrgEx(
+    HDC hDC,
+    int X,
+    int Y,
+    LPPOINT Point)
 {
-  PDC dc;
-
-  dc = DC_LockDc(hDC);
-  if (!dc)
-    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-    }
-
-  if (Point)
-    {
-      NTSTATUS Status = STATUS_SUCCESS;
-      
-      _SEH_TRY
-      {
-         ProbeForWrite(Point,
-                       sizeof(POINT),
-                       1);
-         Point->x = dc->Dc_Attr.ptlViewportOrg.x;
-         Point->y = dc->Dc_Attr.ptlViewportOrg.y;
-      }
-      _SEH_HANDLE
-      {
-         Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
-
-      if(!NT_SUCCESS(Status))
-      {
-        SetLastNtError(Status);
-        DC_UnlockDc(dc);
+    PDC dc;
+    PDC_ATTR pdcattr;
+
+    dc = DC_LockDc(hDC);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
-      }
+    }
+    pdcattr = dc->pdcattr;
+
+    if (Point)
+    {
+        NTSTATUS Status = STATUS_SUCCESS;
+
+        _SEH2_TRY
+        {
+            ProbeForWrite(Point, sizeof(POINT), 1);
+            Point->x = pdcattr->ptlWindowOrg.x;
+            Point->y = pdcattr->ptlWindowOrg.y;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            DC_UnlockDc(dc);
+            return FALSE;
+        }
     }
 
-  dc->Dc_Attr.ptlViewportOrg.x = X;
-  dc->Dc_Attr.ptlViewportOrg.y = Y;
+    pdcattr->ptlWindowOrg.x = X;
+    pdcattr->ptlWindowOrg.y = Y;
 
-  DC_UpdateXforms(dc);
-  DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  DC_UnlockDc(dc);
+    DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
 
-  return TRUE;
+    return TRUE;
 }
 
-BOOL
-STDCALL
-NtGdiSetWindowExtEx(HDC  hDC,
-                   int  XExtent,
-                   int  YExtent,
-                   LPSIZE  Size)
+//
+// Mirror Window function.
+//
+VOID
+FASTCALL
+IntMirrorWindowOrg(PDC dc)
 {
-  PDC dc;
-
-  dc = DC_LockDc(hDC);
-  if (!dc)
-    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-    }
-
-  switch (dc->Dc_Attr.iMapMode)
-    {
-      case MM_HIENGLISH:
-      case MM_HIMETRIC:
-      case MM_LOENGLISH:
-      case MM_LOMETRIC:
-      case MM_TEXT:
-      case MM_TWIPS:
-       DC_UnlockDc(dc);
-       return FALSE;
-    }
-
-  if (Size)
-    {
-      NTSTATUS Status = STATUS_SUCCESS;
-      
-      _SEH_TRY
-      {
-         ProbeForWrite(Size,
-                       sizeof(SIZE),
-                       1);
-         Size->cx = dc->Dc_Attr.szlWindowExt.cx;
-         Size->cy = dc->Dc_Attr.szlWindowExt.cy;
-      }
-      _SEH_HANDLE
-      {
-         Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
-
-      if(!NT_SUCCESS(Status))
-      {
-        SetLastNtError(Status);
+    PDC_ATTR pdcattr;
+    LONG X;
+
+    pdcattr = dc->pdcattr;
+
+    if (!(pdcattr->dwLayout & LAYOUT_RTL))
+    {
+        pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx; // Flip it back.
+        return;
+    }
+    if (!pdcattr->szlViewportExt.cx) return;
+    //
+    // WOrgx = wox - (Width - 1) * WExtx / VExtx
+    //
+    X = (dc->erclWindow.right - dc->erclWindow.left) - 1; // Get device width - 1
+
+    X = (X * pdcattr->szlWindowExt.cx) / pdcattr->szlViewportExt.cx;
+
+    pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx - X; // Now set the inverted win origion.
+
+    return;
+}
+
+// NtGdiSetLayout
+//
+// The default is left to right. This function changes it to right to left, which
+// is the standard in Arabic and Hebrew cultures.
+//
+/*
+ * @implemented
+ */
+DWORD
+APIENTRY
+NtGdiSetLayout(
+    IN HDC hdc,
+    IN LONG wox,
+    IN DWORD dwLayout)
+{
+    PDC dc;
+    PDC_ATTR pdcattr;
+    DWORD oLayout;
+
+    dc = DC_LockDc(hdc);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return GDI_ERROR;
+    }
+    pdcattr = dc->pdcattr;
+
+    pdcattr->dwLayout = dwLayout;
+    oLayout = pdcattr->dwLayout;
+
+    if (!(dwLayout & LAYOUT_ORIENTATIONMASK))
+    {
         DC_UnlockDc(dc);
+        return oLayout;
+    }
+
+    if (dwLayout & LAYOUT_RTL)
+    {
+        pdcattr->iMapMode = MM_ANISOTROPIC;
+    }
+
+    pdcattr->szlWindowExt.cy = -pdcattr->szlWindowExt.cy;
+    pdcattr->ptlWindowOrg.x  = -pdcattr->ptlWindowOrg.x;
+
+    if (wox == -1)
+        IntMirrorWindowOrg(dc);
+    else
+        pdcattr->ptlWindowOrg.x = wox - pdcattr->ptlWindowOrg.x;
+
+    if (!(pdcattr->flTextAlign & TA_CENTER)) pdcattr->flTextAlign |= TA_RIGHT;
+
+    if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
+        dc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
+    else
+        dc->dclevel.flPath |= DCPATH_CLOCKWISE;
+
+    pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
+                         INVALIDATE_ATTRIBUTES |
+                         DEVICE_TO_WORLD_INVALID);
+
+//  DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
+    return oLayout;
+}
+
+/*
+ * @implemented
+ */
+LONG
+APIENTRY
+NtGdiGetDeviceWidth(
+    IN HDC hdc)
+{
+    PDC dc;
+    LONG Ret;
+    dc = DC_LockDc(hdc);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return 0;
+    }
+    Ret = dc->erclWindow.right - dc->erclWindow.left;
+    DC_UnlockDc(dc);
+    return Ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtGdiMirrorWindowOrg(
+    IN HDC hdc)
+{
+    PDC dc;
+    dc = DC_LockDc(hdc);
+    if (!dc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    IntMirrorWindowOrg(dc);
+    DC_UnlockDc(dc);
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtGdiSetSizeDevice(
+    IN HDC hdc,
+    IN INT cxVirtualDevice,
+    IN INT cyVirtualDevice)
+{
+    PDC dc;
+    PDC_ATTR pdcattr;
+
+    if (!cxVirtualDevice || !cyVirtualDevice)
+    {
         return FALSE;
-      }
     }
 
-  dc->Dc_Attr.szlWindowExt.cx = XExtent;
-  dc->Dc_Attr.szlWindowExt.cy = YExtent;
+    dc = DC_LockDc(hdc);
+    if (!dc) return FALSE;
+
+    pdcattr = dc->pdcattr;
+
+    pdcattr->szlVirtualDeviceSize.cx = cxVirtualDevice;
+    pdcattr->szlVirtualDeviceSize.cy = cyVirtualDevice;
 
-  DC_UpdateXforms(dc);
-  DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  DC_UnlockDc(dc);
+//    DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
 
-  return TRUE;
+    return TRUE;
 }
 
+/*
+ * @implemented
+ */
 BOOL
-STDCALL
-NtGdiSetWindowOrgEx(HDC  hDC,
-                   int  X,
-                   int  Y,
-                   LPPOINT  Point)
+APIENTRY
+NtGdiSetVirtualResolution(
+    IN HDC hdc,
+    IN INT cxVirtualDevicePixel,
+    IN INT cyVirtualDevicePixel,
+    IN INT cxVirtualDeviceMm,
+    IN INT cyVirtualDeviceMm)
 {
-  PDC dc;
-
-  dc = DC_LockDc(hDC);
-  if (!dc)
-    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-    }
-
-  if (Point)
-    {
-      NTSTATUS Status = STATUS_SUCCESS;
-      
-      _SEH_TRY
-      {
-         ProbeForWrite(Point,
-                       sizeof(POINT),
-                       1);
-         Point->x = dc->Dc_Attr.ptlWindowOrg.x;
-         Point->y = dc->Dc_Attr.ptlWindowOrg.y;
-      }
-      _SEH_HANDLE
-      {
-         Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
-
-      if(!NT_SUCCESS(Status))
-      {
-        SetLastNtError(Status);
-        DC_UnlockDc(dc);
+    PDC dc;
+    PDC_ATTR pdcattr;
+
+    // Need test types for zeros and non zeros
+
+    dc = DC_LockDc(hdc);
+    if (!dc) return FALSE;
+
+    pdcattr = dc->pdcattr;
+
+    pdcattr->szlVirtualDevicePixel.cx = cxVirtualDevicePixel;
+    pdcattr->szlVirtualDevicePixel.cy = cyVirtualDevicePixel;
+    pdcattr->szlVirtualDeviceMm.cx = cxVirtualDeviceMm;
+    pdcattr->szlVirtualDeviceMm.cy = cyVirtualDeviceMm;
+
+//    DC_UpdateXforms(dc);
+    DC_UnlockDc(dc);
+    return TRUE;
+}
+
+
+// FIXME: Don't use floating point in the kernel!
+BOOL FASTCALL
+DC_InvertXform(const XFORM *xformSrc,
+               XFORM *xformDest)
+{
+    FLOAT  determinant;
+
+    determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
+    if (determinant > -1e-12 && determinant < 1e-12)
+    {
+        return  FALSE;
+    }
+
+    xformDest->eM11 =  xformSrc->eM22 / determinant;
+    xformDest->eM12 = -xformSrc->eM12 / determinant;
+    xformDest->eM21 = -xformSrc->eM21 / determinant;
+    xformDest->eM22 =  xformSrc->eM11 / determinant;
+    xformDest->eDx  = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
+    xformDest->eDy  = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
+
+    return  TRUE;
+}
+
+
+// FIXME: Don't use floating point in the kernel!
+VOID FASTCALL
+DC_UpdateXforms(PDC dc)
+{
+    XFORM  xformWnd2Vport;
+    DOUBLE  scaleX, scaleY;
+    PDC_ATTR pdcattr = dc->pdcattr;
+    XFORM xformWorld2Vport, xformWorld2Wnd, xformVport2World;
+
+    /* Construct a transformation to do the window-to-viewport conversion */
+    scaleX = (pdcattr->szlWindowExt.cx ? (DOUBLE)pdcattr->szlViewportExt.cx / (DOUBLE)pdcattr->szlWindowExt.cx : 0.0f);
+    scaleY = (pdcattr->szlWindowExt.cy ? (DOUBLE)pdcattr->szlViewportExt.cy / (DOUBLE)pdcattr->szlWindowExt.cy : 0.0f);
+    xformWnd2Vport.eM11 = scaleX;
+    xformWnd2Vport.eM12 = 0.0;
+    xformWnd2Vport.eM21 = 0.0;
+    xformWnd2Vport.eM22 = scaleY;
+    xformWnd2Vport.eDx  = (DOUBLE)pdcattr->ptlViewportOrg.x - scaleX * (DOUBLE)pdcattr->ptlWindowOrg.x;
+    xformWnd2Vport.eDy  = (DOUBLE)pdcattr->ptlViewportOrg.y - scaleY * (DOUBLE)pdcattr->ptlWindowOrg.y;
+
+    /* Combine with the world transformation */
+    MatrixS2XForm(&xformWorld2Vport, &dc->dclevel.mxWorldToDevice);
+    MatrixS2XForm(&xformWorld2Wnd, &dc->dclevel.mxWorldToPage);
+    IntGdiCombineTransform(&xformWorld2Vport, &xformWorld2Wnd, &xformWnd2Vport);
+
+    /* Create inverse of world-to-viewport transformation */
+    MatrixS2XForm(&xformVport2World, &dc->dclevel.mxDeviceToWorld);
+    if (DC_InvertXform(&xformWorld2Vport, &xformVport2World))
+    {
+        pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID;
+    }
+    else
+    {
+        pdcattr->flXform |= DEVICE_TO_WORLD_INVALID;
+    }
+
+    XForm2MatrixS(&dc->dclevel.mxWorldToDevice, &xformWorld2Vport);
+
+}
+
+LONG FASTCALL
+IntCalcFillOrigin(PDC pdc)
+{
+    pdc->ptlFillOrigin.x = pdc->dclevel.ptlBrushOrigin.x + pdc->ptlDCOrig.x;
+    pdc->ptlFillOrigin.y = pdc->dclevel.ptlBrushOrigin.y + pdc->ptlDCOrig.y;
+
+    return pdc->ptlFillOrigin.y;
+}
+
+VOID
+APIENTRY
+GdiSetDCOrg(HDC hDC, LONG Left, LONG Top, PRECTL prc)
+{
+    PDC pdc;
+
+    pdc = DC_LockDc(hDC);
+    if (!pdc) return;
+
+    pdc->ptlDCOrig.x = Left;
+    pdc->ptlDCOrig.y = Top;
+
+    IntCalcFillOrigin(pdc);
+
+    if (prc) pdc->erclWindow = *prc;
+
+    DC_UnlockDc(pdc);
+}
+
+// FIXME: remove me
+BOOL FASTCALL
+IntGdiGetDCOrg(PDC pDc, PPOINTL ppt)
+{
+    *ppt = pDc->ptlDCOrig;
+    return TRUE;
+}
+
+// FIXME: remove me
+BOOL APIENTRY
+GdiGetDCOrgEx(HDC hDC, PPOINTL ppt, PRECTL prc)
+{
+    PDC pdc;
+
+    pdc = DC_LockDc(hDC);
+    if (!pdc) return FALSE;
+
+    *prc = pdc->erclWindow;
+    *ppt = pdc->ptlDCOrig;
+
+    DC_UnlockDc(pdc);
+    return TRUE;
+}
+
+static
+VOID FASTCALL
+DC_vGetAspectRatioFilter(PDC pDC, LPSIZE AspectRatio)
+{
+    if (pDC->pdcattr->flFontMapper & 1) // TRUE assume 1.
+    {
+        // "This specifies that Windows should only match fonts that have the
+        // same aspect ratio as the display.", Programming Windows, Fifth Ed.
+        AspectRatio->cx = pDC->ppdev->GDIInfo.ulLogPixelsX;
+        AspectRatio->cy = pDC->ppdev->GDIInfo.ulLogPixelsY;
+    }
+    else
+    {
+        AspectRatio->cx = 0;
+        AspectRatio->cy = 0;
+    }
+}
+
+VOID
+FASTCALL
+DC_vUpdateViewportExt(PDC pdc)
+{
+    PDC_ATTR pdcattr;
+
+    /* Get a pointer to the dc attribute */
+    pdcattr = pdc->pdcattr;
+
+    /* Check if we need to recalculate */
+    if (pdcattr->flXform & PAGE_EXTENTS_CHANGED)
+    {
+        /* Check if we need to do isotropic fixup */
+        if (pdcattr->iMapMode == MM_ISOTROPIC)
+        {
+            IntFixIsotropicMapping(pdc);
+        }
+
+        /* Update xforms, CHECKME: really done here? */
+        DC_UpdateXforms(pdc);
+    }
+}
+
+BOOL APIENTRY
+NtGdiGetDCPoint(
+    HDC hDC,
+    UINT iPoint,
+    PPOINTL Point)
+{
+    BOOL Ret = TRUE;
+    DC *pdc;
+    POINTL SafePoint;
+    SIZE Size;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (!Point)
+    {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return FALSE;
-      }
     }
 
-  dc->Dc_Attr.ptlWindowOrg.x = X;
-  dc->Dc_Attr.ptlWindowOrg.y = Y;
+    pdc = DC_LockDc(hDC);
+    if (!pdc)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    switch (iPoint)
+    {
+        case GdiGetViewPortExt:
+            DC_vUpdateViewportExt(pdc);
+            SafePoint.x = pdc->pdcattr->szlViewportExt.cx;
+            SafePoint.y = pdc->pdcattr->szlViewportExt.cy;
+            break;
+
+        case GdiGetWindowExt:
+            SafePoint.x = pdc->pdcattr->szlWindowExt.cx;
+            SafePoint.y = pdc->pdcattr->szlWindowExt.cy;
+            break;
+
+        case GdiGetViewPortOrg:
+            SafePoint = pdc->pdcattr->ptlViewportOrg;
+            break;
+
+        case GdiGetWindowOrg:
+            SafePoint = pdc->pdcattr->ptlWindowOrg;
+            break;
+
+        case GdiGetDCOrg:
+            SafePoint = pdc->ptlDCOrig;
+            break;
+
+        case GdiGetAspectRatioFilter:
+            DC_vGetAspectRatioFilter(pdc, &Size);
+            SafePoint.x = Size.cx;
+            SafePoint.y = Size.cy;
+            break;
+
+        default:
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            Ret = FALSE;
+            break;
+    }
+
+    if (Ret)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(Point, sizeof(POINT), 1);
+            *Point = SafePoint;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            Ret = FALSE;
+        }
+    }
+
+    DC_UnlockDc(pdc);
+    return Ret;
+}
 
-  DC_UpdateXforms(dc);
-  DCU_UpdateUserXForms(dc, WORLD_TO_PAGE_IDENTITY|DEVICE_TO_WORLD_INVALID|WORLD_XFORM_CHANGED );
-  DC_UnlockDc(dc);
 
-  return TRUE;
+DWORD
+APIENTRY
+NtGdiGetBoundsRect(
+    IN HDC hdc,
+    OUT LPRECT prc,
+    IN DWORD f)
+{
+    DPRINT1("stub\n");
+    return  DCB_RESET;   /* bounding rectangle always empty */
+}
+
+DWORD
+APIENTRY
+NtGdiSetBoundsRect(
+    IN HDC hdc,
+    IN LPRECT prc,
+    IN DWORD f)
+{
+    DPRINT1("stub\n");
+    return  DCB_DISABLE;   /* bounding rectangle always empty */
 }