2 * PROJECT: ReactOS API tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Test for SHCreateFileExtractIconW
5 * COPYRIGHT: Copyright 2017,2018 Mark Jansen (mark.jansen@reactos.org)
13 ULONG
DbgPrint(PCH Format
,...);
14 #include <shellutils.h>
16 HRESULT (STDAPICALLTYPE
*pSHCreateFileExtractIconW
)(LPCWSTR pszFile
, DWORD dwFileAttributes
, REFIID riid
, void **ppv
);
24 static TestData IconTests
[] =
26 { L
"xxx.zip", FILE_ATTRIBUTE_NORMAL
},
27 { L
"xxx.zip", FILE_ATTRIBUTE_DIRECTORY
},
28 { L
"xxx.exe", FILE_ATTRIBUTE_NORMAL
},
29 { L
"xxx.exe", FILE_ATTRIBUTE_DIRECTORY
},
30 { L
"xxx.dll", FILE_ATTRIBUTE_NORMAL
},
31 { L
"xxx.dll", FILE_ATTRIBUTE_DIRECTORY
},
32 { L
"xxx.txt", FILE_ATTRIBUTE_NORMAL
},
33 { L
"xxx.txt", FILE_ATTRIBUTE_DIRECTORY
},
34 { NULL
, FILE_ATTRIBUTE_NORMAL
},
35 { NULL
, FILE_ATTRIBUTE_DIRECTORY
},
41 HRESULT ExpectedCreate
;
42 HRESULT ExpectedQueryInterface
;
45 static TestIID InterfaceTests
[] =
47 { &IID_IDefaultExtractIconInit
, E_NOINTERFACE
, E_NOINTERFACE
},
48 { &IID_IExtractIconW
, S_OK
, S_OK
},
49 { &IID_IExtractIconA
, S_OK
, S_OK
},
50 { &IID_IPersist
, E_NOINTERFACE
, E_NOINTERFACE
},
51 { &IID_IPersistFile
, E_NOINTERFACE
, E_NOINTERFACE
},
55 static void ExtractOneBitmap(HBITMAP hbm
, CComHeapPtr
<BYTE
>& data
, DWORD
& size
)
57 HDC hdc
= CreateCompatibleDC(NULL
);
58 HGDIOBJ obj
= SelectObject(hdc
, hbm
);
60 CComHeapPtr
<BITMAPINFO
> pInfoBM
;
62 pInfoBM
.AllocateBytes(sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
63 memset(pInfoBM
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
64 pInfoBM
->bmiHeader
.biSize
= sizeof(pInfoBM
->bmiHeader
);
65 if (!GetDIBits(hdc
, hbm
, 0, 0, NULL
, pInfoBM
, DIB_RGB_COLORS
))
68 size
= pInfoBM
->bmiHeader
.biSizeImage
;
70 GetDIBits(hdc
, hbm
, 0, pInfoBM
->bmiHeader
.biHeight
, data
, pInfoBM
, DIB_RGB_COLORS
);
72 SelectObject(hdc
, obj
);
76 static bool GetIconData(HICON icon
, CComHeapPtr
<BYTE
>& colorData
, DWORD
& colorSize
, CComHeapPtr
<BYTE
>& maskData
, DWORD
& maskSize
)
80 if (!GetIconInfo(icon
, &iconinfo
))
83 ExtractOneBitmap(iconinfo
.hbmColor
, colorData
, colorSize
);
84 ExtractOneBitmap(iconinfo
.hbmMask
, maskData
, maskSize
);
86 DeleteObject(iconinfo
.hbmColor
);
87 DeleteObject(iconinfo
.hbmMask
);
93 START_TEST(SHCreateFileExtractIconW
)
95 WCHAR CurrentModule
[MAX_PATH
];
96 HMODULE shell32
= LoadLibraryA("shell32.dll");
98 pSHCreateFileExtractIconW
= (HRESULT (__stdcall
*)(LPCWSTR
, DWORD
, REFIID
, void **))GetProcAddress(shell32
, "SHCreateFileExtractIconW");
100 /* Show that icons returned are always the same */
101 UINT tryFlags
[4] = { 0, GIL_FORSHORTCUT
, GIL_OPENICON
};
105 GetModuleFileNameW(NULL
, CurrentModule
, _countof(CurrentModule
));
108 ULONG_PTR firet
= SHGetFileInfoW(CurrentModule
, 0, &shfi
, sizeof(shfi
), SHGFI_ICON
);
112 skip("Unable to get my own icon\n");
117 if (!pSHCreateFileExtractIconW
)
119 skip("SHCreateFileExtractIconW not available\n");
123 for (size_t n
= 0; n
< _countof(InterfaceTests
); ++n
)
126 CComPtr
<IUnknown
> spUnknown
;
127 HRESULT hr
= pSHCreateFileExtractIconW(L
"test.txt", FILE_ATTRIBUTE_NORMAL
, *InterfaceTests
[n
].IID
, (void**)&spUnknown
);
128 ok(hr
== InterfaceTests
[n
].ExpectedCreate
, "Expected hr to be 0x%lx, was 0x%lx for %u\n", InterfaceTests
[n
].ExpectedCreate
, hr
, n
);
132 CComPtr
<IUnknown
> spUnknown
, spUnknown2
;
133 HRESULT hr
= pSHCreateFileExtractIconW(L
"test.txt", FILE_ATTRIBUTE_NORMAL
, IID_PPV_ARG(IUnknown
, &spUnknown
));
134 ok(hr
== S_OK
, "Expected hr to be S_OK, was 0x%lx for %u\n", hr
, n
);
136 hr
= spUnknown
->QueryInterface(*InterfaceTests
[n
].IID
, (void**)&spUnknown2
);
137 ok(hr
== InterfaceTests
[n
].ExpectedQueryInterface
, "Expected hr to be 0x%lx, was 0x%lx for %u\n", InterfaceTests
[n
].ExpectedQueryInterface
, hr
, n
);
141 for (size_t n
= 0; n
< _countof(IconTests
); ++n
)
143 TestData
& cur
= IconTests
[n
];
144 bool useMyIcon
= false;
146 if (cur
.Name
== NULL
)
148 cur
.Name
= CurrentModule
;
152 CComPtr
<IExtractIconW
> spExtract
;
153 HRESULT hr
= pSHCreateFileExtractIconW(cur
.Name
, cur
.dwFlags
, IID_PPV_ARG(IExtractIconW
, &spExtract
));
154 ok(hr
== S_OK
, "Expected hr to be S_OK, was 0x%lx for %S(%lx)\n", hr
, cur
.Name
, cur
.dwFlags
);
159 /* Show that GIL_DEFAULTICON does not work. */
162 UINT wFlags
= 0xdeaddead;
163 WCHAR Buffer
[MAX_PATH
];
165 hr
= spExtract
->GetIconLocation(GIL_DEFAULTICON
, Buffer
, _countof(Buffer
), &ilIndex
, &wFlags
);
166 ok(hr
== S_FALSE
, "Expected hr to be S_FALSE, was 0x%lx for %S(0x%lx)\n", hr
, cur
.Name
, cur
.dwFlags
);
170 for (UINT idFlags
= 0; idFlags
< _countof(tryFlags
); ++idFlags
)
173 UINT wFlags
= 0xdeaddead;
174 WCHAR Buffer
[MAX_PATH
];
176 hr
= spExtract
->GetIconLocation(tryFlags
[idFlags
], Buffer
, _countof(Buffer
), &ilIndex
, &wFlags
);
177 ok(hr
== S_OK
, "Expected hr to be S_OK, was 0x%lx for %S(0x%lx,0x%x)\n", hr
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
181 ok(wFlags
& (GIL_NOTFILENAME
|GIL_PERCLASS
), "Expected GIL_NOTFILENAME|GIL_PERCLASS to be set for %S(0x%lx,0x%x)\n", cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
182 ok(!wcscmp(Buffer
, L
"*"), "Expected '*', was '%S' for %S(0x%lx,0x%x)\n", Buffer
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
185 hr
= spExtract
->Extract(Buffer
, ilIndex
, &ico
, NULL
, 0);
187 /* Visualize the icon extracted for whoever is stepping through this code. */
188 HWND console
= GetConsoleWindow();
189 SendMessage(console
, WM_SETICON
, ICON_BIG
, (LPARAM
)ico
);
190 SendMessage(console
, WM_SETICON
, ICON_SMALL
, (LPARAM
)ico
);
192 CComHeapPtr
<BYTE
> colorData
, maskData
;
193 DWORD colorSize
= 0, maskSize
= 0;
195 GetIconData(ico
, colorData
, colorSize
, maskData
, maskSize
);
197 if (!colorSize
|| !maskSize
)
201 ULONG_PTR firet
= SHGetFileInfoW(cur
.Name
, cur
.dwFlags
, &shfi
, sizeof(shfi
), SHGFI_USEFILEATTRIBUTES
| SHGFI_ICON
| SHGFI_SYSICONINDEX
);
206 ok(shfi
.iIcon
== ilIndex
, "Expected ilIndex to be 0%x, was 0x%x for %S(0x%lx,0x%x)\n", shfi
.iIcon
, ilIndex
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
209 CComHeapPtr
<BYTE
> colorDataRef
, maskDataRef
;
210 DWORD colorSizeRef
= 0, maskSizeRef
= 0;
211 GetIconData(shfi
.hIcon
, colorDataRef
, colorSizeRef
, maskDataRef
, maskSizeRef
);
213 ok(colorSizeRef
== colorSize
, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", colorSizeRef
, colorSize
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
214 ok(maskSizeRef
== maskSize
, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", maskSizeRef
, maskSize
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
216 if (colorSizeRef
== colorSize
)
218 ok(!memcmp(colorData
, colorDataRef
, colorSize
), "Expected equal colorData for %S(0x%lx,0x%x)\n", cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
221 if (maskSizeRef
== maskSize
)
223 ok(!memcmp(maskData
, maskDataRef
, maskSize
), "Expected equal maskData for %S(0x%lx,0x%x)\n", cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
230 colorSizeRef
= maskSizeRef
= 0;
231 GetIconData(myIcon
, colorDataRef
, colorSizeRef
, maskDataRef
, maskSizeRef
);
233 ok(colorSizeRef
== colorSize
, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", colorSizeRef
, colorSize
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
234 ok(maskSizeRef
== maskSize
, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", maskSizeRef
, maskSize
, cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
236 if (colorSizeRef
== colorSize
)
238 /* In case requested filetype does not match, the exe icon is not used! */
239 if (cur
.dwFlags
== FILE_ATTRIBUTE_DIRECTORY
)
241 ok(memcmp(colorData
, colorDataRef
, colorSize
), "Expected colorData to be changed for %S(0x%lx,0x%x)\n", cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
245 ok(!memcmp(colorData
, colorDataRef
, colorSize
), "Expected equal colorData for %S(0x%lx,0x%x)\n", cur
.Name
, cur
.dwFlags
, tryFlags
[idFlags
]);
249 // Mask is not reliable for some reason
250 //if (maskSizeRef == maskSize)
252 // ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(0x%lx,0x%lx)\n", cur.Name, cur.dwFlags);