[SHELL32][APITESTS] Add tests of OpenAs_RunDLL
[reactos.git] / modules / rostests / apitests / shell32 / SHCreateFileExtractIconW.cpp
1 /*
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)
6 */
7
8 #include "shelltest.h"
9
10 #include <wincon.h>
11 #include <wingdi.h>
12
13 ULONG DbgPrint(PCH Format,...);
14 #include <shellutils.h>
15
16 HRESULT (STDAPICALLTYPE *pSHCreateFileExtractIconW)(LPCWSTR pszFile, DWORD dwFileAttributes, REFIID riid, void **ppv);
17
18 struct TestData
19 {
20 const WCHAR* Name;
21 DWORD dwFlags;
22 };
23
24 static TestData IconTests[] =
25 {
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 },
36 };
37
38 struct TestIID
39 {
40 const GUID* IID;
41 HRESULT ExpectedCreate;
42 HRESULT ExpectedQueryInterface;
43 };
44
45 static TestIID InterfaceTests[] =
46 {
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 },
52 };
53
54
55 static void ExtractOneBitmap(HBITMAP hbm, CComHeapPtr<BYTE>& data, DWORD& size)
56 {
57 HDC hdc = CreateCompatibleDC(NULL);
58 HGDIOBJ obj = SelectObject(hdc, hbm);
59
60 CComHeapPtr<BITMAPINFO> pInfoBM;
61
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))
66 return;
67
68 size = pInfoBM->bmiHeader.biSizeImage;
69 data.Allocate(size);
70 GetDIBits(hdc, hbm, 0, pInfoBM->bmiHeader.biHeight, data, pInfoBM, DIB_RGB_COLORS);
71
72 SelectObject(hdc, obj);
73 DeleteDC(hdc);
74 }
75
76 static bool GetIconData(HICON icon, CComHeapPtr<BYTE>& colorData, DWORD& colorSize, CComHeapPtr<BYTE>& maskData, DWORD& maskSize)
77 {
78 ICONINFO iconinfo;
79
80 if (!GetIconInfo(icon, &iconinfo))
81 return false;
82
83 ExtractOneBitmap(iconinfo.hbmColor, colorData, colorSize);
84 ExtractOneBitmap(iconinfo.hbmMask, maskData, maskSize);
85
86 DeleteObject(iconinfo.hbmColor);
87 DeleteObject(iconinfo.hbmMask);
88
89 return true;
90 }
91
92
93 START_TEST(SHCreateFileExtractIconW)
94 {
95 WCHAR CurrentModule[MAX_PATH];
96 HMODULE shell32 = LoadLibraryA("shell32.dll");
97 HICON myIcon;
98 pSHCreateFileExtractIconW = (HRESULT (__stdcall *)(LPCWSTR, DWORD, REFIID, void **))GetProcAddress(shell32, "SHCreateFileExtractIconW");
99
100 /* Show that icons returned are always the same */
101 UINT tryFlags[4] = { 0, GIL_FORSHORTCUT, GIL_OPENICON };
102
103 CoInitialize(NULL);
104
105 GetModuleFileNameW(NULL, CurrentModule, _countof(CurrentModule));
106 {
107 SHFILEINFOW shfi;
108 ULONG_PTR firet = SHGetFileInfoW(CurrentModule, 0, &shfi, sizeof(shfi), SHGFI_ICON);
109 myIcon = shfi.hIcon;
110 if (!firet)
111 {
112 skip("Unable to get my own icon\n");
113 return;
114 }
115 }
116
117 if (!pSHCreateFileExtractIconW)
118 {
119 skip("SHCreateFileExtractIconW not available\n");
120 return;
121 }
122
123 for (size_t n = 0; n < _countof(InterfaceTests); ++n)
124 {
125 {
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);
129 }
130
131 {
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);
135
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);
138 }
139 }
140
141 for (size_t n = 0; n < _countof(IconTests); ++n)
142 {
143 TestData& cur = IconTests[n];
144 bool useMyIcon = false;
145
146 if (cur.Name == NULL)
147 {
148 cur.Name = CurrentModule;
149 useMyIcon = true;
150 }
151
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);
155
156 if (!SUCCEEDED(hr))
157 continue;
158
159 /* Show that GIL_DEFAULTICON does not work. */
160 {
161 int ilIndex = -1;
162 UINT wFlags = 0xdeaddead;
163 WCHAR Buffer[MAX_PATH];
164
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);
167 }
168
169
170 for (UINT idFlags = 0; idFlags < _countof(tryFlags); ++idFlags)
171 {
172 int ilIndex = -1;
173 UINT wFlags = 0xdeaddead;
174 WCHAR Buffer[MAX_PATH];
175
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]);
178 if (!SUCCEEDED(hr))
179 continue;
180
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]);
183
184 HICON ico;
185 hr = spExtract->Extract(Buffer, ilIndex, &ico, NULL, 0);
186
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);
191
192 CComHeapPtr<BYTE> colorData, maskData;
193 DWORD colorSize = 0, maskSize = 0;
194
195 GetIconData(ico, colorData, colorSize, maskData, maskSize);
196
197 if (!colorSize || !maskSize)
198 continue;
199
200 SHFILEINFOW shfi;
201 ULONG_PTR firet = SHGetFileInfoW(cur.Name, cur.dwFlags, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SYSICONINDEX);
202
203 if (!firet)
204 continue;
205
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]);
207
208
209 CComHeapPtr<BYTE> colorDataRef, maskDataRef;
210 DWORD colorSizeRef = 0, maskSizeRef = 0;
211 GetIconData(shfi.hIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef);
212
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]);
215
216 if (colorSizeRef == colorSize)
217 {
218 ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]);
219 }
220
221 if (maskSizeRef == maskSize)
222 {
223 ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]);
224 }
225
226 if (useMyIcon)
227 {
228 colorDataRef.Free();
229 maskDataRef.Free();
230 colorSizeRef = maskSizeRef = 0;
231 GetIconData(myIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef);
232
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]);
235
236 if (colorSizeRef == colorSize)
237 {
238 /* In case requested filetype does not match, the exe icon is not used! */
239 if (cur.dwFlags == FILE_ATTRIBUTE_DIRECTORY)
240 {
241 ok(memcmp(colorData, colorDataRef, colorSize), "Expected colorData to be changed for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]);
242 }
243 else
244 {
245 ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]);
246 }
247 }
248
249 // Mask is not reliable for some reason
250 //if (maskSizeRef == maskSize)
251 //{
252 // ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(0x%lx,0x%lx)\n", cur.Name, cur.dwFlags);
253 //}
254 }
255 }
256 }
257 }