Skip to content

Commit 5461abe

Browse files
authored
[SHELL32][SHELL32_APITESTS] SHDefExtractIcon zero icon size as sysmetric (reactos#7768)
1 parent bdda5b9 commit 5461abe

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

dll/win32/shell32/iconcache.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,9 @@ HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags,
10191019
HICON hIcons[2];
10201020
WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile), iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
10211021

1022+
if (!nIconSize)
1023+
nIconSize = MAKELONG(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXSMICON));
1024+
10221025
ret = PrivateExtractIconsW(pszIconFile, iIndex, nIconSize, nIconSize, hIcons, NULL, 2, LR_DEFAULTCOLOR);
10231026
/* FIXME: deal with uFlags parameter which contains GIL_ flags */
10241027
if (ret == 0xFFFFFFFF)

modules/rostests/apitests/shell32/ExtractIconEx.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@
99
#include "shelltest.h"
1010
#include <stdio.h>
1111

12+
EXTERN_C BOOL WINAPI SHAreIconsEqual(HICON hIcon1, HICON hIcon2);
13+
14+
static void SafeDestroyIcon(HICON hIco)
15+
{
16+
if (hIco)
17+
DestroyIcon(hIco);
18+
}
19+
20+
static UINT GetIcoSize(HICON hIco)
21+
{
22+
ICONINFO info;
23+
if (!GetIconInfo(hIco, &info))
24+
return 0;
25+
26+
BITMAP bm;
27+
if (!GetObject(info.hbmColor ? info.hbmColor : info.hbmMask, sizeof(bm), &bm))
28+
bm.bmWidth = 0;
29+
DeleteObject(info.hbmMask);
30+
DeleteObject(info.hbmColor);
31+
return bm.bmWidth;
32+
}
33+
1234
typedef struct
1335
{
1436
PCWSTR pszFilePath;
@@ -122,3 +144,66 @@ START_TEST(ExtractIconEx)
122144
DeleteFileA(FileName[0]);
123145
DeleteFileA(FileName[1]);
124146
}
147+
148+
static HRESULT SHDEI(LPCWSTR pszIconFile, int Index = 0, UINT GIL = 0, UINT Size = 0)
149+
{
150+
HICON hIco = NULL;
151+
HRESULT hr = SHDefExtractIcon(pszIconFile, Index, GIL, &hIco, NULL, Size);
152+
if (hr == S_OK)
153+
{
154+
hr = GetIcoSize(hIco);
155+
SafeDestroyIcon(hIco);
156+
}
157+
return hr;
158+
}
159+
160+
START_TEST(SHDefExtractIcon)
161+
{
162+
HRESULT hr;
163+
int SysBigIconSize = GetSystemMetrics(SM_CXICON);
164+
165+
// Modern Windows requires the system image list to be initialized for GIL_SIMULATEDOC to work!
166+
SHFILEINFOW shfi;
167+
SHGetFileInfoW(L"x", 0, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
168+
169+
WCHAR path[MAX_PATH];
170+
GetSystemDirectoryW(path, _countof(path));
171+
PathAppendW(path, L"user32.dll");
172+
int index = 1;
173+
174+
ok(SHDEI(path, index, 0, 0) == SysBigIconSize, "0 size must match GetSystemMetrics\n");
175+
ok(SHDEI(path, index, 0, SysBigIconSize * 2) == SysBigIconSize * 2, "Resize failed\n");
176+
177+
HICON hIcoLarge, hIcoSmall;
178+
if (SHDefExtractIcon(path, index, 0, &hIcoLarge, &hIcoSmall, 0) != S_OK)
179+
hIcoLarge = hIcoSmall = NULL;
180+
ok(hIcoLarge && hIcoSmall && !SHAreIconsEqual(hIcoLarge, hIcoSmall), "Large+Small failed\n");
181+
SafeDestroyIcon(hIcoLarge);
182+
SafeDestroyIcon(hIcoSmall);
183+
184+
static const int sizes[] = { 0, SysBigIconSize * 2 };
185+
for (UINT i = 0; i < _countof(sizes); ++i)
186+
{
187+
HICON hIcoNormal, hIcoSimDoc;
188+
if (FAILED(hr = SHDefExtractIcon(path, index, 0, &hIcoNormal, NULL, sizes[i])))
189+
hIcoNormal = NULL;
190+
if (FAILED(hr = SHDefExtractIcon(path, index, GIL_SIMULATEDOC, &hIcoSimDoc, NULL, sizes[i])))
191+
hIcoSimDoc = NULL;
192+
ok(hIcoNormal && hIcoSimDoc && !SHAreIconsEqual(hIcoNormal, hIcoSimDoc), "GIL_SIMULATEDOC failed\n");
193+
SafeDestroyIcon(hIcoNormal);
194+
SafeDestroyIcon(hIcoSimDoc);
195+
}
196+
197+
GetTempPathW(_countof(path), path);
198+
GetTempFileNameW(path, L"TEST", 0, path);
199+
ok(SHDEI(path) == S_FALSE, "Empty file should return S_FALSE\n");
200+
HANDLE hFile = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
201+
if (hFile != INVALID_HANDLE_VALUE)
202+
{
203+
DWORD io;
204+
WriteFile(hFile, "!", 1, &io, NULL);
205+
CloseHandle(hFile);
206+
ok(SHDEI(path) == S_FALSE, "File without icons should return S_FALSE\n");
207+
}
208+
DeleteFile(path);
209+
}

modules/rostests/apitests/shell32/testlist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern void func_SHChangeNotify(void);
3434
extern void func_SHCreateDataObject(void);
3535
extern void func_SHCreateFileDataObject(void);
3636
extern void func_SHCreateFileExtractIconW(void);
37+
extern void func_SHDefExtractIcon(void);
3738
extern void func_SHEnumerateUnreadMailAccountsW(void);
3839
extern void func_She(void);
3940
extern void func_ShellExec_RunDLL(void);
@@ -89,6 +90,7 @@ const struct test winetest_testlist[] =
8990
{ "SHCreateDataObject", func_SHCreateDataObject },
9091
{ "SHCreateFileDataObject", func_SHCreateFileDataObject },
9192
{ "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW },
93+
{ "SHDefExtractIcon", func_SHDefExtractIcon },
9294
{ "SHEnumerateUnreadMailAccountsW", func_SHEnumerateUnreadMailAccountsW },
9395
{ "She", func_She },
9496
{ "ShellExec_RunDLL", func_ShellExec_RunDLL },

0 commit comments

Comments
 (0)