[SHELL32_APITEST] Add test for SHCreateFileExtractIconW
[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 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include "shelltest.h"
9 #include <atlbase.h>
10 #include <atlcom.h>
11 ULONG DbgPrint(PCH Format,...);
12 #include <shellutils.h>
13 #include <wincon.h>
14 #include <wingdi.h>
15
16
17 HRESULT (STDAPICALLTYPE *pSHCreateFileExtractIconW)(LPCWSTR pszFile, DWORD dwFileAttributes, REFIID riid, void **ppv);
18
19 struct test_data
20 {
21 const WCHAR* Name;
22 DWORD dwFlags;
23 };
24
25 static test_data Tests[] =
26 {
27 { L"xxx.zip", FILE_ATTRIBUTE_NORMAL },
28 { L"xxx.zip", FILE_ATTRIBUTE_DIRECTORY },
29 { L"xxx.exe", FILE_ATTRIBUTE_NORMAL },
30 { L"xxx.exe", FILE_ATTRIBUTE_DIRECTORY },
31 { L"xxx.dll", FILE_ATTRIBUTE_NORMAL },
32 { L"xxx.dll", FILE_ATTRIBUTE_DIRECTORY },
33 { L"xxx.txt", FILE_ATTRIBUTE_NORMAL },
34 { L"xxx.txt", FILE_ATTRIBUTE_DIRECTORY },
35 { NULL, FILE_ATTRIBUTE_NORMAL },
36 { NULL, FILE_ATTRIBUTE_DIRECTORY },
37 };
38
39
40 static void ExtractOneBitmap(HBITMAP hbm, CComHeapPtr<BYTE>& data, DWORD& size)
41 {
42 HDC hdc = CreateCompatibleDC(NULL);
43 HGDIOBJ obj = SelectObject(hdc, hbm);
44
45 CComHeapPtr<BITMAPINFO> pInfoBM;
46
47 pInfoBM.AllocateBytes(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
48 memset(pInfoBM, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
49 pInfoBM->bmiHeader.biSize = sizeof(pInfoBM->bmiHeader);
50 if (!GetDIBits(hdc, hbm, 0, 0, NULL, pInfoBM, DIB_RGB_COLORS))
51 return;
52
53 size = pInfoBM->bmiHeader.biSizeImage;
54 data.Allocate(size);
55 GetDIBits(hdc, hbm, 0, pInfoBM->bmiHeader.biHeight, data, pInfoBM, DIB_RGB_COLORS);
56
57 SelectObject(hdc, obj);
58 DeleteDC(hdc);
59 }
60
61 static bool GetIconData(HICON icon, CComHeapPtr<BYTE>& colorData, DWORD& colorSize, CComHeapPtr<BYTE>& maskData, DWORD& maskSize)
62 {
63 ICONINFO iconinfo;
64
65 if (!GetIconInfo(icon, &iconinfo))
66 return false;
67
68 ExtractOneBitmap(iconinfo.hbmColor, colorData, colorSize);
69 ExtractOneBitmap(iconinfo.hbmMask, maskData, maskSize);
70
71 DeleteObject(iconinfo.hbmColor);
72 DeleteObject(iconinfo.hbmMask);
73
74 return true;
75 }
76
77
78 START_TEST(SHCreateFileExtractIconW)
79 {
80 WCHAR CurrentModule[MAX_PATH];
81 HMODULE shell32 = LoadLibraryA("shell32.dll");
82 HICON myIcon;
83 pSHCreateFileExtractIconW = (HRESULT (__stdcall *)(LPCWSTR, DWORD, REFIID, void **))GetProcAddress(shell32, "SHCreateFileExtractIconW");
84
85 CoInitialize(NULL);
86
87 GetModuleFileNameW(NULL, CurrentModule, _countof(CurrentModule));
88 {
89 SHFILEINFOW shfi;
90 ULONG_PTR firet = SHGetFileInfoW(CurrentModule, 0, &shfi, sizeof(shfi), SHGFI_ICON);
91 myIcon = shfi.hIcon;
92 if (!firet)
93 {
94 skip("Unable to get my own icon\n");
95 return;
96 }
97 }
98
99 if (!pSHCreateFileExtractIconW)
100 {
101 skip("SHCreateFileExtractIconW not available\n");
102 return;
103 }
104
105 for (size_t n = 0; n < _countof(Tests); ++n)
106 {
107 test_data& cur = Tests[n];
108 bool useMyIcon = false;
109
110 if (cur.Name == NULL)
111 {
112 cur.Name = CurrentModule;
113 useMyIcon = true;
114 }
115
116 CComPtr<IExtractIconW> spExtract;
117 HRESULT hr = pSHCreateFileExtractIconW(cur.Name, cur.dwFlags, IID_PPV_ARG(IExtractIconW, &spExtract));
118 ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %S(%lx)\n", hr, cur.Name, cur.dwFlags);
119
120 if (!SUCCEEDED(hr))
121 continue;
122
123 int ilIndex = -1;
124 UINT wFlags = 0xdeaddead;
125 WCHAR Buffer[MAX_PATH];
126
127 hr = spExtract->GetIconLocation(0, Buffer, _countof(Buffer), &ilIndex, &wFlags);
128 ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %S(%lx)\n", hr, cur.Name, cur.dwFlags);
129 if (!SUCCEEDED(hr))
130 continue;
131
132 ok(wFlags & (GIL_NOTFILENAME|GIL_PERCLASS), "Expected GIL_NOTFILENAME|GIL_PERCLASS to be set for %S(%lx)\n", cur.Name, cur.dwFlags);
133 ok(!wcscmp(Buffer, L"*"), "Expected '*', was '%S' for %S(%lx)\n", Buffer, cur.Name, cur.dwFlags);
134
135 HICON ico;
136 hr = spExtract->Extract(Buffer, ilIndex, &ico, NULL, 0);
137
138 /* Visualize the icon extracted for whoever is stepping through this code. */
139 HWND console = GetConsoleWindow();
140 SendMessage(console, WM_SETICON, ICON_BIG, (LPARAM)ico);
141 SendMessage(console, WM_SETICON, ICON_SMALL, (LPARAM)ico);
142
143 CComHeapPtr<BYTE> colorData, maskData;
144 DWORD colorSize = 0, maskSize = 0;
145
146 GetIconData(ico, colorData, colorSize, maskData, maskSize);
147
148 if (!colorSize || !maskSize)
149 continue;
150
151 SHFILEINFOW shfi;
152 ULONG_PTR firet = SHGetFileInfoW(cur.Name, cur.dwFlags, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON);
153
154 if (!firet)
155 continue;
156
157 CComHeapPtr<BYTE> colorDataRef, maskDataRef;
158 DWORD colorSizeRef = 0, maskSizeRef = 0;
159 GetIconData(shfi.hIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef);
160
161 ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(%lx)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags);
162 ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(%lx)\n", maskSizeRef, maskSize, cur.Name, cur.dwFlags);
163
164 if (colorSizeRef == colorSize)
165 {
166 ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(%lx)\n", cur.Name, cur.dwFlags);
167 }
168
169 if (maskSizeRef == maskSize)
170 {
171 ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(%lx)\n", cur.Name, cur.dwFlags);
172 }
173
174 if (useMyIcon)
175 {
176 colorDataRef.Free();
177 maskDataRef.Free();
178 colorSizeRef = maskSizeRef = 0;
179 GetIconData(myIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef);
180
181 ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(%lx)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags);
182 ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(%lx)\n", maskSizeRef, maskSize, cur.Name, cur.dwFlags);
183
184 if (colorSizeRef == colorSize)
185 {
186 /* Incase requested filetype does not match, the exe icon is not used! */
187 if (cur.dwFlags == FILE_ATTRIBUTE_DIRECTORY)
188 {
189 ok(memcmp(colorData, colorDataRef, colorSize), "Expected colorData to be changed for %S(%lx)\n", cur.Name, cur.dwFlags);
190 }
191 else
192 {
193 ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(%lx)\n", cur.Name, cur.dwFlags);
194 }
195 }
196
197 // Mask is not reliable for some reason
198 //if (maskSizeRef == maskSize)
199 //{
200 // ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(%lx)\n", cur.Name, cur.dwFlags);
201 //}
202 }
203 }
204 }