On Mon, Apr 25, 2022, 1:44 AM Jinoh Kang jinoh.kang.kr@gmail.com wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52673 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
Notes: v1 -> v2: no changes
v3 -> v4: - Remove patch "shell32: Factor out ShellItem_get_uiobject." - Use IShellItem2_BindToHandler instead of factoring out ShellItem_get_uiobject - Use CreateCompatibleDC(NULL) instead of GetDC(NULL) - Remove new dependency on win32u, use GetIconInfo instead - Remove new dependency on windowcodecs, use gdiplus instead v4 -> v5: revert to using windowscodecs
dlls/shell32/Makefile.in | 2 +- dlls/shell32/shellitem.c | 195 ++++++++++++++++++++++++++++++++- dlls/shell32/tests/shlfolder.c | 2 - 3 files changed, 193 insertions(+), 6 deletions(-)
diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in index eeb6cd63d60..0cfaac8e9cc 100644 --- a/dlls/shell32/Makefile.in +++ b/dlls/shell32/Makefile.in @@ -2,7 +2,7 @@ EXTRADEFS = -D_SHELL32_ MODULE = shell32.dll IMPORTLIB = shell32 IMPORTS = uuid shlwapi user32 gdi32 advapi32 -DELAYIMPORTS = ole32 oleaut32 shdocvw version comctl32 gdiplus +DELAYIMPORTS = ole32 oleaut32 shdocvw version comctl32 gdiplus windowscodecs
C_SRCS = \ appbar.c \ diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c index 0381fa67f0d..a1b3bc57c66 100644 --- a/dlls/shell32/shellitem.c +++ b/dlls/shell32/shellitem.c @@ -31,9 +31,12 @@ #include "pidl.h" #include "shell32_main.h" #include "debughlp.h" +#include "wincodec.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
+HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
typedef struct _ShellItem { IShellItem2 IShellItem2_iface; LONG ref; @@ -565,17 +568,203 @@ static ULONG WINAPI ShellItem_IShellItemImageFactory_Release(IShellItemImageFact return IShellItem2_Release(&This->IShellItem2_iface); }
+static HRESULT ShellItem_get_icons(ShellItem *This, SIZE size, HICON *big_icon, HICON *small_icon) +{
- HRESULT hr;
- IBindCtx *pbc;
- IExtractIconW *ei;
- WCHAR icon_file[MAX_PATH];
- INT source_index;
- UINT gil_in_flags = 0, gil_out_flags;
- INT iconsize;
- iconsize = min(size.cx, size.cy);
- if (iconsize <= 0 || iconsize > 0x7fff)
iconsize = 0x7fff;
- hr = CreateBindCtx(0, &pbc);
- if (FAILED(hr)) goto done;
- hr = IShellItem2_BindToHandler(&This->IShellItem2_iface, pbc,
&BHID_SFUIObject,
&IID_IExtractIconW, (void **)&ei);
- IBindCtx_Release(pbc);
- if (FAILED(hr)) goto done;
- hr = IExtractIconW_GetIconLocation(ei, gil_in_flags, icon_file,
MAX_PATH, &source_index, &gil_out_flags);
- if (FAILED(hr)) goto free_ei;
- if (!(gil_out_flags & GIL_NOTFILENAME))
- {
UINT ei_res;
if (source_index == -1)
source_index = 0; /* special case for some control panel
applications */
FIXME("%s %d\n", debugstr_w(icon_file), source_index);
ei_res = ExtractIconExW(icon_file, source_index, big_icon,
small_icon, 1);
if (!ei_res || ei_res == (UINT)-1)
{
WARN("Failed to extract icon.\n");
hr = E_FAIL;
}
- }
- else
- {
hr = IExtractIconW_Extract(ei, icon_file, source_index, big_icon,
small_icon, MAKELONG(iconsize, iconsize));
- }
+free_ei:
- IExtractIconW_Release(ei);
+done:
- return hr;
+}
+static HICON choose_best_icon(HICON *icons, UINT count, SIZE size_limit, SIZE *out_size) +{
- HICON best_icon = NULL;
- SIZE best_size = {0, 0};
- UINT i;
- for (i = 0; i < count; i++)
- {
ICONINFO iinfo;
BITMAP bm;
SIZE size;
BOOL is_color, ret;
if (!icons[i] || !GetIconInfo(icons[i], &iinfo)) continue;
is_color = iinfo.hbmColor != NULL;
ret = GetObjectW(is_color ? iinfo.hbmColor : iinfo.hbmMask,
sizeof(bm), &bm);
DeleteObject(iinfo.hbmColor);
DeleteObject(iinfo.hbmMask);
if (!ret) continue;
size.cx = bm.bmWidth;
size.cy = is_color ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2;
if (!best_icon || (best_size.cx < size.cx && size.cx <=
size_limit.cx &&
best_size.cy < size.cy && size.cy <=
size_limit.cy))
{
best_icon = icons[i];
best_size = size;
}
- }
- *out_size = best_size;
- return best_icon;
+}
+static HRESULT ShellItem_get_icon_bitmap(ShellItem *This, IWICImagingFactory *imgfactory,
SIZE size, SIIGBF flags,
IWICBitmap **bitmap) +{
- HRESULT hr;
- HICON icons[2] = { NULL, NULL }, best_icon;
- SIZE best_icon_size;
- UINT i;
- *bitmap = NULL;
- hr = ShellItem_get_icons(This, size, &icons[0], &icons[1]);
- if (FAILED(hr)) return hr;
- best_icon = choose_best_icon(icons, ARRAY_SIZE(icons), size,
&best_icon_size);
- for (i = 0; i < ARRAY_SIZE(icons); i++)
if (icons[i] && icons[i] != best_icon) DeleteObject(icons[i]);
- if (!best_icon) return E_FAIL;
- hr = IWICImagingFactory_CreateBitmapFromHICON(imgfactory, best_icon,
bitmap);
- DeleteObject(best_icon);
- return hr;
+}
+static HRESULT convert_wicbitmapsource_to_gdi(IWICImagingFactory *imgfactory,
IWICBitmapSource
*bitmapsource, HBITMAP *gdibitmap) +{
- BITMAPINFOHEADER bmi;
- HRESULT hr;
- UINT width, height;
- IWICBitmapSource *newsrc;
- HDC dc;
- HBITMAP bm;
- void *bits;
- *gdibitmap = NULL;
- hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA,
bitmapsource, &newsrc);
- if (FAILED(hr)) goto done;
- hr = IWICBitmapSource_GetSize(newsrc, &width, &height);
- if (FAILED(hr)) goto free_newsrc;
- dc = CreateCompatibleDC(NULL);
- if (!dc)
- {
hr = E_FAIL;
goto free_newsrc;
- }
- memset(&bmi, 0, sizeof(bmi));
- bmi.biSize = sizeof(bmi);
- bmi.biWidth = width;
- bmi.biHeight = -height;
- bmi.biPlanes = 1;
- bmi.biBitCount = 32;
- bmi.biCompression = BI_RGB;
- bm = CreateDIBSection(dc, (const BITMAPINFO *)&bmi, DIB_RGB_COLORS,
&bits, NULL, 0);
- DeleteDC(dc);
- if (!bm)
- {
WARN("Cannot create bitmap.\n");
hr = E_FAIL;
goto free_newsrc;
- }
- hr = IWICBitmapSource_CopyPixels(newsrc, NULL, width * 4, width *
height * 4, bits);
- if (FAILED(hr))
- {
DeleteObject(bm);
goto free_newsrc;
- }
- hr = S_OK;
- *gdibitmap = bm;
+free_newsrc:
- IWICBitmapSource_Release(newsrc);
+done:
- return hr;
+}
static HRESULT WINAPI ShellItem_IShellItemImageFactory_GetImage(IShellItemImageFactory *iface, SIZE size, SIIGBF flags, HBITMAP *phbm) { ShellItem *This = impl_from_IShellItemImageFactory(iface);
HRESULT hr;
IWICImagingFactory *imgfactory;
IWICBitmap *bitmap = NULL; static int once;
if (!once++)
FIXME("%p ({%lu, %lu} %d %p): stub\n", This, size.cx, size.cy,
flags, phbm);
FIXME("%p ({%lu, %lu} %d %p): partial stub\n", This, size.cx,
size.cy, flags, phbm);
- *phbm = NULL;
This line shouldn't be deleted.
- return E_NOTIMPL;
- if (flags != SIIGBF_BIGGERSIZEOK) return E_NOTIMPL;
- hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &imgfactory);
- if (SUCCEEDED(hr))
- {
hr = ShellItem_get_icon_bitmap(This, imgfactory, size, flags,
&bitmap);
if (SUCCEEDED(hr))
{
hr = convert_wicbitmapsource_to_gdi(imgfactory,
(IWICBitmapSource *)bitmap, phbm);
IWICBitmap_Release(bitmap);
}
IWICImagingFactory_Release(imgfactory);
- }
- return hr;
}
static const IShellItemImageFactoryVtbl ShellItem_IShellItemImageFactory_Vtbl = { diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 78f199eaafc..507b3b1eac5 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -4464,11 +4464,9 @@ static void test_IShellItemImageFactory(void) ok(!GetModuleHandleA("windowscodecs.dll"), "WIC should not have already been loaded\n");
ret = IShellItemImageFactory_GetImage(siif, size,
SIIGBF_BIGGERSIZEOK, &hbm);
todo_wine ok(ret == S_OK || broken(ret == E_PENDING /* win7 */),
"GetImage returned %lx\n", ret); ok(FAILED(ret) == !hbm, "result = %lx but bitmap = %p\n", ret, hbm);
todo_wine ok(!!GetModuleHandleA("windowscodecs.dll"), "WIC should
have been loaded\n");
if (SUCCEEDED(ret) && hbm)
-- 2.34.1