2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for CShellLink
5 * PROGRAMMER: Andreas Maier
12 #include <ndk/rtlfuncs.h>
16 #include <shellutils.h>
18 /* Test IShellLink::SetPath with environment-variables, existing, non-existing, ...*/
24 /* Test 1 - hrGetPathX = IShellLink::GetPath(pathOutX, ... , flagsX); */
35 } TEST_SHELL_LINK_DEF
;
37 static TEST_SHELL_LINK_DEF linkTestList
[] =
41 L
"%comspec%", SLGP_SHORTPATH
, S_OK
, TRUE
,
42 L
"%comspec%", SLGP_RAWPATH
, S_OK
, FALSE
45 L
"%anyvar%", E_INVALIDARG
,
46 L
"", SLGP_SHORTPATH
, S_FALSE
, FALSE
,
47 L
"", SLGP_RAWPATH
, S_FALSE
, FALSE
50 L
"%anyvar%%comspec%", S_OK
,
51 L
"c:\\%anyvar%%comspec%", SLGP_SHORTPATH
, S_OK
, TRUE
,
52 L
"%anyvar%%comspec%", SLGP_RAWPATH
, S_OK
, FALSE
56 L
"%temp%", SLGP_SHORTPATH
, S_OK
, TRUE
,
57 L
"%temp%", SLGP_RAWPATH
, S_OK
, FALSE
61 L
"%systemroot%\\system32\\%shell%", SLGP_SHORTPATH
, S_OK
, TRUE
,
62 L
"%shell%", SLGP_RAWPATH
, S_OK
, FALSE
65 L
"u:\\anypath\\%anyvar%", S_OK
,
66 L
"u:\\anypath\\%anyvar%", SLGP_SHORTPATH
, S_OK
, TRUE
,
67 L
"u:\\anypath\\%anyvar%", SLGP_RAWPATH
, S_OK
, FALSE
71 L
"c:\\temp", SLGP_SHORTPATH
, S_OK
, FALSE
,
72 L
"c:\\temp", SLGP_RAWPATH
, S_OK
, FALSE
76 L
"%comspec%", SLGP_SHORTPATH
, S_OK
, TRUE
,
77 L
"%comspec%", SLGP_RAWPATH
, S_OK
, TRUE
80 L
"c:\\non-existent-path\\non-existent-file", S_OK
,
81 L
"c:\\non-existent-path\\non-existent-file", SLGP_SHORTPATH
, S_OK
, FALSE
,
82 L
"c:\\non-existent-path\\non-existent-file", SLGP_RAWPATH
, S_OK
, FALSE
85 L
"non-existent-file", E_INVALIDARG
,
86 L
"", SLGP_SHORTPATH
, S_FALSE
, FALSE
,
87 L
"", SLGP_RAWPATH
, S_FALSE
, FALSE
93 test_checklinkpath(UINT i
, TEST_SHELL_LINK_DEF
* testDef
)
95 static WCHAR evVar
[MAX_PATH
];
97 HRESULT hr
, expectedHr
;
98 WCHAR wPathOut
[MAX_PATH
];
100 PCWSTR expectedPathOut
;
105 hr
= CoCreateInstance(CLSID_ShellLink
,
107 CLSCTX_INPROC_SERVER
,
108 IID_PPV_ARG(IShellLinkW
, &psl
));
109 ok(hr
== S_OK
, "CoCreateInstance, hr = 0x%lx\n", hr
);
112 skip("Could not instantiate CShellLink\n");
116 hr
= psl
->SetPath(testDef
->pathIn
);
117 ok(hr
== testDef
->hrSetPath
, "IShellLink::SetPath(%d), got hr = 0x%lx, expected 0x%lx\n", i
, hr
, testDef
->hrSetPath
);
119 expectedPathOut
= NULL
;
120 for (i1
= 0; i1
<= 1; i1
++)
122 if (i1
== 1) /* Usually SLGP_RAWPATH */
124 flags
= testDef
->flags1
;
125 expandPathOut
= testDef
->expandPathOut1
;
126 expectedPathOut
= testDef
->pathOut1
;
127 expectedHr
= testDef
->hrGetPath1
;
129 else /* Usually SLGP_SHORTPATH */
131 flags
= testDef
->flags2
;
132 expandPathOut
= testDef
->expandPathOut2
;
133 expectedPathOut
= testDef
->pathOut2
;
134 expectedHr
= testDef
->hrGetPath2
;
137 /* Patch some variables */
140 ExpandEnvironmentStringsW(expectedPathOut
, evVar
, _countof(evVar
));
141 DPRINT("** %S **\n",evVar
);
142 expectedPathOut
= evVar
;
145 hr
= psl
->GetPath(wPathOut
, _countof(wPathOut
), NULL
, flags
);
147 "IShellLink::GetPath(%d), flags 0x%lx, got hr = 0x%lx, expected 0x%lx\n",
148 i
, flags
, hr
, expectedHr
);
149 ok(wcsicmp(wPathOut
, expectedPathOut
) == 0,
150 "IShellLink::GetPath(%d), flags 0x%lx, in %S, got %S, expected %S\n",
151 i
, flags
, testDef
->pathIn
, wPathOut
, expectedPathOut
);
163 /* Needed for test */
164 SetEnvironmentVariableW(L
"shell", L
"cmd.exe");
166 for (i
= 0; i
< _countof(linkTestList
); ++i
)
168 DPRINT("IShellLink-Test(%d): %S\n", i
, linkTestList
[i
].pathIn
);
169 test_checklinkpath(i
, &linkTestList
[i
]);
172 SetEnvironmentVariableW(L
"shell",NULL
);
177 TestDescription(void)
182 PCWSTR testDescription
= L
"This is a test description";
184 /* Test SetDescription */
185 hr
= CoCreateInstance(CLSID_ShellLink
,
187 CLSCTX_INPROC_SERVER
,
188 IID_PPV_ARG(IShellLinkW
, &psl
));
189 ok(hr
== S_OK
, "CoCreateInstance, hr = 0x%lx\n", hr
);
192 skip("Could not instantiate CShellLink\n");
196 memset(buffer
, 0x55, sizeof(buffer
));
197 hr
= psl
->GetDescription(buffer
, RTL_NUMBER_OF(buffer
));
198 ok(hr
== S_OK
, "IShellLink::GetDescription returned hr = 0x%lx\n", hr
);
199 ok(buffer
[0] == 0, "buffer[0] = %x\n", buffer
[0]);
200 ok(buffer
[1] == 0x5555, "buffer[1] = %x\n", buffer
[1]);
202 hr
= psl
->SetDescription(testDescription
);
203 ok(hr
== S_OK
, "IShellLink::SetDescription returned hr = 0x%lx\n", hr
);
205 memset(buffer
, 0x55, sizeof(buffer
));
206 hr
= psl
->GetDescription(buffer
, RTL_NUMBER_OF(buffer
));
207 ok(hr
== S_OK
, "IShellLink::GetDescription returned hr = 0x%lx\n", hr
);
208 ok(buffer
[wcslen(testDescription
)] == 0, "buffer[n] = %x\n", buffer
[wcslen(testDescription
)]);
209 ok(buffer
[wcslen(testDescription
) + 1] == 0x5555, "buffer[n+1] = %x\n", buffer
[wcslen(testDescription
) + 1]);
210 ok(!wcscmp(buffer
, testDescription
), "buffer = '%ls'\n", buffer
);
212 hr
= psl
->SetDescription(NULL
);
213 ok(hr
== S_OK
, "IShellLink::SetDescription returned hr = 0x%lx\n", hr
);
215 memset(buffer
, 0x55, sizeof(buffer
));
216 hr
= psl
->GetDescription(buffer
, RTL_NUMBER_OF(buffer
));
217 ok(hr
== S_OK
, "IShellLink::GetDescription returned hr = 0x%lx\n", hr
);
218 ok(buffer
[0] == 0, "buffer[0] = %x\n", buffer
[0]);
219 ok(buffer
[1] == 0x5555, "buffer[1] = %x\n", buffer
[1]);
225 /* Test IShellLink::Get/SetIconLocation and IExtractIcon::GetIconLocation */
230 /* Expected results */
231 HRESULT hrDefIcon
; // Return value for GIL_DEFAULTICON
232 HRESULT hrForShrt
; // Return value for GIL_FORSHORTCUT
233 /* Return values for GIL_FORSHELL */
239 static TEST_SHELL_ICON ShIconTests
[] =
241 /* Executable with icons */
242 {L
"%SystemRoot%\\system32\\cmd.exe", S_FALSE
, E_INVALIDARG
,
243 S_OK
, L
"%SystemRoot%\\system32\\cmd.exe", GIL_NOTFILENAME
| GIL_PERINSTANCE
},
245 /* Executable without icon */
246 {L
"%SystemRoot%\\system32\\autochk.exe", S_FALSE
, E_INVALIDARG
,
247 S_OK
, L
"%SystemRoot%\\system32\\autochk.exe", GIL_NOTFILENAME
| GIL_PERINSTANCE
},
250 {L
"%SystemRoot%\\system32\\shell32.dll", S_FALSE
, E_INVALIDARG
,
251 S_OK
, L
"%SystemRoot%\\system32\\shell32.dll", GIL_NOTFILENAME
| GIL_PERCLASS
},
253 /* Non-existing file */
254 {L
"c:\\non-existent-path\\non-existent-file.sdf", S_FALSE
, E_INVALIDARG
,
255 S_OK
, L
"c:\\non-existent-path\\non-existent-file.sdf", GIL_NOTFILENAME
| GIL_PERCLASS
},
260 test_iconlocation(UINT i
, TEST_SHELL_ICON
* testDef
)
267 WCHAR szPath
[MAX_PATH
];
269 hr
= CoCreateInstance(CLSID_ShellLink
,
271 CLSCTX_INPROC_SERVER
,
272 IID_PPV_ARG(IShellLinkW
, &psl
));
273 ok(hr
== S_OK
, "CoCreateInstance, hr = 0x%lx\n", hr
);
276 skip("Could not instantiate CShellLink\n");
280 /* Set the path to a file */
281 ExpandEnvironmentStringsW(testDef
->FilePath
, szPath
, _countof(szPath
));
282 hr
= psl
->SetPath(szPath
);
283 ok(hr
== S_OK
, "IShellLink::SetPath failed, hr = 0x%lx\n", hr
);
286 * This test shows that this does not imply that the icon is automatically
287 * set and be retrieved naively by a call to IShellLink::GetIconLocation.
290 wcscpy(szPath
, L
"garbage");
291 hr
= psl
->GetIconLocation(szPath
, _countof(szPath
), &iIcon
);
292 ok(hr
== S_OK
, "IShellLink::GetIconLocation(%d) failed, hr = 0x%lx\n", i
, hr
);
293 ok(*szPath
== L
'\0', "IShellLink::GetIconLocation(%d) returned '%S'\n", i
, szPath
);
294 ok(iIcon
== 0, "IShellLink::GetIconLocation(%d) returned %d\n", i
, iIcon
);
296 /* Try to grab the IExtractIconW interface */
297 hr
= psl
->QueryInterface(IID_PPV_ARG(IExtractIconW
, &pei
));
298 ok(hr
== S_OK
, "IShellLink::QueryInterface(IExtractIconW)(%d) failed, hr = 0x%lx\n", i
, hr
);
301 win_skip("No IExtractIconW interface\n");
306 iIcon
= wFlags
= 0xdeadbeef;
307 wcscpy(szPath
, L
"garbage");
308 hr
= pei
->GetIconLocation(GIL_DEFAULTICON
, szPath
, _countof(szPath
), &iIcon
, &wFlags
);
309 ok(hr
== testDef
->hrDefIcon
, "IShellLink::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i
, hr
, testDef
->hrDefIcon
);
310 ok(*szPath
== L
'\0', "IShellLink::GetIconLocation(%d) returned '%S'\n", i
, szPath
);
311 // ok(iIcon == 0, "IShellLink::GetIconLocation(%d) returned %d\n", i, iIcon);
313 iIcon
= wFlags
= 0xdeadbeef;
314 wcscpy(szPath
, L
"garbage");
315 hr
= pei
->GetIconLocation(GIL_FORSHORTCUT
, szPath
, _countof(szPath
), &iIcon
, &wFlags
);
316 ok(hr
== testDef
->hrForShrt
, "IShellLink::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i
, hr
, testDef
->hrForShrt
);
317 // Here, both szPath and iIcon are untouched...
319 iIcon
= wFlags
= 0xdeadbeef;
320 wcscpy(szPath
, L
"garbage");
321 hr
= pei
->GetIconLocation(GIL_FORSHELL
, szPath
, _countof(szPath
), &iIcon
, &wFlags
);
322 ok(hr
== testDef
->hrForShell
, "IShellLink::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i
, hr
, testDef
->hrForShell
);
323 ok(wFlags
== testDef
->Flags
, "IShellLink::GetIconLocation(%d) returned wFlags = 0x%x, expected 0x%x\n", i
, wFlags
, testDef
->Flags
);
324 // ok(*szPath == L'\0', "IShellLink::GetIconLocation returned '%S'\n", szPath);
325 // ok(iIcon == 0, "IShellLink::GetIconLocation returned %d\n", iIcon);
326 // ok(FALSE, "hr = 0x%lx, szPath = '%S', iIcon = %d, wFlags = %d\n", hr, szPath, iIcon, wFlags);
328 /* Release the interfaces */
335 TestIconLocation(void)
339 for (i
= 0; i
< _countof(ShIconTests
); ++i
)
341 test_iconlocation(i
, &ShIconTests
[i
]);
345 START_TEST(CShellLink
)
347 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);