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).
25 #define _WIN32_IE 0x0400
35 //#include "wine/shobjidl.h"
37 #include "wine/test.h"
39 #include "shell32_test.h"
41 extern BOOL WINAPI
ILIsEqual(LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
);
42 extern HRESULT WINAPI
SHILCreateFromPath(LPCWSTR path
, LPITEMIDLIST
* ppidl
, DWORD
* attributes
);
43 extern void WINAPI
ILFree(LPITEMIDLIST pidl
);
45 static const WCHAR lnkfile
[]= { 'C',':','\\','t','e','s','t','.','l','n','k',0 };
46 static const WCHAR notafile
[]= { 'C',':','\\','n','o','n','e','x','i','s','t','e','n','t','\\','f','i','l','e',0 };
48 const GUID IID_IPersistFile
= { 0x0000010b, 0x0000, 0x0000, { 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 } };
50 /* For some reason SHILCreateFromPath does not work on Win98 and
51 * SHSimpleIDListFromPathA does not work on NT4. But if we call both we
52 * get what we want on all platforms.
54 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathA
)(LPCSTR
)=NULL
;
56 static LPITEMIDLIST
path_to_pidl(const char* path
)
60 if (!pSHSimpleIDListFromPathA
)
62 HMODULE hdll
=LoadLibraryA("shell32.dll");
63 pSHSimpleIDListFromPathA
=(void*)GetProcAddress(hdll
, (char*)162);
64 if (!pSHSimpleIDListFromPathA
)
65 trace("SHSimpleIDListFromPathA not found in shell32.dll\n");
69 if (pSHSimpleIDListFromPathA
)
70 pidl
=pSHSimpleIDListFromPathA(path
);
78 len
=MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
79 pathW
=HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
80 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, len
);
82 r
=SHILCreateFromPath(pathW
, &pidl
, NULL
);
84 ok(SUCCEEDED(r
), "SHILCreateFromPath failed (0x%08lx)\n", r
);
86 HeapFree(GetProcessHeap(), 0, pathW
);
93 * Test manipulation of an IShellLink's properties.
96 static void test_get_set(void)
100 char mypath
[MAX_PATH
];
101 char buffer
[INFOTIPSIZE
];
102 LPITEMIDLIST pidl
, tmp_pidl
;
107 r
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
108 &IID_IShellLinkA
, (LPVOID
*)&sl
);
109 ok(SUCCEEDED(r
), "no IID_IShellLinkA (0x%08lx)\n", r
);
113 /* Test Getting / Setting the description */
114 strcpy(buffer
,"garbage");
115 r
= IShellLinkA_GetDescription(sl
, buffer
, sizeof(buffer
));
116 ok(SUCCEEDED(r
), "GetDescription failed (0x%08lx)\n", r
);
117 ok(*buffer
=='\0', "GetDescription returned '%s'\n", buffer
);
119 str
="Some description";
120 r
= IShellLinkA_SetDescription(sl
, str
);
121 ok(SUCCEEDED(r
), "SetDescription failed (0x%08lx)\n", r
);
123 strcpy(buffer
,"garbage");
124 r
= IShellLinkA_GetDescription(sl
, buffer
, sizeof(buffer
));
125 ok(SUCCEEDED(r
), "GetDescription failed (0x%08lx)\n", r
);
126 ok(lstrcmp(buffer
,str
)==0, "GetDescription returned '%s'\n", buffer
);
128 /* Test Getting / Setting the work directory */
129 strcpy(buffer
,"garbage");
130 r
= IShellLinkA_GetWorkingDirectory(sl
, buffer
, sizeof(buffer
));
131 ok(SUCCEEDED(r
), "GetWorkingDirectory failed (0x%08lx)\n", r
);
132 ok(*buffer
=='\0', "GetWorkingDirectory returned '%s'\n", buffer
);
134 str
="c:\\nonexistent\\directory";
135 r
= IShellLinkA_SetWorkingDirectory(sl
, str
);
136 ok(SUCCEEDED(r
), "SetWorkingDirectory failed (0x%08lx)\n", r
);
138 strcpy(buffer
,"garbage");
139 r
= IShellLinkA_GetWorkingDirectory(sl
, buffer
, sizeof(buffer
));
140 ok(SUCCEEDED(r
), "GetWorkingDirectory failed (0x%08lx)\n", r
);
141 ok(lstrcmpi(buffer
,str
)==0, "GetWorkingDirectory returned '%s'\n", buffer
);
143 /* Test Getting / Setting the work directory */
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 r
= IShellLinkA_SetPath(sl
, "");
150 ok(r
==S_OK
, "SetPath failed (0x%08lx)\n", r
);
152 strcpy(buffer
,"garbage");
153 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
154 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
155 ok(*buffer
=='\0', "GetPath returned '%s'\n", buffer
);
157 str
="c:\\nonexistent\\file";
158 r
= IShellLinkA_SetPath(sl
, str
);
159 ok(r
==S_FALSE
, "SetPath failed (0x%08lx)\n", r
);
161 strcpy(buffer
,"garbage");
162 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
163 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
164 ok(lstrcmpi(buffer
,str
)==0, "GetPath returned '%s'\n", buffer
);
166 /* Get some a real path to play with */
167 r
=GetModuleFileName(NULL
, mypath
, sizeof(mypath
));
168 ok(r
>=0 && r
<sizeof(mypath
), "GetModuleFileName failed (%ld)\n", r
);
170 /* Test the interaction of SetPath and SetIDList */
172 r
= IShellLinkA_GetIDList(sl
, &tmp_pidl
);
173 ok(SUCCEEDED(r
), "GetIDList failed (0x%08lx)\n", r
);
176 strcpy(buffer
,"garbage");
177 r
=SHGetPathFromIDListA(tmp_pidl
, buffer
);
179 ok(r
, "SHGetPathFromIDListA failed\n");
182 ok(lstrcmpi(buffer
,str
)==0, "GetIDList returned '%s'\n", buffer
);
185 pidl
=path_to_pidl(mypath
);
187 ok(pidl
!=NULL
, "path_to_pidl returned a NULL pidl\n");
192 r
= IShellLinkA_SetIDList(sl
, pidl
);
193 ok(SUCCEEDED(r
), "SetIDList failed (0x%08lx)\n", r
);
196 r
= IShellLinkA_GetIDList(sl
, &tmp_pidl
);
197 ok(SUCCEEDED(r
), "GetIDList failed (0x%08lx)\n", r
);
198 ok(tmp_pidl
&& ILIsEqual(pidl
, tmp_pidl
),
199 "GetIDList returned an incorrect pidl\n");
201 /* tmp_pidl is owned by IShellLink so we don't free it */
204 strcpy(buffer
,"garbage");
205 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
206 ok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
207 ok(lstrcmpi(buffer
, mypath
)==0, "GetPath returned '%s'\n", buffer
);
210 /* Test Getting / Setting the arguments */
211 strcpy(buffer
,"garbage");
212 r
= IShellLinkA_GetArguments(sl
, buffer
, sizeof(buffer
));
213 ok(SUCCEEDED(r
), "GetArguments failed (0x%08lx)\n", r
);
214 ok(*buffer
=='\0', "GetArguments returned '%s'\n", buffer
);
216 str
="param1 \"spaced param2\"";
217 r
= IShellLinkA_SetArguments(sl
, str
);
218 ok(SUCCEEDED(r
), "SetArguments failed (0x%08lx)\n", r
);
220 strcpy(buffer
,"garbage");
221 r
= IShellLinkA_GetArguments(sl
, buffer
, sizeof(buffer
));
222 ok(SUCCEEDED(r
), "GetArguments failed (0x%08lx)\n", r
);
223 ok(lstrcmp(buffer
,str
)==0, "GetArguments returned '%s'\n", buffer
);
225 /* Test Getting / Setting showcmd */
227 r
= IShellLinkA_GetShowCmd(sl
, &i
);
228 ok(SUCCEEDED(r
), "GetShowCmd failed (0x%08lx)\n", r
);
229 ok(i
==SW_SHOWNORMAL
, "GetShowCmd returned %d\n", i
);
231 r
= IShellLinkA_SetShowCmd(sl
, SW_SHOWMAXIMIZED
);
232 ok(SUCCEEDED(r
), "SetShowCmd failed (0x%08lx)\n", r
);
235 r
= IShellLinkA_GetShowCmd(sl
, &i
);
236 ok(SUCCEEDED(r
), "GetShowCmd failed (0x%08lx)\n", r
);
237 ok(i
==SW_SHOWMAXIMIZED
, "GetShowCmd returned %d'\n", i
);
239 /* Test Getting / Setting the icon */
241 strcpy(buffer
,"garbage");
242 r
= IShellLinkA_GetIconLocation(sl
, buffer
, sizeof(buffer
), &i
);
244 ok(SUCCEEDED(r
), "GetIconLocation failed (0x%08lx)\n", r
);
246 ok(*buffer
=='\0', "GetIconLocation returned '%s'\n", buffer
);
247 ok(i
==0, "GetIconLocation returned %d\n", i
);
249 str
="c:\\nonexistent\\file";
250 r
= IShellLinkA_SetIconLocation(sl
, str
, 0xbabecafe);
251 ok(SUCCEEDED(r
), "SetIconLocation failed (0x%08lx)\n", r
);
254 r
= IShellLinkA_GetIconLocation(sl
, buffer
, sizeof(buffer
), &i
);
255 ok(SUCCEEDED(r
), "GetIconLocation failed (0x%08lx)\n", r
);
256 ok(lstrcmpi(buffer
,str
)==0, "GetArguments returned '%s'\n", buffer
);
257 ok(i
==0xbabecafe, "GetIconLocation returned %d'\n", i
);
259 /* Test Getting / Setting the hot key */
261 r
= IShellLinkA_GetHotkey(sl
, &w
);
262 ok(SUCCEEDED(r
), "GetHotkey failed (0x%08lx)\n", r
);
263 ok(w
==0, "GetHotkey returned %d\n", w
);
265 r
= IShellLinkA_SetHotkey(sl
, 0x5678);
266 ok(SUCCEEDED(r
), "SetHotkey failed (0x%08lx)\n", r
);
269 r
= IShellLinkA_GetHotkey(sl
, &w
);
270 ok(SUCCEEDED(r
), "GetHotkey failed (0x%08lx)\n", r
);
271 ok(w
==0x5678, "GetHotkey returned %d'\n", w
);
273 IShellLinkA_Release(sl
);
278 * Test saving and loading .lnk files
281 #define lok ok_(__FILE__, line)
282 #define check_lnk(a,b) check_lnk_(__LINE__, (a), (b))
284 void create_lnk_(int line
, const WCHAR
* path
, lnk_desc_t
* desc
, int save_fails
)
290 r
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
291 &IID_IShellLinkA
, (LPVOID
*)&sl
);
292 lok(SUCCEEDED(r
), "no IID_IShellLinkA (0x%08lx)\n", r
);
296 if (desc
->description
)
298 r
= IShellLinkA_SetDescription(sl
, desc
->description
);
299 lok(SUCCEEDED(r
), "SetDescription failed (0x%08lx)\n", r
);
303 r
= IShellLinkA_SetWorkingDirectory(sl
, desc
->workdir
);
304 lok(SUCCEEDED(r
), "SetWorkingDirectory failed (0x%08lx)\n", r
);
308 r
= IShellLinkA_SetPath(sl
, desc
->path
);
309 lok(SUCCEEDED(r
), "SetPath failed (0x%08lx)\n", r
);
313 r
= IShellLinkA_SetIDList(sl
, desc
->pidl
);
314 lok(SUCCEEDED(r
), "SetIDList failed (0x%08lx)\n", r
);
318 r
= IShellLinkA_SetArguments(sl
, desc
->arguments
);
319 lok(SUCCEEDED(r
), "SetArguments failed (0x%08lx)\n", r
);
323 r
= IShellLinkA_SetShowCmd(sl
, desc
->showcmd
);
324 lok(SUCCEEDED(r
), "SetShowCmd failed (0x%08lx)\n", r
);
328 r
= IShellLinkA_SetIconLocation(sl
, desc
->icon
, desc
->icon_id
);
329 lok(SUCCEEDED(r
), "SetIconLocation failed (0x%08lx)\n", r
);
333 r
= IShellLinkA_SetHotkey(sl
, desc
->hotkey
);
334 lok(SUCCEEDED(r
), "SetHotkey failed (0x%08lx)\n", r
);
337 r
= IShellLinkW_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
338 lok(SUCCEEDED(r
), "no IID_IPersistFile (0x%08lx)\n", r
);
341 r
= IPersistFile_Save(pf
, path
, TRUE
);
345 lok(SUCCEEDED(r
), "save failed (0x%08lx)\n", r
);
350 lok(SUCCEEDED(r
), "save failed (0x%08lx)\n", r
);
352 IPersistFile_Release(pf
);
355 IShellLinkA_Release(sl
);
358 static void check_lnk_(int line
, const WCHAR
* path
, lnk_desc_t
* desc
)
363 char buffer
[INFOTIPSIZE
];
365 r
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
366 &IID_IShellLinkA
, (LPVOID
*)&sl
);
367 lok(SUCCEEDED(r
), "no IID_IShellLinkA (0x%08lx)\n", r
);
371 r
= IShellLinkA_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
372 lok(SUCCEEDED(r
), "no IID_IPersistFile (0x%08lx)\n", r
);
375 IShellLinkA_Release(sl
);
379 r
= IPersistFile_Load(pf
, path
, STGM_READ
);
380 lok(SUCCEEDED(r
), "load failed (0x%08lx)\n", r
);
381 IPersistFile_Release(pf
);
384 IShellLinkA_Release(sl
);
388 if (desc
->description
)
390 strcpy(buffer
,"garbage");
391 r
= IShellLinkA_GetDescription(sl
, buffer
, sizeof(buffer
));
392 lok(SUCCEEDED(r
), "GetDescription failed (0x%08lx)\n", r
);
393 lok(lstrcmp(buffer
, desc
->description
)==0,
394 "GetDescription returned '%s' instead of '%s'\n",
395 buffer
, desc
->description
);
399 strcpy(buffer
,"garbage");
400 r
= IShellLinkA_GetWorkingDirectory(sl
, buffer
, sizeof(buffer
));
401 lok(SUCCEEDED(r
), "GetWorkingDirectory failed (0x%08lx)\n", r
);
402 lok(lstrcmpi(buffer
, desc
->workdir
)==0,
403 "GetWorkingDirectory returned '%s' instead of '%s'\n",
404 buffer
, desc
->workdir
);
408 strcpy(buffer
,"garbage");
409 r
= IShellLinkA_GetPath(sl
, buffer
, sizeof(buffer
), NULL
, SLGP_RAWPATH
);
410 lok(SUCCEEDED(r
), "GetPath failed (0x%08lx)\n", r
);
411 lok(lstrcmpi(buffer
, desc
->path
)==0,
412 "GetPath returned '%s' instead of '%s'\n",
417 LPITEMIDLIST pidl
=NULL
;
418 r
= IShellLinkA_GetIDList(sl
, &pidl
);
419 lok(SUCCEEDED(r
), "GetIDList failed (0x%08lx)\n", r
);
420 lok(ILIsEqual(pidl
, desc
->pidl
),
421 "GetIDList returned an incorrect pidl\n");
426 r
= IShellLinkA_GetShowCmd(sl
, &i
);
427 lok(SUCCEEDED(r
), "GetShowCmd failed (0x%08lx)\n", r
);
428 lok(i
==desc
->showcmd
,
429 "GetShowCmd returned 0x%0x instead of 0x%0x\n",
435 strcpy(buffer
,"garbage");
436 r
= IShellLinkA_GetIconLocation(sl
, buffer
, sizeof(buffer
), &i
);
437 lok(SUCCEEDED(r
), "GetIconLocation failed (0x%08lx)\n", r
);
438 lok(lstrcmpi(buffer
, desc
->icon
)==0,
439 "GetIconLocation returned '%s' instead of '%s'\n",
441 lok(i
==desc
->icon_id
,
442 "GetIconLocation returned 0x%0x instead of 0x%0x\n",
448 r
= IShellLinkA_GetHotkey(sl
, &i
);
449 lok(SUCCEEDED(r
), "GetHotkey failed (0x%08lx)\n", r
);
451 "GetHotkey returned 0x%04x instead of 0x%04x\n",
455 IShellLinkA_Release(sl
);
458 static void test_load_save(void)
461 char mypath
[MAX_PATH
];
462 char mydir
[MAX_PATH
];
466 /* Save an empty .lnk file */
467 memset(&desc
, 0, sizeof(desc
));
468 create_lnk(lnkfile
, &desc
, 0);
470 /* It should come back as a bunch of empty strings */
476 check_lnk(lnkfile
, &desc
);
479 /* Point a .lnk file to nonexistent files */
481 desc
.workdir
="c:\\Nonexitent\\work\\directory";
482 desc
.path
="c:\\nonexistent\\path";
486 desc
.icon
="c:\\nonexistent\\icon\\file";
489 create_lnk(lnkfile
, &desc
, 0);
490 check_lnk(lnkfile
, &desc
);
492 r
=GetModuleFileName(NULL
, mypath
, sizeof(mypath
));
493 ok(r
>=0 && r
<sizeof(mypath
), "GetModuleFileName failed (%ld)\n", r
);
494 strcpy(mydir
, mypath
);
495 p
=strrchr(mydir
, '\\');
500 /* Overwrite the existing lnk file and point it to existing files */
501 desc
.description
="test 2";
505 desc
.arguments
="/option1 /option2 \"Some string\"";
506 desc
.showcmd
=SW_SHOWNORMAL
;
510 create_lnk(lnkfile
, &desc
, 0);
511 check_lnk(lnkfile
, &desc
);
513 /* FIXME: Also test saving a .lnk pointing to a pidl that cannot be
514 * represented as a path.
517 /* DeleteFileW is not implemented on Win9x */
518 r
=DeleteFileA("c:\\test.lnk");
519 ok(r
, "failed to delete link (%ld)\n", GetLastError());
522 START_TEST(shelllink
)
526 r
= CoInitialize(NULL
);
527 ok(SUCCEEDED(r
), "CoInitialize failed (0x%08lx)\n", r
);