8915b3a7aa8474f353660d543a2c1ccaee5dfa77
[reactos.git] / modules / rostests / winetests / shlwapi / assoc.c
1 /* Unit test suite for SHLWAPI IQueryAssociations functions
2 *
3 * Copyright 2008 Google (Lei Zhang)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "precomp.h"
21
22 #define expect(expected, got) ok( (expected) == (got), "Expected %d, got %d\n", (expected), (got))
23 #define expect_hr(expected, got) ok( (expected) == (got), "Expected %08x, got %08x\n", (expected), (got))
24
25 static HRESULT (WINAPI *pAssocQueryStringA)(ASSOCF,ASSOCSTR,LPCSTR,LPCSTR,LPSTR,LPDWORD) = NULL;
26 static HRESULT (WINAPI *pAssocQueryStringW)(ASSOCF,ASSOCSTR,LPCWSTR,LPCWSTR,LPWSTR,LPDWORD) = NULL;
27 static HRESULT (WINAPI *pAssocCreate)(CLSID, REFIID, void **) = NULL;
28 static HRESULT (WINAPI *pAssocGetPerceivedType)(LPCWSTR, PERCEIVED *, INT *, LPWSTR *) = NULL;
29
30 /* Every version of Windows with IE should have this association? */
31 static const WCHAR dotHtml[] = { '.','h','t','m','l',0 };
32 static const WCHAR badBad[] = { 'b','a','d','b','a','d',0 };
33 static const WCHAR dotBad[] = { '.','b','a','d',0 };
34 static const WCHAR open[] = { 'o','p','e','n',0 };
35 static const WCHAR invalid[] = { 'i','n','v','a','l','i','d',0 };
36
37 static void test_getstring_bad(void)
38 {
39 static const WCHAR openwith[] = {'O','p','e','n','W','i','t','h','.','e','x','e',0};
40 WCHAR buf[MAX_PATH];
41 HRESULT hr;
42 DWORD len;
43
44 if (!pAssocQueryStringW)
45 {
46 win_skip("AssocQueryStringW() is missing\n");
47 return;
48 }
49
50 len = 0xdeadbeef;
51 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, NULL, open, NULL, &len);
52 expect_hr(E_INVALIDARG, hr);
53 ok(len == 0xdeadbeef, "got %u\n", len);
54
55 len = 0xdeadbeef;
56 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, badBad, open, NULL, &len);
57 ok(hr == E_FAIL ||
58 hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION), /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */
59 "Unexpected result : %08x\n", hr);
60 ok(len == 0xdeadbeef, "got %u\n", len);
61
62 len = sizeof(buf)/sizeof(buf[0]);
63 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, dotBad, open, buf, &len);
64 ok(hr == E_FAIL ||
65 hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION) /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */ ||
66 hr == S_OK /* Win8 */,
67 "Unexpected result : %08x\n", hr);
68 if (hr == S_OK)
69 {
70 ok(len < sizeof(buf)/sizeof(buf[0]), "got %u\n", len);
71 ok(!lstrcmpiW(buf + len - sizeof(openwith)/sizeof(openwith[0]), openwith), "wrong data\n");
72 }
73
74 len = 0xdeadbeef;
75 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, dotHtml, invalid, NULL, &len);
76 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
77 hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION), /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */
78 "Unexpected result : %08x\n", hr);
79 ok(len == 0xdeadbeef, "got %u\n", len);
80
81 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, dotHtml, open, NULL, NULL);
82 ok(hr == E_UNEXPECTED ||
83 hr == E_INVALIDARG, /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */
84 "Unexpected result : %08x\n", hr);
85
86 len = 0xdeadbeef;
87 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, NULL, open, NULL, &len);
88 expect_hr(E_INVALIDARG, hr);
89 ok(len == 0xdeadbeef, "got %u\n", len);
90
91 len = 0xdeadbeef;
92 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, badBad, open, NULL, &len);
93 ok(hr == E_FAIL ||
94 hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION), /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */
95 "Unexpected result : %08x\n", hr);
96 ok(len == 0xdeadbeef, "got %u\n", len);
97
98 len = 0xdeadbeef;
99 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, dotBad, open, NULL, &len);
100 ok(hr == E_FAIL ||
101 hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION) /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */ ||
102 hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) /* Win8 */ ||
103 hr == S_FALSE, /* Win10 */
104 "Unexpected result : %08x\n", hr);
105 ok((hr == S_FALSE && len < sizeof(buf)/sizeof(buf[0])) || len == 0xdeadbeef,
106 "got hr=%08x and len=%u\n", hr, len);
107
108 len = 0xdeadbeef;
109 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, dotHtml, invalid, NULL, &len);
110 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
111 hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION) || /* W2K/Vista/W2K8 */
112 hr == E_FAIL, /* Win9x/WinMe/NT4 */
113 "Unexpected result : %08x\n", hr);
114 ok(len == 0xdeadbeef, "got %u\n", len);
115
116 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, dotHtml, open, NULL, NULL);
117 ok(hr == E_UNEXPECTED ||
118 hr == E_INVALIDARG, /* Win9x/WinMe/NT4/W2K/Vista/W2K8 */
119 "Unexpected result : %08x\n", hr);
120 }
121
122 static void test_getstring_basic(void)
123 {
124 HRESULT hr;
125 WCHAR * friendlyName;
126 WCHAR * executableName;
127 DWORD len, len2, slen;
128
129 if (!pAssocQueryStringW)
130 {
131 win_skip("AssocQueryStringW() is missing\n");
132 return;
133 }
134
135 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, dotHtml, open, NULL, &len);
136 expect_hr(S_FALSE, hr);
137 if (hr != S_FALSE)
138 {
139 skip("failed to get initial len\n");
140 return;
141 }
142
143 executableName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
144 len * sizeof(WCHAR));
145 if (!executableName)
146 {
147 skip("failed to allocate memory\n");
148 return;
149 }
150
151 len2 = len;
152 hr = pAssocQueryStringW(0, ASSOCSTR_EXECUTABLE, dotHtml, open,
153 executableName, &len2);
154 expect_hr(S_OK, hr);
155 slen = lstrlenW(executableName) + 1;
156 expect(len, len2);
157 expect(len, slen);
158
159 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, dotHtml, open, NULL,
160 &len);
161 ok(hr == S_FALSE ||
162 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* Win9x/NT4 */ ||
163 hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), /* Win8 */
164 "Unexpected result : %08x\n", hr);
165 if (hr != S_FALSE)
166 {
167 HeapFree(GetProcessHeap(), 0, executableName);
168 skip("failed to get initial len\n");
169 return;
170 }
171
172 friendlyName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
173 len * sizeof(WCHAR));
174 if (!friendlyName)
175 {
176 HeapFree(GetProcessHeap(), 0, executableName);
177 skip("failed to allocate memory\n");
178 return;
179 }
180
181 len2 = len;
182 hr = pAssocQueryStringW(0, ASSOCSTR_FRIENDLYAPPNAME, dotHtml, open,
183 friendlyName, &len2);
184 expect_hr(S_OK, hr);
185 slen = lstrlenW(friendlyName) + 1;
186 expect(len, len2);
187 expect(len, slen);
188
189 HeapFree(GetProcessHeap(), 0, executableName);
190 HeapFree(GetProcessHeap(), 0, friendlyName);
191 }
192
193 static void test_getstring_no_extra(void)
194 {
195 LONG ret;
196 HKEY hkey;
197 HRESULT hr;
198 static const CHAR dotWinetest[] = {
199 '.','w','i','n','e','t','e','s','t',0
200 };
201 static const CHAR winetestfile[] = {
202 'w','i','n','e','t','e','s','t', 'f','i','l','e',0
203 };
204 static const CHAR winetestfileAction[] = {
205 'w','i','n','e','t','e','s','t','f','i','l','e',
206 '\\','s','h','e','l','l',
207 '\\','f','o','o',
208 '\\','c','o','m','m','a','n','d',0
209 };
210 static const CHAR action[] = {
211 'n','o','t','e','p','a','d','.','e','x','e',0
212 };
213 CHAR buf[MAX_PATH];
214 DWORD len = MAX_PATH;
215
216 if (!pAssocQueryStringA)
217 {
218 win_skip("AssocQueryStringA() is missing\n");
219 return;
220 }
221
222 buf[0] = '\0';
223 ret = RegCreateKeyA(HKEY_CLASSES_ROOT, dotWinetest, &hkey);
224 if (ret != ERROR_SUCCESS) {
225 skip("failed to create dotWinetest key\n");
226 return;
227 }
228
229 ret = RegSetValueA(hkey, NULL, REG_SZ, winetestfile, lstrlenA(winetestfile));
230 RegCloseKey(hkey);
231 if (ret != ERROR_SUCCESS)
232 {
233 skip("failed to set dotWinetest key\n");
234 goto cleanup;
235 }
236
237 ret = RegCreateKeyA(HKEY_CLASSES_ROOT, winetestfileAction, &hkey);
238 if (ret != ERROR_SUCCESS)
239 {
240 skip("failed to create winetestfileAction key\n");
241 goto cleanup;
242 }
243
244 ret = RegSetValueA(hkey, NULL, REG_SZ, action, lstrlenA(action));
245 RegCloseKey(hkey);
246 if (ret != ERROR_SUCCESS)
247 {
248 skip("failed to set winetestfileAction key\n");
249 goto cleanup;
250 }
251
252 hr = pAssocQueryStringA(0, ASSOCSTR_EXECUTABLE, dotWinetest, NULL, buf, &len);
253 ok(hr == S_OK ||
254 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP and W2K3 */
255 "Unexpected result : %08x\n", hr);
256 hr = pAssocQueryStringA(0, ASSOCSTR_EXECUTABLE, dotWinetest, "foo", buf, &len);
257 expect_hr(S_OK, hr);
258 ok(strstr(buf, action) != NULL,
259 "got '%s' (Expected result to include 'notepad.exe')\n", buf);
260
261 cleanup:
262 SHDeleteKeyA(HKEY_CLASSES_ROOT, dotWinetest);
263 SHDeleteKeyA(HKEY_CLASSES_ROOT, winetestfile);
264
265 }
266
267 static void test_assoc_create(void)
268 {
269 HRESULT hr;
270 IQueryAssociations *pqa;
271
272 if (!pAssocCreate)
273 {
274 win_skip("AssocCreate() is missing\n");
275 return;
276 }
277
278 hr = pAssocCreate(IID_NULL, &IID_NULL, NULL);
279 ok(hr == E_INVALIDARG, "Unexpected result : %08x\n", hr);
280
281 hr = pAssocCreate(CLSID_QueryAssociations, &IID_NULL, (LPVOID*)&pqa);
282 ok(hr == CLASS_E_CLASSNOTAVAILABLE || hr == E_NOTIMPL || hr == E_NOINTERFACE
283 , "Unexpected result : %08x\n", hr);
284
285 hr = pAssocCreate(IID_NULL, &IID_IQueryAssociations, (LPVOID*)&pqa);
286 ok(hr == CLASS_E_CLASSNOTAVAILABLE || hr == E_NOTIMPL || hr == E_INVALIDARG
287 , "Unexpected result : %08x\n", hr);
288
289 hr = pAssocCreate(CLSID_QueryAssociations, &IID_IQueryAssociations, (LPVOID*)&pqa);
290 ok(hr == S_OK || hr == E_NOTIMPL /* win98 */
291 , "Unexpected result : %08x\n", hr);
292 if(hr == S_OK)
293 {
294 IQueryAssociations_Release(pqa);
295 }
296
297 hr = pAssocCreate(CLSID_QueryAssociations, &IID_IUnknown, (LPVOID*)&pqa);
298 ok(hr == S_OK || hr == E_NOTIMPL /* win98 */
299 , "Unexpected result : %08x\n", hr);
300 if(hr == S_OK)
301 {
302 IQueryAssociations_Release(pqa);
303 }
304 }
305
306 /* Based on http://www.geoffchappell.com/studies/windows/shell/shlwapi/api/assocapi/getperceivedtype.htm */
307 struct assoc_test_struct
308 {
309 PCSTR extension;
310 PERCEIVED perceived;
311 INT flags;
312 PCSTR type;
313 DWORD minversion;
314 HRESULT hr;
315 };
316
317 #define HARDCODED_NATIVE_WMSDK (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_WMSDK)
318 #define HARDCODED_NATIVE_GDIPLUS (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_GDIPLUS)
319 #define HARDCODED_NATIVE_ZIPFLDR (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_ZIPFOLDER)
320 #define SOFTCODED_NATIVESUPPORT (PERCEIVEDFLAG_SOFTCODED | PERCEIVEDFLAG_NATIVESUPPORT)
321
322 static const struct assoc_test_struct assoc_perceived_types[] =
323 {
324 /* builtins */
325 { ".aif", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
326 { ".aifc", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
327 { ".aiff", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
328 { ".asf", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
329 { ".asx", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
330 { ".au", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
331 { ".avi", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
332 { ".bas", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
333 { ".bat", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
334 { ".bmp", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
335 { ".cmd", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
336 { ".com", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
337 { ".cpl", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_HARDCODED, "system", 0x600 },
338 { ".dib", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
339 { ".dvr-ms", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
340 { ".emf", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
341 { ".exe", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
342 { ".gif", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
343 { ".hta", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
344 /* htm & html are PERCEIVED_TYPE_TEXT, PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_SOFTCODED in w2k3 */
345 { ".htm", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_HARDCODED, "document", 0x600 },
346 { ".html", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_HARDCODED, "document", 0x600 },
347 { ".ico", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
348 { ".IVF", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
349 { ".jfif", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
350 { ".jpe", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
351 { ".jpeg", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
352 { ".jpg", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
353 { ".lnk", PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_HARDCODED, NULL, 0x600, E_FAIL },
354 { ".m1v", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
355 { ".m3u", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
356 { ".mht", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_HARDCODED, "document", 0x600 },
357 { ".mid", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
358 { ".midi", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
359 { ".msi", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
360 /* below win8 this is defined to be video */
361 { ".mp2", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio", 0x602 },
362 { ".mp2v", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
363 { ".mp3", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
364 { ".mpa", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
365 { ".mpe", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
366 { ".mpeg", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
367 { ".mpg", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
368 { ".mpv2", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
369 { ".pif", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
370 { ".png", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
371 { ".reg", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
372 { ".rle", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
373 { ".rmi", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
374 { ".scr", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
375 { ".search-ms", PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_HARDCODED, NULL, 0x600, E_FAIL },
376 { ".snd", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
377 { ".tif", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
378 { ".tiff", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
379 { ".vb", PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, "application" },
380 { ".wav", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
381 { ".wax", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
382 { ".wm", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
383 { ".wma", PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, "audio" },
384 { ".wmf", PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, "image" },
385 { ".wmv", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
386 { ".wmx", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
387 { ".wvx", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" },
388 { ".zip", PERCEIVED_TYPE_COMPRESSED, HARDCODED_NATIVE_ZIPFLDR, "compressed" },
389 /* found in the registry under HKEY_CLASSES_ROOT on a new Win7 VM */
390 { ".386", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system" },
391 { ".3g2", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
392 { ".3gp", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
393 { ".3gp2", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
394 { ".3gpp", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
395 { ".AAC", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
396 { ".ADT", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
397 { ".ADTS", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
398 { ".asm", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
399 { ".asmx", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
400 { ".aspx", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
401 { ".c", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
402 { ".cab", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed", 0x600 },
403 { ".chk", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system" },
404 { ".cpp", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
405 { ".css", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
406 { ".cxx", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
407 { ".def", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
408 { ".diz", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
409 { ".docx", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x601 },
410 { ".drv", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system", 0x600 },
411 { ".gz", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed" },
412 { ".h", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
413 { ".hpp", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
414 { ".hxx", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
415 { ".inc", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
416 { ".ini", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x600 },
417 { ".java", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
418 { ".local", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system" },
419 { ".M2T", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
420 { ".M2TS", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
421 { ".M2V", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
422 { ".m4a", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
423 { ".m4b", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
424 { ".m4p", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
425 { ".m4v", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
426 { ".manifest", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system" },
427 { ".MOD", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
428 { ".mov", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
429 { ".mp4", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
430 { ".mp4v", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
431 { ".MTS", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
432 { ".nvr", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
433 { ".ocx", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system" },
434 { ".odt", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x601 },
435 { ".php3", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
436 { ".pl", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
437 { ".plg", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
438 { ".ps1xml", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "Text" },
439 { ".rtf", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
440 { ".sed", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
441 { ".shtml", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
442 { ".sql", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
443 { ".sys", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system", 0x600 },
444 { ".tar", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed" },
445 { ".text", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
446 { ".tgz", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed" },
447 { ".TS", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
448 { ".tsv", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
449 { ".TTS", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
450 { ".txt", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
451 { ".vob", PERCEIVED_TYPE_VIDEO, PERCEIVEDFLAG_SOFTCODED, "video", 0x601 },
452 { ".vxd", PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_SOFTCODED, "system" },
453 { ".wdp", PERCEIVED_TYPE_IMAGE, PERCEIVEDFLAG_SOFTCODED, "image" },
454 { ".wmz", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed" },
455 { ".wpl", PERCEIVED_TYPE_AUDIO, PERCEIVEDFLAG_SOFTCODED, "audio", 0x601 },
456 { ".wsz", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed" },
457 { ".x", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text" },
458 { ".xml", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x601 },
459 { ".xsl", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x601 },
460 { ".z", PERCEIVED_TYPE_COMPRESSED, PERCEIVEDFLAG_SOFTCODED, "compressed" },
461 /* found in the registry under HKEY_CLASSES_ROOT\PerceivedType */
462 { ".doc", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
463 { ".dot", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
464 { ".mhtml", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
465 { ".pot", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
466 { ".ppt", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
467 { ".rtf", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
468 { ".wri", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
469 { ".xls", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
470 { ".xlt", PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_SOFTCODED, "document", 0x600 },
471
472 };
473
474 static void test_assoc_one(const struct assoc_test_struct* test)
475 {
476 LPWSTR extension, type_expected, type_returned;
477 PERCEIVED perceived;
478 HRESULT hr;
479 INT flags;
480
481 /* if SHStrDupA receives a nullptr as input, it will null the output */
482 SHStrDupA(test->extension, &extension);
483 SHStrDupA(test->type, &type_expected);
484
485 perceived = 0xdeadbeef;
486 flags = 0xdeadbeef;
487
488 hr = pAssocGetPerceivedType(extension, &perceived, &flags, NULL);
489 expect_hr(type_expected ? S_OK : test->hr, hr);
490 ok(perceived == test->perceived, "%s: got perceived 0x%x, expected 0x%x\n",
491 test->extension, perceived, test->perceived);
492 ok(flags == test->flags, "%s: got flags 0x%x, expected 0x%x\n",
493 test->extension, flags, test->flags);
494
495 type_returned = (void *)0xdeadbeef;
496 perceived = 0xdeadbeef;
497 flags = 0xdeadbeef;
498
499 hr = pAssocGetPerceivedType(extension, &perceived, &flags, &type_returned);
500 expect_hr(type_expected ? S_OK : test->hr, hr);
501 ok(perceived == test->perceived, "%s: got perceived 0x%x, expected 0x%x\n",
502 test->extension, perceived, test->perceived);
503 ok(flags == test->flags, "%s: got flags 0x%x, expected 0x%x\n",
504 test->extension, flags, test->flags);
505
506 if (!type_expected)
507 {
508 ok(type_returned == (void *)0xdeadbeef || broken(type_returned == NULL) /* Win 8 */,
509 "%s: got type %p, expected 0xdeadbeef\n", test->extension, type_returned);
510 }
511 else if (type_returned == (void *)0xdeadbeef)
512 {
513 ok(type_returned != (void *)0xdeadbeef, "%s: got type %p, expected '%s'\n",
514 test->extension, type_returned, test->type);
515 }
516 else
517 {
518 ok(StrCmpIW(type_expected, type_returned) == 0, "%s: got type %s, expected '%s'\n",
519 test->extension, wine_dbgstr_w(type_returned), test->type);
520 }
521
522 CoTaskMemFree(type_returned);
523 CoTaskMemFree(extension);
524 CoTaskMemFree(type_expected);
525 }
526
527 static void test_assoc_perceived(void)
528 {
529 static const struct assoc_test_struct should_not_exist =
530 { ".should_not_exist", PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_UNDEFINED, NULL, 0, 0x80070002 };
531 static const struct assoc_test_struct htm[] =
532 {
533 { ".htm", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x600 },
534 { ".html", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x600 },
535 };
536 static const struct assoc_test_struct mp2 =
537 { ".mp2", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" };
538
539 OSVERSIONINFOEXW osvi;
540 DWORD version;
541 size_t i;
542
543 if (!pAssocGetPerceivedType)
544 {
545 win_skip("AssocGetPerceivedType() is missing\n");
546 return;
547 }
548
549 memset(&osvi, 0, sizeof(osvi));
550 osvi.dwOSVersionInfoSize = sizeof(osvi);
551 GetVersionExW((LPOSVERSIONINFOW)&osvi);
552 version = (osvi.dwMajorVersion << 8) | osvi.dwMinorVersion;
553
554 /* invalid entry results in HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) */
555 test_assoc_one(&should_not_exist);
556
557 for (i = 0; i < sizeof(assoc_perceived_types) / sizeof(assoc_perceived_types[0]); ++i)
558 {
559 if (assoc_perceived_types[i].minversion && assoc_perceived_types[i].minversion > version)
560 continue;
561 if (!(assoc_perceived_types[i].flags & PERCEIVEDFLAG_HARDCODED))
562 todo_wine test_assoc_one(&assoc_perceived_types[i]);
563 else
564 test_assoc_one(&assoc_perceived_types[i]);
565 }
566
567 /* below Vista */
568 if (version < 0x600)
569 {
570 todo_wine
571 test_assoc_one(&htm[0]);
572 todo_wine
573 test_assoc_one(&htm[1]);
574 }
575
576 /* below Win8 */
577 if (version < 0x602)
578 {
579 test_assoc_one(&mp2);
580 }
581 }
582
583 START_TEST(assoc)
584 {
585 HMODULE hshlwapi;
586 hshlwapi = GetModuleHandleA("shlwapi.dll");
587 pAssocQueryStringA = (void*)GetProcAddress(hshlwapi, "AssocQueryStringA");
588 pAssocQueryStringW = (void*)GetProcAddress(hshlwapi, "AssocQueryStringW");
589 pAssocCreate = (void*)GetProcAddress(hshlwapi, "AssocCreate");
590 pAssocGetPerceivedType = (void*)GetProcAddress(hshlwapi, "AssocGetPerceivedType");
591
592 test_getstring_bad();
593 test_getstring_basic();
594 test_getstring_no_extra();
595 test_assoc_create();
596 test_assoc_perceived();
597 }