Move and reshuffle reactos/regtetsts into rostests. 1/2
[reactos.git] / rostests / winetests / shell32 / shelllink.c
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., 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).
22 *
23 */
24
25 #define _WIN32_IE 0x0400
26
27 #define COBJMACROS
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "basetyps.h"
34 #include "shlguid.h"
35 //#include "wine/shobjidl.h"
36 #include "shlobj.h"
37 #include "wine/test.h"
38
39 #include "shell32_test.h"
40
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);
44
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 };
47
48 const GUID IID_IPersistFile = { 0x0000010b, 0x0000, 0x0000, { 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 } };
49
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.
53 */
54 static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathA)(LPCSTR)=NULL;
55
56 static LPITEMIDLIST path_to_pidl(const char* path)
57 {
58 LPITEMIDLIST pidl;
59
60 if (!pSHSimpleIDListFromPathA)
61 {
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");
66 }
67
68 pidl=NULL;
69 if (pSHSimpleIDListFromPathA)
70 pidl=pSHSimpleIDListFromPathA(path);
71
72 if (!pidl)
73 {
74 WCHAR* pathW;
75 HRESULT r;
76 int len;
77
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);
81
82 r=SHILCreateFromPath(pathW, &pidl, NULL);
83 todo_wine {
84 ok(SUCCEEDED(r), "SHILCreateFromPath failed (0x%08lx)\n", r);
85 }
86 HeapFree(GetProcessHeap(), 0, pathW);
87 }
88 return pidl;
89 }
90
91
92 /*
93 * Test manipulation of an IShellLink's properties.
94 */
95
96 static void test_get_set(void)
97 {
98 HRESULT r;
99 IShellLinkA *sl;
100 char mypath[MAX_PATH];
101 char buffer[INFOTIPSIZE];
102 LPITEMIDLIST pidl, tmp_pidl;
103 const char * str;
104 int i;
105 WORD w;
106
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);
110 if (!SUCCEEDED(r))
111 return;
112
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);
118
119 str="Some description";
120 r = IShellLinkA_SetDescription(sl, str);
121 ok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r);
122
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);
127
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);
133
134 str="c:\\nonexistent\\directory";
135 r = IShellLinkA_SetWorkingDirectory(sl, str);
136 ok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r);
137
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);
142
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);
148
149 r = IShellLinkA_SetPath(sl, "");
150 ok(r==S_OK, "SetPath failed (0x%08lx)\n", r);
151
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);
156
157 str="c:\\nonexistent\\file";
158 r = IShellLinkA_SetPath(sl, str);
159 ok(r==S_FALSE, "SetPath failed (0x%08lx)\n", r);
160
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);
165
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);
169
170 /* Test the interaction of SetPath and SetIDList */
171 tmp_pidl=NULL;
172 r = IShellLinkA_GetIDList(sl, &tmp_pidl);
173 ok(SUCCEEDED(r), "GetIDList failed (0x%08lx)\n", r);
174 if (SUCCEEDED(r))
175 {
176 strcpy(buffer,"garbage");
177 r=SHGetPathFromIDListA(tmp_pidl, buffer);
178 todo_wine {
179 ok(r, "SHGetPathFromIDListA failed\n");
180 }
181 if (r)
182 ok(lstrcmpi(buffer,str)==0, "GetIDList returned '%s'\n", buffer);
183 }
184
185 pidl=path_to_pidl(mypath);
186 todo_wine {
187 ok(pidl!=NULL, "path_to_pidl returned a NULL pidl\n");
188 }
189
190 if (pidl)
191 {
192 r = IShellLinkA_SetIDList(sl, pidl);
193 ok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r);
194
195 tmp_pidl=NULL;
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");
200
201 /* tmp_pidl is owned by IShellLink so we don't free it */
202 ILFree(pidl);
203
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);
208 }
209
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);
215
216 str="param1 \"spaced param2\"";
217 r = IShellLinkA_SetArguments(sl, str);
218 ok(SUCCEEDED(r), "SetArguments failed (0x%08lx)\n", r);
219
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);
224
225 /* Test Getting / Setting showcmd */
226 i=0xdeadbeef;
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);
230
231 r = IShellLinkA_SetShowCmd(sl, SW_SHOWMAXIMIZED);
232 ok(SUCCEEDED(r), "SetShowCmd failed (0x%08lx)\n", r);
233
234 i=0xdeadbeef;
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);
238
239 /* Test Getting / Setting the icon */
240 i=0xdeadbeef;
241 strcpy(buffer,"garbage");
242 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
243 todo_wine {
244 ok(SUCCEEDED(r), "GetIconLocation failed (0x%08lx)\n", r);
245 }
246 ok(*buffer=='\0', "GetIconLocation returned '%s'\n", buffer);
247 ok(i==0, "GetIconLocation returned %d\n", i);
248
249 str="c:\\nonexistent\\file";
250 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
251 ok(SUCCEEDED(r), "SetIconLocation failed (0x%08lx)\n", r);
252
253 i=0xdeadbeef;
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);
258
259 /* Test Getting / Setting the hot key */
260 w=0xbeef;
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);
264
265 r = IShellLinkA_SetHotkey(sl, 0x5678);
266 ok(SUCCEEDED(r), "SetHotkey failed (0x%08lx)\n", r);
267
268 w=0xbeef;
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);
272
273 IShellLinkA_Release(sl);
274 }
275
276
277 /*
278 * Test saving and loading .lnk files
279 */
280
281 #define lok ok_(__FILE__, line)
282 #define check_lnk(a,b) check_lnk_(__LINE__, (a), (b))
283
284 void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails)
285 {
286 HRESULT r;
287 IShellLinkA *sl;
288 IPersistFile *pf;
289
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);
293 if (!SUCCEEDED(r))
294 return;
295
296 if (desc->description)
297 {
298 r = IShellLinkA_SetDescription(sl, desc->description);
299 lok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r);
300 }
301 if (desc->workdir)
302 {
303 r = IShellLinkA_SetWorkingDirectory(sl, desc->workdir);
304 lok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r);
305 }
306 if (desc->path)
307 {
308 r = IShellLinkA_SetPath(sl, desc->path);
309 lok(SUCCEEDED(r), "SetPath failed (0x%08lx)\n", r);
310 }
311 if (desc->pidl)
312 {
313 r = IShellLinkA_SetIDList(sl, desc->pidl);
314 lok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r);
315 }
316 if (desc->arguments)
317 {
318 r = IShellLinkA_SetArguments(sl, desc->arguments);
319 lok(SUCCEEDED(r), "SetArguments failed (0x%08lx)\n", r);
320 }
321 if (desc->showcmd)
322 {
323 r = IShellLinkA_SetShowCmd(sl, desc->showcmd);
324 lok(SUCCEEDED(r), "SetShowCmd failed (0x%08lx)\n", r);
325 }
326 if (desc->icon)
327 {
328 r = IShellLinkA_SetIconLocation(sl, desc->icon, desc->icon_id);
329 lok(SUCCEEDED(r), "SetIconLocation failed (0x%08lx)\n", r);
330 }
331 if (desc->hotkey)
332 {
333 r = IShellLinkA_SetHotkey(sl, desc->hotkey);
334 lok(SUCCEEDED(r), "SetHotkey failed (0x%08lx)\n", r);
335 }
336
337 r = IShellLinkW_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
338 lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r);
339 if (SUCCEEDED(r))
340 {
341 r = IPersistFile_Save(pf, path, TRUE);
342 if (save_fails)
343 {
344 todo_wine {
345 lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r);
346 }
347 }
348 else
349 {
350 lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r);
351 }
352 IPersistFile_Release(pf);
353 }
354
355 IShellLinkA_Release(sl);
356 }
357
358 static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc)
359 {
360 HRESULT r;
361 IShellLinkA *sl;
362 IPersistFile *pf;
363 char buffer[INFOTIPSIZE];
364
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);
368 if (!SUCCEEDED(r))
369 return;
370
371 r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
372 lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r);
373 if (!SUCCEEDED(r))
374 {
375 IShellLinkA_Release(sl);
376 return;
377 }
378
379 r = IPersistFile_Load(pf, path, STGM_READ);
380 lok(SUCCEEDED(r), "load failed (0x%08lx)\n", r);
381 IPersistFile_Release(pf);
382 if (!SUCCEEDED(r))
383 {
384 IShellLinkA_Release(sl);
385 return;
386 }
387
388 if (desc->description)
389 {
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);
396 }
397 if (desc->workdir)
398 {
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);
405 }
406 if (desc->path)
407 {
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",
413 buffer, desc->path);
414 }
415 if (desc->pidl)
416 {
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");
422 }
423 if (desc->showcmd)
424 {
425 int i=0xdeadbeef;
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",
430 i, desc->showcmd);
431 }
432 if (desc->icon)
433 {
434 int i=0xdeadbeef;
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",
440 buffer, desc->icon);
441 lok(i==desc->icon_id,
442 "GetIconLocation returned 0x%0x instead of 0x%0x\n",
443 i, desc->icon_id);
444 }
445 if (desc->hotkey)
446 {
447 WORD i=0xbeef;
448 r = IShellLinkA_GetHotkey(sl, &i);
449 lok(SUCCEEDED(r), "GetHotkey failed (0x%08lx)\n", r);
450 lok(i==desc->hotkey,
451 "GetHotkey returned 0x%04x instead of 0x%04x\n",
452 i, desc->hotkey);
453 }
454
455 IShellLinkA_Release(sl);
456 }
457
458 static void test_load_save(void)
459 {
460 lnk_desc_t desc;
461 char mypath[MAX_PATH];
462 char mydir[MAX_PATH];
463 char* p;
464 DWORD r;
465
466 /* Save an empty .lnk file */
467 memset(&desc, 0, sizeof(desc));
468 create_lnk(lnkfile, &desc, 0);
469
470 /* It should come back as a bunch of empty strings */
471 desc.description="";
472 desc.workdir="";
473 desc.path="";
474 desc.arguments="";
475 desc.icon="";
476 check_lnk(lnkfile, &desc);
477
478
479 /* Point a .lnk file to nonexistent files */
480 desc.description="";
481 desc.workdir="c:\\Nonexitent\\work\\directory";
482 desc.path="c:\\nonexistent\\path";
483 desc.pidl=NULL;
484 desc.arguments="";
485 desc.showcmd=0;
486 desc.icon="c:\\nonexistent\\icon\\file";
487 desc.icon_id=1234;
488 desc.hotkey=0;
489 create_lnk(lnkfile, &desc, 0);
490 check_lnk(lnkfile, &desc);
491
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, '\\');
496 if (p)
497 *p='\0';
498
499
500 /* Overwrite the existing lnk file and point it to existing files */
501 desc.description="test 2";
502 desc.workdir=mydir;
503 desc.path=mypath;
504 desc.pidl=NULL;
505 desc.arguments="/option1 /option2 \"Some string\"";
506 desc.showcmd=SW_SHOWNORMAL;
507 desc.icon=mypath;
508 desc.icon_id=0;
509 desc.hotkey=0x1234;
510 create_lnk(lnkfile, &desc, 0);
511 check_lnk(lnkfile, &desc);
512
513 /* FIXME: Also test saving a .lnk pointing to a pidl that cannot be
514 * represented as a path.
515 */
516
517 /* DeleteFileW is not implemented on Win9x */
518 r=DeleteFileA("c:\\test.lnk");
519 ok(r, "failed to delete link (%ld)\n", GetLastError());
520 }
521
522 START_TEST(shelllink)
523 {
524 HRESULT r;
525
526 r = CoInitialize(NULL);
527 ok(SUCCEEDED(r), "CoInitialize failed (0x%08lx)\n", r);
528 if (!SUCCEEDED(r))
529 return;
530
531 test_get_set();
532 test_load_save();
533
534 CoUninitialize();
535 }