https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5461abeeba643d6ba1cce3f0610b023f71afc1e9

commit 5461abeeba643d6ba1cce3f0610b023f71afc1e9
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Sun Mar 9 15:41:53 2025 +0100
Commit:     GitHub <nore...@github.com>
CommitDate: Sun Mar 9 15:41:53 2025 +0100

    [SHELL32][SHELL32_APITESTS] SHDefExtractIcon zero icon size as sysmetric 
(#7768)
---
 dll/win32/shell32/iconcache.cpp                    |  3 +
 .../rostests/apitests/shell32/ExtractIconEx.cpp    | 85 ++++++++++++++++++++++
 modules/rostests/apitests/shell32/testlist.c       |  2 +
 3 files changed, 90 insertions(+)

diff --git a/dll/win32/shell32/iconcache.cpp b/dll/win32/shell32/iconcache.cpp
index 392d5fa75ea..e0d8b179ecb 100644
--- a/dll/win32/shell32/iconcache.cpp
+++ b/dll/win32/shell32/iconcache.cpp
@@ -1019,6 +1019,9 @@ HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int 
iIndex, UINT uFlags,
     HICON hIcons[2];
     WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile), 
iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
 
+    if (!nIconSize)
+        nIconSize = MAKELONG(GetSystemMetrics(SM_CXICON), 
GetSystemMetrics(SM_CXSMICON));
+
     ret = PrivateExtractIconsW(pszIconFile, iIndex, nIconSize, nIconSize, 
hIcons, NULL, 2, LR_DEFAULTCOLOR);
     /* FIXME: deal with uFlags parameter which contains GIL_ flags */
     if (ret == 0xFFFFFFFF)
diff --git a/modules/rostests/apitests/shell32/ExtractIconEx.cpp 
b/modules/rostests/apitests/shell32/ExtractIconEx.cpp
index 244081199f3..d8e9fd4b564 100644
--- a/modules/rostests/apitests/shell32/ExtractIconEx.cpp
+++ b/modules/rostests/apitests/shell32/ExtractIconEx.cpp
@@ -9,6 +9,28 @@
 #include "shelltest.h"
 #include <stdio.h>
 
+EXTERN_C BOOL WINAPI SHAreIconsEqual(HICON hIcon1, HICON hIcon2);
+
+static void SafeDestroyIcon(HICON hIco)
+{
+    if (hIco)
+        DestroyIcon(hIco);
+}
+
+static UINT GetIcoSize(HICON hIco)
+{
+    ICONINFO info;
+    if (!GetIconInfo(hIco, &info))
+        return 0;
+
+    BITMAP bm;
+    if (!GetObject(info.hbmColor ? info.hbmColor : info.hbmMask, sizeof(bm), 
&bm))
+        bm.bmWidth = 0;
+    DeleteObject(info.hbmMask);
+    DeleteObject(info.hbmColor);
+    return bm.bmWidth;
+}
+
 typedef struct
 {
     PCWSTR pszFilePath;
@@ -122,3 +144,66 @@ START_TEST(ExtractIconEx)
     DeleteFileA(FileName[0]);
     DeleteFileA(FileName[1]);
 }
+
+static HRESULT SHDEI(LPCWSTR pszIconFile, int Index = 0, UINT GIL = 0, UINT 
Size = 0)
+{
+    HICON hIco = NULL;
+    HRESULT hr = SHDefExtractIcon(pszIconFile, Index, GIL, &hIco, NULL, Size);
+    if (hr == S_OK)
+    {
+        hr = GetIcoSize(hIco);
+        SafeDestroyIcon(hIco);
+    }
+    return hr;
+}
+
+START_TEST(SHDefExtractIcon)
+{
+    HRESULT hr;
+    int SysBigIconSize = GetSystemMetrics(SM_CXICON);
+
+    // Modern Windows requires the system image list to be initialized for 
GIL_SIMULATEDOC to work!
+    SHFILEINFOW shfi;
+    SHGetFileInfoW(L"x", 0, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | 
SHGFI_USEFILEATTRIBUTES);
+
+    WCHAR path[MAX_PATH];
+    GetSystemDirectoryW(path, _countof(path));
+    PathAppendW(path, L"user32.dll");
+    int index = 1;
+
+    ok(SHDEI(path, index, 0, 0) == SysBigIconSize, "0 size must match 
GetSystemMetrics\n");
+    ok(SHDEI(path, index, 0, SysBigIconSize * 2) == SysBigIconSize * 2, 
"Resize failed\n");
+
+    HICON hIcoLarge, hIcoSmall;
+    if (SHDefExtractIcon(path, index, 0, &hIcoLarge, &hIcoSmall, 0) != S_OK)
+        hIcoLarge = hIcoSmall = NULL;
+    ok(hIcoLarge && hIcoSmall && !SHAreIconsEqual(hIcoLarge, hIcoSmall), 
"Large+Small failed\n");
+    SafeDestroyIcon(hIcoLarge);
+    SafeDestroyIcon(hIcoSmall);
+
+    static const int sizes[] = { 0, SysBigIconSize * 2 };
+    for (UINT i = 0; i < _countof(sizes); ++i)
+    {
+        HICON hIcoNormal, hIcoSimDoc;
+        if (FAILED(hr = SHDefExtractIcon(path, index, 0, &hIcoNormal, NULL, 
sizes[i])))
+            hIcoNormal = NULL;
+        if (FAILED(hr = SHDefExtractIcon(path, index, GIL_SIMULATEDOC, 
&hIcoSimDoc, NULL, sizes[i])))
+            hIcoSimDoc = NULL;
+        ok(hIcoNormal && hIcoSimDoc && !SHAreIconsEqual(hIcoNormal, 
hIcoSimDoc), "GIL_SIMULATEDOC failed\n");
+        SafeDestroyIcon(hIcoNormal);
+        SafeDestroyIcon(hIcoSimDoc);
+    }
+
+    GetTempPathW(_countof(path), path);
+    GetTempFileNameW(path, L"TEST", 0, path);
+    ok(SHDEI(path) == S_FALSE, "Empty file should return S_FALSE\n");
+    HANDLE hFile = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ | 
FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+        DWORD io;
+        WriteFile(hFile, "!", 1, &io, NULL);
+        CloseHandle(hFile);
+        ok(SHDEI(path) == S_FALSE, "File without icons should return 
S_FALSE\n");
+    }
+    DeleteFile(path);
+}
diff --git a/modules/rostests/apitests/shell32/testlist.c 
b/modules/rostests/apitests/shell32/testlist.c
index 1c964c36be4..cc5398ddb68 100644
--- a/modules/rostests/apitests/shell32/testlist.c
+++ b/modules/rostests/apitests/shell32/testlist.c
@@ -34,6 +34,7 @@ extern void func_SHChangeNotify(void);
 extern void func_SHCreateDataObject(void);
 extern void func_SHCreateFileDataObject(void);
 extern void func_SHCreateFileExtractIconW(void);
+extern void func_SHDefExtractIcon(void);
 extern void func_SHEnumerateUnreadMailAccountsW(void);
 extern void func_She(void);
 extern void func_ShellExec_RunDLL(void);
@@ -89,6 +90,7 @@ const struct test winetest_testlist[] =
     { "SHCreateDataObject", func_SHCreateDataObject },
     { "SHCreateFileDataObject", func_SHCreateFileDataObject },
     { "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW },
+    { "SHDefExtractIcon", func_SHDefExtractIcon },
     { "SHEnumerateUnreadMailAccountsW", func_SHEnumerateUnreadMailAccountsW },
     { "She", func_She },
     { "ShellExec_RunDLL", func_ShellExec_RunDLL },

Reply via email to