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
30 #include "wine/test.h"
34 #define EXPECT_HR(hr,hr_exp) \
35 ok(hr == hr_exp, "got 0x%08lx, expected 0x%08lx\n", hr, hr_exp)
37 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
38 static void _expect_ref(IUnknown
*obj
, ULONG ref
, int line
)
42 rc
= IUnknown_Release(obj
);
43 ok_(__FILE__
,line
)(rc
== ref
, "Unexpected refcount %ld, expected %ld\n", rc
, ref
);
46 static const WCHAR winetestW
[] = {'w','i','n','e','t','e','s','t',0};
48 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
50 /* Updated Windows 7 has a new IShellDispatch6 in its typelib */
51 DEFINE_GUID(IID_IWin7ShellDispatch6
, 0x34936ba1, 0x67ad, 0x4c41, 0x99,0xb8, 0x8c,0x12,0xdf,0xf1,0xe9,0x74);
53 static BSTR
a2bstr(const char *str
)
58 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
59 ret
= SysAllocStringLen(NULL
, len
);
60 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
65 static void variant_set_string(VARIANT
*v
, const char *s
)
68 V_BSTR(v
) = a2bstr(s
);
71 static void init_function_pointers(void)
75 hshell32
= GetModuleHandleA("shell32.dll");
76 pSHGetNameFromIDList
= (void*)GetProcAddress(hshell32
, "SHGetNameFromIDList");
79 static void test_namespace(void)
81 static const ShellSpecialFolderConstants special_folders
[] =
123 static const WCHAR backslashW
[] = {'\\',0};
124 static const WCHAR clsidW
[] = {
125 ':',':','{','6','4','5','F','F','0','4','0','-','5','0','8','1','-',
126 '1','0','1','B','-','9','F','0','8','-',
127 '0','0','A','A','0','0','2','F','9','5','4','E','}',0};
129 static WCHAR tempW
[MAX_PATH
], curW
[MAX_PATH
];
130 WCHAR
*long_pathW
= NULL
;
137 BSTR title
, item_path
;
141 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void **)&sd
);
142 ok(SUCCEEDED(r
), "Failed to create ShellDispatch object: %#lx.\n", r
);
145 r
= IShellDispatch_get_Application(sd
, &disp
);
146 ok(r
== S_OK
, "Failed to get application pointer, hr %#lx.\n", r
);
147 ok(disp
== (IDispatch
*)sd
, "Unexpected application pointer %p.\n", disp
);
148 IDispatch_Release(disp
);
151 r
= IShellDispatch_get_Parent(sd
, &disp
);
152 ok(r
== S_OK
, "Failed to get Shell object parent, hr %#lx.\n", r
);
153 ok(disp
== (IDispatch
*)sd
, "Unexpected parent pointer %p.\n", disp
);
154 IDispatch_Release(disp
);
157 folder
= (void*)0xdeadbeef;
158 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
159 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
160 ok(folder
== NULL
, "expected NULL, got %p\n", folder
);
162 /* test valid folder ids */
163 for (i
= 0; i
< ARRAY_SIZE(special_folders
); i
++)
166 V_I4(&var
) = special_folders
[i
];
167 folder
= (void*)0xdeadbeef;
168 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
169 if (special_folders
[i
] == ssfALTSTARTUP
|| special_folders
[i
] == ssfCOMMONALTSTARTUP
)
171 ok(r
== S_OK
|| broken(r
== S_FALSE
) /* winxp */, "Failed to get folder for index %#x, got %08lx\n", special_folders
[i
], r
);
173 ok(r
== S_OK
, "Failed to get folder for index %#x, got %08lx\n", special_folders
[i
], r
);
175 Folder_Release(folder
);
180 folder
= (void *)0xdeadbeef;
181 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
182 ok(r
== S_FALSE
, "Unexpected hr %#lx.\n", r
);
183 ok(folder
== NULL
, "Unexpected folder instance %p\n", folder
);
186 V_I4(&var
) = ssfPROGRAMFILES
;
187 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
188 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
191 static WCHAR path
[MAX_PATH
];
193 r
= SHGetFolderPathW(NULL
, CSIDL_PROGRAM_FILES
, NULL
, SHGFP_TYPE_CURRENT
, path
);
194 ok(r
== S_OK
, "Failed to get folder path: %#lx.\n", r
);
196 r
= Folder_get_Title(folder
, &title
);
197 ok(r
== S_OK
, "Folder::get_Title failed: %08lx\n", r
);
200 /* On Win2000-2003 title is equal to program files directory name in
201 HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir.
202 On newer Windows it seems constant and is not changed
203 if the program files directory name is changed */
204 if (pSHGetNameFromIDList
)
209 r
= SHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidl
);
210 ok(r
== S_OK
, "SHGetSpecialFolderLocation failed: %08lx\n", r
);
211 r
= pSHGetNameFromIDList(pidl
, SIGDN_NORMALDISPLAY
, &name
);
212 ok(r
== S_OK
, "SHGetNameFromIDList failed: %08lx\n", r
);
213 ok(!lstrcmpW(title
, name
), "expected %s, got %s\n", wine_dbgstr_w(name
), wine_dbgstr_w(title
));
221 p
= path
+ lstrlenW(path
);
222 while (path
< p
&& *(p
- 1) != '\\')
224 ok(!lstrcmpiW(title
, p
), "expected %s, got %s\n",
225 wine_dbgstr_w(p
), wine_dbgstr_w(title
));
227 SysFreeString(title
);
229 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
230 ok(r
== S_OK
, "Folder::QueryInterface failed: %08lx\n", r
);
233 r
= Folder2_get_Self(folder2
, &item
);
234 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
237 r
= FolderItem_get_Path(item
, &item_path
);
238 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
239 ok(!lstrcmpiW(item_path
, path
), "expected %s, got %s\n", wine_dbgstr_w(path
), wine_dbgstr_w(item_path
));
240 SysFreeString(item_path
);
241 FolderItem_Release(item
);
243 Folder2_Release(folder2
);
245 Folder_Release(folder
);
249 V_I4(&var
) = ssfBITBUCKET
;
250 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
251 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
253 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (void **)&folder2
);
254 ok(r
== S_OK
, "Failed to get Folder2 interface: %#lx.\n", r
);
255 r
= Folder2_get_Self(folder2
, &item
);
256 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
257 r
= FolderItem_get_Path(item
, &item_path
);
258 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
259 /* TODO: we return lowercase GUID here */
260 ok(!lstrcmpiW(item_path
, clsidW
), "expected %s, got %s\n", wine_dbgstr_w(clsidW
), wine_dbgstr_w(item_path
));
262 SysFreeString(item_path
);
263 FolderItem_Release(item
);
264 Folder2_Release(folder2
);
265 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 %08lx\n", r
);
275 SysFreeString(V_BSTR(&var
));
277 GetFullPathNameW(winetestW
, MAX_PATH
, tempW
, NULL
);
279 len
= GetLongPathNameW(tempW
, NULL
, 0);
280 long_pathW
= malloc(len
* sizeof(WCHAR
));
281 GetLongPathNameW(tempW
, long_pathW
, len
);
283 V_VT(&var
) = VT_BSTR
;
284 V_BSTR(&var
) = SysAllocString(tempW
);
285 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
286 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
288 disp
= (void *)0xdeadbeef;
289 r
= Folder_get_Parent(folder
, &disp
);
290 ok(r
== E_NOTIMPL
, "Unexpected hr %#lx.\n", r
);
291 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
293 r
= Folder_get_Title(folder
, &title
);
294 ok(r
== S_OK
, "Failed to get folder title: %#lx.\n", r
);
295 ok(!lstrcmpW(title
, winetestW
), "Unexpected title: %s\n", wine_dbgstr_w(title
));
296 SysFreeString(title
);
298 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (void **)&folder2
);
299 ok(r
== S_OK
, "Failed to get Folder2 interface: %#lx.\n", r
);
300 r
= Folder2_get_Self(folder2
, &item
);
301 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
302 r
= FolderItem_get_Path(item
, &item_path
);
303 ok(r
== S_OK
, "Failed to get item path: %#lx.\n", r
);
304 ok(!lstrcmpW(item_path
, long_pathW
), "Unexpected path %s, got %s\n", wine_dbgstr_w(item_path
), wine_dbgstr_w(long_pathW
));
305 SysFreeString(item_path
);
306 FolderItem_Release(item
);
307 Folder2_Release(folder2
);
309 Folder_Release(folder
);
312 len
= lstrlenW(tempW
);
313 if (len
< MAX_PATH
- 1)
315 lstrcatW(tempW
, backslashW
);
316 V_VT(&var
) = VT_BSTR
;
317 V_BSTR(&var
) = SysAllocString(tempW
);
318 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
319 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
322 r
= Folder_get_Title(folder
, &title
);
323 ok(r
== S_OK
, "Folder::get_Title failed: %08lx\n", r
);
326 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
327 wine_dbgstr_w(title
));
328 SysFreeString(title
);
330 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
331 ok(r
== S_OK
, "Failed to get Folder2 interface: %#lx.\n", r
);
334 r
= Folder2_get_Self(folder2
, &item
);
335 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
338 r
= FolderItem_get_Path(item
, &item_path
);
339 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
340 ok(!lstrcmpW(item_path
, long_pathW
), "Unexpected path %s, got %s\n", wine_dbgstr_w(item_path
),
341 wine_dbgstr_w(long_pathW
));
342 SysFreeString(item_path
);
343 FolderItem_Release(item
);
345 Folder2_Release(folder2
);
347 Folder_Release(folder
);
349 SysFreeString(V_BSTR(&var
));
353 RemoveDirectoryW(winetestW
);
354 SetCurrentDirectoryW(curW
);
355 IShellDispatch_Release(sd
);
358 static void test_items(void)
372 { "00-Myfolder", DIRECTORY
},
373 { "01-empty.bin", EMPTY_FILE
},
375 WCHAR path
[MAX_PATH
], cur_dir
[MAX_PATH
], orig_dir
[MAX_PATH
];
377 IShellDispatch
*sd
= NULL
;
378 Folder
*folder
= NULL
;
380 FolderItems2
*items2
= NULL
;
381 FolderItems3
*items3
= NULL
;
382 FolderItem
*item
= (FolderItem
*)0xdeadbeef, *item2
;
383 FolderItemVerbs
*verbs
= (FolderItemVerbs
*)0xdeadbeef;
384 VARIANT var
, var2
, int_index
, str_index
, str_index2
;
385 IDispatch
*disp
, *disp2
;
394 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void**)&sd
);
395 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08lx\n", r
);
396 ok(!!sd
, "sd is null\n");
398 /* create and enter a temporary directory and a folder object for it */
399 GetTempPathW(MAX_PATH
, path
);
400 GetCurrentDirectoryW(MAX_PATH
, orig_dir
);
401 SetCurrentDirectoryW(path
);
402 ret
= CreateDirectoryW(winetestW
, NULL
);
403 ok(ret
, "CreateDirectory failed: %08lx\n", GetLastError());
404 GetFullPathNameW(winetestW
, MAX_PATH
, path
, NULL
);
405 V_VT(&var
) = VT_BSTR
;
406 V_BSTR(&var
) = SysAllocString(path
);
409 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
410 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
411 ok(!!folder
, "folder is null\n");
412 EXPECT_REF(folder
, 1);
416 SetCurrentDirectoryW(winetestW
);
417 GetCurrentDirectoryW(MAX_PATH
, path
);
418 GetLongPathNameW(path
, cur_dir
, MAX_PATH
);
420 /* FolderItems grabs its Folder reference */
422 r
= Folder_Items(folder
, &items
);
423 ok(r
== S_OK
, "Folder::Items failed: %08lx\n", r
);
424 ok(!!items
, "items is null\n");
425 EXPECT_REF(folder
, 2);
426 EXPECT_REF(items
, 1);
429 r
= Folder_Items(folder
, (FolderItems
**)&unk
);
430 ok(r
== S_OK
, "Folder::Items failed: %08lx\n", r
);
431 EXPECT_REF(folder
, 3);
432 IUnknown_Release(unk
);
433 EXPECT_REF(folder
, 2);
435 FolderItems_AddRef(items
);
436 EXPECT_REF(folder
, 2);
437 FolderItems_Release(items
);
439 /* Application property */
442 r
= Folder_get_Application(folder
, &disp
);
443 ok(r
== S_OK
, "Failed to get application %#lx.\n", r
);
444 ok(disp
!= (IDispatch
*)sd
, "Unexpected application pointer\n");
448 r
= Folder_get_Application(folder
, &disp2
);
449 ok(r
== S_OK
, "Failed to get application %#lx.\n", r
);
450 ok(disp2
== disp
, "Unexpected application pointer\n");
451 IDispatch_Release(disp2
);
453 r
= IDispatch_QueryInterface(disp
, &IID_IShellDispatch
, (void **)&disp2
);
454 ok(r
== S_OK
, "Wrong instance, hr %#lx.\n", r
);
455 IDispatch_Release(disp2
);
456 IDispatch_Release(disp
);
458 if (0) /* crashes on all versions of Windows */
459 r
= FolderItems_get_Count(items
, NULL
);
461 r
= FolderItems_get_Count(items
, &count
);
462 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
463 ok(!count
, "expected 0 files, got %ld\n", count
);
468 if (0) /* crashes on all versions of Windows */
469 r
= FolderItems_Item(items
, var
, NULL
);
471 r
= FolderItems_Item(items
, var
, &item
);
472 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
473 ok(!item
, "item is not null\n");
475 /* create test files */
476 for (i
= 0; i
< ARRAY_SIZE(file_defs
); i
++)
478 switch (file_defs
[i
].type
)
481 r
= CreateDirectoryA(file_defs
[i
].name
, NULL
);
482 ok(r
, "CreateDirectory failed: %08lx\n", GetLastError());
483 PathCombineA(cstr
, file_defs
[i
].name
, "foo.txt");
484 file
= CreateFileA(cstr
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
485 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08lx\n", GetLastError());
490 file
= CreateFileA(file_defs
[i
].name
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
491 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08lx\n", GetLastError());
497 /* test that get_Count is not aware of the newly created files */
499 r
= FolderItems_get_Count(items
, &count
);
500 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
501 ok(!count
, "expected 0 files, got %ld\n", count
);
503 /* test that the newly created files CAN be retrieved by string index */
504 variant_set_string(&var
, file_defs
[0].name
);
506 r
= FolderItems_Item(items
, var
, &item
);
507 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
508 ok(!!item
, "item is null\n");
510 disp
= (void *)0xdeadbeef;
511 r
= FolderItems_get_Parent(items
, &disp
);
512 ok(r
== E_NOTIMPL
, "Unexpected hr %#lx.\n", r
);
513 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
515 r
= FolderItem_get_Parent(item
, &disp
);
516 ok(r
== S_OK
, "Failed to get parent pointer, hr %#lx.\n", r
);
517 ok(disp
== (IDispatch
*)folder
, "Unexpected parent pointer %p.\n", disp
);
518 IDispatch_Release(disp
);
520 if (item
) FolderItem_Release(item
);
523 /* recreate the items object */
524 FolderItems_Release(items
);
526 r
= Folder_Items(folder
, &items
);
527 ok(r
== S_OK
, "Folder::Items failed: %08lx\n", r
);
528 ok(!!items
, "items is null\n");
529 r
= FolderItems_QueryInterface(items
, &IID_FolderItems2
, (void**)&items2
);
530 ok(r
== S_OK
|| broken(r
== E_NOINTERFACE
) /* xp and later */, "FolderItems::QueryInterface failed: %08lx\n", r
);
533 ok(!!items2
, "items2 is null\n");
534 FolderItems2_Release(items2
);
536 r
= FolderItems_QueryInterface(items
, &IID_FolderItems3
, (void**)&items3
);
537 ok(r
== S_OK
, "FolderItems::QueryInterface failed: %08lx\n", r
);
538 ok(!!items3
, "items3 is null\n");
541 r
= FolderItems_get_Count(items
, &count
);
542 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
543 ok(count
== ARRAY_SIZE(file_defs
), "got %ld files\n", count
);
546 V_VT(&var
) = VT_EMPTY
;
547 item
= (FolderItem
*)0xdeadbeef;
548 r
= FolderItems_Item(items
, var
, &item
);
549 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08lx\n", r
);
550 ok(!item
, "item is not null\n");
556 EXPECT_REF(folder
, 2);
557 EXPECT_REF(items
, 2);
559 r
= FolderItems_Item(items
, var
, &item
);
560 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
561 ok(!!item
, "item is null\n");
562 EXPECT_REF(folder
, 3);
563 EXPECT_REF(items
, 2);
565 r
= Folder_get_Application(folder
, &disp
);
566 ok(r
== S_OK
, "Failed to get application pointer %#lx.\n", r
);
567 r
= FolderItem_get_Application(item
, &disp2
);
568 ok(r
== S_OK
, "Failed to get application pointer %#lx.\n", r
);
569 ok(disp
== disp2
, "Unexpected application pointer.\n");
570 IDispatch_Release(disp2
);
571 IDispatch_Release(disp
);
573 FolderItem_Release(item
);
575 /* VT_VARIANT | VT_BYREF */
579 V_VT(&var
) = VT_BYREF
| VT_VARIANT
;
580 V_VARIANTREF(&var
) = &var2
;
583 r
= FolderItems_Item(items
, var
, &item
);
584 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
585 ok(!!item
, "item is null\n");
586 FolderItem_Release(item
);
592 r
= FolderItems_Item(items
, var
, &item
);
593 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
594 ok(!!item
, "item is null\n");
595 if (item
) FolderItem_Release(item
);
598 item
= (FolderItem
*)0xdeadbeef;
599 r
= FolderItems_Item(items
, var
, &item
);
600 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
601 ok(!item
, "item is not null\n");
603 V_VT(&var
) = VT_ERROR
;
606 r
= FolderItems_Item(items
, var
, &item
);
607 ok(r
== S_OK
, "expected S_OK, got %08lx\n", r
);
608 ok(!!item
, "item is null\n");
612 r
= FolderItem_get_Path(item
, &bstr
);
613 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
614 ok(!lstrcmpW(bstr
, cur_dir
),
615 "expected %s, got %s\n", wine_dbgstr_w(cur_dir
), wine_dbgstr_w(bstr
));
617 FolderItem_Release(item
);
620 V_VT(&int_index
) = VT_I4
;
622 /* test the folder item corresponding to each file */
623 for (i
= 0; i
< ARRAY_SIZE(file_defs
); i
++)
628 V_I4(&int_index
) = i
;
629 variant_set_string(&str_index
, file_defs
[i
].name
);
632 r
= FolderItems_Item(items
, int_index
, &item
);
633 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
634 ok(!!item
, "file_defs[%d]: item is null\n", i
);
637 r
= FolderItems_Item(items
, int_index
, &item2
);
638 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
639 ok(item2
!= item
, "file_defs[%d]: item and item2 are the same\n", i
);
640 FolderItem_Release(item2
);
643 r
= FolderItem_get_Path(item
, &bstr
);
644 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08lx\n", i
, r
);
645 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
646 ok(!lstrcmpW(bstr
, path
),
647 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
650 bstr
= a2bstr(file_defs
[i
].name
);
651 r
= FolderItem_get_Name(item
, &name
);
652 ok(r
== S_OK
, "Failed to get item name, hr %#lx.\n", r
);
653 /* Returned display name does not have to strictly match file name, e.g. extension could be omitted. */
654 ok(lstrlenW(name
) <= lstrlenW(bstr
), "file_defs[%d]: unexpected name length.\n", i
);
655 ok(!memcmp(bstr
, name
, lstrlenW(name
) * sizeof(WCHAR
)), "file_defs[%d]: unexpected name %s.\n", i
, wine_dbgstr_w(name
));
659 FolderItem_Release(item
);
662 r
= FolderItems_Item(items
, str_index
, &item
);
663 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
664 ok(!!item
, "file_defs[%d]: item is null\n", i
);
667 r
= FolderItem_get_Path(item
, &bstr
);
668 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08lx\n", i
, r
);
669 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
670 ok(!lstrcmpW(bstr
, path
),
671 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
675 r
= FolderItem_get_IsFolder(item
, &b
);
676 ok(r
== S_OK
, "Failed to get IsFolder property, %#lx.\n", r
);
677 ok(file_defs
[i
].type
== DIRECTORY
? b
== VARIANT_TRUE
: b
== VARIANT_FALSE
, "Unexpected prop value %#x.\n", b
);
679 FolderItem_Release(item
);
681 if (file_defs
[i
].type
== DIRECTORY
)
683 /* test that getting an item object for a file in a subdirectory succeeds */
684 PathCombineA(cstr
, file_defs
[i
].name
, "foo.txt");
685 variant_set_string(&str_index2
, cstr
);
687 r
= FolderItems_Item(items
, str_index2
, &item2
);
688 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
689 ok(!!item2
, "file_defs[%d]: item is null\n", i
);
690 if (item2
) FolderItem_Release(item2
);
691 VariantClear(&str_index2
);
693 /* delete the file in the subdirectory */
694 ret
= DeleteFileA(cstr
);
695 ok(ret
, "file_defs[%d]: DeleteFile failed: %08lx\n", i
, GetLastError());
697 /* test that getting an item object via a relative path fails */
698 strcpy(cstr
, file_defs
[i
].name
);
699 strcat(cstr
, "\\..\\");
700 strcat(cstr
, file_defs
[i
].name
);
701 variant_set_string(&str_index2
, cstr
);
702 item2
= (FolderItem
*)0xdeadbeef;
703 r
= FolderItems_Item(items
, str_index2
, &item2
);
704 ok(r
== S_FALSE
, "file_defs[%d]: expected S_FALSE, got %08lx\n", i
, r
);
705 ok(!item2
, "file_defs[%d]: item is not null\n", i
);
706 VariantClear(&str_index2
);
708 /* remove the directory */
709 ret
= RemoveDirectoryA(file_defs
[i
].name
);
710 ok(ret
, "file_defs[%d]: RemoveDirectory failed: %08lx\n", i
, GetLastError());
714 ret
= DeleteFileA(file_defs
[i
].name
);
715 ok(ret
, "file_defs[%d]: DeleteFile failed: %08lx\n", i
, GetLastError());
718 /* test that the folder item is still accessible by integer index */
720 r
= FolderItems_Item(items
, int_index
, &item
);
721 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
722 ok(!!item
, "file_defs[%d]: item is null\n", i
);
725 r
= FolderItem_get_Path(item
, &bstr
);
726 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08lx\n", i
, r
);
727 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
728 ok(!lstrcmpW(bstr
, path
),
729 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
732 FolderItem_Release(item
);
734 /* test that the folder item is no longer accessible by string index */
735 item
= (FolderItem
*)0xdeadbeef;
736 r
= FolderItems_Item(items
, str_index
, &item
);
737 ok(r
== S_FALSE
, "file_defs[%d]: expected S_FALSE, got %08lx\n", i
, r
);
738 ok(!item
, "file_defs[%d]: item is not null\n", i
);
740 VariantClear(&str_index
);
743 /* test that there are only as many folder items as there were files */
744 V_I4(&int_index
) = ARRAY_SIZE(file_defs
);
745 item
= (FolderItem
*)0xdeadbeef;
746 r
= FolderItems_Item(items
, int_index
, &item
);
747 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
748 ok(!item
, "item is not null\n");
750 if (0) /* crashes on xp */
752 r
= FolderItems_get_Application(items
, NULL
);
753 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08lx\n", r
);
756 r
= FolderItems_get_Application(items
, &disp
);
757 ok(r
== S_OK
, "FolderItems::get_Application failed: %08lx\n", r
);
759 r
= Folder_get_Application(folder
, &disp2
);
760 ok(r
== S_OK
, "Failed to get application pointer, hr %#lx.\n", r
);
761 ok(disp
== disp2
, "Unexpected application pointer.\n");
762 IDispatch_Release(disp2
);
763 IDispatch_Release(disp
);
765 if (0) /* crashes on xp */
767 r
= FolderItems_get_Parent(items
, NULL
);
768 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08lx\n", r
);
771 disp
= (IDispatch
*)0xdeadbeef;
772 r
= FolderItems_get_Parent(items
, &disp
);
773 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08lx\n", r
);
774 ok(!disp
, "disp is not null\n");
776 if (0) /* crashes on xp */
778 r
= FolderItems__NewEnum(items
, NULL
);
779 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08lx\n", r
);
782 r
= FolderItems__NewEnum(items
, &unk
);
784 ok(r
== S_OK
, "FolderItems::_NewEnum failed: %08lx\n", r
);
786 ok(!!unk
, "unk is null\n");
787 if (unk
) IUnknown_Release(unk
);
791 r
= FolderItems3_Filter(items3
, 0, NULL
);
793 ok(r
== S_OK
, "expected S_OK, got %08lx\n", r
);
795 if (0) /* crashes on xp */
797 r
= FolderItems3_get_Verbs(items3
, NULL
);
798 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08lx\n", r
);
801 r
= FolderItems3_get_Verbs(items3
, &verbs
);
803 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
804 ok(!verbs
, "verbs is not null\n");
807 /* remove the temporary directory and restore the original working directory */
808 GetTempPathW(MAX_PATH
, path
);
809 SetCurrentDirectoryW(path
);
810 ret
= RemoveDirectoryW(winetestW
);
811 ok(ret
, "RemoveDirectory failed: %08lx\n", GetLastError());
812 SetCurrentDirectoryW(orig_dir
);
814 /* test that everything stops working after the directory has been removed */
816 r
= FolderItems_get_Count(items
, &count
);
817 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
818 ok(!count
, "expected 0 files, got %ld\n", count
);
821 V_I4(&int_index
) = 0;
822 item
= (FolderItem
*)0xdeadbeef;
823 r
= FolderItems_Item(items
, int_index
, &item
);
824 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
825 ok(!item
, "item is not null\n");
827 variant_set_string(&str_index
, file_defs
[0].name
);
828 item
= (FolderItem
*)0xdeadbeef;
829 r
= FolderItems_Item(items
, str_index
, &item
);
830 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
831 ok(!item
, "item is not null\n");
832 VariantClear(&str_index
);
834 FolderItems_Release(items
);
835 Folder_Release(folder
);
836 if (items3
) FolderItems3_Release(items3
);
837 IShellDispatch_Release(sd
);
840 static void test_service(void)
842 static const WCHAR spooler
[] = {'S','p','o','o','l','e','r',0};
843 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
844 SERVICE_STATUS_PROCESS status
;
845 SC_HANDLE scm
, service
;
852 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
853 &IID_IShellDispatch2
, (void**)&sd
);
856 win_skip("IShellDispatch2 not supported\n");
862 hr
= IShellDispatch2_IsServiceRunning(sd
, NULL
, &v
);
863 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
864 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
867 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
868 service
= OpenServiceW(scm
, spooler
, SERVICE_QUERY_STATUS
);
869 QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
, sizeof(SERVICE_STATUS_PROCESS
), &dummy
);
870 CloseServiceHandle(service
);
871 CloseServiceHandle(scm
);
873 /* service should exist */
874 name
= SysAllocString(spooler
);
876 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
878 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
879 if (status
.dwCurrentState
== SERVICE_RUNNING
)
880 ok(V_BOOL(&v
) == VARIANT_TRUE
, "got %d\n", V_BOOL(&v
));
882 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
885 /* service doesn't exist */
886 name
= SysAllocString(dummyW
);
888 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
890 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
891 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
894 IShellDispatch2_Release(sd
);
897 static void test_dispatch_typeinfo(IDispatch
*disp
, REFIID
*riid
)
905 hr
= IDispatch_GetTypeInfoCount(disp
, &count
);
906 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
907 ok(count
== 1, "got %u\n", count
);
909 hr
= IDispatch_GetTypeInfo(disp
, 0, LOCALE_SYSTEM_DEFAULT
, &typeinfo
);
910 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
912 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
913 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
914 while (!IsEqualGUID(*riid
, &IID_NULL
)) {
915 if (IsEqualGUID(&typeattr
->guid
, *riid
))
919 ok(IsEqualGUID(&typeattr
->guid
, *riid
), "unexpected type guid %s\n", wine_dbgstr_guid(&typeattr
->guid
));
921 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
922 ITypeInfo_Release(typeinfo
);
925 static void test_ShellFolderViewDual(void)
927 static const IID
*shelldisp_riids
[] = {
928 &IID_IShellDispatch6
,
929 &IID_IShellDispatch5
,
930 &IID_IShellDispatch4
,
931 &IID_IShellDispatch2
,
932 &IID_IWin7ShellDispatch6
,
935 IShellFolderViewDual
*viewdual
;
936 IShellFolder
*desktop
, *tmpdir
;
937 IShellView
*view
, *view2
;
938 IDispatch
*disp
, *disp2
;
939 WCHAR pathW
[MAX_PATH
];
943 /* IShellFolderViewDual is not an IShellView extension */
944 hr
= SHGetDesktopFolder(&desktop
);
945 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
947 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
948 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
950 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
951 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
953 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
954 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
956 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp2
);
957 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
958 ok(disp2
== disp
, "got %p, %p\n", disp2
, disp
);
959 IDispatch_Release(disp2
);
961 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
962 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
963 ok(disp
== (IDispatch
*)viewdual
, "got %p, expected %p\n", viewdual
, disp
);
965 hr
= IShellFolderViewDual_QueryInterface(viewdual
, &IID_IShellView
, (void**)&view2
);
966 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
968 /* get_Application() */
970 if (0) /* crashes on pre-vista */ {
971 hr
= IShellFolderViewDual_get_Application(viewdual
, NULL
);
972 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
974 hr
= IShellFolderViewDual_get_Application(viewdual
, &disp2
);
975 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
976 ok(disp2
!= (IDispatch
*)viewdual
, "got %p, %p\n", disp2
, viewdual
);
977 test_dispatch_typeinfo(disp2
, shelldisp_riids
);
978 IDispatch_Release(disp2
);
980 IShellFolderViewDual_Release(viewdual
);
981 IDispatch_Release(disp
);
983 disp
= (void*)0xdeadbeef;
984 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IShellFolderViewDual
, (void**)&disp
);
985 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
) /* win2k */, "got 0x%08lx\n", hr
);
986 ok(disp
== NULL
, "got %p\n", disp
);
987 IShellView_Release(view
);
989 /* Try with some other folder, that's not a desktop */
990 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
991 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, pathW
, NULL
, &pidl
, NULL
);
992 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
994 hr
= IShellFolder_BindToObject(desktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&tmpdir
);
995 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
998 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
999 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1001 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
1002 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1004 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
1005 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1006 IDispatch_Release(disp
);
1007 IShellView_Release(view
);
1009 IShellFolder_Release(tmpdir
);
1010 IShellFolder_Release(desktop
);
1013 static void test_ShellWindows(void)
1015 IShellWindows
*shellwindows
;
1016 LONG cookie
, cookie2
, ret
;
1023 hr
= CoCreateInstance(&CLSID_ShellWindows
, NULL
, CLSCTX_LOCAL_SERVER
,
1024 &IID_IShellWindows
, (void**)&shellwindows
);
1025 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1026 /* TODO: remove when explorer startup with clean prefix is fixed */
1030 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, NULL
);
1031 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "got 0x%08lx\n", hr
);
1033 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, &cookie
);
1034 ok(hr
== E_POINTER
, "got 0x%08lx\n", hr
);
1036 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
1037 ok(hr
== E_POINTER
, "got 0x%08lx\n", hr
);
1039 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
1040 ok(hr
== E_POINTER
, "got 0x%08lx\n", hr
);
1042 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
1043 0, 0, 50, 14, 0, 0, 0, NULL
);
1044 ok(hwnd
!= NULL
, "got %p, error %ld\n", hwnd
, GetLastError());
1047 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie
);
1048 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1049 ok(cookie
!= 0, "got %ld\n", cookie
);
1052 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie2
);
1053 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1054 ok(cookie2
!= 0 && cookie2
!= cookie
, "got %ld\n", cookie2
);
1056 pidl
= ILCreateFromPathA("C:\\");
1057 V_VT(&v
) = VT_ARRAY
| VT_UI1
;
1058 V_ARRAY(&v
) = SafeArrayCreateVector(VT_UI1
, 0, ILGetSize(pidl
));
1059 memcpy(V_ARRAY(&v
)->pvData
, pidl
, ILGetSize(pidl
));
1062 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1063 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1064 ok(!ret
, "Got window %#lx.\n", ret
);
1065 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1067 hr
= IShellWindows_OnNavigate(shellwindows
, 0, &v
);
1068 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1070 hr
= IShellWindows_OnNavigate(shellwindows
, cookie
, &v
);
1071 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1073 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1074 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1075 ok(ret
== (LONG
)(LONG_PTR
)hwnd
, "Expected %p, got %#lx.\n", hwnd
, ret
);
1076 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1078 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
1079 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1081 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1082 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1083 ok(!ret
, "Got window %#lx.\n", ret
);
1084 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1086 hr
= IShellWindows_Revoke(shellwindows
, cookie2
);
1087 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1089 hr
= IShellWindows_Revoke(shellwindows
, 0);
1090 ok(hr
== S_FALSE
, "got 0x%08lx\n", hr
);
1092 /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
1094 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_DESKTOP
, &cookie
);
1095 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1096 ok(cookie
!= 0, "got %ld\n", cookie
);
1098 disp
= (void*)0xdeadbeef;
1101 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, SWFO_NEEDDISPATCH
, &disp
);
1102 ok(hr
== S_OK
|| broken(hr
== S_FALSE
), "got 0x%08lx\n", hr
);
1103 if (hr
== S_FALSE
) /* winxp and earlier */ {
1104 win_skip("SWC_DESKTOP is not supported, some tests will be skipped.\n");
1105 /* older versions allowed to register SWC_DESKTOP and access it with FindWindowSW */
1106 ok(disp
== NULL
, "got %p\n", disp
);
1107 ok(ret
== 0, "got %ld\n", ret
);
1110 static const IID
*browser_riids
[] = {
1115 static const IID
*viewdual_riids
[] = {
1116 &IID_IShellFolderViewDual3
,
1120 IShellFolderViewDual
*view
;
1121 IShellBrowser
*sb
, *sb2
;
1122 IServiceProvider
*sp
;
1123 IDispatch
*doc
, *app
;
1128 ok(disp
!= NULL
, "got %p\n", disp
);
1129 ok(ret
!= HandleToUlong(hwnd
), "got %ld\n", ret
);
1131 /* IDispatch-related tests */
1132 test_dispatch_typeinfo(disp
, browser_riids
);
1135 hr
= IDispatch_QueryInterface(disp
, &IID_IWebBrowser2
, (void**)&wb
);
1136 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1138 hr
= IWebBrowser2_Refresh(wb
);
1140 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1142 hr
= IWebBrowser2_get_Application(wb
, &app
);
1143 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1144 ok(disp
== app
, "got %p, %p\n", app
, disp
);
1145 IDispatch_Release(app
);
1147 hr
= IWebBrowser2_get_Document(wb
, &doc
);
1149 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1151 test_dispatch_typeinfo(doc
, viewdual_riids
);
1153 IWebBrowser2_Release(wb
);
1155 /* IServiceProvider */
1156 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&view
);
1157 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1159 hr
= IDispatch_QueryInterface(disp
, &IID_IServiceProvider
, (void**)&sp
);
1160 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1162 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb
);
1163 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1165 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb2
);
1166 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1167 ok(sb
== sb2
, "got %p, %p\n", sb
, sb2
);
1169 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IOleWindow
, (void**)&unk
);
1170 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1171 IUnknown_Release(unk
);
1173 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IExplorerBrowser
, (void**)&unk
);
1174 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1176 hr
= IShellBrowser_QueryInterface(sb
, &IID_IExplorerBrowser
, (void**)&unk
);
1177 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1179 hr
= IShellBrowser_QueryInterface(sb
, &IID_IWebBrowser2
, (void**)&unk
);
1180 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1182 hr
= IShellBrowser_QueryInterface(sb
, &IID_IDispatch
, (void**)&unk
);
1183 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1185 hr
= IShellBrowser_QueryActiveShellView(sb
, &sv
);
1186 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1187 IShellView_Release(sv
);
1189 IShellBrowser_Release(sb2
);
1190 IShellBrowser_Release(sb
);
1192 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IUnknown
, (void**)&unk
);
1193 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1195 hr
= IUnknown_QueryInterface(unk
, &IID_IShellBrowser
, (void**)&sb2
);
1196 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1197 IShellBrowser_Release(sb2
);
1198 IUnknown_Release(unk
);
1200 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellView
, (void**)&sv
);
1201 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1203 IServiceProvider_Release(sp
);
1204 IDispatch_Release(disp
);
1207 disp
= (void*)0xdeadbeef;
1210 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, 0, &disp
);
1211 ok(hr
== S_OK
|| broken(hr
== S_FALSE
) /* winxp */, "got 0x%08lx\n", hr
);
1212 ok(disp
== NULL
, "got %p\n", disp
);
1213 ok(ret
!= HandleToUlong(hwnd
), "got %ld\n", ret
);
1215 disp
= (void*)0xdeadbeef;
1220 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_BROWSER
, &ret
, SWFO_COOKIEPASSED
, &disp
);
1222 ok(hr
== S_FALSE
, "got 0x%08lx\n", hr
);
1223 ok(disp
== NULL
, "got %p\n", disp
);
1224 ok(ret
== 0, "got %ld\n", ret
);
1226 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
1227 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1228 DestroyWindow(hwnd
);
1229 IShellWindows_Release(shellwindows
);
1232 static void test_ParseName(void)
1234 static const WCHAR cadabraW
[] = {'c','a','d','a','b','r','a',0};
1235 WCHAR pathW
[MAX_PATH
];
1243 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1244 &IID_IShellDispatch
, (void**)&sd
);
1245 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1247 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
1249 V_BSTR(&v
) = SysAllocString(pathW
);
1250 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1251 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1254 item
= (void*)0xdeadbeef;
1255 hr
= Folder_ParseName(folder
, NULL
, &item
);
1256 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08lx\n", hr
);
1257 ok(item
== NULL
, "got %p\n", item
);
1260 str
= SysAllocStringLen(NULL
, 0);
1261 item
= (void*)0xdeadbeef;
1262 hr
= Folder_ParseName(folder
, str
, &item
);
1263 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08lx\n", hr
);
1264 ok(item
== NULL
, "got %p\n", item
);
1267 /* path doesn't exist */
1268 str
= SysAllocString(cadabraW
);
1269 item
= (void*)0xdeadbeef;
1270 hr
= Folder_ParseName(folder
, str
, &item
);
1271 ok(hr
== S_FALSE
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* win2k */,
1272 "got 0x%08lx\n", hr
);
1273 ok(item
== NULL
, "got %p\n", item
);
1276 lstrcatW(pathW
, cadabraW
);
1277 CreateDirectoryW(pathW
, NULL
);
1279 str
= SysAllocString(cadabraW
);
1281 hr
= Folder_ParseName(folder
, str
, &item
);
1282 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1283 ok(item
!= NULL
, "got %p\n", item
);
1286 hr
= FolderItem_get_Path(item
, &str
);
1287 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1288 ok(str
[0] != 0, "path %s\n", wine_dbgstr_w(str
));
1291 RemoveDirectoryW(pathW
);
1292 FolderItem_Release(item
);
1293 Folder_Release(folder
);
1294 IShellDispatch_Release(sd
);
1297 static void test_Verbs(void)
1299 FolderItemVerbs
*verbs
, *verbs2
;
1300 WCHAR pathW
[MAX_PATH
];
1301 FolderItemVerb
*verb
;
1312 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1313 &IID_IShellDispatch
, (void**)&sd
);
1314 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1316 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
1318 V_BSTR(&v
) = SysAllocString(pathW
);
1319 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1320 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1323 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
1324 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1325 Folder_Release(folder
);
1327 hr
= Folder2_get_Self(folder2
, &item
);
1328 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1329 Folder2_Release(folder2
);
1331 if (0) { /* crashes on some systems */
1332 hr
= FolderItem_Verbs(item
, NULL
);
1333 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
1335 hr
= FolderItem_Verbs(item
, &verbs
);
1336 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1338 hr
= FolderItem_Verbs(item
, &verbs2
);
1339 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1340 ok(verbs2
!= verbs
, "Unexpected verbs pointer.\n");
1341 FolderItemVerbs_Release(verbs2
);
1343 disp
= (void *)0xdeadbeef;
1344 hr
= FolderItemVerbs_get_Application(verbs
, &disp
);
1345 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1346 ok(disp
== NULL
, "Unexpected application pointer.\n");
1348 disp
= (void *)0xdeadbeef;
1349 hr
= FolderItemVerbs_get_Parent(verbs
, &disp
);
1350 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1351 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1353 if (0) { /* crashes on winxp/win2k3 */
1354 hr
= FolderItemVerbs_get_Count(verbs
, NULL
);
1355 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
1358 hr
= FolderItemVerbs_get_Count(verbs
, &count
);
1359 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1360 ok(count
> 0, "got count %ld\n", count
);
1362 if (0) { /* crashes on winxp/win2k3 */
1365 hr
= FolderItemVerbs_Item(verbs
, v
, NULL
);
1366 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
1368 /* there's always one item more, so you can access [0,count],
1369 instead of actual [0,count) */
1370 for (i
= 0; i
<= count
; i
++) {
1373 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1374 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1375 hr
= FolderItemVerb_get_Name(verb
, &str
);
1376 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1377 ok(str
!= NULL
, "%ld: name %s\n", i
, wine_dbgstr_w(str
));
1379 ok(str
[0] == 0, "%ld: got terminating item %s\n", i
, wine_dbgstr_w(str
));
1381 disp
= (void *)0xdeadbeef;
1382 hr
= FolderItemVerb_get_Parent(verb
, &disp
);
1383 ok(hr
== E_NOTIMPL
, "got %#lx.\n", hr
);
1384 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1386 disp
= (void *)0xdeadbeef;
1387 hr
= FolderItemVerb_get_Application(verb
, &disp
);
1388 ok(hr
== E_NOTIMPL
, "got %#lx.\n", hr
);
1389 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1392 FolderItemVerb_Release(verb
);
1398 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1399 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1400 ok(verb
== NULL
, "got %p\n", verb
);
1402 FolderItemVerbs_Release(verbs
);
1403 FolderItem_Release(item
);
1404 IShellDispatch_Release(sd
);
1407 static void test_ShellLinkObject(void)
1411 WCHAR path
[MAX_PATH
],
1412 empty_path
[MAX_PATH
],
1413 link_path
[MAX_PATH
];
1418 IDispatch
*dispatch
;
1420 IShellLinkDual2
* sld
;
1427 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1428 &IID_IShellDispatch
, (void**)&sd
);
1429 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1431 GetTempPathW(MAX_PATH
, path
);
1433 V_BSTR(&v
) = SysAllocString(path
);
1434 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1435 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1438 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
1439 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1440 Folder_Release(folder
);
1442 hr
= Folder2_get_Self(folder2
, &item
);
1443 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1445 dispatch
= (IDispatch
*)0xdeadbeef;
1446 hr
= FolderItem_get_GetLink(item
, &dispatch
);
1447 ok(hr
== E_NOTIMPL
, "got 0x%08lx\n", hr
);
1448 ok(dispatch
== NULL
, "got %p\n", dispatch
);
1450 FolderItem_Release(item
);
1452 PathCombineW(empty_path
, path
, L
"winetest_empty_file.txt");
1453 file
= CreateFileW(empty_path
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1454 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08lx\n", GetLastError());
1457 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLinkW
, (LPVOID
*)&sl
);
1458 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1459 hr
= IShellLinkW_SetPath(sl
, empty_path
);
1460 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1461 hr
= IShellLinkW_GetPath(sl
, empty_path
, MAX_PATH
, NULL
, 0);
1462 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1463 hr
= IShellLinkW_SetDescription(sl
, L
"description");
1464 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1465 hr
= IShellLinkW_SetWorkingDirectory(sl
, L
"working directory");
1466 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1467 hr
= IShellLinkW_SetArguments(sl
, L
"arguments");
1468 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1469 hr
= IShellLinkW_SetHotkey(sl
, 1234);
1470 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1471 hr
= IShellLinkW_SetShowCmd(sl
, 1);
1472 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1474 hr
= IShellLinkW_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
1475 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1477 PathCombineW(link_path
, path
, L
"winetest_filled.lnk");
1478 hr
= IPersistFile_Save(pf
, link_path
, TRUE
);
1479 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1481 IPersistFile_Release(pf
);
1482 IShellLinkW_Release(sl
);
1484 str
= SysAllocString(L
"winetest_filled.lnk");
1485 hr
= Folder2_ParseName(folder2
, str
, &item
);
1486 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1490 hr
= FolderItem_get_GetLink(item
, &dispatch
);
1491 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1492 ok(dispatch
!= NULL
, "got %p\n", dispatch
);
1495 sld
= (IShellLinkDual2
*)dispatch
;
1498 hr
= IShellLinkDual2_get_Path(sld
, &str
);
1499 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1501 ok(!wcscmp(str
, empty_path
), "got %s (wanted %s)\n",
1502 wine_dbgstr_w(str
), wine_dbgstr_w(empty_path
));
1507 hr
= IShellLinkDual2_get_Description(sld
, &str
);
1508 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1510 ok(!wcscmp(str
, L
"description"), "got %s\n", wine_dbgstr_w(str
));
1515 hr
= IShellLinkDual2_get_WorkingDirectory(sld
, &str
);
1516 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1518 ok(!wcscmp(str
, L
"working directory"), "got %s\n", wine_dbgstr_w(str
));
1523 hr
= IShellLinkDual2_get_Arguments(sld
, &str
);
1524 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1526 ok(!wcscmp(str
, L
"arguments"), "got %s\n", wine_dbgstr_w(str
));
1531 hr
= IShellLinkDual2_get_Hotkey(sld
, &hk
);
1532 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1533 todo_wine
ok(hk
== 1234, "got %i\n", hk
);
1536 hr
= IShellLinkDual2_get_ShowCommand(sld
, &hk
);
1537 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1538 todo_wine
ok(hk
== 1, "got %i\n", hk
);
1540 IShellLinkDual2_Release(sld
);
1543 FolderItem_Release(item
);
1545 ret
= DeleteFileW(link_path
);
1546 ok(ret
, "DeleteFile failed: %08lx\n", GetLastError());
1547 ret
= DeleteFileW(empty_path
);
1548 ok(ret
, "DeleteFile failed: %08lx\n", GetLastError());
1550 Folder2_Release(folder2
);
1552 IShellDispatch_Release(sd
);
1555 static void test_ShellExecute(void)
1558 IShellDispatch2
*sd
;
1560 VARIANT args
, dir
, op
, show
;
1562 static const WCHAR regW
[] = {'r','e','g',0};
1564 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1565 &IID_IShellDispatch2
, (void**)&sd
);
1568 win_skip("IShellDispatch2 not supported\n");
1577 V_VT(&show
) = VT_I4
;
1580 name
= SysAllocString(regW
);
1582 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1583 ok(hr
== S_OK
, "ShellExecute failed: %08lx\n", hr
);
1585 /* test invalid value for show */
1586 V_VT(&show
) = VT_BSTR
;
1587 V_BSTR(&show
) = name
;
1589 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1590 ok(hr
== S_OK
, "ShellExecute failed: %08lx\n", hr
);
1592 SysFreeString(name
);
1593 IShellDispatch2_Release(sd
);
1596 START_TEST(shelldispatch
)
1600 r
= CoInitialize(NULL
);
1601 ok(SUCCEEDED(r
), "CoInitialize failed: %08lx\n", r
);
1605 init_function_pointers();
1609 test_ShellFolderViewDual();
1610 test_ShellWindows();
1613 test_ShellLinkObject();
1614 test_ShellExecute();