crypt32: Use the available ARRAY_SIZE() macro.
[wine.git] / dlls / shell32 / tests / shelldispatch.c
blob30c8291f5815111abd4a8bd1566e30a1e09f8e44
1 /*
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
21 #define COBJMACROS
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
25 #include "shldisp.h"
26 #include "shlobj.h"
27 #include "shlwapi.h"
28 #include "winsvc.h"
30 #include "wine/heap.h"
31 #include "wine/test.h"
33 #include "initguid.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)
41 ULONG rc;
42 IUnknown_AddRef(obj);
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)
56 BSTR ret;
57 int len;
59 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
60 ret = SysAllocStringLen(NULL, len);
61 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
63 return ret;
66 static void variant_set_string(VARIANT *v, const char *s)
68 V_VT(v) = VT_BSTR;
69 V_BSTR(v) = a2bstr(s);
72 static void init_function_pointers(void)
74 HMODULE hshell32;
76 hshell32 = GetModuleHandleA("shell32.dll");
77 pSHGetNameFromIDList = (void*)GetProcAddress(hshell32, "SHGetNameFromIDList");
80 static void test_namespace(void)
82 static const ShellSpecialFolderConstants special_folders[] =
84 ssfDESKTOP,
85 ssfPROGRAMS,
86 ssfCONTROLS,
87 ssfPRINTERS,
88 ssfPERSONAL,
89 ssfFAVORITES,
90 ssfSTARTUP,
91 ssfRECENT,
92 ssfSENDTO,
93 ssfBITBUCKET,
94 ssfSTARTMENU,
95 ssfDESKTOPDIRECTORY,
96 ssfDRIVES,
97 ssfNETWORK,
98 ssfNETHOOD,
99 ssfFONTS,
100 ssfTEMPLATES,
101 ssfCOMMONSTARTMENU,
102 ssfCOMMONPROGRAMS,
103 ssfCOMMONSTARTUP,
104 ssfCOMMONDESKTOPDIR,
105 ssfAPPDATA,
106 ssfPRINTHOOD,
107 ssfLOCALAPPDATA,
108 ssfALTSTARTUP,
109 ssfCOMMONALTSTARTUP,
110 ssfCOMMONFAVORITES,
111 ssfINTERNETCACHE,
112 ssfCOOKIES,
113 ssfHISTORY,
114 ssfCOMMONAPPDATA,
115 ssfWINDOWS,
116 ssfSYSTEM,
117 ssfPROGRAMFILES,
118 ssfMYPICTURES,
119 ssfPROFILE,
120 ssfSYSTEMx86,
121 ssfPROGRAMFILESx86,
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;
132 HRESULT r;
133 IShellDispatch *sd;
134 Folder *folder;
135 Folder2 *folder2;
136 FolderItem *item;
137 VARIANT var;
138 BSTR title, item_path;
139 IDispatch *disp;
140 int len, i;
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);
145 disp = NULL;
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);
151 disp = NULL;
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);
157 VariantInit(&var);
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++)
166 V_VT(&var) = VT_I4;
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)
171 todo_wine
172 ok(r == S_OK || broken(r == S_FALSE) /* winxp */, "Failed to get folder for index %#x, got %08x\n", special_folders[i], r);
173 else
174 ok(r == S_OK, "Failed to get folder for index %#x, got %08x\n", special_folders[i], r);
175 if (folder)
176 Folder_Release(folder);
179 V_VT(&var) = VT_I4;
180 V_I4(&var) = -1;
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);
186 V_VT(&var) = VT_I4;
187 V_I4(&var) = ssfPROGRAMFILES;
188 r = IShellDispatch_NameSpace(sd, var, &folder);
189 ok(r == S_OK, "IShellDispatch::NameSpace failed: %08x\n", r);
190 if (r == S_OK)
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);
199 if (r == S_OK)
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)
207 LPITEMIDLIST pidl;
208 PWSTR name;
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));
215 CoTaskMemFree(name);
216 CoTaskMemFree(pidl);
218 else
220 WCHAR *p;
222 p = path + lstrlenW(path);
223 while (path < p && *(p - 1) != '\\')
224 p--;
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);
232 if (r == S_OK)
234 r = Folder2_get_Self(folder2, &item);
235 ok(r == S_OK, "Folder::get_Self failed: %08x\n", r);
236 if (r == S_OK)
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);
249 V_VT(&var) = VT_I4;
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);
311 VariantClear(&var);
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);
321 if (r == S_OK)
323 r = Folder_get_Title(folder, &title);
324 ok(r == S_OK, "Folder::get_Title failed: %08x\n", r);
325 if (r == S_OK)
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);
333 if (r == S_OK)
335 r = Folder2_get_Self(folder2, &item);
336 ok(r == S_OK, "Folder::get_Self failed: %08x\n", r);
337 if (r == S_OK)
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)
361 static const struct
363 char name[32];
364 enum
366 DIRECTORY,
367 EMPTY_FILE,
369 type;
371 file_defs[] =
373 { "00-Myfolder", DIRECTORY },
374 { "01-empty.bin", EMPTY_FILE },
376 WCHAR path[MAX_PATH], cur_dir[MAX_PATH], orig_dir[MAX_PATH];
377 HRESULT r;
378 IShellDispatch *sd = NULL;
379 Folder *folder = NULL;
380 FolderItems *items;
381 FolderItems2 *items2 = NULL;
382 FolderItems3 *items3 = NULL;
383 FolderItem *item = (FolderItem*)0xdeadbeef, *item2;
384 FolderItemVerbs *verbs = (FolderItemVerbs*)0xdeadbeef;
385 VARIANT var, int_index, str_index, str_index2;
386 IDispatch *disp, *disp2;
387 LONG count = -1;
388 IUnknown *unk;
389 HANDLE file;
390 BSTR bstr;
391 char cstr[64];
392 BOOL ret;
393 int i;
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);
409 EXPECT_REF(sd, 1);
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);
414 EXPECT_REF(sd, 1);
416 VariantClear(&var);
417 SetCurrentDirectoryW(winetestW);
418 GetCurrentDirectoryW(MAX_PATH, path);
419 GetLongPathNameW(path, cur_dir, MAX_PATH);
421 /* FolderItems grabs its Folder reference */
422 items = NULL;
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);
429 unk = NULL;
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 */
441 disp = NULL;
442 EXPECT_REF(sd, 1);
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");
446 EXPECT_REF(sd, 1);
448 disp2 = NULL;
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);
466 V_VT(&var) = VT_I4;
467 V_I4(&var) = 0;
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)
481 case DIRECTORY:
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());
487 CloseHandle(file);
488 break;
490 case EMPTY_FILE:
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());
493 CloseHandle(file);
494 break;
498 /* test that get_Count is not aware of the newly created files */
499 count = -1;
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);
506 item = NULL;
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);
522 VariantClear(&var);
524 /* recreate the items object */
525 FolderItems_Release(items);
526 items = NULL;
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);
532 if (r == S_OK)
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");
541 count = -1;
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);
546 V_VT(&var) = VT_EMPTY;
547 item = (FolderItem*)0xdeadbeef;
548 r = FolderItems_Item(items, var, &item);
549 ok(r == E_NOTIMPL, "expected E_NOTIMPL, got %08x\n", r);
550 ok(!item, "item is not null\n");
552 V_VT(&var) = VT_I2;
553 V_I2(&var) = 0;
555 EXPECT_REF(folder, 2);
556 EXPECT_REF(items, 2);
557 item = NULL;
558 r = FolderItems_Item(items, var, &item);
559 ok(r == S_OK, "FolderItems::Item failed: %08x\n", r);
560 ok(!!item, "item is null\n");
561 EXPECT_REF(folder, 3);
562 EXPECT_REF(items, 2);
564 r = Folder_get_Application(folder, &disp);
565 ok(r == S_OK, "Failed to get application pointer %#x.\n", r);
566 r = FolderItem_get_Application(item, &disp2);
567 ok(r == S_OK, "Failed to get application pointer %#x.\n", r);
568 ok(disp == disp2, "Unexpected application pointer.\n");
569 IDispatch_Release(disp2);
570 IDispatch_Release(disp);
572 FolderItem_Release(item);
574 V_VT(&var) = VT_I4;
575 V_I4(&var) = 0;
576 item = NULL;
577 r = FolderItems_Item(items, var, &item);
578 ok(r == S_OK, "FolderItems::Item failed: %08x\n", r);
579 ok(!!item, "item is null\n");
580 if (item) FolderItem_Release(item);
582 V_I4(&var) = -1;
583 item = (FolderItem*)0xdeadbeef;
584 r = FolderItems_Item(items, var, &item);
585 ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
586 ok(!item, "item is not null\n");
588 V_VT(&var) = VT_ERROR;
589 V_ERROR(&var) = 0;
590 item = NULL;
591 r = FolderItems_Item(items, var, &item);
592 ok(r == S_OK, "expected S_OK, got %08x\n", r);
593 ok(!!item, "item is null\n");
594 if (item)
596 bstr = NULL;
597 r = FolderItem_get_Path(item, &bstr);
598 ok(r == S_OK, "FolderItem::get_Path failed: %08x\n", r);
599 ok(!lstrcmpW(bstr, cur_dir),
600 "expected %s, got %s\n", wine_dbgstr_w(cur_dir), wine_dbgstr_w(bstr));
601 SysFreeString(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++)
610 VARIANT_BOOL b;
611 BSTR name;
613 V_I4(&int_index) = i;
614 variant_set_string(&str_index, file_defs[i].name);
616 item = NULL;
617 r = FolderItems_Item(items, int_index, &item);
618 ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
619 ok(!!item, "file_defs[%d]: item is null\n", i);
621 item2 = NULL;
622 r = FolderItems_Item(items, int_index, &item2);
623 ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
624 ok(item2 != item, "file_defs[%d]: item and item2 are the same\n", i);
625 FolderItem_Release(item2);
627 bstr = NULL;
628 r = FolderItem_get_Path(item, &bstr);
629 ok(r == S_OK, "file_defs[%d]: FolderItem::get_Path failed: %08x\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));
633 SysFreeString(bstr);
635 bstr = a2bstr(file_defs[i].name);
636 r = FolderItem_get_Name(item, &name);
637 ok(r == S_OK, "Failed to get item name, hr %#x.\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));
641 SysFreeString(name);
642 SysFreeString(bstr);
644 FolderItem_Release(item);
646 item = NULL;
647 r = FolderItems_Item(items, str_index, &item);
648 ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
649 ok(!!item, "file_defs[%d]: item is null\n", i);
651 bstr = NULL;
652 r = FolderItem_get_Path(item, &bstr);
653 ok(r == S_OK, "file_defs[%d]: FolderItem::get_Path failed: %08x\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));
657 SysFreeString(bstr);
659 b = 0xdead;
660 r = FolderItem_get_IsFolder(item, &b);
661 ok(r == S_OK, "Failed to get IsFolder property, %#x.\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 PathCombineA(cstr, file_defs[i].name, "foo.txt");
670 variant_set_string(&str_index2, cstr);
671 item2 = NULL;
672 r = FolderItems_Item(items, str_index2, &item2);
673 ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\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 = DeleteFileA(cstr);
680 ok(ret, "file_defs[%d]: DeleteFile failed: %08x\n", i, GetLastError());
682 /* test that getting an item object via a relative path fails */
683 strcpy(cstr, file_defs[i].name);
684 strcat(cstr, "\\..\\");
685 strcat(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 todo_wine {
690 ok(r == S_FALSE, "file_defs[%d]: expected S_FALSE, got %08x\n", i, r);
691 ok(!item2, "file_defs[%d]: item is not null\n", i);
693 if (item2) FolderItem_Release(item2);
694 VariantClear(&str_index2);
696 /* remove the directory */
697 ret = RemoveDirectoryA(file_defs[i].name);
698 ok(ret, "file_defs[%d]: RemoveDirectory failed: %08x\n", i, GetLastError());
700 else
702 ret = DeleteFileA(file_defs[i].name);
703 ok(ret, "file_defs[%d]: DeleteFile failed: %08x\n", i, GetLastError());
706 /* test that the folder item is still accessible by integer index */
707 item = NULL;
708 r = FolderItems_Item(items, int_index, &item);
709 ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
710 ok(!!item, "file_defs[%d]: item is null\n", i);
712 bstr = NULL;
713 r = FolderItem_get_Path(item, &bstr);
714 ok(r == S_OK, "file_defs[%d]: FolderItem::get_Path failed: %08x\n", i, r);
715 PathCombineW(path, cur_dir, V_BSTR(&str_index));
716 ok(!lstrcmpW(bstr, path),
717 "file_defs[%d]: expected %s, got %s\n", i, wine_dbgstr_w(path), wine_dbgstr_w(bstr));
718 SysFreeString(bstr);
720 FolderItem_Release(item);
722 /* test that the folder item is no longer accessible by string index */
723 item = (FolderItem*)0xdeadbeef;
724 r = FolderItems_Item(items, str_index, &item);
725 ok(r == S_FALSE, "file_defs[%d]: expected S_FALSE, got %08x\n", i, r);
726 ok(!item, "file_defs[%d]: item is not null\n", i);
728 VariantClear(&str_index);
731 /* test that there are only as many folder items as there were files */
732 V_I4(&int_index) = ARRAY_SIZE(file_defs);
733 item = (FolderItem*)0xdeadbeef;
734 r = FolderItems_Item(items, int_index, &item);
735 ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
736 ok(!item, "item is not null\n");
738 if (0) /* crashes on xp */
740 r = FolderItems_get_Application(items, NULL);
741 ok(r == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", r);
744 r = FolderItems_get_Application(items, &disp);
745 ok(r == S_OK, "FolderItems::get_Application failed: %08x\n", r);
747 r = Folder_get_Application(folder, &disp2);
748 ok(r == S_OK, "Failed to get application pointer, hr %#x.\n", r);
749 ok(disp == disp2, "Unexpected application pointer.\n");
750 IDispatch_Release(disp2);
751 IDispatch_Release(disp);
753 if (0) /* crashes on xp */
755 r = FolderItems_get_Parent(items, NULL);
756 ok(r == E_NOTIMPL, "expected E_NOTIMPL, got %08x\n", r);
759 disp = (IDispatch*)0xdeadbeef;
760 r = FolderItems_get_Parent(items, &disp);
761 ok(r == E_NOTIMPL, "expected E_NOTIMPL, got %08x\n", r);
762 ok(!disp, "disp is not null\n");
764 if (0) /* crashes on xp */
766 r = FolderItems__NewEnum(items, NULL);
767 ok(r == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", r);
770 r = FolderItems__NewEnum(items, &unk);
771 todo_wine
772 ok(r == S_OK, "FolderItems::_NewEnum failed: %08x\n", r);
773 todo_wine
774 ok(!!unk, "unk is null\n");
775 if (unk) IUnknown_Release(unk);
777 if (items3)
779 r = FolderItems3_Filter(items3, 0, NULL);
780 todo_wine
781 ok(r == S_OK, "expected S_OK, got %08x\n", r);
783 if (0) /* crashes on xp */
785 r = FolderItems3_get_Verbs(items3, NULL);
786 ok(r == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", r);
789 r = FolderItems3_get_Verbs(items3, &verbs);
790 todo_wine
791 ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
792 ok(!verbs, "verbs is not null\n");
795 /* remove the temporary directory and restore the original working directory */
796 GetTempPathW(MAX_PATH, path);
797 SetCurrentDirectoryW(path);
798 ret = RemoveDirectoryW(winetestW);
799 ok(ret, "RemoveDirectory failed: %08x\n", GetLastError());
800 SetCurrentDirectoryW(orig_dir);
802 /* test that everything stops working after the directory has been removed */
803 count = -1;
804 r = FolderItems_get_Count(items, &count);
805 ok(r == S_OK, "FolderItems::get_Count failed: %08x\n", r);
806 ok(!count, "expected 0 files, got %d\n", count);
808 item = NULL;
809 V_I4(&int_index) = 0;
810 item = (FolderItem*)0xdeadbeef;
811 r = FolderItems_Item(items, int_index, &item);
812 ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
813 ok(!item, "item is not null\n");
815 variant_set_string(&str_index, file_defs[0].name);
816 item = (FolderItem*)0xdeadbeef;
817 r = FolderItems_Item(items, str_index, &item);
818 ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
819 ok(!item, "item is not null\n");
820 VariantClear(&str_index);
822 FolderItems_Release(items);
823 Folder_Release(folder);
824 if (items3) FolderItems3_Release(items3);
825 IShellDispatch_Release(sd);
828 static void test_service(void)
830 static const WCHAR spooler[] = {'S','p','o','o','l','e','r',0};
831 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
832 SERVICE_STATUS_PROCESS status;
833 SC_HANDLE scm, service;
834 IShellDispatch2 *sd;
835 DWORD dummy;
836 HRESULT hr;
837 BSTR name;
838 VARIANT v;
840 hr = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
841 &IID_IShellDispatch2, (void**)&sd);
842 if (hr != S_OK)
844 win_skip("IShellDispatch2 not supported\n");
845 return;
848 V_VT(&v) = VT_I2;
849 V_I2(&v) = 10;
850 hr = IShellDispatch2_IsServiceRunning(sd, NULL, &v);
851 ok(V_VT(&v) == VT_BOOL, "got %d\n", V_VT(&v));
852 ok(V_BOOL(&v) == VARIANT_FALSE, "got %d\n", V_BOOL(&v));
853 EXPECT_HR(hr, S_OK);
855 scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
856 service = OpenServiceW(scm, spooler, SERVICE_QUERY_STATUS);
857 QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, sizeof(SERVICE_STATUS_PROCESS), &dummy);
858 CloseServiceHandle(service);
859 CloseServiceHandle(scm);
861 /* service should exist */
862 name = SysAllocString(spooler);
863 V_VT(&v) = VT_I2;
864 hr = IShellDispatch2_IsServiceRunning(sd, name, &v);
865 EXPECT_HR(hr, S_OK);
866 ok(V_VT(&v) == VT_BOOL, "got %d\n", V_VT(&v));
867 if (status.dwCurrentState == SERVICE_RUNNING)
868 ok(V_BOOL(&v) == VARIANT_TRUE, "got %d\n", V_BOOL(&v));
869 else
870 ok(V_BOOL(&v) == VARIANT_FALSE, "got %d\n", V_BOOL(&v));
871 SysFreeString(name);
873 /* service doesn't exist */
874 name = SysAllocString(dummyW);
875 V_VT(&v) = VT_I2;
876 hr = IShellDispatch2_IsServiceRunning(sd, name, &v);
877 EXPECT_HR(hr, S_OK);
878 ok(V_VT(&v) == VT_BOOL, "got %d\n", V_VT(&v));
879 ok(V_BOOL(&v) == VARIANT_FALSE, "got %d\n", V_BOOL(&v));
880 SysFreeString(name);
882 IShellDispatch2_Release(sd);
885 static void test_dispatch_typeinfo(IDispatch *disp, REFIID *riid)
887 ITypeInfo *typeinfo;
888 TYPEATTR *typeattr;
889 UINT count;
890 HRESULT hr;
892 count = 10;
893 hr = IDispatch_GetTypeInfoCount(disp, &count);
894 ok(hr == S_OK, "got 0x%08x\n", hr);
895 ok(count == 1, "got %u\n", count);
897 hr = IDispatch_GetTypeInfo(disp, 0, LOCALE_SYSTEM_DEFAULT, &typeinfo);
898 ok(hr == S_OK, "got 0x%08x\n", hr);
900 hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
901 ok(hr == S_OK, "got 0x%08x\n", hr);
902 while (!IsEqualGUID(*riid, &IID_NULL)) {
903 if (IsEqualGUID(&typeattr->guid, *riid))
904 break;
905 riid++;
907 ok(IsEqualGUID(&typeattr->guid, *riid), "unexpected type guid %s\n", wine_dbgstr_guid(&typeattr->guid));
909 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
910 ITypeInfo_Release(typeinfo);
913 static void test_ShellFolderViewDual(void)
915 static const IID *shelldisp_riids[] = {
916 &IID_IShellDispatch6,
917 &IID_IShellDispatch5,
918 &IID_IShellDispatch4,
919 &IID_IShellDispatch2,
920 &IID_IWin7ShellDispatch6,
921 &IID_NULL
923 IShellFolderViewDual *viewdual;
924 IShellFolder *desktop, *tmpdir;
925 IShellView *view, *view2;
926 IDispatch *disp, *disp2;
927 WCHAR pathW[MAX_PATH];
928 LPITEMIDLIST pidl;
929 HRESULT hr;
931 /* IShellFolderViewDual is not an IShellView extension */
932 hr = SHGetDesktopFolder(&desktop);
933 ok(hr == S_OK, "got 0x%08x\n", hr);
935 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
936 ok(hr == S_OK, "got 0x%08x\n", hr);
938 hr = IShellView_QueryInterface(view, &IID_IShellFolderViewDual, (void**)&viewdual);
939 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
941 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&disp);
942 ok(hr == S_OK, "got 0x%08x\n", hr);
944 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&disp2);
945 ok(hr == S_OK, "got 0x%08x\n", hr);
946 ok(disp2 == disp, "got %p, %p\n", disp2, disp);
947 IDispatch_Release(disp2);
949 hr = IDispatch_QueryInterface(disp, &IID_IShellFolderViewDual, (void**)&viewdual);
950 ok(hr == S_OK, "got 0x%08x\n", hr);
951 ok(disp == (IDispatch*)viewdual, "got %p, expected %p\n", viewdual, disp);
953 hr = IShellFolderViewDual_QueryInterface(viewdual, &IID_IShellView, (void**)&view2);
954 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
956 /* get_Application() */
958 if (0) /* crashes on pre-vista */ {
959 hr = IShellFolderViewDual_get_Application(viewdual, NULL);
960 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
962 hr = IShellFolderViewDual_get_Application(viewdual, &disp2);
963 ok(hr == S_OK, "got 0x%08x\n", hr);
964 ok(disp2 != (IDispatch*)viewdual, "got %p, %p\n", disp2, viewdual);
965 test_dispatch_typeinfo(disp2, shelldisp_riids);
966 IDispatch_Release(disp2);
968 IShellFolderViewDual_Release(viewdual);
969 IDispatch_Release(disp);
971 disp = (void*)0xdeadbeef;
972 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IShellFolderViewDual, (void**)&disp);
973 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL) /* win2k */, "got 0x%08x\n", hr);
974 ok(disp == NULL, "got %p\n", disp);
975 IShellView_Release(view);
977 /* Try with some other folder, that's not a desktop */
978 GetTempPathW(ARRAY_SIZE(pathW), pathW);
979 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, pathW, NULL, &pidl, NULL);
980 ok(hr == S_OK, "got 0x%08x\n", hr);
982 hr = IShellFolder_BindToObject(desktop, pidl, NULL, &IID_IShellFolder, (void**)&tmpdir);
983 ok(hr == S_OK, "got 0x%08x\n", hr);
984 CoTaskMemFree(pidl);
986 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
987 ok(hr == S_OK, "got 0x%08x\n", hr);
989 hr = IShellView_QueryInterface(view, &IID_IShellFolderViewDual, (void**)&viewdual);
990 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
992 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&disp);
993 ok(hr == S_OK, "got 0x%08x\n", hr);
994 IDispatch_Release(disp);
995 IShellView_Release(view);
997 IShellFolder_Release(tmpdir);
998 IShellFolder_Release(desktop);
1001 static void test_ShellWindows(void)
1003 IShellWindows *shellwindows;
1004 LONG cookie, cookie2, ret;
1005 IDispatch *disp;
1006 VARIANT v, v2;
1007 HRESULT hr;
1008 HWND hwnd;
1010 hr = CoCreateInstance(&CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER,
1011 &IID_IShellWindows, (void**)&shellwindows);
1012 ok(hr == S_OK, "got 0x%08x\n", hr);
1013 /* TODO: remove when explorer startup with clean prefix is fixed */
1014 if (hr != S_OK)
1015 return;
1017 if (0) /* NULL out argument - currently crashes on Wine */ {
1018 hr = IShellWindows_Register(shellwindows, NULL, 0, SWC_EXPLORER, NULL);
1019 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "got 0x%08x\n", hr);
1021 hr = IShellWindows_Register(shellwindows, NULL, 0, SWC_EXPLORER, &cookie);
1022 todo_wine
1023 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1025 hr = IShellWindows_Register(shellwindows, (IDispatch*)shellwindows, 0, SWC_EXPLORER, &cookie);
1026 todo_wine
1027 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1029 hr = IShellWindows_Register(shellwindows, (IDispatch*)shellwindows, 0, SWC_EXPLORER, &cookie);
1030 todo_wine
1031 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1033 hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP,
1034 0, 0, 50, 14, 0, 0, 0, NULL);
1035 ok(hwnd != NULL, "got %p, error %d\n", hwnd, GetLastError());
1037 cookie = 0;
1038 hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_EXPLORER, &cookie);
1039 todo_wine {
1040 ok(hr == S_OK, "got 0x%08x\n", hr);
1041 ok(cookie != 0, "got %d\n", cookie);
1043 cookie2 = 0;
1044 hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_EXPLORER, &cookie2);
1045 todo_wine {
1046 ok(hr == S_OK, "got 0x%08x\n", hr);
1047 ok(cookie2 != 0 && cookie2 != cookie, "got %d\n", cookie2);
1049 hr = IShellWindows_Revoke(shellwindows, cookie);
1050 todo_wine
1051 ok(hr == S_OK, "got 0x%08x\n", hr);
1052 hr = IShellWindows_Revoke(shellwindows, cookie2);
1053 todo_wine
1054 ok(hr == S_OK, "got 0x%08x\n", hr);
1056 hr = IShellWindows_Revoke(shellwindows, 0);
1057 todo_wine
1058 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1060 /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
1061 cookie = 0;
1062 hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_DESKTOP, &cookie);
1063 todo_wine {
1064 ok(hr == S_OK, "got 0x%08x\n", hr);
1065 ok(cookie != 0, "got %d\n", cookie);
1067 disp = (void*)0xdeadbeef;
1068 ret = 0xdead;
1069 VariantInit(&v);
1070 hr = IShellWindows_FindWindowSW(shellwindows, &v, &v, SWC_DESKTOP, &ret, SWFO_NEEDDISPATCH, &disp);
1071 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
1072 if (hr == S_FALSE) /* winxp and earlier */ {
1073 win_skip("SWC_DESKTOP is not supported, some tests will be skipped.\n");
1074 /* older versions allowed to register SWC_DESKTOP and access it with FindWindowSW */
1075 ok(disp == NULL, "got %p\n", disp);
1076 ok(ret == 0, "got %d\n", ret);
1078 else {
1079 static const IID *browser_riids[] = {
1080 &IID_IWebBrowser2,
1081 &IID_NULL
1084 static const IID *viewdual_riids[] = {
1085 &IID_IShellFolderViewDual3,
1086 &IID_NULL
1089 IShellFolderViewDual *view;
1090 IShellBrowser *sb, *sb2;
1091 IServiceProvider *sp;
1092 IDispatch *doc, *app;
1093 IWebBrowser2 *wb;
1094 IShellView *sv;
1095 IUnknown *unk;
1097 ok(disp != NULL, "got %p\n", disp);
1099 if (disp == NULL) goto skip_disp_tests;
1101 ok(ret != HandleToUlong(hwnd), "got %d\n", ret);
1103 /* IDispatch-related tests */
1104 test_dispatch_typeinfo(disp, browser_riids);
1106 /* IWebBrowser2 */
1107 hr = IDispatch_QueryInterface(disp, &IID_IWebBrowser2, (void**)&wb);
1108 ok(hr == S_OK, "got 0x%08x\n", hr);
1110 hr = IWebBrowser2_Refresh(wb);
1111 todo_wine
1112 ok(hr == S_OK, "got 0x%08x\n", hr);
1114 hr = IWebBrowser2_get_Application(wb, &app);
1115 ok(hr == S_OK, "got 0x%08x\n", hr);
1116 ok(disp == app, "got %p, %p\n", app, disp);
1117 IDispatch_Release(app);
1119 hr = IWebBrowser2_get_Document(wb, &doc);
1120 todo_wine
1121 ok(hr == S_OK, "got 0x%08x\n", hr);
1122 if (hr == S_OK) {
1123 test_dispatch_typeinfo(doc, viewdual_riids);
1125 IWebBrowser2_Release(wb);
1127 /* IServiceProvider */
1128 hr = IDispatch_QueryInterface(disp, &IID_IShellFolderViewDual, (void**)&view);
1129 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1131 hr = IDispatch_QueryInterface(disp, &IID_IServiceProvider, (void**)&sp);
1132 ok(hr == S_OK, "got 0x%08x\n", hr);
1134 hr = IServiceProvider_QueryService(sp, &SID_STopLevelBrowser, &IID_IShellBrowser, (void**)&sb);
1135 ok(hr == S_OK, "got 0x%08x\n", hr);
1137 hr = IServiceProvider_QueryService(sp, &SID_STopLevelBrowser, &IID_IShellBrowser, (void**)&sb2);
1138 ok(hr == S_OK, "got 0x%08x\n", hr);
1139 ok(sb == sb2, "got %p, %p\n", sb, sb2);
1141 hr = IServiceProvider_QueryService(sp, &SID_STopLevelBrowser, &IID_IOleWindow, (void**)&unk);
1142 ok(hr == S_OK, "got 0x%08x\n", hr);
1143 IUnknown_Release(unk);
1145 hr = IServiceProvider_QueryService(sp, &SID_STopLevelBrowser, &IID_IExplorerBrowser, (void**)&unk);
1146 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1148 hr = IShellBrowser_QueryInterface(sb, &IID_IExplorerBrowser, (void**)&unk);
1149 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1151 hr = IShellBrowser_QueryInterface(sb, &IID_IWebBrowser2, (void**)&unk);
1152 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1154 hr = IShellBrowser_QueryInterface(sb, &IID_IDispatch, (void**)&unk);
1155 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1157 hr = IShellBrowser_QueryActiveShellView(sb, &sv);
1158 ok(hr == S_OK, "got 0x%08x\n", hr);
1159 IShellView_Release(sv);
1161 IShellBrowser_Release(sb2);
1162 IShellBrowser_Release(sb);
1164 hr = IServiceProvider_QueryService(sp, &SID_STopLevelBrowser, &IID_IUnknown, (void**)&unk);
1165 ok(hr == S_OK, "got 0x%08x\n", hr);
1167 hr = IUnknown_QueryInterface(unk, &IID_IShellBrowser, (void**)&sb2);
1168 ok(hr == S_OK, "got 0x%08x\n", hr);
1169 IShellBrowser_Release(sb2);
1170 IUnknown_Release(unk);
1172 hr = IServiceProvider_QueryService(sp, &SID_STopLevelBrowser, &IID_IShellView, (void**)&sv);
1173 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1175 IServiceProvider_Release(sp);
1176 IDispatch_Release(disp);
1178 skip_disp_tests:
1180 disp = (void*)0xdeadbeef;
1181 ret = 0xdead;
1182 VariantInit(&v);
1183 hr = IShellWindows_FindWindowSW(shellwindows, &v, &v, SWC_DESKTOP, &ret, 0, &disp);
1184 ok(hr == S_OK || broken(hr == S_FALSE) /* winxp */, "got 0x%08x\n", hr);
1185 ok(disp == NULL, "got %p\n", disp);
1186 ok(ret != HandleToUlong(hwnd), "got %d\n", ret);
1188 disp = (void*)0xdeadbeef;
1189 ret = 0xdead;
1190 V_VT(&v) = VT_I4;
1191 V_I4(&v) = cookie;
1192 VariantInit(&v2);
1193 hr = IShellWindows_FindWindowSW(shellwindows, &v, &v2, SWC_BROWSER, &ret, SWFO_COOKIEPASSED, &disp);
1194 todo_wine
1195 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1196 ok(disp == NULL, "got %p\n", disp);
1197 ok(ret == 0, "got %d\n", ret);
1199 hr = IShellWindows_Revoke(shellwindows, cookie);
1200 todo_wine
1201 ok(hr == S_OK, "got 0x%08x\n", hr);
1202 DestroyWindow(hwnd);
1203 IShellWindows_Release(shellwindows);
1206 static void test_ParseName(void)
1208 static const WCHAR cadabraW[] = {'c','a','d','a','b','r','a',0};
1209 WCHAR pathW[MAX_PATH];
1210 IShellDispatch *sd;
1211 FolderItem *item;
1212 Folder *folder;
1213 HRESULT hr;
1214 VARIANT v;
1215 BSTR str;
1217 hr = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
1218 &IID_IShellDispatch, (void**)&sd);
1219 ok(hr == S_OK, "got 0x%08x\n", hr);
1221 GetTempPathW(ARRAY_SIZE(pathW), pathW);
1222 V_VT(&v) = VT_BSTR;
1223 V_BSTR(&v) = SysAllocString(pathW);
1224 hr = IShellDispatch_NameSpace(sd, v, &folder);
1225 ok(hr == S_OK, "got 0x%08x\n", hr);
1226 VariantClear(&v);
1228 item = (void*)0xdeadbeef;
1229 hr = Folder_ParseName(folder, NULL, &item);
1230 ok(hr == S_FALSE || broken(hr == E_INVALIDARG) /* win2k */, "got 0x%08x\n", hr);
1231 ok(item == NULL, "got %p\n", item);
1233 /* empty name */
1234 str = SysAllocStringLen(NULL, 0);
1235 item = (void*)0xdeadbeef;
1236 hr = Folder_ParseName(folder, str, &item);
1237 ok(hr == S_FALSE || broken(hr == E_INVALIDARG) /* win2k */, "got 0x%08x\n", hr);
1238 ok(item == NULL, "got %p\n", item);
1239 SysFreeString(str);
1241 /* path doesn't exist */
1242 str = SysAllocString(cadabraW);
1243 item = (void*)0xdeadbeef;
1244 hr = Folder_ParseName(folder, str, &item);
1245 ok(hr == S_FALSE || broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* win2k */,
1246 "got 0x%08x\n", hr);
1247 ok(item == NULL, "got %p\n", item);
1248 SysFreeString(str);
1250 lstrcatW(pathW, cadabraW);
1251 CreateDirectoryW(pathW, NULL);
1253 str = SysAllocString(cadabraW);
1254 item = NULL;
1255 hr = Folder_ParseName(folder, str, &item);
1256 ok(hr == S_OK, "got 0x%08x\n", hr);
1257 ok(item != NULL, "got %p\n", item);
1258 SysFreeString(str);
1260 hr = FolderItem_get_Path(item, &str);
1261 ok(hr == S_OK, "got 0x%08x\n", hr);
1262 ok(str[0] != 0, "path %s\n", wine_dbgstr_w(str));
1263 SysFreeString(str);
1265 RemoveDirectoryW(pathW);
1266 FolderItem_Release(item);
1267 Folder_Release(folder);
1268 IShellDispatch_Release(sd);
1271 static void test_Verbs(void)
1273 FolderItemVerbs *verbs, *verbs2;
1274 WCHAR pathW[MAX_PATH];
1275 FolderItemVerb *verb;
1276 IShellDispatch *sd;
1277 FolderItem *item;
1278 Folder2 *folder2;
1279 IDispatch *disp;
1280 Folder *folder;
1281 HRESULT hr;
1282 LONG count, i;
1283 VARIANT v;
1284 BSTR str;
1286 hr = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
1287 &IID_IShellDispatch, (void**)&sd);
1288 ok(hr == S_OK, "got 0x%08x\n", hr);
1290 GetTempPathW(ARRAY_SIZE(pathW), pathW);
1291 V_VT(&v) = VT_BSTR;
1292 V_BSTR(&v) = SysAllocString(pathW);
1293 hr = IShellDispatch_NameSpace(sd, v, &folder);
1294 ok(hr == S_OK, "got 0x%08x\n", hr);
1295 VariantClear(&v);
1297 hr = Folder_QueryInterface(folder, &IID_Folder2, (void**)&folder2);
1298 ok(hr == S_OK, "got 0x%08x\n", hr);
1299 Folder_Release(folder);
1301 hr = Folder2_get_Self(folder2, &item);
1302 ok(hr == S_OK, "got 0x%08x\n", hr);
1303 Folder2_Release(folder2);
1305 if (0) { /* crashes on some systems */
1306 hr = FolderItem_Verbs(item, NULL);
1307 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1309 hr = FolderItem_Verbs(item, &verbs);
1310 ok(hr == S_OK, "got 0x%08x\n", hr);
1312 hr = FolderItem_Verbs(item, &verbs2);
1313 ok(hr == S_OK, "got 0x%08x\n", hr);
1314 ok(verbs2 != verbs, "Unexpected verbs pointer.\n");
1315 FolderItemVerbs_Release(verbs2);
1317 disp = (void *)0xdeadbeef;
1318 hr = FolderItemVerbs_get_Application(verbs, &disp);
1319 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
1320 ok(disp == NULL, "Unexpected application pointer.\n");
1322 disp = (void *)0xdeadbeef;
1323 hr = FolderItemVerbs_get_Parent(verbs, &disp);
1324 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
1325 ok(disp == NULL, "Unexpected parent pointer %p.\n", disp);
1327 if (0) { /* crashes on winxp/win2k3 */
1328 hr = FolderItemVerbs_get_Count(verbs, NULL);
1329 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1331 count = 0;
1332 hr = FolderItemVerbs_get_Count(verbs, &count);
1333 ok(hr == S_OK, "got 0x%08x\n", hr);
1334 ok(count > 0, "got count %d\n", count);
1336 if (0) { /* crashes on winxp/win2k3 */
1337 V_VT(&v) = VT_I4;
1338 V_I4(&v) = 0;
1339 hr = FolderItemVerbs_Item(verbs, v, NULL);
1340 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1342 /* there's always one item more, so you can access [0,count],
1343 instead of actual [0,count) */
1344 for (i = 0; i <= count; i++) {
1345 V_VT(&v) = VT_I4;
1346 V_I4(&v) = i;
1347 hr = FolderItemVerbs_Item(verbs, v, &verb);
1348 ok(hr == S_OK, "got 0x%08x\n", hr);
1349 hr = FolderItemVerb_get_Name(verb, &str);
1350 ok(hr == S_OK, "got 0x%08x\n", hr);
1351 ok(str != NULL, "%d: name %s\n", i, wine_dbgstr_w(str));
1352 if (i == count)
1353 ok(str[0] == 0, "%d: got terminating item %s\n", i, wine_dbgstr_w(str));
1355 disp = (void *)0xdeadbeef;
1356 hr = FolderItemVerb_get_Parent(verb, &disp);
1357 ok(hr == E_NOTIMPL, "got %#x.\n", hr);
1358 ok(disp == NULL, "Unexpected parent pointer %p.\n", disp);
1360 disp = (void *)0xdeadbeef;
1361 hr = FolderItemVerb_get_Application(verb, &disp);
1362 ok(hr == E_NOTIMPL, "got %#x.\n", hr);
1363 ok(disp == NULL, "Unexpected parent pointer %p.\n", disp);
1365 SysFreeString(str);
1366 FolderItemVerb_Release(verb);
1369 V_VT(&v) = VT_I4;
1370 V_I4(&v) = count+1;
1371 verb = NULL;
1372 hr = FolderItemVerbs_Item(verbs, v, &verb);
1373 ok(hr == S_OK, "got 0x%08x\n", hr);
1374 ok(verb == NULL, "got %p\n", verb);
1376 FolderItemVerbs_Release(verbs);
1377 FolderItem_Release(item);
1378 IShellDispatch_Release(sd);
1381 static void test_ShellExecute(void)
1383 HRESULT hr;
1384 IShellDispatch2 *sd;
1385 BSTR name;
1386 VARIANT args, dir, op, show;
1388 static const WCHAR regW[] = {'r','e','g',0};
1390 hr = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
1391 &IID_IShellDispatch2, (void**)&sd);
1392 if (hr != S_OK)
1394 win_skip("IShellDispatch2 not supported\n");
1395 return;
1398 VariantInit(&args);
1399 VariantInit(&dir);
1400 VariantInit(&op);
1401 VariantInit(&show);
1403 V_VT(&show) = VT_I4;
1404 V_I4(&show) = 0;
1406 name = SysAllocString(regW);
1408 hr = IShellDispatch2_ShellExecute(sd, name, args, dir, op, show);
1409 ok(hr == S_OK, "ShellExecute failed: %08x\n", hr);
1411 /* test invalid value for show */
1412 V_VT(&show) = VT_BSTR;
1413 V_BSTR(&show) = name;
1415 hr = IShellDispatch2_ShellExecute(sd, name, args, dir, op, show);
1416 ok(hr == S_OK, "ShellExecute failed: %08x\n", hr);
1418 SysFreeString(name);
1419 IShellDispatch2_Release(sd);
1422 START_TEST(shelldispatch)
1424 HRESULT r;
1426 r = CoInitialize(NULL);
1427 ok(SUCCEEDED(r), "CoInitialize failed: %08x\n", r);
1428 if (FAILED(r))
1429 return;
1431 init_function_pointers();
1432 test_namespace();
1433 test_items();
1434 test_service();
1435 test_ShellFolderViewDual();
1436 test_ShellWindows();
1437 test_ParseName();
1438 test_Verbs();
1439 test_ShellExecute();
1441 CoUninitialize();