From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/oleaut32/tests/olepicture.c | 90 ++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+)
diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c index eb9685a0f7d..622d50ddd2e 100644 --- a/dlls/oleaut32/tests/olepicture.c +++ b/dlls/oleaut32/tests/olepicture.c @@ -1622,6 +1622,95 @@ static void test_load_save_dib(void) } }
+static void test_load_save_emf(void) +{ + HDC hdc; + IPicture *pic; + PICTDESC desc; + short type; + OLE_HANDLE handle; + HGLOBAL hmem; + DWORD *mem; + ENHMETAHEADER *emh; + IPersistStream *src_stream; + IStream *dst_stream; + LARGE_INTEGER offset; + HRESULT hr; + LONG size; + + hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); + ok(hdc != 0, "CreateEnhMetaFileA failed\n"); + + desc.cbSizeofstruct = sizeof(desc); + desc.picType = PICTYPE_ENHMETAFILE; + desc.emf.hemf = CloseEnhMetaFile(hdc); + ok(desc.emf.hemf != 0, "CloseEnhMetaFile failed\n"); + hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); + ok(hr == S_OK, "OleCreatePictureIndirect error %#lx\n", hr); + + type = -1; + hr = IPicture_get_Type(pic, &type); + ok(hr == S_OK, "get_Type error %#lx\n", hr); + ok(type == PICTYPE_ENHMETAFILE,"expected PICTYPE_ENHMETAFILE, got %d\n", type); + + hr = IPicture_get_Handle(pic, &handle); + ok(hr == S_OK,"get_Handle error %#lx\n", hr); + ok(IntToPtr(handle) == desc.emf.hemf, "get_Handle returned wrong handle %#x\n", handle); + + hmem = GlobalAlloc(GMEM_MOVEABLE, 0); + hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); + ok(hr == S_OK, "createstreamonhglobal error %#lx\n", hr); + + size = -1; + hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); + ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); + todo_wine + ok(size == 128, "expected 128, got %ld\n", size); + emh = GlobalLock(hmem); + if (size > 0) + { + ok(emh->iType == EMR_HEADER, "wrong iType %04lx\n", emh->iType); + ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08lx\n", emh->dSignature); + } + GlobalUnlock(hmem); + + size = -1; + hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); + todo_wine + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); + todo_wine + ok(size == -1, "expected -1, got %ld\n", size); + + offset.QuadPart = 0; + hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); + ok(hr == S_OK, "IStream_Seek %#lx\n", hr); + + hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); + ok(hr == S_OK, "QueryInterface error %#lx\n", hr); + + hr = IPersistStream_Save(src_stream, dst_stream, TRUE); + todo_wine + ok(hr == S_OK, "Save error %#lx\n", hr); + + IPersistStream_Release(src_stream); + IStream_Release(dst_stream); + + mem = GlobalLock(hmem); + if (hr == S_OK) + { + ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04lx\n", mem[0]); + ok(mem[1] == 128, "expected 128, got %lu\n", mem[1]); + emh = (ENHMETAHEADER *)(mem + 2); + ok(emh->iType == EMR_HEADER, "wrong iType %04lx\n", emh->iType); + ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08lx\n", emh->dSignature); + } + GlobalUnlock(hmem); + GlobalFree(hmem); + + DeleteEnhMetaFile(desc.emf.hemf); + IPicture_Release(pic); +} + START_TEST(olepicture) { hOleaut32 = GetModuleHandleA("oleaut32.dll"); @@ -1663,6 +1752,7 @@ START_TEST(olepicture) test_load_save_dib(); test_load_save_icon(); test_load_save_empty_picture(); + test_load_save_emf(); }
From: Dmitry Timoshkov dmitry@baikal.ru
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40523. Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/oleaut32/olepicture.c | 53 +++++++++++++++++++++++++++++--- dlls/oleaut32/tests/olepicture.c | 5 +-- 2 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index 8278ec1f2f8..5b3783f1de9 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -256,6 +256,18 @@ static void OLEPictureImpl_SetIcon(OLEPictureImpl * This) } }
+static void OLEPictureImpl_SetEMF(OLEPictureImpl *This) +{ + ENHMETAHEADER emh; + + GetEnhMetaFileHeader(This->desc.emf.hemf, sizeof(emh), &emh); + + This->origWidth = 0; + This->origHeight = 0; + This->himetricWidth = emh.rclFrame.right - emh.rclFrame.left; + This->himetricHeight = emh.rclFrame.bottom - emh.rclFrame.top; +} + /************************************************************************ * OLEPictureImpl_Construct * @@ -339,8 +351,7 @@ static HRESULT OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn, OLEPictu break;
case PICTYPE_ENHMETAFILE: - FIXME("EMF is not supported\n"); - newObject->himetricWidth = newObject->himetricHeight = 0; + OLEPictureImpl_SetEMF(newObject); break;
default: @@ -1768,6 +1779,22 @@ static BOOL serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) return success; }
+static HRESULT serializeEMF(HENHMETAFILE hemf, void **buf, unsigned *size) +{ + if (!(*size = GetEnhMetaFileBits(hemf, 0, NULL))) + return E_FAIL; + + if (!(*buf = HeapAlloc(GetProcessHeap(), 0, *size))) + return E_OUTOFMEMORY; + + if (!GetEnhMetaFileBits(hemf, *size, *buf)) + { + HeapFree(GetProcessHeap(), 0, *buf); + return E_FAIL; + } + return S_OK; +} + static HRESULT WINAPI OLEPictureImpl_Save( IPersistStream* iface,IStream*pStm,BOOL fClearDirty) { @@ -1839,12 +1866,28 @@ static HRESULT WINAPI OLEPictureImpl_Save( IStream_Write(pStm, This->data, This->datalen, &dummy); hResult = S_OK; break; + + case PICTYPE_ENHMETAFILE: + if (This->bIsDirty || !This->data) + { + hResult = serializeEMF(This->desc.emf.hemf, &pIconData, &iDataSize); + if (hResult != S_OK) + break; + + HeapFree(GetProcessHeap(), 0, This->data); + This->data = pIconData; + This->datalen = iDataSize; + } + header[0] = 0x0000746c; + header[1] = This->datalen; + IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); + IStream_Write(pStm, This->data, This->datalen, &dummy); + hResult = S_OK; + break; + case PICTYPE_METAFILE: FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty); break; - case PICTYPE_ENHMETAFILE: - FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty); - break; default: FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty); break; diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c index 622d50ddd2e..2b2c84abe38 100644 --- a/dlls/oleaut32/tests/olepicture.c +++ b/dlls/oleaut32/tests/olepicture.c @@ -1689,21 +1689,18 @@ static void test_load_save_emf(void) ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
hr = IPersistStream_Save(src_stream, dst_stream, TRUE); - todo_wine ok(hr == S_OK, "Save error %#lx\n", hr);
IPersistStream_Release(src_stream); IStream_Release(dst_stream);
mem = GlobalLock(hmem); - if (hr == S_OK) - { ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04lx\n", mem[0]); ok(mem[1] == 128, "expected 128, got %lu\n", mem[1]); emh = (ENHMETAHEADER *)(mem + 2); ok(emh->iType == EMR_HEADER, "wrong iType %04lx\n", emh->iType); ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08lx\n", emh->dSignature); - } + GlobalUnlock(hmem); GlobalFree(hmem);
From: Dmitry Timoshkov dmitry@baikal.ru
Based on OLEPictureImpl_Save implementation.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=8532 Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/oleaut32/olepicture.c | 92 +++++++++++++++++++++++++++----- dlls/oleaut32/tests/olepicture.c | 14 +---- 2 files changed, 80 insertions(+), 26 deletions(-)
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index 5b3783f1de9..0ea65cf5430 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -830,19 +830,6 @@ static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface) return S_OK; }
-/************************************************************************ - * OLEPictureImpl_SaveAsFile - */ -static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface, - IStream *pstream, - BOOL SaveMemCopy, - LONG *pcbSize) -{ - OLEPictureImpl *This = impl_from_IPicture(iface); - FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize); - return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize); -} - /************************************************************************ * OLEPictureImpl_get_Attributes */ @@ -1952,6 +1939,85 @@ static HRESULT WINAPI OLEPictureImpl_GetSizeMax(IPersistStream *iface, ULARGE_IN return hr; }
+/************************************************************************ + * OLEPictureImpl_SaveAsFile + */ +static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface, + IStream *stream, BOOL mem_copy, LONG *size) +{ + OLEPictureImpl *This = impl_from_IPicture(iface); + void *data; + unsigned int data_size; + ULONG written; + HRESULT hr; + + FIXME("(%p)->(%p,%d,%p): semi-stub\n", This, stream, mem_copy, size); + + switch (This->desc.picType) + { + case PICTYPE_NONE: + return S_OK; + + case PICTYPE_ICON: + if (!mem_copy) return E_FAIL; + + if (This->bIsDirty || !This->data) + { + if (!serializeIcon(This->desc.icon.hicon, &data, &data_size)) + return E_FAIL; + HeapFree(GetProcessHeap(), 0, This->data); + This->data = data; + This->datalen = data_size; + } + hr = IStream_Write(stream, This->data, This->datalen, &written); + if (hr == S_OK && size) *size = written; + return hr; + + case PICTYPE_BITMAP: + if (!mem_copy) return E_FAIL; + + if (This->bIsDirty || !This->data) + { + switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) + { + case BITMAP_FORMAT_BMP: + hr = serializeBMP(This->desc.bmp.hbitmap, &data, &data_size); + if (hr != S_OK) return hr; + break; + case BITMAP_FORMAT_JPEG: + FIXME("BITMAP_FORMAT_JPEG is not implemented\n"); + return E_NOTIMPL; + case BITMAP_FORMAT_GIF: + FIXME("BITMAP_FORMAT_GIF is not implemented\n"); + return E_NOTIMPL; + case BITMAP_FORMAT_PNG: + FIXME("BITMAP_FORMAT_PNG is not implemented\n"); + return E_NOTIMPL; + default: + FIXME("PICTYPE_BITMAP/%#x is not implemented\n", This->loadtime_format); + return E_NOTIMPL; + } + + HeapFree(GetProcessHeap(), 0, This->data); + This->data = data; + This->datalen = data_size; + } + hr = IStream_Write(stream, This->data, This->datalen, &written); + if (hr == S_OK && size) *size = written; + return hr; + + case PICTYPE_METAFILE: + FIXME("PICTYPE_METAFILE is not implemented\n"); + return E_NOTIMPL; + case PICTYPE_ENHMETAFILE: + FIXME("ENHMETAFILE is not implemented\n"); + return E_NOTIMPL; + default: + FIXME("%#x is not implemented\n", This->desc.picType); + break; + } + return E_NOTIMPL; +}
/************************************************************************ * IDispatch diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c index 2b2c84abe38..2f909503462 100644 --- a/dlls/oleaut32/tests/olepicture.c +++ b/dlls/oleaut32/tests/olepicture.c @@ -1240,18 +1240,14 @@ static void test_load_save_bmp(void) size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); - todo_wine ok(size == 66, "expected 66, got %ld\n", size); mem = GlobalLock(hmem); - todo_wine ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04lx\n", mem[0]); GlobalUnlock(hmem);
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); - todo_wine ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); - todo_wine ok(size == -1, "expected -1, got %ld\n", size);
offset.QuadPart = 0; @@ -1329,15 +1325,12 @@ static void test_load_save_icon(void) todo_wine ok(size == 766, "expected 766, got %ld\n", size); mem = GlobalLock(hmem); - todo_wine ok(mem[0] == 0x00010000, "got wrong icon header %04lx\n", mem[0]); GlobalUnlock(hmem);
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); - todo_wine ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); - todo_wine ok(size == -1, "expected -1, got %ld\n", size);
offset.QuadPart = 0; @@ -1418,13 +1411,11 @@ static void test_load_save_empty_picture(void) size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); - todo_wine ok(size == -1, "expected -1, got %ld\n", size);
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); - todo_wine ok(size == -1, "expected -1, got %ld\n", size);
hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); @@ -1564,7 +1555,6 @@ static void test_load_save_dib(void) size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); - todo_wine ok(size == expected_size, "expected %ld, got %ld\n", expected_size, size); if (size == expected_size) { mem = GlobalLock(hmem); @@ -1577,9 +1567,7 @@ static void test_load_save_dib(void)
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); - todo_wine ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); - todo_wine ok(size == -1, "expected -1, got %ld\n", size);
offset.QuadPart = 0; @@ -1663,6 +1651,7 @@ static void test_load_save_emf(void)
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); + todo_wine ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); todo_wine ok(size == 128, "expected 128, got %ld\n", size); @@ -1678,7 +1667,6 @@ static void test_load_save_emf(void) hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); todo_wine ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); - todo_wine ok(size == -1, "expected -1, got %ld\n", size);
offset.QuadPart = 0;
From: Sebastian Lackner sebastian@fds-team.de
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/oleaut32/olepicture.c | 17 +++++++++++++++-- dlls/oleaut32/tests/olepicture.c | 6 ------ 2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index 0ea65cf5430..d7059382a3d 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -2009,9 +2009,22 @@ static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface, case PICTYPE_METAFILE: FIXME("PICTYPE_METAFILE is not implemented\n"); return E_NOTIMPL; + case PICTYPE_ENHMETAFILE: - FIXME("ENHMETAFILE is not implemented\n"); - return E_NOTIMPL; + if (!mem_copy) return E_FAIL; + + if (This->bIsDirty || !This->data) + { + hr = serializeEMF(This->desc.emf.hemf, &data, &data_size); + if (hr != S_OK) return hr; + HeapFree(GetProcessHeap(), 0, This->data); + This->data = data; + This->datalen = data_size; + } + hr = IStream_Write(stream, This->data, This->datalen, &written); + if (hr == S_OK && size) *size = written; + return hr; + default: FIXME("%#x is not implemented\n", This->desc.picType); break; diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c index 2f909503462..58d5577631c 100644 --- a/dlls/oleaut32/tests/olepicture.c +++ b/dlls/oleaut32/tests/olepicture.c @@ -1651,21 +1651,15 @@ static void test_load_save_emf(void)
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); - todo_wine ok(hr == S_OK, "IPicture_SaveasFile error %#lx\n", hr); - todo_wine ok(size == 128, "expected 128, got %ld\n", size); emh = GlobalLock(hmem); - if (size > 0) - { ok(emh->iType == EMR_HEADER, "wrong iType %04lx\n", emh->iType); ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08lx\n", emh->dSignature); - } GlobalUnlock(hmem);
size = -1; hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); - todo_wine ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); ok(size == -1, "expected -1, got %ld\n", size);
This merge request was approved by Dmitry Timoshkov.