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
40 #include "wine/heap.h"
41 #include "wine/test.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);
49 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
50 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
51 static HRESULT (WINAPI
*pSHCreateItemFromRelativeName
)(IShellItem
*,PCWSTR
,IBindCtx
*,REFIID
,void**);
52 static HRESULT (WINAPI
*pSHCreateItemInKnownFolder
)(REFKNOWNFOLDERID
,DWORD
,PCWSTR
,REFIID
,void **);
53 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
54 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
55 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromIDLists
)(UINT
, PCIDLIST_ABSOLUTE
*, IShellItemArray
**);
56 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
57 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
58 static HRESULT (WINAPI
*pSHGetKnownFolderPath
)(REFKNOWNFOLDERID
,DWORD
,HANDLE
,PWSTR
*);
59 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
60 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
61 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
62 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
63 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
64 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
65 static BOOL (WINAPI
*pSHGetPathFromIDListEx
)(PCIDLIST_ABSOLUTE
,WCHAR
*,DWORD
,GPFIDL_FLAGS
);
67 typedef SHFOLDERCUSTOMSETTINGSW SHFOLDERCUSTOMSETTINGS
, *LPSHFOLDERCUSTOMSETTINGS
;
69 static HRESULT (WINAPI
*pSHGetSetFolderCustomSettings
)(LPSHFOLDERCUSTOMSETTINGS
,PCWSTR
,DWORD
);
71 static WCHAR
*make_wstr(const char *str
)
79 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
83 ret
= heap_alloc(len
* sizeof(WCHAR
));
87 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
91 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
94 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
95 return lstrcmpA(stra
, buf
);
98 static void init_function_pointers(void)
104 hmod
= GetModuleHandleA("shell32.dll");
106 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
107 MAKEFUNC(SHCreateItemFromIDList
);
108 MAKEFUNC(SHCreateItemFromParsingName
);
109 MAKEFUNC(SHCreateItemFromRelativeName
);
110 MAKEFUNC(SHCreateItemInKnownFolder
);
111 MAKEFUNC(SHCreateShellItem
);
112 MAKEFUNC(SHCreateShellItemArray
);
113 MAKEFUNC(SHCreateShellItemArrayFromIDLists
);
114 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
115 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
116 MAKEFUNC(SHGetKnownFolderPath
);
117 MAKEFUNC(SHGetNameFromIDList
);
118 MAKEFUNC(SHGetItemFromDataObject
);
119 MAKEFUNC(SHGetIDListFromObject
);
120 MAKEFUNC(SHGetItemFromObject
);
121 MAKEFUNC(SHCreateDefaultContextMenu
);
122 MAKEFUNC(SHGetPathFromIDListEx
);
123 MAKEFUNC(SHGetSetFolderCustomSettings
);
126 /* test named exports */
127 ptr
= GetProcAddress(hmod
, "ILFree");
128 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
131 #define TESTNAMED(f) \
132 ptr = (void*)GetProcAddress(hmod, #f); \
133 ok(ptr != 0, "expected named export for " #f "\n");
135 TESTNAMED(ILAppendID
);
137 TESTNAMED(ILCloneFirst
);
138 TESTNAMED(ILCombine
);
139 TESTNAMED(ILCreateFromPath
);
140 TESTNAMED(ILCreateFromPathA
);
141 TESTNAMED(ILCreateFromPathW
);
142 TESTNAMED(ILFindChild
);
143 TESTNAMED(ILFindLastID
);
144 TESTNAMED(ILGetNext
);
145 TESTNAMED(ILGetSize
);
146 TESTNAMED(ILIsEqual
);
147 TESTNAMED(ILIsParent
);
148 TESTNAMED(ILRemoveLastID
);
149 TESTNAMED(ILSaveToStream
);
153 hmod
= GetModuleHandleA("kernel32.dll");
154 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
156 hr
= SHGetMalloc(&ppM
);
157 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
160 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
161 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
165 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
171 if (lpszPath
[-1] != '\\')
182 WCHAR path
[MAX_PATH
];
186 {{'c',':','\\',0}, S_OK
},
187 {{'c',':','\\','\\',0}, E_INVALIDARG
, 1},
188 {{'c',':','\\','f','a','k','e',0}, 0x80070002}, /* ERROR_FILE_NOT_FOUND */
189 {{'c',':','f','a','k','e',0}, E_INVALIDARG
, 1},
190 {{'c',':','/',0}, E_INVALIDARG
, 1},
191 {{'c',':','\\','w','i','n','d','o','w','s',0}, S_OK
},
192 {{'c',':','\\','w','i','n','d','o','w','s','\\',0}, S_OK
},
193 {{'c',':','\\','w','i','n','d','o','w','s','\\','.',0}, E_INVALIDARG
, 1},
194 {{'c',':','\\','w','i','n','d','o','w','s','\\','.','.',0}, E_INVALIDARG
, 1},
195 {{'.',0}, E_INVALIDARG
, 1},
196 {{'.','.',0}, E_INVALIDARG
, 1},
197 {{'t','e','s','t',0}, 0x80070002},
198 {{'t','e','s','t','\\',0}, 0x80070002},
199 {{'s','u','b','\\','d','i','r',0}, 0x80070002},
200 {{'s','u','b','/','d','i','r',0}, E_INVALIDARG
, 1},
201 {{'h','t','t','p',':',0}, S_OK
, 1},
202 {{'h','t','t','p',':','t','e','s','t',0}, S_OK
, 1},
203 {{'h','t','t','p',':','\\','t','e','s','t',0}, S_OK
, 1},
204 {{'x','x',':',0}, S_OK
, 1},
207 static void test_ParseDisplayName(void)
209 static WCHAR testdirW
[] = {'p','a','r','s','e','t','e','s','t',0};
210 static WCHAR backslashW
[] = {'\\',0};
211 WCHAR buffer
[MAX_PATH
], buffer2
[MAX_PATH
];
212 IShellFolder
*desktop
;
218 hr
= SHGetDesktopFolder(&desktop
);
219 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
221 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, NULL
, NULL
, &pidl
, NULL
);
222 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
224 for (i
= 0; i
< ARRAY_SIZE(parse_tests
); i
++)
226 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, parse_tests
[i
].path
, NULL
, &pidl
, NULL
);
227 todo_wine_if(parse_tests
[i
].todo
)
228 ok(hr
== parse_tests
[i
].hr
, "%s: expected %#x, got %#x\n",
229 wine_dbgstr_w(parse_tests
[i
].path
), parse_tests
[i
].hr
, hr
);
234 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
235 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
236 * out it doesn't. The magic seems to happen in the file dialogs, then. */
238 bRes
= SHGetSpecialFolderPathW(NULL
, buffer
, CSIDL_PERSONAL
, FALSE
);
239 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
241 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, buffer
, NULL
, &pidl
, 0);
242 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
244 ok(ILFindLastID(pidl
)->mkid
.abID
[0] == 0x31,
245 "Last pidl should be of type PT_FOLDER, but is: %02x\n",
246 ILFindLastID(pidl
)->mkid
.abID
[0]);
249 /* Relative paths are interpreted relative to the desktop. */
250 GetTempPathW(ARRAY_SIZE(buffer
), buffer
);
251 GetLongPathNameW(buffer
, buffer
, ARRAY_SIZE(buffer
));
252 SetCurrentDirectoryW(buffer
);
253 CreateDirectoryW(testdirW
, NULL
);
255 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, testdirW
, NULL
, &pidl
, NULL
);
256 ok(hr
== 0x80070002, "got %#x\n", hr
);
258 RemoveDirectoryW(testdirW
);
260 hr
= SHGetSpecialFolderPathW(NULL
, buffer
, CSIDL_DESKTOP
, FALSE
);
261 ok(hr
== S_FALSE
, "got %#x\n", hr
);
262 SetCurrentDirectoryW(buffer
);
263 CreateDirectoryW(testdirW
, NULL
);
265 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, testdirW
, NULL
, &pidl
, NULL
);
266 ok(hr
== S_OK
, "got %#x\n", hr
);
268 ok(SHGetPathFromIDListW(pidl
, buffer2
), "SHGetPathFromIDList failed\n");
269 lstrcatW(buffer
, backslashW
);
270 lstrcatW(buffer
, testdirW
);
271 ok(!lstrcmpW(buffer
, buffer2
), "expected %s, got %s\n", wine_dbgstr_w(buffer
), wine_dbgstr_w(buffer2
));
273 RemoveDirectoryW(testdirW
);
276 IShellFolder_Release(desktop
);
279 /* creates a file with the specified name for tests */
280 static void CreateTestFile(const CHAR
*name
)
285 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
286 if (file
!= INVALID_HANDLE_VALUE
)
288 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
289 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
295 /* initializes the tests */
296 static void CreateFilesFolders(void)
298 CreateDirectoryA(".\\testdir", NULL
);
299 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
300 CreateTestFile (".\\testdir\\test1.txt ");
301 CreateTestFile (".\\testdir\\test2.txt ");
302 CreateTestFile (".\\testdir\\test3.txt ");
303 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
304 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
307 /* cleans after tests */
308 static void Cleanup(void)
310 DeleteFileA(".\\testdir\\test1.txt");
311 DeleteFileA(".\\testdir\\test2.txt");
312 DeleteFileA(".\\testdir\\test3.txt");
313 RemoveDirectoryA(".\\testdir\\test.txt");
314 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
315 RemoveDirectoryA(".\\testdir\\testdir2");
316 RemoveDirectoryA(".\\testdir");
321 static void test_EnumObjects(IShellFolder
*iFolder
)
323 IEnumIDList
*iEnumList
;
324 LPITEMIDLIST newPIDL
, idlArr
[10];
329 static const WORD iResults
[5][5] =
338 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
339 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
340 static const ULONG attrs
[5] =
342 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
343 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
344 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
345 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
346 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
348 static const ULONG full_attrs
[5] =
350 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
351 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
352 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
353 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
354 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
357 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
358 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
360 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
361 * the filesystem shellfolders return S_OK even if less than 'celt' items are
362 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
363 * only ever returns a single entry per call. */
364 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
366 ok (i
== 5, "i: %d\n", i
);
368 hr
= IEnumIDList_Release(iEnumList
);
369 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
371 /* Sort them first in case of wrong order from system */
372 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
373 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
376 idlArr
[i
] = idlArr
[j
];
380 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
382 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
383 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
387 for (i
= 0; i
< 5; i
++)
390 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
391 /* Native returns all flags no matter what we ask for */
392 flags
= SFGAO_CANCOPY
;
393 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
394 flags
&= SFGAO_testfor
;
395 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
396 ok(flags
== (attrs
[i
]) ||
397 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
398 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
400 flags
= SFGAO_testfor
;
401 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
402 flags
&= SFGAO_testfor
;
403 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
404 ok(flags
== attrs
[i
], "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
407 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
408 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
409 ok((flags
& ~(SFGAO_HASSUBFOLDER
|SFGAO_COMPRESSED
)) == full_attrs
[i
], "%d: got %08x expected %08x\n", i
, flags
, full_attrs
[i
]);
413 IMalloc_Free(ppM
, idlArr
[i
]);
416 static void test_BindToObject(void)
420 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
421 SHITEMID emptyitem
= { 0, { 0 } };
422 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
423 WCHAR wszSystemDir
[MAX_PATH
];
424 char szSystemDir
[MAX_PATH
];
426 WCHAR path
[MAX_PATH
];
427 CHAR pathA
[MAX_PATH
];
429 WCHAR wszMyComputer
[] = {
430 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
431 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
432 static const CHAR filename_html
[] = "winetest.html";
433 static const CHAR filename_txt
[] = "winetest.txt";
434 static const CHAR filename_foo
[] = "winetest.foo";
436 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
437 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
439 hr
= SHGetDesktopFolder(&psfDesktop
);
440 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
441 if (hr
!= S_OK
) return;
443 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
444 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
446 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
447 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
449 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
450 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
452 IShellFolder_Release(psfDesktop
);
456 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
457 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
458 IShellFolder_Release(psfDesktop
);
459 IMalloc_Free(ppM
, pidlMyComputer
);
460 if (hr
!= S_OK
) return;
462 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
463 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
465 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
466 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
468 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
469 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
470 if (cChars
== 0 || cChars
>= MAX_PATH
) {
471 IShellFolder_Release(psfMyComputer
);
474 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
476 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
477 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
479 IShellFolder_Release(psfMyComputer
);
483 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
484 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
485 IShellFolder_Release(psfMyComputer
);
486 IMalloc_Free(ppM
, pidlSystemDir
);
487 if (hr
!= S_OK
) return;
489 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
490 ok (hr
== E_INVALIDARG
,
491 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
493 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
494 ok (hr
== E_INVALIDARG
,
495 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
497 IShellFolder_Release(psfSystemDir
);
499 cChars
= GetCurrentDirectoryA(MAX_PATH
, buf
);
502 skip("Failed to get current directory, skipping tests.\n");
505 if(buf
[cChars
-1] != '\\') lstrcatA(buf
, "\\");
507 SHGetDesktopFolder(&psfDesktop
);
509 /* Attempt BindToObject on files. */
512 lstrcpyA(pathA
, buf
);
513 lstrcatA(pathA
, filename_html
);
514 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
515 if(hfile
!= INVALID_HANDLE_VALUE
)
518 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
519 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
520 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
523 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
525 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
530 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
531 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
535 hr
= IPersist_GetClassID(pp
, &id
);
536 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
537 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
), "Unexpected classid %s\n", wine_dbgstr_guid(&id
));
538 IPersist_Release(pp
);
541 IShellFolder_Release(psfChild
);
548 win_skip("Failed to create .html testfile.\n");
551 lstrcpyA(pathA
, buf
);
552 lstrcatA(pathA
, filename_txt
);
553 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
554 if(hfile
!= INVALID_HANDLE_VALUE
)
557 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
558 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
559 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
562 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
563 ok(hr
== E_FAIL
|| /* Vista+ */
564 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
566 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
572 win_skip("Failed to create .txt testfile.\n");
575 lstrcpyA(pathA
, buf
);
576 lstrcatA(pathA
, filename_foo
);
577 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
578 if(hfile
!= INVALID_HANDLE_VALUE
)
581 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
582 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
583 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
586 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
587 ok(hr
== E_FAIL
|| /* Vista+ */
588 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
590 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
596 win_skip("Failed to create .foo testfile.\n");
598 /* And on the desktop */
599 SHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
600 lstrcatA(pathA
, "\\");
601 lstrcatA(pathA
, filename_html
);
602 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
605 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
606 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
607 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
609 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void **)&psfChild
);
611 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
613 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
615 if(!DeleteFileA(pathA
))
616 trace("Failed to delete: %d\n", GetLastError());
618 SHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
619 lstrcatA(pathA
, "\\");
620 lstrcatA(pathA
, filename_foo
);
621 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
624 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
625 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
626 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
628 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void **)&psfChild
);
629 ok(hr
== E_FAIL
|| /* Vista+ */
630 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
632 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
636 IShellFolder_Release(psfDesktop
);
639 static void test_GetDisplayName(void)
644 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
645 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
648 LPSHELLFOLDER psfDesktop
, psfPersonal
;
650 SHITEMID emptyitem
= { 0, { 0 } };
651 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
652 LPCITEMIDLIST pidlLast
;
653 static const CHAR szFileName
[] = "winetest.foo";
654 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
655 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
657 /* It's ok to use this fixed path. Call will fail anyway. */
658 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
659 LPITEMIDLIST pidlNew
;
661 /* I'm trying to figure if there is a functional difference between calling
662 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
663 * binding to the shellfolder. One thing I thought of was that perhaps
664 * SHGetPathFromIDListW would be able to get the path to a file, which does
665 * not exist anymore, while the other method wouldn't. It turns out there's
666 * no functional difference in this respect.
669 /* First creating a directory in MyDocuments and a file in this directory. */
670 result
= SHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
671 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
674 /* Use ANSI file functions so this works on Windows 9x */
675 lstrcatA(szTestDir
, "\\winetest");
676 CreateDirectoryA(szTestDir
, NULL
);
677 attr
=GetFileAttributesA(szTestDir
);
678 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
680 ok(0, "unable to create the '%s' directory\n", szTestDir
);
684 lstrcpyA(szTestFile
, szTestDir
);
685 lstrcatA(szTestFile
, "\\");
686 lstrcatA(szTestFile
, szFileName
);
687 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
688 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
689 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
690 CloseHandle(hTestFile
);
692 /* Getting an itemidlist for the file. */
693 hr
= SHGetDesktopFolder(&psfDesktop
);
694 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
695 if (hr
!= S_OK
) return;
697 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
699 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
700 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
702 IShellFolder_Release(psfDesktop
);
706 pidlLast
= ILFindLastID(pidlTestFile
);
707 ok(pidlLast
->mkid
.cb
>= 76, "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
708 if (pidlLast
->mkid
.cb
>= 28) {
709 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
710 "Filename should be stored as ansi-string at this position!\n");
712 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
713 if (pidlLast
->mkid
.cb
>= 76) {
714 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
715 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
716 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)) || /* Win7 */
717 (pidlLast
->mkid
.cb
>= 102 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[72], wszFileName
)), /* Win8 */
718 "Filename should be stored as wchar-string at this position!\n");
721 /* It seems as if we cannot bind to regular files on windows, but only directories.
723 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
724 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
725 hr
== E_NOTIMPL
, /* Vista */
728 IUnknown_Release(psfFile
);
731 /* Some tests for IShellFolder::SetNameOf */
732 hr
= SHBindToParent(pidlTestFile
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
733 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
735 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
736 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
737 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
739 ok (((ITEMIDLIST
*)((BYTE
*)pidlNew
+ pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
740 "pidl returned from SetNameOf should be simple!\n");
742 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
743 * is implemented on top of SHFileOperation in WinXP. */
744 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
, SHGDN_FORPARSING
, NULL
);
745 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
747 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
748 * SHGDN flags specify an absolute path. */
749 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
750 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
753 IShellFolder_Release(psfPersonal
);
755 /* Deleting the file and the directory */
756 DeleteFileA(szTestFile
);
757 RemoveDirectoryA(szTestDir
);
759 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
760 result
= SHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
761 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
762 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
764 /* SHBindToParent fails, if called with a NULL PIDL. */
765 hr
= SHBindToParent(NULL
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
766 ok (hr
== E_INVALIDARG
|| broken(hr
== E_OUTOFMEMORY
) /* XP */,
767 "SHBindToParent(NULL) should fail! hr = %08x\n", hr
);
769 /* But it succeeds with an empty PIDL. */
770 hr
= SHBindToParent(pidlEmpty
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
771 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
772 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
774 IShellFolder_Release(psfPersonal
);
776 /* Binding to the folder and querying the display name of the file also works. */
777 hr
= SHBindToParent(pidlTestFile
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
778 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
780 IShellFolder_Release(psfDesktop
);
784 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
785 * pidlTestFile (In accordance with MSDN). */
786 ok (ILFindLastID(pidlTestFile
) == pidlLast
,
787 "SHBindToParent doesn't return the last id of the pidl param!\n");
789 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
790 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
792 IShellFolder_Release(psfDesktop
);
793 IShellFolder_Release(psfPersonal
);
797 hr
= StrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
798 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
799 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
801 ILFree(pidlTestFile
);
802 IShellFolder_Release(psfDesktop
);
803 IShellFolder_Release(psfPersonal
);
806 static void test_CallForAttributes(void)
812 LPSHELLFOLDER psfDesktop
;
813 LPITEMIDLIST pidlMyDocuments
;
814 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
815 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
816 static const WCHAR wszCallForAttributes
[] = {
817 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
818 static const WCHAR wszMyDocumentsKey
[] = {
819 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
820 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
821 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
822 WCHAR wszMyDocuments
[] = {
823 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
824 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
826 /* For the root of a namespace extension, the attributes are not queried by binding
827 * to the object and calling GetAttributesOf. Instead, the attributes are read from
828 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
830 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
831 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
832 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
833 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
835 hr
= SHGetDesktopFolder(&psfDesktop
);
836 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
837 if (hr
!= S_OK
) return;
839 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
840 &pidlMyDocuments
, NULL
);
842 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
844 IShellFolder_Release(psfDesktop
);
848 dwAttributes
= 0xffffffff;
849 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
850 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
851 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
853 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
854 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
855 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
856 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
858 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
859 * key. So the test will return at this point, if run on wine.
861 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
862 ok (lResult
== ERROR_SUCCESS
||
863 lResult
== ERROR_ACCESS_DENIED
,
864 "RegOpenKeyEx failed! result: %08x\n", lResult
);
865 if (lResult
!= ERROR_SUCCESS
) {
866 if (lResult
== ERROR_ACCESS_DENIED
)
867 skip("Not enough rights to open the registry key\n");
868 IMalloc_Free(ppM
, pidlMyDocuments
);
869 IShellFolder_Release(psfDesktop
);
873 /* Query MyDocuments' Attributes value, to be able to restore it later. */
874 dwSize
= sizeof(DWORD
);
875 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
876 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
877 if (lResult
!= ERROR_SUCCESS
) {
879 IMalloc_Free(ppM
, pidlMyDocuments
);
880 IShellFolder_Release(psfDesktop
);
884 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
885 dwSize
= sizeof(DWORD
);
886 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
887 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
888 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
889 if (lResult
!= ERROR_SUCCESS
) {
891 IMalloc_Free(ppM
, pidlMyDocuments
);
892 IShellFolder_Release(psfDesktop
);
896 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
897 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
898 * SFGAO_FILESYSTEM attributes. */
899 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
900 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
901 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
902 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
903 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
905 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
906 * GetAttributesOf. It seems that once there is a single attribute queried, for which
907 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
908 * the flags in Attributes are ignored.
910 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
911 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
912 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
913 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
915 ok (dwAttributes
== SFGAO_FILESYSTEM
,
916 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
919 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
920 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
921 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
922 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
924 IMalloc_Free(ppM
, pidlMyDocuments
);
925 IShellFolder_Release(psfDesktop
);
928 static void test_GetAttributesOf(void)
931 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
932 SHITEMID emptyitem
= { 0, { 0 } };
933 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
934 LPITEMIDLIST pidlMyComputer
;
936 static const DWORD desktopFlags
= SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
|
937 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
;
938 static const DWORD myComputerFlags
= SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
|
939 SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
940 WCHAR wszMyComputer
[] = {
941 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
942 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
943 char cCurrDirA
[MAX_PATH
] = {0};
944 WCHAR cCurrDirW
[MAX_PATH
];
945 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
946 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
950 hr
= SHGetDesktopFolder(&psfDesktop
);
951 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
952 if (hr
!= S_OK
) return;
954 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
955 dwFlags
= 0xffffffff;
956 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
957 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
958 ok (dwFlags
== desktopFlags
, "Wrong Desktop attributes: %08x\n", dwFlags
);
960 /* .. or with no itemidlist at all. */
961 dwFlags
= 0xffffffff;
962 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
963 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
964 ok (dwFlags
== desktopFlags
, "Wrong Desktop attributes: %08x\n", dwFlags
);
966 /* Testing the attributes of the MyComputer shellfolder */
967 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
968 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
970 IShellFolder_Release(psfDesktop
);
974 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
975 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
977 dwFlags
= 0xffffffff;
978 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
979 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
981 ok (dwFlags
== (myComputerFlags
| SFGAO_CANLINK
), "Wrong MyComputer attributes: %08x\n", dwFlags
);
983 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
984 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
985 IShellFolder_Release(psfDesktop
);
986 IMalloc_Free(ppM
, pidlMyComputer
);
987 if (hr
!= S_OK
) return;
989 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
991 ok (hr
== E_INVALIDARG
, "MyComputer->GetAttributesOf(empty pidl) should fail! hr = %08x\n", hr
);
993 dwFlags
= 0xffffffff;
994 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
995 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
997 ok (dwFlags
== myComputerFlags
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
999 IShellFolder_Release(psfMyComputer
);
1001 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1002 len
= lstrlenA(cCurrDirA
);
1005 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1008 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1009 cCurrDirA
[len
-1] = 0;
1011 /* create test directory */
1012 CreateFilesFolders();
1014 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1016 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1017 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1019 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1020 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1022 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1023 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1025 IMalloc_Free(ppM
, newPIDL
);
1027 /* get relative PIDL */
1028 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1029 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1031 /* test the shell attributes of the test directory using the relative PIDL */
1032 dwFlags
= SFGAO_FOLDER
;
1033 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1034 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1035 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1038 IMalloc_Free(ppM
, newPIDL
);
1040 /* append testdirectory name to path */
1041 if (cCurrDirA
[len
-1] == '\\')
1042 cCurrDirA
[len
-1] = 0;
1043 lstrcatA(cCurrDirA
, "\\testdir");
1044 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1046 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1047 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1049 /* test the shell attributes of the test directory using the absolute PIDL */
1050 dwFlags
= SFGAO_FOLDER
;
1051 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1052 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1053 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1056 IMalloc_Free(ppM
, newPIDL
);
1058 IShellFolder_Release(testIShellFolder
);
1062 IShellFolder_Release(IDesktopFolder
);
1065 static void test_SHGetPathFromIDList(void)
1067 SHITEMID emptyitem
= { 0, { 0 } };
1068 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1069 LPITEMIDLIST pidlMyComputer
;
1070 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1073 LPSHELLFOLDER psfDesktop
;
1074 WCHAR wszMyComputer
[] = {
1075 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1076 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1077 WCHAR wszFileName
[MAX_PATH
];
1078 LPITEMIDLIST pidlTestFile
;
1081 static WCHAR wszTestFile
[] = {
1082 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1083 LPITEMIDLIST pidlPrograms
;
1085 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1088 result
= SHGetPathFromIDListW(NULL
, wszPath
);
1089 ok(!result
, "Expected failure\n");
1090 ok(!wszPath
[0], "Expected empty string\n");
1092 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1093 result
= SHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1094 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1095 if (!result
) return;
1097 result
= SHGetPathFromIDListW(pidlEmpty
, wszPath
);
1098 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1099 if (!result
) return;
1100 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1102 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1103 hr
= SHGetDesktopFolder(&psfDesktop
);
1104 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1105 if (hr
!= S_OK
) return;
1107 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1108 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1110 IShellFolder_Release(psfDesktop
);
1114 SetLastError(0xdeadbeef);
1117 result
= SHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1118 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1119 ok (GetLastError()==0xdeadbeef ||
1120 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1121 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1122 ok (!wszPath
[0], "Expected empty path\n");
1124 IShellFolder_Release(psfDesktop
);
1128 IMalloc_Free(ppM
, pidlMyComputer
);
1130 result
= SHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1131 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1133 IShellFolder_Release(psfDesktop
);
1136 myPathAddBackslashW(wszFileName
);
1137 lstrcatW(wszFileName
, wszTestFile
);
1138 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1139 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1140 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1141 IShellFolder_Release(psfDesktop
);
1144 CloseHandle(hTestFile
);
1146 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1147 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1149 IShellFolder_Release(psfDesktop
);
1150 DeleteFileW(wszFileName
);
1151 IMalloc_Free(ppM
, pidlTestFile
);
1155 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1156 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1157 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1158 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1159 IShellFolder_Release(psfDesktop
);
1160 DeleteFileW(wszFileName
);
1162 IMalloc_Free(ppM
, pidlTestFile
);
1165 StrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1166 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1167 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1168 "returned incorrect path for file placed on desktop\n");
1170 result
= SHGetPathFromIDListW(pidlTestFile
, wszPath
);
1171 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1172 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1174 if (pSHGetPathFromIDListEx
)
1176 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1177 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1178 ok(!lstrcmpiW(wszDesktop
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1179 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszDesktop
));
1181 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1182 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1183 ok(!lstrcmpiW(wszFileName
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1184 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszFileName
));
1186 SetLastError(0xdeadbeef);
1187 memset(wszPath
, 0x55, sizeof(wszPath
));
1188 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, 5, SFGAO_FILESYSTEM
);
1189 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1191 SetLastError(0xdeadbeef);
1192 memset(wszPath
, 0x55, sizeof(wszPath
));
1193 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, 5, SFGAO_FILESYSTEM
);
1194 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1197 win_skip("SHGetPathFromIDListEx not available\n");
1199 IMalloc_Free(ppM
, pidlTestFile
);
1201 /* Test if we can get the path from the start menu "program files" PIDL. */
1202 hr
= SHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1203 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1205 SetLastError(0xdeadbeef);
1206 result
= SHGetPathFromIDListW(pidlPrograms
, wszPath
);
1207 IMalloc_Free(ppM
, pidlPrograms
);
1208 ok(result
, "SHGetPathFromIDListW failed\n");
1211 static void test_EnumObjects_and_CompareIDs(void)
1213 ITEMIDLIST
*newPIDL
;
1214 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1215 char cCurrDirA
[MAX_PATH
] = {0};
1216 static const CHAR cTestDirA
[] = "\\testdir";
1217 WCHAR cTestDirW
[MAX_PATH
];
1221 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1222 len
= lstrlenA(cCurrDirA
);
1225 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1228 if(cCurrDirA
[len
-1] == '\\')
1229 cCurrDirA
[len
-1] = 0;
1231 lstrcatA(cCurrDirA
, cTestDirA
);
1232 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1234 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1235 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1237 CreateFilesFolders();
1239 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1240 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1242 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1243 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1245 test_EnumObjects(testIShellFolder
);
1247 IShellFolder_Release(testIShellFolder
);
1251 IMalloc_Free(ppM
, newPIDL
);
1253 IShellFolder_Release(IDesktopFolder
);
1256 /* A simple implementation of an IPropertyBag, which returns fixed values for
1257 * 'Target' and 'Attributes' properties.
1259 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1263 return E_INVALIDARG
;
1265 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1268 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1269 return E_NOINTERFACE
;
1272 IPropertyBag_AddRef(iface
);
1276 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1280 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1284 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1285 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1287 static const WCHAR wszTargetSpecialFolder
[] = {
1288 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1289 static const WCHAR wszTarget
[] = {
1290 'T','a','r','g','e','t',0 };
1291 static const WCHAR wszAttributes
[] = {
1292 'A','t','t','r','i','b','u','t','e','s',0 };
1293 static const WCHAR wszResolveLinkFlags
[] = {
1294 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1295 static const WCHAR wszTargetKnownFolder
[] = {
1296 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1297 static const WCHAR wszCLSID
[] = {
1298 'C','L','S','I','D',0 };
1300 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1301 ok(V_VT(pVar
) == VT_I4
, "Wrong variant type for 'TargetSpecialFolder' property!\n");
1302 return E_INVALIDARG
;
1305 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1307 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1308 return E_INVALIDARG
;
1311 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1312 WCHAR wszPath
[MAX_PATH
];
1315 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'Target' property!\n");
1316 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1318 result
= SHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1319 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1320 if (!result
) return E_INVALIDARG
;
1322 V_BSTR(pVar
) = SysAllocString(wszPath
);
1326 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1327 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1328 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1329 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1330 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1334 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1335 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1337 return E_INVALIDARG
;
1340 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1341 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1343 return E_INVALIDARG
;
1346 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1347 return E_INVALIDARG
;
1350 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1353 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1357 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1358 InitPropertyBag_IPropertyBag_QueryInterface
,
1359 InitPropertyBag_IPropertyBag_AddRef
,
1360 InitPropertyBag_IPropertyBag_Release
,
1361 InitPropertyBag_IPropertyBag_Read
,
1362 InitPropertyBag_IPropertyBag_Write
1365 static struct IPropertyBag InitPropertyBag
= {
1366 &InitPropertyBag_IPropertyBagVtbl
1369 static void test_FolderShortcut(void) {
1370 IPersistPropertyBag
*pPersistPropertyBag
;
1371 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1372 IPersistFolder3
*pPersistFolder3
;
1375 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1378 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1380 WCHAR wszWineTestFolder
[] = {
1381 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1382 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1383 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1384 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1385 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1386 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1387 'N','a','m','e','S','p','a','c','e','\\',
1388 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1389 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1391 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1392 static const GUID CLSID_UnixDosFolder
=
1393 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1395 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1396 * via their IPersistPropertyBag interface. And that the target folder
1397 * is taken from the IPropertyBag's 'Target' property.
1399 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1400 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1401 if (hr
== REGDB_E_CLASSNOTREG
) {
1402 win_skip("CLSID_FolderShortcut is not implemented\n");
1405 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1406 if (hr
!= S_OK
) return;
1408 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1409 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1411 IPersistPropertyBag_Release(pPersistPropertyBag
);
1415 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1416 (LPVOID
*)&pShellFolder
);
1417 IPersistPropertyBag_Release(pPersistPropertyBag
);
1418 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1419 if (hr
!= S_OK
) return;
1421 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1422 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* win10 */,
1423 "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1425 IShellFolder_Release(pShellFolder
);
1429 result
= SHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1430 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1431 if (!result
) return;
1433 StrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1434 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1436 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1437 IShellFolder_Release(pShellFolder
);
1438 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1439 if (hr
!= S_OK
) return;
1441 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1442 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1443 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1445 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1446 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1447 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1449 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1450 * shell namespace. The target folder, read from the property bag above, remains untouched.
1451 * The following tests show this: The itemidlist for some imaginary shellfolder object
1452 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1453 * itemidlist, but GetDisplayNameOf still returns the path from above.
1455 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1456 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1457 if (hr
!= S_OK
) return;
1459 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1460 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1461 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1462 RegCloseKey(hShellExtKey
);
1463 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1464 &pidlWineTestFolder
, NULL
);
1465 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1466 IShellFolder_Release(pDesktopFolder
);
1467 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1468 if (hr
!= S_OK
) return;
1470 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1471 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1473 IPersistFolder3_Release(pPersistFolder3
);
1474 ILFree(pidlWineTestFolder
);
1478 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1479 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1480 ok(ILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1481 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1482 ILFree(pidlCurrentFolder
);
1483 ILFree(pidlWineTestFolder
);
1485 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1486 IPersistFolder3_Release(pPersistFolder3
);
1487 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1488 if (hr
!= S_OK
) return;
1490 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1491 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1493 IShellFolder_Release(pShellFolder
);
1497 StrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1498 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1500 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1501 * but ShellFSFolders. */
1502 myPathAddBackslashW(wszDesktopPath
);
1503 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1504 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1505 IShellFolder_Release(pShellFolder
);
1509 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1510 &pidlSubFolder
, NULL
);
1511 RemoveDirectoryW(wszDesktopPath
);
1512 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1514 IShellFolder_Release(pShellFolder
);
1518 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1519 (LPVOID
*)&pPersistFolder3
);
1520 IShellFolder_Release(pShellFolder
);
1521 ILFree(pidlSubFolder
);
1522 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1526 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1527 * a little bit and also allow CLSID_UnixDosFolder. */
1528 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1529 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1530 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1531 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1533 IPersistFolder3_Release(pPersistFolder3
);
1536 #include "pshpack1.h"
1537 struct FileStructA
{
1541 WORD uFileDate
; /* In our current implementation this is */
1542 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1547 struct FileStructW
{
1548 WORD cbLen
; /* Length of this element. */
1549 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1550 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1551 WORD uTime
; /* (this is currently speculation) */
1552 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1553 WORD uTime2
; /* (this is currently speculation) */
1554 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1555 WCHAR wszName
[1]; /* The long filename in unicode. */
1556 /* Just for documentation: Right after the unicode string: */
1557 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1558 * SHITEMID->cb == uOffset + cbLen */
1560 #include "poppack.h"
1562 static void test_ITEMIDLIST_format(void) {
1563 WCHAR wszPersonal
[MAX_PATH
];
1564 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1565 LPITEMIDLIST pidlPersonal
, pidlFile
;
1569 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1570 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1573 bResult
= SHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1574 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1575 if (!bResult
) return;
1577 SetLastError(0xdeadbeef);
1578 bResult
= SetCurrentDirectoryW(wszPersonal
);
1579 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1580 win_skip("Most W-calls are not implemented\n");
1583 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1584 if (!bResult
) return;
1586 hr
= SHGetDesktopFolder(&psfDesktop
);
1587 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1588 if (hr
!= S_OK
) return;
1590 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1591 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1593 IShellFolder_Release(psfDesktop
);
1597 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1598 (LPVOID
*)&psfPersonal
);
1599 IShellFolder_Release(psfDesktop
);
1600 ILFree(pidlPersonal
);
1601 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1602 if (hr
!= S_OK
) return;
1604 for (i
=0; i
<3; i
++) {
1605 CHAR szFile
[MAX_PATH
];
1606 struct FileStructA
*pFileStructA
;
1609 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1611 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1612 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1613 if (hFile
== INVALID_HANDLE_VALUE
) {
1614 IShellFolder_Release(psfPersonal
);
1619 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1620 DeleteFileW(wszFile
[i
]);
1621 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1623 IShellFolder_Release(psfPersonal
);
1627 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1628 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1629 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1630 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1632 if (i
< 2) /* First two file names are already in valid 8.3 format */
1633 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1635 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1636 * can't implement this correctly, since unix filesystems don't support
1637 * this nasty short/long filename stuff. So we'll probably stay with our
1638 * current habit of storing the long filename here, which seems to work
1641 ok(pidlFile
->mkid
.abID
[18] == '~', "Should be derived 8.3 name!\n");
1643 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1644 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0',
1645 "Alignment byte, where there shouldn't be!\n");
1647 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1648 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1649 "There should be an alignment byte, but isn't!\n");
1651 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1652 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1653 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1654 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)),
1655 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1657 if (cbOffset
>= sizeof(struct FileStructA
) &&
1658 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1660 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1661 WCHAR
*name
= pFileStructW
->wszName
;
1663 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1664 "FileStructW's offset and length should add up to the PIDL's length!\n");
1666 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1667 /* Since we just created the file, time of creation,
1668 * time of last access and time of last write access just be the same.
1669 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1670 * after the first run. I do remember something with NTFS keeping the creation time
1671 * if a file is deleted and then created again within a couple of seconds or so.
1672 * Might be the reason. */
1673 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1674 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1675 "Last write time should match creation time!\n");
1677 /* On FAT filesystems the last access time is midnight
1678 local time, so the values of uDate2 and uTime2 will
1679 depend on the local timezone. If the times are exactly
1680 equal then the dates should be identical for both FAT
1681 and NTFS as no timezone is more than 1 day away from UTC.
1683 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1685 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1686 "Last write date and time should match last access date and time!\n");
1690 /* Filesystem may be FAT. Check date within 1 day
1691 and seconds are zero. */
1692 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1693 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1694 "Last access time on FAT filesystems should have zero seconds.\n");
1695 /* TODO: Perform check for date being within one day.*/
1698 ok (!lstrcmpW(wszFile
[i
], name
) ||
1699 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1700 !lstrcmpW(wszFile
[i
], name
+ 11) || /* Win7 */
1701 !lstrcmpW(wszFile
[i
], name
+ 13), /* Win8 */
1702 "The filename should be stored in unicode at this position!\n");
1709 IShellFolder_Release(psfPersonal
);
1712 static void test_SHGetFolderPathA(void)
1714 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1716 char path
[MAX_PATH
];
1717 char path_x86
[MAX_PATH
];
1718 char path_key
[MAX_PATH
];
1722 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1724 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1725 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1726 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1729 win_skip( "Program Files (x86) not supported\n" );
1732 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1735 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1736 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1737 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1741 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1743 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1745 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1747 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1749 DWORD type
, count
= sizeof(path_x86
);
1750 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1752 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1753 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1755 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1759 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1760 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1761 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1764 win_skip( "Common Files (x86) not supported\n" );
1767 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1770 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1771 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1772 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1776 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1778 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1780 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1782 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1784 DWORD type
, count
= sizeof(path_x86
);
1785 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1787 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1788 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1790 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1794 static void test_SHGetFolderPathAndSubDirA(void)
1800 static const char wine
[] = "wine";
1801 static const char winetemp
[] = "wine\\temp";
1802 static char appdata
[MAX_PATH
];
1803 static char testpath
[MAX_PATH
];
1804 static char toolongpath
[MAX_PATH
+1];
1806 if(FAILED(SHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
1808 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1812 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1813 delret
= RemoveDirectoryA(testpath
);
1814 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
1815 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1819 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1820 delret
= RemoveDirectoryA(testpath
);
1821 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
1822 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1826 /* test invalid second parameter */
1827 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
1828 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
1830 /* test fourth parameter */
1831 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
1833 case S_OK
: /* winvista */
1834 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
1835 "expected %s to start with %s\n", testpath
, appdata
);
1836 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
1837 "expected %s to end with %s\n", testpath
, winetemp
);
1839 case E_INVALIDARG
: /* winxp, win2k3 */
1842 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
1845 /* test fifth parameter */
1847 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
1848 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1849 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1852 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
1853 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1854 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1857 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
1858 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1859 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1861 for(i
=0; i
< MAX_PATH
; i
++)
1862 toolongpath
[i
] = '0' + i
% 10;
1863 toolongpath
[MAX_PATH
] = '\0';
1864 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
1865 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
1866 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
1869 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
1870 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
1872 /* test a not existing path */
1874 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
1875 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
1876 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
1878 /* create a directory inside a not existing directory */
1880 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
1881 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1882 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
1883 "expected %s to start with %s\n", testpath
, appdata
);
1884 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
1885 "expected %s to end with %s\n", testpath
, winetemp
);
1886 dwret
= GetFileAttributesA(testpath
);
1887 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
1890 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1891 RemoveDirectoryA(testpath
);
1892 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1893 RemoveDirectoryA(testpath
);
1896 static void test_LocalizedNames(void)
1898 static char cCurrDirA
[MAX_PATH
];
1899 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
1900 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1901 ITEMIDLIST
*newPIDL
;
1904 static char resourcefile
[MAX_PATH
];
1910 static const char desktopini_contents1
[] =
1911 "[.ShellClassInfo]\r\n"
1912 "LocalizedResourceName=@";
1913 static const char desktopini_contents2
[] =
1915 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
1916 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
1918 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
1919 CreateDirectoryA(".\\testfolder", NULL
);
1921 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
1923 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
1925 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
1926 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1927 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
1928 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
1929 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
1930 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
1931 ok(ret
, "WriteFile failed %i\n", GetLastError());
1934 /* get IShellFolder for parent */
1935 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1936 len
= lstrlenA(cCurrDirA
);
1939 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
1942 if(cCurrDirA
[len
-1] == '\\')
1943 cCurrDirA
[len
-1] = 0;
1945 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1947 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1948 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1950 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1951 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1953 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1954 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1956 IMalloc_Free(ppM
, newPIDL
);
1958 /* windows reads the display name from the resource */
1959 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
1960 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1962 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
1963 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
1965 hr
= StrRetToBufW(&strret
, newPIDL
, tempbufW
, ARRAY_SIZE(tempbufW
));
1966 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
1968 ok (!lstrcmpiW(tempbufW
, folderdisplayW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
1970 /* editing name is also read from the resource */
1971 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
1972 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
1974 hr
= StrRetToBufW(&strret
, newPIDL
, tempbufW
, ARRAY_SIZE(tempbufW
));
1975 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
1977 ok (!lstrcmpiW(tempbufW
, folderdisplayW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
1979 /* parsing name is unchanged */
1980 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
1981 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
1983 hr
= StrRetToBufW(&strret
, newPIDL
, tempbufW
, ARRAY_SIZE(tempbufW
));
1984 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
1985 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
1987 IShellFolder_Release(IDesktopFolder
);
1988 IShellFolder_Release(testIShellFolder
);
1990 IMalloc_Free(ppM
, newPIDL
);
1993 DeleteFileA(".\\testfolder\\desktop.ini");
1994 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
1995 RemoveDirectoryA(".\\testfolder");
1998 static void test_SHCreateShellItem(void)
2000 IShellItem
*shellitem
, *shellitem2
;
2001 IPersistIDList
*persistidl
;
2002 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2004 char curdirA
[MAX_PATH
];
2005 WCHAR curdirW
[MAX_PATH
];
2006 WCHAR fnbufW
[MAX_PATH
];
2007 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2008 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2010 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2012 if (!pSHCreateShellItem
)
2014 win_skip("SHCreateShellItem isn't available\n");
2020 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2024 ret
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2025 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2027 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2029 ret
= SHGetDesktopFolder(&desktopfolder
);
2030 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2032 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2033 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2035 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2036 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2038 CreateTestFile(".\\testfile");
2040 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2041 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2043 pidl_abstestfile
= ILCombine(pidl_cwd
, pidl_testfile
);
2045 shellitem
= (void*)0xdeadbeef;
2046 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2047 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2048 ok(shellitem
== 0, "Got %p\n", shellitem
);
2050 if (0) /* crashes on Windows XP */
2052 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2053 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2054 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2055 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2058 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2059 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2062 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2063 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2066 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2067 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2070 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2073 IPersistIDList_Release(persistidl
);
2075 IShellItem_Release(shellitem
);
2078 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2079 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2082 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2083 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2086 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2087 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2090 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2093 IPersistIDList_Release(persistidl
);
2096 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2097 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2100 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2101 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2104 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2105 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2108 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2111 IPersistIDList_Release(persistidl
);
2113 IShellItem_Release(shellitem2
);
2116 IShellItem_Release(shellitem
);
2119 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2120 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2123 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2124 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2127 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2128 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2131 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2134 IPersistIDList_Release(persistidl
);
2136 IShellItem_Release(shellitem
);
2139 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2140 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2141 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2144 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2145 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2148 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2149 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2152 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2155 IPersistIDList_Release(persistidl
);
2157 IShellItem_Release(shellitem
);
2160 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2161 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2164 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2165 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2168 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2169 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2172 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2175 IPersistIDList_Release(persistidl
);
2178 IShellItem_Release(shellitem
);
2181 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2182 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2185 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2186 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2187 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2188 IShellItem_Release(shellitem
);
2191 /* SHCreateItemFromParsingName */
2192 if(pSHCreateItemFromParsingName
)
2196 /* Crashes under windows 7 */
2197 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2200 shellitem
= (void*)0xdeadbeef;
2201 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2202 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2203 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2205 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2206 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2207 "SHCreateItemFromParsingName returned %x\n", ret
);
2208 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2210 lstrcpyW(fnbufW
, curdirW
);
2211 myPathAddBackslashW(fnbufW
);
2212 lstrcatW(fnbufW
, testfileW
);
2214 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2215 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2219 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2220 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2223 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2224 CoTaskMemFree(tmp_fname
);
2226 IShellItem_Release(shellitem
);
2230 win_skip("No SHCreateItemFromParsingName\n");
2233 /* SHCreateItemFromIDList */
2234 if(pSHCreateItemFromIDList
)
2238 /* Crashes under win7 */
2239 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2242 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2243 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2245 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2246 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2249 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2250 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2253 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2254 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2257 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2260 IPersistIDList_Release(persistidl
);
2262 IShellItem_Release(shellitem
);
2265 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2266 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2269 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2270 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2273 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2274 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2277 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2280 IPersistIDList_Release(persistidl
);
2282 IShellItem_Release(shellitem
);
2286 win_skip("No SHCreateItemFromIDList\n");
2288 /* SHCreateItemFromRelativeName */
2289 if(pSHCreateItemFromRelativeName
&& pSHGetKnownFolderPath
)
2291 IShellItem
*shellitem_desktop
= NULL
;
2292 WCHAR
*desktop_path
, *displayname
;
2293 WCHAR testfile_path
[MAX_PATH
] = {0};
2295 LPITEMIDLIST pidl_desktop_testfile
= NULL
;
2298 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem_desktop
);
2299 ok(ret
== S_OK
, "SHCreateShellItem failed: 0x%08x.\n", ret
);
2301 shellitem
= (void*)0xdeadbeef;
2302 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, NULL
, NULL
, &IID_IShellItem
,
2303 (void**)&shellitem
);
2304 ok(ret
== E_INVALIDARG
, "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n",
2306 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2308 /* Test with a non-existent file */
2309 shellitem
= (void*)0xdeadbeef;
2310 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2311 (void**)&shellitem
);
2312 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2313 "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n",
2314 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), ret
);
2315 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2317 /* Create a file for testing in desktop folder */
2318 pSHGetKnownFolderPath(&FOLDERID_Desktop
, 0, NULL
, &desktop_path
);
2319 lstrcatW(testfile_path
, desktop_path
);
2320 myPathAddBackslashW(testfile_path
);
2321 lstrcatW(testfile_path
, testfileW
);
2322 file
= CreateFileW(testfile_path
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
2323 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError());
2326 shellitem
= (void*)0xdeadbeef;
2327 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2328 (void**)&shellitem
);
2329 ok(ret
== S_OK
, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret
);
2330 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2333 ret
= IShellItem_GetDisplayName(shellitem
, 0, &displayname
);
2334 ok(ret
== S_OK
, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret
);
2335 ok(!lstrcmpW(displayname
, testfileW
), "got wrong display name: %s.\n", wine_dbgstr_w(displayname
));
2336 CoTaskMemFree(displayname
);
2338 shellitem2
= (void*)0xdeadbeef;
2339 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2340 (void**)&shellitem2
);
2341 ok(ret
== S_OK
, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret
);
2342 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2343 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2344 ok(!order
, "order got wrong value: %d.\n", order
);
2345 IShellItem_Release(shellitem2
);
2347 shellitem2
= (void*)0xdeadbeef;
2348 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, testfileW
, NULL
,
2349 &pidl_desktop_testfile
, NULL
);
2350 ok(ret
== S_OK
, "ParseDisplayName failed 0x%08x.\n", ret
);
2351 ret
= pSHCreateItemFromIDList(pidl_desktop_testfile
, &IID_IShellItem
, (void**)&shellitem2
);
2352 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2353 ok(ret
== S_OK
, "IShellItem_Compare fail: 0x%08x.\n", ret
);
2354 ok(!order
, "order got wrong value: %d.\n", order
);
2355 ILFree(pidl_desktop_testfile
);
2356 IShellItem_Release(shellitem2
);
2358 IShellItem_Release(shellitem
);
2361 DeleteFileW(testfile_path
);
2362 CoTaskMemFree(desktop_path
);
2363 IShellItem_Release(shellitem_desktop
);
2366 win_skip("No SHCreateItemFromRelativeName or SHGetKnownFolderPath\n");
2368 /* SHCreateItemInKnownFolder */
2369 if(pSHCreateItemInKnownFolder
&& pSHGetKnownFolderPath
)
2371 WCHAR
*desktop_path
;
2372 WCHAR testfile_path
[MAX_PATH
] = {0};
2374 WCHAR
*displayname
= NULL
;
2376 LPITEMIDLIST pidl_desktop_testfile
= NULL
;
2378 shellitem
= (void*)0xdeadbeef;
2379 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, NULL
, &IID_IShellItem
,
2380 (void**)&shellitem
);
2381 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2382 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2385 shellitem2
= (void*)0xdeadbeef;
2386 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem2
);
2387 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2390 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2391 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2392 ok(!order
, "order got wrong value: %d.\n", order
);
2393 IShellItem_Release(shellitem2
);
2395 IShellItem_Release(shellitem
);
2398 /* Test with a non-existent file */
2399 shellitem
= (void*)0xdeadbeef;
2400 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2401 (void**)&shellitem
);
2402 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2403 "Expected 0x%08x but SHCreateItemInKnownFolder return: 0x%08x.\n",
2404 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), ret
);
2405 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2407 pSHGetKnownFolderPath(&FOLDERID_Desktop
, 0, NULL
, &desktop_path
);
2408 lstrcatW(testfile_path
, desktop_path
);
2409 myPathAddBackslashW(testfile_path
);
2410 lstrcatW(testfile_path
, testfileW
);
2411 file
= CreateFileW(testfile_path
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
2412 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError());
2415 shellitem
= (void*)0xdeadbeef;
2416 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2417 (void**)&shellitem
);
2418 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2419 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2422 ret
= IShellItem_GetDisplayName(shellitem
, 0, &displayname
);
2423 ok(ret
== S_OK
, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret
);
2424 ok(!lstrcmpW(displayname
, testfileW
), "got wrong display name: %s.\n",
2425 wine_dbgstr_w(displayname
));
2426 CoTaskMemFree(displayname
);
2428 shellitem2
= (void*)0xdeadbeef;
2429 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2430 (void**)&shellitem2
);
2431 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2432 ok(shellitem2
!= NULL
, "shellitem was %p.\n", shellitem
);
2433 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2434 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2435 ok(!order
, "order got wrong value: %d.\n", order
);
2436 IShellItem_Release(shellitem2
);
2438 shellitem2
= (void*)0xdeadbeef;
2439 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, testfileW
, NULL
,
2440 &pidl_desktop_testfile
, NULL
);
2441 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x.\n", ret
);
2442 ret
= pSHCreateItemFromIDList(pidl_desktop_testfile
, &IID_IShellItem
, (void**)&shellitem2
);
2443 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2444 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2445 ok(!order
, "order got wrong value: %d.\n", order
);
2446 ILFree(pidl_desktop_testfile
);
2447 IShellItem_Release(shellitem2
);
2449 IShellItem_Release(shellitem
);
2452 shellitem
= (void*)0xdeadbeef;
2453 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Documents
, 0, NULL
, &IID_IShellItem
,
2454 (void**)&shellitem
);
2455 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2456 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2459 shellitem2
= (void*)0xdeadbeef;
2460 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Documents
, 0, NULL
, &IID_IShellItem
,
2461 (void**)&shellitem2
);
2462 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2463 ok(shellitem2
!= NULL
, "shellitem was %p.\n", shellitem
);
2464 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2465 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2466 ok(!order
, "order got wrong value: %d.\n", order
);
2467 IShellItem_Release(shellitem2
);
2469 IShellItem_Release(shellitem
);
2471 DeleteFileW(testfile_path
);
2472 CoTaskMemFree(desktop_path
);
2475 win_skip("No SHCreateItemInKnownFolder or SHGetKnownFolderPath\n");
2477 DeleteFileA(".\\testfile");
2478 ILFree(pidl_abstestfile
);
2479 ILFree(pidl_testfile
);
2480 ILFree(pidl_desktop
);
2482 IShellFolder_Release(currentfolder
);
2483 IShellFolder_Release(desktopfolder
);
2486 static void test_SHGetNameFromIDList(void)
2488 IShellItem
*shellitem
;
2493 static const DWORD flags
[] = {
2494 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2495 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2496 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2497 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2499 if(!pSHGetNameFromIDList
)
2501 win_skip("SHGetNameFromIDList missing.\n");
2505 /* This should be available on any platform that passed the above test. */
2506 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2510 /* Crashes under win7 */
2511 pSHGetNameFromIDList(NULL
, 0, NULL
);
2514 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2515 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2517 /* Test the desktop */
2518 hres
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2519 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2520 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2521 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2524 WCHAR
*nameSI
, *nameSH
;
2525 WCHAR buf
[MAX_PATH
];
2526 HRESULT hrSI
, hrSH
, hrSF
;
2531 SHGetDesktopFolder(&psf
);
2532 for(i
= 0; flags
[i
] != -1234; i
++)
2534 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2535 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2536 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2537 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2538 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2539 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2541 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2542 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2546 StrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2548 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2550 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2552 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2553 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2555 IShellFolder_Release(psf
);
2557 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2558 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2559 res
= SHGetPathFromIDListW(pidl
, buf
);
2560 ok(res
== TRUE
, "Got %d\n", res
);
2561 if(SUCCEEDED(hrSI
) && res
)
2562 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2563 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2565 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2566 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2567 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2569 IShellItem_Release(shellitem
);
2573 /* Test the control panel */
2574 hres
= SHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2575 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2576 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2577 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2580 WCHAR
*nameSI
, *nameSH
;
2581 WCHAR buf
[MAX_PATH
];
2582 HRESULT hrSI
, hrSH
, hrSF
;
2587 SHGetDesktopFolder(&psf
);
2588 for(i
= 0; flags
[i
] != -1234; i
++)
2590 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2591 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2592 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2593 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2594 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2595 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2597 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2598 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2602 StrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2604 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2606 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2608 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2609 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2611 IShellFolder_Release(psf
);
2613 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2614 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2615 res
= SHGetPathFromIDListW(pidl
, buf
);
2616 ok(res
== FALSE
, "Got %d\n", res
);
2617 if(SUCCEEDED(hrSI
) && res
)
2618 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2619 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2621 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2622 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2623 "Got 0x%08x\n", hres
);
2624 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2626 IShellItem_Release(shellitem
);
2631 static void test_SHGetItemFromDataObject(void)
2633 IShellFolder
*psfdesktop
;
2638 if(!pSHGetItemFromDataObject
)
2640 win_skip("No SHGetItemFromDataObject.\n");
2646 /* Crashes under win7 */
2647 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2650 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2651 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2653 SHGetDesktopFolder(&psfdesktop
);
2655 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2656 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2663 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2664 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2665 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2668 LPITEMIDLIST apidl
[5];
2671 for(count
= 0; count
< 5; count
++)
2672 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2677 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2678 &IID_IDataObject
, NULL
, (void**)&pdo
);
2679 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2682 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2683 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2684 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2685 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2686 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2687 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2688 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2689 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2690 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2691 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2692 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2693 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2694 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2695 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2696 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2698 IDataObject_Release(pdo
);
2702 skip("No file(s) found - skipping single-file test.\n");
2706 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2707 &IID_IDataObject
, NULL
, (void**)&pdo
);
2708 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2711 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2712 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2713 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2714 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2715 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2716 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2717 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2718 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2719 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2720 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2721 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2722 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2723 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2724 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2725 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2726 IDataObject_Release(pdo
);
2730 skip("zero or one file found - skipping multi-file test.\n");
2732 for(i
= 0; i
< count
; i
++)
2735 IEnumIDList_Release(peidl
);
2738 IShellView_Release(psv
);
2741 IShellFolder_Release(psfdesktop
);
2744 static void test_ShellItemCompare(void)
2746 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2747 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2748 IShellFolder
*psf_desktop
, *psf_current
;
2749 LPITEMIDLIST pidl_cwd
;
2750 WCHAR curdirW
[MAX_PATH
];
2753 static const WCHAR filesW
[][9] = {
2754 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2755 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2756 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2760 if(!pSHCreateShellItem
)
2762 win_skip("SHCreateShellItem missing.\n");
2766 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2769 skip("Failed to get current directory, skipping.\n");
2773 CreateDirectoryA(".\\a", NULL
);
2774 CreateDirectoryA(".\\b", NULL
);
2775 CreateDirectoryA(".\\c", NULL
);
2776 CreateTestFile(".\\a\\a");
2777 CreateTestFile(".\\a\\b");
2778 CreateTestFile(".\\a\\c");
2779 CreateTestFile(".\\b\\a");
2780 CreateTestFile(".\\b\\b");
2781 CreateTestFile(".\\b\\c");
2782 CreateTestFile(".\\c\\a");
2783 CreateTestFile(".\\c\\b");
2784 CreateTestFile(".\\c\\c");
2786 SHGetDesktopFolder(&psf_desktop
);
2787 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2788 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2789 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2790 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2791 IShellFolder_Release(psf_desktop
);
2794 /* Generate ShellItems for the files */
2795 memset(&psi
, 0, sizeof(psi
));
2797 for(i
= 0; i
< 9; i
++)
2799 LPITEMIDLIST pidl_testfile
= NULL
;
2801 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2802 NULL
, &pidl_testfile
, NULL
);
2803 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2806 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2807 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2808 ILFree(pidl_testfile
);
2810 if(FAILED(hr
)) failed
= TRUE
;
2814 skip("Failed to create all shellitems.\n");
2818 /* Generate ShellItems for the folders */
2819 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2820 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2821 if(FAILED(hr
)) failed
= TRUE
;
2822 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2823 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2824 if(FAILED(hr
)) failed
= TRUE
;
2825 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2826 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2827 if(FAILED(hr
)) failed
= TRUE
;
2831 skip("Failed to create shellitems.\n");
2837 /* Crashes on native (win7, winxp) */
2838 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2839 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2840 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2844 for(i
= 0; i
< 9; i
++)
2846 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
2847 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2848 ok(order
== 0, "Got order %d\n", order
);
2849 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
2850 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2851 ok(order
== 0, "Got order %d\n", order
);
2852 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2853 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2854 ok(order
== 0, "Got order %d\n", order
);
2858 /* a\b:a\a , a\b:a\c, a\b:a\b */
2859 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &order
);
2860 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2861 ok(order
== 1, "Got order %d\n", order
);
2862 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_DISPLAY
, &order
);
2863 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2864 ok(order
== -1, "Got order %d\n", order
);
2865 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2866 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2867 ok(order
== 0, "Got order %d\n", order
);
2869 /* b\b:a\b, b\b:c\b, b\b:c\b */
2870 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
2871 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2872 ok(order
== 1, "Got order %d\n", order
);
2873 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
2874 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2875 ok(order
== -1, "Got order %d\n", order
);
2876 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2877 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2878 ok(order
== 0, "Got order %d\n", order
);
2880 /* b:a\a, b:a\c, b:a\b */
2881 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
2882 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2883 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2884 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
2885 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2886 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2887 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2888 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2889 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2891 /* b:c\a, b:c\c, b:c\b */
2892 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
2893 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2894 ok(order
== -1, "Got order %d\n", order
);
2895 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_DISPLAY
, &order
);
2896 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2897 ok(order
== -1, "Got order %d\n", order
);
2898 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2899 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2900 ok(order
== -1, "Got order %d\n", order
);
2902 /* a\b:a\a , a\b:a\c, a\b:a\b */
2903 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
2904 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2905 ok(order
== 1, "Got order %d\n", order
);
2906 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
2907 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2908 ok(order
== -1, "Got order %d\n", order
);
2909 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2910 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2911 ok(order
== 0, "Got order %d\n", order
);
2913 /* b\b:a\b, b\b:c\b, b\b:c\b */
2914 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
2915 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2916 ok(order
== 1, "Got order %d\n", order
);
2917 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &order
);
2918 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2919 ok(order
== -1, "Got order %d\n", order
);
2920 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2921 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2922 ok(order
== 0, "Got order %d\n", order
);
2924 /* b:a\a, b:a\c, b:a\b */
2925 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
2926 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2927 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2928 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
2929 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2930 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2931 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2932 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2933 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2935 /* b:c\a, b:c\c, b:c\b */
2936 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
2937 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2938 ok(order
== -1, "Got order %d\n", order
);
2939 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_CANONICAL
, &order
);
2940 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2941 ok(order
== -1, "Got order %d\n", order
);
2942 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
2943 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2944 ok(order
== -1, "Got order %d\n", order
);
2947 IShellFolder_Release(psf_current
);
2949 DeleteFileA(".\\a\\a");
2950 DeleteFileA(".\\a\\b");
2951 DeleteFileA(".\\a\\c");
2952 DeleteFileA(".\\b\\a");
2953 DeleteFileA(".\\b\\b");
2954 DeleteFileA(".\\b\\c");
2955 DeleteFileA(".\\c\\a");
2956 DeleteFileA(".\\c\\b");
2957 DeleteFileA(".\\c\\c");
2958 RemoveDirectoryA(".\\a");
2959 RemoveDirectoryA(".\\b");
2960 RemoveDirectoryA(".\\c");
2962 if(psi_a
) IShellItem_Release(psi_a
);
2963 if(psi_b
) IShellItem_Release(psi_b
);
2964 if(psi_c
) IShellItem_Release(psi_c
);
2966 for(i
= 0; i
< 9; i
++)
2967 if(psi
[i
]) IShellItem_Release(psi
[i
]);
2970 /**************************************************************/
2971 /* IUnknown implementation for counting QueryInterface calls. */
2973 IUnknown IUnknown_iface
;
2981 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
2983 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
2986 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
2988 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
2991 for(i
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
2993 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
2995 This
->ifaces
[i
].count
++;
3002 return E_NOINTERFACE
;
3005 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3010 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3015 static const IUnknownVtbl vt_IUnknown
= {
3016 unk_fnQueryInterface
,
3021 static void test_SHGetIDListFromObject(void)
3023 IUnknownImpl
*punkimpl
;
3024 IShellFolder
*psfdesktop
;
3026 LPITEMIDLIST pidl
, pidl_desktop
;
3029 struct if_count ifaces
[] =
3030 { {&IID_IPersistIDList
, 0},
3031 {&IID_IPersistFolder2
, 0},
3032 {&IID_IDataObject
, 0},
3033 {&IID_IParentAndItem
, 0},
3034 {&IID_IFolderView
, 0},
3037 if(!pSHGetIDListFromObject
)
3039 win_skip("SHGetIDListFromObject missing.\n");
3045 /* Crashes native */
3046 pSHGetIDListFromObject(NULL
, NULL
);
3047 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3050 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3051 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3053 punkimpl
= heap_alloc(sizeof(*punkimpl
));
3054 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3055 punkimpl
->ifaces
= ifaces
;
3056 punkimpl
->unknown
= 0;
3058 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3059 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3060 ok(ifaces
[0].count
, "interface not requested.\n");
3061 ok(ifaces
[1].count
, "interface not requested.\n");
3062 ok(ifaces
[2].count
, "interface not requested.\n");
3064 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3065 "interface not requested.\n");
3066 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3067 "interface not requested.\n");
3069 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3070 heap_free(punkimpl
);
3072 pidl_desktop
= NULL
;
3073 SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3074 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3076 SHGetDesktopFolder(&psfdesktop
);
3078 /* Test IShellItem */
3079 if(pSHCreateShellItem
)
3081 IShellItem
*shellitem
;
3082 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3083 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3086 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3087 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3090 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3093 IShellItem_Release(shellitem
);
3097 skip("no SHCreateShellItem.\n");
3099 /* Test IShellFolder */
3100 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3101 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3104 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3108 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3109 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3116 /* Test IFolderView */
3117 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3118 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3121 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3125 /* Test IDataObject */
3126 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3127 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3128 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3131 LPITEMIDLIST apidl
[5];
3133 for(count
= 0; count
< 5; count
++)
3134 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3139 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3140 &IID_IDataObject
, NULL
, (void**)&pdo
);
3141 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3144 pidl
= (void*)0xDEADBEEF;
3145 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3146 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3147 ok(pidl
!= NULL
, "pidl is NULL.\n");
3148 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3151 IDataObject_Release(pdo
);
3155 skip("No files found - skipping single-file test.\n");
3159 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3160 &IID_IDataObject
, NULL
, (void**)&pdo
);
3161 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3164 pidl
= (void*)0xDEADBEEF;
3165 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3166 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3167 "got 0x%08x\n", hres
);
3168 ok(pidl
== NULL
, "pidl is not NULL.\n");
3170 IDataObject_Release(pdo
);
3174 skip("zero or one file found - skipping multi-file test.\n");
3176 for(i
= 0; i
< count
; i
++)
3179 IEnumIDList_Release(peidl
);
3182 IShellView_Release(psv
);
3185 IShellFolder_Release(psfdesktop
);
3186 ILFree(pidl_desktop
);
3189 static void test_SHGetItemFromObject(void)
3191 IUnknownImpl
*punkimpl
;
3192 IShellFolder
*psfdesktop
;
3197 struct if_count ifaces
[] =
3198 { {&IID_IPersistIDList
, 0},
3199 {&IID_IPersistFolder2
, 0},
3200 {&IID_IDataObject
, 0},
3201 {&IID_IParentAndItem
, 0},
3202 {&IID_IFolderView
, 0},
3205 if(!pSHGetItemFromObject
)
3207 skip("No SHGetItemFromObject.\n");
3211 SHGetDesktopFolder(&psfdesktop
);
3215 /* Crashes with Windows 7 */
3216 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3217 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3218 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3221 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3222 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3224 punkimpl
= heap_alloc(sizeof(*punkimpl
));
3225 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3226 punkimpl
->ifaces
= ifaces
;
3227 punkimpl
->unknown
= 0;
3229 /* The same as SHGetIDListFromObject */
3230 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3231 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3232 ok(ifaces
[0].count
, "interface not requested.\n");
3233 ok(ifaces
[1].count
, "interface not requested.\n");
3234 ok(ifaces
[2].count
, "interface not requested.\n");
3236 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3237 "interface not requested.\n");
3238 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3239 "interface not requested.\n");
3241 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3242 heap_free(punkimpl
);
3244 /* Test IShellItem */
3245 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3246 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3250 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3251 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3255 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3256 IShellItem_Release(psi2
);
3258 IShellItem_Release(psi
);
3261 IShellFolder_Release(psfdesktop
);
3264 static void test_SHCreateShellItemArray(void)
3266 IShellFolder
*pdesktopsf
, *psf
;
3267 IShellItemArray
*psia
;
3270 WCHAR cTestDirW
[MAX_PATH
];
3271 LPITEMIDLIST pidl_testdir
, pidl
;
3272 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3274 if(!pSHCreateShellItemArray
) {
3275 skip("No pSHCreateShellItemArray!\n");
3281 /* Crashes under native */
3282 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3283 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3284 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3285 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3288 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3289 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3291 SHGetDesktopFolder(&pdesktopsf
);
3292 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3293 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3295 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3296 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3298 SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3299 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3300 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3303 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3304 myPathAddBackslashW(cTestDirW
);
3305 lstrcatW(cTestDirW
, testdirW
);
3307 CreateFilesFolders();
3309 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3310 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3313 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3315 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3317 IShellFolder_Release(pdesktopsf
);
3321 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3322 ILFree(pidl_testdir
);
3327 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3328 ok(hr
== S_OK
, "Got %08x\n", hr
);
3331 LPITEMIDLIST apidl
[5];
3332 UINT done
, numitems
, i
;
3334 for(done
= 0; done
< 5; done
++)
3335 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3337 ok(done
== 5, "Got %d pidls\n", done
);
3338 IEnumIDList_Release(peidl
);
3340 /* Create a ShellItemArray */
3341 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3342 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3349 /* Crashes in Windows 7 */
3350 IShellItemArray_GetCount(psia
, NULL
);
3353 IShellItemArray_GetCount(psia
, &numitems
);
3354 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3356 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3357 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3359 /* Compare all the items */
3360 for(i
= 0; i
< numitems
; i
++)
3362 LPITEMIDLIST pidl_abs
;
3363 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3365 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3366 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3369 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3370 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3373 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3376 IShellItem_Release(psi
);
3380 for(i
= 0; i
< done
; i
++)
3382 IShellItemArray_Release(psia
);
3386 /* SHCreateShellItemArrayFromShellItem */
3387 if(pSHCreateShellItemArrayFromShellItem
)
3393 /* Crashes under Windows 7 */
3394 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3395 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3396 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3399 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3400 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3403 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3404 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3409 hr
= IShellItemArray_GetCount(psia
, &count
);
3410 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3411 ok(count
== 1, "Got count %d\n", count
);
3412 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3413 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3415 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3418 LPITEMIDLIST pidl1
, pidl2
;
3419 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3420 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3421 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3422 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3423 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3424 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3425 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3428 IShellItem_Release(psi2
);
3430 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3431 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3432 IShellItemArray_Release(psia
);
3434 IShellItem_Release(psi
);
3438 skip("No SHCreateShellItemArrayFromShellItem.\n");
3440 if(pSHCreateShellItemArrayFromDataObject
)
3446 /* Crashes under Windows 7 */
3447 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3449 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3450 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3452 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3453 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3460 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3461 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3462 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3465 LPITEMIDLIST apidl
[5];
3468 for(count
= 0; count
< 5; count
++)
3469 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3471 ok(count
== 5, "Got %d\n", count
);
3475 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3476 &IID_IDataObject
, NULL
, (void**)&pdo
);
3477 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3480 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3482 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3486 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3487 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3488 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3489 for(i
= 0; i
< count_sia
; i
++)
3491 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3493 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3494 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3498 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3499 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3500 ok(pidl
!= NULL
, "pidl as NULL.\n");
3501 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3503 IShellItem_Release(psi
);
3508 IShellItemArray_Release(psia
);
3511 IDataObject_Release(pdo
);
3513 for(i
= 0; i
< count
; i
++)
3517 skip("No files found - skipping test.\n");
3519 IEnumIDList_Release(peidl
);
3521 IShellView_Release(psv
);
3525 skip("No SHCreateShellItemArrayFromDataObject.\n");
3527 if(pSHCreateShellItemArrayFromIDLists
)
3529 WCHAR test1W
[] = {'t','e','s','t','1','.','t','x','t',0};
3530 WCHAR test1pathW
[MAX_PATH
];
3531 LPITEMIDLIST pidltest1
;
3532 LPCITEMIDLIST pidl_array
[2];
3537 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, NULL
);
3540 psia
= (void*)0xdeadbeef;
3541 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, &psia
);
3542 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3543 ok(psia
== NULL
, "Got %p\n", psia
);
3545 psia
= (void*)0xdeadbeef;
3546 hr
= pSHCreateShellItemArrayFromIDLists(0, pidl_array
, &psia
);
3547 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3548 ok(psia
== NULL
, "Got %p\n", psia
);
3550 psia
= (void*)0xdeadbeef;
3551 pidl_array
[0] = NULL
;
3552 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3553 todo_wine
ok(hr
== E_OUTOFMEMORY
, "Got 0x%08x\n", hr
);
3554 ok(psia
== NULL
, "Got %p\n", psia
);
3556 psia
= (void*)0xdeadbeef;
3557 pidl_array
[0] = pidl_testdir
;
3558 pidl_array
[1] = NULL
;
3559 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3560 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Vista */, "Got 0x%08x\n", hr
);
3561 todo_wine
ok(psia
!= NULL
|| broken(psia
== NULL
) /* Vista */, "Got %p\n", psia
);
3567 hr
= IShellItemArray_GetCount(psia
, &count
);
3568 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3569 ok(count
== 2, "Got %d\n", count
);
3571 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3572 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3576 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3577 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3578 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3580 CoTaskMemFree(path
);
3582 IShellItem_Release(psi
);
3585 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3586 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3590 WCHAR desktoppath
[MAX_PATH
];
3593 result
= SHGetSpecialFolderPathW(NULL
, desktoppath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
3594 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
3596 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3597 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3598 ok(!lstrcmpW(path
, desktoppath
), "Got %s\n", wine_dbgstr_w(path
));
3600 CoTaskMemFree(path
);
3602 IShellItem_Release(psi
);
3606 IShellItemArray_Release(psia
);
3611 psia
= (void*)0xdeadbeef;
3612 pidl_array
[0] = pidl_testdir
;
3613 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3614 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3620 hr
= IShellItemArray_GetCount(psia
, &count
);
3621 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3622 ok(count
== 1, "Got %d\n", count
);
3624 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3625 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3629 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3630 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3631 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3633 CoTaskMemFree(path
);
3635 IShellItem_Release(psi
);
3638 IShellItemArray_Release(psia
);
3642 lstrcpyW(test1pathW
, cTestDirW
);
3643 myPathAddBackslashW(test1pathW
);
3644 lstrcatW(test1pathW
, test1W
);
3646 SHGetDesktopFolder(&pdesktopsf
);
3648 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, test1pathW
, NULL
, &pidltest1
, NULL
);
3649 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3652 psia
= (void*)0xdeadbeef;
3653 pidl_array
[0] = pidl_testdir
;
3654 pidl_array
[1] = pidltest1
;
3655 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3656 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3662 hr
= IShellItemArray_GetCount(psia
, &count
);
3663 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3664 ok(count
== 2, "Got %d\n", count
);
3666 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3667 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3671 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3672 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3673 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3675 CoTaskMemFree(path
);
3677 IShellItem_Release(psi
);
3680 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3681 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3685 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3686 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3687 ok(!lstrcmpW(path
, test1pathW
), "Got %s\n", wine_dbgstr_w(path
));
3689 CoTaskMemFree(path
);
3691 IShellItem_Release(psi
);
3695 IShellItemArray_Release(psia
);
3701 IShellFolder_Release(pdesktopsf
);
3704 skip("No SHCreateShellItemArrayFromIDLists.\n");
3706 IShellFolder_Release(psf
);
3707 ILFree(pidl_testdir
);
3711 static void test_ShellItemArrayEnumItems(void)
3713 IShellFolder
*pdesktopsf
, *psf
;
3715 WCHAR cTestDirW
[MAX_PATH
];
3717 LPITEMIDLIST pidl_testdir
;
3718 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3720 if(!pSHCreateShellItemArray
)
3722 win_skip("No SHCreateShellItemArray, skipping test...\n");
3726 CreateFilesFolders();
3728 SHGetDesktopFolder(&pdesktopsf
);
3730 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3731 myPathAddBackslashW(cTestDirW
);
3732 lstrcatW(cTestDirW
, testdirW
);
3734 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3735 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3738 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3740 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3741 ILFree(pidl_testdir
);
3743 IShellFolder_Release(pdesktopsf
);
3744 if (FAILED(hr
)) return;
3746 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3747 ok(hr
== S_OK
, "Got %08x\n", hr
);
3750 IShellItemArray
*psia
;
3751 LPITEMIDLIST apidl
[5];
3752 UINT done
, numitems
, i
;
3754 for(done
= 0; done
< 5; done
++)
3755 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3757 ok(done
== 5, "Got %d pidls\n", done
);
3758 IEnumIDList_Release(peidl
);
3760 /* Create a ShellItemArray */
3761 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3762 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3765 IEnumShellItems
*iesi
;
3766 IShellItem
*my_array
[10];
3769 IShellItemArray_GetCount(psia
, &numitems
);
3770 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3773 hr
= IShellItemArray_EnumItems(psia
, &iesi
);
3774 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3775 ok(iesi
!= NULL
, "Got NULL\n");
3778 IEnumShellItems
*iesi2
;
3780 /* This should fail according to the documentation and Win7+ */
3781 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3782 hr
= IEnumShellItems_Next(iesi
, 2, my_array
, NULL
);
3783 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
3784 for(i
= 0; i
< 2; i
++)
3786 ok(my_array
[i
] == (void*)0xdeadbeef ||
3787 broken(my_array
[i
] != (void*)0xdeadbeef && my_array
[i
] != NULL
), /* Vista */
3788 "Got %p (%d)\n", my_array
[i
], i
);
3790 if(my_array
[i
] != (void*)0xdeadbeef)
3791 IShellItem_Release(my_array
[i
]);
3793 ok(my_array
[2] == (void*)0xdeadbeef, "Got %p\n", my_array
[2]);
3795 IEnumShellItems_Reset(iesi
);
3796 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3797 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, NULL
);
3798 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3799 ok(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3800 if(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef)
3801 IShellItem_Release(my_array
[0]);
3802 ok(my_array
[1] == (void*)0xdeadbeef, "Got %p\n", my_array
[1]);
3804 IEnumShellItems_Reset(iesi
);
3806 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3807 hr
= IEnumShellItems_Next(iesi
, numitems
, my_array
, &fetched
);
3808 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3809 ok(fetched
== numitems
, "Got %d\n", fetched
);
3810 for(i
= 0;i
< numitems
; i
++)
3812 ok(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef,
3813 "Got %p at %d\n", my_array
[i
], i
);
3815 if(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef)
3816 IShellItem_Release(my_array
[i
]);
3818 ok(my_array
[i
] == (void*)0xdeadbeef, "Got %p\n", my_array
[i
]);
3820 /* Compare all the items */
3821 IEnumShellItems_Reset(iesi
);
3822 for(i
= 0; i
< numitems
; i
++)
3827 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3828 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3829 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3830 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3831 ok(fetched
== 1, "Got %d\n", fetched
);
3833 hr
= IShellItem_Compare(psi
, my_array
[0], 0, &order
);
3834 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3835 ok(order
== 0, "Got %d\n", order
);
3837 IShellItem_Release(psi
);
3838 IShellItem_Release(my_array
[0]);
3841 my_array
[0] = (void*)0xdeadbeef;
3842 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3843 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3844 ok(fetched
== 0, "Got %d\n", fetched
);
3845 ok(my_array
[0] == (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3847 /* Cloning not implemented anywhere */
3848 iesi2
= (void*)0xdeadbeef;
3849 hr
= IEnumShellItems_Clone(iesi
, &iesi2
);
3850 ok(hr
== E_NOTIMPL
, "Got 0x%08x\n", hr
);
3851 ok(iesi2
== NULL
|| broken(iesi2
== (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2
);
3853 IEnumShellItems_Release(iesi
);
3856 IShellItemArray_Release(psia
);
3859 for(i
= 0; i
< done
; i
++)
3865 static void test_ShellItemBindToHandler(void)
3868 LPITEMIDLIST pidl_desktop
;
3871 if(!pSHCreateShellItem
)
3873 skip("SHCreateShellItem missing.\n");
3877 hr
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3878 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3881 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3882 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3886 IPersistFolder2
*ppf2
;
3891 /* Crashes under Windows 7 */
3892 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3893 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3895 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3896 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3899 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3900 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3901 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3902 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3903 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3906 LPITEMIDLIST pidl_tmp
;
3907 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3908 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3911 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3914 IPersistFolder2_Release(ppf2
);
3917 /* BHID_SFUIObject */
3918 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3919 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3920 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3921 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3922 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3923 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3925 /* BHID_DataObject */
3926 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3927 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3928 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3932 /* BHID_SFViewObject */
3933 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3934 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3935 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3936 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3937 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3938 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3941 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
3942 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3943 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3944 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
3945 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3946 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3949 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
3950 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3951 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3952 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
3953 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3954 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3956 /* BHID_StorageEnum */
3957 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
3958 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3959 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3962 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
3963 supported starting from Win8. */
3964 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferSource
, (void**)&punk
);
3965 ok(hr
== S_OK
|| broken(FAILED(hr
)) /* pre-Vista */, "Got 0x%08x\n", hr
);
3968 IUnknown_Release(punk
);
3970 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferDestination
, (void**)&punk
);
3971 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3972 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3974 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
3975 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Win8 */, "Got 0x%08x\n", hr
);
3976 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3979 /* BHID_EnumItems */
3980 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
3981 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3982 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3985 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
3986 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3987 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3989 /* BHID_LinkTargetItem */
3990 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
3991 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3992 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3993 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
3994 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3995 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3997 /* BHID_PropertyStore */
3998 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
3999 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4000 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4001 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
4002 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4003 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4005 /* BHID_ThumbnailHandler */
4006 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
4007 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4008 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4010 /* BHID_AssociationArray */
4011 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
4012 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4013 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4015 /* BHID_EnumAssocHandlers */
4016 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
4017 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4018 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4021 IShellItem_Release(psi
);
4024 skip("Failed to create ShellItem.\n");
4026 ILFree(pidl_desktop
);
4029 static void test_ShellItemGetAttributes(void)
4031 IShellItem
*psi
, *psi_folder1
, *psi_file1
;
4032 IShellFolder
*pdesktopsf
;
4033 LPITEMIDLIST pidl_desktop
, pidl
;
4036 WCHAR curdirW
[MAX_PATH
];
4037 WCHAR buf
[MAX_PATH
];
4038 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4039 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4041 if(!pSHCreateShellItem
)
4043 skip("SHCreateShellItem missing.\n");
4047 hr
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
4048 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4051 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
4052 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4053 ILFree(pidl_desktop
);
4057 skip("Skipping tests.\n");
4063 /* Crashes on native (Win 7) */
4064 IShellItem_GetAttributes(psi
, 0, NULL
);
4067 /* Test GetAttributes on the desktop folder. */
4069 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
4070 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
4071 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
4073 IShellItem_Release(psi
);
4075 CreateFilesFolders();
4077 SHGetDesktopFolder(&pdesktopsf
);
4079 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4080 myPathAddBackslashW(curdirW
);
4082 lstrcpyW(buf
, curdirW
);
4083 lstrcatW(buf
, testdir1W
);
4084 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4085 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4086 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_folder1
);
4087 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4090 lstrcpyW(buf
, curdirW
);
4091 lstrcatW(buf
, testfile1W
);
4092 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4093 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4094 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_file1
);
4095 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4098 IShellFolder_Release(pdesktopsf
);
4101 hr
= IShellItem_GetAttributes(psi_folder1
, 0, &sfgao
);
4102 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4103 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4106 hr
= IShellItem_GetAttributes(psi_folder1
, SFGAO_FOLDER
, &sfgao
);
4107 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4108 ok(sfgao
== SFGAO_FOLDER
, "Got 0x%08x\n", sfgao
);
4111 hr
= IShellItem_GetAttributes(psi_file1
, SFGAO_FOLDER
, &sfgao
);
4112 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
4113 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4115 IShellItem_Release(psi_folder1
);
4116 IShellItem_Release(psi_file1
);
4121 static void test_ShellItemArrayGetAttributes(void)
4123 IShellItemArray
*psia_files
, *psia_folders1
, *psia_folders2
, *psia_all
;
4124 IShellFolder
*pdesktopsf
;
4125 LPCITEMIDLIST pidl_array
[5];
4128 WCHAR curdirW
[MAX_PATH
];
4129 WCHAR buf
[MAX_PATH
];
4131 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4132 static const WCHAR testdir2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
4133 static const WCHAR testdir3W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
4134 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4135 static const WCHAR testfile2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
4136 static const WCHAR
*testfilesW
[5] = { testdir1W
, testdir2W
, testdir3W
, testfile1W
, testfile2W
};
4138 if(!pSHCreateShellItemArrayFromShellItem
)
4140 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
4144 CreateFilesFolders();
4145 CreateDirectoryA(".\\testdir\\testdir3", NULL
);
4147 SHGetDesktopFolder(&pdesktopsf
);
4149 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4150 myPathAddBackslashW(curdirW
);
4152 for(i
= 0; i
< 5; i
++)
4154 lstrcpyW(buf
, curdirW
);
4155 lstrcatW(buf
, testfilesW
[i
]);
4156 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, (LPITEMIDLIST
*)&pidl_array
[i
], NULL
);
4157 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4159 IShellFolder_Release(pdesktopsf
);
4161 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia_folders1
);
4162 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4163 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[1], &psia_folders2
);
4164 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4165 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[3], &psia_files
);
4166 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4167 hr
= pSHCreateShellItemArrayFromIDLists(4, &pidl_array
[1], &psia_all
); /* All except the first */
4168 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4170 for(i
= 0; i
< 5; i
++)
4171 ILFree((LPITEMIDLIST
)pidl_array
[i
]);
4173 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
4175 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4176 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4177 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4179 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4180 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4181 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4183 /* [testfolder/testfolder2, testfolder/testfolder3] works */
4185 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4186 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4187 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4189 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4190 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4191 ok(attr
== 0, "Got 0x%08x\n", attr
);
4193 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4194 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4195 ok(attr
== 0, "Got 0x%08x\n", attr
);
4197 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4198 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4199 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4201 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4202 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4203 ok(attr
== 0, "Got 0x%08x\n", attr
);
4205 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4206 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4207 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4209 IShellItemArray_Release(psia_folders1
);
4210 IShellItemArray_Release(psia_folders2
);
4211 IShellItemArray_Release(psia_files
);
4212 IShellItemArray_Release(psia_all
);
4214 RemoveDirectoryA(".\\testdir\\testdir3");
4218 static WCHAR
*get_empty_cddrive(void)
4220 static WCHAR cdrom_drive
[] = {'A',':','\\',0};
4221 DWORD drives
= GetLogicalDrives();
4223 cdrom_drive
[0] = 'A';
4227 GetDriveTypeW(cdrom_drive
) == DRIVE_CDROM
&&
4228 GetFileAttributesW(cdrom_drive
) == INVALID_FILE_ATTRIBUTES
)
4233 drives
= drives
>> 1;
4239 static void test_SHParseDisplayName(void)
4241 LPITEMIDLIST pidl1
, pidl2
;
4242 IShellFolder
*desktop
;
4243 WCHAR dirW
[MAX_PATH
];
4251 /* crashes on native */
4252 SHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
4254 SHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
4257 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
4258 hr
= SHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
4259 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
4260 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
4261 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
4265 hr
= SHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
4266 ok(hr
== S_OK
, "failed %08x\n", hr
);
4267 hr
= SHGetDesktopFolder(&desktop
);
4268 ok(hr
== S_OK
, "failed %08x\n", hr
);
4269 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
4270 ok(hr
== S_OK
, "failed %08x\n", hr
);
4271 ret
= ILIsEqual(pidl1
, pidl2
);
4272 ok(ret
== TRUE
, "expected equal idls\n");
4277 GetWindowsDirectoryW( dirW
, MAX_PATH
);
4279 hr
= SHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4280 ok(hr
== S_OK
, "failed %08x\n", hr
);
4281 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
4282 ok(hr
== S_OK
, "failed %08x\n", hr
);
4284 ret
= ILIsEqual(pidl1
, pidl2
);
4285 ok(ret
== TRUE
, "expected equal idls\n");
4289 /* system32 is not redirected to syswow64 on WOW64 */
4290 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
4295 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
4296 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
4297 hr
= SHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4298 ok(hr
== S_OK
, "failed %08x\n", hr
);
4300 len
= GetSystemWow64DirectoryW(dirW
, MAX_PATH
);
4301 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
4302 hr
= SHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
4303 ok(hr
== S_OK
, "failed %08x\n", hr
);
4304 ret
= ILIsEqual(pidl1
, pidl2
);
4305 ok(ret
== FALSE
, "expected different idls\n");
4310 IShellFolder_Release(desktop
);
4312 cdrom
= get_empty_cddrive();
4314 skip("No empty cdrom drive found, skipping test\n");
4317 hr
= SHParseDisplayName(cdrom
, NULL
, &pidl1
, 0, NULL
);
4318 ok(hr
== S_OK
, "failed %08x\n", hr
);
4319 if (SUCCEEDED(hr
)) ILFree(pidl1
);
4323 static void test_desktop_IPersist(void)
4325 IShellFolder
*desktop
;
4327 IPersistFolder2
*ppf2
;
4331 hr
= SHGetDesktopFolder(&desktop
);
4332 ok(hr
== S_OK
, "failed %08x\n", hr
);
4334 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
4335 ok(hr
== S_OK
, "failed %08x\n", hr
);
4341 /* crashes on native */
4342 IPersist_GetClassID(persist
, NULL
);
4344 memset(&clsid
, 0, sizeof(clsid
));
4345 hr
= IPersist_GetClassID(persist
, &clsid
);
4346 ok(hr
== S_OK
, "failed %08x\n", hr
);
4347 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
4348 IPersist_Release(persist
);
4351 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
4352 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
4355 IPersistFolder
*ppf
;
4357 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
4358 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
4360 IPersistFolder_Release(ppf
);
4363 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
4364 ok(hr
== S_OK
, "got %08x\n", hr
);
4368 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
4369 ok(hr
== S_OK
, "got %08x\n", hr
);
4370 ok(pidl
!= NULL
, "pidl was NULL.\n");
4371 if(SUCCEEDED(hr
)) ILFree(pidl
);
4373 IPersistFolder2_Release(ppf2
);
4376 IShellFolder_Release(desktop
);
4379 static void test_contextmenu_qi(IContextMenu
*menu
, BOOL todo
)
4384 hr
= IContextMenu_QueryInterface(menu
, &IID_IShellExtInit
, (void **)&unk
);
4386 ok(hr
== S_OK
, "Failed to get IShellExtInit, hr %#x.\n", hr
);
4388 IUnknown_Release(unk
);
4390 hr
= IContextMenu_QueryInterface(menu
, &IID_IObjectWithSite
, (void **)&unk
);
4392 ok(hr
== S_OK
, "Failed to get IShellExtInit, hr %#x.\n", hr
);
4394 IUnknown_Release(unk
);
4397 static void test_contextmenu(IContextMenu
*menu
, BOOL background
)
4399 HMENU hmenu
= CreatePopupMenu();
4400 const int id_upper_limit
= 32767;
4401 const int baseItem
= 0x40;
4402 INT max_id
, max_id_check
;
4406 test_contextmenu_qi(menu
, FALSE
);
4408 hr
= IContextMenu_QueryContextMenu(menu
, hmenu
, 0, baseItem
, id_upper_limit
, CMF_NORMAL
);
4409 ok(SUCCEEDED(hr
), "Failed to query the menu, hr %#x.\n", hr
);
4411 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
4412 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
4413 count
= GetMenuItemCount(hmenu
);
4414 ok(count
, "Got %d\n", count
);
4417 for (i
= 0; i
< count
; i
++)
4421 char buf
[255], buf2
[255];
4422 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
4423 mii
.cbSize
= sizeof(MENUITEMINFOA
);
4424 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
| MIIM_STRING
;
4425 mii
.dwTypeData
= buf2
;
4426 mii
.cch
= sizeof(buf2
);
4428 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
4429 ok(res
, "Failed to get menu item info, error %d.\n", GetLastError());
4431 ok((mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
4432 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
4433 if (!(mii
.fType
& MFT_SEPARATOR
))
4435 max_id_check
= (mii
.wID
> max_id_check
) ? mii
.wID
: max_id_check
;
4436 hr
= IContextMenu_GetCommandString(menu
, mii
.wID
- baseItem
, GCS_VERBA
, 0, buf
, sizeof(buf
));
4437 todo_wine_if(background
)
4438 ok(SUCCEEDED(hr
) || hr
== E_NOTIMPL
, "for id 0x%x got 0x%08x (menustr: %s)\n", mii
.wID
- baseItem
, hr
, mii
.dwTypeData
);
4440 trace("for id 0x%x got string %s (menu string: %s)\n", mii
.wID
- baseItem
, buf
, mii
.dwTypeData
);
4441 else if (hr
== E_NOTIMPL
)
4442 trace("for id 0x%x got E_NOTIMPL (menu string: %s)\n", mii
.wID
- baseItem
, mii
.dwTypeData
);
4445 max_id_check
-= baseItem
;
4446 ok((max_id_check
== max_id
) ||
4447 (max_id_check
== max_id
-1) || /* Win 7 */
4448 (max_id_check
== max_id
-2) || /* Win 8 */
4449 (max_id_check
== max_id
-3),
4450 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
4454 CMINVOKECOMMANDINFO cmi
;
4456 memset(&cmi
, 0, sizeof(CMINVOKECOMMANDINFO
));
4457 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
4459 /* Attempt to execute a nonexistent command */
4460 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
4461 hr
= IContextMenu_InvokeCommand(menu
, &cmi
);
4462 todo_wine_if(background
)
4463 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4465 cmi
.lpVerb
= "foobar_wine_test";
4466 hr
= IContextMenu_InvokeCommand(menu
, &cmi
);
4467 todo_wine_if(background
)
4468 ok((hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
4469 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
4470 "Unexpected hr %#x.\n", hr
);
4476 static void test_GetUIObject(void)
4478 IShellFolder
*psf_desktop
;
4482 WCHAR path
[MAX_PATH
];
4483 const WCHAR filename
[] =
4484 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4485 LPCITEMIDLIST pidl_child
;
4488 GetCurrentDirectoryW(MAX_PATH
, path
);
4491 skip("GetCurrentDirectoryW returned an empty string.\n");
4494 lstrcatW(path
, filename
);
4495 SHGetDesktopFolder(&psf_desktop
);
4497 CreateFilesFolders();
4499 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4500 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4502 hr
= SHBindToParent(pidl
, &IID_IShellFolder
, (void **)&psf
, &pidl_child
);
4503 ok(hr
== S_OK
, "Failed to bind to folder, hr %#x.\n", hr
);
4506 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
, (void **)&pcm
);
4507 ok(hr
== S_OK
, "GetUIObjectOf() failed, hr %#x.\n", hr
);
4508 test_contextmenu(pcm
, FALSE
);
4509 IContextMenu_Release(pcm
);
4511 /* Background menu */
4512 hr
= IShellFolder_GetUIObjectOf(psf_desktop
, NULL
, 0, NULL
, &IID_IContextMenu
, NULL
, (void **)&pcm
);
4513 ok(hr
== S_OK
, "GetUIObjectOf() failed, hr %#x.\n", hr
);
4514 test_contextmenu(pcm
, TRUE
);
4515 IContextMenu_Release(pcm
);
4517 IShellFolder_Release(psf
);
4520 IShellFolder_Release(psf_desktop
);
4524 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
4525 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
4527 LPCITEMIDLIST child
;
4528 IShellFolder
*parent
;
4534 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
4538 hr
= SHBindToParent(pidl
, &IID_IShellFolder
, (void **)&parent
, &child
);
4539 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4543 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4544 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4546 IShellFolder_Release(parent
);
4550 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4551 "Got unexpected string type: %d\n", filename
.uType
);
4552 if(filename
.uType
== STRRET_WSTR
){
4553 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4554 "didn't get expected path (%s), instead: %s\n",
4555 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4556 SHFree(U(filename
).pOleStr
);
4557 }else if(filename
.uType
== STRRET_CSTR
){
4558 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4559 "didn't get expected path (%s), instead: %s\n",
4560 wine_dbgstr_w(path
), U(filename
).cStr
);
4563 IShellFolder_Release(parent
);
4565 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4568 static void test_SHSimpleIDListFromPath(void)
4570 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4571 const CHAR adirA
[] = "C:\\sidlfpdir";
4572 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4574 LPITEMIDLIST pidl
= NULL
;
4576 br
= CreateDirectoryA(adirA
, NULL
);
4577 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4580 pidl
= SHSimpleIDListFromPath(adirW
);
4582 pidl
= SHSimpleIDListFromPath((const WCHAR
*)adirA
);
4583 verify_pidl(pidl
, adirW
);
4586 br
= RemoveDirectoryA(adirA
);
4587 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4590 pidl
= SHSimpleIDListFromPath(adirW
);
4592 pidl
= SHSimpleIDListFromPath((const WCHAR
*)adirA
);
4593 verify_pidl(pidl
, adirW
);
4597 /* IFileSystemBindData impl */
4598 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4599 REFIID riid
, void **ppv
)
4601 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4602 IsEqualIID(riid
, &IID_IUnknown
)){
4606 return E_NOINTERFACE
;
4609 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4614 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4619 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4620 const WIN32_FIND_DATAW
*pfd
)
4622 ok(0, "SetFindData called\n");
4626 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4627 WIN32_FIND_DATAW
*pfd
)
4629 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4633 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4634 WIN32_FIND_DATAW
*pfd
)
4636 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4640 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4641 WIN32_FIND_DATAW
*pfd
)
4643 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4644 *pfd
->cFileName
= 'a';
4645 *pfd
->cAlternateFileName
= 'a';
4649 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4650 WIN32_FIND_DATAW
*pfd
)
4652 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4653 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4658 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4659 WIN32_FIND_DATAW
*pfd
)
4664 static IFileSystemBindDataVtbl fsbdVtbl
= {
4665 fsbd_QueryInterface
,
4672 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4674 static void test_ParseDisplayNamePBC(void)
4676 WCHAR wFileSystemBindData
[] =
4677 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4678 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4679 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4680 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4681 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4688 /* Check if we support WCHAR functions */
4689 SetLastError(0xdeadbeef);
4690 lstrcmpiW(adirW
, adirW
);
4691 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4692 win_skip("Most W-calls are not implemented\n");
4696 hres
= SHGetDesktopFolder(&psf
);
4697 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4699 win_skip("Failed to get IShellFolder, can't run tests\n");
4703 /* fails on unknown dir with no IBindCtx */
4704 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4705 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4706 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4707 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4708 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4709 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4711 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4712 hres
= CreateBindCtx(0, &pbc
);
4713 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4715 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4716 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4717 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4718 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4719 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4720 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4722 /* unknown dir with IBindCtx with IFileSystemBindData */
4723 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4724 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4726 /* return E_FAIL from GetFindData */
4727 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4728 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4729 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4730 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4731 if(SUCCEEDED(hres
)){
4732 verify_pidl(pidl
, adirW
);
4736 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4737 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4738 if(SUCCEEDED(hres
)){
4739 verify_pidl(pidl
, afileW
);
4743 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4744 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4745 if(SUCCEEDED(hres
)){
4746 verify_pidl(pidl
, afile2W
);
4750 /* set FIND_DATA struct to NULLs */
4751 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4752 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4753 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4754 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4755 if(SUCCEEDED(hres
)){
4756 verify_pidl(pidl
, adirW
);
4760 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4761 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4762 if(SUCCEEDED(hres
)){
4763 verify_pidl(pidl
, afileW
);
4767 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4768 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4769 if(SUCCEEDED(hres
)){
4770 verify_pidl(pidl
, afile2W
);
4774 /* set FIND_DATA struct to junk */
4775 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4776 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4777 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4778 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4779 if(SUCCEEDED(hres
)){
4780 verify_pidl(pidl
, adirW
);
4784 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4785 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4786 if(SUCCEEDED(hres
)){
4787 verify_pidl(pidl
, afileW
);
4791 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4792 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4793 if(SUCCEEDED(hres
)){
4794 verify_pidl(pidl
, afile2W
);
4798 /* set FIND_DATA struct to invalid data */
4799 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4800 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4801 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4802 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4803 if(SUCCEEDED(hres
)){
4804 verify_pidl(pidl
, adirW
);
4808 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4809 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4810 if(SUCCEEDED(hres
)){
4811 verify_pidl(pidl
, afileW
);
4815 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4816 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4817 if(SUCCEEDED(hres
)){
4818 verify_pidl(pidl
, afile2W
);
4822 /* set FIND_DATA struct to valid data */
4823 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4824 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4825 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4826 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4827 if(SUCCEEDED(hres
)){
4828 verify_pidl(pidl
, adirW
);
4832 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4833 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4834 if(SUCCEEDED(hres
)){
4835 verify_pidl(pidl
, afileW
);
4839 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4840 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4841 if(SUCCEEDED(hres
)){
4842 verify_pidl(pidl
, afile2W
);
4846 IBindCtx_Release(pbc
);
4847 IShellFolder_Release(psf
);
4850 static const CHAR testwindow_class
[] = "testwindow";
4851 #define WM_USER_NOTIFY (WM_APP+1)
4853 struct ChNotifyTest
{
4855 const UINT notify_count
;
4856 UINT missing_events
;
4858 const char path_1
[256];
4859 const char path_2
[256];
4860 } chnotify_tests
[] = {
4861 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
4862 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
4863 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
4866 struct ChNotifyTest
*exp_data
;
4867 BOOL test_new_delivery_flag
;
4869 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4871 LONG signal
= (LONG
)lparam
;
4874 case WM_USER_NOTIFY
:
4875 if(exp_data
->missing_events
> 0) {
4876 WCHAR
*path1
, *path2
;
4877 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
4878 HANDLE hLock
= NULL
;
4880 if(test_new_delivery_flag
) {
4881 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
4882 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
4885 ok(exp_data
->signal
== signal
,
4886 "%s: expected notification type %x, got: %x\n",
4887 exp_data
->id
, exp_data
->signal
, signal
);
4889 trace("verifying pidls for: %s\n", exp_data
->id
);
4890 path1
= make_wstr(exp_data
->path_1
);
4891 path2
= make_wstr(exp_data
->path_2
);
4892 verify_pidl(pidls
[0], path1
);
4893 verify_pidl(pidls
[1], path2
);
4897 exp_data
->missing_events
--;
4899 if(test_new_delivery_flag
)
4900 SHChangeNotification_Unlock(hLock
);
4902 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4905 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
4908 static void register_testwindow_class(void)
4913 ZeroMemory(&cls
, sizeof(cls
));
4914 cls
.cbSize
= sizeof(cls
);
4916 cls
.lpfnWndProc
= testwindow_wndproc
;
4917 cls
.hInstance
= GetModuleHandleA(NULL
);
4918 cls
.lpszClassName
= testwindow_class
;
4921 ret
= RegisterClassExA(&cls
);
4922 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4925 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4926 * have to poll repeatedly for the message to appear */
4927 static void do_events(void)
4930 while (exp_data
->missing_events
&& (c
++ < 10)){
4932 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4933 TranslateMessage(&msg
);
4934 DispatchMessageA(&msg
);
4936 if(exp_data
->missing_events
)
4939 trace("%s: took %d tries\n", exp_data
->id
, c
);
4942 static void test_SHChangeNotify(BOOL test_new_delivery
)
4947 BOOL br
, has_unicode
;
4948 SHChangeNotifyEntry entries
[1];
4949 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4950 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4952 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
4954 CreateDirectoryW(NULL
, NULL
);
4955 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
4957 test_new_delivery_flag
= test_new_delivery
;
4958 if(!test_new_delivery
)
4959 register_testwindow_class();
4961 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
4962 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
4963 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
4964 ok(wnd
!= NULL
, "Failed to make a window\n");
4966 br
= CreateDirectoryA(root_dirA
, NULL
);
4967 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4969 entries
[0].pidl
= NULL
;
4971 hr
= SHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4973 hr
= SHILCreateFromPath((const void *)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4974 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
4975 entries
[0].fRecursive
= TRUE
;
4977 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
4978 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
4979 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
4981 for (i
= 0; i
< ARRAY_SIZE(chnotify_tests
); ++i
)
4983 exp_data
= chnotify_tests
+ i
;
4985 exp_data
->missing_events
= exp_data
->notify_count
;
4986 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
4987 exp_data
->path_1
[0] ? exp_data
->path_1
: NULL
,
4988 exp_data
->path_2
[0] ? exp_data
->path_2
: NULL
);
4990 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4993 WCHAR
*path1
, *path2
;
4995 path1
= make_wstr(exp_data
->path_1
);
4996 path2
= make_wstr(exp_data
->path_2
);
4998 exp_data
->missing_events
= exp_data
->notify_count
;
4999 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
5001 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
5008 SHChangeNotifyDeregister(notifyID
);
5011 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
5012 br
= RemoveDirectoryA(root_dirA
);
5013 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
5016 static void test_SHCreateDefaultContextMenu(void)
5019 WCHAR path
[MAX_PATH
];
5020 IShellFolder
*desktop
,*folder
;
5021 IPersistFolder2
*persist
;
5022 IContextMenu
*cmenu
;
5024 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
5025 DEFCONTEXTMENU cminfo
;
5028 const WCHAR filename
[] =
5029 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
5030 if(!pSHCreateDefaultContextMenu
)
5032 win_skip("SHCreateDefaultContextMenu missing.\n");
5036 GetCurrentDirectoryW(MAX_PATH
, path
);
5039 skip("GetCurrentDirectoryW returned an empty string.\n");
5042 lstrcatW(path
, filename
);
5043 SHGetDesktopFolder(&desktop
);
5045 CreateFilesFolders();
5047 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
5048 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5051 hr
= SHBindToParent(pidl
, &IID_IShellFolder
, (void **)&folder
, (const ITEMIDLIST
**)&pidl_child
);
5052 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5054 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
5055 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
5056 IPersistFolder2_Release(persist
);
5062 cminfo
.pidlFolder
=NULL
;
5063 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
5067 cminfo
.punkAssociationInfo
=NULL
;
5069 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5070 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5071 test_contextmenu_qi(cmenu
, TRUE
);
5072 IContextMenu_Release(cmenu
);
5074 cminfo
.pidlFolder
=pidlFolder
;
5075 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5076 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5077 test_contextmenu_qi(cmenu
, TRUE
);
5078 IContextMenu_Release(cmenu
);
5080 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
5081 if(status
==ERROR_SUCCESS
){
5086 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5087 RegCloseKey(keys
[0]);
5088 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5089 IContextMenu_Release(cmenu
);
5093 IShellFolder_Release(folder
);
5095 IShellFolder_Release(desktop
);
5100 static void test_DataObject(void)
5102 IShellFolder
*desktop
;
5103 IDataObject
*data_obj
;
5108 DWORD cf_shellidlist
;
5111 SHGetDesktopFolder(&desktop
);
5113 hres
= IShellFolder_EnumObjects(desktop
, NULL
,
5114 SHCONTF_NONFOLDERS
|SHCONTF_FOLDERS
|SHCONTF_INCLUDEHIDDEN
, &peidl
);
5115 ok(hres
== S_OK
, "got %x\n", hres
);
5117 if(IEnumIDList_Next(peidl
, 1, &apidl
, NULL
) != S_OK
) {
5118 skip("no files on desktop - skipping GetDataObject tests\n");
5119 IEnumIDList_Release(peidl
);
5120 IShellFolder_Release(desktop
);
5123 IEnumIDList_Release(peidl
);
5125 hres
= IShellFolder_GetUIObjectOf(desktop
, NULL
, 1, (LPCITEMIDLIST
*)&apidl
,
5126 &IID_IDataObject
, NULL
, (void**)&data_obj
);
5127 ok(hres
== S_OK
, "got %x\n", hres
);
5129 IShellFolder_Release(desktop
);
5131 cf_shellidlist
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
5132 fmt
.cfFormat
= cf_shellidlist
;
5134 fmt
.dwAspect
= DVASPECT_CONTENT
;
5136 fmt
.tymed
= TYMED_HGLOBAL
;
5137 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5138 ok(hres
== S_OK
, "got %x\n", hres
);
5140 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5141 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5142 ok(hres
== S_OK
, "got %x\n", hres
);
5144 fmt
.tymed
= TYMED_ISTREAM
;
5145 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5146 todo_wine
ok(hres
== S_FALSE
, "got %x\n", hres
);
5148 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5149 hres
= IDataObject_GetData(data_obj
, &fmt
, &medium
);
5150 ok(hres
== S_OK
, "got %x\n", hres
);
5151 ok(medium
.tymed
== TYMED_HGLOBAL
, "medium.tymed = %x\n", medium
.tymed
);
5152 ReleaseStgMedium(&medium
);
5154 IDataObject_Release(data_obj
);
5157 static void test_GetDefaultColumn(void)
5159 static const CLSID
*folders
[] =
5163 &CLSID_ControlPanel
,
5164 &CLSID_NetworkPlaces
,
5167 &CLSID_ShellDesktop
,
5174 for (i
= 0; i
< ARRAY_SIZE(folders
); i
++)
5176 IShellFolder2
*folder
;
5177 ULONG sort
, display
;
5179 hr
= CoCreateInstance(folders
[i
], NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellFolder2
, (void **)&folder
);
5182 win_skip("Failed to create folder %s, hr %#x.\n", wine_dbgstr_guid(folders
[i
]), hr
);
5186 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, NULL
, NULL
);
5187 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5189 sort
= display
= 123;
5190 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, &sort
, &display
);
5191 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5192 ok(sort
== 123 && display
== 123, "Unexpected default column.\n");
5195 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, NULL
, &display
);
5196 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5197 ok(display
== 123, "Unexpected default column.\n");
5200 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, &sort
, NULL
);
5201 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5202 ok(sort
== 123, "Unexpected default column.\n");
5204 IShellFolder2_Release(folder
);
5210 static void test_GetDefaultSearchGUID(void)
5212 static const CLSID
*folders
[] =
5216 &CLSID_ControlPanel
,
5217 &CLSID_NetworkPlaces
,
5220 &CLSID_ShellDesktop
,
5227 for (i
= 0; i
< ARRAY_SIZE(folders
); i
++)
5229 IShellFolder2
*folder
;
5232 hr
= CoCreateInstance(folders
[i
], NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellFolder2
, (void **)&folder
);
5235 win_skip("Failed to create folder %s, hr %#x.\n", wine_dbgstr_guid(folders
[i
]), hr
);
5242 hr
= IShellFolder2_GetDefaultSearchGUID(folder
, NULL
);
5243 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5246 memcpy(&guid
, &CLSID_MyComputer
, sizeof(guid
));
5247 hr
= IShellFolder2_GetDefaultSearchGUID(folder
, &guid
);
5248 ok(hr
== E_NOTIMPL
|| broken(hr
== S_OK
) /* Method was last supported on XP */, "Unexpected hr %#x.\n", hr
);
5249 if (hr
== E_NOTIMPL
)
5250 ok(IsEqualGUID(&guid
, &CLSID_MyComputer
), "Unexpected guid %s.\n", wine_dbgstr_guid(&guid
));
5252 IShellFolder2_Release(folder
);
5258 static void test_SHLimitInputEdit(void)
5260 IShellFolder
*desktop
;
5264 hr
= SHGetDesktopFolder(&desktop
);
5265 ok(hr
== S_OK
, "Failed to get desktop folder, hr %#x.\n", hr
);
5267 hr
= SHLimitInputEdit(NULL
, desktop
);
5269 ok(hr
== E_FAIL
, "Unexpected hr %#x.\n", hr
);
5271 hwnd
= CreateWindowA("EDIT", NULL
, WS_VISIBLE
, 0, 0, 100, 30, NULL
, NULL
, NULL
, NULL
);
5272 ok(hwnd
!= NULL
, "Failed to create Edit control.\n");
5274 hr
= SHLimitInputEdit(hwnd
, desktop
);
5276 ok(hr
== S_OK
, "Failed to set input limits, hr %#x.\n", hr
);
5278 hr
= SHLimitInputEdit(hwnd
, desktop
);
5280 ok(hr
== S_OK
, "Failed to set input limits, hr %#x.\n", hr
);
5282 DestroyWindow(hwnd
);
5283 IShellFolder_Release(desktop
);
5286 static void test_SHGetSetFolderCustomSettings(void)
5289 SHFOLDERCUSTOMSETTINGS fcs
;
5290 WCHAR pathW
[MAX_PATH
];
5291 WCHAR bufferW
[MAX_PATH
];
5292 WCHAR iconpathW
[MAX_PATH
];
5293 static const WCHAR somedirW
[] = {'s','o','m','e','_','d','i','r',0};
5294 static const WCHAR iconW
[] = {'\\','s','o','m','e','_','i','c','o','n','.','i','c','o',0};
5295 static const WCHAR desktop_iniW
[] = {'\\','D','e','s','k','t','o','p','.','i','n','i',0};
5297 if (!pSHGetSetFolderCustomSettings
)
5299 win_skip("SHGetSetFolderCustomSetting not exported by name (only by ordinal) for version XP/win2003\n");
5303 GetTempPathW(MAX_PATH
, pathW
);
5304 lstrcatW(pathW
, somedirW
);
5305 CreateDirectoryW(pathW
, NULL
);
5307 lstrcpyW(iconpathW
, pathW
);
5308 lstrcatW(iconpathW
, iconW
);
5310 memset(&fcs
, 0, sizeof(fcs
));
5311 fcs
.dwSize
= sizeof(fcs
);
5312 fcs
.dwMask
= FCSM_ICONFILE
;
5313 fcs
.pszIconFile
= iconpathW
;
5315 hr
= pSHGetSetFolderCustomSettings(&fcs
, pathW
, FCS_FORCEWRITE
); /*creates and writes to a Desktop.ini*/
5316 ok(hr
== S_OK
, "Expected S_OK, got %#x\n", hr
);
5318 memset(&fcs
, 0, sizeof(fcs
));
5319 fcs
.dwSize
= sizeof(fcs
);
5320 fcs
.dwMask
= FCSM_ICONFILE
;
5321 fcs
.cchIconFile
= MAX_PATH
;
5322 fcs
.pszIconFile
= bufferW
;
5325 hr
= pSHGetSetFolderCustomSettings(&fcs
, pathW
, FCS_READ
);
5326 todo_wine
ok(hr
== S_OK
, "Expected S_OK, got %#x\n", hr
);
5327 todo_wine
ok(!lstrcmpiW(iconpathW
, fcs
.pszIconFile
), "Expected %s, got %s\n", wine_dbgstr_w(iconpathW
), wine_dbgstr_w(fcs
.pszIconFile
));
5329 hr
= pSHGetSetFolderCustomSettings(&fcs
, NULL
, FCS_READ
);
5330 ok(hr
== E_FAIL
, "Expected E_FAIL, got %#x\n", hr
);
5332 lstrcpyW(bufferW
, pathW
);
5333 lstrcatW(bufferW
, desktop_iniW
);
5334 DeleteFileW(bufferW
);
5335 RemoveDirectoryW(pathW
);
5338 START_TEST(shlfolder
)
5340 init_function_pointers();
5341 /* if OleInitialize doesn't get called, ParseDisplayName returns
5342 CO_E_NOTINITIALIZED for malformed directory names */
5343 OleInitialize(NULL
);
5345 test_ParseDisplayName();
5346 test_SHParseDisplayName();
5347 test_BindToObject();
5348 test_EnumObjects_and_CompareIDs();
5349 test_GetDisplayName();
5350 test_GetAttributesOf();
5351 test_SHGetPathFromIDList();
5352 test_CallForAttributes();
5353 test_FolderShortcut();
5354 test_ITEMIDLIST_format();
5355 test_SHGetFolderPathA();
5356 test_SHGetFolderPathAndSubDirA();
5357 test_LocalizedNames();
5358 test_SHCreateShellItem();
5359 test_SHCreateShellItemArray();
5360 test_ShellItemArrayEnumItems();
5361 test_desktop_IPersist();
5363 test_SHSimpleIDListFromPath();
5364 test_ParseDisplayNamePBC();
5365 test_SHGetNameFromIDList();
5366 test_SHGetItemFromDataObject();
5367 test_SHGetIDListFromObject();
5368 test_SHGetItemFromObject();
5369 test_ShellItemCompare();
5370 test_SHChangeNotify(FALSE
);
5371 test_SHChangeNotify(TRUE
);
5372 test_ShellItemBindToHandler();
5373 test_ShellItemGetAttributes();
5374 test_ShellItemArrayGetAttributes();
5375 test_SHCreateDefaultContextMenu();
5377 test_GetDefaultColumn();
5378 test_GetDefaultSearchGUID();
5379 test_SHLimitInputEdit();
5380 test_SHGetSetFolderCustomSettings();