Add a test for SetMetaFileBitsEx, make it pass under Wine

Dmitry Timoshkov dmitry at baikal.ru
Tue Oct 18 04:05:42 CDT 2005


Hello,

Please apply after CopyMetaFile fixes.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Add a test for SetMetaFileBitsEx, make it pass under Wine.

diff -up cvs/hq/wine/dlls/gdi/metafile.c wine/dlls/gdi/metafile.c
--- cvs/hq/wine/dlls/gdi/metafile.c	2005-10-18 17:22:12.000000000 +0900
+++ wine/dlls/gdi/metafile.c	2005-10-18 17:41:39.000000000 +0900
@@ -247,7 +247,9 @@ static METAHEADER *MF_ReadMetaFile(HANDL
         HeapFree( GetProcessHeap(), 0, mh );
 	return NULL;
     }
-    if(mh->mtVersion != MFVERSION || mh->mtHeaderSize != size / 2) {
+    if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
+        mh->mtHeaderSize != size / 2)
+    {
         HeapFree( GetProcessHeap(), 0, mh );
         return NULL;
     }
@@ -1359,9 +1361,26 @@ HMETAFILE16 WINAPI SetMetaFileBitsBetter
  */
 HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData )
 {
-    METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
-    if (!mh) return 0;
+    METAHEADER *mh = (METAHEADER *)lpData;
+
+    if (size & 1) return 0;
+
+    if (!size || mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
+        mh->mtHeaderSize != sizeof(METAHEADER) / 2)
+    {
+        SetLastError(ERROR_INVALID_DATA);
+        return 0;
+    }
+
+    mh = HeapAlloc( GetProcessHeap(), 0, size );
+    if (!mh)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return 0;
+    }
+
     memcpy(mh, lpData, size);
+    mh->mtSize = size / 2;
     return MF_Create_HMETAFILE(mh);
 }
 
diff -up cvs/hq/wine/dlls/gdi/tests/metafile.c wine/dlls/gdi/tests/metafile.c
--- cvs/hq/wine/dlls/gdi/tests/metafile.c	2005-10-18 17:22:12.000000000 +0900
+++ wine/dlls/gdi/tests/metafile.c	2005-10-18 17:46:32.000000000 +0900
@@ -398,11 +398,9 @@ static int compare_mf_disk_bits(LPCSTR n
 static void test_mf_Blank(void)
 {
     HDC hdcMetafile;
-    HMETAFILE hMetafile, hmf_copy;
+    HMETAFILE hMetafile;
     INT caps;
     BOOL ret;
-    char temp_path[MAX_PATH];
-    char mf_name[MAX_PATH];
     INT type;
 
     hdcMetafile = CreateMetaFileA(NULL);
@@ -424,11 +422,38 @@ static void test_mf_Blank(void)
         "mf_blank") != 0)
             dump_mf_bits (hMetafile, "mf_Blank");
 
+    ret = DeleteMetaFile(hMetafile);
+    ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
+}
+
+static void test_CopyMetaFile(void)
+{
+    HDC hdcMetafile;
+    HMETAFILE hMetafile, hmf_copy;
+    BOOL ret;
+    char temp_path[MAX_PATH];
+    char mf_name[MAX_PATH];
+    INT type;
+
+    hdcMetafile = CreateMetaFileA(NULL);
+    ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
+    trace("hdcMetafile %p\n", hdcMetafile);
+
+    hMetafile = CloseMetaFile(hdcMetafile);
+    ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
+    type = GetObjectType(hMetafile);
+    ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
+
+    if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
+        "mf_blank") != 0)
+            dump_mf_bits (hMetafile, "mf_Blank");
+
     GetTempPathA(MAX_PATH, temp_path);
     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
-    hmf_copy = CopyMetaFileA(hMetafile, mf_name);
 
+    hmf_copy = CopyMetaFileA(hMetafile, mf_name);
     ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError());
+
     type = GetObjectType(hmf_copy);
     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
 
@@ -444,6 +469,82 @@ static void test_mf_Blank(void)
     DeleteFileA(mf_name);
 }
 
+static void test_SetMetaFileBits(void)
+{
+    HMETAFILE hmf;
+    INT type;
+    BOOL ret;
+    BYTE buf[256];
+    METAHEADER *mh;
+
+    hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
+    ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
+    type = GetObjectType(hmf);
+    ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
+
+    if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
+        dump_mf_bits(hmf, "mf_Graphics");
+
+    ret = DeleteMetaFile(hmf);
+    ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
+
+    /* NULL data crashes XP SP1 */
+    /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
+
+    /* Now with not zero size */
+    SetLastError(0xdeadbeef);
+    hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
+    ok(!hmf, "SetMetaFileBitsEx should fail\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
+
+    /* Now with not even size */
+    SetLastError(0xdeadbeef);
+    hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
+    ok(!hmf, "SetMetaFileBitsEx should fail\n");
+    ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError());
+
+    /* Now with zeroed out or faked some header fields */
+    assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
+    memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
+    mh = (METAHEADER *)buf;
+    /* corruption of any of the below fields leads to a failure */
+    mh->mtType = 0;
+    mh->mtVersion = 0;
+    mh->mtHeaderSize = 0;
+    SetLastError(0xdeadbeef);
+    hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
+    ok(!hmf, "SetMetaFileBitsEx should fail\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
+
+    /* Now with corrupted mtSize field */
+    memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
+    mh = (METAHEADER *)buf;
+    /* corruption of mtSize doesn't lead to a failure */
+    mh->mtSize *= 2;
+    hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
+    ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
+
+    if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
+        dump_mf_bits(hmf, "mf_Graphics");
+
+    ret = DeleteMetaFile(hmf);
+    ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
+
+    /* Now with zeroed out mtSize field */
+    memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
+    mh = (METAHEADER *)buf;
+    /* zeroing mtSize doesn't lead to a failure */
+    mh->mtSize = 0;
+    hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
+    ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
+
+    if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
+        dump_mf_bits(hmf, "mf_Graphics");
+
+    ret = DeleteMetaFile(hmf);
+    ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
+}
+
 /* Simple APIs from mfdrv/graphics.c
  */
 
@@ -693,6 +794,8 @@ START_TEST(metafile)
     test_mf_Blank();
     test_mf_Graphics();
     test_mf_PatternBrush();
+    test_CopyMetaFile();
+    test_SetMetaFileBits();
 
     /* For metafile conversions */
     test_mf_conversions();






More information about the wine-patches mailing list