diff --git a/dlls/gdi/metafile.c b/dlls/gdi/metafile.c index 2606aab3d0..1423c7dd6a 100644 --- a/dlls/gdi/metafile.c +++ b/dlls/gdi/metafile.c @@ -247,7 +247,9 @@ static METAHEADER *MF_ReadMetaFile(HANDLE hfile) 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 SetMetaFileBitsBetter16( HMETAFILE16 hMeta ) */ 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 --git a/dlls/gdi/tests/metafile.c b/dlls/gdi/tests/metafile.c index c32d8fef67..ece38668d1 100644 --- a/dlls/gdi/tests/metafile.c +++ b/dlls/gdi/tests/metafile.c @@ -398,11 +398,9 @@ static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const 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); @@ -420,15 +418,42 @@ static void test_mf_Blank(void) ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type); ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n"); + if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), + "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();