shell32/tests: Enable compilation with long types.
[wine.git] / dlls / shell32 / tests / shlfolder.c
blob7b81ef981105342450b839c13a70891586de75e9
1 /*
2 * Unit test of the IShellFolder functions.
4 * Copyright 2004 Vitaliy Margolen
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 #include <stdarg.h>
22 #include <stdio.h>
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wtypes.h"
30 #include "shellapi.h"
33 #include "shlguid.h"
34 #include "shlobj.h"
35 #include "shobjidl.h"
36 #include "shlwapi.h"
37 #include "ocidl.h"
38 #include "oleauto.h"
40 #include "wine/heap.h"
41 #include "wine/test.h"
43 #include <initguid.h>
44 DEFINE_GUID(IID_IParentAndItem, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
45 DEFINE_GUID(CLSID_ShellDocObjView, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
47 static HRESULT (WINAPI *pSHCreateItemFromIDList)(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv);
48 static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**);
49 static HRESULT (WINAPI *pSHCreateItemFromRelativeName)(IShellItem*,PCWSTR,IBindCtx*,REFIID,void**);
50 static HRESULT (WINAPI *pSHCreateItemInKnownFolder)(REFKNOWNFOLDERID,DWORD,PCWSTR,REFIID,void **);
51 static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
52 static HRESULT (WINAPI *pSHCreateShellItemArray)(LPCITEMIDLIST,IShellFolder*,UINT,LPCITEMIDLIST*,IShellItemArray**);
53 static HRESULT (WINAPI *pSHCreateShellItemArrayFromIDLists)(UINT, PCIDLIST_ABSOLUTE*, IShellItemArray**);
54 static HRESULT (WINAPI *pSHCreateShellItemArrayFromDataObject)(IDataObject*, REFIID, void **);
55 static HRESULT (WINAPI *pSHCreateShellItemArrayFromShellItem)(IShellItem*, REFIID, void **);
56 static HRESULT (WINAPI *pSHGetKnownFolderPath)(REFKNOWNFOLDERID,DWORD,HANDLE,PWSTR*);
57 static HRESULT (WINAPI *pSHGetNameFromIDList)(PCIDLIST_ABSOLUTE,SIGDN,PWSTR*);
58 static HRESULT (WINAPI *pSHGetItemFromDataObject)(IDataObject*,DATAOBJ_GET_ITEM_FLAGS,REFIID,void**);
59 static HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*);
60 static HRESULT (WINAPI *pSHGetItemFromObject)(IUnknown*,REFIID,void**);
61 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
62 static HRESULT (WINAPI *pSHCreateDefaultContextMenu)(const DEFCONTEXTMENU*,REFIID,void**);
63 static BOOL (WINAPI *pSHGetPathFromIDListEx)(PCIDLIST_ABSOLUTE,WCHAR*,DWORD,GPFIDL_FLAGS);
64 static HRESULT (WINAPI *pSHGetSetFolderCustomSettings)(LPSHFOLDERCUSTOMSETTINGS,PCWSTR,DWORD);
66 static WCHAR *make_wstr(const char *str)
68 WCHAR *ret;
69 int len;
71 if (!str || !str[0])
72 return NULL;
74 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
75 if(!len || len < 0)
76 return NULL;
78 ret = heap_alloc(len * sizeof(WCHAR));
79 if(!ret)
80 return NULL;
82 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
83 return ret;
86 static void init_function_pointers(void)
88 HMODULE hmod;
89 void *ptr;
91 hmod = GetModuleHandleA("shell32.dll");
93 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
94 MAKEFUNC(SHCreateItemFromIDList);
95 MAKEFUNC(SHCreateItemFromParsingName);
96 MAKEFUNC(SHCreateItemFromRelativeName);
97 MAKEFUNC(SHCreateItemInKnownFolder);
98 MAKEFUNC(SHCreateShellItem);
99 MAKEFUNC(SHCreateShellItemArray);
100 MAKEFUNC(SHCreateShellItemArrayFromIDLists);
101 MAKEFUNC(SHCreateShellItemArrayFromDataObject);
102 MAKEFUNC(SHCreateShellItemArrayFromShellItem);
103 MAKEFUNC(SHGetKnownFolderPath);
104 MAKEFUNC(SHGetNameFromIDList);
105 MAKEFUNC(SHGetItemFromDataObject);
106 MAKEFUNC(SHGetIDListFromObject);
107 MAKEFUNC(SHGetItemFromObject);
108 MAKEFUNC(SHCreateDefaultContextMenu);
109 MAKEFUNC(SHGetPathFromIDListEx);
110 MAKEFUNC(SHGetSetFolderCustomSettings);
111 #undef MAKEFUNC
113 /* test named exports */
114 ptr = GetProcAddress(hmod, "ILFree");
115 ok(broken(ptr == 0) || ptr != 0, "expected named export for ILFree\n");
116 if (ptr)
118 #define TESTNAMED(f) \
119 ptr = (void*)GetProcAddress(hmod, #f); \
120 ok(ptr != 0, "expected named export for " #f "\n");
122 TESTNAMED(ILAppendID);
123 TESTNAMED(ILClone);
124 TESTNAMED(ILCloneFirst);
125 TESTNAMED(ILCombine);
126 TESTNAMED(ILCreateFromPath);
127 TESTNAMED(ILCreateFromPathA);
128 TESTNAMED(ILCreateFromPathW);
129 TESTNAMED(ILFindChild);
130 TESTNAMED(ILFindLastID);
131 TESTNAMED(ILGetNext);
132 TESTNAMED(ILGetSize);
133 TESTNAMED(ILIsEqual);
134 TESTNAMED(ILIsParent);
135 TESTNAMED(ILRemoveLastID);
136 TESTNAMED(ILSaveToStream);
137 #undef TESTNAMED
140 hmod = GetModuleHandleA("kernel32.dll");
141 pIsWow64Process = (void*)GetProcAddress(hmod, "IsWow64Process");
144 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
145 static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
147 size_t iLen;
149 if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
150 return NULL;
152 if (iLen)
154 lpszPath += iLen;
155 if (lpszPath[-1] != '\\')
157 *lpszPath++ = '\\';
158 *lpszPath = '\0';
161 return lpszPath;
164 static struct
166 WCHAR path[MAX_PATH];
167 HRESULT hr;
168 int todo;
169 } parse_tests[] = {
170 {{'c',':','\\',0}, S_OK},
171 {{'c',':','\\','\\',0}, E_INVALIDARG, 1},
172 {{'c',':','\\','f','a','k','e',0}, 0x80070002}, /* ERROR_FILE_NOT_FOUND */
173 {{'c',':','f','a','k','e',0}, E_INVALIDARG, 1},
174 {{'c',':','/',0}, E_INVALIDARG, 1},
175 {{'c',':','\\','w','i','n','d','o','w','s',0}, S_OK},
176 {{'c',':','\\','w','i','n','d','o','w','s','\\',0}, S_OK},
177 {{'c',':','\\','w','i','n','d','o','w','s','\\','.',0}, E_INVALIDARG, 1},
178 {{'c',':','\\','w','i','n','d','o','w','s','\\','.','.',0}, E_INVALIDARG, 1},
179 {{'.',0}, E_INVALIDARG, 1},
180 {{'.','.',0}, E_INVALIDARG, 1},
181 {{'t','e','s','t',0}, 0x80070002},
182 {{'t','e','s','t','\\',0}, 0x80070002},
183 {{'s','u','b','\\','d','i','r',0}, 0x80070002},
184 {{'s','u','b','/','d','i','r',0}, E_INVALIDARG, 1},
185 {{'h','t','t','p',':',0}, S_OK, 1},
186 {{'h','t','t','p',':','t','e','s','t',0}, S_OK, 1},
187 {{'h','t','t','p',':','\\','t','e','s','t',0}, S_OK, 1},
188 {{'x','x',':',0}, S_OK, 1},
191 static void test_ParseDisplayName(void)
193 static WCHAR testdirW[] = {'p','a','r','s','e','t','e','s','t',0};
194 static WCHAR backslashW[] = {'\\',0};
195 WCHAR buffer[MAX_PATH], buffer2[MAX_PATH];
196 IShellFolder *desktop;
197 ITEMIDLIST *pidl;
198 HRESULT hr;
199 BOOL bRes;
200 int i;
202 hr = SHGetDesktopFolder(&desktop);
203 ok(hr == S_OK, "Expected SHGetDesktopFolder to return S_OK, got 0x%08lx\n", hr);
205 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, NULL, NULL, &pidl, NULL);
206 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
208 for (i = 0; i < ARRAY_SIZE(parse_tests); i++)
210 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, parse_tests[i].path, NULL, &pidl, NULL);
211 todo_wine_if(parse_tests[i].todo)
212 ok(hr == parse_tests[i].hr, "%s: expected %#lx, got %#lx\n",
213 wine_dbgstr_w(parse_tests[i].path), parse_tests[i].hr, hr);
214 if (SUCCEEDED(hr))
215 CoTaskMemFree(pidl);
218 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
219 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
220 * out it doesn't. The magic seems to happen in the file dialogs, then. */
222 bRes = SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, FALSE);
223 ok(bRes, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %lu\n", GetLastError());
225 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, buffer, NULL, &pidl, 0);
226 ok(hr == S_OK, "DesktopFolder->ParseDisplayName failed. hr = %08lx.\n", hr);
228 ok(ILFindLastID(pidl)->mkid.abID[0] == 0x31,
229 "Last pidl should be of type PT_FOLDER, but is: %02x\n",
230 ILFindLastID(pidl)->mkid.abID[0]);
231 CoTaskMemFree(pidl);
233 /* Relative paths are interpreted relative to the desktop. */
234 GetTempPathW(ARRAY_SIZE(buffer), buffer);
235 GetLongPathNameW(buffer, buffer, ARRAY_SIZE(buffer));
236 SetCurrentDirectoryW(buffer);
237 CreateDirectoryW(testdirW, NULL);
239 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, testdirW, NULL, &pidl, NULL);
240 ok(hr == 0x80070002, "got %#lx\n", hr);
242 RemoveDirectoryW(testdirW);
244 hr = SHGetSpecialFolderPathW(NULL, buffer, CSIDL_DESKTOP, FALSE);
245 ok(hr == S_FALSE, "got %#lx\n", hr);
246 SetCurrentDirectoryW(buffer);
247 CreateDirectoryW(testdirW, NULL);
249 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, testdirW, NULL, &pidl, NULL);
250 ok(hr == S_OK, "got %#lx\n", hr);
252 ok(SHGetPathFromIDListW(pidl, buffer2), "SHGetPathFromIDList failed\n");
253 lstrcatW(buffer, backslashW);
254 lstrcatW(buffer, testdirW);
255 ok(!lstrcmpW(buffer, buffer2), "expected %s, got %s\n", wine_dbgstr_w(buffer), wine_dbgstr_w(buffer2));
257 RemoveDirectoryW(testdirW);
258 CoTaskMemFree(pidl);
260 IShellFolder_Release(desktop);
263 /* creates a file with the specified name for tests */
264 static void CreateTestFile(const CHAR *name)
266 HANDLE file;
267 DWORD written;
269 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
270 if (file != INVALID_HANDLE_VALUE)
272 WriteFile(file, name, strlen(name), &written, NULL);
273 WriteFile(file, "\n", strlen("\n"), &written, NULL);
274 CloseHandle(file);
279 /* initializes the tests */
280 static void CreateFilesFolders(void)
282 CreateDirectoryA(".\\testdir", NULL);
283 CreateDirectoryA(".\\testdir\\test.txt", NULL);
284 CreateTestFile (".\\testdir\\test1.txt ");
285 CreateTestFile (".\\testdir\\test2.txt ");
286 CreateTestFile (".\\testdir\\test3.txt ");
287 CreateDirectoryA(".\\testdir\\testdir2 ", NULL);
288 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL);
291 /* cleans after tests */
292 static void Cleanup(void)
294 DeleteFileA(".\\testdir\\test1.txt");
295 DeleteFileA(".\\testdir\\test2.txt");
296 DeleteFileA(".\\testdir\\test3.txt");
297 RemoveDirectoryA(".\\testdir\\test.txt");
298 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
299 RemoveDirectoryA(".\\testdir\\testdir2");
300 RemoveDirectoryA(".\\testdir");
304 /* perform test */
305 static void test_EnumObjects(IShellFolder *iFolder)
307 IEnumIDList *iEnumList;
308 LPITEMIDLIST newPIDL, idlArr[10];
309 ULONG NumPIDLs;
310 int i=0, j;
311 HRESULT hr;
313 static const WORD iResults [5][5] =
315 { 0,-1,-1,-1,-1},
316 { 1, 0,-1,-1,-1},
317 { 1, 1, 0,-1,-1},
318 { 1, 1, 1, 0,-1},
319 { 1, 1, 1, 1, 0}
322 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
323 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
324 static const ULONG attrs[5] =
326 SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR,
327 SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR,
328 SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY | SFGAO_FILESYSTEM,
329 SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY | SFGAO_FILESYSTEM,
330 SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY | SFGAO_FILESYSTEM,
332 static const ULONG full_attrs[5] =
334 SFGAO_CAPABILITYMASK | SFGAO_STORAGE | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR,
335 SFGAO_CAPABILITYMASK | SFGAO_STORAGE | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR,
336 SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM,
337 SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM,
338 SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM,
341 hr = IShellFolder_EnumObjects(iFolder, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &iEnumList);
342 ok(hr == S_OK, "EnumObjects failed %08lx\n", hr);
344 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
345 * the filesystem shellfolders return S_OK even if less than 'celt' items are
346 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
347 * only ever returns a single entry per call. */
348 while (IEnumIDList_Next(iEnumList, 10-i, &idlArr[i], &NumPIDLs) == S_OK)
349 i += NumPIDLs;
350 ok (i == 5, "i: %d\n", i);
352 hr = IEnumIDList_Release(iEnumList);
353 ok(hr == S_OK, "IEnumIDList_Release failed %08lx\n", hr);
355 /* Sort them first in case of wrong order from system */
356 for (i=0;i<5;i++) for (j=0;j<5;j++)
357 if ((SHORT)IShellFolder_CompareIDs(iFolder, 0, idlArr[i], idlArr[j]) < 0)
359 newPIDL = idlArr[i];
360 idlArr[i] = idlArr[j];
361 idlArr[j] = newPIDL;
364 for (i=0;i<5;i++) for (j=0;j<5;j++)
366 hr = IShellFolder_CompareIDs(iFolder, 0, idlArr[i], idlArr[j]);
367 ok(hr == iResults[i][j], "Got %lx expected [%d]-[%d]=%x\n", hr, i, j, iResults[i][j]);
370 for (i = 0; i < ARRAY_SIZE(attrs); ++i)
372 SFGAOF flags;
374 flags = SFGAO_CANCOPY;
375 hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags);
376 flags &= SFGAO_testfor;
377 ok(hr == S_OK, "Failed to get item attributes, hr %#lx.\n", hr);
378 ok((flags & attrs[i]) == attrs[i], "%i: unexpected attributes got %#lx, expected %#lx.\n", i, flags, attrs[i]);
380 flags = SFGAO_testfor;
381 hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags);
382 flags &= SFGAO_testfor;
383 ok(hr == S_OK, "Failed to get item attributes, hr %#lx.\n", hr);
384 ok(flags == (attrs[i] | SFGAO_CAPABILITYMASK), "%i: unexpected attributes got %#lx, expected %#lx.\n",
385 i, flags, attrs[i]);
387 flags = ~0u;
388 hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags);
389 ok(hr == S_OK, "Failed to get item attributes, hr %#lx.\n", hr);
390 ok((flags & ~(SFGAO_HASSUBFOLDER|SFGAO_COMPRESSED)) == full_attrs[i], "%d: unexpected attributes %#lx, expected %#lx\n",
391 i, flags, full_attrs[i]);
394 for (i=0;i<5;i++)
395 ILFree(idlArr[i]);
398 static void test_BindToObject(void)
400 HRESULT hr;
401 UINT cChars;
402 IShellFolder *psfDesktop, *psfChild, *psfMyComputer, *psfSystemDir;
403 SHITEMID emptyitem = { 0, { 0 } };
404 LPITEMIDLIST pidlMyComputer, pidlSystemDir, pidl, pidlEmpty = (LPITEMIDLIST)&emptyitem;
405 WCHAR wszSystemDir[MAX_PATH];
406 char szSystemDir[MAX_PATH];
407 char buf[MAX_PATH];
408 WCHAR path[MAX_PATH];
409 CHAR pathA[MAX_PATH];
410 HANDLE hfile;
411 WCHAR wszMyComputer[] = {
412 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
413 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
414 static const CHAR filename_html[] = "winetest.html";
415 static const CHAR filename_txt[] = "winetest.txt";
416 static const CHAR filename_foo[] = "winetest.foo";
418 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
419 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
421 hr = SHGetDesktopFolder(&psfDesktop);
422 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08lx\n", hr);
423 if (hr != S_OK) return;
425 hr = IShellFolder_BindToObject(psfDesktop, pidlEmpty, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
426 ok (hr == E_INVALIDARG, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08lx\n", hr);
428 hr = IShellFolder_BindToObject(psfDesktop, NULL, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
429 ok (hr == E_INVALIDARG, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08lx\n", hr);
431 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL);
432 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08lx\n", hr);
433 if (hr != S_OK) {
434 IShellFolder_Release(psfDesktop);
435 return;
438 hr = IShellFolder_BindToObject(psfDesktop, pidlMyComputer, NULL, &IID_IShellFolder, (LPVOID*)&psfMyComputer);
439 ok (hr == S_OK, "Desktop failed to bind to MyComputer object! hr = %08lx\n", hr);
440 IShellFolder_Release(psfDesktop);
441 ILFree(pidlMyComputer);
442 if (hr != S_OK) return;
444 hr = IShellFolder_BindToObject(psfMyComputer, pidlEmpty, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
445 ok (hr == E_INVALIDARG, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08lx\n", hr);
447 hr = IShellFolder_BindToObject(psfMyComputer, NULL, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
448 ok (hr == E_INVALIDARG, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08lx\n", hr);
450 cChars = GetSystemDirectoryA(szSystemDir, MAX_PATH);
451 ok (cChars > 0 && cChars < MAX_PATH, "GetSystemDirectoryA failed! LastError: %lu\n", GetLastError());
452 if (cChars == 0 || cChars >= MAX_PATH) {
453 IShellFolder_Release(psfMyComputer);
454 return;
456 MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wszSystemDir, MAX_PATH);
458 hr = IShellFolder_ParseDisplayName(psfMyComputer, NULL, NULL, wszSystemDir, NULL, &pidlSystemDir, NULL);
459 ok (hr == S_OK, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08lx\n", hr);
460 if (hr != S_OK) {
461 IShellFolder_Release(psfMyComputer);
462 return;
465 hr = IShellFolder_BindToObject(psfMyComputer, pidlSystemDir, NULL, &IID_IShellFolder, (LPVOID*)&psfSystemDir);
466 ok (hr == S_OK, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08lx\n", hr);
467 IShellFolder_Release(psfMyComputer);
468 ILFree(pidlSystemDir);
469 if (hr != S_OK) return;
471 hr = IShellFolder_BindToObject(psfSystemDir, pidlEmpty, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
472 ok (hr == E_INVALIDARG,
473 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08lx\n", hr);
475 hr = IShellFolder_BindToObject(psfSystemDir, NULL, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
476 ok (hr == E_INVALIDARG,
477 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08lx\n", hr);
479 IShellFolder_Release(psfSystemDir);
481 cChars = GetCurrentDirectoryA(MAX_PATH, buf);
482 if(!cChars)
484 skip("Failed to get current directory, skipping tests.\n");
485 return;
487 if(buf[cChars-1] != '\\') lstrcatA(buf, "\\");
489 SHGetDesktopFolder(&psfDesktop);
491 /* Attempt BindToObject on files. */
493 /* .html */
494 lstrcpyA(pathA, buf);
495 lstrcatA(pathA, filename_html);
496 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
497 if(hfile != INVALID_HANDLE_VALUE)
499 CloseHandle(hfile);
500 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
501 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
502 ok(hr == S_OK, "Got 0x%08lx\n", hr);
503 if(SUCCEEDED(hr))
505 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
506 ok(hr == S_OK ||
507 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */
508 "Got 0x%08lx\n", hr);
509 if(SUCCEEDED(hr))
511 IPersist *pp;
512 hr = IShellFolder_QueryInterface(psfChild, &IID_IPersist, (void**)&pp);
513 ok(hr == S_OK, "Got 0x%08lx\n", hr);
514 if(SUCCEEDED(hr))
516 CLSID id;
517 hr = IPersist_GetClassID(pp, &id);
518 ok(hr == S_OK, "Got 0x%08lx\n", hr);
519 ok(IsEqualIID(&id, &CLSID_ShellDocObjView), "Unexpected classid %s\n", wine_dbgstr_guid(&id));
520 IPersist_Release(pp);
523 IShellFolder_Release(psfChild);
525 ILFree(pidl);
527 DeleteFileA(pathA);
529 else
530 win_skip("Failed to create .html testfile.\n");
532 /* .txt */
533 lstrcpyA(pathA, buf);
534 lstrcatA(pathA, filename_txt);
535 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
536 if(hfile != INVALID_HANDLE_VALUE)
538 CloseHandle(hfile);
539 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
540 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
541 ok(hr == S_OK, "Got 0x%08lx\n", hr);
542 if(SUCCEEDED(hr))
544 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
545 ok(hr == E_FAIL || /* Vista+ */
546 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */
547 "Got 0x%08lx\n", hr);
548 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
549 ILFree(pidl);
551 DeleteFileA(pathA);
553 else
554 win_skip("Failed to create .txt testfile.\n");
556 /* .foo */
557 lstrcpyA(pathA, buf);
558 lstrcatA(pathA, filename_foo);
559 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
560 if(hfile != INVALID_HANDLE_VALUE)
562 CloseHandle(hfile);
563 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
564 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
565 ok(hr == S_OK, "Got 0x%08lx\n", hr);
566 if(SUCCEEDED(hr))
568 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
569 ok(hr == E_FAIL || /* Vista+ */
570 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */
571 "Got 0x%08lx\n", hr);
572 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
573 ILFree(pidl);
575 DeleteFileA(pathA);
577 else
578 win_skip("Failed to create .foo testfile.\n");
580 /* And on the desktop */
581 SHGetSpecialFolderPathA(NULL, pathA, CSIDL_DESKTOP, FALSE);
582 lstrcatA(pathA, "\\");
583 lstrcatA(pathA, filename_html);
584 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
586 CloseHandle(hfile);
587 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
588 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
589 ok(hr == S_OK, "Got 0x%08lx\n", hr);
591 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void **)&psfChild);
592 ok(hr == S_OK ||
593 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */
594 "Got 0x%08lx\n", hr);
595 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
596 ILFree(pidl);
597 if(!DeleteFileA(pathA))
598 trace("Failed to delete: %ld\n", GetLastError());
600 SHGetSpecialFolderPathA(NULL, pathA, CSIDL_DESKTOP, FALSE);
601 lstrcatA(pathA, "\\");
602 lstrcatA(pathA, filename_foo);
603 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
605 CloseHandle(hfile);
606 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
607 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
608 ok(hr == S_OK, "Got 0x%08lx\n", hr);
610 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void **)&psfChild);
611 ok(hr == E_FAIL || /* Vista+ */
612 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */
613 "Got 0x%08lx\n", hr);
614 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
615 ILFree(pidl);
616 DeleteFileA(pathA);
618 IShellFolder_Release(psfDesktop);
621 static void test_GetDisplayName(void)
623 BOOL result;
624 HRESULT hr;
625 HANDLE hTestFile;
626 WCHAR wszTestFile[MAX_PATH], wszTestFile2[MAX_PATH];
627 char szTestFile[MAX_PATH], szTestDir[MAX_PATH];
628 DWORD attr;
629 STRRET strret;
630 LPSHELLFOLDER psfDesktop, psfPersonal;
631 IUnknown *psfFile;
632 SHITEMID emptyitem = { 0, { 0 } };
633 LPITEMIDLIST pidlTestFile, pidlEmpty = (LPITEMIDLIST)&emptyitem;
634 LPCITEMIDLIST pidlLast;
635 static const CHAR szFileName[] = "winetest.foo";
636 static const WCHAR wszFileName[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
637 static const WCHAR wszDirName[] = { 'w','i','n','e','t','e','s','t',0 };
639 /* It's ok to use this fixed path. Call will fail anyway. */
640 WCHAR wszAbsoluteFilename[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
641 LPITEMIDLIST pidlNew;
643 /* I'm trying to figure if there is a functional difference between calling
644 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
645 * binding to the shellfolder. One thing I thought of was that perhaps
646 * SHGetPathFromIDListW would be able to get the path to a file, which does
647 * not exist anymore, while the other method wouldn't. It turns out there's
648 * no functional difference in this respect.
651 /* First creating a directory in MyDocuments and a file in this directory. */
652 result = SHGetSpecialFolderPathA(NULL, szTestDir, CSIDL_PERSONAL, FALSE);
653 ok(result, "SHGetSpecialFolderPathA failed! Last error: %lu\n", GetLastError());
654 if (!result) return;
656 /* Use ANSI file functions so this works on Windows 9x */
657 lstrcatA(szTestDir, "\\winetest");
658 CreateDirectoryA(szTestDir, NULL);
659 attr=GetFileAttributesA(szTestDir);
660 if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY))
662 ok(0, "unable to create the '%s' directory\n", szTestDir);
663 return;
666 lstrcpyA(szTestFile, szTestDir);
667 lstrcatA(szTestFile, "\\");
668 lstrcatA(szTestFile, szFileName);
669 hTestFile = CreateFileA(szTestFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
670 ok((hTestFile != INVALID_HANDLE_VALUE), "CreateFileA failed! Last error: %lu\n", GetLastError());
671 if (hTestFile == INVALID_HANDLE_VALUE) return;
672 CloseHandle(hTestFile);
674 /* Getting an itemidlist for the file. */
675 hr = SHGetDesktopFolder(&psfDesktop);
676 ok(hr == S_OK, "SHGetDesktopFolder failed! hr = %08lx\n", hr);
677 if (hr != S_OK) return;
679 MultiByteToWideChar(CP_ACP, 0, szTestFile, -1, wszTestFile, MAX_PATH);
681 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszTestFile, NULL, &pidlTestFile, NULL);
682 ok(hr == S_OK, "Desktop->ParseDisplayName failed! hr = %08lx\n", hr);
683 if (hr != S_OK) {
684 IShellFolder_Release(psfDesktop);
685 return;
688 pidlLast = ILFindLastID(pidlTestFile);
689 ok(pidlLast->mkid.cb >= 76, "Expected pidl length of at least 76, got %d.\n", pidlLast->mkid.cb);
690 if (pidlLast->mkid.cb >= 28) {
691 ok(!lstrcmpA((CHAR*)&pidlLast->mkid.abID[12], szFileName),
692 "Filename should be stored as ansi-string at this position!\n");
694 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
695 if (pidlLast->mkid.cb >= 76) {
696 ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName) ||
697 (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)) || /* Vista */
698 (pidlLast->mkid.cb >= 98 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[68], wszFileName)) || /* Win7 */
699 (pidlLast->mkid.cb >= 102 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[72], wszFileName)), /* Win8 */
700 "Filename should be stored as wchar-string at this position!\n");
703 /* It seems as if we cannot bind to regular files on windows, but only directories.
705 hr = IShellFolder_BindToObject(psfDesktop, pidlTestFile, NULL, &IID_IUnknown, (VOID**)&psfFile);
706 ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
707 hr == E_NOTIMPL, /* Vista */
708 "hr = %08lx\n", hr);
709 if (hr == S_OK) {
710 IUnknown_Release(psfFile);
713 /* Some tests for IShellFolder::SetNameOf */
714 hr = SHBindToParent(pidlTestFile, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast);
715 ok(hr == S_OK, "SHBindToParent failed! hr = %08lx\n", hr);
717 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
718 hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlLast, wszDirName, SHGDN_NORMAL, &pidlNew);
719 ok (hr == S_OK, "SetNameOf failed! hr = %08lx\n", hr);
721 ok (((ITEMIDLIST *)((BYTE *)pidlNew + pidlNew->mkid.cb))->mkid.cb == 0,
722 "pidl returned from SetNameOf should be simple!\n");
724 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
725 * is implemented on top of SHFileOperation in WinXP. */
726 hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename, SHGDN_FORPARSING, NULL);
727 ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08lx\n", hr);
729 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
730 * SHGDN flags specify an absolute path. */
731 hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL);
732 ok (hr == S_OK, "SetNameOf failed! hr = %08lx\n", hr);
734 ILFree(pidlNew);
735 IShellFolder_Release(psfPersonal);
737 /* Deleting the file and the directory */
738 DeleteFileA(szTestFile);
739 RemoveDirectoryA(szTestDir);
741 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
742 result = SHGetPathFromIDListW(pidlTestFile, wszTestFile2);
743 ok (result, "SHGetPathFromIDListW failed! Last error: %lu\n", GetLastError());
744 ok (!lstrcmpiW(wszTestFile, wszTestFile2), "SHGetPathFromIDListW returns incorrect path!\n");
746 /* SHBindToParent fails, if called with a NULL PIDL. */
747 hr = SHBindToParent(NULL, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast);
748 ok (hr == E_INVALIDARG || broken(hr == E_OUTOFMEMORY) /* XP */,
749 "SHBindToParent(NULL) should fail! hr = %08lx\n", hr);
751 /* But it succeeds with an empty PIDL. */
752 hr = SHBindToParent(pidlEmpty, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast);
753 ok (hr == S_OK, "SHBindToParent(empty PIDL) should succeed! hr = %08lx\n", hr);
754 ok (pidlLast == pidlEmpty, "The last element of an empty PIDL should be the PIDL itself!\n");
755 if (hr == S_OK)
756 IShellFolder_Release(psfPersonal);
758 /* Binding to the folder and querying the display name of the file also works. */
759 hr = SHBindToParent(pidlTestFile, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast);
760 ok (hr == S_OK, "SHBindToParent failed! hr = %08lx\n", hr);
761 if (hr != S_OK) {
762 IShellFolder_Release(psfDesktop);
763 return;
766 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
767 * pidlTestFile (In accordance with MSDN). */
768 ok (ILFindLastID(pidlTestFile) == pidlLast,
769 "SHBindToParent doesn't return the last id of the pidl param!\n");
771 hr = IShellFolder_GetDisplayNameOf(psfPersonal, pidlLast, SHGDN_FORPARSING, &strret);
772 ok (hr == S_OK, "Personal->GetDisplayNameOf failed! hr = %08lx\n", hr);
773 if (hr != S_OK) {
774 IShellFolder_Release(psfDesktop);
775 IShellFolder_Release(psfPersonal);
776 return;
779 hr = StrRetToBufW(&strret, pidlLast, wszTestFile2, MAX_PATH);
780 ok (hr == S_OK, "StrRetToBufW failed! hr = %08lx\n", hr);
781 ok (!lstrcmpiW(wszTestFile, wszTestFile2), "GetDisplayNameOf returns incorrect path!\n");
783 ILFree(pidlTestFile);
784 IShellFolder_Release(psfDesktop);
785 IShellFolder_Release(psfPersonal);
788 static void test_CallForAttributes(void)
790 HKEY hKey;
791 LONG lResult;
792 HRESULT hr;
793 DWORD dwSize;
794 LPSHELLFOLDER psfDesktop;
795 LPITEMIDLIST pidlMyDocuments;
796 DWORD dwAttributes, dwCallForAttributes, dwOrigAttributes, dwOrigCallForAttributes;
797 static const WCHAR wszAttributes[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
798 static const WCHAR wszCallForAttributes[] = {
799 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
800 static const WCHAR wszMyDocumentsKey[] = {
801 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
802 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
803 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
804 WCHAR wszMyDocuments[] = {
805 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
806 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
808 /* For the root of a namespace extension, the attributes are not queried by binding
809 * to the object and calling GetAttributesOf. Instead, the attributes are read from
810 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
812 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
813 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
814 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
815 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
817 hr = SHGetDesktopFolder(&psfDesktop);
818 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08lx\n", hr);
819 if (hr != S_OK) return;
821 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyDocuments, NULL,
822 &pidlMyDocuments, NULL);
823 ok (hr == S_OK,
824 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08lx\n", hr);
825 if (hr != S_OK) {
826 IShellFolder_Release(psfDesktop);
827 return;
830 dwAttributes = 0xffffffff;
831 hr = IShellFolder_GetAttributesOf(psfDesktop, 1,
832 (LPCITEMIDLIST*)&pidlMyDocuments, &dwAttributes);
833 ok (hr == S_OK, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08lx\n", hr);
835 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
836 ok (dwAttributes & SFGAO_FILESYSTEM, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
837 ok (!(dwAttributes & SFGAO_ISSLOW), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
838 ok (!(dwAttributes & SFGAO_GHOSTED), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
840 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
841 * key. So the test will return at this point, if run on wine.
843 lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszMyDocumentsKey, 0, KEY_WRITE|KEY_READ, &hKey);
844 ok (lResult == ERROR_SUCCESS ||
845 lResult == ERROR_ACCESS_DENIED,
846 "RegOpenKeyEx failed! result: %08lx\n", lResult);
847 if (lResult != ERROR_SUCCESS) {
848 if (lResult == ERROR_ACCESS_DENIED)
849 skip("Not enough rights to open the registry key\n");
850 ILFree(pidlMyDocuments);
851 IShellFolder_Release(psfDesktop);
852 return;
855 /* Query MyDocuments' Attributes value, to be able to restore it later. */
856 dwSize = sizeof(DWORD);
857 lResult = RegQueryValueExW(hKey, wszAttributes, NULL, NULL, (LPBYTE)&dwOrigAttributes, &dwSize);
858 ok (lResult == ERROR_SUCCESS, "RegQueryValueEx failed! result: %08lx\n", lResult);
859 if (lResult != ERROR_SUCCESS) {
860 RegCloseKey(hKey);
861 ILFree(pidlMyDocuments);
862 IShellFolder_Release(psfDesktop);
863 return;
866 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
867 dwSize = sizeof(DWORD);
868 lResult = RegQueryValueExW(hKey, wszCallForAttributes, NULL, NULL,
869 (LPBYTE)&dwOrigCallForAttributes, &dwSize);
870 ok (lResult == ERROR_SUCCESS, "RegQueryValueEx failed! result: %08lx\n", lResult);
871 if (lResult != ERROR_SUCCESS) {
872 RegCloseKey(hKey);
873 ILFree(pidlMyDocuments);
874 IShellFolder_Release(psfDesktop);
875 return;
878 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
879 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
880 * SFGAO_FILESYSTEM attributes. */
881 dwAttributes = SFGAO_ISSLOW|SFGAO_GHOSTED;
882 RegSetValueExW(hKey, wszAttributes, 0, REG_DWORD, (LPBYTE)&dwAttributes, sizeof(DWORD));
883 dwCallForAttributes = SFGAO_ISSLOW|SFGAO_FILESYSTEM;
884 RegSetValueExW(hKey, wszCallForAttributes, 0, REG_DWORD,
885 (LPBYTE)&dwCallForAttributes, sizeof(DWORD));
887 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
888 * GetAttributesOf. It seems that once there is a single attribute queried, for which
889 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
890 * the flags in Attributes are ignored.
892 dwAttributes = SFGAO_ISSLOW|SFGAO_GHOSTED|SFGAO_FILESYSTEM;
893 hr = IShellFolder_GetAttributesOf(psfDesktop, 1,
894 (LPCITEMIDLIST*)&pidlMyDocuments, &dwAttributes);
895 ok (hr == S_OK, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08lx\n", hr);
896 if (hr == S_OK)
897 ok (dwAttributes == SFGAO_FILESYSTEM,
898 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08lx\n",
899 dwAttributes);
901 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
902 RegSetValueExW(hKey, wszAttributes, 0, REG_DWORD, (LPBYTE)&dwOrigAttributes, sizeof(DWORD));
903 RegSetValueExW(hKey, wszCallForAttributes, 0, REG_DWORD,
904 (LPBYTE)&dwOrigCallForAttributes, sizeof(DWORD));
905 RegCloseKey(hKey);
906 ILFree(pidlMyDocuments);
907 IShellFolder_Release(psfDesktop);
910 static void test_GetAttributesOf(void)
912 HRESULT hr;
913 LPSHELLFOLDER psfDesktop, psfMyComputer;
914 SHITEMID emptyitem = { 0, { 0 } };
915 LPCITEMIDLIST pidlEmpty = (LPCITEMIDLIST)&emptyitem;
916 LPITEMIDLIST pidlMyComputer;
917 DWORD dwFlags;
918 static const DWORD desktopFlags = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
919 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER;
920 static const DWORD myComputerFlags = SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET |
921 SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
922 WCHAR wszMyComputer[] = {
923 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
924 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
925 char cCurrDirA [MAX_PATH] = {0};
926 WCHAR cCurrDirW [MAX_PATH];
927 static WCHAR cTestDirW[] = {'t','e','s','t','d','i','r',0};
928 IShellFolder *IDesktopFolder, *testIShellFolder;
929 ITEMIDLIST *newPIDL;
930 int len;
932 hr = SHGetDesktopFolder(&psfDesktop);
933 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08lx\n", hr);
934 if (hr != S_OK) return;
936 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
937 dwFlags = 0xffffffff;
938 hr = IShellFolder_GetAttributesOf(psfDesktop, 1, &pidlEmpty, &dwFlags);
939 ok (hr == S_OK, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08lx\n", hr);
940 ok (dwFlags == desktopFlags, "Wrong Desktop attributes: %08lx\n", dwFlags);
942 /* .. or with no itemidlist at all. */
943 dwFlags = 0xffffffff;
944 hr = IShellFolder_GetAttributesOf(psfDesktop, 0, NULL, &dwFlags);
945 ok (hr == S_OK, "Desktop->GetAttributesOf(NULL) failed! hr = %08lx\n", hr);
946 ok (dwFlags == desktopFlags, "Wrong Desktop attributes: %08lx\n", dwFlags);
948 /* Testing the attributes of the MyComputer shellfolder */
949 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL);
950 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08lx\n", hr);
951 if (hr != S_OK) {
952 IShellFolder_Release(psfDesktop);
953 return;
956 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
957 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
959 dwFlags = 0xffffffff;
960 hr = IShellFolder_GetAttributesOf(psfDesktop, 1, (LPCITEMIDLIST*)&pidlMyComputer, &dwFlags);
961 ok (hr == S_OK, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08lx\n", hr);
962 todo_wine
963 ok (dwFlags == (myComputerFlags | SFGAO_CANLINK), "Wrong MyComputer attributes: %08lx\n", dwFlags);
965 hr = IShellFolder_BindToObject(psfDesktop, pidlMyComputer, NULL, &IID_IShellFolder, (LPVOID*)&psfMyComputer);
966 ok (hr == S_OK, "Desktop failed to bind to MyComputer object! hr = %08lx\n", hr);
967 IShellFolder_Release(psfDesktop);
968 ILFree(pidlMyComputer);
969 if (hr != S_OK) return;
971 hr = IShellFolder_GetAttributesOf(psfMyComputer, 1, &pidlEmpty, &dwFlags);
972 todo_wine
973 ok (hr == E_INVALIDARG, "MyComputer->GetAttributesOf(empty pidl) should fail! hr = %08lx\n", hr);
975 dwFlags = 0xffffffff;
976 hr = IShellFolder_GetAttributesOf(psfMyComputer, 0, NULL, &dwFlags);
977 ok (hr == S_OK, "MyComputer->GetAttributesOf(NULL) failed! hr = %08lx\n", hr);
978 todo_wine
979 ok (dwFlags == myComputerFlags, "Wrong MyComputer attributes: %08lx\n", dwFlags);
981 IShellFolder_Release(psfMyComputer);
983 GetCurrentDirectoryA(MAX_PATH, cCurrDirA);
984 len = lstrlenA(cCurrDirA);
986 if (len == 0) {
987 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
988 return;
990 if (len > 3 && cCurrDirA[len-1] == '\\')
991 cCurrDirA[len-1] = 0;
993 /* create test directory */
994 CreateFilesFolders();
996 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
998 hr = SHGetDesktopFolder(&IDesktopFolder);
999 ok(hr == S_OK, "SHGetDesktopfolder failed %08lx\n", hr);
1001 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0);
1002 ok(hr == S_OK, "ParseDisplayName failed %08lx\n", hr);
1004 hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder);
1005 ok(hr == S_OK, "BindToObject failed %08lx\n", hr);
1007 ILFree(newPIDL);
1009 /* get relative PIDL */
1010 hr = IShellFolder_ParseDisplayName(testIShellFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
1011 ok(hr == S_OK, "ParseDisplayName failed %08lx\n", hr);
1013 /* test the shell attributes of the test directory using the relative PIDL */
1014 dwFlags = SFGAO_FOLDER;
1015 hr = IShellFolder_GetAttributesOf(testIShellFolder, 1, (LPCITEMIDLIST*)&newPIDL, &dwFlags);
1016 ok (hr == S_OK, "Desktop->GetAttributesOf() failed! hr = %08lx\n", hr);
1017 ok ((dwFlags&SFGAO_FOLDER), "Wrong directory attribute for relative PIDL: %08lx\n", dwFlags);
1019 /* free memory */
1020 ILFree(newPIDL);
1022 /* append testdirectory name to path */
1023 if (cCurrDirA[len-1] == '\\')
1024 cCurrDirA[len-1] = 0;
1025 lstrcatA(cCurrDirA, "\\testdir");
1026 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
1028 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0);
1029 ok(hr == S_OK, "ParseDisplayName failed %08lx\n", hr);
1031 /* test the shell attributes of the test directory using the absolute PIDL */
1032 dwFlags = SFGAO_FOLDER;
1033 hr = IShellFolder_GetAttributesOf(IDesktopFolder, 1, (LPCITEMIDLIST*)&newPIDL, &dwFlags);
1034 ok (hr == S_OK, "Desktop->GetAttributesOf() failed! hr = %08lx\n", hr);
1035 ok ((dwFlags&SFGAO_FOLDER), "Wrong directory attribute for absolute PIDL: %08lx\n", dwFlags);
1037 /* free memory */
1038 ILFree(newPIDL);
1040 IShellFolder_Release(testIShellFolder);
1042 Cleanup();
1044 IShellFolder_Release(IDesktopFolder);
1047 static void test_SHGetPathFromIDList(void)
1049 SHITEMID emptyitem = { 0, { 0 } };
1050 LPCITEMIDLIST pidlEmpty = (LPCITEMIDLIST)&emptyitem;
1051 LPITEMIDLIST pidlMyComputer;
1052 WCHAR wszPath[MAX_PATH], wszDesktop[MAX_PATH];
1053 BOOL result;
1054 HRESULT hr;
1055 LPSHELLFOLDER psfDesktop;
1056 WCHAR wszMyComputer[] = {
1057 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1058 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1059 WCHAR wszFileName[MAX_PATH];
1060 LPITEMIDLIST pidlTestFile;
1061 HANDLE hTestFile;
1062 STRRET strret;
1063 static WCHAR wszTestFile[] = {
1064 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1065 LPITEMIDLIST pidlPrograms;
1067 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1068 wszPath[0] = 'a';
1069 wszPath[1] = '\0';
1070 result = SHGetPathFromIDListW(NULL, wszPath);
1071 ok(!result, "Expected failure\n");
1072 ok(!wszPath[0], "Expected empty string\n");
1074 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1075 result = SHGetSpecialFolderPathW(NULL, wszDesktop, CSIDL_DESKTOP, FALSE);
1076 ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %lu\n", GetLastError());
1077 if (!result) return;
1079 result = SHGetPathFromIDListW(pidlEmpty, wszPath);
1080 ok(result, "SHGetPathFromIDListW failed! Last error: %lu\n", GetLastError());
1081 if (!result) return;
1082 ok(!lstrcmpiW(wszDesktop, wszPath), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1084 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1085 hr = SHGetDesktopFolder(&psfDesktop);
1086 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08lx\n", hr);
1087 if (hr != S_OK) return;
1089 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL);
1090 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08lx\n", hr);
1091 if (hr != S_OK) {
1092 IShellFolder_Release(psfDesktop);
1093 return;
1096 SetLastError(0xdeadbeef);
1097 wszPath[0] = 'a';
1098 wszPath[1] = '\0';
1099 result = SHGetPathFromIDListW(pidlMyComputer, wszPath);
1100 ok (!result, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1101 ok (GetLastError()==0xdeadbeef ||
1102 GetLastError()==ERROR_SUCCESS, /* Vista and higher */
1103 "Unexpected last error from SHGetPathFromIDListW: %lu\n", GetLastError());
1104 ok (!wszPath[0], "Expected empty path\n");
1105 if (result) {
1106 IShellFolder_Release(psfDesktop);
1107 return;
1110 ILFree(pidlMyComputer);
1112 result = SHGetSpecialFolderPathW(NULL, wszFileName, CSIDL_DESKTOPDIRECTORY, FALSE);
1113 ok(result, "SHGetSpecialFolderPathW failed! Last error: %lu\n", GetLastError());
1114 if (!result) {
1115 IShellFolder_Release(psfDesktop);
1116 return;
1118 myPathAddBackslashW(wszFileName);
1119 lstrcatW(wszFileName, wszTestFile);
1120 hTestFile = CreateFileW(wszFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
1121 ok(hTestFile != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: %lu\n", GetLastError());
1122 if (hTestFile == INVALID_HANDLE_VALUE) {
1123 IShellFolder_Release(psfDesktop);
1124 return;
1126 CloseHandle(hTestFile);
1128 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszTestFile, NULL, &pidlTestFile, NULL);
1129 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse filename hr = %08lx\n", hr);
1130 if (hr != S_OK) {
1131 IShellFolder_Release(psfDesktop);
1132 DeleteFileW(wszFileName);
1133 ILFree(pidlTestFile);
1134 return;
1137 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1138 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1139 hr = IShellFolder_GetDisplayNameOf(psfDesktop, pidlTestFile, SHGDN_FORPARSING, &strret);
1140 ok (hr == S_OK, "Desktop's GetDisplayNamfOf failed! hr = %08lx\n", hr);
1141 IShellFolder_Release(psfDesktop);
1142 DeleteFileW(wszFileName);
1143 if (hr != S_OK) {
1144 ILFree(pidlTestFile);
1145 return;
1147 StrRetToBufW(&strret, pidlTestFile, wszPath, MAX_PATH);
1148 ok(0 == lstrcmpW(wszFileName, wszPath),
1149 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1150 "returned incorrect path for file placed on desktop\n");
1152 result = SHGetPathFromIDListW(pidlTestFile, wszPath);
1153 ok(result, "SHGetPathFromIDListW failed! Last error: %lu\n", GetLastError());
1154 ok(0 == lstrcmpW(wszFileName, wszPath), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1156 if (pSHGetPathFromIDListEx)
1158 result = pSHGetPathFromIDListEx(pidlEmpty, wszPath, MAX_PATH, SFGAO_FILESYSTEM);
1159 ok(result, "SHGetPathFromIDListEx failed: %lu\n", GetLastError());
1160 ok(!lstrcmpiW(wszDesktop, wszPath), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1161 wine_dbgstr_w(wszPath), wine_dbgstr_w(wszDesktop));
1163 result = pSHGetPathFromIDListEx(pidlTestFile, wszPath, MAX_PATH, SFGAO_FILESYSTEM);
1164 ok(result, "SHGetPathFromIDListEx failed: %lu\n", GetLastError());
1165 ok(!lstrcmpiW(wszFileName, wszPath), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1166 wine_dbgstr_w(wszPath), wine_dbgstr_w(wszFileName));
1168 SetLastError(0xdeadbeef);
1169 memset(wszPath, 0x55, sizeof(wszPath));
1170 result = pSHGetPathFromIDListEx(pidlTestFile, wszPath, 5, SFGAO_FILESYSTEM);
1171 ok(!result, "SHGetPathFromIDListEx returned: %x(%lu)\n", result, GetLastError());
1173 SetLastError(0xdeadbeef);
1174 memset(wszPath, 0x55, sizeof(wszPath));
1175 result = pSHGetPathFromIDListEx(pidlEmpty, wszPath, 5, SFGAO_FILESYSTEM);
1176 ok(!result, "SHGetPathFromIDListEx returned: %x(%lu)\n", result, GetLastError());
1178 else
1179 win_skip("SHGetPathFromIDListEx not available\n");
1181 ILFree(pidlTestFile);
1183 /* Test if we can get the path from the start menu "program files" PIDL. */
1184 hr = SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES, &pidlPrograms);
1185 ok(hr == S_OK, "SHGetFolderLocation failed: 0x%08lx\n", hr);
1187 SetLastError(0xdeadbeef);
1188 result = SHGetPathFromIDListW(pidlPrograms, wszPath);
1189 ILFree(pidlPrograms);
1190 ok(result, "SHGetPathFromIDListW failed\n");
1193 static void test_EnumObjects_and_CompareIDs(void)
1195 ITEMIDLIST *newPIDL;
1196 IShellFolder *IDesktopFolder, *testIShellFolder;
1197 char cCurrDirA [MAX_PATH] = {0};
1198 static const CHAR cTestDirA[] = "\\testdir";
1199 WCHAR cTestDirW[MAX_PATH];
1200 int len;
1201 HRESULT hr;
1203 GetCurrentDirectoryA(MAX_PATH, cCurrDirA);
1204 len = lstrlenA(cCurrDirA);
1206 if(len == 0) {
1207 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1208 return;
1210 if(cCurrDirA[len-1] == '\\')
1211 cCurrDirA[len-1] = 0;
1213 lstrcatA(cCurrDirA, cTestDirA);
1214 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cTestDirW, MAX_PATH);
1216 hr = SHGetDesktopFolder(&IDesktopFolder);
1217 ok(hr == S_OK, "SHGetDesktopfolder failed %08lx\n", hr);
1219 CreateFilesFolders();
1221 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
1222 ok(hr == S_OK, "ParseDisplayName failed %08lx\n", hr);
1224 hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder);
1225 ok(hr == S_OK, "BindToObject failed %08lx\n", hr);
1227 test_EnumObjects(testIShellFolder);
1229 IShellFolder_Release(testIShellFolder);
1231 Cleanup();
1233 ILFree(newPIDL);
1235 IShellFolder_Release(IDesktopFolder);
1238 /* A simple implementation of an IPropertyBag, which returns fixed values for
1239 * 'Target' and 'Attributes' properties.
1241 static HRESULT WINAPI InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid,
1242 void **ppvObject)
1244 if (!ppvObject)
1245 return E_INVALIDARG;
1247 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPropertyBag, riid)) {
1248 *ppvObject = iface;
1249 } else {
1250 ok (FALSE, "InitPropertyBag asked for unknown interface!\n");
1251 return E_NOINTERFACE;
1254 IPropertyBag_AddRef(iface);
1255 return S_OK;
1258 static ULONG WINAPI InitPropertyBag_IPropertyBag_AddRef(IPropertyBag *iface) {
1259 return 2;
1262 static ULONG WINAPI InitPropertyBag_IPropertyBag_Release(IPropertyBag *iface) {
1263 return 1;
1266 static HRESULT WINAPI InitPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName,
1267 VARIANT *pVar, IErrorLog *pErrorLog)
1269 static const WCHAR wszTargetSpecialFolder[] = {
1270 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1271 static const WCHAR wszTarget[] = {
1272 'T','a','r','g','e','t',0 };
1273 static const WCHAR wszAttributes[] = {
1274 'A','t','t','r','i','b','u','t','e','s',0 };
1275 static const WCHAR wszResolveLinkFlags[] = {
1276 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1277 static const WCHAR wszTargetKnownFolder[] = {
1278 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1279 static const WCHAR wszCLSID[] = {
1280 'C','L','S','I','D',0 };
1282 if (!lstrcmpW(pszPropName, wszTargetSpecialFolder)) {
1283 ok(V_VT(pVar) == VT_I4, "Wrong variant type for 'TargetSpecialFolder' property!\n");
1284 return E_INVALIDARG;
1287 if (!lstrcmpW(pszPropName, wszResolveLinkFlags))
1289 ok(V_VT(pVar) == VT_UI4, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1290 return E_INVALIDARG;
1293 if (!lstrcmpW(pszPropName, wszTarget)) {
1294 WCHAR wszPath[MAX_PATH];
1295 BOOL result;
1297 ok(V_VT(pVar) == VT_BSTR, "Wrong variant type for 'Target' property!\n");
1298 if (V_VT(pVar) != VT_BSTR) return E_INVALIDARG;
1300 result = SHGetSpecialFolderPathW(NULL, wszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
1301 ok(result, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %lu\n", GetLastError());
1302 if (!result) return E_INVALIDARG;
1304 V_BSTR(pVar) = SysAllocString(wszPath);
1305 return S_OK;
1308 if (!lstrcmpW(pszPropName, wszAttributes)) {
1309 ok(V_VT(pVar) == VT_UI4, "Wrong variant type for 'Attributes' property!\n");
1310 if (V_VT(pVar) != VT_UI4) return E_INVALIDARG;
1311 V_UI4(pVar) = SFGAO_FOLDER|SFGAO_HASSUBFOLDER|SFGAO_FILESYSANCESTOR|
1312 SFGAO_CANRENAME|SFGAO_FILESYSTEM;
1313 return S_OK;
1316 if (!lstrcmpW(pszPropName, wszTargetKnownFolder)) {
1317 ok(V_VT(pVar) == VT_BSTR, "Wrong variant type for 'TargetKnownFolder' property!\n");
1318 /* TODO */
1319 return E_INVALIDARG;
1322 if (!lstrcmpW(pszPropName, wszCLSID)) {
1323 ok(V_VT(pVar) == VT_EMPTY, "Wrong variant type for 'CLSID' property!\n");
1324 /* TODO */
1325 return E_INVALIDARG;
1328 ok(FALSE, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName), V_VT(pVar));
1329 return E_INVALIDARG;
1332 static HRESULT WINAPI InitPropertyBag_IPropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName,
1333 VARIANT *pVar)
1335 ok(FALSE, "Unexpected call to IPropertyBag_Write\n");
1336 return E_NOTIMPL;
1339 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl = {
1340 InitPropertyBag_IPropertyBag_QueryInterface,
1341 InitPropertyBag_IPropertyBag_AddRef,
1342 InitPropertyBag_IPropertyBag_Release,
1343 InitPropertyBag_IPropertyBag_Read,
1344 InitPropertyBag_IPropertyBag_Write
1347 static struct IPropertyBag InitPropertyBag = {
1348 &InitPropertyBag_IPropertyBagVtbl
1351 static void test_FolderShortcut(void) {
1352 IPersistPropertyBag *pPersistPropertyBag;
1353 IShellFolder *pShellFolder, *pDesktopFolder;
1354 IPersistFolder3 *pPersistFolder3;
1355 HRESULT hr;
1356 STRRET strret;
1357 WCHAR wszDesktopPath[MAX_PATH], wszBuffer[MAX_PATH];
1358 BOOL result;
1359 CLSID clsid;
1360 LPITEMIDLIST pidlCurrentFolder, pidlWineTestFolder, pidlSubFolder;
1361 HKEY hShellExtKey;
1362 WCHAR wszWineTestFolder[] = {
1363 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1364 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1365 WCHAR wszShellExtKey[] = { 'S','o','f','t','w','a','r','e','\\',
1366 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1367 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1368 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1369 'N','a','m','e','S','p','a','c','e','\\',
1370 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1371 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1373 WCHAR wszSomeSubFolder[] = { 'S','u','b','F','o','l','d','e','r', 0};
1374 static const GUID CLSID_UnixDosFolder =
1375 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1377 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1378 * via their IPersistPropertyBag interface. And that the target folder
1379 * is taken from the IPropertyBag's 'Target' property.
1381 hr = CoCreateInstance(&CLSID_FolderShortcut, NULL, CLSCTX_INPROC_SERVER,
1382 &IID_IPersistPropertyBag, (LPVOID*)&pPersistPropertyBag);
1383 if (hr == REGDB_E_CLASSNOTREG) {
1384 win_skip("CLSID_FolderShortcut is not implemented\n");
1385 return;
1387 ok (hr == S_OK, "CoCreateInstance failed! hr = 0x%08lx\n", hr);
1388 if (hr != S_OK) return;
1390 hr = IPersistPropertyBag_Load(pPersistPropertyBag, &InitPropertyBag, NULL);
1391 ok(hr == S_OK, "IPersistPropertyBag_Load failed! hr = %08lx\n", hr);
1392 if (hr != S_OK) {
1393 IPersistPropertyBag_Release(pPersistPropertyBag);
1394 return;
1397 hr = IPersistPropertyBag_QueryInterface(pPersistPropertyBag, &IID_IShellFolder,
1398 (LPVOID*)&pShellFolder);
1399 IPersistPropertyBag_Release(pPersistPropertyBag);
1400 ok(hr == S_OK, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08lx\n", hr);
1401 if (hr != S_OK) return;
1403 hr = IShellFolder_GetDisplayNameOf(pShellFolder, NULL, SHGDN_FORPARSING, &strret);
1404 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* win10 */,
1405 "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08lx\n", hr);
1406 if (hr != S_OK) {
1407 IShellFolder_Release(pShellFolder);
1408 return;
1411 result = SHGetSpecialFolderPathW(NULL, wszDesktopPath, CSIDL_DESKTOPDIRECTORY, FALSE);
1412 ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %lu\n", GetLastError());
1413 if (!result) return;
1415 StrRetToBufW(&strret, NULL, wszBuffer, MAX_PATH);
1416 ok(!lstrcmpiW(wszDesktopPath, wszBuffer), "FolderShortcut returned incorrect folder!\n");
1418 hr = IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder3, (LPVOID*)&pPersistFolder3);
1419 IShellFolder_Release(pShellFolder);
1420 ok(hr == S_OK, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08lx\n", hr);
1421 if (hr != S_OK) return;
1423 hr = IPersistFolder3_GetClassID(pPersistFolder3, &clsid);
1424 ok(hr == S_OK, "IPersistFolder3_GetClassID failed! hr=0x%08lx\n", hr);
1425 ok(IsEqualCLSID(&clsid, &CLSID_FolderShortcut), "Unexpected CLSID!\n");
1427 hr = IPersistFolder3_GetCurFolder(pPersistFolder3, &pidlCurrentFolder);
1428 todo_wine ok(hr == S_FALSE, "IPersistFolder3_GetCurFolder failed! hr=0x%08lx\n", hr);
1429 ok(!pidlCurrentFolder, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1431 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1432 * shell namespace. The target folder, read from the property bag above, remains untouched.
1433 * The following tests show this: The itemidlist for some imaginary shellfolder object
1434 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1435 * itemidlist, but GetDisplayNameOf still returns the path from above.
1437 hr = SHGetDesktopFolder(&pDesktopFolder);
1438 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08lx\n", hr);
1439 if (hr != S_OK) return;
1441 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1442 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1443 RegCreateKeyW(HKEY_CURRENT_USER, wszShellExtKey, &hShellExtKey);
1444 RegCloseKey(hShellExtKey);
1445 hr = IShellFolder_ParseDisplayName(pDesktopFolder, NULL, NULL, wszWineTestFolder, NULL,
1446 &pidlWineTestFolder, NULL);
1447 RegDeleteKeyW(HKEY_CURRENT_USER, wszShellExtKey);
1448 IShellFolder_Release(pDesktopFolder);
1449 ok (hr == S_OK, "IShellFolder::ParseDisplayName failed! hr = %08lx\n", hr);
1450 if (hr != S_OK) return;
1452 hr = IPersistFolder3_Initialize(pPersistFolder3, pidlWineTestFolder);
1453 ok (hr == S_OK, "IPersistFolder3::Initialize failed! hr = %08lx\n", hr);
1454 if (hr != S_OK) {
1455 IPersistFolder3_Release(pPersistFolder3);
1456 ILFree(pidlWineTestFolder);
1457 return;
1460 hr = IPersistFolder3_GetCurFolder(pPersistFolder3, &pidlCurrentFolder);
1461 ok(hr == S_OK, "IPersistFolder3_GetCurFolder failed! hr=0x%08lx\n", hr);
1462 ok(ILIsEqual(pidlCurrentFolder, pidlWineTestFolder),
1463 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1464 ILFree(pidlCurrentFolder);
1465 ILFree(pidlWineTestFolder);
1467 hr = IPersistFolder3_QueryInterface(pPersistFolder3, &IID_IShellFolder, (LPVOID*)&pShellFolder);
1468 IPersistFolder3_Release(pPersistFolder3);
1469 ok(hr == S_OK, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08lx\n", hr);
1470 if (hr != S_OK) return;
1472 hr = IShellFolder_GetDisplayNameOf(pShellFolder, NULL, SHGDN_FORPARSING, &strret);
1473 ok(hr == S_OK, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08lx\n", hr);
1474 if (hr != S_OK) {
1475 IShellFolder_Release(pShellFolder);
1476 return;
1479 StrRetToBufW(&strret, NULL, wszBuffer, MAX_PATH);
1480 ok(!lstrcmpiW(wszDesktopPath, wszBuffer), "FolderShortcut returned incorrect folder!\n");
1482 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1483 * but ShellFSFolders. */
1484 myPathAddBackslashW(wszDesktopPath);
1485 lstrcatW(wszDesktopPath, wszSomeSubFolder);
1486 if (!CreateDirectoryW(wszDesktopPath, NULL)) {
1487 IShellFolder_Release(pShellFolder);
1488 return;
1491 hr = IShellFolder_ParseDisplayName(pShellFolder, NULL, NULL, wszSomeSubFolder, NULL,
1492 &pidlSubFolder, NULL);
1493 RemoveDirectoryW(wszDesktopPath);
1494 ok (hr == S_OK, "IShellFolder::ParseDisplayName failed! hr = %08lx\n", hr);
1495 if (hr != S_OK) {
1496 IShellFolder_Release(pShellFolder);
1497 return;
1500 hr = IShellFolder_BindToObject(pShellFolder, pidlSubFolder, NULL, &IID_IPersistFolder3,
1501 (LPVOID*)&pPersistFolder3);
1502 IShellFolder_Release(pShellFolder);
1503 ILFree(pidlSubFolder);
1504 ok (hr == S_OK, "IShellFolder::BindToObject failed! hr = %08lx\n", hr);
1505 if (hr != S_OK)
1506 return;
1508 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1509 * a little bit and also allow CLSID_UnixDosFolder. */
1510 hr = IPersistFolder3_GetClassID(pPersistFolder3, &clsid);
1511 ok(hr == S_OK, "IPersistFolder3_GetClassID failed! hr=0x%08lx\n", hr);
1512 ok(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder) || IsEqualCLSID(&clsid, &CLSID_UnixDosFolder),
1513 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1515 IPersistFolder3_Release(pPersistFolder3);
1518 #include "pshpack1.h"
1519 struct FileStructA {
1520 BYTE type;
1521 BYTE dummy;
1522 DWORD dwFileSize;
1523 WORD uFileDate; /* In our current implementation this is */
1524 WORD uFileTime; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1525 WORD uFileAttribs;
1526 CHAR szName[1];
1529 struct FileStructW {
1530 WORD cbLen; /* Length of this element. */
1531 BYTE abFooBar1[6]; /* Beyond any recognition. */
1532 WORD uDate; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1533 WORD uTime; /* (this is currently speculation) */
1534 WORD uDate2; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1535 WORD uTime2; /* (this is currently speculation) */
1536 BYTE abFooBar2[4]; /* Beyond any recognition. */
1537 WCHAR wszName[1]; /* The long filename in unicode. */
1538 /* Just for documentation: Right after the unicode string: */
1539 WORD cbOffset; /* FileStructW's offset from the beginning of the SHITMEID.
1540 * SHITEMID->cb == uOffset + cbLen */
1542 #include "poppack.h"
1544 static void test_ITEMIDLIST_format(void) {
1545 WCHAR wszPersonal[MAX_PATH];
1546 LPSHELLFOLDER psfDesktop, psfPersonal;
1547 LPITEMIDLIST pidlPersonal, pidlFile;
1548 HANDLE hFile;
1549 HRESULT hr;
1550 BOOL bResult;
1551 WCHAR wszFile[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1552 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1553 int i;
1555 bResult = SHGetSpecialFolderPathW(NULL, wszPersonal, CSIDL_PERSONAL, FALSE);
1556 ok(bResult, "SHGetSpecialFolderPathW failed! Last error: %lu\n", GetLastError());
1557 if (!bResult) return;
1559 SetLastError(0xdeadbeef);
1560 bResult = SetCurrentDirectoryW(wszPersonal);
1561 if (!bResult && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1562 win_skip("Most W-calls are not implemented\n");
1563 return;
1565 ok(bResult, "SetCurrentDirectory failed! Last error: %lu\n", GetLastError());
1566 if (!bResult) return;
1568 hr = SHGetDesktopFolder(&psfDesktop);
1569 ok(hr == S_OK, "SHGetDesktopFolder failed! hr: %08lx\n", hr);
1570 if (hr != S_OK) return;
1572 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszPersonal, NULL, &pidlPersonal, NULL);
1573 ok(hr == S_OK, "psfDesktop->ParseDisplayName failed! hr = %08lx\n", hr);
1574 if (hr != S_OK) {
1575 IShellFolder_Release(psfDesktop);
1576 return;
1579 hr = IShellFolder_BindToObject(psfDesktop, pidlPersonal, NULL, &IID_IShellFolder,
1580 (LPVOID*)&psfPersonal);
1581 IShellFolder_Release(psfDesktop);
1582 ILFree(pidlPersonal);
1583 ok(hr == S_OK, "psfDesktop->BindToObject failed! hr = %08lx\n", hr);
1584 if (hr != S_OK) return;
1586 for (i=0; i<3; i++) {
1587 CHAR szFile[MAX_PATH];
1588 struct FileStructA *pFileStructA;
1589 WORD cbOffset;
1591 WideCharToMultiByte(CP_ACP, 0, wszFile[i], -1, szFile, MAX_PATH, NULL, NULL);
1593 hFile = CreateFileW(wszFile[i], GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_WRITE_THROUGH, NULL);
1594 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed! (%lu)\n", GetLastError());
1595 if (hFile == INVALID_HANDLE_VALUE) {
1596 IShellFolder_Release(psfPersonal);
1597 return;
1599 CloseHandle(hFile);
1601 hr = IShellFolder_ParseDisplayName(psfPersonal, NULL, NULL, wszFile[i], NULL, &pidlFile, NULL);
1602 DeleteFileW(wszFile[i]);
1603 ok(hr == S_OK, "psfPersonal->ParseDisplayName failed! hr: %08lx\n", hr);
1604 if (hr != S_OK) {
1605 IShellFolder_Release(psfPersonal);
1606 return;
1609 pFileStructA = (struct FileStructA *)pidlFile->mkid.abID;
1610 ok(pFileStructA->type == 0x32, "PIDLTYPE should be 0x32!\n");
1611 ok(pFileStructA->dummy == 0x00, "Dummy Byte should be 0x00!\n");
1612 ok(pFileStructA->dwFileSize == 0, "Filesize should be zero!\n");
1614 if (i < 2) /* First two file names are already in valid 8.3 format */
1615 ok(!strcmp(szFile, (CHAR*)&pidlFile->mkid.abID[12]), "Wrong file name!\n");
1616 else
1617 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1618 * can't implement this correctly, since unix filesystems don't support
1619 * this nasty short/long filename stuff. So we'll probably stay with our
1620 * current habit of storing the long filename here, which seems to work
1621 * just fine. */
1622 todo_wine
1623 ok(pidlFile->mkid.abID[18] == '~', "Should be derived 8.3 name!\n");
1625 if (i == 0) /* First file name has an even number of chars. No need for alignment. */
1626 ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] != '\0',
1627 "Alignment byte, where there shouldn't be!\n");
1629 if (i == 1) /* Second file name has an uneven number of chars => alignment byte */
1630 ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] == '\0',
1631 "There should be an alignment byte, but isn't!\n");
1633 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1634 cbOffset = *(WORD*)(((LPBYTE)pidlFile)+pidlFile->mkid.cb-sizeof(WORD));
1635 ok ((cbOffset >= sizeof(struct FileStructA) &&
1636 cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW)),
1637 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset);
1639 if (cbOffset >= sizeof(struct FileStructA) &&
1640 cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW))
1642 struct FileStructW *pFileStructW = (struct FileStructW *)(((LPBYTE)pidlFile)+cbOffset);
1643 WCHAR *name = pFileStructW->wszName;
1645 ok(pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen,
1646 "FileStructW's offset and length should add up to the PIDL's length!\n");
1648 if (pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen) {
1649 /* Since we just created the file, time of creation,
1650 * time of last access and time of last write access just be the same.
1651 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1652 * after the first run. I do remember something with NTFS keeping the creation time
1653 * if a file is deleted and then created again within a couple of seconds or so.
1654 * Might be the reason. */
1655 ok (pFileStructA->uFileDate == pFileStructW->uDate &&
1656 pFileStructA->uFileTime == pFileStructW->uTime,
1657 "Last write time should match creation time!\n");
1659 /* On FAT filesystems the last access time is midnight
1660 local time, so the values of uDate2 and uTime2 will
1661 depend on the local timezone. If the times are exactly
1662 equal then the dates should be identical for both FAT
1663 and NTFS as no timezone is more than 1 day away from UTC.
1665 if (pFileStructA->uFileTime == pFileStructW->uTime2)
1667 ok (pFileStructA->uFileDate == pFileStructW->uDate2,
1668 "Last write date and time should match last access date and time!\n");
1670 else
1672 /* Filesystem may be FAT. Check date within 1 day
1673 and seconds are zero. */
1674 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1675 ok ((pFileStructW->uTime2 & 0x1F) == 0,
1676 "Last access time on FAT filesystems should have zero seconds.\n");
1677 /* TODO: Perform check for date being within one day.*/
1680 ok (!lstrcmpW(wszFile[i], name) ||
1681 !lstrcmpW(wszFile[i], name + 9) || /* Vista */
1682 !lstrcmpW(wszFile[i], name + 11) || /* Win7 */
1683 !lstrcmpW(wszFile[i], name + 13), /* Win8 */
1684 "The filename should be stored in unicode at this position!\n");
1688 ILFree(pidlFile);
1691 IShellFolder_Release(psfPersonal);
1694 static void test_SHGetFolderPathA(void)
1696 static const BOOL is_win64 = sizeof(void *) > sizeof(int);
1697 BOOL is_wow64;
1698 char path[MAX_PATH];
1699 char path_x86[MAX_PATH];
1700 char path_key[MAX_PATH];
1701 HRESULT hr;
1702 HKEY key;
1704 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
1706 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES, 0, SHGFP_TYPE_CURRENT, path );
1707 ok( hr == S_OK, "SHGetFolderPathA failed %lx\n", hr );
1708 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86, 0, SHGFP_TYPE_CURRENT, path_x86 );
1709 if (hr == E_FAIL)
1711 win_skip( "Program Files (x86) not supported\n" );
1712 return;
1714 ok( hr == S_OK, "SHGetFolderPathA failed %lx\n", hr );
1715 if (is_win64)
1717 ok( lstrcmpiA( path, path_x86 ), "paths are identical '%s'\n", path );
1718 ok( strstr( path, "x86" ) == NULL, "64-bit path '%s' contains x86\n", path );
1719 ok( strstr( path_x86, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path_x86 );
1721 else
1723 ok( !lstrcmpiA( path, path_x86 ), "paths differ '%s' != '%s'\n", path, path_x86 );
1724 if (is_wow64)
1725 ok( strstr( path, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path );
1726 else
1727 ok( strstr( path, "x86" ) == NULL, "32-bit path '%s' contains x86\n", path );
1729 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &key ))
1731 DWORD type, count = sizeof(path_x86);
1732 if (!RegQueryValueExA( key, "ProgramFilesDir (x86)", NULL, &type, (BYTE *)path_key, &count ))
1734 ok( is_win64 || is_wow64, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1735 ok( !lstrcmpiA( path_key, path_x86 ), "paths differ '%s' != '%s'\n", path_key, path_x86 );
1737 else ok( !is_win64 && !is_wow64, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1738 RegCloseKey( key );
1741 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON, 0, SHGFP_TYPE_CURRENT, path );
1742 ok( hr == S_OK, "SHGetFolderPathA failed %lx\n", hr );
1743 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86, 0, SHGFP_TYPE_CURRENT, path_x86 );
1744 if (hr == E_FAIL)
1746 win_skip( "Common Files (x86) not supported\n" );
1747 return;
1749 ok( hr == S_OK, "SHGetFolderPathA failed %lx\n", hr );
1750 if (is_win64)
1752 ok( lstrcmpiA( path, path_x86 ), "paths are identical '%s'\n", path );
1753 ok( strstr( path, "x86" ) == NULL, "64-bit path '%s' contains x86\n", path );
1754 ok( strstr( path_x86, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path_x86 );
1756 else
1758 ok( !lstrcmpiA( path, path_x86 ), "paths differ '%s' != '%s'\n", path, path_x86 );
1759 if (is_wow64)
1760 ok( strstr( path, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path );
1761 else
1762 ok( strstr( path, "x86" ) == NULL, "32-bit path '%s' contains x86\n", path );
1764 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &key ))
1766 DWORD type, count = sizeof(path_x86);
1767 if (!RegQueryValueExA( key, "CommonFilesDir (x86)", NULL, &type, (BYTE *)path_key, &count ))
1769 ok( is_win64 || is_wow64, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1770 ok( !lstrcmpiA( path_key, path_x86 ), "paths differ '%s' != '%s'\n", path_key, path_x86 );
1772 else ok( !is_win64 && !is_wow64, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1776 static void test_SHGetFolderPathAndSubDirA(void)
1778 HRESULT ret;
1779 BOOL delret;
1780 DWORD dwret;
1781 int i;
1782 static const char wine[] = "wine";
1783 static const char winetemp[] = "wine\\temp";
1784 static char appdata[MAX_PATH];
1785 static char testpath[2 * MAX_PATH];
1786 static char toolongpath[MAX_PATH+1];
1788 if(FAILED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdata)))
1790 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1791 return;
1794 sprintf(testpath, "%s\\%s", appdata, winetemp);
1795 delret = RemoveDirectoryA(testpath);
1796 if(!delret && (ERROR_PATH_NOT_FOUND != GetLastError()) ) {
1797 win_skip("RemoveDirectoryA(%s) failed with error %lu\n", testpath, GetLastError());
1798 return;
1801 sprintf(testpath, "%s\\%s", appdata, wine);
1802 delret = RemoveDirectoryA(testpath);
1803 if(!delret && (ERROR_PATH_NOT_FOUND != GetLastError()) && (ERROR_FILE_NOT_FOUND != GetLastError())) {
1804 win_skip("RemoveDirectoryA(%s) failed with error %lu\n", testpath, GetLastError());
1805 return;
1808 /* test invalid second parameter */
1809 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | 0xff, NULL, SHGFP_TYPE_CURRENT, wine, testpath);
1810 ok(E_INVALIDARG == ret, "expected E_INVALIDARG, got %lx\n", ret);
1812 /* test fourth parameter */
1813 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, 2, winetemp, testpath);
1814 switch(ret) {
1815 case S_OK: /* winvista */
1816 ok(!strncmp(appdata, testpath, strlen(appdata)),
1817 "expected %s to start with %s\n", testpath, appdata);
1818 ok(!lstrcmpA(&testpath[1 + strlen(appdata)], winetemp),
1819 "expected %s to end with %s\n", testpath, winetemp);
1820 break;
1821 case E_INVALIDARG: /* winxp, win2k3 */
1822 break;
1823 default:
1824 ok(0, "expected S_OK or E_INVALIDARG, got %lx\n", ret);
1827 /* test fifth parameter */
1828 testpath[0] = '\0';
1829 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, NULL, testpath);
1830 ok(S_OK == ret, "expected S_OK, got %lx\n", ret);
1831 ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath);
1833 testpath[0] = '\0';
1834 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, "", testpath);
1835 ok(S_OK == ret, "expected S_OK, got %lx\n", ret);
1836 ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath);
1838 testpath[0] = '\0';
1839 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, "\\", testpath);
1840 ok(S_OK == ret, "expected S_OK, got %lx\n", ret);
1841 ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath);
1843 for(i=0; i< MAX_PATH; i++)
1844 toolongpath[i] = '0' + i % 10;
1845 toolongpath[MAX_PATH] = '\0';
1846 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, toolongpath, testpath);
1847 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) == ret,
1848 "expected %lx, got %lx\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), ret);
1850 testpath[0] = '\0';
1851 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wine, NULL);
1852 ok((S_OK == ret) || (E_INVALIDARG == ret), "expected S_OK or E_INVALIDARG, got %lx\n", ret);
1854 /* test a not existing path */
1855 testpath[0] = '\0';
1856 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, winetemp, testpath);
1857 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == ret,
1858 "expected %lx, got %lx\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), ret);
1860 /* create a directory inside a not existing directory */
1861 testpath[0] = '\0';
1862 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_CREATE | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, winetemp, testpath);
1863 ok(S_OK == ret, "expected S_OK, got %lx\n", ret);
1864 ok(!strncmp(appdata, testpath, strlen(appdata)),
1865 "expected %s to start with %s\n", testpath, appdata);
1866 ok(!lstrcmpA(&testpath[1 + strlen(appdata)], winetemp),
1867 "expected %s to end with %s\n", testpath, winetemp);
1868 dwret = GetFileAttributesA(testpath);
1869 ok(FILE_ATTRIBUTE_DIRECTORY | dwret, "expected %lx to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret);
1871 /* cleanup */
1872 sprintf(testpath, "%s\\%s", appdata, winetemp);
1873 RemoveDirectoryA(testpath);
1874 sprintf(testpath, "%s\\%s", appdata, wine);
1875 RemoveDirectoryA(testpath);
1878 static void test_LocalizedNames(void)
1880 static char cCurrDirA[MAX_PATH];
1881 WCHAR cCurrDirW[MAX_PATH], tempbufW[25];
1882 IShellFolder *IDesktopFolder, *testIShellFolder;
1883 ITEMIDLIST *newPIDL;
1884 int len;
1885 HRESULT hr;
1886 static char resourcefile[MAX_PATH];
1887 DWORD res;
1888 HANDLE file;
1889 STRRET strret;
1890 BOOL ret;
1892 static const char desktopini_contents1[] =
1893 "[.ShellClassInfo]\r\n"
1894 "LocalizedResourceName=@";
1895 static const char desktopini_contents2[] =
1896 ",-1\r\n";
1897 static WCHAR foldernameW[] = {'t','e','s','t','f','o','l','d','e','r',0};
1898 static const WCHAR folderdisplayW[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
1900 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
1901 CreateDirectoryA(".\\testfolder", NULL);
1903 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM);
1905 GetModuleFileNameA(NULL, resourcefile, MAX_PATH);
1907 file = CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE, 0, NULL,
1908 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1909 ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed %li\n", GetLastError());
1910 ret = WriteFile(file, desktopini_contents1, strlen(desktopini_contents1), &res, NULL) &&
1911 WriteFile(file, resourcefile, strlen(resourcefile), &res, NULL) &&
1912 WriteFile(file, desktopini_contents2, strlen(desktopini_contents2), &res, NULL);
1913 ok(ret, "WriteFile failed %li\n", GetLastError());
1914 CloseHandle(file);
1916 /* get IShellFolder for parent */
1917 GetCurrentDirectoryA(MAX_PATH, cCurrDirA);
1918 len = lstrlenA(cCurrDirA);
1920 if (len == 0) {
1921 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
1922 goto cleanup;
1924 if(cCurrDirA[len-1] == '\\')
1925 cCurrDirA[len-1] = 0;
1927 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
1929 hr = SHGetDesktopFolder(&IDesktopFolder);
1930 ok(hr == S_OK, "SHGetDesktopfolder failed %08lx\n", hr);
1932 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0);
1933 ok(hr == S_OK, "ParseDisplayName failed %08lx\n", hr);
1935 hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder);
1936 ok(hr == S_OK, "BindToObject failed %08lx\n", hr);
1938 ILFree(newPIDL);
1940 /* windows reads the display name from the resource */
1941 hr = IShellFolder_ParseDisplayName(testIShellFolder, NULL, NULL, foldernameW, NULL, &newPIDL, 0);
1942 ok(hr == S_OK, "ParseDisplayName failed %08lx\n", hr);
1944 hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER, &strret);
1945 ok(hr == S_OK, "GetDisplayNameOf failed %08lx\n", hr);
1947 hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW));
1948 ok (hr == S_OK, "StrRetToBufW failed! hr = %08lx\n", hr);
1949 todo_wine
1950 ok (!lstrcmpiW(tempbufW, folderdisplayW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
1952 /* editing name is also read from the resource */
1953 hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FOREDITING, &strret);
1954 ok(hr == S_OK, "GetDisplayNameOf failed %08lx\n", hr);
1956 hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW));
1957 ok (hr == S_OK, "StrRetToBufW failed! hr = %08lx\n", hr);
1958 todo_wine
1959 ok (!lstrcmpiW(tempbufW, folderdisplayW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
1961 /* parsing name is unchanged */
1962 hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FORPARSING, &strret);
1963 ok(hr == S_OK, "GetDisplayNameOf failed %08lx\n", hr);
1965 hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW));
1966 ok (hr == S_OK, "StrRetToBufW failed! hr = %08lx\n", hr);
1967 ok (!lstrcmpiW(tempbufW, foldernameW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
1969 IShellFolder_Release(IDesktopFolder);
1970 IShellFolder_Release(testIShellFolder);
1972 ILFree(newPIDL);
1974 cleanup:
1975 DeleteFileA(".\\testfolder\\desktop.ini");
1976 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM);
1977 RemoveDirectoryA(".\\testfolder");
1980 static void test_SHCreateShellItem(void)
1982 IShellItem *shellitem, *shellitem2;
1983 IPersistIDList *persistidl;
1984 LPITEMIDLIST pidl_cwd=NULL, pidl_testfile, pidl_abstestfile, pidl_test, pidl_desktop;
1985 HRESULT ret;
1986 char curdirA[MAX_PATH];
1987 WCHAR curdirW[MAX_PATH];
1988 WCHAR fnbufW[MAX_PATH];
1989 IShellFolder *desktopfolder=NULL, *currentfolder=NULL;
1990 static WCHAR testfileW[] = {'t','e','s','t','f','i','l','e',0};
1992 GetCurrentDirectoryA(MAX_PATH, curdirA);
1994 if (!pSHCreateShellItem)
1996 win_skip("SHCreateShellItem isn't available\n");
1997 return;
2000 if (!curdirA[0])
2002 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2003 return;
2006 ret = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop);
2007 ok(ret == S_OK, "Got 0x%08lx\n", ret);
2009 MultiByteToWideChar(CP_ACP, 0, curdirA, -1, curdirW, MAX_PATH);
2011 ret = SHGetDesktopFolder(&desktopfolder);
2012 ok(SUCCEEDED(ret), "SHGetShellFolder returned %lx\n", ret);
2014 ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, curdirW, NULL, &pidl_cwd, NULL);
2015 ok(SUCCEEDED(ret), "ParseDisplayName returned %lx\n", ret);
2017 ret = IShellFolder_BindToObject(desktopfolder, pidl_cwd, NULL, &IID_IShellFolder, (void**)&currentfolder);
2018 ok(SUCCEEDED(ret), "BindToObject returned %lx\n", ret);
2020 CreateTestFile(".\\testfile");
2022 ret = IShellFolder_ParseDisplayName(currentfolder, NULL, NULL, testfileW, NULL, &pidl_testfile, NULL);
2023 ok(SUCCEEDED(ret), "ParseDisplayName returned %lx\n", ret);
2025 pidl_abstestfile = ILCombine(pidl_cwd, pidl_testfile);
2027 shellitem = (void*)0xdeadbeef;
2028 ret = pSHCreateShellItem(NULL, NULL, NULL, &shellitem);
2029 ok(ret == E_INVALIDARG, "SHCreateShellItem returned %lx\n", ret);
2030 ok(shellitem == 0, "Got %p\n", shellitem);
2032 if (0) /* crashes on Windows XP */
2034 pSHCreateShellItem(NULL, NULL, pidl_cwd, NULL);
2035 pSHCreateShellItem(pidl_cwd, NULL, NULL, &shellitem);
2036 pSHCreateShellItem(NULL, currentfolder, NULL, &shellitem);
2037 pSHCreateShellItem(pidl_cwd, currentfolder, NULL, &shellitem);
2040 ret = pSHCreateShellItem(NULL, NULL, pidl_cwd, &shellitem);
2041 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2042 if (SUCCEEDED(ret))
2044 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2045 ok(SUCCEEDED(ret), "QueryInterface returned %lx\n", ret);
2046 if (SUCCEEDED(ret))
2048 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2049 ok(SUCCEEDED(ret), "GetIDList returned %lx\n", ret);
2050 if (SUCCEEDED(ret))
2052 ok(ILIsEqual(pidl_cwd, pidl_test), "id lists are not equal\n");
2053 ILFree(pidl_test);
2055 IPersistIDList_Release(persistidl);
2057 IShellItem_Release(shellitem);
2060 ret = pSHCreateShellItem(pidl_cwd, NULL, pidl_testfile, &shellitem);
2061 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2062 if (SUCCEEDED(ret))
2064 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2065 ok(SUCCEEDED(ret), "QueryInterface returned %lx\n", ret);
2066 if (SUCCEEDED(ret))
2068 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2069 ok(SUCCEEDED(ret), "GetIDList returned %lx\n", ret);
2070 if (SUCCEEDED(ret))
2072 ok(ILIsEqual(pidl_abstestfile, pidl_test), "id lists are not equal\n");
2073 ILFree(pidl_test);
2075 IPersistIDList_Release(persistidl);
2078 ret = IShellItem_GetParent(shellitem, &shellitem2);
2079 ok(SUCCEEDED(ret), "GetParent returned %lx\n", ret);
2080 if (SUCCEEDED(ret))
2082 ret = IShellItem_QueryInterface(shellitem2, &IID_IPersistIDList, (void**)&persistidl);
2083 ok(SUCCEEDED(ret), "QueryInterface returned %lx\n", ret);
2084 if (SUCCEEDED(ret))
2086 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2087 ok(SUCCEEDED(ret), "GetIDList returned %lx\n", ret);
2088 if (SUCCEEDED(ret))
2090 ok(ILIsEqual(pidl_cwd, pidl_test), "id lists are not equal\n");
2091 ILFree(pidl_test);
2093 IPersistIDList_Release(persistidl);
2095 IShellItem_Release(shellitem2);
2098 IShellItem_Release(shellitem);
2101 ret = pSHCreateShellItem(NULL, currentfolder, pidl_testfile, &shellitem);
2102 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2103 if (SUCCEEDED(ret))
2105 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2106 ok(SUCCEEDED(ret), "QueryInterface returned %lx\n", ret);
2107 if (SUCCEEDED(ret))
2109 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2110 ok(SUCCEEDED(ret), "GetIDList returned %lx\n", ret);
2111 if (SUCCEEDED(ret))
2113 ok(ILIsEqual(pidl_abstestfile, pidl_test), "id lists are not equal\n");
2114 ILFree(pidl_test);
2116 IPersistIDList_Release(persistidl);
2118 IShellItem_Release(shellitem);
2121 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2122 ret = pSHCreateShellItem(pidl_cwd, desktopfolder, pidl_testfile, &shellitem);
2123 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2124 if (SUCCEEDED(ret))
2126 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2127 ok(SUCCEEDED(ret), "QueryInterface returned %lx\n", ret);
2128 if (SUCCEEDED(ret))
2130 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2131 ok(SUCCEEDED(ret), "GetIDList returned %lx\n", ret);
2132 if (SUCCEEDED(ret))
2134 ok(ILIsEqual(pidl_abstestfile, pidl_test), "id lists are not equal\n");
2135 ILFree(pidl_test);
2137 IPersistIDList_Release(persistidl);
2139 IShellItem_Release(shellitem);
2142 ret = pSHCreateShellItem(NULL, desktopfolder, pidl_testfile, &shellitem);
2143 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2144 if (SUCCEEDED(ret))
2146 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2147 ok(SUCCEEDED(ret), "QueryInterface returned %lx\n", ret);
2148 if (SUCCEEDED(ret))
2150 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2151 ok(SUCCEEDED(ret), "GetIDList returned %lx\n", ret);
2152 if (SUCCEEDED(ret))
2154 ok(ILIsEqual(pidl_testfile, pidl_test), "id lists are not equal\n");
2155 ILFree(pidl_test);
2157 IPersistIDList_Release(persistidl);
2160 IShellItem_Release(shellitem);
2163 ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem);
2164 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2165 if (SUCCEEDED(ret))
2167 ret = IShellItem_GetParent(shellitem, &shellitem2);
2168 ok(FAILED(ret), "Got 0x%08lx\n", ret);
2169 if(SUCCEEDED(ret)) IShellItem_Release(shellitem2);
2170 IShellItem_Release(shellitem);
2173 /* SHCreateItemFromParsingName */
2174 if(pSHCreateItemFromParsingName)
2176 if(0)
2178 /* Crashes under windows 7 */
2179 pSHCreateItemFromParsingName(NULL, NULL, &IID_IShellItem, NULL);
2182 shellitem = (void*)0xdeadbeef;
2183 ret = pSHCreateItemFromParsingName(NULL, NULL, &IID_IShellItem, (void**)&shellitem);
2184 ok(ret == E_INVALIDARG, "SHCreateItemFromParsingName returned %lx\n", ret);
2185 ok(shellitem == NULL, "shellitem was %p.\n", shellitem);
2187 ret = pSHCreateItemFromParsingName(testfileW, NULL, &IID_IShellItem, (void**)&shellitem);
2188 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
2189 "SHCreateItemFromParsingName returned %lx\n", ret);
2190 if(SUCCEEDED(ret)) IShellItem_Release(shellitem);
2192 lstrcpyW(fnbufW, curdirW);
2193 myPathAddBackslashW(fnbufW);
2194 lstrcatW(fnbufW, testfileW);
2196 ret = pSHCreateItemFromParsingName(fnbufW, NULL, &IID_IShellItem, (void**)&shellitem);
2197 ok(ret == S_OK, "SHCreateItemFromParsingName returned %lx\n", ret);
2198 if(SUCCEEDED(ret))
2200 LPWSTR tmp_fname;
2201 ret = IShellItem_GetDisplayName(shellitem, SIGDN_FILESYSPATH, &tmp_fname);
2202 ok(ret == S_OK, "GetDisplayName returned %lx\n", ret);
2203 if(SUCCEEDED(ret))
2205 ok(!lstrcmpW(fnbufW, tmp_fname), "strings not equal\n");
2206 CoTaskMemFree(tmp_fname);
2208 IShellItem_Release(shellitem);
2211 else
2212 win_skip("No SHCreateItemFromParsingName\n");
2215 /* SHCreateItemFromIDList */
2216 if(pSHCreateItemFromIDList)
2218 if(0)
2220 /* Crashes under win7 */
2221 pSHCreateItemFromIDList(NULL, &IID_IShellItem, NULL);
2224 ret = pSHCreateItemFromIDList(NULL, &IID_IShellItem, (void**)&shellitem);
2225 ok(ret == E_INVALIDARG, "SHCreateItemFromIDList returned %lx\n", ret);
2227 ret = pSHCreateItemFromIDList(pidl_cwd, &IID_IShellItem, (void**)&shellitem);
2228 ok(ret == S_OK, "SHCreateItemFromIDList returned %lx\n", ret);
2229 if (SUCCEEDED(ret))
2231 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2232 ok(ret == S_OK, "QueryInterface returned %lx\n", ret);
2233 if (SUCCEEDED(ret))
2235 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2236 ok(ret == S_OK, "GetIDList returned %lx\n", ret);
2237 if (SUCCEEDED(ret))
2239 ok(ILIsEqual(pidl_cwd, pidl_test), "id lists are not equal\n");
2240 ILFree(pidl_test);
2242 IPersistIDList_Release(persistidl);
2244 IShellItem_Release(shellitem);
2247 ret = pSHCreateItemFromIDList(pidl_testfile, &IID_IShellItem, (void**)&shellitem);
2248 ok(ret == S_OK, "SHCreateItemFromIDList returned %lx\n", ret);
2249 if (SUCCEEDED(ret))
2251 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl);
2252 ok(ret == S_OK, "QueryInterface returned %lx\n", ret);
2253 if (SUCCEEDED(ret))
2255 ret = IPersistIDList_GetIDList(persistidl, &pidl_test);
2256 ok(ret == S_OK, "GetIDList returned %lx\n", ret);
2257 if (SUCCEEDED(ret))
2259 ok(ILIsEqual(pidl_testfile, pidl_test), "id lists are not equal\n");
2260 ILFree(pidl_test);
2262 IPersistIDList_Release(persistidl);
2264 IShellItem_Release(shellitem);
2267 else
2268 win_skip("No SHCreateItemFromIDList\n");
2270 /* SHCreateItemFromRelativeName */
2271 if(pSHCreateItemFromRelativeName && pSHGetKnownFolderPath)
2273 IShellItem *shellitem_desktop = NULL;
2274 WCHAR *desktop_path, *displayname;
2275 WCHAR testfile_path[MAX_PATH] = {0};
2276 HANDLE file;
2277 LPITEMIDLIST pidl_desktop_testfile = NULL;
2278 int order;
2280 ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem_desktop);
2281 ok(ret == S_OK, "SHCreateShellItem failed: 0x%08lx.\n", ret);
2283 shellitem = (void*)0xdeadbeef;
2284 ret = pSHCreateItemFromRelativeName(shellitem_desktop, NULL, NULL, &IID_IShellItem,
2285 (void**)&shellitem);
2286 ok(ret == E_INVALIDARG, "Expected 0x%08lx but SHCreateItemFromRelativeName return: 0x%08lx.\n",
2287 E_INVALIDARG, ret);
2288 ok(shellitem == NULL, "shellitem was %p.\n", shellitem);
2290 /* Test with a non-existent file */
2291 shellitem = (void*)0xdeadbeef;
2292 ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem,
2293 (void**)&shellitem);
2294 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
2295 "Expected 0x%08lx but SHCreateItemFromRelativeName return: 0x%08lx.\n",
2296 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), ret);
2297 ok(shellitem == NULL, "shellitem was %p.\n", shellitem);
2299 /* Create a file for testing in desktop folder */
2300 pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &desktop_path);
2301 lstrcatW(testfile_path, desktop_path);
2302 myPathAddBackslashW(testfile_path);
2303 lstrcatW(testfile_path, testfileW);
2304 file = CreateFileW(testfile_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
2305 ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: 0x%08lx.\n", GetLastError());
2306 CloseHandle(file);
2308 shellitem = (void*)0xdeadbeef;
2309 ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem,
2310 (void**)&shellitem);
2311 ok(ret == S_OK, "SHCreateItemFromRelativeName failed: 0x%08lx.\n", ret);
2312 ok(shellitem != NULL, "shellitem was %p.\n", shellitem);
2313 if(SUCCEEDED(ret))
2315 ret = IShellItem_GetDisplayName(shellitem, 0, &displayname);
2316 ok(ret == S_OK, "IShellItem_GetDisplayName failed: 0x%08lx.\n", ret);
2317 ok(!lstrcmpW(displayname, testfileW), "got wrong display name: %s.\n", wine_dbgstr_w(displayname));
2318 CoTaskMemFree(displayname);
2320 shellitem2 = (void*)0xdeadbeef;
2321 ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem,
2322 (void**)&shellitem2);
2323 ok(ret == S_OK, "SHCreateItemFromRelativeName failed: 0x%08lx.\n", ret);
2324 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order);
2325 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08lx.\n", ret);
2326 ok(!order, "order got wrong value: %d.\n", order);
2327 IShellItem_Release(shellitem2);
2329 shellitem2 = (void*)0xdeadbeef;
2330 ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, testfileW, NULL,
2331 &pidl_desktop_testfile, NULL);
2332 ok(ret == S_OK, "ParseDisplayName failed 0x%08lx.\n", ret);
2333 ret = pSHCreateItemFromIDList(pidl_desktop_testfile, &IID_IShellItem, (void**)&shellitem2);
2334 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order);
2335 ok(ret == S_OK, "IShellItem_Compare fail: 0x%08lx.\n", ret);
2336 ok(!order, "order got wrong value: %d.\n", order);
2337 ILFree(pidl_desktop_testfile);
2338 IShellItem_Release(shellitem2);
2340 IShellItem_Release(shellitem);
2343 DeleteFileW(testfile_path);
2344 CoTaskMemFree(desktop_path);
2345 IShellItem_Release(shellitem_desktop);
2347 else
2348 win_skip("No SHCreateItemFromRelativeName or SHGetKnownFolderPath\n");
2350 /* SHCreateItemInKnownFolder */
2351 if(pSHCreateItemInKnownFolder && pSHGetKnownFolderPath)
2353 WCHAR *desktop_path;
2354 WCHAR testfile_path[MAX_PATH] = {0};
2355 HANDLE file;
2356 WCHAR *displayname = NULL;
2357 int order;
2358 LPITEMIDLIST pidl_desktop_testfile = NULL;
2360 shellitem = (void*)0xdeadbeef;
2361 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, NULL, &IID_IShellItem,
2362 (void**)&shellitem);
2363 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08lx.\n", ret);
2364 ok(shellitem != NULL, "shellitem was %p.\n", shellitem);
2365 if(SUCCEEDED(ret))
2367 shellitem2 = (void*)0xdeadbeef;
2368 ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem2);
2369 ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret);
2370 if(SUCCEEDED(ret))
2372 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order);
2373 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08lx.\n", ret);
2374 ok(!order, "order got wrong value: %d.\n", order);
2375 IShellItem_Release(shellitem2);
2377 IShellItem_Release(shellitem);
2380 /* Test with a non-existent file */
2381 shellitem = (void*)0xdeadbeef;
2382 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, testfileW, &IID_IShellItem,
2383 (void**)&shellitem);
2384 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
2385 "Expected 0x%08lx but SHCreateItemInKnownFolder return: 0x%08lx.\n",
2386 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), ret);
2387 ok(shellitem == NULL, "shellitem was %p.\n", shellitem);
2389 pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &desktop_path);
2390 lstrcatW(testfile_path, desktop_path);
2391 myPathAddBackslashW(testfile_path);
2392 lstrcatW(testfile_path, testfileW);
2393 file = CreateFileW(testfile_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
2394 ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: 0x%08lx.\n", GetLastError());
2395 CloseHandle(file);
2397 shellitem = (void*)0xdeadbeef;
2398 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, testfileW, &IID_IShellItem,
2399 (void**)&shellitem);
2400 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08lx.\n", ret);
2401 ok(shellitem != NULL, "shellitem was %p.\n", shellitem);
2402 if(SUCCEEDED(ret))
2404 ret = IShellItem_GetDisplayName(shellitem, 0, &displayname);
2405 ok(ret == S_OK, "IShellItem_GetDisplayName failed: 0x%08lx.\n", ret);
2406 ok(!lstrcmpW(displayname, testfileW), "got wrong display name: %s.\n",
2407 wine_dbgstr_w(displayname));
2408 CoTaskMemFree(displayname);
2410 shellitem2 = (void*)0xdeadbeef;
2411 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, testfileW, &IID_IShellItem,
2412 (void**)&shellitem2);
2413 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08lx.\n", ret);
2414 ok(shellitem2 != NULL, "shellitem was %p.\n", shellitem);
2415 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order);
2416 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08lx.\n", ret);
2417 ok(!order, "order got wrong value: %d.\n", order);
2418 IShellItem_Release(shellitem2);
2420 shellitem2 = (void*)0xdeadbeef;
2421 ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, testfileW, NULL,
2422 &pidl_desktop_testfile, NULL);
2423 ok(SUCCEEDED(ret), "ParseDisplayName returned %lx.\n", ret);
2424 ret = pSHCreateItemFromIDList(pidl_desktop_testfile, &IID_IShellItem, (void**)&shellitem2);
2425 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order);
2426 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08lx.\n", ret);
2427 ok(!order, "order got wrong value: %d.\n", order);
2428 ILFree(pidl_desktop_testfile);
2429 IShellItem_Release(shellitem2);
2431 IShellItem_Release(shellitem);
2434 shellitem = (void*)0xdeadbeef;
2435 ret = pSHCreateItemInKnownFolder(&FOLDERID_Documents, 0, NULL, &IID_IShellItem,
2436 (void**)&shellitem);
2437 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08lx.\n", ret);
2438 ok(shellitem != NULL, "shellitem was %p.\n", shellitem);
2439 if(SUCCEEDED(ret))
2441 shellitem2 = (void*)0xdeadbeef;
2442 ret = pSHCreateItemInKnownFolder(&FOLDERID_Documents, 0, NULL, &IID_IShellItem,
2443 (void**)&shellitem2);
2444 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08lx.\n", ret);
2445 ok(shellitem2 != NULL, "shellitem was %p.\n", shellitem);
2446 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order);
2447 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08lx.\n", ret);
2448 ok(!order, "order got wrong value: %d.\n", order);
2449 IShellItem_Release(shellitem2);
2451 IShellItem_Release(shellitem);
2453 DeleteFileW(testfile_path);
2454 CoTaskMemFree(desktop_path);
2456 else
2457 win_skip("No SHCreateItemInKnownFolder or SHGetKnownFolderPath\n");
2459 DeleteFileA(".\\testfile");
2460 ILFree(pidl_abstestfile);
2461 ILFree(pidl_testfile);
2462 ILFree(pidl_desktop);
2463 ILFree(pidl_cwd);
2464 IShellFolder_Release(currentfolder);
2465 IShellFolder_Release(desktopfolder);
2468 static void test_SHGetNameFromIDList(void)
2470 IShellItem *shellitem;
2471 LPITEMIDLIST pidl;
2472 LPWSTR name_string;
2473 HRESULT hres;
2474 UINT i;
2475 static const DWORD flags[] = {
2476 SIGDN_NORMALDISPLAY, SIGDN_PARENTRELATIVEPARSING,
2477 SIGDN_DESKTOPABSOLUTEPARSING,SIGDN_PARENTRELATIVEEDITING,
2478 SIGDN_DESKTOPABSOLUTEEDITING, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2479 SIGDN_PARENTRELATIVEFORADDRESSBAR,SIGDN_PARENTRELATIVE, -1234};
2481 if(!pSHGetNameFromIDList)
2483 win_skip("SHGetNameFromIDList missing.\n");
2484 return;
2487 /* This should be available on any platform that passed the above test. */
2488 ok(pSHCreateShellItem != NULL, "SHCreateShellItem missing.\n");
2490 if(0)
2492 /* Crashes under win7 */
2493 pSHGetNameFromIDList(NULL, 0, NULL);
2496 hres = pSHGetNameFromIDList(NULL, 0, &name_string);
2497 ok(hres == E_INVALIDARG, "Got 0x%08lx\n", hres);
2499 /* Test the desktop */
2500 hres = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
2501 ok(hres == S_OK, "Got 0x%08lx\n", hres);
2502 hres = pSHCreateShellItem(NULL, NULL, pidl, &shellitem);
2503 ok(hres == S_OK, "Got 0x%08lx\n", hres);
2504 if(SUCCEEDED(hres))
2506 WCHAR *nameSI, *nameSH;
2507 WCHAR buf[MAX_PATH];
2508 HRESULT hrSI, hrSH, hrSF;
2509 STRRET strret;
2510 IShellFolder *psf;
2511 BOOL res;
2513 SHGetDesktopFolder(&psf);
2514 for(i = 0; flags[i] != -1234; i++)
2516 hrSI = IShellItem_GetDisplayName(shellitem, flags[i], &nameSI);
2517 ok(hrSI == S_OK, "Got 0x%08lx\n", hrSI);
2518 hrSH = pSHGetNameFromIDList(pidl, flags[i], &nameSH);
2519 ok(hrSH == S_OK, "Got 0x%08lx\n", hrSH);
2520 hrSF = IShellFolder_GetDisplayNameOf(psf, pidl, flags[i] & 0xffff, &strret);
2521 ok(hrSF == S_OK, "Got 0x%08lx\n", hrSF);
2523 if(SUCCEEDED(hrSI) && SUCCEEDED(hrSH))
2524 ok(!lstrcmpW(nameSI, nameSH), "Strings differ.\n");
2526 if(SUCCEEDED(hrSF))
2528 StrRetToBufW(&strret, NULL, buf, MAX_PATH);
2529 if(SUCCEEDED(hrSI))
2530 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
2531 if(SUCCEEDED(hrSF))
2532 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
2534 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
2535 if(SUCCEEDED(hrSH)) CoTaskMemFree(nameSH);
2537 IShellFolder_Release(psf);
2539 hrSI = pSHGetNameFromIDList(pidl, SIGDN_FILESYSPATH, &nameSI);
2540 ok(hrSI == S_OK, "Got 0x%08lx\n", hrSI);
2541 res = SHGetPathFromIDListW(pidl, buf);
2542 ok(res == TRUE, "Got %d\n", res);
2543 if(SUCCEEDED(hrSI) && res)
2544 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
2545 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
2547 hres = pSHGetNameFromIDList(pidl, SIGDN_URL, &name_string);
2548 todo_wine ok(hres == S_OK, "Got 0x%08lx\n", hres);
2549 if(SUCCEEDED(hres)) CoTaskMemFree(name_string);
2551 IShellItem_Release(shellitem);
2553 ILFree(pidl);
2555 /* Test the control panel */
2556 hres = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidl);
2557 ok(hres == S_OK, "Got 0x%08lx\n", hres);
2558 hres = pSHCreateShellItem(NULL, NULL, pidl, &shellitem);
2559 ok(hres == S_OK, "Got 0x%08lx\n", hres);
2560 if(SUCCEEDED(hres))
2562 WCHAR *nameSI, *nameSH;
2563 WCHAR buf[MAX_PATH];
2564 HRESULT hrSI, hrSH, hrSF;
2565 STRRET strret;
2566 IShellFolder *psf;
2567 BOOL res;
2569 SHGetDesktopFolder(&psf);
2570 for(i = 0; flags[i] != -1234; i++)
2572 hrSI = IShellItem_GetDisplayName(shellitem, flags[i], &nameSI);
2573 ok(hrSI == S_OK, "Got 0x%08lx\n", hrSI);
2574 hrSH = pSHGetNameFromIDList(pidl, flags[i], &nameSH);
2575 ok(hrSH == S_OK, "Got 0x%08lx\n", hrSH);
2576 hrSF = IShellFolder_GetDisplayNameOf(psf, pidl, flags[i] & 0xffff, &strret);
2577 ok(hrSF == S_OK, "Got 0x%08lx\n", hrSF);
2579 if(SUCCEEDED(hrSI) && SUCCEEDED(hrSH))
2580 ok(!lstrcmpW(nameSI, nameSH), "Strings differ.\n");
2582 if(SUCCEEDED(hrSF))
2584 StrRetToBufW(&strret, NULL, buf, MAX_PATH);
2585 if(SUCCEEDED(hrSI))
2586 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
2587 if(SUCCEEDED(hrSF))
2588 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
2590 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
2591 if(SUCCEEDED(hrSH)) CoTaskMemFree(nameSH);
2593 IShellFolder_Release(psf);
2595 hrSI = pSHGetNameFromIDList(pidl, SIGDN_FILESYSPATH, &nameSI);
2596 ok(hrSI == E_INVALIDARG, "Got 0x%08lx\n", hrSI);
2597 res = SHGetPathFromIDListW(pidl, buf);
2598 ok(res == FALSE, "Got %d\n", res);
2599 if(SUCCEEDED(hrSI) && res)
2600 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
2601 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
2603 hres = pSHGetNameFromIDList(pidl, SIGDN_URL, &name_string);
2604 todo_wine ok(hres == E_NOTIMPL /* Win7 */ || hres == S_OK /* Vista */,
2605 "Got 0x%08lx\n", hres);
2606 if(SUCCEEDED(hres)) CoTaskMemFree(name_string);
2608 IShellItem_Release(shellitem);
2610 ILFree(pidl);
2613 static void test_SHGetItemFromDataObject(void)
2615 IShellFolder *psfdesktop;
2616 IShellItem *psi;
2617 IShellView *psv;
2618 HRESULT hres;
2620 if(!pSHGetItemFromDataObject)
2622 win_skip("No SHGetItemFromDataObject.\n");
2623 return;
2626 if(0)
2628 /* Crashes under win7 */
2629 pSHGetItemFromDataObject(NULL, 0, &IID_IShellItem, NULL);
2632 hres = pSHGetItemFromDataObject(NULL, 0, &IID_IShellItem, (void**)&psv);
2633 ok(hres == E_INVALIDARG, "got 0x%08lx\n", hres);
2635 SHGetDesktopFolder(&psfdesktop);
2637 hres = IShellFolder_CreateViewObject(psfdesktop, NULL, &IID_IShellView, (void**)&psv);
2638 ok(hres == S_OK, "got 0x%08lx\n", hres);
2639 if(SUCCEEDED(hres))
2641 IEnumIDList *peidl;
2642 IDataObject *pdo;
2643 SHCONTF enum_flags;
2645 enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN;
2646 hres = IShellFolder_EnumObjects(psfdesktop, NULL, enum_flags, &peidl);
2647 ok(hres == S_OK, "got 0x%08lx\n", hres);
2648 if(SUCCEEDED(hres))
2650 LPITEMIDLIST apidl[5];
2651 UINT count = 0, i;
2653 for(count = 0; count < 5; count++)
2654 if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK)
2655 break;
2657 if(count)
2659 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, 1, (LPCITEMIDLIST*)apidl,
2660 &IID_IDataObject, NULL, (void**)&pdo);
2661 ok(hres == S_OK, "got 0x%08lx\n", hres);
2662 if(SUCCEEDED(hres))
2664 hres = pSHGetItemFromDataObject(pdo, DOGIF_DEFAULT, &IID_IShellItem, (void**)&psi);
2665 ok(hres == S_OK, "got 0x%08lx\n", hres);
2666 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2667 hres = pSHGetItemFromDataObject(pdo, DOGIF_TRAVERSE_LINK, &IID_IShellItem, (void**)&psi);
2668 ok(hres == S_OK, "got 0x%08lx\n", hres);
2669 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2670 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_HDROP, &IID_IShellItem, (void**)&psi);
2671 ok(hres == S_OK, "got 0x%08lx\n", hres);
2672 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2673 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_URL, &IID_IShellItem, (void**)&psi);
2674 ok(hres == S_OK, "got 0x%08lx\n", hres);
2675 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2676 hres = pSHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE, &IID_IShellItem, (void**)&psi);
2677 ok(hres == S_OK, "got 0x%08lx\n", hres);
2678 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2680 IDataObject_Release(pdo);
2683 else
2684 skip("No file(s) found - skipping single-file test.\n");
2686 if(count > 1)
2688 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, count, (LPCITEMIDLIST*)apidl,
2689 &IID_IDataObject, NULL, (void**)&pdo);
2690 ok(hres == S_OK, "got 0x%08lx\n", hres);
2691 if(SUCCEEDED(hres))
2693 hres = pSHGetItemFromDataObject(pdo, DOGIF_DEFAULT, &IID_IShellItem, (void**)&psi);
2694 ok(hres == S_OK, "got 0x%08lx\n", hres);
2695 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2696 hres = pSHGetItemFromDataObject(pdo, DOGIF_TRAVERSE_LINK, &IID_IShellItem, (void**)&psi);
2697 ok(hres == S_OK, "got 0x%08lx\n", hres);
2698 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2699 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_HDROP, &IID_IShellItem, (void**)&psi);
2700 ok(hres == S_OK, "got 0x%08lx\n", hres);
2701 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2702 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_URL, &IID_IShellItem, (void**)&psi);
2703 ok(hres == S_OK, "got 0x%08lx\n", hres);
2704 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2705 hres = pSHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE, &IID_IShellItem, (void**)&psi);
2706 ok(hres == E_FAIL, "got 0x%08lx\n", hres);
2707 if(SUCCEEDED(hres)) IShellItem_Release(psi);
2708 IDataObject_Release(pdo);
2711 else
2712 skip("zero or one file found - skipping multi-file test.\n");
2714 for(i = 0; i < count; i++)
2715 ILFree(apidl[i]);
2717 IEnumIDList_Release(peidl);
2720 IShellView_Release(psv);
2723 IShellFolder_Release(psfdesktop);
2726 static void test_ShellItemCompare(void)
2728 IShellItem *psi[9]; /* a\a, a\b, a\c, b\a, .. */
2729 IShellItem *psi_a = NULL, *psi_b = NULL, *psi_c = NULL;
2730 IShellFolder *psf_desktop, *psf_current;
2731 LPITEMIDLIST pidl_cwd;
2732 WCHAR curdirW[MAX_PATH];
2733 BOOL failed;
2734 HRESULT hr;
2735 static const WCHAR filesW[][9] = {
2736 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2737 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2738 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2739 int order;
2740 UINT i;
2742 if(!pSHCreateShellItem)
2744 win_skip("SHCreateShellItem missing.\n");
2745 return;
2748 GetCurrentDirectoryW(MAX_PATH, curdirW);
2749 if (!curdirW[0])
2751 skip("Failed to get current directory, skipping.\n");
2752 return;
2755 CreateDirectoryA(".\\a", NULL);
2756 CreateDirectoryA(".\\b", NULL);
2757 CreateDirectoryA(".\\c", NULL);
2758 CreateTestFile(".\\a\\a");
2759 CreateTestFile(".\\a\\b");
2760 CreateTestFile(".\\a\\c");
2761 CreateTestFile(".\\b\\a");
2762 CreateTestFile(".\\b\\b");
2763 CreateTestFile(".\\b\\c");
2764 CreateTestFile(".\\c\\a");
2765 CreateTestFile(".\\c\\b");
2766 CreateTestFile(".\\c\\c");
2768 SHGetDesktopFolder(&psf_desktop);
2769 hr = IShellFolder_ParseDisplayName(psf_desktop, NULL, NULL, curdirW, NULL, &pidl_cwd, NULL);
2770 ok(SUCCEEDED(hr), "ParseDisplayName returned %lx\n", hr);
2771 hr = IShellFolder_BindToObject(psf_desktop, pidl_cwd, NULL, &IID_IShellFolder, (void**)&psf_current);
2772 ok(SUCCEEDED(hr), "BindToObject returned %lx\n", hr);
2773 IShellFolder_Release(psf_desktop);
2774 ILFree(pidl_cwd);
2776 /* Generate ShellItems for the files */
2777 memset(&psi, 0, sizeof(psi));
2778 failed = FALSE;
2779 for(i = 0; i < 9; i++)
2781 LPITEMIDLIST pidl_testfile = NULL;
2783 hr = IShellFolder_ParseDisplayName(psf_current, NULL, NULL, (LPWSTR)filesW[i],
2784 NULL, &pidl_testfile, NULL);
2785 ok(SUCCEEDED(hr), "ParseDisplayName returned %lx\n", hr);
2786 if(SUCCEEDED(hr))
2788 hr = pSHCreateShellItem(NULL, NULL, pidl_testfile, &psi[i]);
2789 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2790 ILFree(pidl_testfile);
2792 if(FAILED(hr)) failed = TRUE;
2794 if(failed)
2796 skip("Failed to create all shellitems.\n");
2797 goto cleanup;
2800 /* Generate ShellItems for the folders */
2801 hr = IShellItem_GetParent(psi[0], &psi_a);
2802 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2803 if(FAILED(hr)) failed = TRUE;
2804 hr = IShellItem_GetParent(psi[3], &psi_b);
2805 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2806 if(FAILED(hr)) failed = TRUE;
2807 hr = IShellItem_GetParent(psi[6], &psi_c);
2808 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2809 if(FAILED(hr)) failed = TRUE;
2811 if(failed)
2813 skip("Failed to create shellitems.\n");
2814 goto cleanup;
2817 if(0)
2819 /* Crashes on native (win7, winxp) */
2820 IShellItem_Compare(psi_a, NULL, 0, NULL);
2821 IShellItem_Compare(psi_a, psi_b, 0, NULL);
2822 IShellItem_Compare(psi_a, NULL, 0, &order);
2825 /* Basics */
2826 for(i = 0; i < 9; i++)
2828 hr = IShellItem_Compare(psi[i], psi[i], SICHINT_DISPLAY, &order);
2829 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2830 ok(order == 0, "Got order %d\n", order);
2831 hr = IShellItem_Compare(psi[i], psi[i], SICHINT_CANONICAL, &order);
2832 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2833 ok(order == 0, "Got order %d\n", order);
2834 hr = IShellItem_Compare(psi[i], psi[i], SICHINT_ALLFIELDS, &order);
2835 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2836 ok(order == 0, "Got order %d\n", order);
2839 /* Order */
2840 /* a\b:a\a , a\b:a\c, a\b:a\b */
2841 hr = IShellItem_Compare(psi[1], psi[0], SICHINT_DISPLAY, &order);
2842 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2843 ok(order == 1, "Got order %d\n", order);
2844 hr = IShellItem_Compare(psi[1], psi[2], SICHINT_DISPLAY, &order);
2845 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2846 ok(order == -1, "Got order %d\n", order);
2847 hr = IShellItem_Compare(psi[1], psi[1], SICHINT_DISPLAY, &order);
2848 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2849 ok(order == 0, "Got order %d\n", order);
2851 /* b\b:a\b, b\b:c\b, b\b:c\b */
2852 hr = IShellItem_Compare(psi[4], psi[1], SICHINT_DISPLAY, &order);
2853 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2854 ok(order == 1, "Got order %d\n", order);
2855 hr = IShellItem_Compare(psi[4], psi[7], SICHINT_DISPLAY, &order);
2856 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2857 ok(order == -1, "Got order %d\n", order);
2858 hr = IShellItem_Compare(psi[4], psi[4], SICHINT_DISPLAY, &order);
2859 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2860 ok(order == 0, "Got order %d\n", order);
2862 /* b:a\a, b:a\c, b:a\b */
2863 hr = IShellItem_Compare(psi_b, psi[0], SICHINT_DISPLAY, &order);
2864 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2865 todo_wine ok(order == 1, "Got order %d\n", order);
2866 hr = IShellItem_Compare(psi_b, psi[2], SICHINT_DISPLAY, &order);
2867 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2868 todo_wine ok(order == 1, "Got order %d\n", order);
2869 hr = IShellItem_Compare(psi_b, psi[1], SICHINT_DISPLAY, &order);
2870 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2871 todo_wine ok(order == 1, "Got order %d\n", order);
2873 /* b:c\a, b:c\c, b:c\b */
2874 hr = IShellItem_Compare(psi_b, psi[6], SICHINT_DISPLAY, &order);
2875 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2876 ok(order == -1, "Got order %d\n", order);
2877 hr = IShellItem_Compare(psi_b, psi[8], SICHINT_DISPLAY, &order);
2878 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2879 ok(order == -1, "Got order %d\n", order);
2880 hr = IShellItem_Compare(psi_b, psi[7], SICHINT_DISPLAY, &order);
2881 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2882 ok(order == -1, "Got order %d\n", order);
2884 /* a\b:a\a , a\b:a\c, a\b:a\b */
2885 hr = IShellItem_Compare(psi[1], psi[0], SICHINT_CANONICAL, &order);
2886 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2887 ok(order == 1, "Got order %d\n", order);
2888 hr = IShellItem_Compare(psi[1], psi[2], SICHINT_CANONICAL, &order);
2889 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2890 ok(order == -1, "Got order %d\n", order);
2891 hr = IShellItem_Compare(psi[1], psi[1], SICHINT_CANONICAL, &order);
2892 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2893 ok(order == 0, "Got order %d\n", order);
2895 /* b\b:a\b, b\b:c\b, b\b:c\b */
2896 hr = IShellItem_Compare(psi[4], psi[1], SICHINT_CANONICAL, &order);
2897 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2898 ok(order == 1, "Got order %d\n", order);
2899 hr = IShellItem_Compare(psi[4], psi[7], SICHINT_CANONICAL, &order);
2900 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2901 ok(order == -1, "Got order %d\n", order);
2902 hr = IShellItem_Compare(psi[4], psi[4], SICHINT_CANONICAL, &order);
2903 ok(hr == S_OK, "Got 0x%08lx\n", hr);
2904 ok(order == 0, "Got order %d\n", order);
2906 /* b:a\a, b:a\c, b:a\b */
2907 hr = IShellItem_Compare(psi_b, psi[0], SICHINT_CANONICAL, &order);
2908 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2909 todo_wine ok(order == 1, "Got order %d\n", order);
2910 hr = IShellItem_Compare(psi_b, psi[2], SICHINT_CANONICAL, &order);
2911 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2912 todo_wine ok(order == 1, "Got order %d\n", order);
2913 hr = IShellItem_Compare(psi_b, psi[1], SICHINT_CANONICAL, &order);
2914 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2915 todo_wine ok(order == 1, "Got order %d\n", order);
2917 /* b:c\a, b:c\c, b:c\b */
2918 hr = IShellItem_Compare(psi_b, psi[6], SICHINT_CANONICAL, &order);
2919 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2920 ok(order == -1, "Got order %d\n", order);
2921 hr = IShellItem_Compare(psi_b, psi[8], SICHINT_CANONICAL, &order);
2922 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2923 ok(order == -1, "Got order %d\n", order);
2924 hr = IShellItem_Compare(psi_b, psi[7], SICHINT_CANONICAL, &order);
2925 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
2926 ok(order == -1, "Got order %d\n", order);
2928 cleanup:
2929 IShellFolder_Release(psf_current);
2931 DeleteFileA(".\\a\\a");
2932 DeleteFileA(".\\a\\b");
2933 DeleteFileA(".\\a\\c");
2934 DeleteFileA(".\\b\\a");
2935 DeleteFileA(".\\b\\b");
2936 DeleteFileA(".\\b\\c");
2937 DeleteFileA(".\\c\\a");
2938 DeleteFileA(".\\c\\b");
2939 DeleteFileA(".\\c\\c");
2940 RemoveDirectoryA(".\\a");
2941 RemoveDirectoryA(".\\b");
2942 RemoveDirectoryA(".\\c");
2944 if(psi_a) IShellItem_Release(psi_a);
2945 if(psi_b) IShellItem_Release(psi_b);
2946 if(psi_c) IShellItem_Release(psi_c);
2948 for(i = 0; i < 9; i++)
2949 if(psi[i]) IShellItem_Release(psi[i]);
2952 /**************************************************************/
2953 /* IUnknown implementation for counting QueryInterface calls. */
2954 typedef struct {
2955 IUnknown IUnknown_iface;
2956 struct if_count {
2957 REFIID id;
2958 LONG count;
2959 } *ifaces;
2960 LONG unknown;
2961 } IUnknownImpl;
2963 static inline IUnknownImpl *impl_from_IUnknown(IUnknown *iface)
2965 return CONTAINING_RECORD(iface, IUnknownImpl, IUnknown_iface);
2968 static HRESULT WINAPI unk_fnQueryInterface(IUnknown *iunk, REFIID riid, void** punk)
2970 IUnknownImpl *This = impl_from_IUnknown(iunk);
2971 UINT i;
2972 BOOL found = FALSE;
2973 for(i = 0; This->ifaces[i].id != NULL; i++)
2975 if(IsEqualIID(This->ifaces[i].id, riid))
2977 This->ifaces[i].count++;
2978 found = TRUE;
2979 break;
2982 if(!found)
2983 This->unknown++;
2984 return E_NOINTERFACE;
2987 static ULONG WINAPI unk_fnAddRef(IUnknown *iunk)
2989 return 2;
2992 static ULONG WINAPI unk_fnRelease(IUnknown *iunk)
2994 return 1;
2997 static const IUnknownVtbl vt_IUnknown = {
2998 unk_fnQueryInterface,
2999 unk_fnAddRef,
3000 unk_fnRelease
3003 static void test_SHGetIDListFromObject(void)
3005 IUnknownImpl *punkimpl;
3006 IShellFolder *psfdesktop;
3007 IShellView *psv;
3008 LPITEMIDLIST pidl, pidl_desktop;
3009 HRESULT hres;
3010 UINT i;
3011 struct if_count ifaces[] =
3012 { {&IID_IPersistIDList, 0},
3013 {&IID_IPersistFolder2, 0},
3014 {&IID_IDataObject, 0},
3015 {&IID_IParentAndItem, 0},
3016 {&IID_IFolderView, 0},
3017 {NULL, 0} };
3019 if(!pSHGetIDListFromObject)
3021 win_skip("SHGetIDListFromObject missing.\n");
3022 return;
3025 if(0)
3027 /* Crashes native */
3028 pSHGetIDListFromObject(NULL, NULL);
3029 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL);
3032 hres = pSHGetIDListFromObject(NULL, &pidl);
3033 ok(hres == E_NOINTERFACE, "Got %lx\n", hres);
3035 punkimpl = heap_alloc(sizeof(*punkimpl));
3036 punkimpl->IUnknown_iface.lpVtbl = &vt_IUnknown;
3037 punkimpl->ifaces = ifaces;
3038 punkimpl->unknown = 0;
3040 hres = pSHGetIDListFromObject(&punkimpl->IUnknown_iface, &pidl);
3041 ok(hres == E_NOINTERFACE, "Got %lx\n", hres);
3042 ok(ifaces[0].count, "interface not requested.\n");
3043 ok(ifaces[1].count, "interface not requested.\n");
3044 ok(ifaces[2].count, "interface not requested.\n");
3045 todo_wine
3046 ok(ifaces[3].count || broken(!ifaces[3].count /*vista*/),
3047 "interface not requested.\n");
3048 ok(ifaces[4].count || broken(!ifaces[4].count /*vista*/),
3049 "interface not requested.\n");
3051 ok(!punkimpl->unknown, "Got %ld unknown.\n", punkimpl->unknown);
3052 heap_free(punkimpl);
3054 pidl_desktop = NULL;
3055 SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop);
3056 ok(pidl_desktop != NULL, "Failed to get desktop pidl.\n");
3058 SHGetDesktopFolder(&psfdesktop);
3060 /* Test IShellItem */
3061 if(pSHCreateShellItem)
3063 IShellItem *shellitem;
3064 hres = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem);
3065 ok(hres == S_OK, "got 0x%08lx\n", hres);
3066 if(SUCCEEDED(hres))
3068 hres = pSHGetIDListFromObject((IUnknown*)shellitem, &pidl);
3069 ok(hres == S_OK, "got 0x%08lx\n", hres);
3070 if(SUCCEEDED(hres))
3072 ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n");
3073 ILFree(pidl);
3075 IShellItem_Release(shellitem);
3078 else
3079 skip("no SHCreateShellItem.\n");
3081 /* Test IShellFolder */
3082 hres = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl);
3083 ok(hres == S_OK, "got 0x%08lx\n", hres);
3084 if(SUCCEEDED(hres))
3086 ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n");
3087 ILFree(pidl);
3090 hres = IShellFolder_CreateViewObject(psfdesktop, NULL, &IID_IShellView, (void**)&psv);
3091 ok(hres == S_OK, "got 0x%08lx\n", hres);
3092 if(SUCCEEDED(hres))
3094 IEnumIDList *peidl;
3095 IDataObject *pdo;
3096 SHCONTF enum_flags;
3098 /* Test IFolderView */
3099 hres = pSHGetIDListFromObject((IUnknown*)psv, &pidl);
3100 ok(hres == S_OK, "got 0x%08lx\n", hres);
3101 if(SUCCEEDED(hres))
3103 ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n");
3104 ILFree(pidl);
3107 /* Test IDataObject */
3108 enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN;
3109 hres = IShellFolder_EnumObjects(psfdesktop, NULL, enum_flags, &peidl);
3110 ok(hres == S_OK, "got 0x%08lx\n", hres);
3111 if(SUCCEEDED(hres))
3113 LPITEMIDLIST apidl[5];
3114 UINT count = 0;
3115 for(count = 0; count < 5; count++)
3116 if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK)
3117 break;
3119 if(count)
3121 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, 1, (LPCITEMIDLIST*)apidl,
3122 &IID_IDataObject, NULL, (void**)&pdo);
3123 ok(hres == S_OK, "got 0x%08lx\n", hres);
3124 if(SUCCEEDED(hres))
3126 pidl = (void*)0xDEADBEEF;
3127 hres = pSHGetIDListFromObject((IUnknown*)pdo, &pidl);
3128 ok(hres == S_OK, "got 0x%08lx\n", hres);
3129 ok(pidl != NULL, "pidl is NULL.\n");
3130 ok(ILIsEqual(pidl, apidl[0]), "pidl not equal.\n");
3131 ILFree(pidl);
3133 IDataObject_Release(pdo);
3136 else
3137 skip("No files found - skipping single-file test.\n");
3139 if(count > 1)
3141 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, count, (LPCITEMIDLIST*)apidl,
3142 &IID_IDataObject, NULL, (void**)&pdo);
3143 ok(hres == S_OK, "got 0x%08lx\n", hres);
3144 if(SUCCEEDED(hres))
3146 pidl = (void*)0xDEADBEEF;
3147 hres = pSHGetIDListFromObject((IUnknown*)pdo, &pidl);
3148 ok(hres == E_NOINTERFACE || hres == E_FAIL /*Vista*/,
3149 "got 0x%08lx\n", hres);
3150 ok(pidl == NULL, "pidl is not NULL.\n");
3152 IDataObject_Release(pdo);
3155 else
3156 skip("zero or one file found - skipping multi-file test.\n");
3158 for(i = 0; i < count; i++)
3159 ILFree(apidl[i]);
3161 IEnumIDList_Release(peidl);
3164 IShellView_Release(psv);
3167 IShellFolder_Release(psfdesktop);
3168 ILFree(pidl_desktop);
3171 static void test_SHGetItemFromObject(void)
3173 IUnknownImpl *punkimpl;
3174 IShellFolder *psfdesktop;
3175 LPITEMIDLIST pidl;
3176 IShellItem *psi;
3177 IUnknown *punk;
3178 HRESULT hres;
3179 struct if_count ifaces[] =
3180 { {&IID_IPersistIDList, 0},
3181 {&IID_IPersistFolder2, 0},
3182 {&IID_IDataObject, 0},
3183 {&IID_IParentAndItem, 0},
3184 {&IID_IFolderView, 0},
3185 {NULL, 0} };
3187 if(!pSHGetItemFromObject)
3189 skip("No SHGetItemFromObject.\n");
3190 return;
3193 SHGetDesktopFolder(&psfdesktop);
3195 if(0)
3197 /* Crashes with Windows 7 */
3198 pSHGetItemFromObject((IUnknown*)psfdesktop, &IID_IUnknown, NULL);
3199 pSHGetItemFromObject(NULL, &IID_IUnknown, NULL);
3200 pSHGetItemFromObject((IUnknown*)psfdesktop, NULL, (void**)&punk);
3203 hres = pSHGetItemFromObject(NULL, &IID_IUnknown, (void**)&punk);
3204 ok(hres == E_NOINTERFACE, "Got 0x%08lx\n", hres);
3206 punkimpl = heap_alloc(sizeof(*punkimpl));
3207 punkimpl->IUnknown_iface.lpVtbl = &vt_IUnknown;
3208 punkimpl->ifaces = ifaces;
3209 punkimpl->unknown = 0;
3211 /* The same as SHGetIDListFromObject */
3212 hres = pSHGetIDListFromObject(&punkimpl->IUnknown_iface, &pidl);
3213 ok(hres == E_NOINTERFACE, "Got %lx\n", hres);
3214 ok(ifaces[0].count, "interface not requested.\n");
3215 ok(ifaces[1].count, "interface not requested.\n");
3216 ok(ifaces[2].count, "interface not requested.\n");
3217 todo_wine
3218 ok(ifaces[3].count || broken(!ifaces[3].count /*vista*/),
3219 "interface not requested.\n");
3220 ok(ifaces[4].count || broken(!ifaces[4].count /*vista*/),
3221 "interface not requested.\n");
3223 ok(!punkimpl->unknown, "Got %ld unknown.\n", punkimpl->unknown);
3224 heap_free(punkimpl);
3226 /* Test IShellItem */
3227 hres = pSHGetItemFromObject((IUnknown*)psfdesktop, &IID_IShellItem, (void**)&psi);
3228 ok(hres == S_OK, "Got 0x%08lx\n", hres);
3229 if(SUCCEEDED(hres))
3231 IShellItem *psi2;
3232 hres = pSHGetItemFromObject((IUnknown*)psi, &IID_IShellItem, (void**)&psi2);
3233 ok(hres == S_OK, "Got 0x%08lx\n", hres);
3234 if(SUCCEEDED(hres))
3236 todo_wine
3237 ok(psi == psi2, "Different instances (%p != %p).\n", psi, psi2);
3238 IShellItem_Release(psi2);
3240 IShellItem_Release(psi);
3243 IShellFolder_Release(psfdesktop);
3246 static void test_SHCreateShellItemArray(void)
3248 IShellFolder *pdesktopsf, *psf;
3249 IShellItemArray *psia;
3250 IEnumIDList *peidl;
3251 HRESULT hr;
3252 WCHAR cTestDirW[MAX_PATH];
3253 LPITEMIDLIST pidl_testdir, pidl;
3254 static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0};
3256 if(!pSHCreateShellItemArray) {
3257 skip("No pSHCreateShellItemArray!\n");
3258 return;
3261 if(0)
3263 /* Crashes under native */
3264 pSHCreateShellItemArray(NULL, NULL, 0, NULL, NULL);
3265 pSHCreateShellItemArray(NULL, NULL, 1, NULL, NULL);
3266 pSHCreateShellItemArray(NULL, pdesktopsf, 0, NULL, NULL);
3267 pSHCreateShellItemArray(pidl, NULL, 0, NULL, NULL);
3270 hr = pSHCreateShellItemArray(NULL, NULL, 0, NULL, &psia);
3271 ok(hr == E_POINTER, "got 0x%08lx\n", hr);
3273 SHGetDesktopFolder(&pdesktopsf);
3274 hr = pSHCreateShellItemArray(NULL, pdesktopsf, 0, NULL, &psia);
3275 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
3277 hr = pSHCreateShellItemArray(NULL, pdesktopsf, 1, NULL, &psia);
3278 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
3280 SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
3281 hr = pSHCreateShellItemArray(pidl, NULL, 0, NULL, &psia);
3282 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
3283 ILFree(pidl);
3285 GetCurrentDirectoryW(MAX_PATH, cTestDirW);
3286 myPathAddBackslashW(cTestDirW);
3287 lstrcatW(cTestDirW, testdirW);
3289 CreateFilesFolders();
3291 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, cTestDirW, NULL, &pidl_testdir, 0);
3292 ok(hr == S_OK, "got 0x%08lx\n", hr);
3293 if(SUCCEEDED(hr))
3295 hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder,
3296 (void**)&psf);
3297 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3299 IShellFolder_Release(pdesktopsf);
3301 if(FAILED(hr))
3303 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3304 ILFree(pidl_testdir);
3305 Cleanup();
3306 return;
3309 hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl);
3310 ok(hr == S_OK, "Got %08lx\n", hr);
3311 if(SUCCEEDED(hr))
3313 LPITEMIDLIST apidl[5];
3314 UINT done;
3315 DWORD numitems, i;
3317 for(done = 0; done < 5; done++)
3318 if(IEnumIDList_Next(peidl, 1, &apidl[done], NULL) != S_OK)
3319 break;
3320 ok(done == 5, "Got %d pidls\n", done);
3321 IEnumIDList_Release(peidl);
3323 /* Create a ShellItemArray */
3324 hr = pSHCreateShellItemArray(NULL, psf, done, (LPCITEMIDLIST*)apidl, &psia);
3325 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3326 if(SUCCEEDED(hr))
3328 IShellItem *psi;
3330 if(0)
3332 /* Crashes in Windows 7 */
3333 IShellItemArray_GetCount(psia, NULL);
3336 IShellItemArray_GetCount(psia, &numitems);
3337 ok(numitems == done, "Got %ld, expected %d\n", numitems, done);
3339 hr = IShellItemArray_GetItemAt(psia, numitems, &psi);
3340 ok(hr == E_FAIL, "Got 0x%08lx\n", hr);
3342 /* Compare all the items */
3343 for(i = 0; i < numitems; i++)
3345 LPITEMIDLIST pidl_abs;
3346 pidl_abs = ILCombine(pidl_testdir, apidl[i]);
3348 hr = IShellItemArray_GetItemAt(psia, i, &psi);
3349 ok(hr == S_OK, "(%ld) Failed with 0x%08lx\n", i, hr);
3350 if(SUCCEEDED(hr))
3352 hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl);
3353 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3354 if(SUCCEEDED(hr))
3356 ok(ILIsEqual(pidl_abs, pidl), "Pidl not equal.\n");
3357 ILFree(pidl);
3359 IShellItem_Release(psi);
3361 ILFree(pidl_abs);
3363 for(i = 0; i < done; i++)
3364 ILFree(apidl[i]);
3365 IShellItemArray_Release(psia);
3369 /* SHCreateShellItemArrayFromShellItem */
3370 if(pSHCreateShellItemArrayFromShellItem)
3372 IShellItem *psi;
3374 if(0)
3376 /* Crashes under Windows 7 */
3377 pSHCreateShellItemArrayFromShellItem(NULL, &IID_IShellItemArray, NULL);
3378 pSHCreateShellItemArrayFromShellItem(NULL, &IID_IShellItemArray, (void**)&psia);
3379 pSHCreateShellItemArrayFromShellItem(psi, &IID_IShellItemArray, NULL);
3382 hr = pSHCreateItemFromIDList(pidl_testdir, &IID_IShellItem, (void**)&psi);
3383 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3384 if(SUCCEEDED(hr))
3386 hr = pSHCreateShellItemArrayFromShellItem(psi, &IID_IShellItemArray, (void**)&psia);
3387 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3388 if(SUCCEEDED(hr))
3390 IShellItem *psi2;
3391 DWORD count;
3392 hr = IShellItemArray_GetCount(psia, &count);
3393 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3394 ok(count == 1, "Got count %ld\n", count);
3395 hr = IShellItemArray_GetItemAt(psia, 0, &psi2);
3396 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3397 todo_wine
3398 ok(psi != psi2, "ShellItems are of the same instance.\n");
3399 if(SUCCEEDED(hr))
3401 LPITEMIDLIST pidl1, pidl2;
3402 hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl1);
3403 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3404 ok(pidl1 != NULL, "pidl1 was null.\n");
3405 hr = pSHGetIDListFromObject((IUnknown*)psi2, &pidl2);
3406 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3407 ok(pidl2 != NULL, "pidl2 was null.\n");
3408 ok(ILIsEqual(pidl1, pidl2), "pidls not equal.\n");
3409 ILFree(pidl1);
3410 ILFree(pidl2);
3411 IShellItem_Release(psi2);
3413 hr = IShellItemArray_GetItemAt(psia, 1, &psi2);
3414 ok(hr == E_FAIL, "Got 0x%08lx\n", hr);
3415 IShellItemArray_Release(psia);
3417 IShellItem_Release(psi);
3420 else
3421 skip("No SHCreateShellItemArrayFromShellItem.\n");
3423 if(pSHCreateShellItemArrayFromDataObject)
3425 IShellView *psv;
3427 if(0)
3429 /* Crashes under Windows 7 */
3430 pSHCreateShellItemArrayFromDataObject(NULL, &IID_IShellItemArray, NULL);
3432 hr = pSHCreateShellItemArrayFromDataObject(NULL, &IID_IShellItemArray, (void**)&psia);
3433 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
3435 hr = IShellFolder_CreateViewObject(psf, NULL, &IID_IShellView, (void**)&psv);
3436 ok(hr == S_OK, "got 0x%08lx\n", hr);
3437 if(SUCCEEDED(hr))
3439 IEnumIDList *peidl;
3440 IDataObject *pdo;
3441 SHCONTF enum_flags;
3443 enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN;
3444 hr = IShellFolder_EnumObjects(psf, NULL, enum_flags, &peidl);
3445 ok(hr == S_OK, "got 0x%08lx\n", hr);
3446 if(SUCCEEDED(hr))
3448 LPITEMIDLIST apidl[5];
3449 UINT count, i;
3451 for(count = 0; count < 5; count++)
3452 if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK)
3453 break;
3454 ok(count == 5, "Got %d\n", count);
3456 if(count)
3458 hr = IShellFolder_GetUIObjectOf(psf, NULL, count, (LPCITEMIDLIST*)apidl,
3459 &IID_IDataObject, NULL, (void**)&pdo);
3460 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3461 if(SUCCEEDED(hr))
3463 hr = pSHCreateShellItemArrayFromDataObject(pdo, &IID_IShellItemArray,
3464 (void**)&psia);
3465 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3466 if(SUCCEEDED(hr))
3468 DWORD count_sia, i;
3469 hr = IShellItemArray_GetCount(psia, &count_sia);
3470 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3471 ok(count_sia == count, "Counts differ (%d, %ld)\n", count, count_sia);
3472 for(i = 0; i < count_sia; i++)
3474 LPITEMIDLIST pidl_abs = ILCombine(pidl_testdir, apidl[i]);
3475 IShellItem *psi;
3476 hr = IShellItemArray_GetItemAt(psia, i, &psi);
3477 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3478 if(SUCCEEDED(hr))
3480 LPITEMIDLIST pidl;
3481 hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl);
3482 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3483 ok(pidl != NULL, "pidl as NULL.\n");
3484 ok(ILIsEqual(pidl, pidl_abs), "pidls differ.\n");
3485 ILFree(pidl);
3486 IShellItem_Release(psi);
3488 ILFree(pidl_abs);
3491 IShellItemArray_Release(psia);
3494 IDataObject_Release(pdo);
3496 for(i = 0; i < count; i++)
3497 ILFree(apidl[i]);
3499 else
3500 skip("No files found - skipping test.\n");
3502 IEnumIDList_Release(peidl);
3504 IShellView_Release(psv);
3507 else
3508 skip("No SHCreateShellItemArrayFromDataObject.\n");
3510 if(pSHCreateShellItemArrayFromIDLists)
3512 WCHAR test1W[] = {'t','e','s','t','1','.','t','x','t',0};
3513 WCHAR test1pathW[MAX_PATH];
3514 LPITEMIDLIST pidltest1;
3515 LPCITEMIDLIST pidl_array[2];
3517 if(0)
3519 /* Crashes */
3520 hr = pSHCreateShellItemArrayFromIDLists(0, NULL, NULL);
3523 psia = (void*)0xdeadbeef;
3524 hr = pSHCreateShellItemArrayFromIDLists(0, NULL, &psia);
3525 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
3526 ok(psia == NULL, "Got %p\n", psia);
3528 psia = (void*)0xdeadbeef;
3529 hr = pSHCreateShellItemArrayFromIDLists(0, pidl_array, &psia);
3530 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
3531 ok(psia == NULL, "Got %p\n", psia);
3533 psia = (void*)0xdeadbeef;
3534 pidl_array[0] = NULL;
3535 hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia);
3536 todo_wine ok(hr == E_OUTOFMEMORY, "Got 0x%08lx\n", hr);
3537 ok(psia == NULL, "Got %p\n", psia);
3539 psia = (void*)0xdeadbeef;
3540 pidl_array[0] = pidl_testdir;
3541 pidl_array[1] = NULL;
3542 hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia);
3543 todo_wine ok(hr == S_OK || broken(hr == E_INVALIDARG) /* Vista */, "Got 0x%08lx\n", hr);
3544 todo_wine ok(psia != NULL || broken(psia == NULL) /* Vista */, "Got %p\n", psia);
3545 if(SUCCEEDED(hr))
3547 IShellItem *psi;
3548 DWORD count = 0;
3550 hr = IShellItemArray_GetCount(psia, &count);
3551 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3552 ok(count == 2, "Got %ld\n", count);
3554 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
3555 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3556 if(SUCCEEDED(hr))
3558 LPWSTR path;
3559 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
3560 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3561 ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path));
3562 if(SUCCEEDED(hr))
3563 CoTaskMemFree(path);
3565 IShellItem_Release(psi);
3568 hr = IShellItemArray_GetItemAt(psia, 1, &psi);
3569 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3570 if(SUCCEEDED(hr))
3572 LPWSTR path;
3573 WCHAR desktoppath[MAX_PATH];
3574 BOOL result;
3576 result = SHGetSpecialFolderPathW(NULL, desktoppath, CSIDL_DESKTOPDIRECTORY, FALSE);
3577 ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %lu\n", GetLastError());
3579 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
3580 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3581 ok(!lstrcmpW(path, desktoppath), "Got %s\n", wine_dbgstr_w(path));
3582 if(SUCCEEDED(hr))
3583 CoTaskMemFree(path);
3585 IShellItem_Release(psi);
3589 IShellItemArray_Release(psia);
3593 /* Single pidl */
3594 psia = (void*)0xdeadbeef;
3595 pidl_array[0] = pidl_testdir;
3596 hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia);
3597 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3598 if(SUCCEEDED(hr))
3600 IShellItem *psi;
3601 DWORD count = 0;
3603 hr = IShellItemArray_GetCount(psia, &count);
3604 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3605 ok(count == 1, "Got %ld\n", count);
3607 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
3608 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3609 if(SUCCEEDED(hr))
3611 LPWSTR path;
3612 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
3613 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3614 ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path));
3615 if(SUCCEEDED(hr))
3616 CoTaskMemFree(path);
3618 IShellItem_Release(psi);
3621 IShellItemArray_Release(psia);
3625 lstrcpyW(test1pathW, cTestDirW);
3626 myPathAddBackslashW(test1pathW);
3627 lstrcatW(test1pathW, test1W);
3629 SHGetDesktopFolder(&pdesktopsf);
3631 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, test1pathW, NULL, &pidltest1, NULL);
3632 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3633 if(SUCCEEDED(hr))
3635 psia = (void*)0xdeadbeef;
3636 pidl_array[0] = pidl_testdir;
3637 pidl_array[1] = pidltest1;
3638 hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia);
3639 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3640 if(SUCCEEDED(hr))
3642 IShellItem *psi;
3643 DWORD count = 0;
3645 hr = IShellItemArray_GetCount(psia, &count);
3646 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3647 ok(count == 2, "Got %ld\n", count);
3649 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
3650 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3651 if(SUCCEEDED(hr))
3653 LPWSTR path;
3654 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
3655 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3656 ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path));
3657 if(SUCCEEDED(hr))
3658 CoTaskMemFree(path);
3660 IShellItem_Release(psi);
3663 hr = IShellItemArray_GetItemAt(psia, 1, &psi);
3664 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3665 if(SUCCEEDED(hr))
3667 LPWSTR path;
3668 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
3669 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3670 ok(!lstrcmpW(path, test1pathW), "Got %s\n", wine_dbgstr_w(path));
3671 if(SUCCEEDED(hr))
3672 CoTaskMemFree(path);
3674 IShellItem_Release(psi);
3678 IShellItemArray_Release(psia);
3681 ILFree(pidltest1);
3684 IShellFolder_Release(pdesktopsf);
3686 else
3687 skip("No SHCreateShellItemArrayFromIDLists.\n");
3689 IShellFolder_Release(psf);
3690 ILFree(pidl_testdir);
3691 Cleanup();
3694 static void test_ShellItemArrayEnumItems(void)
3696 IShellFolder *pdesktopsf, *psf;
3697 IEnumIDList *peidl;
3698 WCHAR cTestDirW[MAX_PATH];
3699 HRESULT hr;
3700 LPITEMIDLIST pidl_testdir;
3701 static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0};
3703 if(!pSHCreateShellItemArray)
3705 win_skip("No SHCreateShellItemArray, skipping test...\n");
3706 return;
3709 CreateFilesFolders();
3711 SHGetDesktopFolder(&pdesktopsf);
3713 GetCurrentDirectoryW(MAX_PATH, cTestDirW);
3714 myPathAddBackslashW(cTestDirW);
3715 lstrcatW(cTestDirW, testdirW);
3717 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, cTestDirW, NULL, &pidl_testdir, 0);
3718 ok(hr == S_OK, "got 0x%08lx\n", hr);
3719 if(SUCCEEDED(hr))
3721 hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder,
3722 (void**)&psf);
3723 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3724 ILFree(pidl_testdir);
3726 IShellFolder_Release(pdesktopsf);
3727 if (FAILED(hr)) return;
3729 hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl);
3730 ok(hr == S_OK, "Got %08lx\n", hr);
3731 if(SUCCEEDED(hr))
3733 IShellItemArray *psia;
3734 LPITEMIDLIST apidl[5];
3735 UINT done;
3736 DWORD numitems, i;
3738 for(done = 0; done < 5; done++)
3739 if(IEnumIDList_Next(peidl, 1, &apidl[done], NULL) != S_OK)
3740 break;
3741 ok(done == 5, "Got %d pidls\n", done);
3742 IEnumIDList_Release(peidl);
3744 /* Create a ShellItemArray */
3745 hr = pSHCreateShellItemArray(NULL, psf, done, (LPCITEMIDLIST*)apidl, &psia);
3746 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3747 if(SUCCEEDED(hr))
3749 IEnumShellItems *iesi;
3750 IShellItem *my_array[10];
3751 ULONG fetched;
3753 IShellItemArray_GetCount(psia, &numitems);
3754 ok(numitems == done, "Got %ld, expected %d\n", numitems, done);
3756 iesi = NULL;
3757 hr = IShellItemArray_EnumItems(psia, &iesi);
3758 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3759 ok(iesi != NULL, "Got NULL\n");
3760 if(SUCCEEDED(hr))
3762 IEnumShellItems *iesi2;
3764 /* This should fail according to the documentation and Win7+ */
3765 for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef;
3766 hr = IEnumShellItems_Next(iesi, 2, my_array, NULL);
3767 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* Vista */, "Got 0x%08lx\n", hr);
3768 for(i = 0; i < 2; i++)
3770 ok(my_array[i] == (void*)0xdeadbeef ||
3771 broken(my_array[i] != (void*)0xdeadbeef && my_array[i] != NULL), /* Vista */
3772 "Got %p (%ld)\n", my_array[i], i);
3774 if(my_array[i] != (void*)0xdeadbeef)
3775 IShellItem_Release(my_array[i]);
3777 ok(my_array[2] == (void*)0xdeadbeef, "Got %p\n", my_array[2]);
3779 IEnumShellItems_Reset(iesi);
3780 for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef;
3781 hr = IEnumShellItems_Next(iesi, 1, my_array, NULL);
3782 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3783 ok(my_array[0] != NULL && my_array[0] != (void*)0xdeadbeef, "Got %p\n", my_array[0]);
3784 if(my_array[0] != NULL && my_array[0] != (void*)0xdeadbeef)
3785 IShellItem_Release(my_array[0]);
3786 ok(my_array[1] == (void*)0xdeadbeef, "Got %p\n", my_array[1]);
3788 IEnumShellItems_Reset(iesi);
3789 fetched = 0;
3790 for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef;
3791 hr = IEnumShellItems_Next(iesi, numitems, my_array, &fetched);
3792 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3793 ok(fetched == numitems, "Got %ld\n", fetched);
3794 for(i = 0;i < numitems; i++)
3796 ok(my_array[i] != NULL && my_array[i] != (void*)0xdeadbeef,
3797 "Got %p at %ld\n", my_array[i], i);
3799 if(my_array[i] != NULL && my_array[i] != (void*)0xdeadbeef)
3800 IShellItem_Release(my_array[i]);
3802 ok(my_array[i] == (void*)0xdeadbeef, "Got %p\n", my_array[i]);
3804 /* Compare all the items */
3805 IEnumShellItems_Reset(iesi);
3806 for(i = 0; i < numitems; i++)
3808 IShellItem *psi;
3809 int order;
3811 hr = IShellItemArray_GetItemAt(psia, i, &psi);
3812 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3813 hr = IEnumShellItems_Next(iesi, 1, my_array, &fetched);
3814 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3815 ok(fetched == 1, "Got %ld\n", fetched);
3817 hr = IShellItem_Compare(psi, my_array[0], 0, &order);
3818 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3819 ok(order == 0, "Got %d\n", order);
3821 IShellItem_Release(psi);
3822 IShellItem_Release(my_array[0]);
3825 my_array[0] = (void*)0xdeadbeef;
3826 hr = IEnumShellItems_Next(iesi, 1, my_array, &fetched);
3827 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
3828 ok(fetched == 0, "Got %ld\n", fetched);
3829 ok(my_array[0] == (void*)0xdeadbeef, "Got %p\n", my_array[0]);
3831 /* Cloning not implemented anywhere */
3832 iesi2 = (void*)0xdeadbeef;
3833 hr = IEnumShellItems_Clone(iesi, &iesi2);
3834 ok(hr == E_NOTIMPL, "Got 0x%08lx\n", hr);
3835 ok(iesi2 == NULL || broken(iesi2 == (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2);
3837 IEnumShellItems_Release(iesi);
3840 IShellItemArray_Release(psia);
3843 for(i = 0; i < done; i++)
3844 ILFree(apidl[i]);
3847 IShellFolder_Release(psf);
3851 static void test_ShellItemBindToHandler(void)
3853 IShellItem *psi;
3854 LPITEMIDLIST pidl_desktop;
3855 HRESULT hr;
3857 if(!pSHCreateShellItem)
3859 skip("SHCreateShellItem missing.\n");
3860 return;
3863 hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop);
3864 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3865 if(SUCCEEDED(hr))
3867 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psi);
3868 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3870 if(SUCCEEDED(hr))
3872 IPersistFolder2 *ppf2;
3873 IUnknown *punk;
3875 if(0)
3877 /* Crashes under Windows 7 */
3878 IShellItem_BindToHandler(psi, NULL, NULL, NULL, NULL);
3879 IShellItem_BindToHandler(psi, NULL, &IID_IUnknown, &IID_IUnknown, NULL);
3881 hr = IShellItem_BindToHandler(psi, NULL, &IID_IUnknown, &IID_IUnknown, (void**)&punk);
3882 ok(hr == MK_E_NOOBJECT, "Got 0x%08lx\n", hr);
3884 /* BHID_SFObject */
3885 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IShellFolder, (void**)&punk);
3886 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3887 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3888 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IPersistFolder2, (void**)&ppf2);
3889 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3890 if(SUCCEEDED(hr))
3892 LPITEMIDLIST pidl_tmp;
3893 hr = IPersistFolder2_GetCurFolder(ppf2, &pidl_tmp);
3894 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3895 if(SUCCEEDED(hr))
3897 ok(ILIsEqual(pidl_desktop, pidl_tmp), "Pidl not equal (%p, %p)\n", pidl_desktop, pidl_tmp);
3898 ILFree(pidl_tmp);
3900 IPersistFolder2_Release(ppf2);
3903 /* BHID_SFUIObject */
3904 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFUIObject, &IID_IDataObject, (void**)&punk);
3905 ok(hr == S_OK || broken(hr == E_NOINTERFACE /* XP */), "Got 0x%08lx\n", hr);
3906 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3907 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFUIObject, &IID_IContextMenu, (void**)&punk);
3908 ok(hr == S_OK || broken(hr == E_NOINTERFACE /* XP */), "Got 0x%08lx\n", hr);
3909 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3911 /* BHID_DataObject */
3912 hr = IShellItem_BindToHandler(psi, NULL, &BHID_DataObject, &IID_IDataObject, (void**)&punk);
3913 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3914 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3916 todo_wine
3918 /* BHID_SFViewObject */
3919 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFViewObject, &IID_IShellView, (void**)&punk);
3920 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3921 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3922 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFViewObject, &IID_IShellFolderView, (void**)&punk);
3923 ok(hr == E_NOINTERFACE, "Got 0x%08lx\n", hr);
3924 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3926 /* BHID_Storage */
3927 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Storage, &IID_IStream, (void**)&punk);
3928 ok(hr == E_NOINTERFACE, "Got 0x%08lx\n", hr);
3929 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3930 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Storage, &IID_IUnknown, (void**)&punk);
3931 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3932 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3934 /* BHID_Stream */
3935 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Stream, &IID_IStream, (void**)&punk);
3936 ok(hr == E_NOINTERFACE, "Got 0x%08lx\n", hr);
3937 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3938 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Stream, &IID_IUnknown, (void**)&punk);
3939 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3940 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3942 /* BHID_StorageEnum */
3943 hr = IShellItem_BindToHandler(psi, NULL, &BHID_StorageEnum, &IID_IEnumShellItems, (void**)&punk);
3944 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3945 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3947 /* BHID_Transfer
3948 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
3949 supported starting from Win8. */
3950 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_ITransferSource, (void**)&punk);
3951 ok(hr == S_OK || broken(FAILED(hr)) /* pre-Vista */, "Got 0x%08lx\n", hr);
3952 if(SUCCEEDED(hr))
3954 IUnknown_Release(punk);
3956 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_ITransferDestination, (void**)&punk);
3957 ok(hr == S_OK, "Got 0x%08lx\n", hr);
3958 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3960 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_IUnknown, (void**)&punk);
3961 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* pre-Win8 */, "Got 0x%08lx\n", hr);
3962 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3965 /* BHID_EnumItems */
3966 hr = IShellItem_BindToHandler(psi, NULL, &BHID_EnumItems, &IID_IEnumShellItems, (void**)&punk);
3967 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3968 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3970 /* BHID_Filter */
3971 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Filter, &IID_IUnknown, (void**)&punk);
3972 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3973 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3975 /* BHID_LinkTargetItem */
3976 hr = IShellItem_BindToHandler(psi, NULL, &BHID_LinkTargetItem, &IID_IShellItem, (void**)&punk);
3977 ok(hr == E_NOINTERFACE || broken(hr == E_INVALIDARG /* XP */), "Got 0x%08lx\n", hr);
3978 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3979 hr = IShellItem_BindToHandler(psi, NULL, &BHID_LinkTargetItem, &IID_IUnknown, (void**)&punk);
3980 ok(hr == E_NOINTERFACE || broken(hr == E_INVALIDARG /* XP */), "Got 0x%08lx\n", hr);
3981 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3983 /* BHID_PropertyStore */
3984 hr = IShellItem_BindToHandler(psi, NULL, &BHID_PropertyStore, &IID_IPropertyStore, (void**)&punk);
3985 ok(hr == E_NOINTERFACE || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3986 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3987 hr = IShellItem_BindToHandler(psi, NULL, &BHID_PropertyStore, &IID_IPropertyStoreFactory, (void**)&punk);
3988 ok(hr == E_NOINTERFACE || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3989 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3991 /* BHID_ThumbnailHandler */
3992 hr = IShellItem_BindToHandler(psi, NULL, &BHID_ThumbnailHandler, &IID_IUnknown, (void**)&punk);
3993 ok(hr == E_INVALIDARG || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3994 if(SUCCEEDED(hr)) IUnknown_Release(punk);
3996 /* BHID_AssociationArray */
3997 hr = IShellItem_BindToHandler(psi, NULL, &BHID_AssociationArray, &IID_IQueryAssociations, (void**)&punk);
3998 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
3999 if(SUCCEEDED(hr)) IUnknown_Release(punk);
4001 /* BHID_EnumAssocHandlers */
4002 hr = IShellItem_BindToHandler(psi, NULL, &BHID_EnumAssocHandlers, &IID_IUnknown, (void**)&punk);
4003 ok(hr == E_NOINTERFACE || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08lx\n", hr);
4004 if(SUCCEEDED(hr)) IUnknown_Release(punk);
4007 IShellItem_Release(psi);
4009 else
4010 skip("Failed to create ShellItem.\n");
4012 ILFree(pidl_desktop);
4015 static void test_ShellItemGetAttributes(void)
4017 IShellItem *psi, *psi_folder1, *psi_file1;
4018 IShellFolder *pdesktopsf;
4019 LPITEMIDLIST pidl_desktop, pidl;
4020 SFGAOF sfgao;
4021 HRESULT hr;
4022 WCHAR curdirW[MAX_PATH];
4023 WCHAR buf[MAX_PATH];
4024 static const WCHAR testdir1W[] = {'t','e','s','t','d','i','r',0};
4025 static const WCHAR testfile1W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4027 if(!pSHCreateShellItem)
4029 skip("SHCreateShellItem missing.\n");
4030 return;
4033 hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop);
4034 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4035 if(SUCCEEDED(hr))
4037 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psi);
4038 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4039 ILFree(pidl_desktop);
4041 if(FAILED(hr))
4043 skip("Skipping tests.\n");
4044 return;
4047 if(0)
4049 /* Crashes on native (Win 7) */
4050 IShellItem_GetAttributes(psi, 0, NULL);
4053 /* Test GetAttributes on the desktop folder. */
4054 sfgao = 0xdeadbeef;
4055 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER, &sfgao);
4056 ok(hr == S_OK || broken(hr == E_FAIL) /* <Vista */, "Got 0x%08lx\n", hr);
4057 ok(sfgao == SFGAO_FOLDER || broken(sfgao == 0) /* <Vista */, "Got 0x%08lx\n", sfgao);
4059 IShellItem_Release(psi);
4061 CreateFilesFolders();
4063 SHGetDesktopFolder(&pdesktopsf);
4065 GetCurrentDirectoryW(MAX_PATH, curdirW);
4066 myPathAddBackslashW(curdirW);
4068 lstrcpyW(buf, curdirW);
4069 lstrcatW(buf, testdir1W);
4070 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, &pidl, NULL);
4071 ok(hr == S_OK, "got 0x%08lx\n", hr);
4072 hr = pSHCreateShellItem(NULL, NULL, pidl, &psi_folder1);
4073 ok(hr == S_OK, "Got 0x%08lx\n", sfgao);
4074 ILFree(pidl);
4076 lstrcpyW(buf, curdirW);
4077 lstrcatW(buf, testfile1W);
4078 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, &pidl, NULL);
4079 ok(hr == S_OK, "got 0x%08lx\n", hr);
4080 hr = pSHCreateShellItem(NULL, NULL, pidl, &psi_file1);
4081 ok(hr == S_OK, "Got 0x%08lx\n", sfgao);
4082 ILFree(pidl);
4084 IShellFolder_Release(pdesktopsf);
4086 sfgao = 0xdeadbeef;
4087 hr = IShellItem_GetAttributes(psi_folder1, 0, &sfgao);
4088 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4089 ok(sfgao == 0, "Got 0x%08lx\n", sfgao);
4091 sfgao = 0xdeadbeef;
4092 hr = IShellItem_GetAttributes(psi_folder1, SFGAO_FOLDER, &sfgao);
4093 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4094 ok(sfgao == SFGAO_FOLDER, "Got 0x%08lx\n", sfgao);
4096 sfgao = 0xdeadbeef;
4097 hr = IShellItem_GetAttributes(psi_file1, SFGAO_FOLDER, &sfgao);
4098 ok(hr == S_FALSE, "Got 0x%08lx\n", hr);
4099 ok(sfgao == 0, "Got 0x%08lx\n", sfgao);
4101 IShellItem_Release(psi_folder1);
4102 IShellItem_Release(psi_file1);
4104 Cleanup();
4107 static void test_ShellItemArrayGetAttributes(void)
4109 IShellItemArray *psia_files, *psia_folders1, *psia_folders2, *psia_all;
4110 IShellFolder *pdesktopsf;
4111 LPCITEMIDLIST pidl_array[5];
4112 SFGAOF attr;
4113 HRESULT hr;
4114 WCHAR curdirW[MAX_PATH];
4115 WCHAR buf[MAX_PATH];
4116 UINT i;
4117 static const WCHAR testdir1W[] = {'t','e','s','t','d','i','r',0};
4118 static const WCHAR testdir2W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
4119 static const WCHAR testdir3W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
4120 static const WCHAR testfile1W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4121 static const WCHAR testfile2W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
4122 static const WCHAR *testfilesW[5] = { testdir1W, testdir2W, testdir3W, testfile1W, testfile2W };
4124 if(!pSHCreateShellItemArrayFromShellItem)
4126 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
4127 return;
4130 CreateFilesFolders();
4131 CreateDirectoryA(".\\testdir\\testdir3", NULL);
4133 SHGetDesktopFolder(&pdesktopsf);
4135 GetCurrentDirectoryW(MAX_PATH, curdirW);
4136 myPathAddBackslashW(curdirW);
4138 for(i = 0; i < 5; i++)
4140 lstrcpyW(buf, curdirW);
4141 lstrcatW(buf, testfilesW[i]);
4142 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, (LPITEMIDLIST*)&pidl_array[i], NULL);
4143 ok(hr == S_OK, "got 0x%08lx\n", hr);
4145 IShellFolder_Release(pdesktopsf);
4147 hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia_folders1);
4148 ok(hr == S_OK, "got 0x%08lx\n", hr);
4149 hr = pSHCreateShellItemArrayFromIDLists(2, &pidl_array[1], &psia_folders2);
4150 ok(hr == S_OK, "got 0x%08lx\n", hr);
4151 hr = pSHCreateShellItemArrayFromIDLists(2, &pidl_array[3], &psia_files);
4152 ok(hr == S_OK, "got 0x%08lx\n", hr);
4153 hr = pSHCreateShellItemArrayFromIDLists(4, &pidl_array[1], &psia_all); /* All except the first */
4154 ok(hr == S_OK, "got 0x%08lx\n", hr);
4156 for(i = 0; i < 5; i++)
4157 ILFree((LPITEMIDLIST)pidl_array[i]);
4159 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
4160 attr = 0xdeadbeef;
4161 hr = IShellItemArray_GetAttributes(psia_folders1, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
4162 ok(hr == S_OK || broken(hr == E_UNEXPECTED) /* Vista */, "Got 0x%08lx\n", hr);
4163 ok(attr == SFGAO_FOLDER || broken(attr == 0) /* Vista */, "Got 0x%08lx\n", attr);
4164 attr = 0xdeadbeef;
4165 hr = IShellItemArray_GetAttributes(psia_folders1, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
4166 ok(hr == S_OK || broken(hr == E_UNEXPECTED) /* Vista */, "Got 0x%08lx\n", hr);
4167 ok(attr == SFGAO_FOLDER || broken(attr == 0) /* Vista */, "Got 0x%08lx\n", attr);
4169 /* [testfolder/testfolder2, testfolder/testfolder3] works */
4170 attr = 0xdeadbeef;
4171 hr = IShellItemArray_GetAttributes(psia_folders2, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
4172 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4173 ok(attr == SFGAO_FOLDER, "Got 0x%08lx\n", attr);
4174 attr = 0xdeadbeef;
4175 hr = IShellItemArray_GetAttributes(psia_files, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
4176 ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08lx\n", hr);
4177 ok(attr == 0, "Got 0x%08lx\n", attr);
4178 attr = 0xdeadbeef;
4179 hr = IShellItemArray_GetAttributes(psia_all, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
4180 ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08lx\n", hr);
4181 ok(attr == 0, "Got 0x%08lx\n", attr);
4182 attr = 0xdeadbeef;
4183 hr = IShellItemArray_GetAttributes(psia_folders2, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
4184 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4185 ok(attr == SFGAO_FOLDER, "Got 0x%08lx\n", attr);
4186 attr = 0xdeadbeef;
4187 hr = IShellItemArray_GetAttributes(psia_files, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
4188 ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08lx\n", hr);
4189 ok(attr == 0, "Got 0x%08lx\n", attr);
4190 attr = 0xdeadbeef;
4191 hr = IShellItemArray_GetAttributes(psia_all, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
4192 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4193 ok(attr == SFGAO_FOLDER, "Got 0x%08lx\n", attr);
4195 IShellItemArray_Release(psia_folders1);
4196 IShellItemArray_Release(psia_folders2);
4197 IShellItemArray_Release(psia_files);
4198 IShellItemArray_Release(psia_all);
4200 RemoveDirectoryA(".\\testdir\\testdir3");
4201 Cleanup();
4204 static void test_SHParseDisplayName(void)
4206 LPITEMIDLIST pidl1, pidl2;
4207 IShellFolder *desktop;
4208 WCHAR dirW[MAX_PATH];
4209 WCHAR nameW[10];
4210 HRESULT hr;
4211 BOOL ret, is_wow64;
4213 if (0)
4215 /* crashes on native */
4216 SHParseDisplayName(NULL, NULL, NULL, 0, NULL);
4217 nameW[0] = 0;
4218 SHParseDisplayName(nameW, NULL, NULL, 0, NULL);
4221 pidl1 = (LPITEMIDLIST)0xdeadbeef;
4222 hr = SHParseDisplayName(NULL, NULL, &pidl1, 0, NULL);
4223 ok(broken(hr == E_OUTOFMEMORY) /* < Vista */ ||
4224 hr == E_INVALIDARG, "failed %08lx\n", hr);
4225 ok(pidl1 == 0, "expected null ptr, got %p\n", pidl1);
4227 /* dummy name */
4228 nameW[0] = 0;
4229 hr = SHParseDisplayName(nameW, NULL, &pidl1, 0, NULL);
4230 ok(hr == S_OK, "failed %08lx\n", hr);
4231 hr = SHGetDesktopFolder(&desktop);
4232 ok(hr == S_OK, "failed %08lx\n", hr);
4233 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, nameW, NULL, &pidl2, NULL);
4234 ok(hr == S_OK, "failed %08lx\n", hr);
4235 ret = ILIsEqual(pidl1, pidl2);
4236 ok(ret == TRUE, "expected equal idls\n");
4237 ILFree(pidl1);
4238 ILFree(pidl2);
4240 /* with path */
4241 GetWindowsDirectoryW( dirW, MAX_PATH );
4243 hr = SHParseDisplayName(dirW, NULL, &pidl1, 0, NULL);
4244 ok(hr == S_OK, "failed %08lx\n", hr);
4245 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, dirW, NULL, &pidl2, NULL);
4246 ok(hr == S_OK, "failed %08lx\n", hr);
4248 ret = ILIsEqual(pidl1, pidl2);
4249 ok(ret == TRUE, "expected equal idls\n");
4250 ILFree(pidl1);
4251 ILFree(pidl2);
4253 /* system32 is not redirected to syswow64 on WOW64 */
4254 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
4255 if (is_wow64)
4257 UINT len;
4258 *dirW = 0;
4259 len = GetSystemDirectoryW(dirW, MAX_PATH);
4260 ok(len > 0, "GetSystemDirectoryW failed: %lu\n", GetLastError());
4261 hr = SHParseDisplayName(dirW, NULL, &pidl1, 0, NULL);
4262 ok(hr == S_OK, "failed %08lx\n", hr);
4263 *dirW = 0;
4264 len = GetSystemWow64DirectoryW(dirW, MAX_PATH);
4265 ok(len > 0, "GetSystemWow64DirectoryW failed: %lu\n", GetLastError());
4266 hr = SHParseDisplayName(dirW, NULL, &pidl2, 0, NULL);
4267 ok(hr == S_OK, "failed %08lx\n", hr);
4268 ret = ILIsEqual(pidl1, pidl2);
4269 ok(ret == FALSE, "expected different idls\n");
4270 ILFree(pidl1);
4271 ILFree(pidl2);
4274 IShellFolder_Release(desktop);
4277 static void test_desktop_IPersist(void)
4279 IShellFolder *desktop;
4280 IPersist *persist;
4281 IPersistFolder2 *ppf2;
4282 CLSID clsid;
4283 HRESULT hr;
4285 hr = SHGetDesktopFolder(&desktop);
4286 ok(hr == S_OK, "failed %08lx\n", hr);
4288 hr = IShellFolder_QueryInterface(desktop, &IID_IPersist, (void**)&persist);
4289 ok(hr == S_OK, "failed %08lx\n", hr);
4291 if (hr == S_OK)
4293 if (0)
4295 /* crashes on native */
4296 IPersist_GetClassID(persist, NULL);
4298 memset(&clsid, 0, sizeof(clsid));
4299 hr = IPersist_GetClassID(persist, &clsid);
4300 ok(hr == S_OK, "failed %08lx\n", hr);
4301 ok(IsEqualIID(&CLSID_ShellDesktop, &clsid), "Expected CLSID_ShellDesktop\n");
4302 IPersist_Release(persist);
4305 hr = IShellFolder_QueryInterface(desktop, &IID_IPersistFolder2, (void**)&ppf2);
4306 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* pre-Vista */, "failed %08lx\n", hr);
4307 if(SUCCEEDED(hr))
4309 IPersistFolder *ppf;
4310 LPITEMIDLIST pidl;
4311 hr = IShellFolder_QueryInterface(desktop, &IID_IPersistFolder, (void**)&ppf);
4312 ok(hr == S_OK, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
4313 if(SUCCEEDED(hr))
4314 IPersistFolder_Release(ppf);
4316 todo_wine {
4317 hr = IPersistFolder2_Initialize(ppf2, NULL);
4318 ok(hr == S_OK, "got %08lx\n", hr);
4321 pidl = NULL;
4322 hr = IPersistFolder2_GetCurFolder(ppf2, &pidl);
4323 ok(hr == S_OK, "got %08lx\n", hr);
4324 ok(pidl != NULL, "pidl was NULL.\n");
4325 if(SUCCEEDED(hr)) ILFree(pidl);
4327 IPersistFolder2_Release(ppf2);
4330 IShellFolder_Release(desktop);
4333 static void test_contextmenu_qi(IContextMenu *menu, BOOL todo)
4335 IUnknown *unk;
4336 HRESULT hr;
4338 hr = IContextMenu_QueryInterface(menu, &IID_IShellExtInit, (void **)&unk);
4339 todo_wine_if(todo)
4340 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#lx.\n", hr);
4341 if (hr == S_OK)
4342 IUnknown_Release(unk);
4344 hr = IContextMenu_QueryInterface(menu, &IID_IObjectWithSite, (void **)&unk);
4345 todo_wine_if(todo)
4346 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#lx.\n", hr);
4347 if (hr == S_OK)
4348 IUnknown_Release(unk);
4351 static void test_contextmenu(IContextMenu *menu, BOOL background)
4353 HMENU hmenu = CreatePopupMenu();
4354 UINT count, i, max_id;
4355 HRESULT hr;
4357 test_contextmenu_qi(menu, FALSE);
4359 hr = IContextMenu_QueryContextMenu(menu, hmenu, 0, 64, 32767, CMF_NORMAL);
4360 ok(SUCCEEDED(hr), "Failed to query the menu, hr %#lx.\n", hr);
4362 max_id = HRESULT_CODE(hr) - 1; /* returns max_id + 1 */
4363 ok(max_id <= 32767, "Got %d\n", max_id);
4364 count = GetMenuItemCount(hmenu);
4365 ok(count, "Got %d\n", count);
4367 for (i = 0; i < count; i++)
4369 MENUITEMINFOA mii;
4370 INT res;
4371 char buf[255], buf2[255];
4372 ZeroMemory(&mii, sizeof(MENUITEMINFOA));
4373 mii.cbSize = sizeof(MENUITEMINFOA);
4374 mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
4375 mii.dwTypeData = buf2;
4376 mii.cch = sizeof(buf2);
4378 res = GetMenuItemInfoA(hmenu, i, TRUE, &mii);
4379 ok(res, "Failed to get menu item info, error %ld.\n", GetLastError());
4381 if (!(mii.fType & MFT_SEPARATOR))
4383 ok(mii.wID >= 64 && mii.wID <= 64 + max_id,
4384 "Expected between 64 and %d, got %d.\n", 64 + max_id, mii.wID);
4385 hr = IContextMenu_GetCommandString(menu, mii.wID - 64, GCS_VERBA, 0, buf, sizeof(buf));
4386 ok(hr == S_OK || hr == E_NOTIMPL || hr == E_INVALIDARG,
4387 "Got unexpected hr %#lx for ID %d, string %s.\n", hr, mii.wID, debugstr_a(mii.dwTypeData));
4388 if (hr == S_OK)
4390 trace("Got ID %d, verb %s, string %s.\n", mii.wID, debugstr_a(buf), debugstr_a(mii.dwTypeData));
4391 if (!strcmp(buf, "copy"))
4393 CMINVOKECOMMANDINFO cmi;
4394 ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_COPY, "wrong menu wID %d\n", mii.wID);
4395 memset(&cmi, 0, sizeof(CMINVOKECOMMANDINFO));
4396 cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
4397 cmi.lpVerb = "copy";
4398 hr = IContextMenu_InvokeCommand(menu, &cmi);
4399 ok(hr == S_OK, "got 0x%08lx\n", hr);
4400 ok(IsClipboardFormatAvailable(RegisterClipboardFormatA(CFSTR_SHELLIDLISTA)), "CFSTR_SHELLIDLISTA not available\n");
4401 ok(IsClipboardFormatAvailable(CF_HDROP), "CF_HDROP not available\n");
4403 else if (!strcmp(buf, "paste"))
4404 ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_INSERT, "wrong menu wID %d\n", mii.wID);
4405 else if (!strcmp(buf, "properties"))
4406 ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_PROPERTIES, "wrong menu wID %d\n", mii.wID);
4408 else
4409 trace("Got ID %d, hr %#lx, string %s.\n", mii.wID, hr, debugstr_a(mii.dwTypeData));
4413 if (count)
4415 CMINVOKECOMMANDINFO cmi;
4417 memset(&cmi, 0, sizeof(CMINVOKECOMMANDINFO));
4418 cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
4420 /* Attempt to execute a nonexistent command */
4421 cmi.lpVerb = MAKEINTRESOURCEA(9999);
4422 hr = IContextMenu_InvokeCommand(menu, &cmi);
4423 todo_wine_if(background)
4424 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
4426 cmi.lpVerb = "foobar_wine_test";
4427 hr = IContextMenu_InvokeCommand(menu, &cmi);
4428 todo_wine_if(background)
4429 ok((hr == E_INVALIDARG) || (hr == E_FAIL /* Win7 */) ||
4430 (hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION) /* Vista */),
4431 "Unexpected hr %#lx.\n", hr);
4434 DestroyMenu(hmenu);
4437 static void test_GetUIObject(void)
4439 IShellFolder *psf_desktop;
4440 IContextMenu *pcm;
4441 LPITEMIDLIST pidl;
4442 HRESULT hr;
4443 WCHAR path[MAX_PATH];
4444 const WCHAR filename[] =
4445 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4446 LPCITEMIDLIST pidl_child;
4447 IShellFolder *psf;
4449 GetCurrentDirectoryW(MAX_PATH, path);
4450 if (!path[0])
4452 skip("GetCurrentDirectoryW returned an empty string.\n");
4453 return;
4455 lstrcatW(path, filename);
4456 SHGetDesktopFolder(&psf_desktop);
4458 CreateFilesFolders();
4460 hr = IShellFolder_ParseDisplayName(psf_desktop, NULL, NULL, path, NULL, &pidl, 0);
4461 ok(hr == S_OK, "Got 0x%08lx\n", hr);
4463 hr = SHBindToParent(pidl, &IID_IShellFolder, (void **)&psf, &pidl_child);
4464 ok(hr == S_OK, "Failed to bind to folder, hr %#lx.\n", hr);
4466 /* Item menu */
4467 hr = IShellFolder_GetUIObjectOf(psf, NULL, 1, &pidl_child, &IID_IContextMenu, NULL, (void **)&pcm);
4468 ok(hr == S_OK, "GetUIObjectOf() failed, hr %#lx.\n", hr);
4469 test_contextmenu(pcm, FALSE);
4470 IContextMenu_Release(pcm);
4472 /* Background menu */
4473 hr = IShellFolder_GetUIObjectOf(psf_desktop, NULL, 0, NULL, &IID_IContextMenu, NULL, (void **)&pcm);
4474 ok(hr == S_OK, "GetUIObjectOf() failed, hr %#lx.\n", hr);
4475 test_contextmenu(pcm, TRUE);
4476 IContextMenu_Release(pcm);
4478 IShellFolder_Release(psf);
4479 ILFree(pidl);
4481 IShellFolder_Release(psf_desktop);
4482 Cleanup();
4485 static void test_CreateViewObject_contextmenu(void)
4487 IShellFolder *desktop;
4488 IShellFolder *folder;
4489 IContextMenu *cmenu;
4490 WCHAR path[MAX_PATH];
4491 LPITEMIDLIST pidl;
4492 HRESULT hr;
4493 DWORD ret;
4494 int i;
4496 static const CLSID *folders[] =
4498 &CLSID_MyComputer,
4499 &CLSID_MyDocuments,
4500 &CLSID_ControlPanel,
4501 &CLSID_NetworkPlaces,
4502 &CLSID_Printers,
4503 &CLSID_RecycleBin
4506 for (i = 0; i < ARRAY_SIZE(folders); i++)
4508 hr = CoCreateInstance(folders[i], NULL, CLSCTX_INPROC_SERVER, &IID_IShellFolder, (void**)&folder);
4509 if (hr != S_OK)
4511 win_skip("Failed to create folder %s, hr %#lx.\n", wine_dbgstr_guid(folders[i]), hr);
4512 continue;
4515 hr = IShellFolder_CreateViewObject(folder, NULL, &IID_IContextMenu, (void**)&cmenu);
4516 if (IsEqualIID(folders[i], &CLSID_MyDocuments))
4517 ok(hr == S_OK, "got 0x%08lx\n", hr);
4518 else if (IsEqualIID(folders[i], &CLSID_MyComputer))
4519 ok(hr == S_OK || broken(hr == E_NOINTERFACE /* win10 */), "got 0x%08lx\n", hr);
4520 else
4521 ok(hr == E_NOINTERFACE || broken(FAILED(hr)), "got 0x%08lx for %s\n", hr, wine_dbgstr_guid(folders[i]));
4522 if (SUCCEEDED(hr))
4523 IContextMenu_Release(cmenu);
4524 IShellFolder_Release(folder);
4527 hr = SHGetDesktopFolder(&desktop);
4528 ok(hr == S_OK, "got 0x%08lx\n", hr);
4529 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IContextMenu, (void**)&cmenu);
4530 ok(hr == S_OK, "got 0x%08lx\n", hr);
4531 if (SUCCEEDED(hr))
4532 IContextMenu_Release(cmenu);
4533 ret = GetCurrentDirectoryW(MAX_PATH, path);
4534 ok(ret, "got %ld\n", GetLastError());
4535 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &pidl, 0);
4536 ok(hr == S_OK, "got 0x%08lx\n", hr);
4537 hr = IShellFolder_BindToObject(desktop, pidl, NULL, &IID_IShellFolder, (void**)&folder);
4538 ok(hr == S_OK, "got 0x%08lx\n", hr);
4539 hr = IShellFolder_CreateViewObject(folder, NULL, &IID_IContextMenu, (void**)&cmenu);
4540 ok(hr == S_OK, "got 0x%08lx\n", hr);
4541 if (SUCCEEDED(hr))
4542 IContextMenu_Release(cmenu);
4543 IShellFolder_Release(folder);
4544 ILFree(pidl);
4545 IShellFolder_Release(desktop);
4548 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
4549 static void r_verify_pidl(unsigned l, LPCITEMIDLIST pidl, const WCHAR *path)
4551 LPCITEMIDLIST child;
4552 IShellFolder *parent;
4553 STRRET filename;
4554 HRESULT hr;
4556 if(path){
4557 if(!pidl){
4558 ok_(__FILE__,l)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path));
4559 return;
4562 hr = SHBindToParent(pidl, &IID_IShellFolder, (void **)&parent, &child);
4563 ok_(__FILE__,l)(hr == S_OK, "SHBindToParent failed: 0x%08lx\n", hr);
4564 if(FAILED(hr))
4565 return;
4567 hr = IShellFolder_GetDisplayNameOf(parent, child, SHGDN_FORPARSING, &filename);
4568 ok_(__FILE__,l)(hr == S_OK, "GetDisplayNameOf failed: 0x%08lx\n", hr);
4569 if(FAILED(hr)){
4570 IShellFolder_Release(parent);
4571 return;
4574 ok_(__FILE__,l)(filename.uType == STRRET_WSTR || filename.uType == STRRET_CSTR,
4575 "Got unexpected string type: %d\n", filename.uType);
4576 if(filename.uType == STRRET_WSTR){
4577 ok_(__FILE__,l)(lstrcmpW(path, U(filename).pOleStr) == 0,
4578 "didn't get expected path (%s), instead: %s\n",
4579 wine_dbgstr_w(path), wine_dbgstr_w(U(filename).pOleStr));
4580 SHFree(U(filename).pOleStr);
4582 else if(filename.uType == STRRET_CSTR)
4584 WCHAR *strW = make_wstr(U(filename).cStr);
4585 ok_(__FILE__,l)(!lstrcmpW(path, strW), "didn't get expected path (%s), instead: %s\n",
4586 wine_dbgstr_w(path), U(filename).cStr);
4587 heap_free(strW);
4590 IShellFolder_Release(parent);
4591 }else
4592 ok_(__FILE__,l)(pidl == NULL, "Expected PIDL to be NULL\n");
4595 static void test_SHSimpleIDListFromPath(void)
4597 const WCHAR adirW[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4598 const CHAR adirA[] = "C:\\sidlfpdir";
4599 BOOL br, is_unicode = !(GetVersion() & 0x80000000);
4601 LPITEMIDLIST pidl = NULL;
4603 br = CreateDirectoryA(adirA, NULL);
4604 ok(br == TRUE, "CreateDirectory failed: %ld\n", GetLastError());
4606 if(is_unicode)
4607 pidl = SHSimpleIDListFromPath(adirW);
4608 else
4609 pidl = SHSimpleIDListFromPath((const WCHAR *)adirA);
4610 verify_pidl(pidl, adirW);
4611 ILFree(pidl);
4613 br = RemoveDirectoryA(adirA);
4614 ok(br == TRUE, "RemoveDirectory failed: %ld\n", GetLastError());
4616 if(is_unicode)
4617 pidl = SHSimpleIDListFromPath(adirW);
4618 else
4619 pidl = SHSimpleIDListFromPath((const WCHAR *)adirA);
4620 verify_pidl(pidl, adirW);
4621 ILFree(pidl);
4624 /* IFileSystemBindData impl */
4625 static HRESULT WINAPI fsbd_QueryInterface(IFileSystemBindData *fsbd,
4626 REFIID riid, void **ppv)
4628 if(IsEqualIID(riid, &IID_IFileSystemBindData) ||
4629 IsEqualIID(riid, &IID_IUnknown)){
4630 *ppv = fsbd;
4631 return S_OK;
4633 return E_NOINTERFACE;
4636 static ULONG WINAPI fsbd_AddRef(IFileSystemBindData *fsbd)
4638 return 2;
4641 static ULONG WINAPI fsbd_Release(IFileSystemBindData *fsbd)
4643 return 1;
4646 static HRESULT WINAPI fsbd_SetFindData(IFileSystemBindData *fsbd,
4647 const WIN32_FIND_DATAW *pfd)
4649 ok(0, "SetFindData called\n");
4650 return E_NOTIMPL;
4653 static HRESULT WINAPI fsbd_GetFindData_nul(IFileSystemBindData *fsbd,
4654 WIN32_FIND_DATAW *pfd)
4656 memset(pfd, 0, sizeof(WIN32_FIND_DATAW));
4657 return S_OK;
4660 static HRESULT WINAPI fsbd_GetFindData_junk(IFileSystemBindData *fsbd,
4661 WIN32_FIND_DATAW *pfd)
4663 memset(pfd, 0xef, sizeof(WIN32_FIND_DATAW));
4664 return S_OK;
4667 static HRESULT WINAPI fsbd_GetFindData_invalid(IFileSystemBindData *fsbd,
4668 WIN32_FIND_DATAW *pfd)
4670 memset(pfd, 0, sizeof(WIN32_FIND_DATAW));
4671 *pfd->cFileName = 'a';
4672 *pfd->cAlternateFileName = 'a';
4673 return S_OK;
4676 static HRESULT WINAPI fsbd_GetFindData_valid(IFileSystemBindData *fsbd,
4677 WIN32_FIND_DATAW *pfd)
4679 static const WCHAR adirW[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4680 HANDLE handle = FindFirstFileW(adirW, pfd);
4681 FindClose(handle);
4682 return S_OK;
4685 static HRESULT WINAPI fsbd_GetFindData_fail(IFileSystemBindData *fsbd,
4686 WIN32_FIND_DATAW *pfd)
4688 return E_FAIL;
4691 static IFileSystemBindDataVtbl fsbdVtbl = {
4692 fsbd_QueryInterface,
4693 fsbd_AddRef,
4694 fsbd_Release,
4695 fsbd_SetFindData,
4696 NULL
4699 static IFileSystemBindData fsbd = { &fsbdVtbl };
4701 static void test_ParseDisplayNamePBC(void)
4703 WCHAR wFileSystemBindData[] =
4704 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4705 WCHAR adirW[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4706 WCHAR afileW[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4707 WCHAR afile2W[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4708 const HRESULT exp_err = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4710 IShellFolder *psf;
4711 IBindCtx *pbc;
4712 HRESULT hres;
4713 ITEMIDLIST *pidl;
4715 /* Check if we support WCHAR functions */
4716 SetLastError(0xdeadbeef);
4717 lstrcmpiW(adirW, adirW);
4718 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED){
4719 win_skip("Most W-calls are not implemented\n");
4720 return;
4723 hres = SHGetDesktopFolder(&psf);
4724 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08lx\n", hres);
4725 if(FAILED(hres)){
4726 win_skip("Failed to get IShellFolder, can't run tests\n");
4727 return;
4730 /* fails on unknown dir with no IBindCtx */
4731 hres = IShellFolder_ParseDisplayName(psf, NULL, NULL, adirW, NULL, &pidl, NULL);
4732 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08lx\n", hres);
4733 hres = IShellFolder_ParseDisplayName(psf, NULL, NULL, afileW, NULL, &pidl, NULL);
4734 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08lx\n", hres);
4735 hres = IShellFolder_ParseDisplayName(psf, NULL, NULL, afile2W, NULL, &pidl, NULL);
4736 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08lx\n", hres);
4738 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4739 hres = CreateBindCtx(0, &pbc);
4740 ok(hres == S_OK, "CreateBindCtx failed: 0x%08lx\n", hres);
4742 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL);
4743 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08lx\n", hres);
4744 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL);
4745 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08lx\n", hres);
4746 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL);
4747 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08lx\n", hres);
4749 /* unknown dir with IBindCtx with IFileSystemBindData */
4750 hres = IBindCtx_RegisterObjectParam(pbc, wFileSystemBindData, (IUnknown*)&fsbd);
4751 ok(hres == S_OK, "RegisterObjectParam failed: 0x%08lx\n", hres);
4753 /* return E_FAIL from GetFindData */
4754 pidl = (ITEMIDLIST*)0xdeadbeef;
4755 fsbdVtbl.GetFindData = fsbd_GetFindData_fail;
4756 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL);
4757 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4758 if(SUCCEEDED(hres)){
4759 verify_pidl(pidl, adirW);
4760 ILFree(pidl);
4763 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL);
4764 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4765 if(SUCCEEDED(hres)){
4766 verify_pidl(pidl, afileW);
4767 ILFree(pidl);
4770 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL);
4771 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4772 if(SUCCEEDED(hres)){
4773 verify_pidl(pidl, afile2W);
4774 ILFree(pidl);
4777 /* set FIND_DATA struct to NULLs */
4778 pidl = (ITEMIDLIST*)0xdeadbeef;
4779 fsbdVtbl.GetFindData = fsbd_GetFindData_nul;
4780 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL);
4781 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4782 if(SUCCEEDED(hres)){
4783 verify_pidl(pidl, adirW);
4784 ILFree(pidl);
4787 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL);
4788 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4789 if(SUCCEEDED(hres)){
4790 verify_pidl(pidl, afileW);
4791 ILFree(pidl);
4794 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL);
4795 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4796 if(SUCCEEDED(hres)){
4797 verify_pidl(pidl, afile2W);
4798 ILFree(pidl);
4801 /* set FIND_DATA struct to junk */
4802 pidl = (ITEMIDLIST*)0xdeadbeef;
4803 fsbdVtbl.GetFindData = fsbd_GetFindData_junk;
4804 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL);
4805 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4806 if(SUCCEEDED(hres)){
4807 verify_pidl(pidl, adirW);
4808 ILFree(pidl);
4811 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL);
4812 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4813 if(SUCCEEDED(hres)){
4814 verify_pidl(pidl, afileW);
4815 ILFree(pidl);
4818 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL);
4819 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4820 if(SUCCEEDED(hres)){
4821 verify_pidl(pidl, afile2W);
4822 ILFree(pidl);
4825 /* set FIND_DATA struct to invalid data */
4826 pidl = (ITEMIDLIST*)0xdeadbeef;
4827 fsbdVtbl.GetFindData = fsbd_GetFindData_invalid;
4828 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL);
4829 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4830 if(SUCCEEDED(hres)){
4831 verify_pidl(pidl, adirW);
4832 ILFree(pidl);
4835 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL);
4836 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4837 if(SUCCEEDED(hres)){
4838 verify_pidl(pidl, afileW);
4839 ILFree(pidl);
4842 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL);
4843 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4844 if(SUCCEEDED(hres)){
4845 verify_pidl(pidl, afile2W);
4846 ILFree(pidl);
4849 /* set FIND_DATA struct to valid data */
4850 pidl = (ITEMIDLIST*)0xdeadbeef;
4851 fsbdVtbl.GetFindData = fsbd_GetFindData_valid;
4852 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL);
4853 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4854 if(SUCCEEDED(hres)){
4855 verify_pidl(pidl, adirW);
4856 ILFree(pidl);
4859 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL);
4860 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4861 if(SUCCEEDED(hres)){
4862 verify_pidl(pidl, afileW);
4863 ILFree(pidl);
4866 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL);
4867 ok(hres == S_OK, "ParseDisplayName failed: 0x%08lx\n", hres);
4868 if(SUCCEEDED(hres)){
4869 verify_pidl(pidl, afile2W);
4870 ILFree(pidl);
4873 IBindCtx_Release(pbc);
4874 IShellFolder_Release(psf);
4877 static const CHAR testwindow_class[] = "testwindow";
4878 #define WM_USER_NOTIFY (WM_APP+1)
4880 struct ChNotifyTest {
4881 const char id[256];
4882 const UINT notify_count;
4883 UINT missing_events;
4884 UINT signal;
4885 const char path_1[256];
4886 const char path_2[256];
4887 } chnotify_tests[] = {
4888 {"MKDIR", 1, 0, SHCNE_MKDIR, "C:\\shell32_cn_test\\test", ""},
4889 {"CREATE", 1, 0, SHCNE_CREATE, "C:\\shell32_cn_test\\test\\file.txt", ""},
4890 {"RMDIR", 1, 0, SHCNE_RMDIR, "C:\\shell32_cn_test\\test", ""},
4893 struct ChNotifyTest *exp_data;
4894 BOOL test_new_delivery_flag;
4896 static LRESULT CALLBACK testwindow_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4898 LONG signal = (LONG)lparam;
4900 switch(msg){
4901 case WM_USER_NOTIFY:
4902 if(exp_data->missing_events > 0) {
4903 WCHAR *path1, *path2;
4904 LPITEMIDLIST *pidls = (LPITEMIDLIST*)wparam;
4905 HANDLE hLock = NULL;
4907 if(test_new_delivery_flag) {
4908 hLock = SHChangeNotification_Lock((HANDLE)wparam, lparam, &pidls, &signal);
4909 ok(hLock != NULL, "SHChangeNotification_Lock returned NULL\n");
4912 ok(exp_data->signal == signal,
4913 "%s: expected notification type %x, got: %lx\n",
4914 exp_data->id, exp_data->signal, signal);
4916 trace("verifying pidls for: %s\n", exp_data->id);
4917 path1 = make_wstr(exp_data->path_1);
4918 path2 = make_wstr(exp_data->path_2);
4919 verify_pidl(pidls[0], path1);
4920 verify_pidl(pidls[1], path2);
4921 heap_free(path1);
4922 heap_free(path2);
4924 exp_data->missing_events--;
4926 if(test_new_delivery_flag)
4927 SHChangeNotification_Unlock(hLock);
4928 }else
4929 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %lx)\n", signal);
4930 return 0;
4932 return DefWindowProcA(hwnd, msg, wparam, lparam);
4935 static void register_testwindow_class(void)
4937 WNDCLASSEXA cls;
4938 ATOM ret;
4940 ZeroMemory(&cls, sizeof(cls));
4941 cls.cbSize = sizeof(cls);
4942 cls.style = 0;
4943 cls.lpfnWndProc = testwindow_wndproc;
4944 cls.hInstance = GetModuleHandleA(NULL);
4945 cls.lpszClassName = testwindow_class;
4947 SetLastError(0);
4948 ret = RegisterClassExA(&cls);
4949 ok(ret != 0, "RegisterClassExA failed: %ld\n", GetLastError());
4952 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4953 * have to poll repeatedly for the message to appear */
4954 static void do_events(void)
4956 int c = 0;
4957 while (exp_data->missing_events && (c++ < 10)){
4958 MSG msg;
4959 while(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)){
4960 TranslateMessage(&msg);
4961 DispatchMessageA(&msg);
4963 if(exp_data->missing_events)
4964 Sleep(500);
4966 trace("%s: took %d tries\n", exp_data->id, c);
4969 static void test_SHChangeNotify(BOOL test_new_delivery)
4971 HWND wnd;
4972 ULONG notifyID, i;
4973 HRESULT hr;
4974 BOOL br, has_unicode;
4975 SHChangeNotifyEntry entries[1];
4976 const CHAR root_dirA[] = "C:\\shell32_cn_test";
4977 const WCHAR root_dirW[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4979 trace("SHChangeNotify tests (%x)\n", test_new_delivery);
4981 CreateDirectoryW(NULL, NULL);
4982 has_unicode = !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
4984 test_new_delivery_flag = test_new_delivery;
4985 if(!test_new_delivery)
4986 register_testwindow_class();
4988 wnd = CreateWindowExA(0, testwindow_class, testwindow_class, 0,
4989 CW_USEDEFAULT, CW_USEDEFAULT, 130, 105,
4990 NULL, NULL, GetModuleHandleA(NULL), 0);
4991 ok(wnd != NULL, "Failed to make a window\n");
4993 br = CreateDirectoryA(root_dirA, NULL);
4994 ok(br == TRUE, "CreateDirectory failed: %ld\n", GetLastError());
4996 entries[0].pidl = NULL;
4997 if(has_unicode)
4998 hr = SHILCreateFromPath(root_dirW, (LPITEMIDLIST*)&entries[0].pidl, 0);
4999 else
5000 hr = SHILCreateFromPath((const void *)root_dirA, (LPITEMIDLIST*)&entries[0].pidl, 0);
5001 ok(hr == S_OK, "SHILCreateFromPath failed: 0x%08lx\n", hr);
5002 entries[0].fRecursive = TRUE;
5004 notifyID = SHChangeNotifyRegister(wnd, !test_new_delivery ? SHCNRF_ShellLevel : SHCNRF_ShellLevel|SHCNRF_NewDelivery,
5005 SHCNE_ALLEVENTS, WM_USER_NOTIFY, 1, entries);
5006 ok(notifyID != 0, "Failed to register a window for change notifications\n");
5008 for (i = 0; i < ARRAY_SIZE(chnotify_tests); ++i)
5010 exp_data = chnotify_tests + i;
5012 exp_data->missing_events = exp_data->notify_count;
5013 SHChangeNotify(exp_data->signal, SHCNF_PATHA | SHCNF_FLUSH,
5014 exp_data->path_1[0] ? exp_data->path_1 : NULL,
5015 exp_data->path_2[0] ? exp_data->path_2 : NULL);
5016 do_events();
5017 ok(exp_data->missing_events == 0, "%s: Expected wndproc to be called\n", exp_data->id);
5019 if(has_unicode){
5020 WCHAR *path1, *path2;
5022 path1 = make_wstr(exp_data->path_1);
5023 path2 = make_wstr(exp_data->path_2);
5025 exp_data->missing_events = exp_data->notify_count;
5026 SHChangeNotify(exp_data->signal, SHCNF_PATHW | SHCNF_FLUSH, path1, path2);
5027 do_events();
5028 ok(exp_data->missing_events == 0, "%s: Expected wndproc to be called\n", exp_data->id);
5030 heap_free(path1);
5031 heap_free(path2);
5035 SHChangeNotifyDeregister(notifyID);
5036 DestroyWindow(wnd);
5038 ILFree((LPITEMIDLIST)entries[0].pidl);
5039 br = RemoveDirectoryA(root_dirA);
5040 ok(br == TRUE, "RemoveDirectory failed: %ld\n", GetLastError());
5043 static void test_SHCreateDefaultContextMenu(void)
5045 HKEY keys[16];
5046 WCHAR path[MAX_PATH];
5047 IShellFolder *desktop,*folder;
5048 IPersistFolder2 *persist;
5049 IContextMenu *cmenu;
5050 LONG status;
5051 LPITEMIDLIST pidlFolder, pidl_child, pidl;
5052 DEFCONTEXTMENU cminfo;
5053 HRESULT hr;
5054 UINT i;
5055 const WCHAR filename[] =
5056 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
5057 if(!pSHCreateDefaultContextMenu)
5059 win_skip("SHCreateDefaultContextMenu missing.\n");
5060 return;
5063 GetCurrentDirectoryW(MAX_PATH, path);
5064 if (!path[0])
5066 skip("GetCurrentDirectoryW returned an empty string.\n");
5067 return;
5069 lstrcatW(path, filename);
5070 SHGetDesktopFolder(&desktop);
5072 CreateFilesFolders();
5074 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &pidl, 0);
5075 ok(hr == S_OK, "Got 0x%08lx\n", hr);
5076 if(SUCCEEDED(hr))
5078 hr = SHBindToParent(pidl, &IID_IShellFolder, (void **)&folder, (const ITEMIDLIST **)&pidl_child);
5079 ok(hr == S_OK, "Got 0x%08lx\n", hr);
5081 IShellFolder_QueryInterface(folder,&IID_IPersistFolder2,(void**)&persist);
5082 IPersistFolder2_GetCurFolder(persist,&pidlFolder);
5083 IPersistFolder2_Release(persist);
5084 if(SUCCEEDED(hr))
5086 cminfo.hwnd=NULL;
5087 cminfo.pcmcb=NULL;
5088 cminfo.psf=folder;
5089 cminfo.pidlFolder=NULL;
5090 cminfo.apidl=(LPCITEMIDLIST*)&pidl_child;
5091 cminfo.cidl=1;
5092 cminfo.aKeys=NULL;
5093 cminfo.cKeys=0;
5094 cminfo.punkAssociationInfo=NULL;
5096 hr = pSHCreateDefaultContextMenu(&cminfo,&IID_IContextMenu,(void**)&cmenu);
5097 ok(hr==S_OK,"Got 0x%08lx\n", hr);
5098 test_contextmenu_qi(cmenu, TRUE);
5099 IContextMenu_Release(cmenu);
5101 cminfo.pidlFolder=pidlFolder;
5102 hr = pSHCreateDefaultContextMenu(&cminfo,&IID_IContextMenu,(void**)&cmenu);
5103 ok(hr==S_OK,"Got 0x%08lx\n", hr);
5104 test_contextmenu_qi(cmenu, TRUE);
5105 IContextMenu_Release(cmenu);
5107 status = RegOpenKeyExA(HKEY_CLASSES_ROOT,"*",0,KEY_READ,keys);
5108 if(status==ERROR_SUCCESS){
5109 for(i=1;i<16;i++)
5110 keys[i]=keys[0];
5111 cminfo.aKeys=keys;
5112 cminfo.cKeys=16;
5113 hr = pSHCreateDefaultContextMenu(&cminfo,&IID_IContextMenu,(void**)&cmenu);
5114 RegCloseKey(keys[0]);
5115 ok(hr==S_OK,"Got 0x%08lx\n", hr);
5116 IContextMenu_Release(cmenu);
5119 ILFree(pidlFolder);
5120 IShellFolder_Release(folder);
5122 IShellFolder_Release(desktop);
5123 ILFree(pidl);
5124 Cleanup();
5127 static void test_DataObject(void)
5129 IShellFolder *desktop;
5130 IDataObject *data_obj;
5131 HRESULT hres;
5132 IEnumIDList *peidl;
5133 LPITEMIDLIST apidl;
5134 FORMATETC fmt;
5135 DWORD cf_shellidlist;
5136 STGMEDIUM medium;
5138 SHGetDesktopFolder(&desktop);
5140 hres = IShellFolder_EnumObjects(desktop, NULL,
5141 SHCONTF_NONFOLDERS|SHCONTF_FOLDERS|SHCONTF_INCLUDEHIDDEN, &peidl);
5142 ok(hres == S_OK, "got %lx\n", hres);
5144 if(IEnumIDList_Next(peidl, 1, &apidl, NULL) != S_OK) {
5145 skip("no files on desktop - skipping GetDataObject tests\n");
5146 IEnumIDList_Release(peidl);
5147 IShellFolder_Release(desktop);
5148 return;
5150 IEnumIDList_Release(peidl);
5152 hres = IShellFolder_GetUIObjectOf(desktop, NULL, 1, (LPCITEMIDLIST*)&apidl,
5153 &IID_IDataObject, NULL, (void**)&data_obj);
5154 ok(hres == S_OK, "got %lx\n", hres);
5155 ILFree(apidl);
5156 IShellFolder_Release(desktop);
5158 cf_shellidlist = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
5159 fmt.cfFormat = cf_shellidlist;
5160 fmt.ptd = NULL;
5161 fmt.dwAspect = DVASPECT_CONTENT;
5162 fmt.lindex = -1;
5163 fmt.tymed = TYMED_HGLOBAL;
5164 hres = IDataObject_QueryGetData(data_obj, &fmt);
5165 ok(hres == S_OK, "got %lx\n", hres);
5167 fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM;
5168 hres = IDataObject_QueryGetData(data_obj, &fmt);
5169 ok(hres == S_OK, "got %lx\n", hres);
5171 fmt.tymed = TYMED_ISTREAM;
5172 hres = IDataObject_QueryGetData(data_obj, &fmt);
5173 todo_wine ok(hres == S_FALSE, "got %lx\n", hres);
5175 fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM;
5176 hres = IDataObject_GetData(data_obj, &fmt, &medium);
5177 ok(hres == S_OK, "got %lx\n", hres);
5178 ok(medium.tymed == TYMED_HGLOBAL, "medium.tymed = %lx\n", medium.tymed);
5179 ReleaseStgMedium(&medium);
5181 IDataObject_Release(data_obj);
5184 static void test_GetDefaultColumn(void)
5186 static const CLSID *folders[] =
5188 &CLSID_MyComputer,
5189 &CLSID_MyDocuments,
5190 &CLSID_ControlPanel,
5191 &CLSID_NetworkPlaces,
5192 &CLSID_Printers,
5193 &CLSID_RecycleBin,
5194 &CLSID_ShellDesktop,
5196 HRESULT hr;
5197 int i;
5199 CoInitialize(NULL);
5201 for (i = 0; i < ARRAY_SIZE(folders); i++)
5203 IShellFolder2 *folder;
5204 ULONG sort, display;
5206 hr = CoCreateInstance(folders[i], NULL, CLSCTX_INPROC_SERVER, &IID_IShellFolder2, (void **)&folder);
5207 if (hr != S_OK)
5209 win_skip("Failed to create folder %s, hr %#lx.\n", wine_dbgstr_guid(folders[i]), hr);
5210 continue;
5213 hr = IShellFolder2_GetDefaultColumn(folder, 0, NULL, NULL);
5214 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5216 sort = display = 123;
5217 hr = IShellFolder2_GetDefaultColumn(folder, 0, &sort, &display);
5218 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5219 ok(sort == 123 && display == 123, "Unexpected default column.\n");
5221 display = 123;
5222 hr = IShellFolder2_GetDefaultColumn(folder, 0, NULL, &display);
5223 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5224 ok(display == 123, "Unexpected default column.\n");
5226 sort = 123;
5227 hr = IShellFolder2_GetDefaultColumn(folder, 0, &sort, NULL);
5228 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5229 ok(sort == 123, "Unexpected default column.\n");
5231 IShellFolder2_Release(folder);
5234 CoUninitialize();
5237 static void test_GetDefaultSearchGUID(void)
5239 static const CLSID *folders[] =
5241 &CLSID_MyComputer,
5242 &CLSID_MyDocuments,
5243 &CLSID_ControlPanel,
5244 &CLSID_NetworkPlaces,
5245 &CLSID_Printers,
5246 &CLSID_RecycleBin,
5247 &CLSID_ShellDesktop,
5249 HRESULT hr;
5250 int i;
5252 CoInitialize(NULL);
5254 for (i = 0; i < ARRAY_SIZE(folders); i++)
5256 IShellFolder2 *folder;
5257 GUID guid;
5259 hr = CoCreateInstance(folders[i], NULL, CLSCTX_INPROC_SERVER, &IID_IShellFolder2, (void **)&folder);
5260 if (hr != S_OK)
5262 win_skip("Failed to create folder %s, hr %#lx.\n", wine_dbgstr_guid(folders[i]), hr);
5263 continue;
5266 if (0)
5268 /* crashes on XP */
5269 hr = IShellFolder2_GetDefaultSearchGUID(folder, NULL);
5270 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5273 memcpy(&guid, &CLSID_MyComputer, sizeof(guid));
5274 hr = IShellFolder2_GetDefaultSearchGUID(folder, &guid);
5275 ok(hr == E_NOTIMPL || broken(hr == S_OK) /* Method was last supported on XP */, "Unexpected hr %#lx.\n", hr);
5276 if (hr == E_NOTIMPL)
5277 ok(IsEqualGUID(&guid, &CLSID_MyComputer), "Unexpected guid %s.\n", wine_dbgstr_guid(&guid));
5279 IShellFolder2_Release(folder);
5282 CoUninitialize();
5285 static void test_SHLimitInputEdit(void)
5287 IShellFolder *desktop;
5288 HRESULT hr;
5289 HWND hwnd;
5291 hr = SHGetDesktopFolder(&desktop);
5292 ok(hr == S_OK, "Failed to get desktop folder, hr %#lx.\n", hr);
5294 hr = SHLimitInputEdit(NULL, desktop);
5295 todo_wine
5296 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5298 hwnd = CreateWindowA("EDIT", NULL, WS_VISIBLE, 0, 0, 100, 30, NULL, NULL, NULL, NULL);
5299 ok(hwnd != NULL, "Failed to create Edit control.\n");
5301 hr = SHLimitInputEdit(hwnd, desktop);
5302 todo_wine
5303 ok(hr == S_OK, "Failed to set input limits, hr %#lx.\n", hr);
5305 hr = SHLimitInputEdit(hwnd, desktop);
5306 todo_wine
5307 ok(hr == S_OK, "Failed to set input limits, hr %#lx.\n", hr);
5309 DestroyWindow(hwnd);
5310 IShellFolder_Release(desktop);
5313 static void test_SHGetSetFolderCustomSettings(void)
5315 HRESULT hr;
5316 SHFOLDERCUSTOMSETTINGS fcs;
5317 WCHAR pathW[MAX_PATH];
5318 WCHAR bufferW[MAX_PATH];
5319 WCHAR iconpathW[MAX_PATH];
5320 static const WCHAR somedirW[] = {'s','o','m','e','_','d','i','r',0};
5321 static const WCHAR iconW[] = {'\\','s','o','m','e','_','i','c','o','n','.','i','c','o',0};
5322 static const WCHAR desktop_iniW[] = {'\\','D','e','s','k','t','o','p','.','i','n','i',0};
5324 if (!pSHGetSetFolderCustomSettings)
5326 win_skip("SHGetSetFolderCustomSetting is not available.\n");
5327 return;
5330 GetTempPathW(MAX_PATH, pathW);
5331 lstrcatW(pathW, somedirW);
5332 CreateDirectoryW(pathW, NULL);
5334 lstrcpyW(iconpathW, pathW);
5335 lstrcatW(iconpathW, iconW);
5337 memset(&fcs, 0, sizeof(fcs));
5338 fcs.dwSize = sizeof(fcs);
5339 fcs.dwMask = FCSM_ICONFILE;
5340 fcs.pszIconFile = iconpathW;
5342 hr = pSHGetSetFolderCustomSettings(&fcs, pathW, FCS_FORCEWRITE); /*creates and writes to a Desktop.ini*/
5343 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5345 memset(&fcs, 0, sizeof(fcs));
5346 fcs.dwSize = sizeof(fcs);
5347 fcs.dwMask = FCSM_ICONFILE;
5348 fcs.cchIconFile = MAX_PATH;
5349 fcs.pszIconFile = bufferW;
5350 bufferW[0] = 0;
5352 hr = pSHGetSetFolderCustomSettings(&fcs, pathW, FCS_READ);
5353 todo_wine ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5354 todo_wine ok(!lstrcmpiW(iconpathW, fcs.pszIconFile), "Expected %s, got %s\n", wine_dbgstr_w(iconpathW), wine_dbgstr_w(fcs.pszIconFile));
5356 hr = pSHGetSetFolderCustomSettings(&fcs, NULL, FCS_READ);
5357 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
5359 lstrcpyW(bufferW, pathW);
5360 lstrcatW(bufferW, desktop_iniW);
5361 DeleteFileW(bufferW);
5362 RemoveDirectoryW(pathW);
5365 START_TEST(shlfolder)
5367 init_function_pointers();
5368 /* if OleInitialize doesn't get called, ParseDisplayName returns
5369 CO_E_NOTINITIALIZED for malformed directory names */
5370 OleInitialize(NULL);
5372 test_ParseDisplayName();
5373 test_SHParseDisplayName();
5374 test_BindToObject();
5375 test_EnumObjects_and_CompareIDs();
5376 test_GetDisplayName();
5377 test_GetAttributesOf();
5378 test_SHGetPathFromIDList();
5379 test_CallForAttributes();
5380 test_FolderShortcut();
5381 test_ITEMIDLIST_format();
5382 test_SHGetFolderPathA();
5383 test_SHGetFolderPathAndSubDirA();
5384 test_LocalizedNames();
5385 test_SHCreateShellItem();
5386 test_SHCreateShellItemArray();
5387 test_ShellItemArrayEnumItems();
5388 test_desktop_IPersist();
5389 test_GetUIObject();
5390 test_CreateViewObject_contextmenu();
5391 test_SHSimpleIDListFromPath();
5392 test_ParseDisplayNamePBC();
5393 test_SHGetNameFromIDList();
5394 test_SHGetItemFromDataObject();
5395 test_SHGetIDListFromObject();
5396 test_SHGetItemFromObject();
5397 test_ShellItemCompare();
5398 test_SHChangeNotify(FALSE);
5399 test_SHChangeNotify(TRUE);
5400 test_ShellItemBindToHandler();
5401 test_ShellItemGetAttributes();
5402 test_ShellItemArrayGetAttributes();
5403 test_SHCreateDefaultContextMenu();
5404 test_DataObject();
5405 test_GetDefaultColumn();
5406 test_GetDefaultSearchGUID();
5407 test_SHLimitInputEdit();
5408 test_SHGetSetFolderCustomSettings();
5410 OleUninitialize();