2 * Unit tests for shelllinks
4 * Copyright 2004 Mike McCormack
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * This is a test program for the SHGet{Special}Folder{Path|Location} functions
20 * of shell32, that get either a filesytem path or a LPITEMIDLIST (shell
21 * namespace) path for a given folder (CSIDL value).
34 #include "wine/test.h"
36 #include "shell32_test.h"
38 static const WCHAR lnkfile
[]= { 'C',':','\\','t','e','s','t','.','l','n','k',0 };
39 static const WCHAR notafile
[]= { 'C',':','\\','n','o','n','e','x','i','s','t','e','n','t','\\','f','i','l','e',0 };
42 /* For some reason SHILCreateFromPath does not work on Win98 and
43 * SHSimpleIDListFromPathA does not work on NT4. But if we call both we
44 * get what we want on all platforms.
46 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathA
)(LPCSTR
)=NULL
;
48 static LPITEMIDLIST
path_to_pidl(const char* path
)
52 if (!pSHSimpleIDListFromPathA
)
54 HMODULE hdll
=LoadLibraryA("shell32.dll");
55 pSHSimpleIDListFromPathA
=(void*)GetProcAddress(hdll
, (char*)162);
56 if (!pSHSimpleIDListFromPathA
)
57 trace("SHSimpleIDListFromPathA not found in shell32.dll\n");
61 if (pSHSimpleIDListFromPathA
)
62 pidl
=pSHSimpleIDListFromPathA(path
);
70 len
=MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
71 pathW
=HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
72 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, len
);
74 r
=SHILCreateFromPath(pathW
, &pidl
, NULL
);
76 ok(SUCCEEDED(r
), "SHILCreateFromPath failed (0x%08lx)\n", r
);
78 HeapFree(GetProcessHeap(), 0, pathW
);
85 * Test manipulation of an IShellLink's properties.
88 static void test_get_set(void)
92 char mypath
[MAX_PATH
];
93 char buffer
[INFOTIPSIZE
];
94 LPITEMIDLIST pidl
, tmp_pidl
;
99 r
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
100 &IID_IShellLinkA
, (LPVOID
*)&sl
);
101 ok(SUCCEEDED(r
), "no IID_IShellLinkA (0x%08lx)\n", r
);
105 /* Test Getting / Setting the description */
106 strcpy(buffer
,"garbage");
107 r
= IShellLinkA_GetDescription(sl
, buffer
, sizeof(buffer
));
108 ok(SUCCEEDED(r
), "GetDescription failed (0x%08lx)\n", r
);
109 ok(*buffer
=='\0', "GetDescription returned '%s'\n", buffer
);
111 str
="Some description";
112 r
= IShellLinkA_SetDescription(sl
, str
);
113 ok(SUCCEEDED(r
), "SetDescription failed (0x%08lx)\n", r
);
115 strcpy(buffer
,"garbage");
116 r
= IShellLinkA_GetDescription(sl
, buffer
, sizeof(buffer
));
117 ok(SUCCEEDED(r
), "GetDescription failed (0x%08lx)\n", r
);
118 ok(lstrcmp(buffer
,str
)==0, "GetDescription returned '%s'\n", buffer
);
120 /* Test Getting / Setting the work directory */
121 strcpy(buffer
,"garbage");
122 r
= IShellLinkA_GetWorkingDirectory(sl
, buffer
, sizeof(buffer
));
123 ok(SUCCEEDED(r
), "GetWorkingDirectory failed (0x%08lx)\n", r
);
124 ok(*buffer
=='\0', "GetWorkingDirectory returned '%s'\n", buffer
);
126 str
="c:\\nonexistent\\directory";
127 r
= IShellLinkA_SetWorkingDirectory(sl
, str
);
128 ok(SUCCEEDED(r
), "SetWorkingDirectory failed (0x%08lx)\n", r
);
130 strcpy(buffer
,"garbage");
131 r
= IShellLinkA_GetWorkingDirectory(sl
, buffer
, sizeof(buffer
));
132 ok(SUCCEEDED(r
), "GetWorkingDirectory failed (0x%08lx)\n", r
);
133 ok(lstrcmpi(buffer
,str
)==0, "GetWorkingDirectory returned '%s'\n", buffer
);
135 /* Test Getting / Setting the work directory */
136 strcpy(buffer
,"garbage");
137 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
138 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
139 ok(*buffer
=='\0', "GetPath returned '%s'\n", buffer
);
141 r
= IShellLinkA_SetPath(sl
, "");
142 ok(r
==S_OK
, "SetPath failed (0x%08lx)\n", r
);
144 strcpy(buffer
,"garbage");
145 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
146 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
147 ok(*buffer
=='\0', "GetPath returned '%s'\n", buffer
);
149 str
="c:\\nonexistent\\file";
150 r
= IShellLinkA_SetPath(sl
, str
);
151 ok(r
==S_FALSE
, "SetPath failed (0x%08lx)\n", r
);
153 strcpy(buffer
,"garbage");
154 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
155 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
156 ok(lstrcmpi(buffer
,str
)==0, "GetPath returned '%s'\n", buffer
);
158 /* Get some a real path to play with */
159 r
=GetModuleFileName(NULL
, mypath
, sizeof(mypath
));
160 ok(r
>=0 && r
<sizeof(mypath
), "GetModuleFileName failed (%ld)\n", r
);
162 /* Test the interaction of SetPath and SetIDList */
164 r
= IShellLinkA_GetIDList(sl
, &tmp_pidl
);
165 ok(SUCCEEDED(r
), "GetIDList failed (0x%08lx)\n", r
);
168 strcpy(buffer
,"garbage");
169 r
=SHGetPathFromIDListA(tmp_pidl
, buffer
);
171 ok(r
, "SHGetPathFromIDListA failed\n");
174 ok(lstrcmpi(buffer
,str
)==0, "GetIDList returned '%s'\n", buffer
);
177 pidl
=path_to_pidl(mypath
);
179 ok(pidl
!=NULL
, "path_to_pidl returned a NULL pidl\n");
184 r
= IShellLinkA_SetIDList(sl
, pidl
);
185 ok(SUCCEEDED(r
), "SetIDList failed (0x%08lx)\n", r
);
188 r
= IShellLinkA_GetIDList(sl
, &tmp_pidl
);
189 ok(SUCCEEDED(r
), "GetIDList failed (0x%08lx)\n", r
);
190 ok(tmp_pidl
&& ILIsEqual(pidl
, tmp_pidl
),
191 "GetIDList returned an incorrect pidl\n");
193 /* tmp_pidl is owned by IShellLink so we don't free it */
196 strcpy(buffer
,"garbage");
197 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
198 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
199 ok(lstrcmpi(buffer
, mypath
)==0, "GetPath returned '%s'\n", buffer
);
202 /* Test Getting / Setting the arguments */
203 strcpy(buffer
,"garbage");
204 r
= IShellLinkA_GetArguments(sl
, buffer
, sizeof(buffer
));
205 ok(SUCCEEDED(r
), "GetArguments failed (0x%08lx)\n", r
);
206 ok(*buffer
=='\0', "GetArguments returned '%s'\n", buffer
);
208 str
="param1 \"spaced param2\"";
209 r
= IShellLinkA_SetArguments(sl
, str
);
210 ok(SUCCEEDED(r
), "SetArguments failed (0x%08lx)\n", r
);
212 strcpy(buffer
,"garbage");
213 r
= IShellLinkA_GetArguments(sl
, buffer
, sizeof(buffer
));
214 ok(SUCCEEDED(r
), "GetArguments failed (0x%08lx)\n", r
);
215 ok(lstrcmp(buffer
,str
)==0, "GetArguments returned '%s'\n", buffer
);
217 /* Test Getting / Setting showcmd */
219 r
= IShellLinkA_GetShowCmd(sl
, &i
);
220 ok(SUCCEEDED(r
), "GetShowCmd failed (0x%08lx)\n", r
);
221 ok(i
==SW_SHOWNORMAL
, "GetShowCmd returned %d\n", i
);
223 r
= IShellLinkA_SetShowCmd(sl
, SW_SHOWMAXIMIZED
);
224 ok(SUCCEEDED(r
), "SetShowCmd failed (0x%08lx)\n", r
);
227 r
= IShellLinkA_GetShowCmd(sl
, &i
);
228 ok(SUCCEEDED(r
), "GetShowCmd failed (0x%08lx)\n", r
);
229 ok(i
==SW_SHOWMAXIMIZED
, "GetShowCmd returned %d'\n", i
);
231 /* Test Getting / Setting the icon */
233 strcpy(buffer
,"garbage");
234 r
= IShellLinkA_GetIconLocation(sl
, buffer
, sizeof(buffer
), &i
);
236 ok(SUCCEEDED(r
), "GetIconLocation failed (0x%08lx)\n", r
);
238 ok(*buffer
=='\0', "GetIconLocation returned '%s'\n", buffer
);
239 ok(i
==0, "GetIconLocation returned %d\n", i
);
241 str
="c:\\nonexistent\\file";
242 r
= IShellLinkA_SetIconLocation(sl
, str
, 0xbabecafe);
243 ok(SUCCEEDED(r
), "SetIconLocation failed (0x%08lx)\n", r
);
246 r
= IShellLinkA_GetIconLocation(sl
, buffer
, sizeof(buffer
), &i
);
247 ok(SUCCEEDED(r
), "GetIconLocation failed (0x%08lx)\n", r
);
248 ok(lstrcmpi(buffer
,str
)==0, "GetArguments returned '%s'\n", buffer
);
249 ok(i
==0xbabecafe, "GetIconLocation returned %d'\n", i
);
251 /* Test Getting / Setting the hot key */
253 r
= IShellLinkA_GetHotkey(sl
, &w
);
254 ok(SUCCEEDED(r
), "GetHotkey failed (0x%08lx)\n", r
);
255 ok(w
==0, "GetHotkey returned %d\n", w
);
257 r
= IShellLinkA_SetHotkey(sl
, 0x5678);
258 ok(SUCCEEDED(r
), "SetHotkey failed (0x%08lx)\n", r
);
261 r
= IShellLinkA_GetHotkey(sl
, &w
);
262 ok(SUCCEEDED(r
), "GetHotkey failed (0x%08lx)\n", r
);
263 ok(w
==0x5678, "GetHotkey returned %d'\n", w
);
265 IShellLinkA_Release(sl
);
270 * Test saving and loading .lnk files
273 #define lok ok_(__FILE__, line)
274 #define check_lnk(a,b) check_lnk_(__LINE__, (a), (b))
276 void create_lnk_(int line
, const WCHAR
* path
, lnk_desc_t
* desc
, int save_fails
)
282 r
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
283 &IID_IShellLinkA
, (LPVOID
*)&sl
);
284 lok(SUCCEEDED(r
), "no IID_IShellLinkA (0x%08lx)\n", r
);
288 if (desc
->description
)
290 r
= IShellLinkA_SetDescription(sl
, desc
->description
);
291 lok(SUCCEEDED(r
), "SetDescription failed (0x%08lx)\n", r
);
295 r
= IShellLinkA_SetWorkingDirectory(sl
, desc
->workdir
);
296 lok(SUCCEEDED(r
), "SetWorkingDirectory failed (0x%08lx)\n", r
);
300 r
= IShellLinkA_SetPath(sl
, desc
->path
);
301 lok(SUCCEEDED(r
), "SetPath failed (0x%08lx)\n", r
);
305 r
= IShellLinkA_SetIDList(sl
, desc
->pidl
);
306 lok(SUCCEEDED(r
), "SetIDList failed (0x%08lx)\n", r
);
310 r
= IShellLinkA_SetArguments(sl
, desc
->arguments
);
311 lok(SUCCEEDED(r
), "SetArguments failed (0x%08lx)\n", r
);
315 r
= IShellLinkA_SetShowCmd(sl
, desc
->showcmd
);
316 lok(SUCCEEDED(r
), "SetShowCmd failed (0x%08lx)\n", r
);
320 r
= IShellLinkA_SetIconLocation(sl
, desc
->icon
, desc
->icon_id
);
321 lok(SUCCEEDED(r
), "SetIconLocation failed (0x%08lx)\n", r
);
325 r
= IShellLinkA_SetHotkey(sl
, desc
->hotkey
);
326 lok(SUCCEEDED(r
), "SetHotkey failed (0x%08lx)\n", r
);
329 r
= IShellLinkW_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
330 lok(SUCCEEDED(r
), "no IID_IPersistFile (0x%08lx)\n", r
);
333 r
= IPersistFile_Save(pf
, path
, TRUE
);
337 lok(SUCCEEDED(r
), "save failed (0x%08lx)\n", r
);
342 lok(SUCCEEDED(r
), "save failed (0x%08lx)\n", r
);
344 IPersistFile_Release(pf
);
347 IShellLinkA_Release(sl
);
350 static void check_lnk_(int line
, const WCHAR
* path
, lnk_desc_t
* desc
)
355 char buffer
[INFOTIPSIZE
];
357 r
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
358 &IID_IShellLinkA
, (LPVOID
*)&sl
);
359 lok(SUCCEEDED(r
), "no IID_IShellLinkA (0x%08lx)\n", r
);
363 r
= IShellLinkA_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
364 lok(SUCCEEDED(r
), "no IID_IPersistFile (0x%08lx)\n", r
);
367 IShellLinkA_Release(sl
);
371 r
= IPersistFile_Load(pf
, path
, STGM_READ
);
372 lok(SUCCEEDED(r
), "load failed (0x%08lx)\n", r
);
373 IPersistFile_Release(pf
);
376 IShellLinkA_Release(sl
);
380 if (desc
->description
)
382 strcpy(buffer
,"garbage");
383 r
= IShellLinkA_GetDescription(sl
, buffer
, sizeof(buffer
));
384 lok(SUCCEEDED(r
), "GetDescription failed (0x%08lx)\n", r
);
385 lok(lstrcmp(buffer
, desc
->description
)==0,
386 "GetDescription returned '%s' instead of '%s'\n",
387 buffer
, desc
->description
);
391 strcpy(buffer
,"garbage");
392 r
= IShellLinkA_GetWorkingDirectory(sl
, buffer
, sizeof(buffer
));
393 lok(SUCCEEDED(r
), "GetWorkingDirectory failed (0x%08lx)\n", r
);
394 lok(lstrcmpi(buffer
, desc
->workdir
)==0,
395 "GetWorkingDirectory returned '%s' instead of '%s'\n",
396 buffer
, desc
->workdir
);
400 strcpy(buffer
,"garbage");
401 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
402 lok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
403 lok(lstrcmpi(buffer
, desc
->path
)==0,
404 "GetPath returned '%s' instead of '%s'\n",
409 LPITEMIDLIST pidl
=NULL
;
410 r
= IShellLinkA_GetIDList(sl
, &pidl
);
411 lok(SUCCEEDED(r
), "GetIDList failed (0x%08lx)\n", r
);
412 lok(ILIsEqual(pidl
, desc
->pidl
),
413 "GetIDList returned an incorrect pidl\n");
418 r
= IShellLinkA_GetShowCmd(sl
, &i
);
419 lok(SUCCEEDED(r
), "GetShowCmd failed (0x%08lx)\n", r
);
420 lok(i
==desc
->showcmd
,
421 "GetShowCmd returned 0x%0x instead of 0x%0x\n",
427 strcpy(buffer
,"garbage");
428 r
= IShellLinkA_GetIconLocation(sl
, buffer
, sizeof(buffer
), &i
);
429 lok(SUCCEEDED(r
), "GetIconLocation failed (0x%08lx)\n", r
);
430 lok(lstrcmpi(buffer
, desc
->icon
)==0,
431 "GetIconLocation returned '%s' instead of '%s'\n",
433 lok(i
==desc
->icon_id
,
434 "GetIconLocation returned 0x%0x instead of 0x%0x\n",
440 r
= IShellLinkA_GetHotkey(sl
, &i
);
441 lok(SUCCEEDED(r
), "GetHotkey failed (0x%08lx)\n", r
);
443 "GetHotkey returned 0x%04x instead of 0x%04x\n",
447 IShellLinkA_Release(sl
);
450 static void test_load_save(void)
453 char mypath
[MAX_PATH
];
454 char mydir
[MAX_PATH
];
458 /* Save an empty .lnk file */
459 memset(&desc
, 0, sizeof(desc
));
460 create_lnk(lnkfile
, &desc
, 0);
462 /* It should come back as a bunch of empty strings */
468 check_lnk(lnkfile
, &desc
);
471 /* Point a .lnk file to nonexistent files */
473 desc
.workdir
="c:\\Nonexitent\\work\\directory";
474 desc
.path
="c:\\nonexistent\\path";
478 desc
.icon
="c:\\nonexistent\\icon\\file";
481 create_lnk(lnkfile
, &desc
, 0);
482 check_lnk(lnkfile
, &desc
);
484 r
=GetModuleFileName(NULL
, mypath
, sizeof(mypath
));
485 ok(r
>=0 && r
<sizeof(mypath
), "GetModuleFileName failed (%ld)\n", r
);
486 strcpy(mydir
, mypath
);
487 p
=strrchr(mydir
, '\\');
492 /* Overwrite the existing lnk file and point it to existing files */
493 desc
.description
="test 2";
497 desc
.arguments
="/option1 /option2 \"Some string\"";
498 desc
.showcmd
=SW_SHOWNORMAL
;
502 create_lnk(lnkfile
, &desc
, 0);
503 check_lnk(lnkfile
, &desc
);
505 /* FIXME: Also test saving a .lnk pointing to a pidl that cannot be
506 * represented as a path.
509 /* DeleteFileW is not implemented on Win9x */
510 r
=DeleteFileA("c:\\test.lnk");
511 ok(r
, "failed to delete link (%ld)\n", GetLastError());
514 START_TEST(shelllink
)
518 r
= CoInitialize(NULL
);
519 ok(SUCCEEDED(r
), "CoInitialize failed (0x%08lx)\n", r
);