[PATCH 2/3] gdi32: PlayEnhMetaFileRecord should be called with the same HDC as EnumEnhMetaFile

Andrew Eikum aeikum at codeweavers.com
Thu Aug 24 11:26:55 CDT 2017


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
 dlls/gdi32/enhmetafile.c    | 34 ++++++++++++++++--
 dlls/gdi32/tests/metafile.c | 88 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/enhmetafile.c b/dlls/gdi32/enhmetafile.c
index cffac375f9..5153e3932d 100644
--- a/dlls/gdi32/enhmetafile.c
+++ b/dlls/gdi32/enhmetafile.c
@@ -513,6 +513,7 @@ typedef struct EMF_dc_state
 
 typedef struct enum_emh_data
 {
+    HDC orig_hdc;
     XFORM init_transform;
     EMF_dc_state state;
     INT save_level;
@@ -758,7 +759,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
 
   TRACE("hdc = %p, handletable = %p, record = %p, numHandles = %d\n",
         hdc, handletable, mr, handles);
-  if (!mr) return FALSE;
+  if (!mr || !hdc) return FALSE;
 
   type = mr->iType;
 
@@ -780,6 +781,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
         const EMRSETMAPMODE *pSetMapMode = (const EMRSETMAPMODE *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         if (info->state.mode == pSetMapMode->iMode &&
             (info->state.mode == MM_ISOTROPIC || info->state.mode == MM_ANISOTROPIC))
             break;
@@ -882,6 +886,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
     	const EMRSETWINDOWORGEX *pSetWindowOrgEx = (const EMRSETWINDOWORGEX *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         info->state.wndOrgX = pSetWindowOrgEx->ptlOrigin.x;
         info->state.wndOrgY = pSetWindowOrgEx->ptlOrigin.y;
 
@@ -891,7 +898,10 @@ BOOL WINAPI PlayEnhMetaFileRecord(
     case EMR_SETWINDOWEXTEX:
       {
 	const EMRSETWINDOWEXTEX *pSetWindowExtEx = (const EMRSETWINDOWEXTEX *)mr;
-	
+
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
 	    break;
         info->state.wndExtX = pSetWindowExtEx->szlExtent.cx;
@@ -906,6 +916,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
 	const EMRSETVIEWPORTORGEX *pSetViewportOrgEx = (const EMRSETVIEWPORTORGEX *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         info->state.vportOrgX = pSetViewportOrgEx->ptlOrigin.x;
         info->state.vportOrgY = pSetViewportOrgEx->ptlOrigin.y;
         TRACE("SetViewportOrgEx: %d,%d\n", info->state.vportOrgX, info->state.vportOrgY);
@@ -915,6 +928,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
 	const EMRSETVIEWPORTEXTEX *pSetViewportExtEx = (const EMRSETVIEWPORTEXTEX *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
 	    break;
         info->state.vportExtX = pSetViewportExtEx->szlExtent.cx;
@@ -1250,6 +1266,10 @@ BOOL WINAPI PlayEnhMetaFileRecord(
     case EMR_SETWORLDTRANSFORM:
       {
         const EMRSETWORLDTRANSFORM *lpXfrm = (const EMRSETWORLDTRANSFORM *)mr;
+
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         info->state.world_transform = lpXfrm->xform;
         break;
       }
@@ -1388,6 +1408,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
         const EMRSCALEVIEWPORTEXTEX *lpScaleViewportExtEx = (const EMRSCALEVIEWPORTEXTEX *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
 	    break;
         if (!lpScaleViewportExtEx->xNum || !lpScaleViewportExtEx->xDenom || 
@@ -1413,6 +1436,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
         const EMRSCALEWINDOWEXTEX *lpScaleWindowExtEx = (const EMRSCALEWINDOWEXTEX *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
 	    break;
         if (!lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->xDenom || 
@@ -1438,6 +1464,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
       {
         const EMRMODIFYWORLDTRANSFORM *lpModifyWorldTrans = (const EMRMODIFYWORLDTRANSFORM *)mr;
 
+        if (hdc != info->orig_hdc)
+            return FALSE;
+
         switch(lpModifyWorldTrans->iMode) {
         case MWT_IDENTITY:
             info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1;
@@ -2299,6 +2328,7 @@ BOOL WINAPI EnumEnhMetaFile(
 	SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 	return FALSE;
     }
+    info->orig_hdc = hdc;
     info->state.mode = MM_TEXT;
     info->state.wndOrgX = 0;
     info->state.wndOrgY = 0;
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index eeec79c800..dbef7fc61a 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -3912,6 +3912,93 @@ static void test_emf_GradientFill(void)
     DeleteEnhMetaFile( hemf );
 }
 
+static void set_rotation_xform(XFORM *out, float rad, int dx, int dy)
+{
+    out->eM11 = cosf(rad);
+    out->eM12 = -1.f * sinf(rad);
+    out->eM21 = sinf(rad);
+    out->eM22 = cosf(rad);
+    out->eDx = dx;
+    out->eDy = dy;
+}
+
+static INT CALLBACK enum_emf_PlayEnhMetaFileRecord(HDC hdc, HANDLETABLE *ht,
+        const ENHMETARECORD *emr, INT nobj, LPARAM param)
+{
+    BOOL ret;
+    HDC local_hdc = (HDC)param;
+
+    ret = PlayEnhMetaFileRecord(NULL, ht, emr, nobj);
+    ok(ret == FALSE, "PlayEnhMetaFileRecord should have failed\n");
+
+    ret = PlayEnhMetaFileRecord(local_hdc, ht, emr, nobj);
+    switch(emr->iType)
+    {
+    /* playing back some EMR types fails, while others succeed. docs say this
+     * is all invalid. */
+    case EMR_SETWORLDTRANSFORM:
+    case EMR_MODIFYWORLDTRANSFORM:
+        ok(ret == FALSE, "PlayEnhMetaFileRecord should have failed\n");
+        break;
+    default:
+        ok(ret == TRUE, "PlayEnhMetaFileRecord failed\n");
+        break;
+    }
+
+    if(hdc != NULL){
+        ret = PlayEnhMetaFileRecord(hdc, ht, emr, nobj);
+        ok(ret == TRUE, "PlayEnhMetaFileRecord should have failed\n");
+    }
+
+    return 1;
+}
+
+static void test_emf_PlayEnhMetaFileRecord(void)
+{
+    HDC hdcMetafile, hdc, local_hdc;
+    HWND hwnd;
+    HENHMETAFILE hemf;
+    XFORM xform;
+    BOOL ret;
+    RECT rect = { 0, 0, 100, 100 };
+
+    hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
+    ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
+
+    ret = SetGraphicsMode(hdcMetafile, GM_ADVANCED);
+    ok(ret == TRUE, "SetGraphicsMode failed\n");
+
+    set_rotation_xform(&xform, M_PI / 4.f, 2, 3);
+    ret = SetWorldTransform(hdcMetafile, &xform); /* EMR_SETWORLDTRANSFORM */
+    ok(ret == TRUE, "SetWorldTransform failed\n");
+
+    ret = LineTo(hdcMetafile, 1, 1);
+    ok(ret == TRUE, "LineTo failed\n");
+
+    hemf = CloseEnhMetaFile(hdcMetafile);
+    ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
+
+    hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
+                           0, 0, 200, 200, 0, 0, 0, NULL);
+    ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
+
+    hdc = GetDC(hwnd);
+    ok(hdc != 0, "GetDC failed\n");
+
+    ret = EnumEnhMetaFile(NULL, hemf, enum_emf_PlayEnhMetaFileRecord, hdc, &rect);
+    ok(ret == TRUE, "EnumEnhMetaFile failed: %u\n", GetLastError());
+
+    local_hdc = CreateCompatibleDC(NULL);
+
+    ret = EnumEnhMetaFile(local_hdc, hemf, enum_emf_PlayEnhMetaFileRecord, hdc, &rect);
+    ok(ret == TRUE, "EnumEnhMetaFile failed: %u\n", GetLastError());
+
+    ReleaseDC(hwnd, hdc);
+    DestroyWindow(hwnd);
+
+    DeleteEnhMetaFile(hemf);
+}
+
 START_TEST(metafile)
 {
     init_function_pointers();
@@ -3928,6 +4015,7 @@ START_TEST(metafile)
     test_emf_paths();
     test_emf_PolyPolyline();
     test_emf_GradientFill();
+    test_emf_PlayEnhMetaFileRecord();
 
     /* For win-format metafiles (mfdrv) */
     test_mf_SaveDC();
-- 
2.14.1





More information about the wine-patches mailing list