diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 130a1ac99e1f452a4615b43c3068ec1c625296a6..6118e443a6f88dc40b000aec524d9a9eddd6accf 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -577,9 +577,9 @@ static BOOL reset_dc_state( HDC hdc )
 
 
 /***********************************************************************
- *           SaveDC    (GDI32.@)
+ *           NtGdiSaveDC    (win32u.@)
  */
-INT WINAPI SaveDC( HDC hdc )
+INT WINAPI NtGdiSaveDC( HDC hdc )
 {
     DC * dc;
     INT ret = 0;
diff --git a/dlls/gdi32/enhmfdrv/dc.c b/dlls/gdi32/enhmfdrv/dc.c
index 1faf777c47ea17f0106852903c2335c6cf2b7384..5148e03a231957956251c905b445fac3f95b2868 100644
--- a/dlls/gdi32/enhmfdrv/dc.c
+++ b/dlls/gdi32/enhmfdrv/dc.c
@@ -22,19 +22,12 @@
 #include <assert.h>
 #include "enhmfdrv/enhmetafiledrv.h"
 
-INT CDECL EMFDRV_SaveDC( PHYSDEV dev )
+BOOL EMFDC_SaveDC( DC_ATTR *dc_attr )
 {
-    PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSaveDC );
-    INT ret = next->funcs->pSaveDC( next );
-
-    if (ret)
-    {
-        EMRSAVEDC emr;
-        emr.emr.iType = EMR_SAVEDC;
-        emr.emr.nSize = sizeof(emr);
-        EMFDRV_WriteRecord( dev, &emr.emr );
-    }
-    return ret;
+    EMRSAVEDC emr;
+    emr.emr.iType = EMR_SAVEDC;
+    emr.emr.nSize = sizeof(emr);
+    return EMFDRV_WriteRecord( dc_attr->emf, &emr.emr );
 }
 
 BOOL CDECL EMFDRV_RestoreDC( PHYSDEV dev, INT level )
diff --git a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
index 981cdea78877d8d690505f9f351d5ae979972869..35ff9af0e905a95f4025cd84fee2cfd61ef88f41 100644
--- a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
+++ b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
@@ -102,7 +102,6 @@ extern BOOL     CDECL EMFDRV_Rectangle( PHYSDEV dev, INT left, INT top, INT righ
 extern BOOL     CDECL EMFDRV_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN;
 extern BOOL     CDECL EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
                                         INT ell_width, INT ell_height ) DECLSPEC_HIDDEN;
-extern INT      CDECL EMFDRV_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern BOOL     CDECL EMFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom,
                                                  INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
 extern BOOL     CDECL EMFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom,
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index 516c6c4e88414d3abd3cd071617c9302bd796fc1..2291e22348f13f721b13133519ed5329794a54cd 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -118,7 +118,7 @@ static const struct gdi_dc_funcs emfdrv_driver =
     NULL,                            /* pResetDC */
     EMFDRV_RestoreDC,                /* pRestoreDC */
     EMFDRV_RoundRect,                /* pRoundRect */
-    EMFDRV_SaveDC,                   /* pSaveDC */
+    NULL,                            /* pSaveDC */
     EMFDRV_ScaleViewportExtEx,       /* pScaleViewportExtEx */
     EMFDRV_ScaleWindowExtEx,         /* pScaleWindowExtEx */
     EMFDRV_SelectBitmap,             /* pSelectBitmap */
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 105d72b23f028f4ef4062de554960aa7b4544c0e..197ee8942c52a02c53ca792e5ed288eb6dc2f689 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -66,6 +66,7 @@ extern BOOL METADC_Polyline( HDC hdc, const POINT *points,INT count) DECLSPEC_HI
 extern BOOL METADC_Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom) DECLSPEC_HIDDEN;
 extern BOOL METADC_RoundRect( HDC hdc, INT left, INT top, INT right, INT bottom,
                               INT ell_width, INT ell_height ) DECLSPEC_HIDDEN;
+extern BOOL METADC_SaveDC( HDC hdc ) DECLSPEC_HIDDEN;
 extern BOOL METADC_SetBkMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN;
 extern BOOL METADC_SetPixel( HDC hdc, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN;
 extern BOOL METADC_SetPolyFillMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN;
@@ -114,6 +115,7 @@ extern BOOL EMFDC_Rectangle( DC_ATTR *dc_attr, INT left, INT top, INT right,
                              INT bottom) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_RoundRect( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom,
                              INT ell_width, INT ell_height ) DECLSPEC_HIDDEN;
+extern BOOL EMFDC_SaveDC( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_SetArcDirection( DC_ATTR *dc_attr, INT dir ) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_SetBkMode( DC_ATTR *dc_attr, INT mode ) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_SetPixel( DC_ATTR *dc_attr, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c
index 42df880f718b211ec0820f50bc639fc5b39ddde7..6dd5940d45aa36981e04eda69cb8740bd28a214b 100644
--- a/dlls/gdi32/gdidc.c
+++ b/dlls/gdi32/gdidc.c
@@ -112,6 +112,19 @@ HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
     return ret;
 }
 
+/***********************************************************************
+ *           SaveDC    (GDI32.@)
+ */
+INT WINAPI SaveDC( HDC hdc )
+{
+    DC_ATTR *dc_attr;
+
+    if (is_meta_dc( hdc )) return METADC_SaveDC( hdc );
+    if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
+    if (dc_attr->emf && !EMFDC_SaveDC( dc_attr )) return FALSE;
+    return NtGdiSaveDC( hdc );
+}
+
 /***********************************************************************
  *		GetTextAlign (GDI32.@)
  */
diff --git a/dlls/gdi32/mfdrv/dc.c b/dlls/gdi32/mfdrv/dc.c
index 044e228b2bfe3eaecad7d444283f7f983bd57370..9513da7160c5272926c7f10a8cbf844ce0c2617f 100644
--- a/dlls/gdi32/mfdrv/dc.c
+++ b/dlls/gdi32/mfdrv/dc.c
@@ -20,9 +20,9 @@
 
 #include "mfdrv/metafiledrv.h"
 
-INT CDECL MFDRV_SaveDC( PHYSDEV dev )
+BOOL METADC_SaveDC( HDC hdc )
 {
-    return MFDRV_MetaParam0( dev, META_SAVEDC );
+    return metadc_param0( hdc, META_SAVEDC );
 }
 
 BOOL CDECL MFDRV_RestoreDC( PHYSDEV dev, INT level )
diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c
index 31a0297c9e3b4e8e5748221998d6f10665d5f57e..70442fac20f29ae0fa3b2c4de0431909a0412317 100644
--- a/dlls/gdi32/mfdrv/init.c
+++ b/dlls/gdi32/mfdrv/init.c
@@ -181,7 +181,7 @@ static const struct gdi_dc_funcs MFDRV_Funcs =
     NULL,                            /* pResetDC */
     MFDRV_RestoreDC,                 /* pRestoreDC */
     NULL,                            /* pRoundRect */
-    MFDRV_SaveDC,                    /* pSaveDC */
+    NULL,                            /* pSaveDC */
     MFDRV_ScaleViewportExtEx,        /* pScaleViewportExtEx */
     MFDRV_ScaleWindowExtEx,          /* pScaleWindowExtEx */
     MFDRV_SelectBitmap,              /* pSelectBitmap */
@@ -613,6 +613,14 @@ BOOL metadc_param1( HDC hdc, short func, short param )
     return MFDRV_MetaParam1( &dev->dev, func, param );
 }
 
+BOOL metadc_param0( HDC hdc, short func )
+{
+    METAFILEDRV_PDEVICE *dev;
+
+    if (!(dev = get_metadc_ptr( hdc ))) return FALSE;
+    return MFDRV_MetaParam0( &dev->dev, func );
+}
+
 BOOL metadc_param2( HDC hdc, short func, short param1, short param2 )
 {
     METAFILEDRV_PDEVICE *dev;
diff --git a/dlls/gdi32/mfdrv/metafiledrv.h b/dlls/gdi32/mfdrv/metafiledrv.h
index 567b60158b243712d61d901d717fa056c9ba0dd0..b3104318223e24038a8b7e54b5db0ee8cab54108 100644
--- a/dlls/gdi32/mfdrv/metafiledrv.h
+++ b/dlls/gdi32/mfdrv/metafiledrv.h
@@ -60,6 +60,7 @@ extern BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index ) DECLSPEC_HIDDEN;
 extern INT16 MFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) DECLSPEC_HIDDEN;
 
 extern METAFILEDRV_PDEVICE *get_metadc_ptr( HDC hdc ) DECLSPEC_HIDDEN;
+extern BOOL metadc_param0( HDC hdc, short func ) DECLSPEC_HIDDEN;
 extern BOOL metadc_param1( HDC hdc, short func, short param ) DECLSPEC_HIDDEN;
 extern BOOL metadc_param2( HDC hdc, short func, short param1, short param2 ) DECLSPEC_HIDDEN;
 extern BOOL metadc_param4( HDC hdc, short func, short param1, short param2,
@@ -95,7 +96,6 @@ extern BOOL CDECL MFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD ro
 extern BOOL CDECL MFDRV_PolyBezier( PHYSDEV dev, const POINT* pt, DWORD count ) DECLSPEC_HIDDEN;
 extern BOOL CDECL MFDRV_PolyBezierTo( PHYSDEV dev, const POINT* pt, DWORD count ) DECLSPEC_HIDDEN;
 extern BOOL CDECL MFDRV_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN;
-extern INT  CDECL MFDRV_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern BOOL CDECL MFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
 extern BOOL CDECL MFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
 extern HBITMAP CDECL MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/tests/dc.c b/dlls/gdi32/tests/dc.c
index 054279bf46c75f4822dc95b3ab59e2293018e319..bdc8186bf76018ea9088cca48350782603915043 100644
--- a/dlls/gdi32/tests/dc.c
+++ b/dlls/gdi32/tests/dc.c
@@ -234,6 +234,11 @@ static void test_savedc(void)
        "ret = %d\n", ret);
 
     DeleteDC(hdc);
+
+    SetLastError(0xdeadbeef);
+    ret = SaveDC(ULongToHandle(0xdeadbeef));
+    ok(!ret, "SaveDC returned %u\n", ret);
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %u\n", GetLastError());
 }
 
 static void test_GdiConvertToDevmodeW(void)