secur32: Update ntlm_auth version detection to detect new samba4 version numbers.
[wine] / dlls / shell32 / tests / 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 COBJMACROS
26
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"
35
36 #include "shell32_test.h"
37
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 };
40
41
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.
45  */
46 static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID);
47
48 static LPITEMIDLIST path_to_pidl(const char* path)
49 {
50     LPITEMIDLIST pidl;
51
52     if (!pSHSimpleIDListFromPathAW)
53     {
54         HMODULE hdll=LoadLibraryA("shell32.dll");
55         pSHSimpleIDListFromPathAW=(void*)GetProcAddress(hdll, (char*)162);
56         if (!pSHSimpleIDListFromPathAW)
57             trace("SHSimpleIDListFromPathAW not found in shell32.dll\n");
58     }
59
60     pidl=NULL;
61     /* pSHSimpleIDListFromPathAW maps to A on non NT platforms */
62     if (pSHSimpleIDListFromPathAW && (GetVersion() & 0x80000000))
63         pidl=pSHSimpleIDListFromPathAW(path);
64
65     if (!pidl)
66     {
67         WCHAR* pathW;
68         HRESULT r;
69         int len;
70
71         len=MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
72         pathW=HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
73         MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len);
74
75         r=SHILCreateFromPath(pathW, &pidl, NULL);
76         todo_wine {
77         ok(SUCCEEDED(r), "SHILCreateFromPath failed (0x%08lx)\n", r);
78         }
79         HeapFree(GetProcessHeap(), 0, pathW);
80     }
81     return pidl;
82 }
83
84
85 /*
86  * Test manipulation of an IShellLink's properties.
87  */
88
89 static void test_get_set(void)
90 {
91     HRESULT r;
92     IShellLinkA *sl;
93     char mypath[MAX_PATH];
94     char buffer[INFOTIPSIZE];
95     LPITEMIDLIST pidl, tmp_pidl;
96     const char * str;
97     int i;
98     WORD w;
99
100     r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
101                          &IID_IShellLinkA, (LPVOID*)&sl);
102     ok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08lx)\n", r);
103     if (!SUCCEEDED(r))
104         return;
105
106     /* Test Getting / Setting the description */
107     strcpy(buffer,"garbage");
108     r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
109     ok(SUCCEEDED(r), "GetDescription failed (0x%08lx)\n", r);
110     ok(*buffer=='\0', "GetDescription returned '%s'\n", buffer);
111
112     str="Some description";
113     r = IShellLinkA_SetDescription(sl, str);
114     ok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r);
115
116     strcpy(buffer,"garbage");
117     r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
118     ok(SUCCEEDED(r), "GetDescription failed (0x%08lx)\n", r);
119     ok(lstrcmp(buffer,str)==0, "GetDescription returned '%s'\n", buffer);
120
121     /* Test Getting / Setting the work directory */
122     strcpy(buffer,"garbage");
123     r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer));
124     ok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08lx)\n", r);
125     ok(*buffer=='\0', "GetWorkingDirectory returned '%s'\n", buffer);
126
127     str="c:\\nonexistent\\directory";
128     r = IShellLinkA_SetWorkingDirectory(sl, str);
129     ok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r);
130
131     strcpy(buffer,"garbage");
132     r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer));
133     ok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08lx)\n", r);
134     ok(lstrcmpi(buffer,str)==0, "GetWorkingDirectory returned '%s'\n", buffer);
135
136     /* Test Getting / Setting the work directory */
137     strcpy(buffer,"garbage");
138     r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
139     ok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r);
140     ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
141
142     r = IShellLinkA_SetPath(sl, "");
143     ok(r==S_OK, "SetPath failed (0x%08lx)\n", r);
144
145     strcpy(buffer,"garbage");
146     r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
147     ok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r);
148     ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
149
150     str="c:\\nonexistent\\file";
151     r = IShellLinkA_SetPath(sl, str);
152     ok(r==S_FALSE, "SetPath failed (0x%08lx)\n", r);
153
154     strcpy(buffer,"garbage");
155     r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
156     ok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r);
157     ok(lstrcmpi(buffer,str)==0, "GetPath returned '%s'\n", buffer);
158
159     /* Get some a real path to play with */
160     r=GetModuleFileName(NULL, mypath, sizeof(mypath));
161     ok(r>=0 && r<sizeof(mypath), "GetModuleFileName failed (%ld)\n", r);
162
163     /* Test the interaction of SetPath and SetIDList */
164     tmp_pidl=NULL;
165     r = IShellLinkA_GetIDList(sl, &tmp_pidl);
166     ok(SUCCEEDED(r), "GetIDList failed (0x%08lx)\n", r);
167     if (SUCCEEDED(r))
168     {
169         strcpy(buffer,"garbage");
170         r=SHGetPathFromIDListA(tmp_pidl, buffer);
171         todo_wine {
172         ok(r, "SHGetPathFromIDListA failed\n");
173         }
174         if (r)
175             ok(lstrcmpi(buffer,str)==0, "GetIDList returned '%s'\n", buffer);
176     }
177
178     pidl=path_to_pidl(mypath);
179     todo_wine {
180     ok(pidl!=NULL, "path_to_pidl returned a NULL pidl\n");
181     }
182
183     if (pidl)
184     {
185         r = IShellLinkA_SetIDList(sl, pidl);
186         ok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r);
187
188         tmp_pidl=NULL;
189         r = IShellLinkA_GetIDList(sl, &tmp_pidl);
190         ok(SUCCEEDED(r), "GetIDList failed (0x%08lx)\n", r);
191         ok(tmp_pidl && ILIsEqual(pidl, tmp_pidl),
192            "GetIDList returned an incorrect pidl\n");
193
194         /* tmp_pidl is owned by IShellLink so we don't free it */
195         ILFree(pidl);
196
197         strcpy(buffer,"garbage");
198         r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
199         ok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r);
200         ok(lstrcmpi(buffer, mypath)==0, "GetPath returned '%s'\n", buffer);
201     }
202
203     /* Test Getting / Setting the arguments */
204     strcpy(buffer,"garbage");
205     r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
206     ok(SUCCEEDED(r), "GetArguments failed (0x%08lx)\n", r);
207     ok(*buffer=='\0', "GetArguments returned '%s'\n", buffer);
208
209     str="param1 \"spaced param2\"";
210     r = IShellLinkA_SetArguments(sl, str);
211     ok(SUCCEEDED(r), "SetArguments failed (0x%08lx)\n", r);
212
213     strcpy(buffer,"garbage");
214     r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
215     ok(SUCCEEDED(r), "GetArguments failed (0x%08lx)\n", r);
216     ok(lstrcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
217
218     /* Test Getting / Setting showcmd */
219     i=0xdeadbeef;
220     r = IShellLinkA_GetShowCmd(sl, &i);
221     ok(SUCCEEDED(r), "GetShowCmd failed (0x%08lx)\n", r);
222     ok(i==SW_SHOWNORMAL, "GetShowCmd returned %d\n", i);
223
224     r = IShellLinkA_SetShowCmd(sl, SW_SHOWMAXIMIZED);
225     ok(SUCCEEDED(r), "SetShowCmd failed (0x%08lx)\n", r);
226
227     i=0xdeadbeef;
228     r = IShellLinkA_GetShowCmd(sl, &i);
229     ok(SUCCEEDED(r), "GetShowCmd failed (0x%08lx)\n", r);
230     ok(i==SW_SHOWMAXIMIZED, "GetShowCmd returned %d'\n", i);
231
232     /* Test Getting / Setting the icon */
233     i=0xdeadbeef;
234     strcpy(buffer,"garbage");
235     r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
236     todo_wine {
237     ok(SUCCEEDED(r), "GetIconLocation failed (0x%08lx)\n", r);
238     }
239     ok(*buffer=='\0', "GetIconLocation returned '%s'\n", buffer);
240     ok(i==0, "GetIconLocation returned %d\n", i);
241
242     str="c:\\nonexistent\\file";
243     r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
244     ok(SUCCEEDED(r), "SetIconLocation failed (0x%08lx)\n", r);
245
246     i=0xdeadbeef;
247     r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
248     ok(SUCCEEDED(r), "GetIconLocation failed (0x%08lx)\n", r);
249     ok(lstrcmpi(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
250     ok(i==0xbabecafe, "GetIconLocation returned %d'\n", i);
251
252     /* Test Getting / Setting the hot key */
253     w=0xbeef;
254     r = IShellLinkA_GetHotkey(sl, &w);
255     ok(SUCCEEDED(r), "GetHotkey failed (0x%08lx)\n", r);
256     ok(w==0, "GetHotkey returned %d\n", w);
257
258     r = IShellLinkA_SetHotkey(sl, 0x5678);
259     ok(SUCCEEDED(r), "SetHotkey failed (0x%08lx)\n", r);
260
261     w=0xbeef;
262     r = IShellLinkA_GetHotkey(sl, &w);
263     ok(SUCCEEDED(r), "GetHotkey failed (0x%08lx)\n", r);
264     ok(w==0x5678, "GetHotkey returned %d'\n", w);
265
266     IShellLinkA_Release(sl);
267 }
268
269
270 /*
271  * Test saving and loading .lnk files
272  */
273
274 #define lok                   ok_(__FILE__, line)
275 #define check_lnk(a,b)        check_lnk_(__LINE__, (a), (b))
276
277 void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails)
278 {
279     HRESULT r;
280     IShellLinkA *sl;
281     IPersistFile *pf;
282
283     r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
284                          &IID_IShellLinkA, (LPVOID*)&sl);
285     lok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08lx)\n", r);
286     if (!SUCCEEDED(r))
287         return;
288
289     if (desc->description)
290     {
291         r = IShellLinkA_SetDescription(sl, desc->description);
292         lok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r);
293     }
294     if (desc->workdir)
295     {
296         r = IShellLinkA_SetWorkingDirectory(sl, desc->workdir);
297         lok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r);
298     }
299     if (desc->path)
300     {
301         r = IShellLinkA_SetPath(sl, desc->path);
302         lok(SUCCEEDED(r), "SetPath failed (0x%08lx)\n", r);
303     }
304     if (desc->pidl)
305     {
306         r = IShellLinkA_SetIDList(sl, desc->pidl);
307         lok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r);
308     }
309     if (desc->arguments)
310     {
311         r = IShellLinkA_SetArguments(sl, desc->arguments);
312         lok(SUCCEEDED(r), "SetArguments failed (0x%08lx)\n", r);
313     }
314     if (desc->showcmd)
315     {
316         r = IShellLinkA_SetShowCmd(sl, desc->showcmd);
317         lok(SUCCEEDED(r), "SetShowCmd failed (0x%08lx)\n", r);
318     }
319     if (desc->icon)
320     {
321         r = IShellLinkA_SetIconLocation(sl, desc->icon, desc->icon_id);
322         lok(SUCCEEDED(r), "SetIconLocation failed (0x%08lx)\n", r);
323     }
324     if (desc->hotkey)
325     {
326         r = IShellLinkA_SetHotkey(sl, desc->hotkey);
327         lok(SUCCEEDED(r), "SetHotkey failed (0x%08lx)\n", r);
328     }
329
330     r = IShellLinkW_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
331     lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r);
332     if (SUCCEEDED(r))
333     {
334         r = IPersistFile_Save(pf, path, TRUE);
335         if (save_fails)
336         {
337             todo_wine {
338             lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r);
339             }
340         }
341         else
342         {
343             lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r);
344         }
345         IPersistFile_Release(pf);
346     }
347
348     IShellLinkA_Release(sl);
349 }
350
351 static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc)
352 {
353     HRESULT r;
354     IShellLinkA *sl;
355     IPersistFile *pf;
356     char buffer[INFOTIPSIZE];
357
358     r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
359                          &IID_IShellLinkA, (LPVOID*)&sl);
360     lok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08lx)\n", r);
361     if (!SUCCEEDED(r))
362         return;
363
364     r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
365     lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r);
366     if (!SUCCEEDED(r))
367     {
368         IShellLinkA_Release(sl);
369         return;
370     }
371
372     r = IPersistFile_Load(pf, path, STGM_READ);
373     lok(SUCCEEDED(r), "load failed (0x%08lx)\n", r);
374     IPersistFile_Release(pf);
375     if (!SUCCEEDED(r))
376     {
377         IShellLinkA_Release(sl);
378         return;
379     }
380
381     if (desc->description)
382     {
383         strcpy(buffer,"garbage");
384         r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer));
385         lok(SUCCEEDED(r), "GetDescription failed (0x%08lx)\n", r);
386         lok(lstrcmp(buffer, desc->description)==0,
387            "GetDescription returned '%s' instead of '%s'\n",
388            buffer, desc->description);
389     }
390     if (desc->workdir)
391     {
392         strcpy(buffer,"garbage");
393         r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer));
394         lok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08lx)\n", r);
395         lok(lstrcmpi(buffer, desc->workdir)==0,
396            "GetWorkingDirectory returned '%s' instead of '%s'\n",
397            buffer, desc->workdir);
398     }
399     if (desc->path)
400     {
401         strcpy(buffer,"garbage");
402         r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
403         lok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r);
404         lok(lstrcmpi(buffer, desc->path)==0,
405            "GetPath returned '%s' instead of '%s'\n",
406            buffer, desc->path);
407     }
408     if (desc->pidl)
409     {
410         LPITEMIDLIST pidl=NULL;
411         r = IShellLinkA_GetIDList(sl, &pidl);
412         lok(SUCCEEDED(r), "GetIDList failed (0x%08lx)\n", r);
413         lok(ILIsEqual(pidl, desc->pidl),
414            "GetIDList returned an incorrect pidl\n");
415     }
416     if (desc->showcmd)
417     {
418         int i=0xdeadbeef;
419         r = IShellLinkA_GetShowCmd(sl, &i);
420         lok(SUCCEEDED(r), "GetShowCmd failed (0x%08lx)\n", r);
421         lok(i==desc->showcmd,
422            "GetShowCmd returned 0x%0x instead of 0x%0x\n",
423            i, desc->showcmd);
424     }
425     if (desc->icon)
426     {
427         int i=0xdeadbeef;
428         strcpy(buffer,"garbage");
429         r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
430         lok(SUCCEEDED(r), "GetIconLocation failed (0x%08lx)\n", r);
431         lok(lstrcmpi(buffer, desc->icon)==0,
432            "GetIconLocation returned '%s' instead of '%s'\n",
433            buffer, desc->icon);
434         lok(i==desc->icon_id,
435            "GetIconLocation returned 0x%0x instead of 0x%0x\n",
436            i, desc->icon_id);
437     }
438     if (desc->hotkey)
439     {
440         WORD i=0xbeef;
441         r = IShellLinkA_GetHotkey(sl, &i);
442         lok(SUCCEEDED(r), "GetHotkey failed (0x%08lx)\n", r);
443         lok(i==desc->hotkey,
444            "GetHotkey returned 0x%04x instead of 0x%04x\n",
445            i, desc->hotkey);
446     }
447
448     IShellLinkA_Release(sl);
449 }
450
451 static void test_load_save(void)
452 {
453     lnk_desc_t desc;
454     char mypath[MAX_PATH];
455     char mydir[MAX_PATH];
456     char* p;
457     DWORD r;
458
459     /* Save an empty .lnk file */
460     memset(&desc, 0, sizeof(desc));
461     create_lnk(lnkfile, &desc, 0);
462
463     /* It should come back as a bunch of empty strings */
464     desc.description="";
465     desc.workdir="";
466     desc.path="";
467     desc.arguments="";
468     desc.icon="";
469     check_lnk(lnkfile, &desc);
470
471
472     /* Point a .lnk file to nonexistent files */
473     desc.description="";
474     desc.workdir="c:\\Nonexitent\\work\\directory";
475     desc.path="c:\\nonexistent\\path";
476     desc.pidl=NULL;
477     desc.arguments="";
478     desc.showcmd=0;
479     desc.icon="c:\\nonexistent\\icon\\file";
480     desc.icon_id=1234;
481     desc.hotkey=0;
482     create_lnk(lnkfile, &desc, 0);
483     check_lnk(lnkfile, &desc);
484
485     r=GetModuleFileName(NULL, mypath, sizeof(mypath));
486     ok(r>=0 && r<sizeof(mypath), "GetModuleFileName failed (%ld)\n", r);
487     strcpy(mydir, mypath);
488     p=strrchr(mydir, '\\');
489     if (p)
490         *p='\0';
491
492
493     /* Overwrite the existing lnk file and point it to existing files */
494     desc.description="test 2";
495     desc.workdir=mydir;
496     desc.path=mypath;
497     desc.pidl=NULL;
498     desc.arguments="/option1 /option2 \"Some string\"";
499     desc.showcmd=SW_SHOWNORMAL;
500     desc.icon=mypath;
501     desc.icon_id=0;
502     desc.hotkey=0x1234;
503     create_lnk(lnkfile, &desc, 0);
504     check_lnk(lnkfile, &desc);
505
506     /* FIXME: Also test saving a .lnk pointing to a pidl that cannot be
507      * represented as a path.
508      */
509
510     /* DeleteFileW is not implemented on Win9x */
511     r=DeleteFileA("c:\\test.lnk");
512     ok(r, "failed to delete link (%ld)\n", GetLastError());
513 }
514
515 static void test_datalink(void)
516 {
517     static const WCHAR lnk[] = {
518       ':',':','{','9','d','b','1','1','8','6','f','-','4','0','d','f','-','1',
519       '1','d','1','-','a','a','8','c','-','0','0','c','0','4','f','b','6','7',
520       '8','6','3','}',':','{','0','0','0','1','0','4','0','9','-','7','8','E',
521       '1','-','1','1','D','2','-','B','6','0','F','-','0','0','6','0','9','7',
522       'C','9','9','8','E','7','}',':',':','{','9','d','b','1','1','8','6','e',
523       '-','4','0','d','f','-','1','1','d','1','-','a','a','8','c','-','0','0',
524       'c','0','4','f','b','6','7','8','6','3','}',':','2','6',',','!','!','g',
525       'x','s','f','(','N','g',']','q','F','`','H','{','L','s','A','C','C','E',
526       'S','S','F','i','l','e','s','>','p','l','T',']','j','I','{','j','f','(',
527       '=','1','&','L','[','-','8','1','-',']',':',':',0 };
528     static const WCHAR comp[] = {
529       '2','6',',','!','!','g','x','s','f','(','N','g',']','q','F','`','H','{',
530       'L','s','A','C','C','E','S','S','F','i','l','e','s','>','p','l','T',']',
531       'j','I','{','j','f','(','=','1','&','L','[','-','8','1','-',']',0 };
532     IShellLinkDataList *dl = NULL;
533     IShellLinkW *sl = NULL;
534     HRESULT r;
535     DWORD flags = 0;
536     EXP_DARWIN_LINK *dar;
537
538     r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
539                             &IID_IShellLinkW, (LPVOID*)&sl );
540     ok( r == S_OK, "no shelllink\n");
541     if (!sl)
542         return;
543
544     r = IShellLinkW_QueryInterface( sl, &IID_IShellLinkDataList, (LPVOID*) &dl );
545     ok(r == S_OK, "no datalink interface\n");
546
547     if (!dl)
548         return;
549
550     flags = 0;
551     r = dl->lpVtbl->GetFlags( dl, &flags );
552     ok( r == S_OK, "GetFlags failed\n");
553     ok( flags == 0, "GetFlags returned wrong flags\n");
554
555     dar = (void*)-1;
556     r = dl->lpVtbl->CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar );
557     ok( r == E_FAIL, "CopyDataBlock failed\n");
558     ok( dar == NULL, "should be null\n");
559
560     r = IShellLinkW_SetPath(sl, lnk);
561     ok(r == S_OK, "set path failed\n");
562
563     /*
564      * The following crashes:
565      * r = dl->lpVtbl->GetFlags( dl, NULL );
566      */
567
568     flags = 0;
569     r = dl->lpVtbl->GetFlags( dl, &flags );
570     ok( r == S_OK, "GetFlags failed\n");
571     ok( flags == (SLDF_HAS_DARWINID|SLDF_HAS_LOGO3ID),
572         "GetFlags returned wrong flags\n");
573
574     dar = NULL;
575     r = dl->lpVtbl->CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar );
576     ok( r == S_OK, "CopyDataBlock failed\n");
577
578     ok( dar && dar->dbh.dwSignature == EXP_DARWIN_ID_SIG, "signature wrong\n");
579     ok( dar && 0==lstrcmpW(dar->szwDarwinID, comp ), "signature wrong\n");
580
581     LocalFree( dar );
582
583     IUnknown_Release( dl );
584     IShellLinkW_Release( sl );
585 }
586
587 START_TEST(shelllink)
588 {
589     HRESULT r;
590
591     r = CoInitialize(NULL);
592     ok(SUCCEEDED(r), "CoInitialize failed (0x%08lx)\n", r);
593     if (!SUCCEEDED(r))
594         return;
595
596     test_get_set();
597     test_load_save();
598     test_datalink();
599
600     CoUninitialize();
601 }