From: Akihiro Sagawa sagawa.aki@gmail.com
Instead of 32-bit or 16-bit per pixel format with BI_BITFIELDS.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56246 --- dlls/oleaut32/olepicture.c | 41 +++++++++++++++++++++++++++++++- dlls/oleaut32/tests/olepicture.c | 2 -- 2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index e4bfafe6fd0..03679ad91cb 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -1538,6 +1538,8 @@ static HRESULT serializeBMP(HBITMAP hbmp, void **buffer, unsigned int *length) { char infobuf[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)] = { 0 }; BITMAPINFO *info = (BITMAPINFO *)infobuf; + BITMAP bm; + HBITMAP hdib = NULL; BITMAPINFO *bitmap; BITMAPFILEHEADER *filehdr; int numentries; @@ -1545,8 +1547,43 @@ static HRESULT serializeBMP(HBITMAP hbmp, void **buffer, unsigned int *length) HRESULT hr = S_OK; unsigned char *data = NULL;
- /* Find out bitmap size and padded length */ hdc = GetDC(0); + if (!GetObjectW(hbmp, sizeof(bm), &bm)) { + hr = E_INVALIDARG; + goto done; + } + + /* Convert 16bpp/32bpp bitmap to 24bpp */ + if (bm.bmBitsPixel == 16 || bm.bmBitsPixel == 32) { + void *bits; + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = bm.bmWidth; + info->bmiHeader.biHeight = bm.bmHeight; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 24; + info->bmiHeader.biCompression = BI_RGB; + hdib = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &bits, NULL, 0); + if (!hdib) { + hr = E_OUTOFMEMORY; + goto done; + } + if (buffer) { + HDC src, dst; + src = CreateCompatibleDC(hdc); + dst = CreateCompatibleDC(hdc); + SelectObject(src, hbmp); + SelectObject(dst, hdib); + if (!BitBlt(dst, 0, 0, bm.bmWidth, bm.bmHeight, src, 0, 0, SRCCOPY)) + hr = E_INVALIDARG; + DeleteDC(src); + DeleteDC(dst); + if (FAILED(hr)) + goto done; + } + hbmp = hdib; + } + + /* Find out bitmap size and padded length */ info->bmiHeader.biSize = sizeof(info->bmiHeader); if (!GetDIBits(hdc, hbmp, 0, 0, NULL, info, DIB_RGB_COLORS)) { hr = E_INVALIDARG; @@ -1607,6 +1644,8 @@ static HRESULT serializeBMP(HBITMAP hbmp, void **buffer, unsigned int *length) done: free(data); ReleaseDC(0, hdc); + if (hdib && hbmp == hdib) + DeleteObject(hdib); return hr; }
diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c index 1d591b971cd..f0468a6f83c 100644 --- a/dlls/oleaut32/tests/olepicture.c +++ b/dlls/oleaut32/tests/olepicture.c @@ -1601,9 +1601,7 @@ static void test_load_save_dib(void) ok(mem[1] == expected_size, "expected stream size %lu, got %lu\n", expected_size, mem[1]); ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04lx\n", mem[2]); info = (BITMAPINFO *)(((BITMAPFILEHEADER *)&mem[2]) + 1); - todo_wine_if(bpp != expected_bpp) ok(info->bmiHeader.biBitCount == expected_bpp, "expected bpp %lu, got %hu\n", expected_bpp, info->bmiHeader.biBitCount); - todo_wine_if(bpp == 16 || bpp == 32) ok(info->bmiHeader.biCompression == BI_RGB, "expected BI_RGB, got %lu\n", info->bmiHeader.biCompression);
GlobalUnlock(hmem);