diff --git a/dlls/gdi32/enhmetafile.c b/dlls/gdi32/enhmetafile.c index c822b28b904..9e7684b9258 100644 --- a/dlls/gdi32/enhmetafile.c +++ b/dlls/gdi32/enhmetafile.c @@ -250,9 +250,20 @@ static inline BOOL is_dib_monochrome( const BITMAPINFO* info ) HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) { HENHMETAFILE hmf = 0; - ENHMETAFILEOBJ *metaObj = GDI_AllocObject( sizeof(ENHMETAFILEOBJ), - ENHMETAFILE_MAGIC, - (HGDIOBJ *)&hmf, NULL ); + ENHMETAFILEOBJ *metaObj; + + if (emh->iType != EMR_HEADER || emh->dSignature != ENHMETA_SIGNATURE || + (emh->nBytes & 3)) /* refuse to load unaligned EMF as Windows does */ + { + WARN("Invalid emf header type 0x%08x sig 0x%08x.\n", + emh->iType, emh->dSignature); + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + metaObj = GDI_AllocObject( sizeof(ENHMETAFILEOBJ), + ENHMETAFILE_MAGIC, + (HGDIOBJ *)&hmf, NULL ); if (metaObj) { metaObj->emh = emh; @@ -304,6 +315,7 @@ static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile ) { ENHMETAHEADER *emh; HANDLE hMapping; + HENHMETAFILE hemf; hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); @@ -311,24 +323,10 @@ static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile ) if (!emh) return 0; - if (emh->iType != EMR_HEADER || emh->dSignature != ENHMETA_SIGNATURE) { - WARN("Invalid emf header type 0x%08x sig 0x%08x.\n", - emh->iType, emh->dSignature); - goto err; - } - - /* refuse to load unaligned EMF as Windows does */ - if (emh->nBytes & 3) - { - WARN("Refusing to load unaligned EMF\n"); - goto err; - } - - return EMF_Create_HENHMETAFILE( emh, TRUE ); - -err: - UnmapViewOfFile( emh ); - return 0; + hemf = EMF_Create_HENHMETAFILE( emh, TRUE ); + if (!hemf) + UnmapViewOfFile( emh ); + return hemf; } diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c index a1481c39573..3cc27d6a7e8 100644 --- a/dlls/gdi32/tests/metafile.c +++ b/dlls/gdi32/tests/metafile.c @@ -1541,7 +1541,7 @@ static void test_gdiis(void) ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n"); ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n"); ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n"); - DeleteObject(CloseMetaFile(hmfDC)); + DeleteMetaFile(CloseMetaFile(hmfDC)); /* try with an enhanced metafile */ hdc = GetDC(NULL); @@ -1554,10 +1554,53 @@ static void test_gdiis(void) hemf = CloseEnhMetaFile(hemfDC); ok(hemf != NULL, "failed to close EMF\n"); - DeleteObject(hemf); + DeleteEnhMetaFile(hemf); ReleaseDC(NULL,hdc); } +static void test_SetEnhMetaFileBits(void) +{ + BYTE data[256]; + HENHMETAFILE hemf; + ENHMETAHEADER *emh; + + memset(data, 0xAA, sizeof(data)); + SetLastError(0xdeadbeef); + hemf = SetEnhMetaFileBits(sizeof(data), data); + ok(!hemf, "SetEnhMetaFileBits should fail\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %u\n", GetLastError()); + + emh = (ENHMETAHEADER *)data; + memset(emh, 0, sizeof(*emh)); + + emh->iType = EMR_HEADER; + emh->nSize = sizeof(*emh); + emh->dSignature = ENHMETA_SIGNATURE; + /* emh->nVersion = 0x10000; XP doesn't care about version */ + emh->nBytes = sizeof(*emh); + /* emh->nRecords = 1; XP doesn't care about records */ + emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */ + + SetLastError(0xdeadbeef); + hemf = SetEnhMetaFileBits(emh->nBytes, data); + ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError()); + DeleteEnhMetaFile(hemf); + + /* XP refuses to load unaligned EMF */ + emh->nBytes++; + SetLastError(0xdeadbeef); + hemf = SetEnhMetaFileBits(emh->nBytes, data); + ok(!hemf, "SetEnhMetaFileBits should fail\n"); + /* XP doesn't set error in this case */ + + emh->dSignature = 0; + emh->nBytes--; + SetLastError(0xdeadbeef); + hemf = SetEnhMetaFileBits(emh->nBytes, data); + ok(!hemf, "SetEnhMetaFileBits should fail\n"); + /* XP doesn't set error in this case */ +} + START_TEST(metafile) { init_function_pointers(); @@ -1580,4 +1623,5 @@ START_TEST(metafile) test_SetWinMetaFileBits(); test_gdiis(); + test_SetEnhMetaFileBits(); }