2 * Unit tests for IShellDispatch
4 * Copyright 2010 Alexander Morozov for Etersoft
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define EXPECT_HR(hr,hr_exp) \
27 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
29 static const WCHAR winetestW
[] = {'w','i','n','e','t','e','s','t',0};
31 static HRESULT (WINAPI
*pSHGetFolderPathW
)(HWND
, int, HANDLE
, DWORD
, LPWSTR
);
32 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
33 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
34 static DWORD (WINAPI
*pGetLongPathNameW
)(LPCWSTR
, LPWSTR
, DWORD
);
36 /* Updated Windows 7 has a new IShellDispatch6 in its typelib */
37 DEFINE_GUID(IID_IWin7ShellDispatch6
, 0x34936ba1, 0x67ad, 0x4c41, 0x99,0xb8, 0x8c,0x12,0xdf,0xf1,0xe9,0x74);
39 static void init_function_pointers(void)
41 HMODULE hshell32
, hkernel32
;
43 hshell32
= GetModuleHandleA("shell32.dll");
44 hkernel32
= GetModuleHandleA("kernel32.dll");
45 pSHGetFolderPathW
= (void*)GetProcAddress(hshell32
, "SHGetFolderPathW");
46 pSHGetNameFromIDList
= (void*)GetProcAddress(hshell32
, "SHGetNameFromIDList");
47 pSHGetSpecialFolderLocation
= (void*)GetProcAddress(hshell32
,
48 "SHGetSpecialFolderLocation");
49 pGetLongPathNameW
= (void*)GetProcAddress(hkernel32
, "GetLongPathNameW");
52 static void test_namespace(void)
54 static const ShellSpecialFolderConstants special_folders
[] =
96 static const WCHAR backslashW
[] = {'\\',0};
97 static const WCHAR clsidW
[] = {
98 ':',':','{','6','4','5','F','F','0','4','0','-','5','0','8','1','-',
99 '1','0','1','B','-','9','F','0','8','-',
100 '0','0','A','A','0','0','2','F','9','5','4','E','}',0};
102 static WCHAR tempW
[MAX_PATH
], curW
[MAX_PATH
];
103 WCHAR
*long_pathW
= NULL
;
110 BSTR title
, item_path
;
113 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
114 &IID_IShellDispatch
, (LPVOID
*)&sd
);
115 if (r
== REGDB_E_CLASSNOTREG
) /* NT4 */
117 win_skip("skipping IShellDispatch tests\n");
120 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08x\n", r
);
125 folder
= (void*)0xdeadbeef;
126 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
127 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
128 ok(folder
== NULL
, "expected NULL, got %p\n", folder
);
130 /* test valid folder ids */
131 for (i
= 0; i
< sizeof(special_folders
)/sizeof(special_folders
[0]); i
++)
134 V_I4(&var
) = special_folders
[i
];
135 folder
= (void*)0xdeadbeef;
136 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
137 if (special_folders
[i
] == ssfALTSTARTUP
|| special_folders
[i
] == ssfCOMMONALTSTARTUP
)
138 ok(r
== S_OK
|| broken(r
== S_FALSE
) /* winxp */, "Failed to get folder for index %#x, got %08x\n", special_folders
[i
], r
);
140 ok(r
== S_OK
, "Failed to get folder for index %#x, got %08x\n", special_folders
[i
], r
);
142 Folder_Release(folder
);
147 folder
= (void*)0xdeadbeef;
148 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
150 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
151 ok(folder
== NULL
, "got %p\n", folder
);
153 Folder_Release(folder
);
156 V_I4(&var
) = ssfPROGRAMFILES
;
157 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
159 broken(r
== S_FALSE
), /* NT4 */
160 "IShellDispatch::NameSpace failed: %08x\n", r
);
163 static WCHAR path
[MAX_PATH
];
165 if (pSHGetFolderPathW
)
167 r
= pSHGetFolderPathW(NULL
, CSIDL_PROGRAM_FILES
, NULL
,
168 SHGFP_TYPE_CURRENT
, path
);
169 ok(r
== S_OK
, "SHGetFolderPath failed: %08x\n", r
);
171 r
= Folder_get_Title(folder
, &title
);
173 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
176 /* On Win2000-2003 title is equal to program files directory name in
177 HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir.
178 On newer Windows it seems constant and is not changed
179 if the program files directory name is changed */
180 if (pSHGetSpecialFolderLocation
&& pSHGetNameFromIDList
)
185 r
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidl
);
186 ok(r
== S_OK
, "SHGetSpecialFolderLocation failed: %08x\n", r
);
187 r
= pSHGetNameFromIDList(pidl
, SIGDN_NORMALDISPLAY
, &name
);
188 ok(r
== S_OK
, "SHGetNameFromIDList failed: %08x\n", r
);
190 ok(!lstrcmpW(title
, name
), "expected %s, got %s\n",
191 wine_dbgstr_w(name
), wine_dbgstr_w(title
));
195 else if (pSHGetFolderPathW
)
199 p
= path
+ lstrlenW(path
);
200 while (path
< p
&& *(p
- 1) != '\\')
202 ok(!lstrcmpiW(title
, p
), "expected %s, got %s\n",
203 wine_dbgstr_w(p
), wine_dbgstr_w(title
));
205 else skip("skipping Folder::get_Title test\n");
206 SysFreeString(title
);
208 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
209 ok(r
== S_OK
, "Folder::QueryInterface failed: %08x\n", r
);
212 r
= Folder2_get_Self(folder2
, &item
);
213 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
216 r
= FolderItem_get_Path(item
, &item_path
);
217 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
218 if (pSHGetFolderPathW
)
219 ok(!lstrcmpiW(item_path
, path
), "expected %s, got %s\n",
220 wine_dbgstr_w(path
), wine_dbgstr_w(item_path
));
221 SysFreeString(item_path
);
222 FolderItem_Release(item
);
224 Folder2_Release(folder2
);
226 Folder_Release(folder
);
230 V_I4(&var
) = ssfBITBUCKET
;
231 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
233 broken(r
== S_FALSE
), /* NT4 */
234 "IShellDispatch::NameSpace failed: %08x\n", r
);
237 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
239 broken(r
== E_NOINTERFACE
), /* NT4 */
240 "Folder::QueryInterface failed: %08x\n", r
);
243 r
= Folder2_get_Self(folder2
, &item
);
244 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
247 r
= FolderItem_get_Path(item
, &item_path
);
249 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
251 ok(!lstrcmpW(item_path
, clsidW
), "expected %s, got %s\n",
252 wine_dbgstr_w(clsidW
), wine_dbgstr_w(item_path
));
253 SysFreeString(item_path
);
254 FolderItem_Release(item
);
256 Folder2_Release(folder2
);
258 Folder_Release(folder
);
261 GetTempPathW(MAX_PATH
, tempW
);
262 GetCurrentDirectoryW(MAX_PATH
, curW
);
263 SetCurrentDirectoryW(tempW
);
264 CreateDirectoryW(winetestW
, NULL
);
265 V_VT(&var
) = VT_BSTR
;
266 V_BSTR(&var
) = SysAllocString(winetestW
);
267 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
268 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
269 SysFreeString(V_BSTR(&var
));
271 GetFullPathNameW(winetestW
, MAX_PATH
, tempW
, NULL
);
272 if (pGetLongPathNameW
)
274 len
= pGetLongPathNameW(tempW
, NULL
, 0);
275 long_pathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
277 pGetLongPathNameW(tempW
, long_pathW
, len
);
279 V_VT(&var
) = VT_BSTR
;
280 V_BSTR(&var
) = SysAllocString(tempW
);
281 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
282 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
285 r
= Folder_get_Title(folder
, &title
);
286 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
289 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
290 wine_dbgstr_w(title
));
291 SysFreeString(title
);
293 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
295 broken(r
== E_NOINTERFACE
), /* NT4 */
296 "Folder::QueryInterface failed: %08x\n", r
);
299 r
= Folder2_get_Self(folder2
, &item
);
300 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
303 r
= FolderItem_get_Path(item
, &item_path
);
304 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
306 ok(!lstrcmpW(item_path
, long_pathW
),
307 "expected %s, got %s\n", wine_dbgstr_w(long_pathW
),
308 wine_dbgstr_w(item_path
));
309 SysFreeString(item_path
);
310 FolderItem_Release(item
);
312 Folder2_Release(folder2
);
314 Folder_Release(folder
);
316 SysFreeString(V_BSTR(&var
));
318 len
= lstrlenW(tempW
);
319 if (len
< MAX_PATH
- 1)
321 lstrcatW(tempW
, backslashW
);
322 V_VT(&var
) = VT_BSTR
;
323 V_BSTR(&var
) = SysAllocString(tempW
);
324 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
325 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
328 r
= Folder_get_Title(folder
, &title
);
329 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
332 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
333 wine_dbgstr_w(title
));
334 SysFreeString(title
);
336 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
338 broken(r
== E_NOINTERFACE
), /* NT4 */
339 "Folder::QueryInterface failed: %08x\n", r
);
342 r
= Folder2_get_Self(folder2
, &item
);
343 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
346 r
= FolderItem_get_Path(item
, &item_path
);
347 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
349 ok(!lstrcmpW(item_path
, long_pathW
),
350 "expected %s, got %s\n", wine_dbgstr_w(long_pathW
),
351 wine_dbgstr_w(item_path
));
352 SysFreeString(item_path
);
353 FolderItem_Release(item
);
355 Folder2_Release(folder2
);
357 Folder_Release(folder
);
359 SysFreeString(V_BSTR(&var
));
362 HeapFree(GetProcessHeap(), 0, long_pathW
);
363 RemoveDirectoryW(winetestW
);
364 SetCurrentDirectoryW(curW
);
365 IShellDispatch_Release(sd
);
368 static void test_items(void)
370 WCHAR wstr
[MAX_PATH
], orig_dir
[MAX_PATH
];
372 IShellDispatch
*sd
= NULL
;
373 Folder
*folder
= NULL
;
374 FolderItems
*items
= NULL
;
375 FolderItems2
*items2
= NULL
;
376 FolderItems3
*items3
= NULL
;
377 FolderItem
*item
= (FolderItem
*)0xdeadbeef;
378 IDispatch
*disp
= NULL
;
379 IUnknown
*unk
= NULL
;
380 FolderItemVerbs
*verbs
= (FolderItemVerbs
*)0xdeadbeef;
384 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void**)&sd
);
385 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08x\n", r
);
386 ok(!!sd
, "sd is null\n");
388 GetTempPathW(MAX_PATH
, wstr
);
389 GetCurrentDirectoryW(MAX_PATH
, orig_dir
);
390 SetCurrentDirectoryW(wstr
);
391 CreateDirectoryW(winetestW
, NULL
);
392 GetFullPathNameW(winetestW
, MAX_PATH
, wstr
, NULL
);
393 V_VT(&var
) = VT_BSTR
;
394 V_BSTR(&var
) = SysAllocString(wstr
);
395 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
396 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
397 ok(!!folder
, "folder is null\n");
398 SysFreeString(V_BSTR(&var
));
399 IShellDispatch_Release(sd
);
400 SetCurrentDirectoryW(winetestW
);
402 r
= Folder_Items(folder
, &items
);
403 ok(r
== S_OK
, "Folder::Items failed: %08x\n", r
);
404 ok(!!items
, "items is null\n");
405 r
= FolderItems_QueryInterface(items
, &IID_FolderItems2
, (void**)&items2
);
406 ok(r
== S_OK
|| broken(r
== E_NOINTERFACE
) /* xp and later */, "FolderItems::QueryInterface failed: %08x\n", r
);
407 ok(!!items2
|| broken(!items2
) /* xp and later */, "items2 is null\n");
408 r
= FolderItems_QueryInterface(items
, &IID_FolderItems3
, (void**)&items3
);
409 ok(r
== S_OK
, "FolderItems::QueryInterface failed: %08x\n", r
);
410 ok(!!items3
, "items3 is null\n");
411 Folder_Release(folder
);
413 if (0) /* crashes on all versions of Windows */
414 r
= FolderItems_get_Count(items
, NULL
);
416 r
= FolderItems_get_Count(items
, &lcount
);
417 ok(r
== S_OK
, "FolderItems::get_Count failed: %08x\n", r
);
418 ok(!lcount
, "expected 0 files, got %d\n", lcount
);
423 if (0) /* crashes on all versions of Windows */
424 r
= FolderItems_Item(items
, var
, NULL
);
426 r
= FolderItems_Item(items
, var
, &item
);
428 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
429 ok(!item
, "item is not null\n");
431 if (0) /* crashes on xp */
433 r
= FolderItems_get_Application(items
, NULL
);
434 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
437 r
= FolderItems_get_Application(items
, &disp
);
439 ok(r
== S_OK
, "FolderItems::get_Application failed: %08x\n", r
);
441 ok(!!disp
, "disp is null\n");
442 if (disp
) IDispatch_Release(disp
);
444 if (0) /* crashes on xp */
446 r
= FolderItems_get_Parent(items
, NULL
);
447 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
450 disp
= (IDispatch
*)0xdeadbeef;
451 r
= FolderItems_get_Parent(items
, &disp
);
452 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
453 ok(!disp
, "disp is not null\n");
455 if (0) /* crashes on xp */
457 r
= FolderItems__NewEnum(items
, NULL
);
458 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
461 r
= FolderItems__NewEnum(items
, &unk
);
463 ok(r
== S_OK
, "FolderItems::_NewEnum failed: %08x\n", r
);
465 ok(!!unk
, "unk is null\n");
466 if (unk
) IUnknown_Release(unk
);
470 r
= FolderItems3_Filter(items3
, 0, NULL
);
472 ok(r
== S_OK
, "expected S_OK, got %08x\n", r
);
474 if (0) /* crashes on xp */
476 r
= FolderItems3_get_Verbs(items3
, NULL
);
477 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
480 r
= FolderItems3_get_Verbs(items3
, &verbs
);
482 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
483 ok(!verbs
, "verbs is not null\n");
486 GetTempPathW(MAX_PATH
, wstr
);
487 SetCurrentDirectoryW(wstr
);
488 RemoveDirectoryW(winetestW
);
489 SetCurrentDirectoryW(orig_dir
);
491 FolderItems_Release(items
);
492 if (items2
) FolderItems2_Release(items2
);
493 if (items3
) FolderItems3_Release(items3
);
496 static void test_service(void)
498 static const WCHAR spooler
[] = {'S','p','o','o','l','e','r',0};
499 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
500 SERVICE_STATUS_PROCESS status
;
501 SC_HANDLE scm
, service
;
508 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
509 &IID_IShellDispatch2
, (void**)&sd
);
512 win_skip("IShellDispatch2 not supported\n");
518 hr
= IShellDispatch2_IsServiceRunning(sd
, NULL
, &v
);
519 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
520 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
523 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
524 service
= OpenServiceW(scm
, spooler
, SERVICE_QUERY_STATUS
);
525 QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
, sizeof(SERVICE_STATUS_PROCESS
), &dummy
);
526 CloseServiceHandle(service
);
527 CloseServiceHandle(scm
);
529 /* service should exist */
530 name
= SysAllocString(spooler
);
532 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
534 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
535 if (status
.dwCurrentState
== SERVICE_RUNNING
)
536 ok(V_BOOL(&v
) == VARIANT_TRUE
, "got %d\n", V_BOOL(&v
));
538 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
541 /* service doesn't exist */
542 name
= SysAllocString(dummyW
);
544 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
546 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
547 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
550 IShellDispatch2_Release(sd
);
553 static void test_dispatch_typeinfo(IDispatch
*disp
, REFIID
*riid
)
561 hr
= IDispatch_GetTypeInfoCount(disp
, &count
);
562 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
563 ok(count
== 1, "got %u\n", count
);
565 hr
= IDispatch_GetTypeInfo(disp
, 0, LOCALE_SYSTEM_DEFAULT
, &typeinfo
);
566 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
568 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
569 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
570 while (!IsEqualGUID(*riid
, &IID_NULL
)) {
571 if (IsEqualGUID(&typeattr
->guid
, *riid
))
575 ok(IsEqualGUID(&typeattr
->guid
, *riid
), "unexpected type guid %s\n", wine_dbgstr_guid(&typeattr
->guid
));
577 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
578 ITypeInfo_Release(typeinfo
);
581 static void test_ShellFolderViewDual(void)
583 static const IID
*shelldisp_riids
[] = {
584 &IID_IShellDispatch6
,
585 &IID_IShellDispatch5
,
586 &IID_IShellDispatch4
,
587 &IID_IShellDispatch2
,
588 &IID_IWin7ShellDispatch6
,
591 IShellFolderViewDual
*viewdual
;
592 IShellFolder
*desktop
, *tmpdir
;
593 IShellView
*view
, *view2
;
594 IDispatch
*disp
, *disp2
;
595 WCHAR pathW
[MAX_PATH
];
599 /* IShellFolderViewDual is not an IShellView extension */
600 hr
= SHGetDesktopFolder(&desktop
);
601 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
603 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
604 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
606 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
607 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
609 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
612 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp2
);
613 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
614 ok(disp2
== disp
, "got %p, %p\n", disp2
, disp
);
615 IDispatch_Release(disp2
);
617 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
618 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
619 ok(disp
== (IDispatch
*)viewdual
, "got %p, expected %p\n", viewdual
, disp
);
621 hr
= IShellFolderViewDual_QueryInterface(viewdual
, &IID_IShellView
, (void**)&view2
);
622 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
624 /* get_Application() */
626 if (0) /* crashes on pre-vista */ {
627 hr
= IShellFolderViewDual_get_Application(viewdual
, NULL
);
628 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
630 hr
= IShellFolderViewDual_get_Application(viewdual
, &disp2
);
631 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
632 ok(disp2
!= (IDispatch
*)viewdual
, "got %p, %p\n", disp2
, viewdual
);
633 test_dispatch_typeinfo(disp2
, shelldisp_riids
);
634 IDispatch_Release(disp2
);
636 IShellFolderViewDual_Release(viewdual
);
637 IDispatch_Release(disp
);
639 disp
= (void*)0xdeadbeef;
640 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IShellFolderViewDual
, (void**)&disp
);
641 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
) /* win2k */, "got 0x%08x\n", hr
);
642 ok(disp
== NULL
, "got %p\n", disp
);
643 IShellView_Release(view
);
645 /* Try with some other folder, that's not a desktop */
646 GetTempPathW(sizeof(pathW
)/sizeof(pathW
[0]), pathW
);
647 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, pathW
, NULL
, &pidl
, NULL
);
648 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
650 hr
= IShellFolder_BindToObject(desktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&tmpdir
);
651 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
654 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
655 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
657 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
658 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
660 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
661 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
662 IDispatch_Release(disp
);
663 IShellView_Release(view
);
665 IShellFolder_Release(tmpdir
);
666 IShellFolder_Release(desktop
);
669 static void test_ShellWindows(void)
671 IShellWindows
*shellwindows
;
672 LONG cookie
, cookie2
, ret
;
678 hr
= CoCreateInstance(&CLSID_ShellWindows
, NULL
, CLSCTX_LOCAL_SERVER
,
679 &IID_IShellWindows
, (void**)&shellwindows
);
680 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
681 /* TODO: remove when explorer startup with clean prefix is fixed */
685 if (0) /* NULL out argument - currently crashes on Wine */ {
686 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, NULL
);
687 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "got 0x%08x\n", hr
);
689 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, &cookie
);
691 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
693 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
695 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
697 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
699 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
701 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
702 0, 0, 50, 14, 0, 0, 0, NULL
);
703 ok(hwnd
!= NULL
, "got %p, error %d\n", hwnd
, GetLastError());
706 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie
);
708 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
709 ok(cookie
!= 0, "got %d\n", cookie
);
712 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie2
);
714 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
715 ok(cookie2
!= 0 && cookie2
!= cookie
, "got %d\n", cookie2
);
717 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
719 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
720 hr
= IShellWindows_Revoke(shellwindows
, cookie2
);
722 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
724 hr
= IShellWindows_Revoke(shellwindows
, 0);
726 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
728 /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
730 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_DESKTOP
, &cookie
);
732 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
733 ok(cookie
!= 0, "got %d\n", cookie
);
735 disp
= (void*)0xdeadbeef;
738 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, SWFO_NEEDDISPATCH
, &disp
);
739 ok(hr
== S_OK
|| broken(hr
== S_FALSE
), "got 0x%08x\n", hr
);
740 if (hr
== S_FALSE
) /* winxp and earlier */ {
741 win_skip("SWC_DESKTOP is not supported, some tests will be skipped.\n");
742 /* older versions allowed to regiser SWC_DESKTOP and access it with FindWindowSW */
743 ok(disp
== NULL
, "got %p\n", disp
);
744 ok(ret
== 0, "got %d\n", ret
);
747 static const IID
*browser_riids
[] = {
752 static const IID
*viewdual_riids
[] = {
753 &IID_IShellFolderViewDual3
,
757 IShellFolderViewDual
*view
;
758 IShellBrowser
*sb
, *sb2
;
759 IServiceProvider
*sp
;
760 IDispatch
*doc
, *app
;
765 ok(disp
!= NULL
, "got %p\n", disp
);
766 ok(ret
!= HandleToUlong(hwnd
), "got %d\n", ret
);
768 /* IDispatch-related tests */
769 test_dispatch_typeinfo(disp
, browser_riids
);
772 hr
= IDispatch_QueryInterface(disp
, &IID_IWebBrowser2
, (void**)&wb
);
773 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
775 hr
= IWebBrowser2_Refresh(wb
);
777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
779 hr
= IWebBrowser2_get_Application(wb
, &app
);
780 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
781 ok(disp
== app
, "got %p, %p\n", app
, disp
);
782 IDispatch_Release(app
);
784 hr
= IWebBrowser2_get_Document(wb
, &doc
);
786 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
788 test_dispatch_typeinfo(doc
, viewdual_riids
);
790 IWebBrowser2_Release(wb
);
792 /* IServiceProvider */
793 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&view
);
794 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
796 hr
= IDispatch_QueryInterface(disp
, &IID_IServiceProvider
, (void**)&sp
);
797 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
799 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb
);
800 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
802 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb2
);
803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
804 ok(sb
== sb2
, "got %p, %p\n", sb
, sb2
);
806 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IOleWindow
, (void**)&unk
);
807 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
808 IUnknown_Release(unk
);
810 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IExplorerBrowser
, (void**)&unk
);
811 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
813 hr
= IShellBrowser_QueryInterface(sb
, &IID_IExplorerBrowser
, (void**)&unk
);
814 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
816 hr
= IShellBrowser_QueryInterface(sb
, &IID_IWebBrowser2
, (void**)&unk
);
817 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
819 hr
= IShellBrowser_QueryInterface(sb
, &IID_IDispatch
, (void**)&unk
);
820 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
822 hr
= IShellBrowser_QueryActiveShellView(sb
, &sv
);
823 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
824 IShellView_Release(sv
);
826 IShellBrowser_Release(sb2
);
827 IShellBrowser_Release(sb
);
829 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IUnknown
, (void**)&unk
);
830 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
832 hr
= IUnknown_QueryInterface(unk
, &IID_IShellBrowser
, (void**)&sb2
);
833 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
834 IShellBrowser_Release(sb2
);
835 IUnknown_Release(unk
);
837 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellView
, (void**)&sv
);
838 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
840 IServiceProvider_Release(sp
);
841 IDispatch_Release(disp
);
844 disp
= (void*)0xdeadbeef;
847 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, 0, &disp
);
848 ok(hr
== S_OK
|| broken(hr
== S_FALSE
) /* winxp */, "got 0x%08x\n", hr
);
849 ok(disp
== NULL
, "got %p\n", disp
);
850 ok(ret
!= HandleToUlong(hwnd
), "got %d\n", ret
);
852 disp
= (void*)0xdeadbeef;
857 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_BROWSER
, &ret
, SWFO_COOKIEPASSED
, &disp
);
859 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
860 ok(disp
== NULL
, "got %p\n", disp
);
861 ok(ret
== 0, "got %d\n", ret
);
863 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
865 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
867 IShellWindows_Release(shellwindows
);
870 static void test_ParseName(void)
872 static const WCHAR cadabraW
[] = {'c','a','d','a','b','r','a',0};
873 WCHAR pathW
[MAX_PATH
];
881 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
882 &IID_IShellDispatch
, (void**)&sd
);
883 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
885 GetTempPathW(sizeof(pathW
)/sizeof(pathW
[0]), pathW
);
887 V_BSTR(&v
) = SysAllocString(pathW
);
888 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
892 item
= (void*)0xdeadbeef;
893 hr
= Folder_ParseName(folder
, NULL
, &item
);
894 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08x\n", hr
);
895 ok(item
== NULL
, "got %p\n", item
);
898 str
= SysAllocStringLen(NULL
, 0);
899 item
= (void*)0xdeadbeef;
900 hr
= Folder_ParseName(folder
, str
, &item
);
901 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08x\n", hr
);
902 ok(item
== NULL
, "got %p\n", item
);
905 /* path doesn't exist */
906 str
= SysAllocString(cadabraW
);
907 item
= (void*)0xdeadbeef;
908 hr
= Folder_ParseName(folder
, str
, &item
);
909 ok(hr
== S_FALSE
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* win2k */,
911 ok(item
== NULL
, "got %p\n", item
);
914 lstrcatW(pathW
, cadabraW
);
915 CreateDirectoryW(pathW
, NULL
);
917 str
= SysAllocString(cadabraW
);
919 hr
= Folder_ParseName(folder
, str
, &item
);
920 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
921 ok(item
!= NULL
, "got %p\n", item
);
924 hr
= FolderItem_get_Path(item
, &str
);
925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
926 ok(str
[0] != 0, "path %s\n", wine_dbgstr_w(str
));
929 RemoveDirectoryW(pathW
);
930 FolderItem_Release(item
);
931 Folder_Release(folder
);
932 IShellDispatch_Release(sd
);
935 static void test_Verbs(void)
937 FolderItemVerbs
*verbs
;
938 WCHAR pathW
[MAX_PATH
];
939 FolderItemVerb
*verb
;
949 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
950 &IID_IShellDispatch
, (void**)&sd
);
951 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
953 GetTempPathW(sizeof(pathW
)/sizeof(pathW
[0]), pathW
);
955 V_BSTR(&v
) = SysAllocString(pathW
);
956 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
957 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
960 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
961 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
962 Folder_Release(folder
);
964 hr
= Folder2_get_Self(folder2
, &item
);
965 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
966 Folder2_Release(folder2
);
968 if (0) { /* crashes on some systems */
969 hr
= FolderItem_Verbs(item
, NULL
);
970 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
972 hr
= FolderItem_Verbs(item
, &verbs
);
973 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
975 if (0) { /* crashes on winxp/win2k3 */
976 hr
= FolderItemVerbs_get_Count(verbs
, NULL
);
977 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
980 hr
= FolderItemVerbs_get_Count(verbs
, &count
);
981 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
982 ok(count
> 0, "got count %d\n", count
);
984 if (0) { /* crashes on winxp/win2k3 */
987 hr
= FolderItemVerbs_Item(verbs
, v
, NULL
);
988 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
990 /* there's always one item more, so you can access [0,count],
991 instead of actual [0,count) */
992 for (i
= 0; i
<= count
; i
++) {
995 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
996 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
997 hr
= FolderItemVerb_get_Name(verb
, &str
);
998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
999 ok(str
!= NULL
, "%d: name %s\n", i
, wine_dbgstr_w(str
));
1001 ok(str
[0] == 0, "%d: got teminating item %s\n", i
, wine_dbgstr_w(str
));
1004 FolderItemVerb_Release(verb
);
1010 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1012 ok(verb
== NULL
, "got %p\n", verb
);
1014 FolderItemVerbs_Release(verbs
);
1015 FolderItem_Release(item
);
1016 IShellDispatch_Release(sd
);
1019 static void test_ShellExecute(void)
1022 IShellDispatch2
*sd
;
1024 VARIANT args
, dir
, op
, show
;
1026 static const WCHAR regW
[] = {'r','e','g',0};
1028 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1029 &IID_IShellDispatch2
, (void**)&sd
);
1032 win_skip("IShellDispatch2 not supported\n");
1041 V_VT(&show
) = VT_I4
;
1044 name
= SysAllocString(regW
);
1046 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1047 ok(hr
== S_OK
, "ShellExecute failed: %08x\n", hr
);
1049 /* test invalid value for show */
1050 V_VT(&show
) = VT_BSTR
;
1051 V_BSTR(&show
) = name
;
1053 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1054 ok(hr
== S_OK
, "ShellExecute failed: %08x\n", hr
);
1056 SysFreeString(name
);
1059 START_TEST(shelldispatch
)
1063 r
= CoInitialize(NULL
);
1064 ok(SUCCEEDED(r
), "CoInitialize failed: %08x\n", r
);
1068 init_function_pointers();
1072 test_ShellFolderViewDual();
1073 test_ShellWindows();
1076 test_ShellExecute();