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
27 #include "wine/test.h"
31 #define EXPECT_HR(hr,hr_exp) \
32 ok(hr == hr_exp, "got 0x%08lx, expected 0x%08lx\n", hr, hr_exp)
34 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
35 static void _expect_ref(IUnknown
*obj
, ULONG ref
, int line
)
39 rc
= IUnknown_Release(obj
);
40 ok_(__FILE__
,line
)(rc
== ref
, "Unexpected refcount %ld, expected %ld\n", rc
, ref
);
43 static const WCHAR winetestW
[] = {'w','i','n','e','t','e','s','t',0};
45 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
47 /* Updated Windows 7 has a new IShellDispatch6 in its typelib */
48 DEFINE_GUID(IID_IWin7ShellDispatch6
, 0x34936ba1, 0x67ad, 0x4c41, 0x99,0xb8, 0x8c,0x12,0xdf,0xf1,0xe9,0x74);
50 static void variant_set_string(VARIANT
*v
, const WCHAR
*s
)
53 V_BSTR(v
) = SysAllocString(s
);
56 static void init_function_pointers(void)
60 hshell32
= GetModuleHandleA("shell32.dll");
61 pSHGetNameFromIDList
= (void*)GetProcAddress(hshell32
, "SHGetNameFromIDList");
64 static void test_namespace(void)
66 static const ShellSpecialFolderConstants special_folders
[] =
108 static const WCHAR backslashW
[] = {'\\',0};
109 static const WCHAR clsidW
[] = {
110 ':',':','{','6','4','5','F','F','0','4','0','-','5','0','8','1','-',
111 '1','0','1','B','-','9','F','0','8','-',
112 '0','0','A','A','0','0','2','F','9','5','4','E','}',0};
114 static WCHAR tempW
[MAX_PATH
], curW
[MAX_PATH
];
115 WCHAR
*long_pathW
= NULL
;
122 BSTR title
, item_path
;
126 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void **)&sd
);
127 ok(SUCCEEDED(r
), "Failed to create ShellDispatch object: %#lx.\n", r
);
130 r
= IShellDispatch_get_Application(sd
, &disp
);
131 ok(r
== S_OK
, "Failed to get application pointer, hr %#lx.\n", r
);
132 ok(disp
== (IDispatch
*)sd
, "Unexpected application pointer %p.\n", disp
);
133 IDispatch_Release(disp
);
136 r
= IShellDispatch_get_Parent(sd
, &disp
);
137 ok(r
== S_OK
, "Failed to get Shell object parent, hr %#lx.\n", r
);
138 ok(disp
== (IDispatch
*)sd
, "Unexpected parent pointer %p.\n", disp
);
139 IDispatch_Release(disp
);
142 folder
= (void*)0xdeadbeef;
143 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
144 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
145 ok(folder
== NULL
, "expected NULL, got %p\n", folder
);
147 /* test valid folder ids */
148 for (i
= 0; i
< ARRAY_SIZE(special_folders
); i
++)
151 V_I4(&var
) = special_folders
[i
];
152 folder
= (void*)0xdeadbeef;
153 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
154 if (special_folders
[i
] == ssfALTSTARTUP
|| special_folders
[i
] == ssfCOMMONALTSTARTUP
)
156 ok(r
== S_OK
|| broken(r
== S_FALSE
) /* winxp */, "Failed to get folder for index %#x, got %08lx\n", special_folders
[i
], r
);
158 ok(r
== S_OK
, "Failed to get folder for index %#x, got %08lx\n", special_folders
[i
], r
);
160 Folder_Release(folder
);
165 folder
= (void *)0xdeadbeef;
166 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
167 ok(r
== S_FALSE
, "Unexpected hr %#lx.\n", r
);
168 ok(folder
== NULL
, "Unexpected folder instance %p\n", folder
);
171 V_I4(&var
) = ssfPROGRAMFILES
;
172 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
173 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
176 static WCHAR path
[MAX_PATH
];
178 r
= SHGetFolderPathW(NULL
, CSIDL_PROGRAM_FILES
, NULL
, SHGFP_TYPE_CURRENT
, path
);
179 ok(r
== S_OK
, "Failed to get folder path: %#lx.\n", r
);
181 r
= Folder_get_Title(folder
, &title
);
182 ok(r
== S_OK
, "Folder::get_Title failed: %08lx\n", r
);
185 /* On Win2000-2003 title is equal to program files directory name in
186 HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir.
187 On newer Windows it seems constant and is not changed
188 if the program files directory name is changed */
189 if (pSHGetNameFromIDList
)
194 r
= SHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidl
);
195 ok(r
== S_OK
, "SHGetSpecialFolderLocation failed: %08lx\n", r
);
196 r
= pSHGetNameFromIDList(pidl
, SIGDN_NORMALDISPLAY
, &name
);
197 ok(r
== S_OK
, "SHGetNameFromIDList failed: %08lx\n", r
);
198 ok(!lstrcmpW(title
, name
), "expected %s, got %s\n", wine_dbgstr_w(name
), wine_dbgstr_w(title
));
206 p
= path
+ lstrlenW(path
);
207 while (path
< p
&& *(p
- 1) != '\\')
209 ok(!lstrcmpiW(title
, p
), "expected %s, got %s\n",
210 wine_dbgstr_w(p
), wine_dbgstr_w(title
));
212 SysFreeString(title
);
214 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
215 ok(r
== S_OK
, "Folder::QueryInterface failed: %08lx\n", r
);
218 r
= Folder2_get_Self(folder2
, &item
);
219 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
222 r
= FolderItem_get_Path(item
, &item_path
);
223 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
224 ok(!lstrcmpiW(item_path
, path
), "expected %s, got %s\n", wine_dbgstr_w(path
), wine_dbgstr_w(item_path
));
225 SysFreeString(item_path
);
226 FolderItem_Release(item
);
228 Folder2_Release(folder2
);
230 Folder_Release(folder
);
234 V_I4(&var
) = ssfBITBUCKET
;
235 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
236 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
238 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (void **)&folder2
);
239 ok(r
== S_OK
, "Failed to get Folder2 interface: %#lx.\n", r
);
240 r
= Folder2_get_Self(folder2
, &item
);
241 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
242 r
= FolderItem_get_Path(item
, &item_path
);
243 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
244 /* TODO: we return lowercase GUID here */
245 ok(!lstrcmpiW(item_path
, clsidW
), "expected %s, got %s\n", wine_dbgstr_w(clsidW
), wine_dbgstr_w(item_path
));
247 SysFreeString(item_path
);
248 FolderItem_Release(item
);
249 Folder2_Release(folder2
);
250 Folder_Release(folder
);
252 GetTempPathW(MAX_PATH
, tempW
);
253 GetCurrentDirectoryW(MAX_PATH
, curW
);
254 SetCurrentDirectoryW(tempW
);
255 CreateDirectoryW(winetestW
, NULL
);
256 V_VT(&var
) = VT_BSTR
;
257 V_BSTR(&var
) = SysAllocString(winetestW
);
258 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
259 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
260 SysFreeString(V_BSTR(&var
));
262 GetFullPathNameW(winetestW
, MAX_PATH
, tempW
, NULL
);
264 len
= GetLongPathNameW(tempW
, NULL
, 0);
265 long_pathW
= malloc(len
* sizeof(WCHAR
));
266 GetLongPathNameW(tempW
, long_pathW
, len
);
268 V_VT(&var
) = VT_BSTR
;
269 V_BSTR(&var
) = SysAllocString(tempW
);
270 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
271 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
273 disp
= (void *)0xdeadbeef;
274 r
= Folder_get_Parent(folder
, &disp
);
275 ok(r
== E_NOTIMPL
, "Unexpected hr %#lx.\n", r
);
276 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
278 r
= Folder_get_Title(folder
, &title
);
279 ok(r
== S_OK
, "Failed to get folder title: %#lx.\n", r
);
280 ok(!lstrcmpW(title
, winetestW
), "Unexpected title: %s\n", wine_dbgstr_w(title
));
281 SysFreeString(title
);
283 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (void **)&folder2
);
284 ok(r
== S_OK
, "Failed to get Folder2 interface: %#lx.\n", r
);
285 r
= Folder2_get_Self(folder2
, &item
);
286 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
287 r
= FolderItem_get_Path(item
, &item_path
);
288 ok(r
== S_OK
, "Failed to get item path: %#lx.\n", r
);
289 ok(!lstrcmpW(item_path
, long_pathW
), "Unexpected path %s, got %s\n", wine_dbgstr_w(item_path
), wine_dbgstr_w(long_pathW
));
290 SysFreeString(item_path
);
291 FolderItem_Release(item
);
292 Folder2_Release(folder2
);
294 Folder_Release(folder
);
297 len
= lstrlenW(tempW
);
298 if (len
< MAX_PATH
- 1)
300 lstrcatW(tempW
, backslashW
);
301 V_VT(&var
) = VT_BSTR
;
302 V_BSTR(&var
) = SysAllocString(tempW
);
303 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
304 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
307 r
= Folder_get_Title(folder
, &title
);
308 ok(r
== S_OK
, "Folder::get_Title failed: %08lx\n", r
);
311 ok(!lstrcmpW(title
, winetestW
), "bad title: %s\n",
312 wine_dbgstr_w(title
));
313 SysFreeString(title
);
315 r
= Folder_QueryInterface(folder
, &IID_Folder2
, (LPVOID
*)&folder2
);
316 ok(r
== S_OK
, "Failed to get Folder2 interface: %#lx.\n", r
);
319 r
= Folder2_get_Self(folder2
, &item
);
320 ok(r
== S_OK
, "Folder::get_Self failed: %08lx\n", r
);
323 r
= FolderItem_get_Path(item
, &item_path
);
324 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
325 ok(!lstrcmpW(item_path
, long_pathW
), "Unexpected path %s, got %s\n", wine_dbgstr_w(item_path
),
326 wine_dbgstr_w(long_pathW
));
327 SysFreeString(item_path
);
328 FolderItem_Release(item
);
330 Folder2_Release(folder2
);
332 Folder_Release(folder
);
334 SysFreeString(V_BSTR(&var
));
338 RemoveDirectoryW(winetestW
);
339 SetCurrentDirectoryW(curW
);
340 IShellDispatch_Release(sd
);
343 static void test_items(void)
357 { L
"00-Myfolder", DIRECTORY
},
358 { L
"01-empty.bin", EMPTY_FILE
},
360 WCHAR path
[MAX_PATH
], cur_dir
[MAX_PATH
], orig_dir
[MAX_PATH
];
362 IShellDispatch
*sd
= NULL
;
363 Folder
*folder
= NULL
;
365 FolderItems2
*items2
= NULL
;
366 FolderItems3
*items3
= NULL
;
367 FolderItem
*item
= (FolderItem
*)0xdeadbeef, *item2
;
368 FolderItemVerbs
*verbs
= (FolderItemVerbs
*)0xdeadbeef;
369 VARIANT var
, var2
, int_index
, str_index
, str_index2
;
370 IDispatch
*disp
, *disp2
;
379 r
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellDispatch
, (void**)&sd
);
380 ok(SUCCEEDED(r
), "CoCreateInstance failed: %08lx\n", r
);
381 ok(!!sd
, "sd is null\n");
383 /* create and enter a temporary directory and a folder object for it */
384 GetTempPathW(MAX_PATH
, path
);
385 GetCurrentDirectoryW(MAX_PATH
, orig_dir
);
386 SetCurrentDirectoryW(path
);
387 ret
= CreateDirectoryW(winetestW
, NULL
);
388 ok(ret
, "CreateDirectory failed: %08lx\n", GetLastError());
389 GetFullPathNameW(winetestW
, MAX_PATH
, path
, NULL
);
390 V_VT(&var
) = VT_BSTR
;
391 V_BSTR(&var
) = SysAllocString(path
);
394 r
= IShellDispatch_NameSpace(sd
, var
, &folder
);
395 ok(r
== S_OK
, "IShellDispatch::NameSpace failed: %08lx\n", r
);
396 ok(!!folder
, "folder is null\n");
397 EXPECT_REF(folder
, 1);
401 SetCurrentDirectoryW(winetestW
);
402 GetCurrentDirectoryW(MAX_PATH
, path
);
403 GetLongPathNameW(path
, cur_dir
, MAX_PATH
);
405 /* FolderItems grabs its Folder reference */
407 r
= Folder_Items(folder
, &items
);
408 ok(r
== S_OK
, "Folder::Items failed: %08lx\n", r
);
409 ok(!!items
, "items is null\n");
410 EXPECT_REF(folder
, 2);
411 EXPECT_REF(items
, 1);
414 r
= Folder_Items(folder
, (FolderItems
**)&unk
);
415 ok(r
== S_OK
, "Folder::Items failed: %08lx\n", r
);
416 EXPECT_REF(folder
, 3);
417 IUnknown_Release(unk
);
418 EXPECT_REF(folder
, 2);
420 FolderItems_AddRef(items
);
421 EXPECT_REF(folder
, 2);
422 FolderItems_Release(items
);
424 /* Application property */
427 r
= Folder_get_Application(folder
, &disp
);
428 ok(r
== S_OK
, "Failed to get application %#lx.\n", r
);
429 ok(disp
!= (IDispatch
*)sd
, "Unexpected application pointer\n");
433 r
= Folder_get_Application(folder
, &disp2
);
434 ok(r
== S_OK
, "Failed to get application %#lx.\n", r
);
435 ok(disp2
== disp
, "Unexpected application pointer\n");
436 IDispatch_Release(disp2
);
438 r
= IDispatch_QueryInterface(disp
, &IID_IShellDispatch
, (void **)&disp2
);
439 ok(r
== S_OK
, "Wrong instance, hr %#lx.\n", r
);
440 IDispatch_Release(disp2
);
441 IDispatch_Release(disp
);
443 if (0) /* crashes on all versions of Windows */
444 r
= FolderItems_get_Count(items
, NULL
);
446 r
= FolderItems_get_Count(items
, &count
);
447 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
448 ok(!count
, "expected 0 files, got %ld\n", count
);
453 if (0) /* crashes on all versions of Windows */
454 r
= FolderItems_Item(items
, var
, NULL
);
456 r
= FolderItems_Item(items
, var
, &item
);
457 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
458 ok(!item
, "item is not null\n");
460 /* create test files */
461 for (i
= 0; i
< ARRAY_SIZE(file_defs
); i
++)
463 switch (file_defs
[i
].type
)
466 r
= CreateDirectoryW(file_defs
[i
].name
, NULL
);
467 ok(r
, "CreateDirectory failed: %08lx\n", GetLastError());
468 PathCombineW(cstr
, file_defs
[i
].name
, L
"foo.txt");
469 file
= CreateFileW(cstr
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
470 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08lx\n", GetLastError());
475 file
= CreateFileW(file_defs
[i
].name
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
476 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08lx\n", GetLastError());
482 /* test that get_Count is not aware of the newly created files */
484 r
= FolderItems_get_Count(items
, &count
);
485 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
486 ok(!count
, "expected 0 files, got %ld\n", count
);
488 /* test that the newly created files CAN be retrieved by string index */
489 variant_set_string(&var
, file_defs
[0].name
);
491 r
= FolderItems_Item(items
, var
, &item
);
492 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
493 ok(!!item
, "item is null\n");
495 disp
= (void *)0xdeadbeef;
496 r
= FolderItems_get_Parent(items
, &disp
);
497 ok(r
== E_NOTIMPL
, "Unexpected hr %#lx.\n", r
);
498 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
500 r
= FolderItem_get_Parent(item
, &disp
);
501 ok(r
== S_OK
, "Failed to get parent pointer, hr %#lx.\n", r
);
502 ok(disp
== (IDispatch
*)folder
, "Unexpected parent pointer %p.\n", disp
);
503 IDispatch_Release(disp
);
505 if (item
) FolderItem_Release(item
);
508 /* recreate the items object */
509 FolderItems_Release(items
);
511 r
= Folder_Items(folder
, &items
);
512 ok(r
== S_OK
, "Folder::Items failed: %08lx\n", r
);
513 ok(!!items
, "items is null\n");
514 r
= FolderItems_QueryInterface(items
, &IID_FolderItems2
, (void**)&items2
);
515 ok(r
== S_OK
|| broken(r
== E_NOINTERFACE
) /* xp and later */, "FolderItems::QueryInterface failed: %08lx\n", r
);
518 ok(!!items2
, "items2 is null\n");
519 FolderItems2_Release(items2
);
521 r
= FolderItems_QueryInterface(items
, &IID_FolderItems3
, (void**)&items3
);
522 ok(r
== S_OK
, "FolderItems::QueryInterface failed: %08lx\n", r
);
523 ok(!!items3
, "items3 is null\n");
526 r
= FolderItems_get_Count(items
, &count
);
527 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
528 ok(count
== ARRAY_SIZE(file_defs
), "got %ld files\n", count
);
531 V_VT(&var
) = VT_EMPTY
;
532 item
= (FolderItem
*)0xdeadbeef;
533 r
= FolderItems_Item(items
, var
, &item
);
534 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08lx\n", r
);
535 ok(!item
, "item is not null\n");
541 EXPECT_REF(folder
, 2);
542 EXPECT_REF(items
, 2);
544 r
= FolderItems_Item(items
, var
, &item
);
545 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
546 ok(!!item
, "item is null\n");
547 EXPECT_REF(folder
, 3);
548 EXPECT_REF(items
, 2);
550 r
= Folder_get_Application(folder
, &disp
);
551 ok(r
== S_OK
, "Failed to get application pointer %#lx.\n", r
);
552 r
= FolderItem_get_Application(item
, &disp2
);
553 ok(r
== S_OK
, "Failed to get application pointer %#lx.\n", r
);
554 ok(disp
== disp2
, "Unexpected application pointer.\n");
555 IDispatch_Release(disp2
);
556 IDispatch_Release(disp
);
558 FolderItem_Release(item
);
560 /* VT_VARIANT | VT_BYREF */
564 V_VT(&var
) = VT_BYREF
| VT_VARIANT
;
565 V_VARIANTREF(&var
) = &var2
;
568 r
= FolderItems_Item(items
, var
, &item
);
569 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
570 ok(!!item
, "item is null\n");
571 FolderItem_Release(item
);
577 r
= FolderItems_Item(items
, var
, &item
);
578 ok(r
== S_OK
, "FolderItems::Item failed: %08lx\n", r
);
579 ok(!!item
, "item is null\n");
580 if (item
) FolderItem_Release(item
);
583 item
= (FolderItem
*)0xdeadbeef;
584 r
= FolderItems_Item(items
, var
, &item
);
585 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
586 ok(!item
, "item is not null\n");
588 V_VT(&var
) = VT_ERROR
;
591 r
= FolderItems_Item(items
, var
, &item
);
592 ok(r
== S_OK
, "expected S_OK, got %08lx\n", r
);
593 ok(!!item
, "item is null\n");
597 r
= FolderItem_get_Path(item
, &bstr
);
598 ok(r
== S_OK
, "FolderItem::get_Path failed: %08lx\n", r
);
599 ok(!lstrcmpW(bstr
, cur_dir
),
600 "expected %s, got %s\n", wine_dbgstr_w(cur_dir
), wine_dbgstr_w(bstr
));
602 FolderItem_Release(item
);
605 V_VT(&int_index
) = VT_I4
;
607 /* test the folder item corresponding to each file */
608 for (i
= 0; i
< ARRAY_SIZE(file_defs
); i
++)
613 V_I4(&int_index
) = i
;
614 variant_set_string(&str_index
, file_defs
[i
].name
);
617 r
= FolderItems_Item(items
, int_index
, &item
);
618 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
619 ok(!!item
, "file_defs[%d]: item is null\n", i
);
622 r
= FolderItems_Item(items
, int_index
, &item2
);
623 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
624 ok(item2
!= item
, "file_defs[%d]: item and item2 are the same\n", i
);
625 FolderItem_Release(item2
);
628 r
= FolderItem_get_Path(item
, &bstr
);
629 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08lx\n", i
, r
);
630 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
631 ok(!lstrcmpW(bstr
, path
),
632 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
635 bstr
= SysAllocString(file_defs
[i
].name
);
636 r
= FolderItem_get_Name(item
, &name
);
637 ok(r
== S_OK
, "Failed to get item name, hr %#lx.\n", r
);
638 /* Returned display name does not have to strictly match file name, e.g. extension could be omitted. */
639 ok(lstrlenW(name
) <= lstrlenW(bstr
), "file_defs[%d]: unexpected name length.\n", i
);
640 ok(!memcmp(bstr
, name
, lstrlenW(name
) * sizeof(WCHAR
)), "file_defs[%d]: unexpected name %s.\n", i
, wine_dbgstr_w(name
));
644 FolderItem_Release(item
);
647 r
= FolderItems_Item(items
, str_index
, &item
);
648 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
649 ok(!!item
, "file_defs[%d]: item is null\n", i
);
652 r
= FolderItem_get_Path(item
, &bstr
);
653 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08lx\n", i
, r
);
654 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
655 ok(!lstrcmpW(bstr
, path
),
656 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
660 r
= FolderItem_get_IsFolder(item
, &b
);
661 ok(r
== S_OK
, "Failed to get IsFolder property, %#lx.\n", r
);
662 ok(file_defs
[i
].type
== DIRECTORY
? b
== VARIANT_TRUE
: b
== VARIANT_FALSE
, "Unexpected prop value %#x.\n", b
);
664 FolderItem_Release(item
);
666 if (file_defs
[i
].type
== DIRECTORY
)
668 /* test that getting an item object for a file in a subdirectory succeeds */
669 PathCombineW(cstr
, file_defs
[i
].name
, L
"foo.txt");
670 variant_set_string(&str_index2
, cstr
);
672 r
= FolderItems_Item(items
, str_index2
, &item2
);
673 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
674 ok(!!item2
, "file_defs[%d]: item is null\n", i
);
675 if (item2
) FolderItem_Release(item2
);
676 VariantClear(&str_index2
);
678 /* delete the file in the subdirectory */
679 ret
= DeleteFileW(cstr
);
680 ok(ret
, "file_defs[%d]: DeleteFile failed: %08lx\n", i
, GetLastError());
682 /* test that getting an item object via a relative path fails */
683 wcscpy(cstr
, file_defs
[i
].name
);
684 wcscat(cstr
, L
"\\..\\");
685 wcscat(cstr
, file_defs
[i
].name
);
686 variant_set_string(&str_index2
, cstr
);
687 item2
= (FolderItem
*)0xdeadbeef;
688 r
= FolderItems_Item(items
, str_index2
, &item2
);
689 ok(r
== S_FALSE
, "file_defs[%d]: expected S_FALSE, got %08lx\n", i
, r
);
690 ok(!item2
, "file_defs[%d]: item is not null\n", i
);
691 VariantClear(&str_index2
);
693 /* remove the directory */
694 ret
= RemoveDirectoryW(file_defs
[i
].name
);
695 ok(ret
, "file_defs[%d]: RemoveDirectory failed: %08lx\n", i
, GetLastError());
699 ret
= DeleteFileW(file_defs
[i
].name
);
700 ok(ret
, "file_defs[%d]: DeleteFile failed: %08lx\n", i
, GetLastError());
703 /* test that the folder item is still accessible by integer index */
705 r
= FolderItems_Item(items
, int_index
, &item
);
706 ok(r
== S_OK
, "file_defs[%d]: FolderItems::Item failed: %08lx\n", i
, r
);
707 ok(!!item
, "file_defs[%d]: item is null\n", i
);
710 r
= FolderItem_get_Path(item
, &bstr
);
711 ok(r
== S_OK
, "file_defs[%d]: FolderItem::get_Path failed: %08lx\n", i
, r
);
712 PathCombineW(path
, cur_dir
, V_BSTR(&str_index
));
713 ok(!lstrcmpW(bstr
, path
),
714 "file_defs[%d]: expected %s, got %s\n", i
, wine_dbgstr_w(path
), wine_dbgstr_w(bstr
));
717 FolderItem_Release(item
);
719 /* test that the folder item is no longer accessible by string index */
720 item
= (FolderItem
*)0xdeadbeef;
721 r
= FolderItems_Item(items
, str_index
, &item
);
722 ok(r
== S_FALSE
, "file_defs[%d]: expected S_FALSE, got %08lx\n", i
, r
);
723 ok(!item
, "file_defs[%d]: item is not null\n", i
);
725 VariantClear(&str_index
);
728 /* test that there are only as many folder items as there were files */
729 V_I4(&int_index
) = ARRAY_SIZE(file_defs
);
730 item
= (FolderItem
*)0xdeadbeef;
731 r
= FolderItems_Item(items
, int_index
, &item
);
732 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
733 ok(!item
, "item is not null\n");
735 if (0) /* crashes on xp */
737 r
= FolderItems_get_Application(items
, NULL
);
738 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08lx\n", r
);
741 r
= FolderItems_get_Application(items
, &disp
);
742 ok(r
== S_OK
, "FolderItems::get_Application failed: %08lx\n", r
);
744 r
= Folder_get_Application(folder
, &disp2
);
745 ok(r
== S_OK
, "Failed to get application pointer, hr %#lx.\n", r
);
746 ok(disp
== disp2
, "Unexpected application pointer.\n");
747 IDispatch_Release(disp2
);
748 IDispatch_Release(disp
);
750 if (0) /* crashes on xp */
752 r
= FolderItems_get_Parent(items
, NULL
);
753 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08lx\n", r
);
756 disp
= (IDispatch
*)0xdeadbeef;
757 r
= FolderItems_get_Parent(items
, &disp
);
758 ok(r
== E_NOTIMPL
, "expected E_NOTIMPL, got %08lx\n", r
);
759 ok(!disp
, "disp is not null\n");
761 if (0) /* crashes on xp */
763 r
= FolderItems__NewEnum(items
, NULL
);
764 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08lx\n", r
);
767 r
= FolderItems__NewEnum(items
, &unk
);
769 ok(r
== S_OK
, "FolderItems::_NewEnum failed: %08lx\n", r
);
771 ok(!!unk
, "unk is null\n");
772 if (unk
) IUnknown_Release(unk
);
776 r
= FolderItems3_Filter(items3
, 0, NULL
);
778 ok(r
== S_OK
, "expected S_OK, got %08lx\n", r
);
780 if (0) /* crashes on xp */
782 r
= FolderItems3_get_Verbs(items3
, NULL
);
783 ok(r
== E_INVALIDARG
, "expected E_INVALIDARG, got %08lx\n", r
);
786 r
= FolderItems3_get_Verbs(items3
, &verbs
);
788 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
789 ok(!verbs
, "verbs is not null\n");
792 /* remove the temporary directory and restore the original working directory */
793 GetTempPathW(MAX_PATH
, path
);
794 SetCurrentDirectoryW(path
);
795 ret
= RemoveDirectoryW(winetestW
);
796 ok(ret
, "RemoveDirectory failed: %08lx\n", GetLastError());
797 SetCurrentDirectoryW(orig_dir
);
799 /* test that everything stops working after the directory has been removed */
801 r
= FolderItems_get_Count(items
, &count
);
802 ok(r
== S_OK
, "FolderItems::get_Count failed: %08lx\n", r
);
803 ok(!count
, "expected 0 files, got %ld\n", count
);
806 V_I4(&int_index
) = 0;
807 item
= (FolderItem
*)0xdeadbeef;
808 r
= FolderItems_Item(items
, int_index
, &item
);
809 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
810 ok(!item
, "item is not null\n");
812 variant_set_string(&str_index
, file_defs
[0].name
);
813 item
= (FolderItem
*)0xdeadbeef;
814 r
= FolderItems_Item(items
, str_index
, &item
);
815 ok(r
== S_FALSE
, "expected S_FALSE, got %08lx\n", r
);
816 ok(!item
, "item is not null\n");
817 VariantClear(&str_index
);
819 FolderItems_Release(items
);
820 Folder_Release(folder
);
821 if (items3
) FolderItems3_Release(items3
);
822 IShellDispatch_Release(sd
);
825 static void test_service(void)
827 static const WCHAR spooler
[] = {'S','p','o','o','l','e','r',0};
828 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
829 SERVICE_STATUS_PROCESS status
;
830 SC_HANDLE scm
, service
;
837 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
838 &IID_IShellDispatch2
, (void**)&sd
);
841 win_skip("IShellDispatch2 not supported\n");
847 hr
= IShellDispatch2_IsServiceRunning(sd
, NULL
, &v
);
848 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
849 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
852 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
853 service
= OpenServiceW(scm
, spooler
, SERVICE_QUERY_STATUS
);
854 QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
, sizeof(SERVICE_STATUS_PROCESS
), &dummy
);
855 CloseServiceHandle(service
);
856 CloseServiceHandle(scm
);
858 /* service should exist */
859 name
= SysAllocString(spooler
);
861 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
863 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
864 if (status
.dwCurrentState
== SERVICE_RUNNING
)
865 ok(V_BOOL(&v
) == VARIANT_TRUE
, "got %d\n", V_BOOL(&v
));
867 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
870 /* service doesn't exist */
871 name
= SysAllocString(dummyW
);
873 hr
= IShellDispatch2_IsServiceRunning(sd
, name
, &v
);
875 ok(V_VT(&v
) == VT_BOOL
, "got %d\n", V_VT(&v
));
876 ok(V_BOOL(&v
) == VARIANT_FALSE
, "got %d\n", V_BOOL(&v
));
879 IShellDispatch2_Release(sd
);
882 static void test_dispatch_typeinfo(IDispatch
*disp
, REFIID
*riid
)
890 hr
= IDispatch_GetTypeInfoCount(disp
, &count
);
891 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
892 ok(count
== 1, "got %u\n", count
);
894 hr
= IDispatch_GetTypeInfo(disp
, 0, LOCALE_SYSTEM_DEFAULT
, &typeinfo
);
895 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
897 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
898 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
899 while (!IsEqualGUID(*riid
, &IID_NULL
)) {
900 if (IsEqualGUID(&typeattr
->guid
, *riid
))
904 ok(IsEqualGUID(&typeattr
->guid
, *riid
), "unexpected type guid %s\n", wine_dbgstr_guid(&typeattr
->guid
));
906 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
907 ITypeInfo_Release(typeinfo
);
910 static void test_ShellFolderViewDual(void)
912 static const IID
*shelldisp_riids
[] = {
913 &IID_IShellDispatch6
,
914 &IID_IShellDispatch5
,
915 &IID_IShellDispatch4
,
916 &IID_IShellDispatch2
,
917 &IID_IWin7ShellDispatch6
,
920 IShellFolderViewDual
*viewdual
;
921 IShellFolder
*desktop
, *tmpdir
;
922 IShellView
*view
, *view2
;
923 IDispatch
*disp
, *disp2
;
924 WCHAR pathW
[MAX_PATH
];
928 /* IShellFolderViewDual is not an IShellView extension */
929 hr
= SHGetDesktopFolder(&desktop
);
930 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
932 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
933 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
935 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
936 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
938 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
939 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
941 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp2
);
942 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
943 ok(disp2
== disp
, "got %p, %p\n", disp2
, disp
);
944 IDispatch_Release(disp2
);
946 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
947 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
948 ok(disp
== (IDispatch
*)viewdual
, "got %p, expected %p\n", viewdual
, disp
);
950 hr
= IShellFolderViewDual_QueryInterface(viewdual
, &IID_IShellView
, (void**)&view2
);
951 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
953 /* get_Application() */
955 if (0) /* crashes on pre-vista */ {
956 hr
= IShellFolderViewDual_get_Application(viewdual
, NULL
);
957 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
959 hr
= IShellFolderViewDual_get_Application(viewdual
, &disp2
);
960 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
961 ok(disp2
!= (IDispatch
*)viewdual
, "got %p, %p\n", disp2
, viewdual
);
962 test_dispatch_typeinfo(disp2
, shelldisp_riids
);
963 IDispatch_Release(disp2
);
965 IShellFolderViewDual_Release(viewdual
);
966 IDispatch_Release(disp
);
968 disp
= (void*)0xdeadbeef;
969 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IShellFolderViewDual
, (void**)&disp
);
970 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_NOTIMPL
) /* win2k */, "got 0x%08lx\n", hr
);
971 ok(disp
== NULL
, "got %p\n", disp
);
972 IShellView_Release(view
);
974 /* Try with some other folder, that's not a desktop */
975 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
976 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, pathW
, NULL
, &pidl
, NULL
);
977 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
979 hr
= IShellFolder_BindToObject(desktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&tmpdir
);
980 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
983 hr
= IShellFolder_CreateViewObject(desktop
, NULL
, &IID_IShellView
, (void**)&view
);
984 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
986 hr
= IShellView_QueryInterface(view
, &IID_IShellFolderViewDual
, (void**)&viewdual
);
987 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
989 hr
= IShellView_GetItemObject(view
, SVGIO_BACKGROUND
, &IID_IDispatch
, (void**)&disp
);
990 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
991 IDispatch_Release(disp
);
992 IShellView_Release(view
);
994 IShellFolder_Release(tmpdir
);
995 IShellFolder_Release(desktop
);
998 static void test_ShellWindows(void)
1000 IShellWindows
*shellwindows
;
1001 LONG cookie
, cookie2
, ret
;
1008 hr
= CoCreateInstance(&CLSID_ShellWindows
, NULL
, CLSCTX_LOCAL_SERVER
,
1009 &IID_IShellWindows
, (void**)&shellwindows
);
1010 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1011 /* TODO: remove when explorer startup with clean prefix is fixed */
1015 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, NULL
);
1016 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "got 0x%08lx\n", hr
);
1018 hr
= IShellWindows_Register(shellwindows
, NULL
, 0, SWC_EXPLORER
, &cookie
);
1019 ok(hr
== E_POINTER
, "got 0x%08lx\n", hr
);
1021 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
1022 ok(hr
== E_POINTER
, "got 0x%08lx\n", hr
);
1024 hr
= IShellWindows_Register(shellwindows
, (IDispatch
*)shellwindows
, 0, SWC_EXPLORER
, &cookie
);
1025 ok(hr
== E_POINTER
, "got 0x%08lx\n", hr
);
1027 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
1028 0, 0, 50, 14, 0, 0, 0, NULL
);
1029 ok(hwnd
!= NULL
, "got %p, error %ld\n", hwnd
, GetLastError());
1032 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie
);
1033 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1034 ok(cookie
!= 0, "got %ld\n", cookie
);
1037 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_EXPLORER
, &cookie2
);
1038 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1039 ok(cookie2
!= 0 && cookie2
!= cookie
, "got %ld\n", cookie2
);
1041 pidl
= ILCreateFromPathA("C:\\");
1042 V_VT(&v
) = VT_ARRAY
| VT_UI1
;
1043 V_ARRAY(&v
) = SafeArrayCreateVector(VT_UI1
, 0, ILGetSize(pidl
));
1044 memcpy(V_ARRAY(&v
)->pvData
, pidl
, ILGetSize(pidl
));
1047 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1048 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1049 ok(!ret
, "Got window %#lx.\n", ret
);
1050 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1052 hr
= IShellWindows_OnNavigate(shellwindows
, 0, &v
);
1053 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1055 hr
= IShellWindows_OnNavigate(shellwindows
, cookie
, &v
);
1056 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1058 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1059 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1060 ok(ret
== (LONG
)(LONG_PTR
)hwnd
, "Expected %p, got %#lx.\n", hwnd
, ret
);
1061 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1063 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
1064 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1066 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_EXPLORER
, &ret
, 0, &disp
);
1067 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1068 ok(!ret
, "Got window %#lx.\n", ret
);
1069 ok(!disp
, "Got IDispatch %p.\n", &disp
);
1071 hr
= IShellWindows_Revoke(shellwindows
, cookie2
);
1072 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1074 hr
= IShellWindows_Revoke(shellwindows
, 0);
1075 ok(hr
== S_FALSE
, "got 0x%08lx\n", hr
);
1077 /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
1079 hr
= IShellWindows_Register(shellwindows
, NULL
, HandleToLong(hwnd
), SWC_DESKTOP
, &cookie
);
1080 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1081 ok(cookie
!= 0, "got %ld\n", cookie
);
1083 disp
= (void*)0xdeadbeef;
1086 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, SWFO_NEEDDISPATCH
, &disp
);
1087 ok(hr
== S_OK
|| broken(hr
== S_FALSE
), "got 0x%08lx\n", hr
);
1088 if (hr
== S_FALSE
) /* winxp and earlier */ {
1089 win_skip("SWC_DESKTOP is not supported, some tests will be skipped.\n");
1090 /* older versions allowed to register SWC_DESKTOP and access it with FindWindowSW */
1091 ok(disp
== NULL
, "got %p\n", disp
);
1092 ok(ret
== 0, "got %ld\n", ret
);
1095 static const IID
*browser_riids
[] = {
1100 static const IID
*viewdual_riids
[] = {
1101 &IID_IShellFolderViewDual3
,
1105 IShellFolderViewDual
*view
;
1106 IShellBrowser
*sb
, *sb2
;
1107 IServiceProvider
*sp
;
1108 IDispatch
*doc
, *app
;
1113 ok(disp
!= NULL
, "got %p\n", disp
);
1114 ok(ret
!= HandleToUlong(hwnd
), "got %ld\n", ret
);
1116 /* IDispatch-related tests */
1117 test_dispatch_typeinfo(disp
, browser_riids
);
1120 hr
= IDispatch_QueryInterface(disp
, &IID_IWebBrowser2
, (void**)&wb
);
1121 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1123 hr
= IWebBrowser2_Refresh(wb
);
1125 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1127 hr
= IWebBrowser2_get_Application(wb
, &app
);
1128 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1129 ok(disp
== app
, "got %p, %p\n", app
, disp
);
1130 IDispatch_Release(app
);
1132 hr
= IWebBrowser2_get_Document(wb
, &doc
);
1134 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1136 test_dispatch_typeinfo(doc
, viewdual_riids
);
1138 IWebBrowser2_Release(wb
);
1140 /* IServiceProvider */
1141 hr
= IDispatch_QueryInterface(disp
, &IID_IShellFolderViewDual
, (void**)&view
);
1142 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1144 hr
= IDispatch_QueryInterface(disp
, &IID_IServiceProvider
, (void**)&sp
);
1145 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1147 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb
);
1148 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1150 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellBrowser
, (void**)&sb2
);
1151 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1152 ok(sb
== sb2
, "got %p, %p\n", sb
, sb2
);
1154 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IOleWindow
, (void**)&unk
);
1155 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1156 IUnknown_Release(unk
);
1158 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IExplorerBrowser
, (void**)&unk
);
1159 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1161 hr
= IShellBrowser_QueryInterface(sb
, &IID_IExplorerBrowser
, (void**)&unk
);
1162 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1164 hr
= IShellBrowser_QueryInterface(sb
, &IID_IWebBrowser2
, (void**)&unk
);
1165 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1167 hr
= IShellBrowser_QueryInterface(sb
, &IID_IDispatch
, (void**)&unk
);
1168 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1170 hr
= IShellBrowser_QueryActiveShellView(sb
, &sv
);
1171 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1172 IShellView_Release(sv
);
1174 IShellBrowser_Release(sb2
);
1175 IShellBrowser_Release(sb
);
1177 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IUnknown
, (void**)&unk
);
1178 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1180 hr
= IUnknown_QueryInterface(unk
, &IID_IShellBrowser
, (void**)&sb2
);
1181 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1182 IShellBrowser_Release(sb2
);
1183 IUnknown_Release(unk
);
1185 hr
= IServiceProvider_QueryService(sp
, &SID_STopLevelBrowser
, &IID_IShellView
, (void**)&sv
);
1186 ok(hr
== E_NOINTERFACE
, "got 0x%08lx\n", hr
);
1188 IServiceProvider_Release(sp
);
1189 IDispatch_Release(disp
);
1192 disp
= (void*)0xdeadbeef;
1195 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v
, SWC_DESKTOP
, &ret
, 0, &disp
);
1196 ok(hr
== S_OK
|| broken(hr
== S_FALSE
) /* winxp */, "got 0x%08lx\n", hr
);
1197 ok(disp
== NULL
, "got %p\n", disp
);
1198 ok(ret
!= HandleToUlong(hwnd
), "got %ld\n", ret
);
1200 disp
= (void*)0xdeadbeef;
1205 hr
= IShellWindows_FindWindowSW(shellwindows
, &v
, &v2
, SWC_BROWSER
, &ret
, SWFO_COOKIEPASSED
, &disp
);
1207 ok(hr
== S_FALSE
, "got 0x%08lx\n", hr
);
1208 ok(disp
== NULL
, "got %p\n", disp
);
1209 ok(ret
== 0, "got %ld\n", ret
);
1211 hr
= IShellWindows_Revoke(shellwindows
, cookie
);
1212 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1213 DestroyWindow(hwnd
);
1214 IShellWindows_Release(shellwindows
);
1217 static void test_ParseName(void)
1219 static const WCHAR cadabraW
[] = {'c','a','d','a','b','r','a',0};
1220 WCHAR pathW
[MAX_PATH
];
1228 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1229 &IID_IShellDispatch
, (void**)&sd
);
1230 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1232 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
1234 V_BSTR(&v
) = SysAllocString(pathW
);
1235 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1236 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1239 item
= (void*)0xdeadbeef;
1240 hr
= Folder_ParseName(folder
, NULL
, &item
);
1241 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08lx\n", hr
);
1242 ok(item
== NULL
, "got %p\n", item
);
1245 str
= SysAllocStringLen(NULL
, 0);
1246 item
= (void*)0xdeadbeef;
1247 hr
= Folder_ParseName(folder
, str
, &item
);
1248 ok(hr
== S_FALSE
|| broken(hr
== E_INVALIDARG
) /* win2k */, "got 0x%08lx\n", hr
);
1249 ok(item
== NULL
, "got %p\n", item
);
1252 /* path doesn't exist */
1253 str
= SysAllocString(cadabraW
);
1254 item
= (void*)0xdeadbeef;
1255 hr
= Folder_ParseName(folder
, str
, &item
);
1256 ok(hr
== S_FALSE
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* win2k */,
1257 "got 0x%08lx\n", hr
);
1258 ok(item
== NULL
, "got %p\n", item
);
1261 lstrcatW(pathW
, cadabraW
);
1262 CreateDirectoryW(pathW
, NULL
);
1264 str
= SysAllocString(cadabraW
);
1266 hr
= Folder_ParseName(folder
, str
, &item
);
1267 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1268 ok(item
!= NULL
, "got %p\n", item
);
1271 hr
= FolderItem_get_Path(item
, &str
);
1272 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1273 ok(str
[0] != 0, "path %s\n", wine_dbgstr_w(str
));
1276 RemoveDirectoryW(pathW
);
1277 FolderItem_Release(item
);
1278 Folder_Release(folder
);
1279 IShellDispatch_Release(sd
);
1282 static void test_Verbs(void)
1284 FolderItemVerbs
*verbs
, *verbs2
;
1285 WCHAR pathW
[MAX_PATH
];
1286 FolderItemVerb
*verb
;
1297 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1298 &IID_IShellDispatch
, (void**)&sd
);
1299 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1301 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
1303 V_BSTR(&v
) = SysAllocString(pathW
);
1304 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1305 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1308 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
1309 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1310 Folder_Release(folder
);
1312 hr
= Folder2_get_Self(folder2
, &item
);
1313 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1314 Folder2_Release(folder2
);
1316 if (0) { /* crashes on some systems */
1317 hr
= FolderItem_Verbs(item
, NULL
);
1318 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
1320 hr
= FolderItem_Verbs(item
, &verbs
);
1321 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1323 hr
= FolderItem_Verbs(item
, &verbs2
);
1324 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1325 ok(verbs2
!= verbs
, "Unexpected verbs pointer.\n");
1326 FolderItemVerbs_Release(verbs2
);
1328 disp
= (void *)0xdeadbeef;
1329 hr
= FolderItemVerbs_get_Application(verbs
, &disp
);
1330 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1331 ok(disp
== NULL
, "Unexpected application pointer.\n");
1333 disp
= (void *)0xdeadbeef;
1334 hr
= FolderItemVerbs_get_Parent(verbs
, &disp
);
1335 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1336 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1338 if (0) { /* crashes on winxp/win2k3 */
1339 hr
= FolderItemVerbs_get_Count(verbs
, NULL
);
1340 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
1343 hr
= FolderItemVerbs_get_Count(verbs
, &count
);
1344 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1345 ok(count
> 0, "got count %ld\n", count
);
1347 if (0) { /* crashes on winxp/win2k3 */
1350 hr
= FolderItemVerbs_Item(verbs
, v
, NULL
);
1351 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
1353 /* there's always one item more, so you can access [0,count],
1354 instead of actual [0,count) */
1355 for (i
= 0; i
<= count
; i
++) {
1358 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1359 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1360 hr
= FolderItemVerb_get_Name(verb
, &str
);
1361 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1362 ok(str
!= NULL
, "%ld: name %s\n", i
, wine_dbgstr_w(str
));
1364 ok(str
[0] == 0, "%ld: got terminating item %s\n", i
, wine_dbgstr_w(str
));
1366 disp
= (void *)0xdeadbeef;
1367 hr
= FolderItemVerb_get_Parent(verb
, &disp
);
1368 ok(hr
== E_NOTIMPL
, "got %#lx.\n", hr
);
1369 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1371 disp
= (void *)0xdeadbeef;
1372 hr
= FolderItemVerb_get_Application(verb
, &disp
);
1373 ok(hr
== E_NOTIMPL
, "got %#lx.\n", hr
);
1374 ok(disp
== NULL
, "Unexpected parent pointer %p.\n", disp
);
1377 FolderItemVerb_Release(verb
);
1383 hr
= FolderItemVerbs_Item(verbs
, v
, &verb
);
1384 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1385 ok(verb
== NULL
, "got %p\n", verb
);
1387 FolderItemVerbs_Release(verbs
);
1388 FolderItem_Release(item
);
1389 IShellDispatch_Release(sd
);
1392 static void test_ShellLinkObject(void)
1396 WCHAR path
[MAX_PATH
],
1397 empty_path
[MAX_PATH
],
1398 link_path
[MAX_PATH
];
1403 IDispatch
*dispatch
;
1405 IShellLinkDual2
* sld
;
1412 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1413 &IID_IShellDispatch
, (void**)&sd
);
1414 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1416 GetTempPathW(MAX_PATH
, path
);
1418 V_BSTR(&v
) = SysAllocString(path
);
1419 hr
= IShellDispatch_NameSpace(sd
, v
, &folder
);
1420 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1423 hr
= Folder_QueryInterface(folder
, &IID_Folder2
, (void**)&folder2
);
1424 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1425 Folder_Release(folder
);
1427 hr
= Folder2_get_Self(folder2
, &item
);
1428 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1430 dispatch
= (IDispatch
*)0xdeadbeef;
1431 hr
= FolderItem_get_GetLink(item
, &dispatch
);
1432 ok(hr
== E_NOTIMPL
, "got 0x%08lx\n", hr
);
1433 ok(dispatch
== NULL
, "got %p\n", dispatch
);
1435 FolderItem_Release(item
);
1437 PathCombineW(empty_path
, path
, L
"winetest_empty_file.txt");
1438 file
= CreateFileW(empty_path
, 0, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1439 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %08lx\n", GetLastError());
1442 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLinkW
, (LPVOID
*)&sl
);
1443 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1444 hr
= IShellLinkW_SetPath(sl
, empty_path
);
1445 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1446 hr
= IShellLinkW_GetPath(sl
, empty_path
, MAX_PATH
, NULL
, 0);
1447 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1448 hr
= IShellLinkW_SetDescription(sl
, L
"description");
1449 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1450 hr
= IShellLinkW_SetWorkingDirectory(sl
, L
"working directory");
1451 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1452 hr
= IShellLinkW_SetArguments(sl
, L
"arguments");
1453 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1454 hr
= IShellLinkW_SetHotkey(sl
, 1234);
1455 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1456 hr
= IShellLinkW_SetShowCmd(sl
, 1);
1457 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1459 hr
= IShellLinkW_QueryInterface(sl
, &IID_IPersistFile
, (LPVOID
*)&pf
);
1460 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1462 PathCombineW(link_path
, path
, L
"winetest_filled.lnk");
1463 hr
= IPersistFile_Save(pf
, link_path
, TRUE
);
1464 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1466 IPersistFile_Release(pf
);
1467 IShellLinkW_Release(sl
);
1469 str
= SysAllocString(L
"winetest_filled.lnk");
1470 hr
= Folder2_ParseName(folder2
, str
, &item
);
1471 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1475 hr
= FolderItem_get_GetLink(item
, &dispatch
);
1476 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1477 ok(dispatch
!= NULL
, "got %p\n", dispatch
);
1480 sld
= (IShellLinkDual2
*)dispatch
;
1483 hr
= IShellLinkDual2_get_Path(sld
, &str
);
1484 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1486 ok(!wcscmp(str
, empty_path
), "got %s (wanted %s)\n",
1487 wine_dbgstr_w(str
), wine_dbgstr_w(empty_path
));
1492 hr
= IShellLinkDual2_get_Description(sld
, &str
);
1493 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1495 ok(!wcscmp(str
, L
"description"), "got %s\n", wine_dbgstr_w(str
));
1500 hr
= IShellLinkDual2_get_WorkingDirectory(sld
, &str
);
1501 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1503 ok(!wcscmp(str
, L
"working directory"), "got %s\n", wine_dbgstr_w(str
));
1508 hr
= IShellLinkDual2_get_Arguments(sld
, &str
);
1509 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1511 ok(!wcscmp(str
, L
"arguments"), "got %s\n", wine_dbgstr_w(str
));
1516 hr
= IShellLinkDual2_get_Hotkey(sld
, &hk
);
1517 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1518 todo_wine
ok(hk
== 1234, "got %i\n", hk
);
1521 hr
= IShellLinkDual2_get_ShowCommand(sld
, &hk
);
1522 todo_wine
ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
1523 todo_wine
ok(hk
== 1, "got %i\n", hk
);
1525 IShellLinkDual2_Release(sld
);
1528 FolderItem_Release(item
);
1530 ret
= DeleteFileW(link_path
);
1531 ok(ret
, "DeleteFile failed: %08lx\n", GetLastError());
1532 ret
= DeleteFileW(empty_path
);
1533 ok(ret
, "DeleteFile failed: %08lx\n", GetLastError());
1535 Folder2_Release(folder2
);
1537 IShellDispatch_Release(sd
);
1540 static void test_ShellExecute(void)
1543 IShellDispatch2
*sd
;
1545 VARIANT args
, dir
, op
, show
;
1547 static const WCHAR regW
[] = {'r','e','g',0};
1549 hr
= CoCreateInstance(&CLSID_Shell
, NULL
, CLSCTX_INPROC_SERVER
,
1550 &IID_IShellDispatch2
, (void**)&sd
);
1553 win_skip("IShellDispatch2 not supported\n");
1562 V_VT(&show
) = VT_I4
;
1565 name
= SysAllocString(regW
);
1567 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1568 ok(hr
== S_OK
, "ShellExecute failed: %08lx\n", hr
);
1570 /* test invalid value for show */
1571 V_VT(&show
) = VT_BSTR
;
1572 V_BSTR(&show
) = name
;
1574 hr
= IShellDispatch2_ShellExecute(sd
, name
, args
, dir
, op
, show
);
1575 ok(hr
== S_OK
, "ShellExecute failed: %08lx\n", hr
);
1577 SysFreeString(name
);
1578 IShellDispatch2_Release(sd
);
1581 START_TEST(shelldispatch
)
1585 r
= CoInitialize(NULL
);
1586 ok(SUCCEEDED(r
), "CoInitialize failed: %08lx\n", r
);
1590 init_function_pointers();
1594 test_ShellFolderViewDual();
1595 test_ShellWindows();
1598 test_ShellLinkObject();
1599 test_ShellExecute();