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/heap.h"
31 #include "wine/test.h"
35 #define EXPECT_HR(hr,hr_exp) \
36 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
38 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
39 static void _expect_ref(IUnknown
*obj
, ULONG ref
, int line
)
43 rc
= IUnknown_Release(obj
);
44 ok_(__FILE__
,line
)(rc
== ref
, "Unexpected refcount %d, expected %d\n", rc
, ref
);
47 static const WCHAR winetestW
[] = {'w','i','n','e','t','e','s','t',0};
49 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
51 /* Updated Windows 7 has a new IShellDispatch6 in its typelib */
52 DEFINE_GUID(IID_IWin7ShellDispatch6
, 0x34936ba1, 0x67ad, 0x4c41, 0x99,0xb8, 0x8c,0x12,0xdf,0xf1,0xe9,0x74);
54 static BSTR
a2bstr(const char *str
)
59 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
60 ret
= SysAllocStringLen(NULL
, len
);
61 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
66 static void variant_set_string(VARIANT
*v
, const char *s
)
69 V_BSTR(v
) = a2bstr(s
);
72 static void init_function_pointers(void)
76 hshell32
= GetModuleHandleA("shell32.dll");
77 pSHGetNameFromIDList
= (void*)GetProcAddress(hshell32
, "SHGetNameFromIDList");
80 static void test_namespace(void)
82 static const ShellSpecialFolderConstants special_folders
[] =
124 static const WCHAR backslashW
[] = {'\\',0};
125 static const WCHAR clsidW
[] = {
126 ':',':','{','6','4','5','F','F','0','4','0','-','5','0','8','1','-',
127 '1','0','1','B','-','9','F','0','8','-',
128 '0','0','A','A','0','0','2','F','9','5','4','E','}',0};
130 static WCHAR tempW
[MAX_PATH
], curW
[MAX_PATH
];
131 WCHAR
*long_pathW
= NULL
;
138 BSTR title
, item_path
;
142 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void **)&sd
);
143 ok(SUCCEEDED(r
), "Failed to create ShellDispatch object: %#x.\n", r
);
146 r
= IShellDispatch_get_Application(sd
, &disp
);
147 ok(r
== S_OK
, "Failed to get application pointer, hr %#x.\n", r
);
148 ok(disp
== (IDispatch
*)sd
, "Unexpected application pointer %p.\n", disp
);
149 IDispatch_Release(disp
);
152 r
= IShellDispatch_get_Parent(sd
, &disp
);
153 ok(r
== S_OK
, "Failed to get Shell object parent, hr %#x.\n", r
);
154 ok(disp
== (IDispatch
*)sd
, "Unexpected parent pointer %p.\n", disp
);
155 IDispatch_Release(disp
);
158 folder
= (void*)0xdeadbeef;
159 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
160 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
161 ok(folder
== NULL
, "expected NULL, got %p\n", folder
);
163 /* test valid folder ids */
164 for (i
= 0; i
< ARRAY_SIZE(special_folders
); i
++)
167 V_I4(&var
) = special_folders
[i
];
168 folder
= (void*)0xdeadbeef;
169 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
170 if (special_folders
[i
] == ssfALTSTARTUP
|| special_folders
[i
] == ssfCOMMONALTSTARTUP
)
172 ok(r
== S_OK
|| broken(r
== S_FALSE
) /* winxp */, "Failed to get folder for index %#x, got %08x\n", special_folders
[i
], r
);
174 ok(r
== S_OK
, "Failed to get folder for index %#x, got %08x\n", special_folders
[i
], r
);
176 Folder_Release(folder
);
181 folder
= (void *)0xdeadbeef;
182 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
183 ok(r
== S_FALSE
, "Unexpected hr %#x.\n", r
);
184 ok(folder
== NULL
, "Unexpected folder instance %p\n", folder
);
187 V_I4(&var
) = ssfPROGRAMFILES
;
188 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
189 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
192 static WCHAR path
[MAX_PATH
];
194 r
= SHGetFolderPathW(NULL
, CSIDL_PROGRAM_FILES
, NULL
, SHGFP_TYPE_CURRENT
, path
);
195 ok(r
== S_OK
, "Failed to get folder path: %#x.\n", r
);
197 r
= Folder_get_Title(folder
, &title
);
198 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
201 /* On Win2000-2003 title is equal to program files directory name in
202 HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir.
203 On newer Windows it seems constant and is not changed
204 if the program files directory name is changed */
205 if (pSHGetNameFromIDList
)
210 r
= SHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidl
);
211 ok(r
== S_OK
, "SHGetSpecialFolderLocation failed: %08x\n", r
);
212 r
= pSHGetNameFromIDList(pidl
, SIGDN_NORMALDISPLAY
, &name
);
213 ok(r
== S_OK
, "SHGetNameFromIDList failed: %08x\n", r
);
214 ok(!lstrcmpW(title
, name
), "expected %s, got %s\n", wine_dbgstr_w(name
), wine_dbgstr_w(title
));
222 p
= path
+ lstrlenW(path
);
223 while (path
< p
&& *(p
- 1) != '\\')
225 ok(!lstrcmpiW(title
, p
), "expected %s, got %s\n",
226 wine_dbgstr_w(p
), wine_dbgstr_w(title
));
228 SysFreeString(title
);
230 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
231 ok(r
== S_OK
, "Folder::QueryInterface failed: %08x\n", r
);
234 r
= Folder2_get_Self(folder2
, &item
);
235 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
238 r
= FolderItem_get_Path(item
, &item_path
);
239 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
240 ok(!lstrcmpiW(item_path
, path
), "expected %s, got %s\n", wine_dbgstr_w(path
), wine_dbgstr_w(item_path
));
241 SysFreeString(item_path
);
242 FolderItem_Release(item
);
244 Folder2_Release(folder2
);
246 Folder_Release(folder
);
250 V_I4(&var
) = ssfBITBUCKET
;
251 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
252 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
254 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (void **)&folder2
);
255 ok(r
== S_OK
, "Failed to get Folder2 interface: %#x.\n", r
);
256 r
= Folder2_get_Self(folder2
, &item
);
257 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
258 r
= FolderItem_get_Path(item
, &item_path
);
259 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
260 /* TODO: we return lowercase GUID here */
261 ok(!lstrcmpiW(item_path
, clsidW
), "expected %s, got %s\n", wine_dbgstr_w(clsidW
), wine_dbgstr_w(item_path
));
263 SysFreeString(item_path
);
264 FolderItem_Release(item
);
265 Folder2_Release(folder2
);
266 Folder_Release(folder
);
268 GetTempPathW(MAX_PATH
, tempW
);
269 GetCurrentDirectoryW(MAX_PATH
, curW
);
270 SetCurrentDirectoryW(tempW
);
271 CreateDirectoryW(winetestW
, NULL
);
272 V_VT(&var
) = VT_BSTR
;
273 V_BSTR(&var
) = SysAllocString(winetestW
);
274 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
275 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
276 SysFreeString(V_BSTR(&var
));
278 GetFullPathNameW(winetestW
, MAX_PATH
, tempW
, NULL
);
280 len
= GetLongPathNameW(tempW
, NULL
, 0);
281 long_pathW
= heap_alloc(len
* sizeof(WCHAR
));
282 GetLongPathNameW(tempW
, long_pathW
, len
);
284 V_VT(&var
) = VT_BSTR
;
285 V_BSTR(&var
) = SysAllocString(tempW
);
286 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
287 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
289 disp
= (void *)0xdeadbeef;
290 r
= Folder_get_Parent(folder
, &disp
);
291 ok(r
== E_NOTIMPL
, "Unexpected hr %#x.\n", r
);
292 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
294 r
= Folder_get_Title(folder
, &title
);
295 ok(r
== S_OK
, "Failed to get folder title: %#x.\n", r
);
296 ok(!lstrcmpW(title
, winetestW
), "Unexpected title: %s\n", wine_dbgstr_w(title
));
297 SysFreeString(title
);
299 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (void **)&folder2
);
300 ok(r
== S_OK
, "Failed to get Folder2 interface: %#x.\n", r
);
301 r
= Folder2_get_Self(folder2
, &item
);
302 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
303 r
= FolderItem_get_Path(item
, &item_path
);
304 ok(r
== S_OK
, "Failed to get item path: %#x.\n", r
);
305 ok(!lstrcmpW(item_path
, long_pathW
), "Unexpected path %s, got %s\n", wine_dbgstr_w(item_path
), wine_dbgstr_w(long_pathW
));
306 SysFreeString(item_path
);
307 FolderItem_Release(item
);
308 Folder2_Release(folder2
);
310 Folder_Release(folder
);
313 len
= lstrlenW(tempW
);
314 if (len
< MAX_PATH
- 1)
316 lstrcatW(tempW
, backslashW
);
317 V_VT(&var
) = VT_BSTR
;
318 V_BSTR(&var
) = SysAllocString(tempW
);
319 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
320 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
323 r
= Folder_get_Title(folder
, &title
);
324 ok(r
== S_OK
, "Folder::get_Title failed: %08x\n", r
);
327 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
328 wine_dbgstr_w(title
));
329 SysFreeString(title
);
331 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
332 ok(r
== S_OK
, "Failed to get Folder2 interface: %#x.\n", r
);
335 r
= Folder2_get_Self(folder2
, &item
);
336 ok(r
== S_OK
, "Folder::get_Self failed: %08x\n", r
);
339 r
= FolderItem_get_Path(item
, &item_path
);
340 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
341 ok(!lstrcmpW(item_path
, long_pathW
), "Unexpected path %s, got %s\n", wine_dbgstr_w(item_path
),
342 wine_dbgstr_w(long_pathW
));
343 SysFreeString(item_path
);
344 FolderItem_Release(item
);
346 Folder2_Release(folder2
);
348 Folder_Release(folder
);
350 SysFreeString(V_BSTR(&var
));
353 heap_free(long_pathW
);
354 RemoveDirectoryW(winetestW
);
355 SetCurrentDirectoryW(curW
);
356 IShellDispatch_Release(sd
);
359 static void test_items(void)
373 { "00-Myfolder", DIRECTORY
},
374 { "01-empty.bin", EMPTY_FILE
},
376 WCHAR path
[MAX_PATH
], cur_dir
[MAX_PATH
], orig_dir
[MAX_PATH
];
378 IShellDispatch
*sd
= NULL
;
379 Folder
*folder
= NULL
;
381 FolderItems2
*items2
= NULL
;
382 FolderItems3
*items3
= NULL
;
383 FolderItem
*item
= (FolderItem
*)0xdeadbeef, *item2
;
384 FolderItemVerbs
*verbs
= (FolderItemVerbs
*)0xdeadbeef;
385 VARIANT var
, var2
, int_index
, str_index
, str_index2
;
386 IDispatch
*disp
, *disp2
;
395 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void**)&sd
);
396 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08x\n", r
);
397 ok(!!sd
, "sd is null\n");
399 /* create and enter a temporary directory and a folder object for it */
400 GetTempPathW(MAX_PATH
, path
);
401 GetCurrentDirectoryW(MAX_PATH
, orig_dir
);
402 SetCurrentDirectoryW(path
);
403 ret
= CreateDirectoryW(winetestW
, NULL
);
404 ok(ret
, "CreateDirectory failed: %08x\n", GetLastError());
405 GetFullPathNameW(winetestW
, MAX_PATH
, path
, NULL
);
406 V_VT(&var
) = VT_BSTR
;
407 V_BSTR(&var
) = SysAllocString(path
);
410 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
411 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08x\n", r
);
412 ok(!!folder
, "folder is null\n");
413 EXPECT_REF(folder
, 1);
417 SetCurrentDirectoryW(winetestW
);
418 GetCurrentDirectoryW(MAX_PATH
, path
);
419 GetLongPathNameW(path
, cur_dir
, MAX_PATH
);
421 /* FolderItems grabs its Folder reference */
423 r
= Folder_Items(folder
, &items
);
424 ok(r
== S_OK
, "Folder::Items failed: %08x\n", r
);
425 ok(!!items
, "items is null\n");
426 EXPECT_REF(folder
, 2);
427 EXPECT_REF(items
, 1);
430 r
= Folder_Items(folder
, (FolderItems
**)&unk
);
431 ok(r
== S_OK
, "Folder::Items failed: %08x\n", r
);
432 EXPECT_REF(folder
, 3);
433 IUnknown_Release(unk
);
434 EXPECT_REF(folder
, 2);
436 FolderItems_AddRef(items
);
437 EXPECT_REF(folder
, 2);
438 FolderItems_Release(items
);
440 /* Application property */
443 r
= Folder_get_Application(folder
, &disp
);
444 ok(r
== S_OK
, "Failed to get application %#x.\n", r
);
445 ok(disp
!= (IDispatch
*)sd
, "Unexpected application pointer\n");
449 r
= Folder_get_Application(folder
, &disp2
);
450 ok(r
== S_OK
, "Failed to get application %#x.\n", r
);
451 ok(disp2
== disp
, "Unexpected application pointer\n");
452 IDispatch_Release(disp2
);
454 r
= IDispatch_QueryInterface(disp
, &IID_IShellDispatch
, (void **)&disp2
);
455 ok(r
== S_OK
, "Wrong instance, hr %#x.\n", r
);
456 IDispatch_Release(disp2
);
457 IDispatch_Release(disp
);
459 if (0) /* crashes on all versions of Windows */
460 r
= FolderItems_get_Count(items
, NULL
);
462 r
= FolderItems_get_Count(items
, &count
);
463 ok(r
== S_OK
, "FolderItems::get_Count failed: %08x\n", r
);
464 ok(!count
, "expected 0 files, got %d\n", count
);
469 if (0) /* crashes on all versions of Windows */
470 r
= FolderItems_Item(items
, var
, NULL
);
472 r
= FolderItems_Item(items
, var
, &item
);
473 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
474 ok(!item
, "item is not null\n");
476 /* create test files */
477 for (i
= 0; i
< ARRAY_SIZE(file_defs
); i
++)
479 switch (file_defs
[i
].type
)
482 r
= CreateDirectoryA(file_defs
[i
].name
, NULL
);
483 ok(r
, "CreateDirectory failed: %08x\n", GetLastError());
484 PathCombineA(cstr
, file_defs
[i
].name
, "foo.txt");
485 file
= CreateFileA(cstr
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
486 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08x\n", GetLastError());
491 file
= CreateFileA(file_defs
[i
].name
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
492 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08x\n", GetLastError());
498 /* test that get_Count is not aware of the newly created files */
500 r
= FolderItems_get_Count(items
, &count
);
501 ok(r
== S_OK
, "FolderItems::get_Count failed: %08x\n", r
);
502 ok(!count
, "expected 0 files, got %d\n", count
);
504 /* test that the newly created files CAN be retrieved by string index */
505 variant_set_string(&var
, file_defs
[0].name
);
507 r
= FolderItems_Item(items
, var
, &item
);
508 ok(r
== S_OK
, "FolderItems::Item failed: %08x\n", r
);
509 ok(!!item
, "item is null\n");
511 disp
= (void *)0xdeadbeef;
512 r
= FolderItems_get_Parent(items
, &disp
);
513 ok(r
== E_NOTIMPL
, "Unexpected hr %#x.\n", r
);
514 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
516 r
= FolderItem_get_Parent(item
, &disp
);
517 ok(r
== S_OK
, "Failed to get parent pointer, hr %#x.\n", r
);
518 ok(disp
== (IDispatch
*)folder
, "Unexpected parent pointer %p.\n", disp
);
519 IDispatch_Release(disp
);
521 if (item
) FolderItem_Release(item
);
524 /* recreate the items object */
525 FolderItems_Release(items
);
527 r
= Folder_Items(folder
, &items
);
528 ok(r
== S_OK
, "Folder::Items failed: %08x\n", r
);
529 ok(!!items
, "items is null\n");
530 r
= FolderItems_QueryInterface(items
, &IID_FolderItems2
, (void**)&items2
);
531 ok(r
== S_OK
|| broken(r
== E_NOINTERFACE
) /* xp and later */, "FolderItems::QueryInterface failed: %08x\n", r
);
534 ok(!!items2
, "items2 is null\n");
535 FolderItems2_Release(items2
);
537 r
= FolderItems_QueryInterface(items
, &IID_FolderItems3
, (void**)&items3
);
538 ok(r
== S_OK
, "FolderItems::QueryInterface failed: %08x\n", r
);
539 ok(!!items3
, "items3 is null\n");
542 r
= FolderItems_get_Count(items
, &count
);
543 ok(r
== S_OK
, "FolderItems::get_Count failed: %08x\n", r
);
544 ok(count
== ARRAY_SIZE(file_defs
), "got %d files\n", count
);
547 V_VT(&var
) = VT_EMPTY
;
548 item
= (FolderItem
*)0xdeadbeef;
549 r
= FolderItems_Item(items
, var
, &item
);
550 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
551 ok(!item
, "item is not null\n");
557 EXPECT_REF(folder
, 2);
558 EXPECT_REF(items
, 2);
560 r
= FolderItems_Item(items
, var
, &item
);
561 ok(r
== S_OK
, "FolderItems::Item failed: %08x\n", r
);
562 ok(!!item
, "item is null\n");
563 EXPECT_REF(folder
, 3);
564 EXPECT_REF(items
, 2);
566 r
= Folder_get_Application(folder
, &disp
);
567 ok(r
== S_OK
, "Failed to get application pointer %#x.\n", r
);
568 r
= FolderItem_get_Application(item
, &disp2
);
569 ok(r
== S_OK
, "Failed to get application pointer %#x.\n", r
);
570 ok(disp
== disp2
, "Unexpected application pointer.\n");
571 IDispatch_Release(disp2
);
572 IDispatch_Release(disp
);
574 FolderItem_Release(item
);
576 /* VT_VARIANT | VT_BYREF */
580 V_VT(&var
) = VT_BYREF
| VT_VARIANT
;
581 V_VARIANTREF(&var
) = &var2
;
584 r
= FolderItems_Item(items
, var
, &item
);
585 ok(r
== S_OK
, "FolderItems::Item failed: %08x\n", r
);
586 ok(!!item
, "item is null\n");
587 FolderItem_Release(item
);
593 r
= FolderItems_Item(items
, var
, &item
);
594 ok(r
== S_OK
, "FolderItems::Item failed: %08x\n", r
);
595 ok(!!item
, "item is null\n");
596 if (item
) FolderItem_Release(item
);
599 item
= (FolderItem
*)0xdeadbeef;
600 r
= FolderItems_Item(items
, var
, &item
);
601 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
602 ok(!item
, "item is not null\n");
604 V_VT(&var
) = VT_ERROR
;
607 r
= FolderItems_Item(items
, var
, &item
);
608 ok(r
== S_OK
, "expected S_OK, got %08x\n", r
);
609 ok(!!item
, "item is null\n");
613 r
= FolderItem_get_Path(item
, &bstr
);
614 ok(r
== S_OK
, "FolderItem::get_Path failed: %08x\n", r
);
615 ok(!lstrcmpW(bstr
, cur_dir
),
616 "expected %s, got %s\n", wine_dbgstr_w(cur_dir
), wine_dbgstr_w(bstr
));
618 FolderItem_Release(item
);
621 V_VT(&int_index
) = VT_I4
;
623 /* test the folder item corresponding to each file */
624 for (i
= 0; i
< ARRAY_SIZE(file_defs
); i
++)
629 V_I4(&int_index
) = i
;
630 variant_set_string(&str_index
, file_defs
[i
].name
);
633 r
= FolderItems_Item(items
, int_index
, &item
);
634 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08x\n", i
, r
);
635 ok(!!item
, "file_defs[%d]: item is null\n", i
);
638 r
= FolderItems_Item(items
, int_index
, &item2
);
639 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08x\n", i
, r
);
640 ok(item2
!= item
, "file_defs[%d]: item and item2 are the same\n", i
);
641 FolderItem_Release(item2
);
644 r
= FolderItem_get_Path(item
, &bstr
);
645 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08x\n", i
, r
);
646 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
647 ok(!lstrcmpW(bstr
, path
),
648 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
651 bstr
= a2bstr(file_defs
[i
].name
);
652 r
= FolderItem_get_Name(item
, &name
);
653 ok(r
== S_OK
, "Failed to get item name, hr %#x.\n", r
);
654 /* Returned display name does not have to strictly match file name, e.g. extension could be omitted. */
655 ok(lstrlenW(name
) <= lstrlenW(bstr
), "file_defs[%d]: unexpected name length.\n", i
);
656 ok(!memcmp(bstr
, name
, lstrlenW(name
) * sizeof(WCHAR
)), "file_defs[%d]: unexpected name %s.\n", i
, wine_dbgstr_w(name
));
660 FolderItem_Release(item
);
663 r
= FolderItems_Item(items
, str_index
, &item
);
664 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08x\n", i
, r
);
665 ok(!!item
, "file_defs[%d]: item is null\n", i
);
668 r
= FolderItem_get_Path(item
, &bstr
);
669 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08x\n", i
, r
);
670 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
671 ok(!lstrcmpW(bstr
, path
),
672 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
676 r
= FolderItem_get_IsFolder(item
, &b
);
677 ok(r
== S_OK
, "Failed to get IsFolder property, %#x.\n", r
);
678 ok(file_defs
[i
].type
== DIRECTORY
? b
== VARIANT_TRUE
: b
== VARIANT_FALSE
, "Unexpected prop value %#x.\n", b
);
680 FolderItem_Release(item
);
682 if (file_defs
[i
].type
== DIRECTORY
)
684 /* test that getting an item object for a file in a subdirectory succeeds */
685 PathCombineA(cstr
, file_defs
[i
].name
, "foo.txt");
686 variant_set_string(&str_index2
, cstr
);
688 r
= FolderItems_Item(items
, str_index2
, &item2
);
689 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08x\n", i
, r
);
690 ok(!!item2
, "file_defs[%d]: item is null\n", i
);
691 if (item2
) FolderItem_Release(item2
);
692 VariantClear(&str_index2
);
694 /* delete the file in the subdirectory */
695 ret
= DeleteFileA(cstr
);
696 ok(ret
, "file_defs[%d]: DeleteFile failed: %08x\n", i
, GetLastError());
698 /* test that getting an item object via a relative path fails */
699 strcpy(cstr
, file_defs
[i
].name
);
700 strcat(cstr
, "\\..\\");
701 strcat(cstr
, file_defs
[i
].name
);
702 variant_set_string(&str_index2
, cstr
);
703 item2
= (FolderItem
*)0xdeadbeef;
704 r
= FolderItems_Item(items
, str_index2
, &item2
);
706 ok(r
== S_FALSE
, "file_defs[%d]: expected S_FALSE, got %08x\n", i
, r
);
707 ok(!item2
, "file_defs[%d]: item is not null\n", i
);
709 if (item2
) FolderItem_Release(item2
);
710 VariantClear(&str_index2
);
712 /* remove the directory */
713 ret
= RemoveDirectoryA(file_defs
[i
].name
);
714 ok(ret
, "file_defs[%d]: RemoveDirectory failed: %08x\n", i
, GetLastError());
718 ret
= DeleteFileA(file_defs
[i
].name
);
719 ok(ret
, "file_defs[%d]: DeleteFile failed: %08x\n", i
, GetLastError());
722 /* test that the folder item is still accessible by integer index */
724 r
= FolderItems_Item(items
, int_index
, &item
);
725 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08x\n", i
, r
);
726 ok(!!item
, "file_defs[%d]: item is null\n", i
);
729 r
= FolderItem_get_Path(item
, &bstr
);
730 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08x\n", i
, r
);
731 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
732 ok(!lstrcmpW(bstr
, path
),
733 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
736 FolderItem_Release(item
);
738 /* test that the folder item is no longer accessible by string index */
739 item
= (FolderItem
*)0xdeadbeef;
740 r
= FolderItems_Item(items
, str_index
, &item
);
741 ok(r
== S_FALSE
, "file_defs[%d]: expected S_FALSE, got %08x\n", i
, r
);
742 ok(!item
, "file_defs[%d]: item is not null\n", i
);
744 VariantClear(&str_index
);
747 /* test that there are only as many folder items as there were files */
748 V_I4(&int_index
) = ARRAY_SIZE(file_defs
);
749 item
= (FolderItem
*)0xdeadbeef;
750 r
= FolderItems_Item(items
, int_index
, &item
);
751 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
752 ok(!item
, "item is not null\n");
754 if (0) /* crashes on xp */
756 r
= FolderItems_get_Application(items
, NULL
);
757 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
760 r
= FolderItems_get_Application(items
, &disp
);
761 ok(r
== S_OK
, "FolderItems::get_Application failed: %08x\n", r
);
763 r
= Folder_get_Application(folder
, &disp2
);
764 ok(r
== S_OK
, "Failed to get application pointer, hr %#x.\n", r
);
765 ok(disp
== disp2
, "Unexpected application pointer.\n");
766 IDispatch_Release(disp2
);
767 IDispatch_Release(disp
);
769 if (0) /* crashes on xp */
771 r
= FolderItems_get_Parent(items
, NULL
);
772 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
775 disp
= (IDispatch
*)0xdeadbeef;
776 r
= FolderItems_get_Parent(items
, &disp
);
777 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08x\n", r
);
778 ok(!disp
, "disp is not null\n");
780 if (0) /* crashes on xp */
782 r
= FolderItems__NewEnum(items
, NULL
);
783 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
786 r
= FolderItems__NewEnum(items
, &unk
);
788 ok(r
== S_OK
, "FolderItems::_NewEnum failed: %08x\n", r
);
790 ok(!!unk
, "unk is null\n");
791 if (unk
) IUnknown_Release(unk
);
795 r
= FolderItems3_Filter(items3
, 0, NULL
);
797 ok(r
== S_OK
, "expected S_OK, got %08x\n", r
);
799 if (0) /* crashes on xp */
801 r
= FolderItems3_get_Verbs(items3
, NULL
);
802 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08x\n", r
);
805 r
= FolderItems3_get_Verbs(items3
, &verbs
);
807 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
808 ok(!verbs
, "verbs is not null\n");
811 /* remove the temporary directory and restore the original working directory */
812 GetTempPathW(MAX_PATH
, path
);
813 SetCurrentDirectoryW(path
);
814 ret
= RemoveDirectoryW(winetestW
);
815 ok(ret
, "RemoveDirectory failed: %08x\n", GetLastError());
816 SetCurrentDirectoryW(orig_dir
);
818 /* test that everything stops working after the directory has been removed */
820 r
= FolderItems_get_Count(items
, &count
);
821 ok(r
== S_OK
, "FolderItems::get_Count failed: %08x\n", r
);
822 ok(!count
, "expected 0 files, got %d\n", count
);
825 V_I4(&int_index
) = 0;
826 item
= (FolderItem
*)0xdeadbeef;
827 r
= FolderItems_Item(items
, int_index
, &item
);
828 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
829 ok(!item
, "item is not null\n");
831 variant_set_string(&str_index
, file_defs
[0].name
);
832 item
= (FolderItem
*)0xdeadbeef;
833 r
= FolderItems_Item(items
, str_index
, &item
);
834 ok(r
== S_FALSE
, "expected S_FALSE, got %08x\n", r
);
835 ok(!item
, "item is not null\n");
836 VariantClear(&str_index
);
838 FolderItems_Release(items
);
839 Folder_Release(folder
);
840 if (items3
) FolderItems3_Release(items3
);
841 IShellDispatch_Release(sd
);
844 static void test_service(void)
846 static const WCHAR spooler
[] = {'S','p','o','o','l','e','r',0};
847 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
848 SERVICE_STATUS_PROCESS status
;
849 SC_HANDLE scm
, service
;
856 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
857 &IID_IShellDispatch2
, (void**)&sd
);
860 win_skip("IShellDispatch2 not supported\n");
866 hr
= IShellDispatch2_IsServiceRunning(sd
, NULL
, &v
);
867 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
868 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
871 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
872 service
= OpenServiceW(scm
, spooler
, SERVICE_QUERY_STATUS
);
873 QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
, sizeof(SERVICE_STATUS_PROCESS
), &dummy
);
874 CloseServiceHandle(service
);
875 CloseServiceHandle(scm
);
877 /* service should exist */
878 name
= SysAllocString(spooler
);
880 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
882 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
883 if (status
.dwCurrentState
== SERVICE_RUNNING
)
884 ok(V_BOOL(&v
) == VARIANT_TRUE
, "got %d\n", V_BOOL(&v
));
886 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
889 /* service doesn't exist */
890 name
= SysAllocString(dummyW
);
892 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
894 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
895 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
898 IShellDispatch2_Release(sd
);
901 static void test_dispatch_typeinfo(IDispatch
*disp
, REFIID
*riid
)
909 hr
= IDispatch_GetTypeInfoCount(disp
, &count
);
910 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
911 ok(count
== 1, "got %u\n", count
);
913 hr
= IDispatch_GetTypeInfo(disp
, 0, LOCALE_SYSTEM_DEFAULT
, &typeinfo
);
914 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
916 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
918 while (!IsEqualGUID(*riid
, &IID_NULL
)) {
919 if (IsEqualGUID(&typeattr
->guid
, *riid
))
923 ok(IsEqualGUID(&typeattr
->guid
, *riid
), "unexpected type guid %s\n", wine_dbgstr_guid(&typeattr
->guid
));
925 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
926 ITypeInfo_Release(typeinfo
);
929 static void test_ShellFolderViewDual(void)
931 static const IID
*shelldisp_riids
[] = {
932 &IID_IShellDispatch6
,
933 &IID_IShellDispatch5
,
934 &IID_IShellDispatch4
,
935 &IID_IShellDispatch2
,
936 &IID_IWin7ShellDispatch6
,
939 IShellFolderViewDual
*viewdual
;
940 IShellFolder
*desktop
, *tmpdir
;
941 IShellView
*view
, *view2
;
942 IDispatch
*disp
, *disp2
;
943 WCHAR pathW
[MAX_PATH
];
947 /* IShellFolderViewDual is not an IShellView extension */
948 hr
= SHGetDesktopFolder(&desktop
);
949 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
951 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
952 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
954 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
955 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
957 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
958 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
960 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp2
);
961 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
962 ok(disp2
== disp
, "got %p, %p\n", disp2
, disp
);
963 IDispatch_Release(disp2
);
965 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
966 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
967 ok(disp
== (IDispatch
*)viewdual
, "got %p, expected %p\n", viewdual
, disp
);
969 hr
= IShellFolderViewDual_QueryInterface(viewdual
, &IID_IShellView
, (void**)&view2
);
970 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
972 /* get_Application() */
974 if (0) /* crashes on pre-vista */ {
975 hr
= IShellFolderViewDual_get_Application(viewdual
, NULL
);
976 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
978 hr
= IShellFolderViewDual_get_Application(viewdual
, &disp2
);
979 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
980 ok(disp2
!= (IDispatch
*)viewdual
, "got %p, %p\n", disp2
, viewdual
);
981 test_dispatch_typeinfo(disp2
, shelldisp_riids
);
982 IDispatch_Release(disp2
);
984 IShellFolderViewDual_Release(viewdual
);
985 IDispatch_Release(disp
);
987 disp
= (void*)0xdeadbeef;
988 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IShellFolderViewDual
, (void**)&disp
);
989 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
) /* win2k */, "got 0x%08x\n", hr
);
990 ok(disp
== NULL
, "got %p\n", disp
);
991 IShellView_Release(view
);
993 /* Try with some other folder, that's not a desktop */
994 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
995 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, pathW
, NULL
, &pidl
, NULL
);
996 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
998 hr
= IShellFolder_BindToObject(desktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&tmpdir
);
999 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1000 CoTaskMemFree(pidl
);
1002 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
1003 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1005 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
1006 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1008 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
1009 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1010 IDispatch_Release(disp
);
1011 IShellView_Release(view
);
1013 IShellFolder_Release(tmpdir
);
1014 IShellFolder_Release(desktop
);
1017 static void test_ShellWindows(void)
1019 IShellWindows
*shellwindows
;
1020 LONG cookie
, cookie2
, ret
;
1027 hr
= CoCreateInstance(&CLSID_ShellWindows
, NULL
, CLSCTX_LOCAL_SERVER
,
1028 &IID_IShellWindows
, (void**)&shellwindows
);
1029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1030 /* TODO: remove when explorer startup with clean prefix is fixed */
1034 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, NULL
);
1035 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "got 0x%08x\n", hr
);
1037 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, &cookie
);
1038 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
1040 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
1041 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
1043 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
1044 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
1046 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
1047 0, 0, 50, 14, 0, 0, 0, NULL
);
1048 ok(hwnd
!= NULL
, "got %p, error %d\n", hwnd
, GetLastError());
1051 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie
);
1052 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1053 ok(cookie
!= 0, "got %d\n", cookie
);
1056 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie2
);
1057 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1058 ok(cookie2
!= 0 && cookie2
!= cookie
, "got %d\n", cookie2
);
1060 pidl
= ILCreateFromPathA("C:\\");
1061 V_VT(&v
) = VT_ARRAY
| VT_UI1
;
1062 V_ARRAY(&v
) = SafeArrayCreateVector(VT_UI1
, 0, ILGetSize(pidl
));
1063 memcpy(V_ARRAY(&v
)->pvData
, pidl
, ILGetSize(pidl
));
1066 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1067 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1068 ok(!ret
, "Got window %#x.\n", ret
);
1069 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1071 hr
= IShellWindows_OnNavigate(shellwindows
, 0, &v
);
1072 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1074 hr
= IShellWindows_OnNavigate(shellwindows
, cookie
, &v
);
1075 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1077 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1078 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1079 ok(ret
== (LONG
)(LONG_PTR
)hwnd
, "Expected %p, got %#x.\n", hwnd
, ret
);
1080 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1082 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
1083 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1085 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1086 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1087 ok(!ret
, "Got window %#x.\n", ret
);
1088 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1090 hr
= IShellWindows_Revoke(shellwindows
, cookie2
);
1091 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1093 hr
= IShellWindows_Revoke(shellwindows
, 0);
1094 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
1096 /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
1098 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_DESKTOP
, &cookie
);
1099 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1100 ok(cookie
!= 0, "got %d\n", cookie
);
1102 disp
= (void*)0xdeadbeef;
1105 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, SWFO_NEEDDISPATCH
, &disp
);
1106 ok(hr
== S_OK
|| broken(hr
== S_FALSE
), "got 0x%08x\n", hr
);
1107 if (hr
== S_FALSE
) /* winxp and earlier */ {
1108 win_skip("SWC_DESKTOP is not supported, some tests will be skipped.\n");
1109 /* older versions allowed to register SWC_DESKTOP and access it with FindWindowSW */
1110 ok(disp
== NULL
, "got %p\n", disp
);
1111 ok(ret
== 0, "got %d\n", ret
);
1114 static const IID
*browser_riids
[] = {
1119 static const IID
*viewdual_riids
[] = {
1120 &IID_IShellFolderViewDual3
,
1124 IShellFolderViewDual
*view
;
1125 IShellBrowser
*sb
, *sb2
;
1126 IServiceProvider
*sp
;
1127 IDispatch
*doc
, *app
;
1132 ok(disp
!= NULL
, "got %p\n", disp
);
1133 ok(ret
!= HandleToUlong(hwnd
), "got %d\n", ret
);
1135 /* IDispatch-related tests */
1136 test_dispatch_typeinfo(disp
, browser_riids
);
1139 hr
= IDispatch_QueryInterface(disp
, &IID_IWebBrowser2
, (void**)&wb
);
1140 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1142 hr
= IWebBrowser2_Refresh(wb
);
1144 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1146 hr
= IWebBrowser2_get_Application(wb
, &app
);
1147 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1148 ok(disp
== app
, "got %p, %p\n", app
, disp
);
1149 IDispatch_Release(app
);
1151 hr
= IWebBrowser2_get_Document(wb
, &doc
);
1153 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1155 test_dispatch_typeinfo(doc
, viewdual_riids
);
1157 IWebBrowser2_Release(wb
);
1159 /* IServiceProvider */
1160 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&view
);
1161 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1163 hr
= IDispatch_QueryInterface(disp
, &IID_IServiceProvider
, (void**)&sp
);
1164 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1166 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb
);
1167 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1169 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb2
);
1170 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1171 ok(sb
== sb2
, "got %p, %p\n", sb
, sb2
);
1173 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IOleWindow
, (void**)&unk
);
1174 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1175 IUnknown_Release(unk
);
1177 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IExplorerBrowser
, (void**)&unk
);
1178 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1180 hr
= IShellBrowser_QueryInterface(sb
, &IID_IExplorerBrowser
, (void**)&unk
);
1181 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1183 hr
= IShellBrowser_QueryInterface(sb
, &IID_IWebBrowser2
, (void**)&unk
);
1184 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1186 hr
= IShellBrowser_QueryInterface(sb
, &IID_IDispatch
, (void**)&unk
);
1187 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1189 hr
= IShellBrowser_QueryActiveShellView(sb
, &sv
);
1190 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1191 IShellView_Release(sv
);
1193 IShellBrowser_Release(sb2
);
1194 IShellBrowser_Release(sb
);
1196 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IUnknown
, (void**)&unk
);
1197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1199 hr
= IUnknown_QueryInterface(unk
, &IID_IShellBrowser
, (void**)&sb2
);
1200 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1201 IShellBrowser_Release(sb2
);
1202 IUnknown_Release(unk
);
1204 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellView
, (void**)&sv
);
1205 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
1207 IServiceProvider_Release(sp
);
1208 IDispatch_Release(disp
);
1211 disp
= (void*)0xdeadbeef;
1214 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, 0, &disp
);
1215 ok(hr
== S_OK
|| broken(hr
== S_FALSE
) /* winxp */, "got 0x%08x\n", hr
);
1216 ok(disp
== NULL
, "got %p\n", disp
);
1217 ok(ret
!= HandleToUlong(hwnd
), "got %d\n", ret
);
1219 disp
= (void*)0xdeadbeef;
1224 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_BROWSER
, &ret
, SWFO_COOKIEPASSED
, &disp
);
1226 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
1227 ok(disp
== NULL
, "got %p\n", disp
);
1228 ok(ret
== 0, "got %d\n", ret
);
1230 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
1231 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1232 DestroyWindow(hwnd
);
1233 IShellWindows_Release(shellwindows
);
1236 static void test_ParseName(void)
1238 static const WCHAR cadabraW
[] = {'c','a','d','a','b','r','a',0};
1239 WCHAR pathW
[MAX_PATH
];
1247 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1248 &IID_IShellDispatch
, (void**)&sd
);
1249 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1251 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
1253 V_BSTR(&v
) = SysAllocString(pathW
);
1254 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1255 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1258 item
= (void*)0xdeadbeef;
1259 hr
= Folder_ParseName(folder
, NULL
, &item
);
1260 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08x\n", hr
);
1261 ok(item
== NULL
, "got %p\n", item
);
1264 str
= SysAllocStringLen(NULL
, 0);
1265 item
= (void*)0xdeadbeef;
1266 hr
= Folder_ParseName(folder
, str
, &item
);
1267 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08x\n", hr
);
1268 ok(item
== NULL
, "got %p\n", item
);
1271 /* path doesn't exist */
1272 str
= SysAllocString(cadabraW
);
1273 item
= (void*)0xdeadbeef;
1274 hr
= Folder_ParseName(folder
, str
, &item
);
1275 ok(hr
== S_FALSE
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* win2k */,
1276 "got 0x%08x\n", hr
);
1277 ok(item
== NULL
, "got %p\n", item
);
1280 lstrcatW(pathW
, cadabraW
);
1281 CreateDirectoryW(pathW
, NULL
);
1283 str
= SysAllocString(cadabraW
);
1285 hr
= Folder_ParseName(folder
, str
, &item
);
1286 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1287 ok(item
!= NULL
, "got %p\n", item
);
1290 hr
= FolderItem_get_Path(item
, &str
);
1291 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1292 ok(str
[0] != 0, "path %s\n", wine_dbgstr_w(str
));
1295 RemoveDirectoryW(pathW
);
1296 FolderItem_Release(item
);
1297 Folder_Release(folder
);
1298 IShellDispatch_Release(sd
);
1301 static void test_Verbs(void)
1303 FolderItemVerbs
*verbs
, *verbs2
;
1304 WCHAR pathW
[MAX_PATH
];
1305 FolderItemVerb
*verb
;
1316 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1317 &IID_IShellDispatch
, (void**)&sd
);
1318 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1320 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
1322 V_BSTR(&v
) = SysAllocString(pathW
);
1323 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1324 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1327 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
1328 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1329 Folder_Release(folder
);
1331 hr
= Folder2_get_Self(folder2
, &item
);
1332 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1333 Folder2_Release(folder2
);
1335 if (0) { /* crashes on some systems */
1336 hr
= FolderItem_Verbs(item
, NULL
);
1337 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1339 hr
= FolderItem_Verbs(item
, &verbs
);
1340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1342 hr
= FolderItem_Verbs(item
, &verbs2
);
1343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1344 ok(verbs2
!= verbs
, "Unexpected verbs pointer.\n");
1345 FolderItemVerbs_Release(verbs2
);
1347 disp
= (void *)0xdeadbeef;
1348 hr
= FolderItemVerbs_get_Application(verbs
, &disp
);
1349 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
1350 ok(disp
== NULL
, "Unexpected application pointer.\n");
1352 disp
= (void *)0xdeadbeef;
1353 hr
= FolderItemVerbs_get_Parent(verbs
, &disp
);
1354 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
1355 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1357 if (0) { /* crashes on winxp/win2k3 */
1358 hr
= FolderItemVerbs_get_Count(verbs
, NULL
);
1359 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1362 hr
= FolderItemVerbs_get_Count(verbs
, &count
);
1363 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1364 ok(count
> 0, "got count %d\n", count
);
1366 if (0) { /* crashes on winxp/win2k3 */
1369 hr
= FolderItemVerbs_Item(verbs
, v
, NULL
);
1370 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1372 /* there's always one item more, so you can access [0,count],
1373 instead of actual [0,count) */
1374 for (i
= 0; i
<= count
; i
++) {
1377 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1378 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1379 hr
= FolderItemVerb_get_Name(verb
, &str
);
1380 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1381 ok(str
!= NULL
, "%d: name %s\n", i
, wine_dbgstr_w(str
));
1383 ok(str
[0] == 0, "%d: got terminating item %s\n", i
, wine_dbgstr_w(str
));
1385 disp
= (void *)0xdeadbeef;
1386 hr
= FolderItemVerb_get_Parent(verb
, &disp
);
1387 ok(hr
== E_NOTIMPL
, "got %#x.\n", hr
);
1388 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1390 disp
= (void *)0xdeadbeef;
1391 hr
= FolderItemVerb_get_Application(verb
, &disp
);
1392 ok(hr
== E_NOTIMPL
, "got %#x.\n", hr
);
1393 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1396 FolderItemVerb_Release(verb
);
1402 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1403 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1404 ok(verb
== NULL
, "got %p\n", verb
);
1406 FolderItemVerbs_Release(verbs
);
1407 FolderItem_Release(item
);
1408 IShellDispatch_Release(sd
);
1411 static void test_ShellLinkObject(void)
1415 WCHAR path
[MAX_PATH
],
1416 empty_path
[MAX_PATH
],
1417 link_path
[MAX_PATH
];
1422 IDispatch
*dispatch
;
1424 IShellLinkDual2
* sld
;
1431 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1432 &IID_IShellDispatch
, (void**)&sd
);
1433 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1435 GetTempPathW(MAX_PATH
, path
);
1437 V_BSTR(&v
) = SysAllocString(path
);
1438 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1439 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1442 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
1443 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1444 Folder_Release(folder
);
1446 hr
= Folder2_get_Self(folder2
, &item
);
1447 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1449 dispatch
= (IDispatch
*)0xdeadbeef;
1450 hr
= FolderItem_get_GetLink(item
, &dispatch
);
1451 ok(hr
== E_NOTIMPL
, "got 0x%08x\n", hr
);
1452 ok(dispatch
== NULL
, "got %p\n", dispatch
);
1454 FolderItem_Release(item
);
1456 PathCombineW(empty_path
, path
, L
"winetest_empty_file.txt");
1457 file
= CreateFileW(empty_path
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1458 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08x\n", GetLastError());
1461 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLinkW
, (LPVOID
*)&sl
);
1462 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1463 hr
= IShellLinkW_SetPath(sl
, empty_path
);
1464 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1465 hr
= IShellLinkW_GetPath(sl
, empty_path
, MAX_PATH
, NULL
, 0);
1466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1467 hr
= IShellLinkW_SetDescription(sl
, L
"description");
1468 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1469 hr
= IShellLinkW_SetWorkingDirectory(sl
, L
"working directory");
1470 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1471 hr
= IShellLinkW_SetArguments(sl
, L
"arguments");
1472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1473 hr
= IShellLinkW_SetHotkey(sl
, 1234);
1474 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1475 hr
= IShellLinkW_SetShowCmd(sl
, 1);
1476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1478 hr
= IShellLinkW_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
1479 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1481 PathCombineW(link_path
, path
, L
"winetest_filled.lnk");
1482 hr
= IPersistFile_Save(pf
, link_path
, TRUE
);
1483 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1485 IPersistFile_Release(pf
);
1486 IShellLinkW_Release(sl
);
1488 str
= SysAllocString(L
"winetest_filled.lnk");
1489 hr
= Folder2_ParseName(folder2
, str
, &item
);
1490 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1494 hr
= FolderItem_get_GetLink(item
, &dispatch
);
1495 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1496 ok(dispatch
!= NULL
, "got %p\n", dispatch
);
1499 sld
= (IShellLinkDual2
*)dispatch
;
1502 hr
= IShellLinkDual2_get_Path(sld
, &str
);
1503 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1505 ok(!wcscmp(str
, empty_path
), "got %s (wanted %s)\n",
1506 wine_dbgstr_w(str
), wine_dbgstr_w(empty_path
));
1511 hr
= IShellLinkDual2_get_Description(sld
, &str
);
1512 todo_wine
ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1514 ok(!wcscmp(str
, L
"description"), "got %s\n", wine_dbgstr_w(str
));
1519 hr
= IShellLinkDual2_get_WorkingDirectory(sld
, &str
);
1520 todo_wine
ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1522 ok(!wcscmp(str
, L
"working directory"), "got %s\n", wine_dbgstr_w(str
));
1527 hr
= IShellLinkDual2_get_Arguments(sld
, &str
);
1528 todo_wine
ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1530 ok(!wcscmp(str
, L
"arguments"), "got %s\n", wine_dbgstr_w(str
));
1535 hr
= IShellLinkDual2_get_Hotkey(sld
, &hk
);
1536 todo_wine
ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1537 todo_wine
ok(hk
== 1234, "got %i\n", hk
);
1540 hr
= IShellLinkDual2_get_ShowCommand(sld
, &hk
);
1541 todo_wine
ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1542 todo_wine
ok(hk
== 1, "got %i\n", hk
);
1544 IShellLinkDual2_Release(sld
);
1547 FolderItem_Release(item
);
1549 ret
= DeleteFileW(link_path
);
1550 ok(ret
, "DeleteFile failed: %08x\n", GetLastError());
1551 ret
= DeleteFileW(empty_path
);
1552 ok(ret
, "DeleteFile failed: %08x\n", GetLastError());
1554 Folder2_Release(folder2
);
1556 IShellDispatch_Release(sd
);
1559 static void test_ShellExecute(void)
1562 IShellDispatch2
*sd
;
1564 VARIANT args
, dir
, op
, show
;
1566 static const WCHAR regW
[] = {'r','e','g',0};
1568 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1569 &IID_IShellDispatch2
, (void**)&sd
);
1572 win_skip("IShellDispatch2 not supported\n");
1581 V_VT(&show
) = VT_I4
;
1584 name
= SysAllocString(regW
);
1586 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1587 ok(hr
== S_OK
, "ShellExecute failed: %08x\n", hr
);
1589 /* test invalid value for show */
1590 V_VT(&show
) = VT_BSTR
;
1591 V_BSTR(&show
) = name
;
1593 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1594 ok(hr
== S_OK
, "ShellExecute failed: %08x\n", hr
);
1596 SysFreeString(name
);
1597 IShellDispatch2_Release(sd
);
1600 START_TEST(shelldispatch
)
1604 r
= CoInitialize(NULL
);
1605 ok(SUCCEEDED(r
), "CoInitialize failed: %08x\n", r
);
1609 init_function_pointers();
1613 test_ShellFolderViewDual();
1614 test_ShellWindows();
1617 test_ShellLinkObject();
1618 test_ShellExecute();