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
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
28 #include "wine/test.h"
32 #define EXPECT_HR(hr,hr_exp) \
33 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
35 static const WCHAR winetestW
[] = {'w','i','n','e','t','e','s','t',0};
37 static HRESULT (WINAPI
*pSHGetFolderPathW
)(HWND
, int, HANDLE
, DWORD
, LPWSTR
);
38 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
39 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
40 static DWORD (WINAPI
*pGetLongPathNameW
)(LPCWSTR
, LPWSTR
, DWORD
);
42 /* Updated Windows 7 has a new IShellDispatch6 in its typelib */
43 DEFINE_GUID(IID_IWin7ShellDispatch6
, 0x34936ba1, 0x67ad, 0x4c41, 0x99,0xb8, 0x8c,0x12,0xdf,0xf1,0xe9,0x74);
45 static void init_function_pointers(void)
47 HMODULE hshell32
, hkernel32
;
49 hshell32
= GetModuleHandleA("shell32.dll");
50 hkernel32
= GetModuleHandleA("kernel32.dll");
51 pSHGetFolderPathW
= (void*)GetProcAddress(hshell32
, "SHGetFolderPathW");
52 pSHGetNameFromIDList
= (void*)GetProcAddress(hshell32
, "SHGetNameFromIDList");
53 pSHGetSpecialFolderLocation
= (void*)GetProcAddress(hshell32
,
54 "SHGetSpecialFolderLocation");
55 pGetLongPathNameW
= (void*)GetProcAddress(hkernel32
, "GetLongPathNameW");
58 static void test_namespace(void)
60 static const ShellSpecialFolderConstants special_folders
[] =
102 static const WCHAR backslashW
[] = {'\\',0};
103 static const WCHAR clsidW
[] = {
104 ':',':','{','6','4','5','F','F','0','4','0','-','5','0','8','1','-',
105 '1','0','1','B','-','9','F','0','8','-',
106 '0','0','A','A','0','0','2','F','9','5','4','E','}',0};
108 static WCHAR tempW
[MAX_PATH
], curW
[MAX_PATH
];
109 WCHAR
*long_pathW
= NULL
;
116 BSTR title
, item_path
;
119 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
120 &IID_IShellDispatch
, (LPVOID
*)&sd
);
121 if (r
== REGDB_E_CLASSNOTREG
) /* NT4 */
123 win_skip("skipping IShellDispatch tests\n");
126 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08x\n", r
);
131 folder
= (void*)0xdeadbeef;
132 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
133 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
134 ok(folder
== NULL
, "expected NULL, got %p\n", folder
);
136 /* test valid folder ids */
137 for (i
= 0; i
< sizeof(special_folders
)/sizeof(special_folders
[0]); i
++)
140 V_I4(&var
) = special_folders
[i
];
141 folder
= (void*)0xdeadbeef;
142 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
143 if (special_folders
[i
] == ssfALTSTARTUP
|| special_folders
[i
] == ssfCOMMONALTSTARTUP
)
144 ok(r
== S_OK
|| broken(r
== S_FALSE
) /* winxp */, "Failed to get folder for index %#x, got %08x\n", special_folders
[i
], r
);
146 ok(r
== S_OK
, "Failed to get folder for index %#x, got %08x\n", special_folders
[i
], r
);
148 Folder_Release(folder
);
153 folder
= (void*)0xdeadbeef;
154 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
156 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
157 ok(folder
== NULL
, "got %p\n", folder
);
159 Folder_Release(folder
);
162 V_I4(&var
) = ssfPROGRAMFILES
;
163 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
165 broken(r
== S_FALSE
), /* NT4 */
166 "IShellDispatch::NameSpace failed: %08x\n", r
);
169 static WCHAR path
[MAX_PATH
];
171 if (pSHGetFolderPathW
)
173 r
= pSHGetFolderPathW(NULL
, CSIDL_PROGRAM_FILES
, NULL
,
174 SHGFP_TYPE_CURRENT
, path
);
175 ok(r
== S_OK
, "SHGetFolderPath failed: %08x\n", r
);
177 r
= Folder_get_Title(folder
, &title
);
179 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
182 /* On Win2000-2003 title is equal to program files directory name in
183 HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir.
184 On newer Windows it seems constant and is not changed
185 if the program files directory name is changed */
186 if (pSHGetSpecialFolderLocation
&& pSHGetNameFromIDList
)
191 r
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidl
);
192 ok(r
== S_OK
, "SHGetSpecialFolderLocation failed: %08x\n", r
);
193 r
= pSHGetNameFromIDList(pidl
, SIGDN_NORMALDISPLAY
, &name
);
194 ok(r
== S_OK
, "SHGetNameFromIDList failed: %08x\n", r
);
196 ok(!lstrcmpW(title
, name
), "expected %s, got %s\n",
197 wine_dbgstr_w(name
), wine_dbgstr_w(title
));
201 else if (pSHGetFolderPathW
)
205 p
= path
+ lstrlenW(path
);
206 while (path
< p
&& *(p
- 1) != '\\')
208 ok(!lstrcmpiW(title
, p
), "expected %s, got %s\n",
209 wine_dbgstr_w(p
), wine_dbgstr_w(title
));
211 else skip("skipping Folder::get_Title test\n");
212 SysFreeString(title
);
214 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
215 ok(r
== S_OK
, "Folder::QueryInterface failed: %08x\n", r
);
218 r
= Folder2_get_Self(folder2
, &item
);
219 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
222 r
= FolderItem_get_Path(item
, &item_path
);
223 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
224 if (pSHGetFolderPathW
)
225 ok(!lstrcmpiW(item_path
, path
), "expected %s, got %s\n",
226 wine_dbgstr_w(path
), wine_dbgstr_w(item_path
));
227 SysFreeString(item_path
);
228 FolderItem_Release(item
);
230 Folder2_Release(folder2
);
232 Folder_Release(folder
);
236 V_I4(&var
) = ssfBITBUCKET
;
237 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
239 broken(r
== S_FALSE
), /* NT4 */
240 "IShellDispatch::NameSpace failed: %08x\n", r
);
243 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
245 broken(r
== E_NOINTERFACE
), /* NT4 */
246 "Folder::QueryInterface failed: %08x\n", r
);
249 r
= Folder2_get_Self(folder2
, &item
);
250 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
253 r
= FolderItem_get_Path(item
, &item_path
);
255 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
257 ok(!lstrcmpW(item_path
, clsidW
), "expected %s, got %s\n",
258 wine_dbgstr_w(clsidW
), wine_dbgstr_w(item_path
));
259 SysFreeString(item_path
);
260 FolderItem_Release(item
);
262 Folder2_Release(folder2
);
264 Folder_Release(folder
);
267 GetTempPathW(MAX_PATH
, tempW
);
268 GetCurrentDirectoryW(MAX_PATH
, curW
);
269 SetCurrentDirectoryW(tempW
);
270 CreateDirectoryW(winetestW
, NULL
);
271 V_VT(&var
) = VT_BSTR
;
272 V_BSTR(&var
) = SysAllocString(winetestW
);
273 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
274 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
275 SysFreeString(V_BSTR(&var
));
277 GetFullPathNameW(winetestW
, MAX_PATH
, tempW
, NULL
);
278 if (pGetLongPathNameW
)
280 len
= pGetLongPathNameW(tempW
, NULL
, 0);
281 long_pathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
283 pGetLongPathNameW(tempW
, long_pathW
, len
);
285 V_VT(&var
) = VT_BSTR
;
286 V_BSTR(&var
) = SysAllocString(tempW
);
287 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
288 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
291 r
= Folder_get_Title(folder
, &title
);
292 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
295 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
296 wine_dbgstr_w(title
));
297 SysFreeString(title
);
299 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
301 broken(r
== E_NOINTERFACE
), /* NT4 */
302 "Folder::QueryInterface failed: %08x\n", r
);
305 r
= Folder2_get_Self(folder2
, &item
);
306 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
309 r
= FolderItem_get_Path(item
, &item_path
);
310 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
312 ok(!lstrcmpW(item_path
, long_pathW
),
313 "expected %s, got %s\n", wine_dbgstr_w(long_pathW
),
314 wine_dbgstr_w(item_path
));
315 SysFreeString(item_path
);
316 FolderItem_Release(item
);
318 Folder2_Release(folder2
);
320 Folder_Release(folder
);
322 SysFreeString(V_BSTR(&var
));
324 len
= lstrlenW(tempW
);
325 if (len
< MAX_PATH
- 1)
327 lstrcatW(tempW
, backslashW
);
328 V_VT(&var
) = VT_BSTR
;
329 V_BSTR(&var
) = SysAllocString(tempW
);
330 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
331 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
334 r
= Folder_get_Title(folder
, &title
);
335 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
338 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
339 wine_dbgstr_w(title
));
340 SysFreeString(title
);
342 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
344 broken(r
== E_NOINTERFACE
), /* NT4 */
345 "Folder::QueryInterface failed: %08x\n", r
);
348 r
= Folder2_get_Self(folder2
, &item
);
349 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
352 r
= FolderItem_get_Path(item
, &item_path
);
353 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
355 ok(!lstrcmpW(item_path
, long_pathW
),
356 "expected %s, got %s\n", wine_dbgstr_w(long_pathW
),
357 wine_dbgstr_w(item_path
));
358 SysFreeString(item_path
);
359 FolderItem_Release(item
);
361 Folder2_Release(folder2
);
363 Folder_Release(folder
);
365 SysFreeString(V_BSTR(&var
));
368 HeapFree(GetProcessHeap(), 0, long_pathW
);
369 RemoveDirectoryW(winetestW
);
370 SetCurrentDirectoryW(curW
);
371 IShellDispatch_Release(sd
);
374 static void test_items(void)
376 WCHAR wstr
[MAX_PATH
], orig_dir
[MAX_PATH
];
378 IShellDispatch
*sd
= NULL
;
379 Folder
*folder
= NULL
;
380 FolderItems
*items
= NULL
;
381 FolderItems2
*items2
= NULL
;
382 FolderItems3
*items3
= NULL
;
383 FolderItem
*item
= (FolderItem
*)0xdeadbeef;
384 IDispatch
*disp
= NULL
;
385 IUnknown
*unk
= NULL
;
386 FolderItemVerbs
*verbs
= (FolderItemVerbs
*)0xdeadbeef;
390 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void**)&sd
);
391 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08x\n", r
);
392 ok(!!sd
, "sd is null\n");
394 GetTempPathW(MAX_PATH
, wstr
);
395 GetCurrentDirectoryW(MAX_PATH
, orig_dir
);
396 SetCurrentDirectoryW(wstr
);
397 CreateDirectoryW(winetestW
, NULL
);
398 GetFullPathNameW(winetestW
, MAX_PATH
, wstr
, NULL
);
399 V_VT(&var
) = VT_BSTR
;
400 V_BSTR(&var
) = SysAllocString(wstr
);
401 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
402 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
403 ok(!!folder
, "folder is null\n");
404 SysFreeString(V_BSTR(&var
));
405 IShellDispatch_Release(sd
);
406 SetCurrentDirectoryW(winetestW
);
408 r
= Folder_Items(folder
, &items
);
409 ok(r
== S_OK
, "Folder::Items failed: %08x\n", r
);
410 ok(!!items
, "items is null\n");
411 r
= FolderItems_QueryInterface(items
, &IID_FolderItems2
, (void**)&items2
);
412 ok(r
== S_OK
|| broken(r
== E_NOINTERFACE
) /* xp and later */, "FolderItems::QueryInterface failed: %08x\n", r
);
413 ok(!!items2
|| broken(!items2
) /* xp and later */, "items2 is null\n");
414 r
= FolderItems_QueryInterface(items
, &IID_FolderItems3
, (void**)&items3
);
415 ok(r
== S_OK
, "FolderItems::QueryInterface failed: %08x\n", r
);
416 ok(!!items3
, "items3 is null\n");
417 Folder_Release(folder
);
419 if (0) /* crashes on all versions of Windows */
420 r
= FolderItems_get_Count(items
, NULL
);
422 r
= FolderItems_get_Count(items
, &lcount
);
423 ok(r
== S_OK
, "FolderItems::get_Count failed: %08x\n", r
);
424 ok(!lcount
, "expected 0 files, got %d\n", lcount
);
429 if (0) /* crashes on all versions of Windows */
430 r
= FolderItems_Item(items
, var
, NULL
);
432 r
= FolderItems_Item(items
, var
, &item
);
434 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
435 ok(!item
, "item is not null\n");
437 if (0) /* crashes on xp */
439 r
= FolderItems_get_Application(items
, NULL
);
440 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
443 r
= FolderItems_get_Application(items
, &disp
);
445 ok(r
== S_OK
, "FolderItems::get_Application failed: %08x\n", r
);
447 ok(!!disp
, "disp is null\n");
448 if (disp
) IDispatch_Release(disp
);
450 if (0) /* crashes on xp */
452 r
= FolderItems_get_Parent(items
, NULL
);
453 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
456 disp
= (IDispatch
*)0xdeadbeef;
457 r
= FolderItems_get_Parent(items
, &disp
);
458 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
459 ok(!disp
, "disp is not null\n");
461 if (0) /* crashes on xp */
463 r
= FolderItems__NewEnum(items
, NULL
);
464 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
467 r
= FolderItems__NewEnum(items
, &unk
);
469 ok(r
== S_OK
, "FolderItems::_NewEnum failed: %08x\n", r
);
471 ok(!!unk
, "unk is null\n");
472 if (unk
) IUnknown_Release(unk
);
476 r
= FolderItems3_Filter(items3
, 0, NULL
);
478 ok(r
== S_OK
, "expected S_OK, got %08x\n", r
);
480 if (0) /* crashes on xp */
482 r
= FolderItems3_get_Verbs(items3
, NULL
);
483 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
486 r
= FolderItems3_get_Verbs(items3
, &verbs
);
488 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
489 ok(!verbs
, "verbs is not null\n");
492 GetTempPathW(MAX_PATH
, wstr
);
493 SetCurrentDirectoryW(wstr
);
494 RemoveDirectoryW(winetestW
);
495 SetCurrentDirectoryW(orig_dir
);
497 FolderItems_Release(items
);
498 if (items2
) FolderItems2_Release(items2
);
499 if (items3
) FolderItems3_Release(items3
);
502 static void test_service(void)
504 static const WCHAR spooler
[] = {'S','p','o','o','l','e','r',0};
505 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
506 SERVICE_STATUS_PROCESS status
;
507 SC_HANDLE scm
, service
;
514 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
515 &IID_IShellDispatch2
, (void**)&sd
);
518 win_skip("IShellDispatch2 not supported\n");
524 hr
= IShellDispatch2_IsServiceRunning(sd
, NULL
, &v
);
525 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
526 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
529 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
530 service
= OpenServiceW(scm
, spooler
, SERVICE_QUERY_STATUS
);
531 QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
, sizeof(SERVICE_STATUS_PROCESS
), &dummy
);
532 CloseServiceHandle(service
);
533 CloseServiceHandle(scm
);
535 /* service should exist */
536 name
= SysAllocString(spooler
);
538 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
540 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
541 if (status
.dwCurrentState
== SERVICE_RUNNING
)
542 ok(V_BOOL(&v
) == VARIANT_TRUE
, "got %d\n", V_BOOL(&v
));
544 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
547 /* service doesn't exist */
548 name
= SysAllocString(dummyW
);
550 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
552 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
553 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
556 IShellDispatch2_Release(sd
);
559 static void test_dispatch_typeinfo(IDispatch
*disp
, REFIID
*riid
)
567 hr
= IDispatch_GetTypeInfoCount(disp
, &count
);
568 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
569 ok(count
== 1, "got %u\n", count
);
571 hr
= IDispatch_GetTypeInfo(disp
, 0, LOCALE_SYSTEM_DEFAULT
, &typeinfo
);
572 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
574 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
575 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
576 while (!IsEqualGUID(*riid
, &IID_NULL
)) {
577 if (IsEqualGUID(&typeattr
->guid
, *riid
))
581 ok(IsEqualGUID(&typeattr
->guid
, *riid
), "unexpected type guid %s\n", wine_dbgstr_guid(&typeattr
->guid
));
583 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
584 ITypeInfo_Release(typeinfo
);
587 static void test_ShellFolderViewDual(void)
589 static const IID
*shelldisp_riids
[] = {
590 &IID_IShellDispatch6
,
591 &IID_IShellDispatch5
,
592 &IID_IShellDispatch4
,
593 &IID_IShellDispatch2
,
594 &IID_IWin7ShellDispatch6
,
597 IShellFolderViewDual
*viewdual
;
598 IShellFolder
*desktop
, *tmpdir
;
599 IShellView
*view
, *view2
;
600 IDispatch
*disp
, *disp2
;
601 WCHAR pathW
[MAX_PATH
];
605 /* IShellFolderViewDual is not an IShellView extension */
606 hr
= SHGetDesktopFolder(&desktop
);
607 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
609 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
610 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
612 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
613 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
615 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
616 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
618 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp2
);
619 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
620 ok(disp2
== disp
, "got %p, %p\n", disp2
, disp
);
621 IDispatch_Release(disp2
);
623 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
624 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
625 ok(disp
== (IDispatch
*)viewdual
, "got %p, expected %p\n", viewdual
, disp
);
627 hr
= IShellFolderViewDual_QueryInterface(viewdual
, &IID_IShellView
, (void**)&view2
);
628 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
630 /* get_Application() */
632 if (0) /* crashes on pre-vista */ {
633 hr
= IShellFolderViewDual_get_Application(viewdual
, NULL
);
634 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
636 hr
= IShellFolderViewDual_get_Application(viewdual
, &disp2
);
637 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
638 ok(disp2
!= (IDispatch
*)viewdual
, "got %p, %p\n", disp2
, viewdual
);
639 test_dispatch_typeinfo(disp2
, shelldisp_riids
);
640 IDispatch_Release(disp2
);
642 IShellFolderViewDual_Release(viewdual
);
643 IDispatch_Release(disp
);
645 disp
= (void*)0xdeadbeef;
646 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IShellFolderViewDual
, (void**)&disp
);
647 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
) /* win2k */, "got 0x%08x\n", hr
);
648 ok(disp
== NULL
, "got %p\n", disp
);
649 IShellView_Release(view
);
651 /* Try with some other folder, that's not a desktop */
652 GetTempPathW(sizeof(pathW
)/sizeof(pathW
[0]), pathW
);
653 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, pathW
, NULL
, &pidl
, NULL
);
654 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
656 hr
= IShellFolder_BindToObject(desktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&tmpdir
);
657 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
660 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
661 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
663 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
664 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
666 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
667 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
668 IDispatch_Release(disp
);
669 IShellView_Release(view
);
671 IShellFolder_Release(tmpdir
);
672 IShellFolder_Release(desktop
);
675 static void test_ShellWindows(void)
677 IShellWindows
*shellwindows
;
678 LONG cookie
, cookie2
, ret
;
684 hr
= CoCreateInstance(&CLSID_ShellWindows
, NULL
, CLSCTX_LOCAL_SERVER
,
685 &IID_IShellWindows
, (void**)&shellwindows
);
686 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
687 /* TODO: remove when explorer startup with clean prefix is fixed */
691 if (0) /* NULL out argument - currently crashes on Wine */ {
692 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, NULL
);
693 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "got 0x%08x\n", hr
);
695 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, &cookie
);
697 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
699 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
701 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
703 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
705 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
707 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
708 0, 0, 50, 14, 0, 0, 0, NULL
);
709 ok(hwnd
!= NULL
, "got %p, error %d\n", hwnd
, GetLastError());
712 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie
);
714 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
715 ok(cookie
!= 0, "got %d\n", cookie
);
718 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie2
);
720 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
721 ok(cookie2
!= 0 && cookie2
!= cookie
, "got %d\n", cookie2
);
723 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
725 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
726 hr
= IShellWindows_Revoke(shellwindows
, cookie2
);
728 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
730 hr
= IShellWindows_Revoke(shellwindows
, 0);
732 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
734 /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
736 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_DESKTOP
, &cookie
);
738 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
739 ok(cookie
!= 0, "got %d\n", cookie
);
741 disp
= (void*)0xdeadbeef;
744 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, SWFO_NEEDDISPATCH
, &disp
);
745 ok(hr
== S_OK
|| broken(hr
== S_FALSE
), "got 0x%08x\n", hr
);
746 if (hr
== S_FALSE
) /* winxp and earlier */ {
747 win_skip("SWC_DESKTOP is not supported, some tests will be skipped.\n");
748 /* older versions allowed to regiser SWC_DESKTOP and access it with FindWindowSW */
749 ok(disp
== NULL
, "got %p\n", disp
);
750 ok(ret
== 0, "got %d\n", ret
);
753 static const IID
*browser_riids
[] = {
758 static const IID
*viewdual_riids
[] = {
759 &IID_IShellFolderViewDual3
,
763 IShellFolderViewDual
*view
;
764 IShellBrowser
*sb
, *sb2
;
765 IServiceProvider
*sp
;
766 IDispatch
*doc
, *app
;
771 ok(disp
!= NULL
, "got %p\n", disp
);
772 ok(ret
!= HandleToUlong(hwnd
), "got %d\n", ret
);
774 /* IDispatch-related tests */
775 test_dispatch_typeinfo(disp
, browser_riids
);
778 hr
= IDispatch_QueryInterface(disp
, &IID_IWebBrowser2
, (void**)&wb
);
779 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
781 hr
= IWebBrowser2_Refresh(wb
);
783 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
785 hr
= IWebBrowser2_get_Application(wb
, &app
);
786 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
787 ok(disp
== app
, "got %p, %p\n", app
, disp
);
788 IDispatch_Release(app
);
790 hr
= IWebBrowser2_get_Document(wb
, &doc
);
792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
794 test_dispatch_typeinfo(doc
, viewdual_riids
);
796 IWebBrowser2_Release(wb
);
798 /* IServiceProvider */
799 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&view
);
800 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
802 hr
= IDispatch_QueryInterface(disp
, &IID_IServiceProvider
, (void**)&sp
);
803 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
805 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb
);
806 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
808 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb2
);
809 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
810 ok(sb
== sb2
, "got %p, %p\n", sb
, sb2
);
812 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IOleWindow
, (void**)&unk
);
813 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
814 IUnknown_Release(unk
);
816 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IExplorerBrowser
, (void**)&unk
);
817 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
819 hr
= IShellBrowser_QueryInterface(sb
, &IID_IExplorerBrowser
, (void**)&unk
);
820 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
822 hr
= IShellBrowser_QueryInterface(sb
, &IID_IWebBrowser2
, (void**)&unk
);
823 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
825 hr
= IShellBrowser_QueryInterface(sb
, &IID_IDispatch
, (void**)&unk
);
826 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
828 hr
= IShellBrowser_QueryActiveShellView(sb
, &sv
);
829 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
830 IShellView_Release(sv
);
832 IShellBrowser_Release(sb2
);
833 IShellBrowser_Release(sb
);
835 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IUnknown
, (void**)&unk
);
836 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
838 hr
= IUnknown_QueryInterface(unk
, &IID_IShellBrowser
, (void**)&sb2
);
839 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
840 IShellBrowser_Release(sb2
);
841 IUnknown_Release(unk
);
843 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellView
, (void**)&sv
);
844 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
846 IServiceProvider_Release(sp
);
847 IDispatch_Release(disp
);
850 disp
= (void*)0xdeadbeef;
853 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, 0, &disp
);
854 ok(hr
== S_OK
|| broken(hr
== S_FALSE
) /* winxp */, "got 0x%08x\n", hr
);
855 ok(disp
== NULL
, "got %p\n", disp
);
856 ok(ret
!= HandleToUlong(hwnd
), "got %d\n", ret
);
858 disp
= (void*)0xdeadbeef;
863 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_BROWSER
, &ret
, SWFO_COOKIEPASSED
, &disp
);
865 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
866 ok(disp
== NULL
, "got %p\n", disp
);
867 ok(ret
== 0, "got %d\n", ret
);
869 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
871 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
873 IShellWindows_Release(shellwindows
);
876 static void test_ParseName(void)
878 static const WCHAR cadabraW
[] = {'c','a','d','a','b','r','a',0};
879 WCHAR pathW
[MAX_PATH
];
887 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
888 &IID_IShellDispatch
, (void**)&sd
);
889 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
891 GetTempPathW(sizeof(pathW
)/sizeof(pathW
[0]), pathW
);
893 V_BSTR(&v
) = SysAllocString(pathW
);
894 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
895 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
898 item
= (void*)0xdeadbeef;
899 hr
= Folder_ParseName(folder
, NULL
, &item
);
900 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08x\n", hr
);
901 ok(item
== NULL
, "got %p\n", item
);
904 str
= SysAllocStringLen(NULL
, 0);
905 item
= (void*)0xdeadbeef;
906 hr
= Folder_ParseName(folder
, str
, &item
);
907 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08x\n", hr
);
908 ok(item
== NULL
, "got %p\n", item
);
911 /* path doesn't exist */
912 str
= SysAllocString(cadabraW
);
913 item
= (void*)0xdeadbeef;
914 hr
= Folder_ParseName(folder
, str
, &item
);
915 ok(hr
== S_FALSE
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* win2k */,
917 ok(item
== NULL
, "got %p\n", item
);
920 lstrcatW(pathW
, cadabraW
);
921 CreateDirectoryW(pathW
, NULL
);
923 str
= SysAllocString(cadabraW
);
925 hr
= Folder_ParseName(folder
, str
, &item
);
926 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
927 ok(item
!= NULL
, "got %p\n", item
);
930 hr
= FolderItem_get_Path(item
, &str
);
931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
932 ok(str
[0] != 0, "path %s\n", wine_dbgstr_w(str
));
935 RemoveDirectoryW(pathW
);
936 FolderItem_Release(item
);
937 Folder_Release(folder
);
938 IShellDispatch_Release(sd
);
941 static void test_Verbs(void)
943 FolderItemVerbs
*verbs
;
944 WCHAR pathW
[MAX_PATH
];
945 FolderItemVerb
*verb
;
955 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
956 &IID_IShellDispatch
, (void**)&sd
);
957 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
959 GetTempPathW(sizeof(pathW
)/sizeof(pathW
[0]), pathW
);
961 V_BSTR(&v
) = SysAllocString(pathW
);
962 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
963 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
966 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
967 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
968 Folder_Release(folder
);
970 hr
= Folder2_get_Self(folder2
, &item
);
971 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
972 Folder2_Release(folder2
);
974 if (0) { /* crashes on some systems */
975 hr
= FolderItem_Verbs(item
, NULL
);
976 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
978 hr
= FolderItem_Verbs(item
, &verbs
);
979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
981 if (0) { /* crashes on winxp/win2k3 */
982 hr
= FolderItemVerbs_get_Count(verbs
, NULL
);
983 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
986 hr
= FolderItemVerbs_get_Count(verbs
, &count
);
987 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
988 ok(count
> 0, "got count %d\n", count
);
990 if (0) { /* crashes on winxp/win2k3 */
993 hr
= FolderItemVerbs_Item(verbs
, v
, NULL
);
994 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
996 /* there's always one item more, so you can access [0,count],
997 instead of actual [0,count) */
998 for (i
= 0; i
<= count
; i
++) {
1001 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1002 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1003 hr
= FolderItemVerb_get_Name(verb
, &str
);
1004 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1005 ok(str
!= NULL
, "%d: name %s\n", i
, wine_dbgstr_w(str
));
1007 ok(str
[0] == 0, "%d: got teminating item %s\n", i
, wine_dbgstr_w(str
));
1010 FolderItemVerb_Release(verb
);
1016 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1017 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1018 ok(verb
== NULL
, "got %p\n", verb
);
1020 FolderItemVerbs_Release(verbs
);
1021 FolderItem_Release(item
);
1022 IShellDispatch_Release(sd
);
1025 static void test_ShellExecute(void)
1028 IShellDispatch2
*sd
;
1030 VARIANT args
, dir
, op
, show
;
1032 static const WCHAR regW
[] = {'r','e','g',0};
1034 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1035 &IID_IShellDispatch2
, (void**)&sd
);
1038 win_skip("IShellDispatch2 not supported\n");
1047 V_VT(&show
) = VT_I4
;
1050 name
= SysAllocString(regW
);
1052 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1053 ok(hr
== S_OK
, "ShellExecute failed: %08x\n", hr
);
1055 /* test invalid value for show */
1056 V_VT(&show
) = VT_BSTR
;
1057 V_BSTR(&show
) = name
;
1059 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1060 ok(hr
== S_OK
, "ShellExecute failed: %08x\n", hr
);
1062 SysFreeString(name
);
1065 START_TEST(shelldispatch
)
1069 r
= CoInitialize(NULL
);
1070 ok(SUCCEEDED(r
), "CoInitialize failed: %08x\n", r
);
1074 init_function_pointers();
1078 test_ShellFolderViewDual();
1079 test_ShellWindows();
1082 test_ShellExecute();