SHELL32.ILFindLastID is exported by ordinal.
[wine.git] / dlls / shell32 / tests / shelllink.c
blobaf0c9b760cc5661514eb50825fbae0068fc87e5a
1 /*
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 COBJMACROS
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "shlguid.h"
32 #include "shobjidl.h"
33 #include "shlobj.h"
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)
50 LPITEMIDLIST pidl;
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");
60 pidl=NULL;
61 if (pSHSimpleIDListFromPathA)
62 pidl=pSHSimpleIDListFromPathA(path);
64 if (!pidl)
66 WCHAR* pathW;
67 HRESULT r;
68 int len;
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);
75 todo_wine {
76 ok(SUCCEEDED(r), "SHILCreateFromPath failed (0x%08lx)\n", r);
78 HeapFree(GetProcessHeap(), 0, pathW);
80 return pidl;
85 * Test manipulation of an IShellLink's properties.
88 static void test_get_set(void)
90 HRESULT r;
91 IShellLinkA *sl;
92 char mypath[MAX_PATH];
93 char buffer[INFOTIPSIZE];
94 LPITEMIDLIST pidl, tmp_pidl;
95 const char * str;
96 int i;
97 WORD w;
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);
102 if (!SUCCEEDED(r))
103 return;
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 */
163 tmp_pidl=NULL;
164 r = IShellLinkA_GetIDList(sl, &tmp_pidl);
165 ok(SUCCEEDED(r), "GetIDList failed (0x%08lx)\n", r);
166 if (SUCCEEDED(r))
168 strcpy(buffer,"garbage");
169 r=SHGetPathFromIDListA(tmp_pidl, buffer);
170 todo_wine {
171 ok(r, "SHGetPathFromIDListA failed\n");
173 if (r)
174 ok(lstrcmpi(buffer,str)==0, "GetIDList returned '%s'\n", buffer);
177 pidl=path_to_pidl(mypath);
178 todo_wine {
179 ok(pidl!=NULL, "path_to_pidl returned a NULL pidl\n");
182 if (pidl)
184 r = IShellLinkA_SetIDList(sl, pidl);
185 ok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r);
187 tmp_pidl=NULL;
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 */
194 ILFree(pidl);
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 */
218 i=0xdeadbeef;
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);
226 i=0xdeadbeef;
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 */
232 i=0xdeadbeef;
233 strcpy(buffer,"garbage");
234 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
235 todo_wine {
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);
245 i=0xdeadbeef;
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 */
252 w=0xbeef;
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);
260 w=0xbeef;
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)
278 HRESULT r;
279 IShellLinkA *sl;
280 IPersistFile *pf;
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);
285 if (!SUCCEEDED(r))
286 return;
288 if (desc->description)
290 r = IShellLinkA_SetDescription(sl, desc->description);
291 lok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r);
293 if (desc->workdir)
295 r = IShellLinkA_SetWorkingDirectory(sl, desc->workdir);
296 lok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r);
298 if (desc->path)
300 r = IShellLinkA_SetPath(sl, desc->path);
301 lok(SUCCEEDED(r), "SetPath failed (0x%08lx)\n", r);
303 if (desc->pidl)
305 r = IShellLinkA_SetIDList(sl, desc->pidl);
306 lok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r);
308 if (desc->arguments)
310 r = IShellLinkA_SetArguments(sl, desc->arguments);
311 lok(SUCCEEDED(r), "SetArguments failed (0x%08lx)\n", r);
313 if (desc->showcmd)
315 r = IShellLinkA_SetShowCmd(sl, desc->showcmd);
316 lok(SUCCEEDED(r), "SetShowCmd failed (0x%08lx)\n", r);
318 if (desc->icon)
320 r = IShellLinkA_SetIconLocation(sl, desc->icon, desc->icon_id);
321 lok(SUCCEEDED(r), "SetIconLocation failed (0x%08lx)\n", r);
323 if (desc->hotkey)
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);
331 if (SUCCEEDED(r))
333 r = IPersistFile_Save(pf, path, TRUE);
334 if (save_fails)
336 todo_wine {
337 lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r);
340 else
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)
352 HRESULT r;
353 IShellLinkA *sl;
354 IPersistFile *pf;
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);
360 if (!SUCCEEDED(r))
361 return;
363 r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
364 lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r);
365 if (!SUCCEEDED(r))
367 IShellLinkA_Release(sl);
368 return;
371 r = IPersistFile_Load(pf, path, STGM_READ);
372 lok(SUCCEEDED(r), "load failed (0x%08lx)\n", r);
373 IPersistFile_Release(pf);
374 if (!SUCCEEDED(r))
376 IShellLinkA_Release(sl);
377 return;
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);
389 if (desc->workdir)
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);
398 if (desc->path)
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",
405 buffer, desc->path);
407 if (desc->pidl)
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");
415 if (desc->showcmd)
417 int i=0xdeadbeef;
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",
422 i, desc->showcmd);
424 if (desc->icon)
426 int i=0xdeadbeef;
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",
432 buffer, desc->icon);
433 lok(i==desc->icon_id,
434 "GetIconLocation returned 0x%0x instead of 0x%0x\n",
435 i, desc->icon_id);
437 if (desc->hotkey)
439 WORD i=0xbeef;
440 r = IShellLinkA_GetHotkey(sl, &i);
441 lok(SUCCEEDED(r), "GetHotkey failed (0x%08lx)\n", r);
442 lok(i==desc->hotkey,
443 "GetHotkey returned 0x%04x instead of 0x%04x\n",
444 i, desc->hotkey);
447 IShellLinkA_Release(sl);
450 static void test_load_save(void)
452 lnk_desc_t desc;
453 char mypath[MAX_PATH];
454 char mydir[MAX_PATH];
455 char* p;
456 DWORD r;
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 */
463 desc.description="";
464 desc.workdir="";
465 desc.path="";
466 desc.arguments="";
467 desc.icon="";
468 check_lnk(lnkfile, &desc);
471 /* Point a .lnk file to nonexistent files */
472 desc.description="";
473 desc.workdir="c:\\Nonexitent\\work\\directory";
474 desc.path="c:\\nonexistent\\path";
475 desc.pidl=NULL;
476 desc.arguments="";
477 desc.showcmd=0;
478 desc.icon="c:\\nonexistent\\icon\\file";
479 desc.icon_id=1234;
480 desc.hotkey=0;
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, '\\');
488 if (p)
489 *p='\0';
492 /* Overwrite the existing lnk file and point it to existing files */
493 desc.description="test 2";
494 desc.workdir=mydir;
495 desc.path=mypath;
496 desc.pidl=NULL;
497 desc.arguments="/option1 /option2 \"Some string\"";
498 desc.showcmd=SW_SHOWNORMAL;
499 desc.icon=mypath;
500 desc.icon_id=0;
501 desc.hotkey=0x1234;
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)
516 HRESULT r;
518 r = CoInitialize(NULL);
519 ok(SUCCEEDED(r), "CoInitialize failed (0x%08lx)\n", r);
520 if (!SUCCEEDED(r))
521 return;
523 test_get_set();
524 test_load_save();
526 CoUninitialize();