ReactOS  0.4.14-dev-583-g2a1ba2c
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 
45 static void (WINAPI *pILFree)(LPITEMIDLIST);
46 static BOOL (WINAPI *pILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
47 static HRESULT (WINAPI *pSHILCreateFromPath)(LPCWSTR, LPITEMIDLIST *,DWORD*);
48 static HRESULT (WINAPI *pSHGetFolderLocation)(HWND,INT,HANDLE,DWORD,PIDLIST_ABSOLUTE*);
49 static HRESULT (WINAPI *pSHDefExtractIconA)(LPCSTR, int, UINT, HICON*, HICON*, UINT);
50 static HRESULT (WINAPI *pSHGetStockIconInfo)(SHSTOCKICONID, UINT, SHSTOCKICONINFO *);
51 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR, LPSTR, DWORD);
52 static DWORD (WINAPI *pGetShortPathNameA)(LPCSTR, LPSTR, DWORD);
53 static UINT (WINAPI *pSHExtractIconsW)(LPCWSTR, int, int, int, HICON *, UINT *, UINT, UINT);
54 static BOOL (WINAPI *pIsProcessDPIAware)(void);
55 
56 static const GUID _IID_IShellLinkDataList = {
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  */
66 static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID);
67 
68 static 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 
91  len=MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
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 
107 static 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 
416 void 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  {
473  LPOLESTR str;
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  {
501  IMalloc *pmalloc;
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 
518 static 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];
524  LPOLESTR str;
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  {
559  IMalloc *pmalloc;
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 
647 static 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 
819  r = DeleteFileA(mypath);
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 
861 static 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 };
874  IShellLinkDataList *dl = NULL;
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 
924 if (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 
950 static 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 
978 static 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 
1065 static void test_SHGetStockIconInfo(void)
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 
1163 static 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 
1220 static void test_propertystore(void)
1221 {
1222  IShellLinkA *linkA;
1223  IShellLinkW *linkW;
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 
1255 static 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);
1269 todo_wine
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");
1292  CloseHandle(file);
1293 
1294  hicon = ExtractIconA(NULL, path, 0);
1295 todo_wine
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);
1302 todo_wine
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 */
1309 if (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");
1340  CloseHandle(file);
1341 
1342  hicon = ExtractIconW(NULL, pathW, 0);
1343 todo_wine
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);
1350 todo_wine
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;
1366  hicon = ExtractAssociatedIconA(NULL, pathA, &index);
1367 todo_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");
1377  hicon = ExtractAssociatedIconA(NULL, pathA, &index);
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");
1386  hicon = ExtractAssociatedIconA(NULL, pathA, &index);
1388 todo_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");
1398  hicon = ExtractAssociatedIconA(NULL, pathA, &index);
1400 todo_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 
1408 static 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 
1423 static 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 
1499 START_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();
1523  test_load_save();
1524  test_datalink();
1530  test_ExtractIcon();
1533 
1534  CoUninitialize();
1535 }
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
#define SHIL_LARGE
Definition: shellapi.h:182
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3257
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:4023
GLint GLint GLsizei width
Definition: gl.h:1546
static HICON
Definition: imagelist.c:84
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
Definition: pidl.c:1264
#define E_NOINTERFACE
Definition: winerror.h:2364
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex)
Definition: shell32_main.c:860
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
static void *__cdecl * pmalloc(unsigned int)
HRESULT hr
Definition: shlfolder.c:183
GLint x0
Definition: linetemp.h:95
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define SHIL_JUMBO
Definition: shellapi.h:187
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2022
DWORD WINAPI CharLowerBuffA(_Inout_updates_(cchLength) LPSTR lpsz, _In_ DWORD cchLength)
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: atltest.h:87
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define SW_SHOWMAXIMIZED
Definition: winuser.h:767
#define CP_ACP
Definition: compat.h:99
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define HKEY_CURRENT_USER
Definition: winreg.h:11
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
BOOL todo
Definition: filedlg.c:313
static HINSTANCE hkernel32
Definition: process.c:66
#define SHGSI_ICON
Definition: shellapi.h:163
HANDLE HWND
Definition: compat.h:13
HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal)
Definition: shellole.c:290
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
char * LPSTR
Definition: xmlstorage.h:182
static LPOLESTR
Definition: stg_prop.c:27
#define E_FAIL
Definition: ddrawi.h:102
int winetest_debug
int32_t INT
Definition: typedefs.h:56
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2014
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:548
DWORD WINAPI GetVersion(VOID)
Definition: version.c:22
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
#define CSIDL_CONTROLS
Definition: shlobj.h:2006
HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
Definition: shell32_main.c:878
struct _test_info info[]
Definition: SetCursorPos.c:19
GLuint * ids
Definition: glext.h:5907
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
#define EXP_DARWIN_ID_SIG
Definition: shlobj.h:1885
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2079
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:1122
unsigned int BOOL
Definition: ntddk_ex.h:94
HRESULT WINAPI SHGetImageList(int iImageList, REFIID riid, void **ppv)
Definition: shellord.c:2013
static const WCHAR desc[]
Definition: protectdata.c:36
#define GENERIC_WRITE
Definition: nt_native.h:90
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
#define SM_CXICON
Definition: winuser.h:962
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
#define MAKELONG(a, b)
Definition: typedefs.h:248
smooth NULL
Definition: ftsmooth.c:416
#define SHIL_LAST
Definition: shellapi.h:188
static int winetest_strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: test.h:90
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
Definition: parser.c:48
HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)
Definition: iconcache.cpp:919
static HMODULE huser32
Definition: profile.c:34
GLuint index
Definition: glext.h:6031
const char * LPCSTR
Definition: xmlstorage.h:183
static const WCHAR nameW[]
Definition: main.c:46
#define STGM_READ
Definition: objbase.h:916
#define SHGSI_ICONLOCATION
Definition: shellapi.h:710
#define todo_wine_if(is_todo)
Definition: test.h:164
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
GLsizeiptr size
Definition: glext.h:5919
#define trace
Definition: atltest.h:70
SHSTOCKICONID
Definition: shellapi.h:712
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SHGSI_SMALLICON
Definition: shellapi.h:175
LONG refs
Definition: locator.c:1513
GLbitfield flags
Definition: glext.h:7161
#define SM_CXSMICON
Definition: winuser.h:1002
int ret
#define SM_CYICON
Definition: winuser.h:963
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define index(s, c)
Definition: various.h:29
#define todo_wine
Definition: test.h:163
HKEY key
Definition: reg.c:42
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
Definition: _list.h:228
GLsizei const GLfloat * value
Definition: glext.h:6069
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
#define broken(x)
Definition: _sntprintf.h:21
BOOL WINAPI Shell_GetImageLists(HIMAGELIST *lpBigList, HIMAGELIST *lpSmallList)
Definition: iconcache.cpp:706
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:141
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define S_OK
Definition: intsafe.h:59
#define CREATE_ALWAYS
Definition: disk.h:72
#define SW_SHOWNORMAL
Definition: winuser.h:764
static const WCHAR emptyW[]
Definition: navigate.c:40
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2053
#define create_lnk(a, b, c)
Definition: shell32_test.h:37
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
#define ARRAY_SIZE(a)
Definition: main.h:24
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define INFOTIPSIZE
Definition: commctrl.h:124
#define ok(value,...)
Definition: atltest.h:57
Definition: bl.h:1331
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2336
#define list
Definition: rosglue.h:35
#define expect(expected, got)
Definition: combo.c:36
unsigned int UINT
Definition: ndis.h:50
static PVOID hdll
Definition: shimdbg.c:126
#define MultiByteToWideChar
Definition: compat.h:100
struct _SHSTOCKICONINFO SHSTOCKICONINFO
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
#define CreateFileW
Definition: compat.h:408
#define skip(...)
Definition: atltest.h:64
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
CONST void * LPCVOID
Definition: windef.h:191
const GUID IID_IPersistFile
GLuint res
Definition: glext.h:9613
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
GLuint pathA
Definition: glext.h:11719
#define GetProcAddress(x, y)
Definition: compat.h:418
#define SHIL_SMALL
Definition: shellapi.h:183
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:407
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define SHIL_SYSSMALL
Definition: shellapi.h:185
#define memset(x, y, z)
Definition: compat.h:39
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
#define win_skip
Definition: test.h:150
static const WCHAR linkW[]
Definition: string.c:50
#define SUCCEEDED(hr)
Definition: intsafe.h:57
#define SHIL_EXTRALARGE
Definition: shellapi.h:184
Definition: path.c:41
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define HandleToLong(h)
Definition: basetsd.h:80
Definition: fci.c:126
#define REG_SZ
Definition: layer.c:22