ReactOS 0.4.16-dev-321-g63bb46a
shelllink.c
Go to the documentation of this file.
1/*
2 * Unit tests for shelllinks
3 *
4 * Copyright 2004 Mike McCormack
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 */
21
22#define COBJMACROS
23
24#include "initguid.h"
25#include "windows.h"
26#include "shlguid.h"
27#include "shobjidl.h"
28#include "shlobj.h"
29#include "shellapi.h"
30#include "commoncontrols.h"
31
32#include "wine/heap.h"
33#include "wine/test.h"
34
35#include "shell32_test.h"
36
37#ifdef __REACTOS__
38#include <reactos/undocshell.h>
39#endif
40
41#ifndef SLDF_HAS_LOGO3ID
42# define SLDF_HAS_LOGO3ID 0x00000800 /* not available in the Vista SDK */
43#endif
44
45static void (WINAPI *pILFree)(LPITEMIDLIST);
46static BOOL (WINAPI *pILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
47static HRESULT (WINAPI *pSHILCreateFromPath)(LPCWSTR, LPITEMIDLIST *,DWORD*);
48static HRESULT (WINAPI *pSHGetFolderLocation)(HWND,INT,HANDLE,DWORD,PIDLIST_ABSOLUTE*);
49static HRESULT (WINAPI *pSHDefExtractIconA)(LPCSTR, int, UINT, HICON*, HICON*, UINT);
50static HRESULT (WINAPI *pSHGetStockIconInfo)(SHSTOCKICONID, UINT, SHSTOCKICONINFO *);
51static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR, LPSTR, DWORD);
52static DWORD (WINAPI *pGetShortPathNameA)(LPCSTR, LPSTR, DWORD);
53static UINT (WINAPI *pSHExtractIconsW)(LPCWSTR, int, int, int, HICON *, UINT *, UINT, UINT);
54static BOOL (WINAPI *pIsProcessDPIAware)(void);
55
57 0x45e2b4ae, 0xb1c3, 0x11d0,
58 { 0xb9, 0x2f, 0x00, 0xa0, 0xc9, 0x03, 0x12, 0xe1 }
59};
60
61
62/* For some reason SHILCreateFromPath does not work on Win98 and
63 * SHSimpleIDListFromPathA does not work on NT4. But if we call both we
64 * get what we want on all platforms.
65 */
66static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID);
67
68static LPITEMIDLIST path_to_pidl(const char* path)
69{
70 LPITEMIDLIST pidl;
71
72 if (!pSHSimpleIDListFromPathAW)
73 {
74 HMODULE hdll=GetModuleHandleA("shell32.dll");
75 pSHSimpleIDListFromPathAW=(void*)GetProcAddress(hdll, (char*)162);
76 if (!pSHSimpleIDListFromPathAW)
77 win_skip("SHSimpleIDListFromPathAW not found in shell32.dll\n");
78 }
79
80 pidl=NULL;
81 /* pSHSimpleIDListFromPathAW maps to A on non NT platforms */
82 if (pSHSimpleIDListFromPathAW && (GetVersion() & 0x80000000))
83 pidl=pSHSimpleIDListFromPathAW(path);
84
85 if (!pidl)
86 {
87 WCHAR* pathW;
88 HRESULT r;
89 int len;
90
92 pathW = heap_alloc(len * sizeof(WCHAR));
93 MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len);
94
95 r=pSHILCreateFromPath(pathW, &pidl, NULL);
96 ok(r == S_OK, "SHILCreateFromPath failed (0x%08x)\n", r);
97 heap_free(pathW);
98 }
99 return pidl;
100}
101
102
103/*
104 * Test manipulation of an IShellLink's properties.
105 */
106
107static void test_get_set(void)
108{
109 HRESULT r;
110 IShellLinkA *sl;
111 IShellLinkW *slW = NULL;
112 char mypath[MAX_PATH];
113 char buffer[INFOTIPSIZE];
114 WIN32_FIND_DATAA finddata;
115 LPITEMIDLIST pidl, tmp_pidl;
116 const char * str;
117 int i;
118 WORD w;
119
120 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
121 &IID_IShellLinkA, (LPVOID*)&sl);
122 ok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r);
123 if (r != S_OK)
124 return;
125
126 /* Test Getting / Setting the description */
127 strcpy(buffer,"garbage");
128 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
129 ok(r == S_OK, "GetDescription failed (0x%08x)\n", r);
130 ok(*buffer=='\0', "GetDescription returned '%s'\n", buffer);
131
132 str="Some description";
133 r = IShellLinkA_SetDescription(sl, str);
134 ok(r == S_OK, "SetDescription failed (0x%08x)\n", r);
135
136 strcpy(buffer,"garbage");
137 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
138 ok(r == S_OK, "GetDescription failed (0x%08x)\n", r);
139 ok(strcmp(buffer,str)==0, "GetDescription returned '%s'\n", buffer);
140
141 r = IShellLinkA_SetDescription(sl, NULL);
142 ok(r == S_OK, "SetDescription failed (0x%08x)\n", r);
143
144 strcpy(buffer,"garbage");
145 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
146 ok(r == S_OK, "GetDescription failed (0x%08x)\n", r);
147 ok(*buffer=='\0' || broken(strcmp(buffer,str)==0), "GetDescription returned '%s'\n", buffer); /* NT4 */
148
149 /* Test Getting / Setting the work directory */
150 strcpy(buffer,"garbage");
151 r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer));
152 ok(r == S_OK, "GetWorkingDirectory failed (0x%08x)\n", r);
153 ok(*buffer=='\0', "GetWorkingDirectory returned '%s'\n", buffer);
154
155 str="c:\\nonexistent\\directory";
156 r = IShellLinkA_SetWorkingDirectory(sl, str);
157 ok(r == S_OK, "SetWorkingDirectory failed (0x%08x)\n", r);
158
159 strcpy(buffer,"garbage");
160 r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer));
161 ok(r == S_OK, "GetWorkingDirectory failed (0x%08x)\n", r);
162 ok(lstrcmpiA(buffer,str)==0, "GetWorkingDirectory returned '%s'\n", buffer);
163
164 /* Test Getting / Setting the path */
165 strcpy(buffer,"garbage");
166 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
167 ok(r == S_FALSE || broken(r == S_OK) /* NT4/W2K */, "GetPath failed (0x%08x)\n", r);
168 ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
169
170 strcpy(buffer,"garbage");
171 memset(&finddata, 0xaa, sizeof(finddata));
172 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH);
173 ok(r == S_FALSE || broken(r == S_OK) /* NT4/W2K */, "GetPath failed (0x%08x)\n", r);
174 ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
175 ok(finddata.dwFileAttributes == 0, "unexpected attributes %x\n", finddata.dwFileAttributes);
176 ok(finddata.cFileName[0] == 0, "unexpected filename '%s'\n", finddata.cFileName);
177
178 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
179 &IID_IShellLinkW, (LPVOID*)&slW);
180 ok(r == S_OK, "CoCreateInstance failed (0x%08x)\n", r);
181 if (!slW /* Win9x */ || !pGetLongPathNameA /* NT4 */)
182 skip("SetPath with NULL parameter crashes on Win9x and some NT4\n");
183 else
184 {
185 IShellLinkW_Release(slW);
186 r = IShellLinkA_SetPath(sl, NULL);
187 ok(r==E_INVALIDARG ||
188 broken(r==S_OK), /* Some Win95 and NT4 */
189 "SetPath returned wrong error (0x%08x)\n", r);
190 }
191
192 r = IShellLinkA_SetPath(sl, "");
193 ok(r==S_OK, "SetPath failed (0x%08x)\n", r);
194
195 strcpy(buffer,"garbage");
196 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
197 ok(r == S_FALSE, "GetPath failed (0x%08x)\n", r);
198 ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
199
200 /* Win98 returns S_FALSE, but WinXP returns S_OK */
201 str="c:\\nonexistent\\file";
202 r = IShellLinkA_SetPath(sl, str);
203 ok(r==S_FALSE || r==S_OK, "SetPath failed (0x%08x)\n", r);
204
205 strcpy(buffer,"garbage");
206 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
207 ok(r == S_OK, "GetPath failed (0x%08x)\n", r);
208 ok(lstrcmpiA(buffer,str)==0, "GetPath returned '%s'\n", buffer);
209
210 strcpy(buffer,"garbage");
211 memset(&finddata, 0xaa, sizeof(finddata));
212 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH);
213 ok(r == S_OK, "GetPath failed (0x%08x)\n", r);
214 ok(lstrcmpiA(buffer,str)==0, "GetPath returned '%s'\n", buffer);
215 ok(finddata.dwFileAttributes == 0, "unexpected attributes %x\n", finddata.dwFileAttributes);
216 ok(lstrcmpiA(finddata.cFileName, "file") == 0, "unexpected filename '%s'\n", finddata.cFileName);
217
218 /* Get some real path to play with */
219 GetWindowsDirectoryA( mypath, sizeof(mypath)-12 );
220 strcat(mypath, "\\regedit.exe");
221
222 /* Test the interaction of SetPath and SetIDList */
223 tmp_pidl=NULL;
224 r = IShellLinkA_GetIDList(sl, &tmp_pidl);
225 ok(r == S_OK, "GetIDList failed (0x%08x)\n", r);
226 if (r == S_OK)
227 {
228 BOOL ret;
229
230 strcpy(buffer,"garbage");
231 ret = SHGetPathFromIDListA(tmp_pidl, buffer);
232 ok(ret, "SHGetPathFromIDListA failed\n");
233 if (ret)
234 ok(lstrcmpiA(buffer,str)==0, "GetIDList returned '%s'\n", buffer);
235 pILFree(tmp_pidl);
236 }
237
238 pidl=path_to_pidl(mypath);
239 ok(pidl!=NULL, "path_to_pidl returned a NULL pidl\n");
240
241 if (pidl)
242 {
243 LPITEMIDLIST second_pidl;
244
245 r = IShellLinkA_SetIDList(sl, pidl);
246 ok(r == S_OK, "SetIDList failed (0x%08x)\n", r);
247
248 tmp_pidl=NULL;
249 r = IShellLinkA_GetIDList(sl, &tmp_pidl);
250 ok(r == S_OK, "GetIDList failed (0x%08x)\n", r);
251 ok(tmp_pidl && pILIsEqual(pidl, tmp_pidl),
252 "GetIDList returned an incorrect pidl\n");
253
254 r = IShellLinkA_GetIDList(sl, &second_pidl);
255 ok(r == S_OK, "GetIDList failed (0x%08x)\n", r);
256 ok(second_pidl && pILIsEqual(pidl, second_pidl),
257 "GetIDList returned an incorrect pidl\n");
258 ok(second_pidl != tmp_pidl, "pidls are the same\n");
259
260 pILFree(second_pidl);
261 pILFree(tmp_pidl);
262 pILFree(pidl);
263
264 strcpy(buffer,"garbage");
265 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
266 ok(r == S_OK, "GetPath failed (0x%08x)\n", r);
267 ok(lstrcmpiA(buffer, mypath)==0, "GetPath returned '%s'\n", buffer);
268
269 strcpy(buffer,"garbage");
270 memset(&finddata, 0xaa, sizeof(finddata));
271 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH);
272 ok(r == S_OK, "GetPath failed (0x%08x)\n", r);
273 ok(lstrcmpiA(buffer, mypath)==0, "GetPath returned '%s'\n", buffer);
274 ok(finddata.dwFileAttributes != 0, "unexpected attributes %x\n", finddata.dwFileAttributes);
275 ok(lstrcmpiA(finddata.cFileName, "regedit.exe") == 0, "unexpected filename '%s'\n", finddata.cFileName);
276 }
277
278 if (pSHGetFolderLocation)
279 {
280 LPITEMIDLIST pidl_controls;
281
282 r = pSHGetFolderLocation(NULL, CSIDL_CONTROLS, NULL, 0, &pidl_controls);
283 ok(r == S_OK, "SHGetFolderLocation failed (0x%08x)\n", r);
284
285 r = IShellLinkA_SetIDList(sl, pidl_controls);
286 ok(r == S_OK, "SetIDList failed (0x%08x)\n", r);
287
288 strcpy(buffer,"garbage");
289 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
290 ok(r == S_FALSE, "GetPath failed (0x%08x)\n", r);
291 ok(buffer[0] == 0, "GetPath returned '%s'\n", buffer);
292
293 strcpy(buffer,"garbage");
294 memset(&finddata, 0xaa, sizeof(finddata));
295 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH);
296 ok(r == S_FALSE, "GetPath failed (0x%08x)\n", r);
297 ok(buffer[0] == 0, "GetPath returned '%s'\n", buffer);
298 ok(finddata.dwFileAttributes == 0, "unexpected attributes %x\n", finddata.dwFileAttributes);
299 ok(finddata.cFileName[0] == 0, "unexpected filename '%s'\n", finddata.cFileName);
300
301 pILFree(pidl_controls);
302 }
303
304 /* test path with quotes (IShellLinkA_SetPath returns S_FALSE on W2K and below and S_OK on XP and above */
305 r = IShellLinkA_SetPath(sl, "\"c:\\nonexistent\\file\"");
306 ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
307
308 strcpy(buffer,"garbage");
309 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
310 ok(r==S_OK, "GetPath failed (0x%08x)\n", r);
311 todo_wine ok(!strcmp(buffer, "C:\\nonexistent\\file") ||
312 broken(!strcmp(buffer, "C:\\\"c:\\nonexistent\\file\"")), /* NT4 */
313 "case doesn't match\n");
314
315 r = IShellLinkA_SetPath(sl, "\"c:\\foo");
316 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
317
318 r = IShellLinkA_SetPath(sl, "\"\"c:\\foo");
319 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
320
321 r = IShellLinkA_SetPath(sl, "c:\\foo\"");
322 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
323
324 r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\"");
325 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
326
327 r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\"\"");
328 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
329
330 /* Test Getting / Setting the arguments */
331 strcpy(buffer,"garbage");
332 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
333 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r);
334 ok(*buffer=='\0', "GetArguments returned '%s'\n", buffer);
335
336 str="param1 \"spaced param2\"";
337 r = IShellLinkA_SetArguments(sl, str);
338 ok(r == S_OK, "SetArguments failed (0x%08x)\n", r);
339
340 strcpy(buffer,"garbage");
341 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
342 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r);
343 ok(strcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
344
345 strcpy(buffer,"garbage");
346 r = IShellLinkA_SetArguments(sl, NULL);
347 ok(r == S_OK, "SetArguments failed (0x%08x)\n", r);
348 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
349 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r);
350 ok(!buffer[0] || strcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
351
352 strcpy(buffer,"garbage");
353 r = IShellLinkA_SetArguments(sl, "");
354 ok(r == S_OK, "SetArguments failed (0x%08x)\n", r);
355 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
356 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r);
357 ok(!buffer[0], "GetArguments returned '%s'\n", buffer);
358
359 /* Test Getting / Setting showcmd */
360 i=0xdeadbeef;
361 r = IShellLinkA_GetShowCmd(sl, &i);
362 ok(r == S_OK, "GetShowCmd failed (0x%08x)\n", r);
363 ok(i==SW_SHOWNORMAL, "GetShowCmd returned %d\n", i);
364
365 r = IShellLinkA_SetShowCmd(sl, SW_SHOWMAXIMIZED);
366 ok(r == S_OK, "SetShowCmd failed (0x%08x)\n", r);
367
368 i=0xdeadbeef;
369 r = IShellLinkA_GetShowCmd(sl, &i);
370 ok(r == S_OK, "GetShowCmd failed (0x%08x)\n", r);
371 ok(i==SW_SHOWMAXIMIZED, "GetShowCmd returned %d'\n", i);
372
373 /* Test Getting / Setting the icon */
374 i=0xdeadbeef;
375 strcpy(buffer,"garbage");
376 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
377 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
378 ok(*buffer=='\0', "GetIconLocation returned '%s'\n", buffer);
379 ok(i==0, "GetIconLocation returned %d\n", i);
380
381 str="c:\\nonexistent\\file";
382 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
383 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
384
385 i=0xdeadbeef;
386 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
387 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
388 ok(lstrcmpiA(buffer,str)==0, "GetIconLocation returned '%s'\n", buffer);
389 ok(i==0xbabecafe, "GetIconLocation returned %d'\n", i);
390
391 /* Test Getting / Setting the hot key */
392 w=0xbeef;
393 r = IShellLinkA_GetHotkey(sl, &w);
394 ok(r == S_OK, "GetHotkey failed (0x%08x)\n", r);
395 ok(w==0, "GetHotkey returned %d\n", w);
396
397 r = IShellLinkA_SetHotkey(sl, 0x5678);
398 ok(r == S_OK, "SetHotkey failed (0x%08x)\n", r);
399
400 w=0xbeef;
401 r = IShellLinkA_GetHotkey(sl, &w);
402 ok(r == S_OK, "GetHotkey failed (0x%08x)\n", r);
403 ok(w==0x5678, "GetHotkey returned %d'\n", w);
404
405 IShellLinkA_Release(sl);
406}
407
408
409/*
410 * Test saving and loading .lnk files
411 */
412
413#define lok ok_(__FILE__, line)
414#define check_lnk(a,b,c) check_lnk_(__LINE__, (a), (b), (c))
415
416void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails)
417{
418 HRESULT r;
419 IShellLinkA *sl;
420 IPersistFile *pf;
421
422 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
423 &IID_IShellLinkA, (LPVOID*)&sl);
424 lok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r);
425 if (r != S_OK)
426 return;
427
428 if (desc->description)
429 {
430 r = IShellLinkA_SetDescription(sl, desc->description);
431 lok(r == S_OK, "SetDescription failed (0x%08x)\n", r);
432 }
433 if (desc->workdir)
434 {
435 r = IShellLinkA_SetWorkingDirectory(sl, desc->workdir);
436 lok(r == S_OK, "SetWorkingDirectory failed (0x%08x)\n", r);
437 }
438 if (desc->path)
439 {
440 r = IShellLinkA_SetPath(sl, desc->path);
441 lok(SUCCEEDED(r), "SetPath failed (0x%08x)\n", r);
442 }
443 if (desc->pidl)
444 {
445 r = IShellLinkA_SetIDList(sl, desc->pidl);
446 lok(r == S_OK, "SetIDList failed (0x%08x)\n", r);
447 }
448 if (desc->arguments)
449 {
450 r = IShellLinkA_SetArguments(sl, desc->arguments);
451 lok(r == S_OK, "SetArguments failed (0x%08x)\n", r);
452 }
453 if (desc->showcmd)
454 {
455 r = IShellLinkA_SetShowCmd(sl, desc->showcmd);
456 lok(r == S_OK, "SetShowCmd failed (0x%08x)\n", r);
457 }
458 if (desc->icon)
459 {
460 r = IShellLinkA_SetIconLocation(sl, desc->icon, desc->icon_id);
461 lok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
462 }
463 if (desc->hotkey)
464 {
465 r = IShellLinkA_SetHotkey(sl, desc->hotkey);
466 lok(r == S_OK, "SetHotkey failed (0x%08x)\n", r);
467 }
468
469 r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (void**)&pf);
470 lok(r == S_OK, "no IID_IPersistFile (0x%08x)\n", r);
471 if (r == S_OK)
472 {
474
475 if (0)
476 {
477 /* crashes on XP */
478 IPersistFile_GetCurFile(pf, NULL);
479 }
480
481 /* test GetCurFile before ::Save */
482 str = (LPWSTR)0xdeadbeef;
483 r = IPersistFile_GetCurFile(pf, &str);
484 lok(r == S_FALSE ||
485 broken(r == S_OK), /* shell32 < 5.0 */
486 "got 0x%08x\n", r);
487 lok(str == NULL, "got %p\n", str);
488
489 r = IPersistFile_Save(pf, path, TRUE);
490 todo_wine_if (save_fails)
491 lok(r == S_OK, "save failed (0x%08x)\n", r);
492
493 /* test GetCurFile after ::Save */
494 r = IPersistFile_GetCurFile(pf, &str);
495 lok(r == S_OK, "got 0x%08x\n", r);
496 lok(str != NULL ||
497 broken(str == NULL), /* shell32 < 5.0 */
498 "Didn't expect NULL\n");
499 if (str != NULL)
500 {
502
503 lok(!winetest_strcmpW(path, str), "Expected %s, got %s\n",
505
507 IMalloc_Free(pmalloc, str);
508 }
509 else
510 win_skip("GetCurFile fails on shell32 < 5.0\n");
511
512 IPersistFile_Release(pf);
513 }
514
515 IShellLinkA_Release(sl);
516}
517
518static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo)
519{
520 HRESULT r;
521 IShellLinkA *sl;
522 IPersistFile *pf;
523 char buffer[INFOTIPSIZE];
525
526 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
527 &IID_IShellLinkA, (LPVOID*)&sl);
528 lok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r);
529 if (r != S_OK)
530 return;
531
532 r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
533 lok(r == S_OK, "no IID_IPersistFile (0x%08x)\n", r);
534 if (r != S_OK)
535 {
536 IShellLinkA_Release(sl);
537 return;
538 }
539
540 /* test GetCurFile before ::Load */
541 str = (LPWSTR)0xdeadbeef;
542 r = IPersistFile_GetCurFile(pf, &str);
543 lok(r == S_FALSE ||
544 broken(r == S_OK), /* shell32 < 5.0 */
545 "got 0x%08x\n", r);
546 lok(str == NULL, "got %p\n", str);
547
548 r = IPersistFile_Load(pf, path, STGM_READ);
549 lok(r == S_OK, "load failed (0x%08x)\n", r);
550
551 /* test GetCurFile after ::Save */
552 r = IPersistFile_GetCurFile(pf, &str);
553 lok(r == S_OK, "got 0x%08x\n", r);
554 lok(str != NULL ||
555 broken(str == NULL), /* shell32 < 5.0 */
556 "Didn't expect NULL\n");
557 if (str != NULL)
558 {
560
561 lok(!winetest_strcmpW(path, str), "Expected %s, got %s\n",
563
565 IMalloc_Free(pmalloc, str);
566 }
567 else
568 win_skip("GetCurFile fails on shell32 < 5.0\n");
569
570 IPersistFile_Release(pf);
571 if (r != S_OK)
572 {
573 IShellLinkA_Release(sl);
574 return;
575 }
576
577 if (desc->description)
578 {
579 strcpy(buffer,"garbage");
580 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
581 lok(r == S_OK, "GetDescription failed (0x%08x)\n", r);
582 todo_wine_if ((todo & 0x1) != 0)
583 lok(strcmp(buffer, desc->description)==0, "GetDescription returned '%s' instead of '%s'\n",
584 buffer, desc->description);
585 }
586 if (desc->workdir)
587 {
588 strcpy(buffer,"garbage");
589 r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer));
590 lok(r == S_OK, "GetWorkingDirectory failed (0x%08x)\n", r);
591 todo_wine_if ((todo & 0x2) != 0)
592 lok(lstrcmpiA(buffer, desc->workdir)==0, "GetWorkingDirectory returned '%s' instead of '%s'\n",
593 buffer, desc->workdir);
594 }
595 if (desc->path)
596 {
597 strcpy(buffer,"garbage");
598 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
599 lok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r);
600 todo_wine_if ((todo & 0x4) != 0)
601 lok(lstrcmpiA(buffer, desc->path)==0, "GetPath returned '%s' instead of '%s'\n",
602 buffer, desc->path);
603 }
604 if (desc->pidl)
605 {
606 LPITEMIDLIST pidl=NULL;
607 r = IShellLinkA_GetIDList(sl, &pidl);
608 lok(r == S_OK, "GetIDList failed (0x%08x)\n", r);
609 todo_wine_if ((todo & 0x8) != 0)
610 lok(pILIsEqual(pidl, desc->pidl), "GetIDList returned an incorrect pidl\n");
611 }
612 if (desc->showcmd)
613 {
614 int i=0xdeadbeef;
615 r = IShellLinkA_GetShowCmd(sl, &i);
616 lok(r == S_OK, "GetShowCmd failed (0x%08x)\n", r);
617 todo_wine_if ((todo & 0x10) != 0)
618 lok(i==desc->showcmd, "GetShowCmd returned 0x%0x instead of 0x%0x\n",
619 i, desc->showcmd);
620 }
621 if (desc->icon)
622 {
623 int i=0xdeadbeef;
624 strcpy(buffer,"garbage");
625 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
626 lok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
627 todo_wine_if ((todo & 0x20) != 0) {
628 lok(lstrcmpiA(buffer, desc->icon)==0, "GetIconLocation returned '%s' instead of '%s'\n",
629 buffer, desc->icon);
630 lok(i==desc->icon_id, "GetIconLocation returned 0x%0x instead of 0x%0x\n",
631 i, desc->icon_id);
632 }
633 }
634 if (desc->hotkey)
635 {
636 WORD i=0xbeef;
637 r = IShellLinkA_GetHotkey(sl, &i);
638 lok(r == S_OK, "GetHotkey failed (0x%08x)\n", r);
639 todo_wine_if ((todo & 0x40) != 0)
640 lok(i==desc->hotkey, "GetHotkey returned 0x%04x instead of 0x%04x\n",
641 i, desc->hotkey);
642 }
643
644 IShellLinkA_Release(sl);
645}
646
647static void test_load_save(void)
648{
649 WCHAR lnkfile[MAX_PATH];
650 char lnkfileA[MAX_PATH];
651 static const char lnkfileA_name[] = "\\test.lnk";
652
654 char mypath[MAX_PATH];
655 char mydir[MAX_PATH];
656 char realpath[MAX_PATH];
657 char* p;
658 HANDLE hf;
659 DWORD r;
660
661 if (!pGetLongPathNameA)
662 {
663 win_skip("GetLongPathNameA is not available\n");
664 return;
665 }
666
667 /* Don't used a fixed path for the test.lnk file */
668 GetTempPathA(MAX_PATH, lnkfileA);
669 lstrcatA(lnkfileA, lnkfileA_name);
670 MultiByteToWideChar(CP_ACP, 0, lnkfileA, -1, lnkfile, MAX_PATH);
671
672 /* Save an empty .lnk file */
673 memset(&desc, 0, sizeof(desc));
674 create_lnk(lnkfile, &desc, 0);
675
676 /* It should come back as a bunch of empty strings */
677 desc.description="";
678 desc.workdir="";
679 desc.path="";
680 desc.arguments="";
681 desc.icon="";
682 check_lnk(lnkfile, &desc, 0x0);
683
684 /* Point a .lnk file to nonexistent files */
685 desc.description="";
686 desc.workdir="c:\\Nonexitent\\work\\directory";
687 desc.path="c:\\nonexistent\\path";
688 desc.pidl=NULL;
689 desc.arguments="";
690 desc.showcmd=0;
691 desc.icon="c:\\nonexistent\\icon\\file";
692 desc.icon_id=1234;
693 desc.hotkey=0;
694 create_lnk(lnkfile, &desc, 0);
695 check_lnk(lnkfile, &desc, 0x0);
696
698 ok(r<sizeof(mypath), "GetModuleFileName failed (%d)\n", r);
699 strcpy(mydir, mypath);
700 p=strrchr(mydir, '\\');
701 if (p)
702 *p='\0';
703
704 /* IShellLink returns path in long form */
705 if (!pGetLongPathNameA(mypath, realpath, MAX_PATH)) strcpy( realpath, mypath );
706
707 /* Overwrite the existing lnk file and point it to existing files */
708 desc.description="test 2";
709 desc.workdir=mydir;
710 desc.path=realpath;
711 desc.pidl=NULL;
712 desc.arguments="/option1 /option2 \"Some string\"";
713 desc.showcmd=SW_SHOWNORMAL;
714 desc.icon=mypath;
715 desc.icon_id=0;
716 desc.hotkey=0x1234;
717 create_lnk(lnkfile, &desc, 0);
718 check_lnk(lnkfile, &desc, 0x0);
719
720 /* Test omitting .exe from an absolute path */
721 p=strrchr(realpath, '.');
722 if (p)
723 *p='\0';
724
725 desc.description="absolute path without .exe";
726 desc.workdir=mydir;
727 desc.path=realpath;
728 desc.pidl=NULL;
729 desc.arguments="/option1 /option2 \"Some string\"";
730 desc.showcmd=SW_SHOWNORMAL;
731 desc.icon=mypath;
732 desc.icon_id=0;
733 desc.hotkey=0x1234;
734 create_lnk(lnkfile, &desc, 0);
735 strcat(realpath, ".exe");
736 check_lnk(lnkfile, &desc, 0x4);
737
738 /* Overwrite the existing lnk file and test link to a command on the path */
739 desc.description="command on path";
740 desc.workdir=mypath;
741 desc.path="rundll32.exe";
742 desc.pidl=NULL;
743 desc.arguments="/option1 /option2 \"Some string\"";
744 desc.showcmd=SW_SHOWNORMAL;
745 desc.icon=mypath;
746 desc.icon_id=0;
747 desc.hotkey=0x1234;
748 create_lnk(lnkfile, &desc, 0);
749 /* Check that link is created to proper location */
750 SearchPathA( NULL, desc.path, NULL, MAX_PATH, realpath, NULL);
751 desc.path=realpath;
752 check_lnk(lnkfile, &desc, 0x0);
753
754 /* Test omitting .exe from a command on the path */
755 desc.description="command on path without .exe";
756 desc.workdir=mypath;
757 desc.path="rundll32";
758 desc.pidl=NULL;
759 desc.arguments="/option1 /option2 \"Some string\"";
760 desc.showcmd=SW_SHOWNORMAL;
761 desc.icon=mypath;
762 desc.icon_id=0;
763 desc.hotkey=0x1234;
764 create_lnk(lnkfile, &desc, 0);
765 /* Check that link is created to proper location */
766 SearchPathA( NULL, "rundll32", NULL, MAX_PATH, realpath, NULL);
767 desc.path=realpath;
768 check_lnk(lnkfile, &desc, 0x4);
769
770 /* Create a temporary non-executable file */
771 r=GetTempPathA(sizeof(mypath), mypath);
772 ok(r<sizeof(mypath), "GetTempPath failed (%d), err %d\n", r, GetLastError());
773 r=pGetLongPathNameA(mypath, mydir, sizeof(mydir));
774 ok(r<sizeof(mydir), "GetLongPathName failed (%d), err %d\n", r, GetLastError());
775 p=strrchr(mydir, '\\');
776 if (p)
777 *p='\0';
778
779 strcpy(mypath, mydir);
780 strcat(mypath, "\\test.txt");
783 CloseHandle(hf);
784
785 /* Overwrite the existing lnk file and test link to an existing non-executable file */
786 desc.description="non-executable file";
787 desc.workdir=mydir;
788 desc.path=mypath;
789 desc.pidl=NULL;
790 desc.arguments="";
791 desc.showcmd=SW_SHOWNORMAL;
792 desc.icon=mypath;
793 desc.icon_id=0;
794 desc.hotkey=0x1234;
795 create_lnk(lnkfile, &desc, 0);
796 check_lnk(lnkfile, &desc, 0x0);
797
798 r=pGetShortPathNameA(mydir, mypath, sizeof(mypath));
799 ok(r<sizeof(mypath), "GetShortPathName failed (%d), err %d\n", r, GetLastError());
800
801 strcpy(realpath, mypath);
802 strcat(realpath, "\\test.txt");
803 strcat(mypath, "\\\\test.txt");
804
805 /* Overwrite the existing lnk file and test link to a short path with double backslashes */
806 desc.description="non-executable file";
807 desc.workdir=mydir;
808 desc.path=mypath;
809 desc.pidl=NULL;
810 desc.arguments="";
811 desc.showcmd=SW_SHOWNORMAL;
812 desc.icon=mypath;
813 desc.icon_id=0;
814 desc.hotkey=0x1234;
815 create_lnk(lnkfile, &desc, 0);
816 desc.path=realpath;
817 check_lnk(lnkfile, &desc, 0x0);
818
820 ok(r, "failed to delete file %s (%d)\n", mypath, GetLastError());
821
822 /* Create a temporary .bat file */
823 strcpy(mypath, mydir);
824 strcat(mypath, "\\test.bat");
827 CloseHandle(hf);
828
829 strcpy(realpath, mypath);
830
831 p=strrchr(mypath, '.');
832 if (p)
833 *p='\0';
834
835 /* Try linking to the .bat file without the extension */
836 desc.description="batch file";
837 desc.workdir=mydir;
838 desc.path=mypath;
839 desc.pidl=NULL;
840 desc.arguments="";
841 desc.showcmd=SW_SHOWNORMAL;
842 desc.icon=mypath;
843 desc.icon_id=0;
844 desc.hotkey=0x1234;
845 create_lnk(lnkfile, &desc, 0);
846 desc.path = realpath;
847 check_lnk(lnkfile, &desc, 0x4);
848
849 r = DeleteFileA(realpath);
850 ok(r, "failed to delete file %s (%d)\n", realpath, GetLastError());
851
852 /* FIXME: Also test saving a .lnk pointing to a pidl that cannot be
853 * represented as a path.
854 */
855
856 /* DeleteFileW is not implemented on Win9x */
857 r=DeleteFileA(lnkfileA);
858 ok(r, "failed to delete link '%s' (%d)\n", lnkfileA, GetLastError());
859}
860
861static void test_datalink(void)
862{
863 static const WCHAR lnk[] = {
864 ':',':','{','9','d','b','1','1','8','6','e','-','4','0','d','f','-','1',
865 '1','d','1','-','a','a','8','c','-','0','0','c','0','4','f','b','6','7',
866 '8','6','3','}',':','2','6',',','!','!','g','x','s','f','(','N','g',']',
867 'q','F','`','H','{','L','s','A','C','C','E','S','S','F','i','l','e','s',
868 '>','p','l','T',']','j','I','{','j','f','(','=','1','&','L','[','-','8',
869 '1','-',']',':',':',0 };
870 static const WCHAR comp[] = {
871 '2','6',',','!','!','g','x','s','f','(','N','g',']','q','F','`','H','{',
872 'L','s','A','C','C','E','S','S','F','i','l','e','s','>','p','l','T',']',
873 'j','I','{','j','f','(','=','1','&','L','[','-','8','1','-',']',0 };
875 IShellLinkW *sl = NULL;
876 HRESULT r;
877 DWORD flags = 0;
878 EXP_DARWIN_LINK *dar;
879
880 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
881 &IID_IShellLinkW, (LPVOID*)&sl );
882 ok( r == S_OK ||
883 broken(r == E_NOINTERFACE), /* Win9x */
884 "CoCreateInstance failed (0x%08x)\n", r);
885 if (!sl)
886 {
887 win_skip("no shelllink\n");
888 return;
889 }
890
891 r = IShellLinkW_QueryInterface( sl, &_IID_IShellLinkDataList, (LPVOID*) &dl );
892 ok( r == S_OK ||
893 broken(r == E_NOINTERFACE), /* NT4 */
894 "IShellLinkW_QueryInterface failed (0x%08x)\n", r);
895
896 if (!dl)
897 {
898 win_skip("no datalink interface\n");
899 IShellLinkW_Release( sl );
900 return;
901 }
902
903 flags = 0;
904 r = IShellLinkDataList_GetFlags( dl, &flags );
905 ok( r == S_OK, "GetFlags failed\n");
906 ok( flags == 0, "GetFlags returned wrong flags\n");
907
908 dar = (void*)-1;
909 r = IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar );
910 ok( r == E_FAIL, "CopyDataBlock failed\n");
911 ok( dar == NULL, "should be null\n");
912
913 if (!pGetLongPathNameA /* NT4 */)
914 skip("SetPath with NULL parameter crashes on NT4\n");
915 else
916 {
917 r = IShellLinkW_SetPath(sl, NULL);
918 ok(r == E_INVALIDARG, "SetPath returned wrong error (0x%08x)\n", r);
919 }
920
921 r = IShellLinkW_SetPath(sl, lnk);
922 ok(r == S_OK, "SetPath failed\n");
923
924if (0)
925{
926 /* the following crashes */
927 IShellLinkDataList_GetFlags( dl, NULL );
928}
929
930 flags = 0;
931 r = IShellLinkDataList_GetFlags( dl, &flags );
932 ok( r == S_OK, "GetFlags failed\n");
933 /* SLDF_HAS_LOGO3ID is no longer supported on Vista+, filter it out */
935 "GetFlags returned wrong flags\n");
936
937 dar = NULL;
938 r = IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar );
939 ok( r == S_OK, "CopyDataBlock failed\n");
940
941 ok( dar && ((DATABLOCK_HEADER*)dar)->dwSignature == EXP_DARWIN_ID_SIG, "signature wrong\n");
942 ok( dar && 0==lstrcmpW(dar->szwDarwinID, comp ), "signature wrong\n");
943
944 LocalFree( dar );
945
946 IShellLinkDataList_Release( dl );
947 IShellLinkW_Release( sl );
948}
949
950static void test_shdefextracticon(void)
951{
952 HICON hiconlarge=NULL, hiconsmall=NULL;
953 HRESULT res;
954
955 if (!pSHDefExtractIconA)
956 {
957 win_skip("SHDefExtractIconA is unavailable\n");
958 return;
959 }
960
961 res = pSHDefExtractIconA("shell32.dll", 0, 0, &hiconlarge, &hiconsmall, MAKELONG(16,24));
962 ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res);
963 ok(hiconlarge != NULL, "got null hiconlarge\n");
964 ok(hiconsmall != NULL, "got null hiconsmall\n");
965 DestroyIcon(hiconlarge);
966 DestroyIcon(hiconsmall);
967
968 hiconsmall = NULL;
969 res = pSHDefExtractIconA("shell32.dll", 0, 0, NULL, &hiconsmall, MAKELONG(16,24));
970 ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res);
971 ok(hiconsmall != NULL, "got null hiconsmall\n");
972 DestroyIcon(hiconsmall);
973
974 res = pSHDefExtractIconA("shell32.dll", 0, 0, NULL, NULL, MAKELONG(16,24));
975 ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res);
976}
977
978static void test_GetIconLocation(void)
979{
980 IShellLinkW *slW;
981 IShellLinkA *sl;
982 const char *str;
984 int i;
985 HRESULT r;
986 LPITEMIDLIST pidl;
987
988 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
989 &IID_IShellLinkA, (LPVOID*)&sl);
990 ok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r);
991 if(r != S_OK)
992 return;
993
994 i = 0xdeadbeef;
995 strcpy(buffer, "garbage");
996 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
997 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
998 ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer);
999 ok(i == 0, "GetIconLocation returned %d\n", i);
1000
1001 str = "c:\\some\\path";
1002 r = IShellLinkA_SetPath(sl, str);
1003 ok(r == S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
1004
1005 i = 0xdeadbeef;
1006 strcpy(buffer, "garbage");
1007 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
1008 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
1009 ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer);
1010 ok(i == 0, "GetIconLocation returned %d\n", i);
1011
1012 GetWindowsDirectoryA(mypath, sizeof(mypath) - 12);
1013 strcat(mypath, "\\regedit.exe");
1014 pidl = path_to_pidl(mypath);
1015 r = IShellLinkA_SetIDList(sl, pidl);
1016 ok(r == S_OK, "SetPath failed (0x%08x)\n", r);
1017 pILFree(pidl);
1018
1019 i = 0xdeadbeef;
1020 strcpy(buffer, "garbage");
1021 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
1022 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
1023 ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer);
1024 ok(i == 0, "GetIconLocation returned %d\n", i);
1025
1026 str = "c:\\nonexistent\\file";
1027 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
1028 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
1029
1030 i = 0xdeadbeef;
1031 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
1032 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
1033 ok(lstrcmpiA(buffer,str) == 0, "GetIconLocation returned '%s'\n", buffer);
1034 ok(i == 0xbabecafe, "GetIconLocation returned %#x.\n", i);
1035
1036 r = IShellLinkA_SetIconLocation(sl, NULL, 0xcafefe);
1037 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
1038
1039 i = 0xdeadbeef;
1040 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
1041 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
1042 ok(!*buffer, "GetIconLocation returned '%s'\n", buffer);
1043 ok(i == 0xcafefe, "GetIconLocation returned %#x.\n", i);
1044
1045 r = IShellLinkA_QueryInterface(sl, &IID_IShellLinkW, (void **)&slW);
1046 ok(SUCCEEDED(r), "Failed to get IShellLinkW, hr %#x.\n", r);
1047
1048 str = "c:\\nonexistent\\file";
1049 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
1050 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
1051
1052 r = IShellLinkA_SetIconLocation(sl, NULL, 0xcafefe);
1053 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
1054
1055 i = 0xdeadbeef;
1056 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
1057 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
1058 ok(!*buffer, "GetIconLocation returned '%s'\n", buffer);
1059 ok(i == 0xcafefe, "GetIconLocation returned %#x.\n", i);
1060
1061 IShellLinkW_Release(slW);
1062 IShellLinkA_Release(sl);
1063}
1064
1066{
1067 BYTE buffer[sizeof(SHSTOCKICONINFO) + 16];
1069 HRESULT hr;
1070 INT i;
1071
1072 /* not present before vista */
1073 if (!pSHGetStockIconInfo)
1074 {
1075 win_skip("SHGetStockIconInfo not available\n");
1076 return;
1077 }
1078
1079 /* negative values are handled */
1080 memset(buffer, '#', sizeof(buffer));
1081 sii->cbSize = sizeof(SHSTOCKICONINFO);
1082 hr = pSHGetStockIconInfo(SIID_INVALID, SHGSI_ICONLOCATION, sii);
1083 ok(hr == E_INVALIDARG, "-1: got 0x%x (expected E_INVALIDARG)\n", hr);
1084
1085 /* max. id for vista is 140 (no definition exists for this value) */
1086 for (i = SIID_DOCNOASSOC; i <= SIID_CLUSTEREDDRIVE; i++)
1087 {
1088 memset(buffer, '#', sizeof(buffer));
1089 sii->cbSize = sizeof(SHSTOCKICONINFO);
1090 hr = pSHGetStockIconInfo(i, SHGSI_ICONLOCATION, sii);
1091
1092 ok(hr == S_OK,
1093 "%3d: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x (expected S_OK)\n",
1094 i, hr, sii->iSysImageIndex, sii->iIcon);
1095
1096 if ((hr == S_OK) && (winetest_debug > 1))
1097 trace("%3d: got iSysImageIndex %3d, iIcon %3d and %s\n", i, sii->iSysImageIndex,
1098 sii->iIcon, wine_dbgstr_w(sii->szPath));
1099 }
1100
1101 /* test invalid icons indices that are invalid for all platforms */
1102 for (i = SIID_MAX_ICONS; i < (SIID_MAX_ICONS + 25) ; i++)
1103 {
1104 memset(buffer, '#', sizeof(buffer));
1105 sii->cbSize = sizeof(SHSTOCKICONINFO);
1106 hr = pSHGetStockIconInfo(i, SHGSI_ICONLOCATION, sii);
1107 ok(hr == E_INVALIDARG, "%3d: got 0x%x (expected E_INVALIDARG)\n", i, hr);
1108 todo_wine {
1109 ok(sii->iSysImageIndex == -1, "%d: got iSysImageIndex %d\n", i, sii->iSysImageIndex);
1110 ok(sii->iIcon == -1, "%d: got iIcon %d\n", i, sii->iIcon);
1111 }
1112 }
1113
1114 /* test more returned SHSTOCKICONINFO elements without extra flags */
1115 memset(buffer, '#', sizeof(buffer));
1116 sii->cbSize = sizeof(SHSTOCKICONINFO);
1117 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii);
1118 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1119 ok(!sii->hIcon, "got %p (expected NULL)\n", sii->hIcon);
1120 ok(sii->iSysImageIndex == -1, "got %d (expected -1)\n", sii->iSysImageIndex);
1121
1122 /* the exact size is required of the struct */
1123 memset(buffer, '#', sizeof(buffer));
1124 sii->cbSize = sizeof(SHSTOCKICONINFO) + 2;
1125 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii);
1126 ok(hr == E_INVALIDARG, "+2: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon);
1127
1128 memset(buffer, '#', sizeof(buffer));
1129 sii->cbSize = sizeof(SHSTOCKICONINFO) + 1;
1130 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii);
1131 ok(hr == E_INVALIDARG, "+1: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon);
1132
1133 memset(buffer, '#', sizeof(buffer));
1134 sii->cbSize = sizeof(SHSTOCKICONINFO) - 1;
1135 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii);
1136 ok(hr == E_INVALIDARG, "-1: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon);
1137
1138 memset(buffer, '#', sizeof(buffer));
1139 sii->cbSize = sizeof(SHSTOCKICONINFO) - 2;
1140 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii);
1141 ok(hr == E_INVALIDARG, "-2: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon);
1142
1143 /* there is a NULL check for the struct */
1144 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, NULL);
1145 ok(hr == E_INVALIDARG, "NULL: got 0x%x\n", hr);
1146
1147 for(i = 0; i < 140; i++) /* highest on wvista, i > 140 gives E_INVALIDARG, win7 can go higher */
1148 {
1149 memset(buffer, 0, sizeof(buffer));
1150 sii->cbSize = sizeof(SHSTOCKICONINFO);
1151 hr = pSHGetStockIconInfo(i, SHGSI_ICON | SHGSI_SMALLICON, sii);
1152 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1153 ok(sii->hIcon != NULL, "got NULL, expected an icon handle\n");
1154 ok(sii->iIcon != 0, "got unexpected 0 for SIID %d\n", i); /* howto find out exact sii->iIcon value??? */
1155 ok(sii->iSysImageIndex == -1, "got %d (expected -1)\n", sii->iSysImageIndex);
1156 ok(DestroyIcon(sii->hIcon), "DestroyIcon failed\n");
1157 if (winetest_debug > 1)
1158 trace("%3d: got iSysImageIndex %3d, iIcon %3d and %s\n", i, sii->iSysImageIndex,
1159 sii->iIcon, wine_dbgstr_w(sii->szPath));
1160 }
1161}
1162
1163static void test_SHExtractIcons(void)
1164{
1165 static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0};
1166 static const WCHAR shell32W[] = {'s','h','e','l','l','3','2','.','d','l','l',0};
1167 static const WCHAR emptyW[] = {0};
1168 UINT ret, ret2;
1169 HICON icons[256];
1170 UINT ids[256], i;
1171
1172 if (!pSHExtractIconsW)
1173 {
1174 win_skip("SHExtractIconsW not available\n");
1175 return;
1176 }
1177
1178 ret = pSHExtractIconsW(emptyW, 0, 16, 16, icons, ids, 1, 0);
1179 ok(ret == ~0u, "got %u\n", ret);
1180
1181 ret = pSHExtractIconsW(notepadW, 0, 16, 16, NULL, NULL, 1, 0);
1182 ok(ret == 1 || broken(ret == 2) /* win2k */, "got %u\n", ret);
1183
1184 icons[0] = (HICON)0xdeadbeef;
1185 ret = pSHExtractIconsW(notepadW, 0, 16, 16, icons, NULL, 1, 0);
1186 ok(ret == 1, "got %u\n", ret);
1187 ok(icons[0] != (HICON)0xdeadbeef, "icon not set\n");
1188 DestroyIcon(icons[0]);
1189
1190 icons[0] = (HICON)0xdeadbeef;
1191 ids[0] = 0xdeadbeef;
1192 ret = pSHExtractIconsW(notepadW, 0, 16, 16, icons, ids, 1, 0);
1193 ok(ret == 1, "got %u\n", ret);
1194 ok(icons[0] != (HICON)0xdeadbeef, "icon not set\n");
1195 ok(ids[0] != 0xdeadbeef, "id not set\n");
1196 DestroyIcon(icons[0]);
1197
1198 ret = pSHExtractIconsW(shell32W, 0, 16, 16, NULL, NULL, 0, 0);
1199 ret2 = pSHExtractIconsW(shell32W, 4, MAKELONG(32,16), MAKELONG(32,16), NULL, NULL, 256, 0);
1200 ok(ret && ret == ret2,
1201 "icon count should be independent of requested icon sizes and base icon index\n");
1202
1203 ret = pSHExtractIconsW(shell32W, 0, 16, 16, icons, ids, 0, 0);
1204 ok(ret == ~0u || !ret /* < vista */, "got %u\n", ret);
1205
1206 ret = pSHExtractIconsW(shell32W, 0, 16, 16, icons, ids, 3, 0);
1207 ok(ret == 3, "got %u\n", ret);
1208 for (i = 0; i < ret; i++) DestroyIcon(icons[i]);
1209
1210 /* count must be a multiple of two when getting two sizes */
1211 ret = pSHExtractIconsW(shell32W, 0, MAKELONG(16,32), MAKELONG(16,32), icons, ids, 3, 0);
1212 ok(!ret /* vista */ || ret == 4, "got %u\n", ret);
1213 for (i = 0; i < ret; i++) DestroyIcon(icons[i]);
1214
1215 ret = pSHExtractIconsW(shell32W, 0, MAKELONG(16,32), MAKELONG(16,32), icons, ids, 4, 0);
1216 ok(ret == 4, "got %u\n", ret);
1217 for (i = 0; i < ret; i++) DestroyIcon(icons[i]);
1218}
1219
1220static void test_propertystore(void)
1221{
1222 IShellLinkA *linkA;
1224 IPropertyStore *ps;
1225 HRESULT hr;
1226
1227 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1228 &IID_IShellLinkA, (void**)&linkA);
1229 ok(hr == S_OK, "got 0x%08x\n", hr);
1230
1231 hr = IShellLinkA_QueryInterface(linkA, &IID_IShellLinkW, (void**)&linkW);
1232 ok(hr == S_OK, "got 0x%08x\n", hr);
1233
1234 hr = IShellLinkA_QueryInterface(linkA, &IID_IPropertyStore, (void**)&ps);
1235 if (hr == S_OK) {
1236 IPropertyStoreCache *pscache;
1237
1238 IPropertyStore_Release(ps);
1239
1240 hr = IShellLinkW_QueryInterface(linkW, &IID_IPropertyStore, (void**)&ps);
1241 ok(hr == S_OK, "got 0x%08x\n", hr);
1242
1243 hr = IPropertyStore_QueryInterface(ps, &IID_IPropertyStoreCache, (void**)&pscache);
1244 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1245
1246 IPropertyStore_Release(ps);
1247 }
1248 else
1249 win_skip("IShellLink doesn't support IPropertyStore.\n");
1250
1251 IShellLinkA_Release(linkA);
1252 IShellLinkW_Release(linkW);
1253}
1254
1255static void test_ExtractIcon(void)
1256{
1257 static const WCHAR nameW[] = {'\\','e','x','t','r','a','c','t','i','c','o','n','_','t','e','s','t','.','t','x','t',0};
1258 static const WCHAR shell32W[] = {'s','h','e','l','l','3','2','.','d','l','l',0};
1259 WCHAR pathW[MAX_PATH];
1260 HICON hicon, hicon2;
1261 char path[MAX_PATH];
1262 HANDLE file;
1263 int r;
1264 ICONINFO info;
1265 BITMAP bm;
1266
1267 /* specified instance handle */
1268 hicon = ExtractIconA(GetModuleHandleA("shell32.dll"), NULL, 0);
1270 ok(hicon == NULL, "Got icon %p\n", hicon);
1271 hicon2 = ExtractIconA(GetModuleHandleA("shell32.dll"), "shell32.dll", -1);
1272 ok(hicon2 != NULL, "Got icon %p\n", hicon2);
1273
1274 /* existing index */
1275 hicon = ExtractIconA(NULL, "shell32.dll", 0);
1276 ok(hicon != NULL && HandleToLong(hicon) != -1, "Got icon %p\n", hicon);
1277 DestroyIcon(hicon);
1278
1279 /* returns number of resources */
1280 hicon = ExtractIconA(NULL, "shell32.dll", -1);
1281 ok(HandleToLong(hicon) > 1 && hicon == hicon2, "Got icon %p\n", hicon);
1282
1283 /* invalid index, valid dll name */
1284 hicon = ExtractIconA(NULL, "shell32.dll", 3000);
1285 ok(hicon == NULL, "Got icon %p\n", hicon);
1286
1287 /* Create a temporary non-executable file */
1288 GetTempPathA(sizeof(path), path);
1289 strcat(path, "\\extracticon_test.txt");
1291 ok(file != INVALID_HANDLE_VALUE, "Failed to create a test file\n");
1293
1294 hicon = ExtractIconA(NULL, path, 0);
1296 ok(hicon == NULL, "Got icon %p\n", hicon);
1297
1298 hicon = ExtractIconA(NULL, path, -1);
1299 ok(hicon == NULL, "Got icon %p\n", hicon);
1300
1301 hicon = ExtractIconA(NULL, path, 1);
1303 ok(hicon == NULL, "Got icon %p\n", hicon);
1304
1305 r = DeleteFileA(path);
1306 ok(r, "failed to delete file %s (%d)\n", path, GetLastError());
1307
1308 /* same for W variant */
1309if (0)
1310{
1311 /* specified instance handle, crashes on XP, 2k3 */
1312 hicon = ExtractIconW(GetModuleHandleA("shell32.dll"), NULL, 0);
1313 ok(hicon == NULL, "Got icon %p\n", hicon);
1314}
1315 hicon2 = ExtractIconW(GetModuleHandleA("shell32.dll"), shell32W, -1);
1316 ok(hicon2 != NULL, "Got icon %p\n", hicon2);
1317
1318 /* existing index */
1319 hicon = ExtractIconW(NULL, shell32W, 0);
1320 ok(hicon != NULL && HandleToLong(hicon) != -1, "Got icon %p\n", hicon);
1321 GetIconInfo(hicon, &info);
1322 GetObjectW(info.hbmColor, sizeof(bm), &bm);
1323 ok(bm.bmWidth == GetSystemMetrics(SM_CXICON), "got %d\n", bm.bmWidth);
1324 ok(bm.bmHeight == GetSystemMetrics(SM_CYICON), "got %d\n", bm.bmHeight);
1325 DestroyIcon(hicon);
1326
1327 /* returns number of resources */
1328 hicon = ExtractIconW(NULL, shell32W, -1);
1329 ok(HandleToLong(hicon) > 1 && hicon == hicon2, "Got icon %p\n", hicon);
1330
1331 /* invalid index, valid dll name */
1332 hicon = ExtractIconW(NULL, shell32W, 3000);
1333 ok(hicon == NULL, "Got icon %p\n", hicon);
1334
1335 /* Create a temporary non-executable file */
1336 GetTempPathW(ARRAY_SIZE(pathW), pathW);
1337 lstrcatW(pathW, nameW);
1339 ok(file != INVALID_HANDLE_VALUE, "Failed to create a test file\n");
1341
1342 hicon = ExtractIconW(NULL, pathW, 0);
1344 ok(hicon == NULL, "Got icon %p\n", hicon);
1345
1346 hicon = ExtractIconW(NULL, pathW, -1);
1347 ok(hicon == NULL, "Got icon %p\n", hicon);
1348
1349 hicon = ExtractIconW(NULL, pathW, 1);
1351 ok(hicon == NULL, "Got icon %p\n", hicon);
1352
1353 r = DeleteFileW(pathW);
1354 ok(r, "failed to delete file %s (%d)\n", path, GetLastError());
1355}
1356
1358{
1359 char pathA[MAX_PATH];
1360 HICON hicon;
1361 WORD index;
1362
1363 /* empty path */
1364 index = 0;
1365 *pathA = 0;
1367todo_wine {
1368 ok(hicon != NULL, "Got icon %p\n", hicon);
1369 ok(!*pathA, "Unexpected path %s\n", pathA);
1370 ok(index == 0, "Unexpected index %u\n", index);
1371}
1372 DestroyIcon(hicon);
1373
1374 /* by index */
1375 index = 0;
1376 strcpy(pathA, "shell32.dll");
1378 ok(hicon != NULL, "Got icon %p\n", hicon);
1379 ok(!strcmp(pathA, "shell32.dll"), "Unexpected path %s\n", pathA);
1380 ok(index == 0, "Unexpected index %u\n", index);
1381 DestroyIcon(hicon);
1382
1383 /* valid dll name, invalid index */
1384 index = 5000;
1385 strcpy(pathA, "user32.dll");
1388todo_wine {
1389 ok(hicon != NULL, "Got icon %p\n", hicon);
1390 ok(!!strstr(pathA, "shell32.dll"), "Unexpected path %s\n", pathA);
1391}
1392 ok(index != 5000, "Unexpected index %u\n", index);
1393 DestroyIcon(hicon);
1394
1395 /* associated icon */
1396 index = 0xcaca;
1397 strcpy(pathA, "dummy.exe");
1400todo_wine {
1401 ok(hicon != NULL, "Got icon %p\n", hicon);
1402 ok(!!strstr(pathA, "shell32.dll"), "Unexpected path %s\n", pathA);
1403}
1404 ok(index != 0xcaca, "Unexpected index %u\n", index);
1405 DestroyIcon(hicon);
1406}
1407
1408static int get_shell_icon_size(void)
1409{
1410 char buf[10];
1411 DWORD value = 32, size = sizeof(buf), type;
1412 HKEY key;
1413
1414 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", &key ))
1415 {
1416 if (!RegQueryValueExA( key, "Shell Icon Size", NULL, &type, (BYTE *)buf, &size ) && type == REG_SZ)
1417 value = atoi( buf );
1418 RegCloseKey( key );
1419 }
1420 return value;
1421}
1422
1423static void test_SHGetImageList(void)
1424{
1425 HRESULT hr;
1426 IImageList *list, *list2;
1427 BOOL ret;
1428 HIMAGELIST lg, sm;
1429 ULONG start_refs, refs;
1430 int i, width, height, expect;
1431 BOOL dpi_aware = pIsProcessDPIAware && pIsProcessDPIAware();
1432
1433 hr = SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&list );
1434 ok( hr == S_OK, "got %08x\n", hr );
1435 start_refs = IImageList_AddRef( list );
1436 IImageList_Release( list );
1437
1438 hr = SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&list2 );
1439 ok( hr == S_OK, "got %08x\n", hr );
1440 ok( list == list2, "lists differ\n" );
1441 refs = IImageList_AddRef( list );
1442 IImageList_Release( list );
1443 ok( refs == start_refs + 1, "got %d, start_refs %d\n", refs, start_refs );
1444 IImageList_Release( list2 );
1445
1446 hr = SHGetImageList( SHIL_SMALL, &IID_IImageList, (void **)&list2 );
1447 ok( hr == S_OK, "got %08x\n", hr );
1448
1449 ret = Shell_GetImageLists( &lg, &sm );
1450 ok( ret, "got %d\n", ret );
1451 ok( lg == (HIMAGELIST)list, "mismatch\n" );
1452 ok( sm == (HIMAGELIST)list2, "mismatch\n" );
1453
1454 /* Shell_GetImageLists doesn't take a reference */
1455 refs = IImageList_AddRef( list );
1456 IImageList_Release( list );
1457 ok( refs == start_refs, "got %d, start_refs %d\n", refs, start_refs );
1458
1459 IImageList_Release( list2 );
1460 IImageList_Release( list );
1461
1462 /* Test the icon sizes */
1463 for (i = 0; i <= SHIL_LAST; i++)
1464 {
1465 hr = SHGetImageList( i, &IID_IImageList, (void **)&list );
1466 ok( hr == S_OK || broken( i == SHIL_JUMBO && hr == E_INVALIDARG ), /* XP and 2003 */
1467 "%d: got %08x\n", i, hr );
1468 if (FAILED(hr)) continue;
1469 IImageList_GetIconSize( list, &width, &height );
1470 switch (i)
1471 {
1472 case SHIL_LARGE:
1473 if (dpi_aware) expect = GetSystemMetrics( SM_CXICON );
1474 else expect = get_shell_icon_size();
1475 break;
1476 case SHIL_SMALL:
1477 if (dpi_aware) expect = GetSystemMetrics( SM_CXICON ) / 2;
1479 break;
1480 case SHIL_EXTRALARGE:
1481 expect = (GetSystemMetrics( SM_CXICON ) * 3) / 2;
1482 break;
1483 case SHIL_SYSSMALL:
1485 break;
1486 case SHIL_JUMBO:
1487 expect = 256;
1488 break;
1489 }
1490 todo_wine_if(i == SHIL_SYSSMALL && dpi_aware && expect != GetSystemMetrics( SM_CXICON ) / 2)
1491 {
1492 ok( width == expect, "%d: got %d expect %d\n", i, width, expect );
1493 ok( height == expect, "%d: got %d expect %d\n", i, height, expect );
1494 }
1495 IImageList_Release( list );
1496 }
1497}
1498
1499START_TEST(shelllink)
1500{
1501 HRESULT r;
1502 HMODULE hmod = GetModuleHandleA("shell32.dll");
1503 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
1504 HMODULE huser32 = GetModuleHandleA("user32.dll");
1505
1506 pILFree = (void *)GetProcAddress(hmod, (LPSTR)155);
1507 pILIsEqual = (void *)GetProcAddress(hmod, (LPSTR)21);
1508 pSHILCreateFromPath = (void *)GetProcAddress(hmod, (LPSTR)28);
1509 pSHGetFolderLocation = (void *)GetProcAddress(hmod, "SHGetFolderLocation");
1510 pSHDefExtractIconA = (void *)GetProcAddress(hmod, "SHDefExtractIconA");
1511 pSHGetStockIconInfo = (void *)GetProcAddress(hmod, "SHGetStockIconInfo");
1512 pGetLongPathNameA = (void *)GetProcAddress(hkernel32, "GetLongPathNameA");
1513 pGetShortPathNameA = (void *)GetProcAddress(hkernel32, "GetShortPathNameA");
1514 pSHExtractIconsW = (void *)GetProcAddress(hmod, "SHExtractIconsW");
1515 pIsProcessDPIAware = (void *)GetProcAddress(huser32, "IsProcessDPIAware");
1516
1517 r = CoInitialize(NULL);
1518 ok(r == S_OK, "CoInitialize failed (0x%08x)\n", r);
1519 if (r != S_OK)
1520 return;
1521
1522 test_get_set();
1524 test_datalink();
1533
1535}
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
static const WCHAR nameW[]
Definition: main.c:49
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define HandleToLong(h)
Definition: basetsd.h:80
#define RegCloseKey(hKey)
Definition: registry.h:49
Definition: list.h:37
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define SIID_FOLDER
Definition: precomp.h:30
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
#define CloseHandle
Definition: compat.h:739
#define CP_ACP
Definition: compat.h:109
HANDLE HWND
Definition: compat.h:19
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define MultiByteToWideChar
Definition: compat.h:110
static const WCHAR linkW[]
Definition: string.c:50
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
DWORD WINAPI SearchPathA(IN LPCSTR lpPath OPTIONAL, IN LPCSTR lpFileName, IN LPCSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart OPTIONAL)
Definition: path.c:1123
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2080
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2337
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4243
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4224
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal)
Definition: shellole.c:285
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint * ids
Definition: glext.h:5907
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint pathA
Definition: glext.h:11719
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
BOOL WINAPI Shell_GetImageLists(HIMAGELIST *lpBigList, HIMAGELIST *lpSmallList)
Definition: iconcache.cpp:683
HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)
Definition: iconcache.cpp:908
static const WCHAR emptyW[]
Definition: navigate.c:40
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define wine_dbgstr_w
Definition: kernel32.h:34
#define REG_SZ
Definition: layer.c:22
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
#define CREATE_ALWAYS
Definition: disk.h:72
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:143
static HICON
Definition: imagelist.c:80
BOOL todo
Definition: filedlg.c:313
static const WCHAR desc[]
Definition: protectdata.c:36
static HINSTANCE hkernel32
Definition: process.c:66
static HMODULE huser32
Definition: profile.c:34
#define todo_wine_if(is_todo)
Definition: custom.c:86
#define todo_wine
Definition: custom.c:89
static void *__cdecl * pmalloc(unsigned int)
static LPOLESTR
Definition: stg_prop.c:27
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define GENERIC_WRITE
Definition: nt_native.h:90
#define STGM_READ
Definition: objbase.h:917
const GUID IID_IPersistFile
BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
Definition: pidl.c:1390
#define INFOTIPSIZE
Definition: commctrl.h:124
DWORD WINAPI GetVersion()
Definition: redirtest.c:5
#define list
Definition: rosglue.h:35
const WCHAR * str
_CRT_RESTORE_GCC_WARNINGS _CRT_DISABLE_GCC_WARNINGS _Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
int winetest_debug
#define win_skip
Definition: test.h:163
static int winetest_strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: test.h:97
#define memset(x, y, z)
Definition: compat.h:39
HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
Definition: shell32_main.c:864
HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex)
Definition: shell32_main.c:846
#define create_lnk(a, b, c)
Definition: shell32_test.h:37
struct _SHSTOCKICONINFO SHSTOCKICONINFO
#define SHIL_SYSSMALL
Definition: shellapi.h:188
#define SHIL_SMALL
Definition: shellapi.h:186
#define SHIL_JUMBO
Definition: shellapi.h:190
SHSTOCKICONID
Definition: shellapi.h:718
@ SIID_DOCNOASSOC
Definition: shellapi.h:720
@ SIID_CLUSTEREDDRIVE
Definition: shellapi.h:819
@ SIID_MAX_ICONS
Definition: shellapi.h:821
@ SIID_INVALID
Definition: shellapi.h:719
#define SHGSI_SMALLICON
Definition: shellapi.h:178
#define SHIL_LARGE
Definition: shellapi.h:185
#define SHGSI_ICON
Definition: shellapi.h:166
#define SHGSI_ICONLOCATION
Definition: shellapi.h:715
#define SHIL_LAST
Definition: shellapi.h:191
#define SHIL_EXTRALARGE
Definition: shellapi.h:187
HRESULT WINAPI SHGetImageList(int iImageList, REFIID riid, void **ppv)
Definition: shellord.c:2673
static PVOID hdll
Definition: shimdbg.c:126
HRESULT hr
Definition: shlfolder.c:183
#define EXP_DARWIN_ID_SIG
Definition: shlobj.h:2055
@ SLDF_HAS_DARWINID
Definition: shlobj.h:1958
#define CSIDL_CONTROLS
Definition: shlobj.h:2176
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
Definition: bl.h:1331
Definition: fci.c:127
Definition: copy.c:22
Definition: parser.c:49
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:94
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
CONST void * LPCVOID
Definition: windef.h:191
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define SW_SHOWNORMAL
Definition: winuser.h:773
#define SW_SHOWMAXIMIZED
Definition: winuser.h:776
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2097
DWORD WINAPI CharLowerBuffA(_Inout_updates_(cchLength) LPSTR lpsz, _In_ DWORD cchLength)
#define SM_CXSMICON
Definition: winuser.h:1015
#define SM_CYICON
Definition: winuser.h:976
#define SM_CXICON
Definition: winuser.h:975
int WINAPI GetSystemMetrics(_In_ int)
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2105
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193