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/test.h"
43 DEFINE_GUID(IID_IParentAndItem
, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
44 DEFINE_GUID(CLSID_ShellDocObjView
, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
48 static HRESULT (WINAPI
*pSHBindToParent
)(LPCITEMIDLIST
, REFIID
, LPVOID
*, LPCITEMIDLIST
*);
49 static HRESULT (WINAPI
*pSHGetFolderPathA
)(HWND
, int, HANDLE
, DWORD
, LPSTR
);
50 static HRESULT (WINAPI
*pSHGetFolderPathAndSubDirA
)(HWND
, int, HANDLE
, DWORD
, LPCSTR
, LPSTR
);
51 static BOOL (WINAPI
*pSHGetPathFromIDListW
)(LPCITEMIDLIST
,LPWSTR
);
52 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
53 static BOOL (WINAPI
*pSHGetSpecialFolderPathA
)(HWND
, LPSTR
, int, BOOL
);
54 static BOOL (WINAPI
*pSHGetSpecialFolderPathW
)(HWND
, LPWSTR
, int, BOOL
);
55 static HRESULT (WINAPI
*pStrRetToBufW
)(STRRET
*,LPCITEMIDLIST
,LPWSTR
,UINT
);
56 static LPITEMIDLIST (WINAPI
*pILFindLastID
)(LPCITEMIDLIST
);
57 static void (WINAPI
*pILFree
)(LPITEMIDLIST
);
58 static BOOL (WINAPI
*pILIsEqual
)(LPCITEMIDLIST
, LPCITEMIDLIST
);
59 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
60 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
61 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
62 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
63 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromIDLists
)(UINT
, PCIDLIST_ABSOLUTE
*, IShellItemArray
**);
64 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
65 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
66 static LPITEMIDLIST (WINAPI
*pILCombine
)(LPCITEMIDLIST
,LPCITEMIDLIST
);
67 static HRESULT (WINAPI
*pSHParseDisplayName
)(LPCWSTR
,IBindCtx
*,LPITEMIDLIST
*,SFGAOF
,SFGAOF
*);
68 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathAW
)(LPCVOID
);
69 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
70 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
71 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
72 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
73 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
74 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)(LPWSTR
, UINT
);
75 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
76 static HRESULT (WINAPI
*pSHCreateShellFolderView
)(const SFV_CREATE
*pcsfv
, IShellView
**ppsv
);
77 static HRESULT (WINAPI
*pSHCreateShellFolderViewEx
)(LPCSFV psvcbi
, IShellView
**ppv
);
78 static HRESULT (WINAPI
*pSHILCreateFromPath
)(LPCWSTR
, LPITEMIDLIST
*,DWORD
*);
79 static BOOL (WINAPI
*pSHGetPathFromIDListEx
)(PCIDLIST_ABSOLUTE
,WCHAR
*,DWORD
,GPFIDL_FLAGS
);
81 static WCHAR
*make_wstr(const char *str
)
89 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
93 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
97 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
101 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
104 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
105 return lstrcmpA(stra
, buf
);
108 static void init_function_pointers(void)
114 hmod
= GetModuleHandleA("shell32.dll");
116 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
117 MAKEFUNC(SHBindToParent
);
118 MAKEFUNC(SHCreateItemFromIDList
);
119 MAKEFUNC(SHCreateItemFromParsingName
);
120 MAKEFUNC(SHCreateShellItem
);
121 MAKEFUNC(SHCreateShellItemArray
);
122 MAKEFUNC(SHCreateShellItemArrayFromIDLists
);
123 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
124 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
125 MAKEFUNC(SHGetFolderPathA
);
126 MAKEFUNC(SHGetFolderPathAndSubDirA
);
127 MAKEFUNC(SHGetPathFromIDListW
);
128 MAKEFUNC(SHGetSpecialFolderPathA
);
129 MAKEFUNC(SHGetSpecialFolderPathW
);
130 MAKEFUNC(SHGetSpecialFolderLocation
);
131 MAKEFUNC(SHParseDisplayName
);
132 MAKEFUNC(SHGetNameFromIDList
);
133 MAKEFUNC(SHGetItemFromDataObject
);
134 MAKEFUNC(SHGetIDListFromObject
);
135 MAKEFUNC(SHGetItemFromObject
);
136 MAKEFUNC(SHCreateDefaultContextMenu
);
137 MAKEFUNC(SHCreateShellFolderView
);
138 MAKEFUNC(SHCreateShellFolderViewEx
);
139 MAKEFUNC(SHGetPathFromIDListEx
);
142 #define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
143 MAKEFUNC_ORD(ILFindLastID
, 16);
144 MAKEFUNC_ORD(ILIsEqual
, 21);
145 MAKEFUNC_ORD(ILCombine
, 25);
146 MAKEFUNC_ORD(SHILCreateFromPath
, 28);
147 MAKEFUNC_ORD(ILFree
, 155);
148 MAKEFUNC_ORD(SHSimpleIDListFromPathAW
, 162);
151 /* test named exports */
152 ptr
= GetProcAddress(hmod
, "ILFree");
153 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
156 #define TESTNAMED(f) \
157 ptr = (void*)GetProcAddress(hmod, #f); \
158 ok(ptr != 0, "expected named export for " #f "\n");
160 TESTNAMED(ILAppendID
);
162 TESTNAMED(ILCloneFirst
);
163 TESTNAMED(ILCombine
);
164 TESTNAMED(ILCreateFromPath
);
165 TESTNAMED(ILCreateFromPathA
);
166 TESTNAMED(ILCreateFromPathW
);
167 TESTNAMED(ILFindChild
);
168 TESTNAMED(ILFindLastID
);
169 TESTNAMED(ILGetNext
);
170 TESTNAMED(ILGetSize
);
171 TESTNAMED(ILIsEqual
);
172 TESTNAMED(ILIsParent
);
173 TESTNAMED(ILRemoveLastID
);
174 TESTNAMED(ILSaveToStream
);
178 hmod
= GetModuleHandleA("shlwapi.dll");
179 pStrRetToBufW
= (void*)GetProcAddress(hmod
, "StrRetToBufW");
181 hmod
= GetModuleHandleA("kernel32.dll");
182 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
183 pGetSystemWow64DirectoryW
= (void*)GetProcAddress(hmod
, "GetSystemWow64DirectoryW");
185 hr
= SHGetMalloc(&ppM
);
186 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
189 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
190 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
194 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
200 if (lpszPath
[-1] != '\\')
209 static void test_ParseDisplayName(void)
212 IShellFolder
*IDesktopFolder
;
213 static const char *cNonExistDir1A
= "c:\\nonexist_subdir";
214 static const char *cNonExistDir2A
= "c:\\\\nonexist_subdir";
215 static const char *cInetTestA
= "http:\\yyy";
216 static const char *cInetTest2A
= "xx:yyy";
218 WCHAR cTestDirW
[MAX_PATH
] = {0};
222 hr
= SHGetDesktopFolder(&IDesktopFolder
);
223 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
224 if(hr
!= S_OK
) return;
226 /* Tests crash on W2K and below (SHCreateShellItem available as of XP) */
227 if (pSHCreateShellItem
)
231 /* null name and pidl, also crashes on Windows 8 */
232 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
,
233 NULL
, NULL
, NULL
, 0);
234 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
238 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
239 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
240 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
241 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
242 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
245 win_skip("Tests would crash on W2K and below\n");
247 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
248 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
249 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
250 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
251 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
254 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
255 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
256 IMalloc_Free(ppM
, newPIDL
);
259 MultiByteToWideChar(CP_ACP
, 0, cInetTest2A
, -1, cTestDirW
, MAX_PATH
);
260 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
261 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
262 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
263 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
266 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
267 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
268 IMalloc_Free(ppM
, newPIDL
);
271 res
= GetFileAttributesA(cNonExistDir1A
);
272 if(res
!= INVALID_FILE_ATTRIBUTES
)
274 skip("Test directory unexpectedly exists\n");
278 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
279 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
280 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
281 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
),
282 "ParseDisplayName returned %08x, expected 80070002 or E_FAIL\n", hr
);
284 res
= GetFileAttributesA(cNonExistDir2A
);
285 if(res
!= INVALID_FILE_ATTRIBUTES
)
287 skip("Test directory unexpectedly exists\n");
291 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
292 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
293 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
294 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
295 "ParseDisplayName returned %08x, expected 80070002, E_FAIL or E_INVALIDARG\n", hr
);
297 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
298 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
299 * out it doesn't. The magic seems to happen in the file dialogs, then. */
300 if (!pSHGetSpecialFolderPathW
|| !pILFindLastID
)
302 win_skip("SHGetSpecialFolderPathW and/or ILFindLastID are not available\n");
306 bRes
= pSHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
307 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
308 if (!bRes
) goto finished
;
310 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
311 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
312 if (hr
!= S_OK
) goto finished
;
314 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31 ||
315 pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0xb1, /* Win98 */
316 "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
317 pILFindLastID(newPIDL
)->mkid
.abID
[0]);
318 IMalloc_Free(ppM
, newPIDL
);
321 IShellFolder_Release(IDesktopFolder
);
324 /* creates a file with the specified name for tests */
325 static void CreateTestFile(const CHAR
*name
)
330 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
331 if (file
!= INVALID_HANDLE_VALUE
)
333 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
334 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
340 /* initializes the tests */
341 static void CreateFilesFolders(void)
343 CreateDirectoryA(".\\testdir", NULL
);
344 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
345 CreateTestFile (".\\testdir\\test1.txt ");
346 CreateTestFile (".\\testdir\\test2.txt ");
347 CreateTestFile (".\\testdir\\test3.txt ");
348 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
349 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
352 /* cleans after tests */
353 static void Cleanup(void)
355 DeleteFileA(".\\testdir\\test1.txt");
356 DeleteFileA(".\\testdir\\test2.txt");
357 DeleteFileA(".\\testdir\\test3.txt");
358 RemoveDirectoryA(".\\testdir\\test.txt");
359 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
360 RemoveDirectoryA(".\\testdir\\testdir2");
361 RemoveDirectoryA(".\\testdir");
366 static void test_EnumObjects(IShellFolder
*iFolder
)
368 IEnumIDList
*iEnumList
;
369 LPITEMIDLIST newPIDL
, idlArr
[10];
374 static const WORD iResults
[5][5] =
383 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
384 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
385 static const ULONG attrs
[5] =
387 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
388 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
389 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
390 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
391 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
393 static const ULONG full_attrs
[5] =
395 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
396 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
397 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
398 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
399 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
402 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
403 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
405 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
406 * the filesystem shellfolders return S_OK even if less than 'celt' items are
407 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
408 * only ever returns a single entry per call. */
409 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
411 ok (i
== 5, "i: %d\n", i
);
413 hr
= IEnumIDList_Release(iEnumList
);
414 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
416 /* Sort them first in case of wrong order from system */
417 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
418 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
421 idlArr
[i
] = idlArr
[j
];
425 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
427 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
428 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
432 for (i
= 0; i
< 5; i
++)
435 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
436 /* Native returns all flags no matter what we ask for */
437 flags
= SFGAO_CANCOPY
;
438 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
439 flags
&= SFGAO_testfor
;
440 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
441 ok(flags
== (attrs
[i
]) ||
442 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
) || /* Win9x, NT4 */
443 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
444 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
446 flags
= SFGAO_testfor
;
447 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
448 flags
&= SFGAO_testfor
;
449 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
450 ok(flags
== attrs
[i
] ||
451 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
), /* Win9x, NT4 */
452 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
455 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
456 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
457 ok((flags
& ~SFGAO_HASSUBFOLDER
) == full_attrs
[i
], "%d: got %08x expected %08x\n", i
, flags
, full_attrs
[i
]);
461 IMalloc_Free(ppM
, idlArr
[i
]);
464 static void test_BindToObject(void)
468 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
469 SHITEMID emptyitem
= { 0, { 0 } };
470 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
471 WCHAR wszSystemDir
[MAX_PATH
];
472 char szSystemDir
[MAX_PATH
];
474 WCHAR path
[MAX_PATH
];
475 CHAR pathA
[MAX_PATH
];
477 WCHAR wszMyComputer
[] = {
478 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
479 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
480 static const CHAR filename_html
[] = "winetest.html";
481 static const CHAR filename_txt
[] = "winetest.txt";
482 static const CHAR filename_foo
[] = "winetest.foo";
484 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
485 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
487 hr
= SHGetDesktopFolder(&psfDesktop
);
488 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
489 if (hr
!= S_OK
) return;
491 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
492 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
494 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
495 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
497 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
498 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
500 IShellFolder_Release(psfDesktop
);
504 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
505 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
506 IShellFolder_Release(psfDesktop
);
507 IMalloc_Free(ppM
, pidlMyComputer
);
508 if (hr
!= S_OK
) return;
510 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
511 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
515 /* this call segfaults on 98SE */
516 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
517 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
520 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
521 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
522 if (cChars
== 0 || cChars
>= MAX_PATH
) {
523 IShellFolder_Release(psfMyComputer
);
526 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
528 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
529 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
531 IShellFolder_Release(psfMyComputer
);
535 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
536 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
537 IShellFolder_Release(psfMyComputer
);
538 IMalloc_Free(ppM
, pidlSystemDir
);
539 if (hr
!= S_OK
) return;
541 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
542 ok (hr
== E_INVALIDARG
,
543 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
547 /* this call segfaults on 98SE */
548 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
549 ok (hr
== E_INVALIDARG
,
550 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
553 IShellFolder_Release(psfSystemDir
);
555 cChars
= GetCurrentDirectoryA(MAX_PATH
, buf
);
558 skip("Failed to get current directory, skipping tests.\n");
561 if(buf
[cChars
-1] != '\\') lstrcatA(buf
, "\\");
563 SHGetDesktopFolder(&psfDesktop
);
565 /* Attempt BindToObject on files. */
568 lstrcpyA(pathA
, buf
);
569 lstrcatA(pathA
, filename_html
);
570 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
571 if(hfile
!= INVALID_HANDLE_VALUE
)
574 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
575 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
576 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
579 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
581 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
586 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
588 broken(hr
== E_NOINTERFACE
), /* Win9x, NT4, W2K */
593 hr
= IPersist_GetClassID(pp
, &id
);
594 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
595 /* CLSID_ShellFSFolder on some w2k systems */
596 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
) || broken(IsEqualIID(&id
, &CLSID_ShellFSFolder
)),
597 "Unexpected classid %s\n", wine_dbgstr_guid(&id
));
598 IPersist_Release(pp
);
601 IShellFolder_Release(psfChild
);
608 win_skip("Failed to create .html testfile.\n");
611 lstrcpyA(pathA
, buf
);
612 lstrcatA(pathA
, filename_txt
);
613 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
614 if(hfile
!= INVALID_HANDLE_VALUE
)
617 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
618 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
619 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
622 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
623 ok(hr
== E_FAIL
|| /* Vista+ */
624 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
625 hr
== E_INVALIDARG
|| /* W2K item in top dir */
626 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
628 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
634 win_skip("Failed to create .txt testfile.\n");
637 lstrcpyA(pathA
, buf
);
638 lstrcatA(pathA
, filename_foo
);
639 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
640 if(hfile
!= INVALID_HANDLE_VALUE
)
643 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
644 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
645 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
648 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
649 ok(hr
== E_FAIL
|| /* Vista+ */
650 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
651 hr
== E_INVALIDARG
|| /* W2K item in top dir */
652 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
654 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
660 win_skip("Failed to create .foo testfile.\n");
662 /* And on the desktop */
663 if(pSHGetSpecialFolderPathA
)
665 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
666 lstrcatA(pathA
, "\\");
667 lstrcatA(pathA
, filename_html
);
668 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
669 if(hfile
!= INVALID_HANDLE_VALUE
)
672 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
673 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
674 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
677 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
679 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
681 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
684 if(!DeleteFileA(pathA
))
685 trace("Failed to delete: %d\n", GetLastError());
689 win_skip("Failed to create .html testfile.\n");
691 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
692 lstrcatA(pathA
, "\\");
693 lstrcatA(pathA
, filename_foo
);
694 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
695 if(hfile
!= INVALID_HANDLE_VALUE
)
698 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
699 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
700 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
703 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
704 ok(hr
== E_FAIL
|| /* Vista+ */
705 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
706 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
708 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
714 win_skip("Failed to create .foo testfile.\n");
717 IShellFolder_Release(psfDesktop
);
720 static void test_GetDisplayName(void)
725 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
726 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
729 LPSHELLFOLDER psfDesktop
, psfPersonal
;
731 SHITEMID emptyitem
= { 0, { 0 } };
732 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
733 LPCITEMIDLIST pidlLast
;
734 static const CHAR szFileName
[] = "winetest.foo";
735 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
736 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
738 /* I'm trying to figure if there is a functional difference between calling
739 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
740 * binding to the shellfolder. One thing I thought of was that perhaps
741 * SHGetPathFromIDListW would be able to get the path to a file, which does
742 * not exist anymore, while the other method wouldn't. It turns out there's
743 * no functional difference in this respect.
746 if(!pSHGetSpecialFolderPathA
) {
747 win_skip("SHGetSpecialFolderPathA is not available\n");
751 /* First creating a directory in MyDocuments and a file in this directory. */
752 result
= pSHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
753 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
756 /* Use ANSI file functions so this works on Windows 9x */
757 lstrcatA(szTestDir
, "\\winetest");
758 CreateDirectoryA(szTestDir
, NULL
);
759 attr
=GetFileAttributesA(szTestDir
);
760 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
762 ok(0, "unable to create the '%s' directory\n", szTestDir
);
766 lstrcpyA(szTestFile
, szTestDir
);
767 lstrcatA(szTestFile
, "\\");
768 lstrcatA(szTestFile
, szFileName
);
769 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
770 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
771 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
772 CloseHandle(hTestFile
);
774 /* Getting an itemidlist for the file. */
775 hr
= SHGetDesktopFolder(&psfDesktop
);
776 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
777 if (hr
!= S_OK
) return;
779 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
781 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
782 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
784 IShellFolder_Release(psfDesktop
);
788 pidlLast
= pILFindLastID(pidlTestFile
);
789 ok(pidlLast
->mkid
.cb
>=76 ||
790 broken(pidlLast
->mkid
.cb
== 28) || /* W2K */
791 broken(pidlLast
->mkid
.cb
== 40), /* Win9x, WinME */
792 "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
793 if (pidlLast
->mkid
.cb
>= 28) {
794 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
795 "Filename should be stored as ansi-string at this position!\n");
797 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
798 if (pidlLast
->mkid
.cb
>= 76) {
799 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
800 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
801 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)) || /* Win7 */
802 (pidlLast
->mkid
.cb
>= 102 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[72], wszFileName
)), /* Win8 */
803 "Filename should be stored as wchar-string at this position!\n");
806 /* It seems as if we cannot bind to regular files on windows, but only directories.
808 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
809 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
810 hr
== E_NOTIMPL
|| /* Vista */
811 broken(hr
== S_OK
), /* Win9x, W2K */
814 IUnknown_Release(psfFile
);
817 if (!pSHBindToParent
)
819 win_skip("SHBindToParent is missing\n");
820 DeleteFileA(szTestFile
);
821 RemoveDirectoryA(szTestDir
);
825 /* Some tests for IShellFolder::SetNameOf */
826 if (pSHGetFolderPathAndSubDirA
)
828 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
829 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
831 /* It's ok to use this fixed path. Call will fail anyway. */
832 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
833 LPITEMIDLIST pidlNew
;
835 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
836 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
837 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
840 ok (((LPITEMIDLIST
)((LPBYTE
)pidlNew
+pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
841 "pidl returned from SetNameOf should be simple!\n");
843 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
844 * is implemented on top of SHFileOperation in WinXP. */
845 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
,
846 SHGDN_FORPARSING
, NULL
);
847 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
849 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
850 * SHGDN flags specify an absolute path. */
851 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
852 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
857 IShellFolder_Release(psfPersonal
);
861 win_skip("Avoid needs of interaction on Win2k\n");
863 /* Deleting the file and the directory */
864 DeleteFileA(szTestFile
);
865 RemoveDirectoryA(szTestDir
);
867 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
868 if (pSHGetPathFromIDListW
)
870 result
= pSHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
871 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
872 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
875 /* SHBindToParent fails, if called with a NULL PIDL. */
876 hr
= pSHBindToParent(NULL
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
877 ok (hr
!= S_OK
, "SHBindToParent(NULL) should fail!\n");
879 /* But it succeeds with an empty PIDL. */
880 hr
= pSHBindToParent(pidlEmpty
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
881 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
882 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
884 IShellFolder_Release(psfPersonal
);
886 /* Binding to the folder and querying the display name of the file also works. */
887 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
888 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
890 IShellFolder_Release(psfDesktop
);
894 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
895 * pidlTestFile (In accordance with MSDN). */
896 ok (pILFindLastID(pidlTestFile
) == pidlLast
,
897 "SHBindToParent doesn't return the last id of the pidl param!\n");
899 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
900 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
902 IShellFolder_Release(psfDesktop
);
903 IShellFolder_Release(psfPersonal
);
909 hr
= pStrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
910 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
911 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
914 ILFree(pidlTestFile
);
915 IShellFolder_Release(psfDesktop
);
916 IShellFolder_Release(psfPersonal
);
919 static void test_CallForAttributes(void)
925 LPSHELLFOLDER psfDesktop
;
926 LPITEMIDLIST pidlMyDocuments
;
927 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
928 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
929 static const WCHAR wszCallForAttributes
[] = {
930 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
931 static const WCHAR wszMyDocumentsKey
[] = {
932 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
933 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
934 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
935 WCHAR wszMyDocuments
[] = {
936 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
937 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
939 /* For the root of a namespace extension, the attributes are not queried by binding
940 * to the object and calling GetAttributesOf. Instead, the attributes are read from
941 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
943 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
944 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
945 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
946 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
948 hr
= SHGetDesktopFolder(&psfDesktop
);
949 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
950 if (hr
!= S_OK
) return;
952 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
953 &pidlMyDocuments
, NULL
);
955 broken(hr
== E_INVALIDARG
), /* Win95, NT4 */
956 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
958 IShellFolder_Release(psfDesktop
);
962 dwAttributes
= 0xffffffff;
963 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
964 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
965 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
967 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
968 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
969 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
970 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
972 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
973 * key. So the test will return at this point, if run on wine.
975 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
976 ok (lResult
== ERROR_SUCCESS
||
977 lResult
== ERROR_ACCESS_DENIED
,
978 "RegOpenKeyEx failed! result: %08x\n", lResult
);
979 if (lResult
!= ERROR_SUCCESS
) {
980 if (lResult
== ERROR_ACCESS_DENIED
)
981 skip("Not enough rights to open the registry key\n");
982 IMalloc_Free(ppM
, pidlMyDocuments
);
983 IShellFolder_Release(psfDesktop
);
987 /* Query MyDocuments' Attributes value, to be able to restore it later. */
988 dwSize
= sizeof(DWORD
);
989 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
990 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
991 if (lResult
!= ERROR_SUCCESS
) {
993 IMalloc_Free(ppM
, pidlMyDocuments
);
994 IShellFolder_Release(psfDesktop
);
998 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
999 dwSize
= sizeof(DWORD
);
1000 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
1001 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
1002 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
1003 if (lResult
!= ERROR_SUCCESS
) {
1005 IMalloc_Free(ppM
, pidlMyDocuments
);
1006 IShellFolder_Release(psfDesktop
);
1010 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
1011 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
1012 * SFGAO_FILESYSTEM attributes. */
1013 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
1014 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
1015 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
1016 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1017 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
1019 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
1020 * GetAttributesOf. It seems that once there is a single attribute queried, for which
1021 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
1022 * the flags in Attributes are ignored.
1024 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
1025 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
1026 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
1027 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
1029 ok (dwAttributes
== SFGAO_FILESYSTEM
,
1030 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
1033 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
1034 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
1035 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1036 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
1038 IMalloc_Free(ppM
, pidlMyDocuments
);
1039 IShellFolder_Release(psfDesktop
);
1042 static void test_GetAttributesOf(void)
1045 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
1046 SHITEMID emptyitem
= { 0, { 0 } };
1047 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1048 LPITEMIDLIST pidlMyComputer
;
1050 static const DWORD desktopFlags
[] = {
1052 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
|
1053 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1055 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_STREAM
| SFGAO_FILESYSANCESTOR
|
1056 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1057 /* WinMe, Win9x, WinNT*/
1058 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSANCESTOR
|
1059 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1061 static const DWORD myComputerFlags
[] = {
1063 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
1064 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1066 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_STREAM
|
1067 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1068 /* WinMe, Win9x, WinNT */
1069 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1070 SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1071 /* Win95, WinNT when queried directly */
1072 SFGAO_CANLINK
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1073 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1075 WCHAR wszMyComputer
[] = {
1076 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1077 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1078 char cCurrDirA
[MAX_PATH
] = {0};
1079 WCHAR cCurrDirW
[MAX_PATH
];
1080 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
1081 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1082 ITEMIDLIST
*newPIDL
;
1084 BOOL foundFlagsMatch
;
1086 hr
= SHGetDesktopFolder(&psfDesktop
);
1087 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1088 if (hr
!= S_OK
) return;
1090 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
1091 dwFlags
= 0xffffffff;
1092 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
1093 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
1094 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1095 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1097 if (desktopFlags
[i
] == dwFlags
)
1098 foundFlagsMatch
= TRUE
;
1100 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1102 /* .. or with no itemidlist at all. */
1103 dwFlags
= 0xffffffff;
1104 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
1105 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1106 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1107 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1109 if (desktopFlags
[i
] == dwFlags
)
1110 foundFlagsMatch
= TRUE
;
1112 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1114 /* Testing the attributes of the MyComputer shellfolder */
1115 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1116 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1118 IShellFolder_Release(psfDesktop
);
1122 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
1123 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
1125 dwFlags
= 0xffffffff;
1126 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
1127 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
1128 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1129 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1131 if ((myComputerFlags
[i
] | SFGAO_CANLINK
) == dwFlags
)
1132 foundFlagsMatch
= TRUE
;
1135 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1137 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
1138 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
1139 IShellFolder_Release(psfDesktop
);
1140 IMalloc_Free(ppM
, pidlMyComputer
);
1141 if (hr
!= S_OK
) return;
1143 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
1145 ok (hr
== E_INVALIDARG
||
1146 broken(hr
== S_OK
), /* W2K and earlier */
1147 "MyComputer->GetAttributesOf(empty pidl) should fail! hr = %08x\n", hr
);
1149 dwFlags
= 0xffffffff;
1150 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
1151 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1152 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1153 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1155 if (myComputerFlags
[i
] == dwFlags
)
1156 foundFlagsMatch
= TRUE
;
1159 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1161 IShellFolder_Release(psfMyComputer
);
1163 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1164 len
= lstrlenA(cCurrDirA
);
1167 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1170 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1171 cCurrDirA
[len
-1] = 0;
1173 /* create test directory */
1174 CreateFilesFolders();
1176 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1178 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1179 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1181 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1182 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1184 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1185 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1187 IMalloc_Free(ppM
, newPIDL
);
1189 /* get relative PIDL */
1190 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1191 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1193 /* test the shell attributes of the test directory using the relative PIDL */
1194 dwFlags
= SFGAO_FOLDER
;
1195 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1196 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1197 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1200 IMalloc_Free(ppM
, newPIDL
);
1202 /* append testdirectory name to path */
1203 if (cCurrDirA
[len
-1] == '\\')
1204 cCurrDirA
[len
-1] = 0;
1205 lstrcatA(cCurrDirA
, "\\testdir");
1206 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1208 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1209 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1211 /* test the shell attributes of the test directory using the absolute PIDL */
1212 dwFlags
= SFGAO_FOLDER
;
1213 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1214 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1215 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1218 IMalloc_Free(ppM
, newPIDL
);
1220 IShellFolder_Release(testIShellFolder
);
1224 IShellFolder_Release(IDesktopFolder
);
1227 static void test_SHGetPathFromIDList(void)
1229 SHITEMID emptyitem
= { 0, { 0 } };
1230 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1231 LPITEMIDLIST pidlMyComputer
;
1232 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1235 LPSHELLFOLDER psfDesktop
;
1236 WCHAR wszMyComputer
[] = {
1237 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1238 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1239 WCHAR wszFileName
[MAX_PATH
];
1240 LPITEMIDLIST pidlTestFile
;
1243 static WCHAR wszTestFile
[] = {
1244 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1245 LPITEMIDLIST pidlPrograms
;
1247 if(!pSHGetPathFromIDListW
|| !pSHGetSpecialFolderPathW
)
1249 win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
1253 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1256 result
= pSHGetPathFromIDListW(NULL
, wszPath
);
1257 ok(!result
, "Expected failure\n");
1258 ok(!wszPath
[0], "Expected empty string\n");
1260 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1261 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1262 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1263 if (!result
) return;
1265 /* Check if we are on Win9x */
1266 SetLastError(0xdeadbeef);
1267 lstrcmpiW(wszDesktop
, wszDesktop
);
1268 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1270 win_skip("Most W-calls are not implemented\n");
1274 result
= pSHGetPathFromIDListW(pidlEmpty
, wszPath
);
1275 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1276 if (!result
) return;
1277 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1279 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1280 hr
= SHGetDesktopFolder(&psfDesktop
);
1281 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1282 if (hr
!= S_OK
) return;
1284 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1285 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1287 IShellFolder_Release(psfDesktop
);
1291 SetLastError(0xdeadbeef);
1294 result
= pSHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1295 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1296 ok (GetLastError()==0xdeadbeef ||
1297 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1298 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1299 ok (!wszPath
[0], "Expected empty path\n");
1301 IShellFolder_Release(psfDesktop
);
1305 IMalloc_Free(ppM
, pidlMyComputer
);
1307 result
= pSHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1308 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1310 IShellFolder_Release(psfDesktop
);
1313 myPathAddBackslashW(wszFileName
);
1314 lstrcatW(wszFileName
, wszTestFile
);
1315 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1316 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1317 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1318 IShellFolder_Release(psfDesktop
);
1321 CloseHandle(hTestFile
);
1323 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1324 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1326 IShellFolder_Release(psfDesktop
);
1327 DeleteFileW(wszFileName
);
1328 IMalloc_Free(ppM
, pidlTestFile
);
1332 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1333 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1334 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1335 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1336 IShellFolder_Release(psfDesktop
);
1337 DeleteFileW(wszFileName
);
1339 IMalloc_Free(ppM
, pidlTestFile
);
1344 pStrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1345 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1346 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1347 "returned incorrect path for file placed on desktop\n");
1350 result
= pSHGetPathFromIDListW(pidlTestFile
, wszPath
);
1351 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1352 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1354 if (pSHGetPathFromIDListEx
)
1356 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1357 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1358 ok(!lstrcmpiW(wszDesktop
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1359 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszDesktop
));
1361 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1362 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1363 ok(!lstrcmpiW(wszFileName
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1364 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszFileName
));
1366 SetLastError(0xdeadbeef);
1367 memset(wszPath
, 0x55, sizeof(wszPath
));
1368 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, 5, SFGAO_FILESYSTEM
);
1369 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1371 SetLastError(0xdeadbeef);
1372 memset(wszPath
, 0x55, sizeof(wszPath
));
1373 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, 5, SFGAO_FILESYSTEM
);
1374 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1377 win_skip("SHGetPathFromIDListEx not available\n");
1379 IMalloc_Free(ppM
, pidlTestFile
);
1381 /* Test if we can get the path from the start menu "program files" PIDL. */
1382 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1383 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1385 SetLastError(0xdeadbeef);
1386 result
= pSHGetPathFromIDListW(pidlPrograms
, wszPath
);
1387 IMalloc_Free(ppM
, pidlPrograms
);
1388 ok(result
, "SHGetPathFromIDListW failed\n");
1391 static void test_EnumObjects_and_CompareIDs(void)
1393 ITEMIDLIST
*newPIDL
;
1394 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1395 char cCurrDirA
[MAX_PATH
] = {0};
1396 static const CHAR cTestDirA
[] = "\\testdir";
1397 WCHAR cTestDirW
[MAX_PATH
];
1401 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1402 len
= lstrlenA(cCurrDirA
);
1405 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1408 if(cCurrDirA
[len
-1] == '\\')
1409 cCurrDirA
[len
-1] = 0;
1411 lstrcatA(cCurrDirA
, cTestDirA
);
1412 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1414 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1415 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1417 CreateFilesFolders();
1419 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1420 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1422 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1423 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1425 test_EnumObjects(testIShellFolder
);
1427 IShellFolder_Release(testIShellFolder
);
1431 IMalloc_Free(ppM
, newPIDL
);
1433 IShellFolder_Release(IDesktopFolder
);
1436 /* A simple implementation of an IPropertyBag, which returns fixed values for
1437 * 'Target' and 'Attributes' properties.
1439 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1443 return E_INVALIDARG
;
1445 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1448 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1449 return E_NOINTERFACE
;
1452 IPropertyBag_AddRef(iface
);
1456 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1460 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1464 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1465 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1467 static const WCHAR wszTargetSpecialFolder
[] = {
1468 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1469 static const WCHAR wszTarget
[] = {
1470 'T','a','r','g','e','t',0 };
1471 static const WCHAR wszAttributes
[] = {
1472 'A','t','t','r','i','b','u','t','e','s',0 };
1473 static const WCHAR wszResolveLinkFlags
[] = {
1474 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1475 static const WCHAR wszTargetKnownFolder
[] = {
1476 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1477 static const WCHAR wszCLSID
[] = {
1478 'C','L','S','I','D',0 };
1480 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1481 ok(V_VT(pVar
) == VT_I4
||
1482 broken(V_VT(pVar
) == VT_BSTR
), /* Win2k */
1483 "Wrong variant type for 'TargetSpecialFolder' property!\n");
1484 return E_INVALIDARG
;
1487 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1489 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1490 return E_INVALIDARG
;
1493 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1494 WCHAR wszPath
[MAX_PATH
];
1497 ok(V_VT(pVar
) == VT_BSTR
||
1498 broken(V_VT(pVar
) == VT_EMPTY
), /* Win2k */
1499 "Wrong variant type for 'Target' property!\n");
1500 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1502 result
= pSHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1503 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1504 if (!result
) return E_INVALIDARG
;
1506 V_BSTR(pVar
) = SysAllocString(wszPath
);
1510 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1511 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1512 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1513 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1514 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1518 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1519 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1521 return E_INVALIDARG
;
1524 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1525 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1527 return E_INVALIDARG
;
1530 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1531 return E_INVALIDARG
;
1534 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1537 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1541 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1542 InitPropertyBag_IPropertyBag_QueryInterface
,
1543 InitPropertyBag_IPropertyBag_AddRef
,
1544 InitPropertyBag_IPropertyBag_Release
,
1545 InitPropertyBag_IPropertyBag_Read
,
1546 InitPropertyBag_IPropertyBag_Write
1549 static struct IPropertyBag InitPropertyBag
= {
1550 &InitPropertyBag_IPropertyBagVtbl
1553 static void test_FolderShortcut(void) {
1554 IPersistPropertyBag
*pPersistPropertyBag
;
1555 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1556 IPersistFolder3
*pPersistFolder3
;
1559 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1562 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1564 WCHAR wszWineTestFolder
[] = {
1565 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1566 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1567 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1568 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1569 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1570 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1571 'N','a','m','e','S','p','a','c','e','\\',
1572 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1573 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1575 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1576 static const GUID CLSID_UnixDosFolder
=
1577 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1579 if (!pSHGetSpecialFolderPathW
|| !pStrRetToBufW
) {
1580 win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
1584 if (!pSHGetFolderPathAndSubDirA
)
1586 win_skip("FolderShortcut test doesn't work on Win2k\n");
1590 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1591 * via their IPersistPropertyBag interface. And that the target folder
1592 * is taken from the IPropertyBag's 'Target' property.
1594 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1595 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1596 if (hr
== REGDB_E_CLASSNOTREG
) {
1597 win_skip("CLSID_FolderShortcut is not implemented\n");
1600 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1601 if (hr
!= S_OK
) return;
1603 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1604 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1606 IPersistPropertyBag_Release(pPersistPropertyBag
);
1610 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1611 (LPVOID
*)&pShellFolder
);
1612 IPersistPropertyBag_Release(pPersistPropertyBag
);
1613 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1614 if (hr
!= S_OK
) return;
1616 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1617 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* win10 */,
1618 "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1620 IShellFolder_Release(pShellFolder
);
1624 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1625 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1626 if (!result
) return;
1628 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1629 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1631 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1632 IShellFolder_Release(pShellFolder
);
1633 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1634 if (hr
!= S_OK
) return;
1636 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1637 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1638 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1640 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1641 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1642 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1644 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1645 * shell namespace. The target folder, read from the property bag above, remains untouched.
1646 * The following tests show this: The itemidlist for some imaginary shellfolder object
1647 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1648 * itemidlist, but GetDisplayNameOf still returns the path from above.
1650 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1651 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1652 if (hr
!= S_OK
) return;
1654 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1655 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1656 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1657 RegCloseKey(hShellExtKey
);
1658 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1659 &pidlWineTestFolder
, NULL
);
1660 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1661 IShellFolder_Release(pDesktopFolder
);
1662 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1663 if (hr
!= S_OK
) return;
1665 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1666 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1668 IPersistFolder3_Release(pPersistFolder3
);
1669 pILFree(pidlWineTestFolder
);
1673 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1674 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1675 ok(pILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1676 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1677 pILFree(pidlCurrentFolder
);
1678 pILFree(pidlWineTestFolder
);
1680 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1681 IPersistFolder3_Release(pPersistFolder3
);
1682 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1683 if (hr
!= S_OK
) return;
1685 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1686 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1688 IShellFolder_Release(pShellFolder
);
1692 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1693 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1695 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1696 * but ShellFSFolders. */
1697 myPathAddBackslashW(wszDesktopPath
);
1698 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1699 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1700 IShellFolder_Release(pShellFolder
);
1704 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1705 &pidlSubFolder
, NULL
);
1706 RemoveDirectoryW(wszDesktopPath
);
1707 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1709 IShellFolder_Release(pShellFolder
);
1713 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1714 (LPVOID
*)&pPersistFolder3
);
1715 IShellFolder_Release(pShellFolder
);
1716 pILFree(pidlSubFolder
);
1717 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1721 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1722 * a little bit and also allow CLSID_UnixDosFolder. */
1723 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1724 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1725 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1726 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1728 IPersistFolder3_Release(pPersistFolder3
);
1731 #include "pshpack1.h"
1732 struct FileStructA
{
1736 WORD uFileDate
; /* In our current implementation this is */
1737 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1742 struct FileStructW
{
1743 WORD cbLen
; /* Length of this element. */
1744 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1745 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1746 WORD uTime
; /* (this is currently speculation) */
1747 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1748 WORD uTime2
; /* (this is currently speculation) */
1749 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1750 WCHAR wszName
[1]; /* The long filename in unicode. */
1751 /* Just for documentation: Right after the unicode string: */
1752 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1753 * SHITEMID->cb == uOffset + cbLen */
1755 #include "poppack.h"
1757 static void test_ITEMIDLIST_format(void) {
1758 WCHAR wszPersonal
[MAX_PATH
];
1759 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1760 LPITEMIDLIST pidlPersonal
, pidlFile
;
1764 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1765 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1768 if (!pSHGetSpecialFolderPathW
) return;
1770 bResult
= pSHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1771 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1772 if (!bResult
) return;
1774 SetLastError(0xdeadbeef);
1775 bResult
= SetCurrentDirectoryW(wszPersonal
);
1776 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1777 win_skip("Most W-calls are not implemented\n");
1780 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1781 if (!bResult
) return;
1783 hr
= SHGetDesktopFolder(&psfDesktop
);
1784 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1785 if (hr
!= S_OK
) return;
1787 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1788 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1790 IShellFolder_Release(psfDesktop
);
1794 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1795 (LPVOID
*)&psfPersonal
);
1796 IShellFolder_Release(psfDesktop
);
1797 pILFree(pidlPersonal
);
1798 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1799 if (hr
!= S_OK
) return;
1801 for (i
=0; i
<3; i
++) {
1802 CHAR szFile
[MAX_PATH
];
1803 struct FileStructA
*pFileStructA
;
1806 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1808 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1809 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1810 if (hFile
== INVALID_HANDLE_VALUE
) {
1811 IShellFolder_Release(psfPersonal
);
1816 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1817 DeleteFileW(wszFile
[i
]);
1818 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1820 IShellFolder_Release(psfPersonal
);
1824 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1825 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1826 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1827 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1829 if (i
< 2) /* First two file names are already in valid 8.3 format */
1830 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1832 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1833 * can't implement this correctly, since unix filesystems don't support
1834 * this nasty short/long filename stuff. So we'll probably stay with our
1835 * current habit of storing the long filename here, which seems to work
1838 ok(pidlFile
->mkid
.abID
[18] == '~' ||
1839 broken(pidlFile
->mkid
.abID
[34] == '~'), /* Win2k */
1840 "Should be derived 8.3 name!\n");
1842 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1843 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0' ||
1844 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1), /* Win2k */
1845 "Alignment byte, where there shouldn't be!\n");
1847 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1848 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1849 "There should be an alignment byte, but isn't!\n");
1851 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1852 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1853 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1854 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)) ||
1855 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1) || /* Win2k on short names */
1856 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 12 + 1), /* Win2k on long names */
1857 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1859 if (cbOffset
>= sizeof(struct FileStructA
) &&
1860 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1862 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1863 WCHAR
*name
= pFileStructW
->wszName
;
1865 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1866 "FileStructW's offset and length should add up to the PIDL's length!\n");
1868 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1869 /* Since we just created the file, time of creation,
1870 * time of last access and time of last write access just be the same.
1871 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1872 * after the first run. I do remember something with NTFS keeping the creation time
1873 * if a file is deleted and then created again within a couple of seconds or so.
1874 * Might be the reason. */
1875 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1876 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1877 "Last write time should match creation time!\n");
1879 /* On FAT filesystems the last access time is midnight
1880 local time, so the values of uDate2 and uTime2 will
1881 depend on the local timezone. If the times are exactly
1882 equal then the dates should be identical for both FAT
1883 and NTFS as no timezone is more than 1 day away from UTC.
1885 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1887 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1888 "Last write date and time should match last access date and time!\n");
1892 /* Filesystem may be FAT. Check date within 1 day
1893 and seconds are zero. */
1894 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1895 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1896 "Last access time on FAT filesystems should have zero seconds.\n");
1897 /* TODO: Perform check for date being within one day.*/
1900 ok (!lstrcmpW(wszFile
[i
], name
) ||
1901 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1902 !lstrcmpW(wszFile
[i
], name
+ 11) || /* Win7 */
1903 !lstrcmpW(wszFile
[i
], name
+ 13), /* Win8 */
1904 "The filename should be stored in unicode at this position!\n");
1911 IShellFolder_Release(psfPersonal
);
1914 static void test_SHGetFolderPathA(void)
1916 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1918 char path
[MAX_PATH
];
1919 char path_x86
[MAX_PATH
];
1920 char path_key
[MAX_PATH
];
1924 if (!pSHGetFolderPathA
)
1926 win_skip("SHGetFolderPathA not present\n");
1929 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1931 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1932 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1933 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1936 win_skip( "Program Files (x86) not supported\n" );
1939 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1942 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1943 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1944 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1948 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1950 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1952 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1954 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1956 DWORD type
, count
= sizeof(path_x86
);
1957 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1959 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1960 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1962 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1966 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1967 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1968 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1971 win_skip( "Common Files (x86) not supported\n" );
1974 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1977 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1978 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1979 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1983 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1985 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1987 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1989 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1991 DWORD type
, count
= sizeof(path_x86
);
1992 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1994 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1995 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1997 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
2001 static void test_SHGetFolderPathAndSubDirA(void)
2007 static const char wine
[] = "wine";
2008 static const char winetemp
[] = "wine\\temp";
2009 static char appdata
[MAX_PATH
];
2010 static char testpath
[MAX_PATH
];
2011 static char toolongpath
[MAX_PATH
+1];
2013 if(!pSHGetFolderPathAndSubDirA
)
2015 win_skip("SHGetFolderPathAndSubDirA not present!\n");
2019 if(!pSHGetFolderPathA
) {
2020 win_skip("SHGetFolderPathA not present!\n");
2023 if(FAILED(pSHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
2025 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
2029 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2030 delret
= RemoveDirectoryA(testpath
);
2031 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
2032 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
2036 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2037 delret
= RemoveDirectoryA(testpath
);
2038 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
2039 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
2043 /* test invalid second parameter */
2044 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
2045 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
2047 /* test fourth parameter */
2048 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
2050 case S_OK
: /* winvista */
2051 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2052 "expected %s to start with %s\n", testpath
, appdata
);
2053 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2054 "expected %s to end with %s\n", testpath
, winetemp
);
2056 case E_INVALIDARG
: /* winxp, win2k3 */
2059 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2062 /* test fifth parameter */
2064 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
2065 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2066 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2069 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
2070 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2071 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2074 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
2075 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2076 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2078 for(i
=0; i
< MAX_PATH
; i
++)
2079 toolongpath
[i
] = '0' + i
% 10;
2080 toolongpath
[MAX_PATH
] = '\0';
2081 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
2082 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
2083 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
2086 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
2087 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2089 /* test a not existing path */
2091 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2092 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
2093 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
2095 /* create a directory inside a not existing directory */
2097 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2098 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2099 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2100 "expected %s to start with %s\n", testpath
, appdata
);
2101 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2102 "expected %s to end with %s\n", testpath
, winetemp
);
2103 dwret
= GetFileAttributesA(testpath
);
2104 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
2107 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2108 RemoveDirectoryA(testpath
);
2109 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2110 RemoveDirectoryA(testpath
);
2113 static void test_LocalizedNames(void)
2115 static char cCurrDirA
[MAX_PATH
];
2116 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
2117 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
2118 ITEMIDLIST
*newPIDL
;
2121 static char resourcefile
[MAX_PATH
];
2127 static const char desktopini_contents1
[] =
2128 "[.ShellClassInfo]\r\n"
2129 "LocalizedResourceName=@";
2130 static const char desktopini_contents2
[] =
2132 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
2133 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
2135 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
2136 CreateDirectoryA(".\\testfolder", NULL
);
2138 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
2140 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
2142 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
2143 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2144 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
2145 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
2146 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
2147 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
2148 ok(ret
, "WriteFile failed %i\n", GetLastError());
2151 /* get IShellFolder for parent */
2152 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
2153 len
= lstrlenA(cCurrDirA
);
2156 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
2159 if(cCurrDirA
[len
-1] == '\\')
2160 cCurrDirA
[len
-1] = 0;
2162 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
2164 hr
= SHGetDesktopFolder(&IDesktopFolder
);
2165 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
2167 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
2168 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2170 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
2171 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
2173 IMalloc_Free(ppM
, newPIDL
);
2175 /* windows reads the display name from the resource */
2176 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
2177 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2179 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
2180 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2182 if (hr
== S_OK
&& pStrRetToBufW
)
2184 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2185 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2187 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2188 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2189 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2192 /* editing name is also read from the resource */
2193 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
2194 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2196 if (hr
== S_OK
&& pStrRetToBufW
)
2198 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2199 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2201 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2202 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2203 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2206 /* parsing name is unchanged */
2207 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
2208 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2210 if (hr
== S_OK
&& pStrRetToBufW
)
2212 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2213 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2214 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2217 IShellFolder_Release(IDesktopFolder
);
2218 IShellFolder_Release(testIShellFolder
);
2220 IMalloc_Free(ppM
, newPIDL
);
2223 DeleteFileA(".\\testfolder\\desktop.ini");
2224 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
2225 RemoveDirectoryA(".\\testfolder");
2228 static void test_SHCreateShellItem(void)
2230 IShellItem
*shellitem
, *shellitem2
;
2231 IPersistIDList
*persistidl
;
2232 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2234 char curdirA
[MAX_PATH
];
2235 WCHAR curdirW
[MAX_PATH
];
2236 WCHAR fnbufW
[MAX_PATH
];
2237 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2238 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2240 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2242 if (!pSHCreateShellItem
)
2244 win_skip("SHCreateShellItem isn't available\n");
2250 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2254 if(pSHGetSpecialFolderLocation
)
2256 ret
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2257 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2261 win_skip("pSHGetSpecialFolderLocation missing.\n");
2262 pidl_desktop
= NULL
;
2265 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2267 ret
= SHGetDesktopFolder(&desktopfolder
);
2268 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2270 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2271 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2273 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2274 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2276 CreateTestFile(".\\testfile");
2278 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2279 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2281 pidl_abstestfile
= pILCombine(pidl_cwd
, pidl_testfile
);
2283 shellitem
= (void*)0xdeadbeef;
2284 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2285 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2286 ok(shellitem
== 0, "Got %p\n", shellitem
);
2288 if (0) /* crashes on Windows XP */
2290 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2291 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2292 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2293 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2296 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2297 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2300 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2301 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2304 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2305 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2308 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2311 IPersistIDList_Release(persistidl
);
2313 IShellItem_Release(shellitem
);
2316 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2317 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2320 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2321 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2324 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2325 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2328 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2331 IPersistIDList_Release(persistidl
);
2334 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2335 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2338 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2339 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2342 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2343 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2346 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2349 IPersistIDList_Release(persistidl
);
2351 IShellItem_Release(shellitem2
);
2354 IShellItem_Release(shellitem
);
2357 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2358 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2361 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2362 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2365 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2366 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2369 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2372 IPersistIDList_Release(persistidl
);
2374 IShellItem_Release(shellitem
);
2377 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2378 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2379 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2382 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2383 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2386 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2387 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2390 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2393 IPersistIDList_Release(persistidl
);
2395 IShellItem_Release(shellitem
);
2398 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2399 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2402 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2403 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2406 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2407 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2410 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2413 IPersistIDList_Release(persistidl
);
2416 IShellItem_Release(shellitem
);
2419 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2420 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2423 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2424 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2425 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2426 IShellItem_Release(shellitem
);
2429 /* SHCreateItemFromParsingName */
2430 if(pSHCreateItemFromParsingName
)
2434 /* Crashes under windows 7 */
2435 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2438 shellitem
= (void*)0xdeadbeef;
2439 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2440 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2441 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2443 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2444 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2445 "SHCreateItemFromParsingName returned %x\n", ret
);
2446 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2448 lstrcpyW(fnbufW
, curdirW
);
2449 myPathAddBackslashW(fnbufW
);
2450 lstrcatW(fnbufW
, testfileW
);
2452 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2453 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2457 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2458 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2461 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2462 CoTaskMemFree(tmp_fname
);
2464 IShellItem_Release(shellitem
);
2468 win_skip("No SHCreateItemFromParsingName\n");
2471 /* SHCreateItemFromIDList */
2472 if(pSHCreateItemFromIDList
)
2476 /* Crashes under win7 */
2477 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2480 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2481 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2483 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2484 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2487 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2488 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2491 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2492 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2495 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2498 IPersistIDList_Release(persistidl
);
2500 IShellItem_Release(shellitem
);
2503 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2504 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2507 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2508 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2511 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2512 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2515 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2518 IPersistIDList_Release(persistidl
);
2520 IShellItem_Release(shellitem
);
2524 win_skip("No SHCreateItemFromIDList\n");
2526 DeleteFileA(".\\testfile");
2527 pILFree(pidl_abstestfile
);
2528 pILFree(pidl_testfile
);
2529 pILFree(pidl_desktop
);
2531 IShellFolder_Release(currentfolder
);
2532 IShellFolder_Release(desktopfolder
);
2535 static void test_SHGetNameFromIDList(void)
2537 IShellItem
*shellitem
;
2542 static const DWORD flags
[] = {
2543 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2544 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2545 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2546 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2548 if(!pSHGetNameFromIDList
)
2550 win_skip("SHGetNameFromIDList missing.\n");
2554 /* These should be available on any platform that passed the above test. */
2555 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2556 ok(pSHBindToParent
!= NULL
, "SHBindToParent missing.\n");
2557 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
2558 ok(pStrRetToBufW
!= NULL
, "StrRetToBufW missing.\n");
2562 /* Crashes under win7 */
2563 pSHGetNameFromIDList(NULL
, 0, NULL
);
2566 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2567 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2569 /* Test the desktop */
2570 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2571 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2572 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2573 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2576 WCHAR
*nameSI
, *nameSH
;
2577 WCHAR buf
[MAX_PATH
];
2578 HRESULT hrSI
, hrSH
, hrSF
;
2583 SHGetDesktopFolder(&psf
);
2584 for(i
= 0; flags
[i
] != -1234; i
++)
2586 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2587 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2588 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2589 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2590 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2591 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2593 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2594 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2598 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2600 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2602 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2604 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2605 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2607 IShellFolder_Release(psf
);
2609 if(pSHGetPathFromIDListW
){
2610 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2611 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2612 res
= pSHGetPathFromIDListW(pidl
, buf
);
2613 ok(res
== TRUE
, "Got %d\n", res
);
2614 if(SUCCEEDED(hrSI
) && res
)
2615 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2616 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2618 win_skip("pSHGetPathFromIDListW not available\n");
2620 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2621 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2622 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2624 IShellItem_Release(shellitem
);
2628 /* Test the control panel */
2629 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2630 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2631 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2632 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2635 WCHAR
*nameSI
, *nameSH
;
2636 WCHAR buf
[MAX_PATH
];
2637 HRESULT hrSI
, hrSH
, hrSF
;
2642 SHGetDesktopFolder(&psf
);
2643 for(i
= 0; flags
[i
] != -1234; i
++)
2645 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2646 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2647 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2648 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2649 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2650 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2652 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2653 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2657 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2659 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2661 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2663 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2664 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2666 IShellFolder_Release(psf
);
2668 if(pSHGetPathFromIDListW
){
2669 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2670 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2671 res
= pSHGetPathFromIDListW(pidl
, buf
);
2672 ok(res
== FALSE
, "Got %d\n", res
);
2673 if(SUCCEEDED(hrSI
) && res
)
2674 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2675 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2677 win_skip("pSHGetPathFromIDListW not available\n");
2679 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2680 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2681 "Got 0x%08x\n", hres
);
2682 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2684 IShellItem_Release(shellitem
);
2689 static void test_SHGetItemFromDataObject(void)
2691 IShellFolder
*psfdesktop
;
2696 if(!pSHGetItemFromDataObject
)
2698 win_skip("No SHGetItemFromDataObject.\n");
2704 /* Crashes under win7 */
2705 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2708 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2709 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2711 SHGetDesktopFolder(&psfdesktop
);
2713 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2714 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2721 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2722 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2723 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2726 LPITEMIDLIST apidl
[5];
2729 for(count
= 0; count
< 5; count
++)
2730 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2735 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2736 &IID_IDataObject
, NULL
, (void**)&pdo
);
2737 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2740 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2741 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2742 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2743 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2744 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2745 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2746 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2747 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2748 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2749 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2750 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2751 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2752 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2753 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2754 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2756 IDataObject_Release(pdo
);
2760 skip("No file(s) found - skipping single-file test.\n");
2764 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2765 &IID_IDataObject
, NULL
, (void**)&pdo
);
2766 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2769 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2770 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2771 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2772 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2773 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2774 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2775 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2776 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2777 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2778 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2779 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2780 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2781 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2782 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2783 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2784 IDataObject_Release(pdo
);
2788 skip("zero or one file found - skipping multi-file test.\n");
2790 for(i
= 0; i
< count
; i
++)
2793 IEnumIDList_Release(peidl
);
2796 IShellView_Release(psv
);
2799 IShellFolder_Release(psfdesktop
);
2802 static void test_ShellItemCompare(void)
2804 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2805 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2806 IShellFolder
*psf_desktop
, *psf_current
;
2807 LPITEMIDLIST pidl_cwd
;
2808 WCHAR curdirW
[MAX_PATH
];
2811 static const WCHAR filesW
[][9] = {
2812 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2813 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2814 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2818 if(!pSHCreateShellItem
)
2820 win_skip("SHCreateShellItem missing.\n");
2824 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2827 skip("Failed to get current directory, skipping.\n");
2831 CreateDirectoryA(".\\a", NULL
);
2832 CreateDirectoryA(".\\b", NULL
);
2833 CreateDirectoryA(".\\c", NULL
);
2834 CreateTestFile(".\\a\\a");
2835 CreateTestFile(".\\a\\b");
2836 CreateTestFile(".\\a\\c");
2837 CreateTestFile(".\\b\\a");
2838 CreateTestFile(".\\b\\b");
2839 CreateTestFile(".\\b\\c");
2840 CreateTestFile(".\\c\\a");
2841 CreateTestFile(".\\c\\b");
2842 CreateTestFile(".\\c\\c");
2844 SHGetDesktopFolder(&psf_desktop
);
2845 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2846 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2847 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2848 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2849 IShellFolder_Release(psf_desktop
);
2852 /* Generate ShellItems for the files */
2853 memset(&psi
, 0, sizeof(psi
));
2855 for(i
= 0; i
< 9; i
++)
2857 LPITEMIDLIST pidl_testfile
= NULL
;
2859 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2860 NULL
, &pidl_testfile
, NULL
);
2861 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2864 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2865 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2866 pILFree(pidl_testfile
);
2868 if(FAILED(hr
)) failed
= TRUE
;
2872 skip("Failed to create all shellitems.\n");
2876 /* Generate ShellItems for the folders */
2877 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2878 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2879 if(FAILED(hr
)) failed
= TRUE
;
2880 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2881 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2882 if(FAILED(hr
)) failed
= TRUE
;
2883 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2884 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2885 if(FAILED(hr
)) failed
= TRUE
;
2889 skip("Failed to create shellitems.\n");
2895 /* Crashes on native (win7, winxp) */
2896 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2897 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2898 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2902 for(i
= 0; i
< 9; i
++)
2904 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
2905 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2906 ok(order
== 0, "Got order %d\n", order
);
2907 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
2908 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2909 ok(order
== 0, "Got order %d\n", order
);
2910 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2911 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2912 ok(order
== 0, "Got order %d\n", order
);
2916 /* a\b:a\a , a\b:a\c, a\b:a\b */
2917 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &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
[1], psi
[2], SICHINT_DISPLAY
, &order
);
2921 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2922 ok(order
== -1, "Got order %d\n", order
);
2923 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2924 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2925 ok(order
== 0, "Got order %d\n", order
);
2927 /* b\b:a\b, b\b:c\b, b\b:c\b */
2928 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
2929 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2930 ok(order
== 1, "Got order %d\n", order
);
2931 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
2932 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2933 ok(order
== -1, "Got order %d\n", order
);
2934 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2935 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2936 ok(order
== 0, "Got order %d\n", order
);
2938 /* b:a\a, b:a\c, b:a\b */
2939 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
2940 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2941 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2942 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
2943 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2944 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2945 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2946 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2947 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2949 /* b:c\a, b:c\c, b:c\b */
2950 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
2951 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2952 ok(order
== -1, "Got order %d\n", order
);
2953 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_DISPLAY
, &order
);
2954 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2955 ok(order
== -1, "Got order %d\n", order
);
2956 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2957 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2958 ok(order
== -1, "Got order %d\n", order
);
2960 /* a\b:a\a , a\b:a\c, a\b:a\b */
2961 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
2962 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2963 ok(order
== 1, "Got order %d\n", order
);
2964 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
2965 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2966 ok(order
== -1, "Got order %d\n", order
);
2967 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2968 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2969 ok(order
== 0, "Got order %d\n", order
);
2971 /* b\b:a\b, b\b:c\b, b\b:c\b */
2972 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
2973 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2974 ok(order
== 1, "Got order %d\n", order
);
2975 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &order
);
2976 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2977 ok(order
== -1, "Got order %d\n", order
);
2978 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2979 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2980 ok(order
== 0, "Got order %d\n", order
);
2982 /* b:a\a, b:a\c, b:a\b */
2983 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
2984 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2985 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2986 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
2987 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2988 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2989 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2990 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2991 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2993 /* b:c\a, b:c\c, b:c\b */
2994 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
2995 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2996 ok(order
== -1, "Got order %d\n", order
);
2997 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_CANONICAL
, &order
);
2998 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2999 ok(order
== -1, "Got order %d\n", order
);
3000 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
3001 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3002 ok(order
== -1, "Got order %d\n", order
);
3005 IShellFolder_Release(psf_current
);
3007 DeleteFileA(".\\a\\a");
3008 DeleteFileA(".\\a\\b");
3009 DeleteFileA(".\\a\\c");
3010 DeleteFileA(".\\b\\a");
3011 DeleteFileA(".\\b\\b");
3012 DeleteFileA(".\\b\\c");
3013 DeleteFileA(".\\c\\a");
3014 DeleteFileA(".\\c\\b");
3015 DeleteFileA(".\\c\\c");
3016 RemoveDirectoryA(".\\a");
3017 RemoveDirectoryA(".\\b");
3018 RemoveDirectoryA(".\\c");
3020 if(psi_a
) IShellItem_Release(psi_a
);
3021 if(psi_b
) IShellItem_Release(psi_b
);
3022 if(psi_c
) IShellItem_Release(psi_c
);
3024 for(i
= 0; i
< 9; i
++)
3025 if(psi
[i
]) IShellItem_Release(psi
[i
]);
3028 /**************************************************************/
3029 /* IUnknown implementation for counting QueryInterface calls. */
3031 IUnknown IUnknown_iface
;
3039 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
3041 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
3044 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
3046 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
3049 for(i
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
3051 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
3053 This
->ifaces
[i
].count
++;
3060 return E_NOINTERFACE
;
3063 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3068 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3073 static const IUnknownVtbl vt_IUnknown
= {
3074 unk_fnQueryInterface
,
3079 static void test_SHGetIDListFromObject(void)
3081 IUnknownImpl
*punkimpl
;
3082 IShellFolder
*psfdesktop
;
3084 LPITEMIDLIST pidl
, pidl_desktop
;
3087 struct if_count ifaces
[] =
3088 { {&IID_IPersistIDList
, 0},
3089 {&IID_IPersistFolder2
, 0},
3090 {&IID_IDataObject
, 0},
3091 {&IID_IParentAndItem
, 0},
3092 {&IID_IFolderView
, 0},
3095 if(!pSHGetIDListFromObject
)
3097 win_skip("SHGetIDListFromObject missing.\n");
3101 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3105 /* Crashes native */
3106 pSHGetIDListFromObject(NULL
, NULL
);
3107 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3110 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3111 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3113 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3114 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3115 punkimpl
->ifaces
= ifaces
;
3116 punkimpl
->unknown
= 0;
3118 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3119 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3120 ok(ifaces
[0].count
, "interface not requested.\n");
3121 ok(ifaces
[1].count
, "interface not requested.\n");
3122 ok(ifaces
[2].count
, "interface not requested.\n");
3124 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3125 "interface not requested.\n");
3126 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3127 "interface not requested.\n");
3129 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3130 HeapFree(GetProcessHeap(), 0, punkimpl
);
3132 pidl_desktop
= NULL
;
3133 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3134 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3136 SHGetDesktopFolder(&psfdesktop
);
3138 /* Test IShellItem */
3139 if(pSHCreateShellItem
)
3141 IShellItem
*shellitem
;
3142 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3143 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3146 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3147 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3150 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3153 IShellItem_Release(shellitem
);
3157 skip("no SHCreateShellItem.\n");
3159 /* Test IShellFolder */
3160 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3161 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3164 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3168 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3169 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3176 /* Test IFolderView */
3177 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3178 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3181 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3185 /* Test IDataObject */
3186 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3187 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3188 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3191 LPITEMIDLIST apidl
[5];
3193 for(count
= 0; count
< 5; count
++)
3194 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3199 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3200 &IID_IDataObject
, NULL
, (void**)&pdo
);
3201 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3204 pidl
= (void*)0xDEADBEEF;
3205 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3206 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3207 ok(pidl
!= NULL
, "pidl is NULL.\n");
3208 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3211 IDataObject_Release(pdo
);
3215 skip("No files found - skipping single-file test.\n");
3219 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3220 &IID_IDataObject
, NULL
, (void**)&pdo
);
3221 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3224 pidl
= (void*)0xDEADBEEF;
3225 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3226 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3227 "got 0x%08x\n", hres
);
3228 ok(pidl
== NULL
, "pidl is not NULL.\n");
3230 IDataObject_Release(pdo
);
3234 skip("zero or one file found - skipping multi-file test.\n");
3236 for(i
= 0; i
< count
; i
++)
3239 IEnumIDList_Release(peidl
);
3242 IShellView_Release(psv
);
3245 IShellFolder_Release(psfdesktop
);
3246 pILFree(pidl_desktop
);
3249 static void test_SHGetItemFromObject(void)
3251 IUnknownImpl
*punkimpl
;
3252 IShellFolder
*psfdesktop
;
3257 struct if_count ifaces
[] =
3258 { {&IID_IPersistIDList
, 0},
3259 {&IID_IPersistFolder2
, 0},
3260 {&IID_IDataObject
, 0},
3261 {&IID_IParentAndItem
, 0},
3262 {&IID_IFolderView
, 0},
3265 if(!pSHGetItemFromObject
)
3267 skip("No SHGetItemFromObject.\n");
3271 SHGetDesktopFolder(&psfdesktop
);
3275 /* Crashes with Windows 7 */
3276 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3277 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3278 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3281 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3282 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3284 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3285 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3286 punkimpl
->ifaces
= ifaces
;
3287 punkimpl
->unknown
= 0;
3289 /* The same as SHGetIDListFromObject */
3290 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3291 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3292 ok(ifaces
[0].count
, "interface not requested.\n");
3293 ok(ifaces
[1].count
, "interface not requested.\n");
3294 ok(ifaces
[2].count
, "interface not requested.\n");
3296 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3297 "interface not requested.\n");
3298 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3299 "interface not requested.\n");
3301 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3302 HeapFree(GetProcessHeap(), 0, punkimpl
);
3304 /* Test IShellItem */
3305 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3306 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3310 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3311 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3315 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3316 IShellItem_Release(psi2
);
3318 IShellItem_Release(psi
);
3321 IShellFolder_Release(psfdesktop
);
3324 static void test_SHCreateShellItemArray(void)
3326 IShellFolder
*pdesktopsf
, *psf
;
3327 IShellItemArray
*psia
;
3330 WCHAR cTestDirW
[MAX_PATH
];
3331 LPITEMIDLIST pidl_testdir
, pidl
;
3332 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3334 if(!pSHCreateShellItemArray
) {
3335 skip("No pSHCreateShellItemArray!\n");
3339 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3343 /* Crashes under native */
3344 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3345 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3346 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3347 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3350 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3351 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3353 SHGetDesktopFolder(&pdesktopsf
);
3354 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3355 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3357 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3358 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3360 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3361 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3362 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3365 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3366 myPathAddBackslashW(cTestDirW
);
3367 lstrcatW(cTestDirW
, testdirW
);
3369 CreateFilesFolders();
3371 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3372 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3375 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3377 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3379 IShellFolder_Release(pdesktopsf
);
3383 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3384 pILFree(pidl_testdir
);
3389 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3390 ok(hr
== S_OK
, "Got %08x\n", hr
);
3393 LPITEMIDLIST apidl
[5];
3394 UINT done
, numitems
, i
;
3396 for(done
= 0; done
< 5; done
++)
3397 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3399 ok(done
== 5, "Got %d pidls\n", done
);
3400 IEnumIDList_Release(peidl
);
3402 /* Create a ShellItemArray */
3403 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3404 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3411 /* Crashes in Windows 7 */
3412 IShellItemArray_GetCount(psia
, NULL
);
3415 IShellItemArray_GetCount(psia
, &numitems
);
3416 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3418 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3419 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3421 /* Compare all the items */
3422 for(i
= 0; i
< numitems
; i
++)
3424 LPITEMIDLIST pidl_abs
;
3425 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3427 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3428 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3431 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3432 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3435 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3438 IShellItem_Release(psi
);
3442 for(i
= 0; i
< done
; i
++)
3444 IShellItemArray_Release(psia
);
3448 /* SHCreateShellItemArrayFromShellItem */
3449 if(pSHCreateShellItemArrayFromShellItem
)
3455 /* Crashes under Windows 7 */
3456 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3457 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3458 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3461 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3462 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3465 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3466 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3471 hr
= IShellItemArray_GetCount(psia
, &count
);
3472 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3473 ok(count
== 1, "Got count %d\n", count
);
3474 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3475 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3477 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3480 LPITEMIDLIST pidl1
, pidl2
;
3481 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3482 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3483 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3484 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3485 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3486 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3487 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3490 IShellItem_Release(psi2
);
3492 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3493 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3494 IShellItemArray_Release(psia
);
3496 IShellItem_Release(psi
);
3500 skip("No SHCreateShellItemArrayFromShellItem.\n");
3502 if(pSHCreateShellItemArrayFromDataObject
)
3508 /* Crashes under Windows 7 */
3509 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3511 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3512 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3514 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3522 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3523 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3524 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3527 LPITEMIDLIST apidl
[5];
3530 for(count
= 0; count
< 5; count
++)
3531 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3533 ok(count
== 5, "Got %d\n", count
);
3537 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3538 &IID_IDataObject
, NULL
, (void**)&pdo
);
3539 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3542 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3544 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3548 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3549 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3550 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3551 for(i
= 0; i
< count_sia
; i
++)
3553 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3555 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3556 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3560 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3561 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3562 ok(pidl
!= NULL
, "pidl as NULL.\n");
3563 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3565 IShellItem_Release(psi
);
3570 IShellItemArray_Release(psia
);
3573 IDataObject_Release(pdo
);
3575 for(i
= 0; i
< count
; i
++)
3579 skip("No files found - skipping test.\n");
3581 IEnumIDList_Release(peidl
);
3583 IShellView_Release(psv
);
3587 skip("No SHCreateShellItemArrayFromDataObject.\n");
3589 if(pSHCreateShellItemArrayFromIDLists
)
3591 WCHAR test1W
[] = {'t','e','s','t','1','.','t','x','t',0};
3592 WCHAR test1pathW
[MAX_PATH
];
3593 LPITEMIDLIST pidltest1
;
3594 LPCITEMIDLIST pidl_array
[2];
3599 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, NULL
);
3602 psia
= (void*)0xdeadbeef;
3603 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, &psia
);
3604 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3605 ok(psia
== NULL
, "Got %p\n", psia
);
3607 psia
= (void*)0xdeadbeef;
3608 hr
= pSHCreateShellItemArrayFromIDLists(0, pidl_array
, &psia
);
3609 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3610 ok(psia
== NULL
, "Got %p\n", psia
);
3612 psia
= (void*)0xdeadbeef;
3613 pidl_array
[0] = NULL
;
3614 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3615 todo_wine
ok(hr
== E_OUTOFMEMORY
, "Got 0x%08x\n", hr
);
3616 ok(psia
== NULL
, "Got %p\n", psia
);
3618 psia
= (void*)0xdeadbeef;
3619 pidl_array
[0] = pidl_testdir
;
3620 pidl_array
[1] = NULL
;
3621 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3622 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Vista */, "Got 0x%08x\n", hr
);
3623 todo_wine
ok(psia
!= NULL
|| broken(psia
== NULL
) /* Vista */, "Got %p\n", psia
);
3629 hr
= IShellItemArray_GetCount(psia
, &count
);
3630 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3631 ok(count
== 2, "Got %d\n", count
);
3633 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3634 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3638 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3639 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3640 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3642 CoTaskMemFree(path
);
3644 IShellItem_Release(psi
);
3647 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3648 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3652 WCHAR desktoppath
[MAX_PATH
];
3655 result
= pSHGetSpecialFolderPathW(NULL
, desktoppath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
3656 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
3658 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3659 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3660 ok(!lstrcmpW(path
, desktoppath
), "Got %s\n", wine_dbgstr_w(path
));
3662 CoTaskMemFree(path
);
3664 IShellItem_Release(psi
);
3668 IShellItemArray_Release(psia
);
3673 psia
= (void*)0xdeadbeef;
3674 pidl_array
[0] = pidl_testdir
;
3675 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3676 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3682 hr
= IShellItemArray_GetCount(psia
, &count
);
3683 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3684 ok(count
== 1, "Got %d\n", count
);
3686 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3687 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3691 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3692 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3693 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3695 CoTaskMemFree(path
);
3697 IShellItem_Release(psi
);
3700 IShellItemArray_Release(psia
);
3704 lstrcpyW(test1pathW
, cTestDirW
);
3705 myPathAddBackslashW(test1pathW
);
3706 lstrcatW(test1pathW
, test1W
);
3708 SHGetDesktopFolder(&pdesktopsf
);
3710 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, test1pathW
, NULL
, &pidltest1
, NULL
);
3711 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3714 psia
= (void*)0xdeadbeef;
3715 pidl_array
[0] = pidl_testdir
;
3716 pidl_array
[1] = pidltest1
;
3717 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3718 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3724 hr
= IShellItemArray_GetCount(psia
, &count
);
3725 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3726 ok(count
== 2, "Got %d\n", count
);
3728 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3729 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3733 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3734 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3735 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3737 CoTaskMemFree(path
);
3739 IShellItem_Release(psi
);
3742 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3743 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3747 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3748 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3749 ok(!lstrcmpW(path
, test1pathW
), "Got %s\n", wine_dbgstr_w(path
));
3751 CoTaskMemFree(path
);
3753 IShellItem_Release(psi
);
3757 IShellItemArray_Release(psia
);
3763 IShellFolder_Release(pdesktopsf
);
3766 skip("No SHCreateShellItemArrayFromIDLists.\n");
3768 IShellFolder_Release(psf
);
3769 pILFree(pidl_testdir
);
3773 static void test_ShellItemArrayEnumItems(void)
3775 IShellFolder
*pdesktopsf
, *psf
;
3777 WCHAR cTestDirW
[MAX_PATH
];
3779 LPITEMIDLIST pidl_testdir
;
3780 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3782 if(!pSHCreateShellItemArray
)
3784 win_skip("No SHCreateShellItemArray, skipping test...\n");
3788 CreateFilesFolders();
3790 SHGetDesktopFolder(&pdesktopsf
);
3792 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3793 myPathAddBackslashW(cTestDirW
);
3794 lstrcatW(cTestDirW
, testdirW
);
3796 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3797 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3800 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3802 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3804 pILFree(pidl_testdir
);
3806 IShellFolder_Release(pdesktopsf
);
3808 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3809 ok(hr
== S_OK
, "Got %08x\n", hr
);
3812 IShellItemArray
*psia
;
3813 LPITEMIDLIST apidl
[5];
3814 UINT done
, numitems
, i
;
3816 for(done
= 0; done
< 5; done
++)
3817 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3819 ok(done
== 5, "Got %d pidls\n", done
);
3820 IEnumIDList_Release(peidl
);
3822 /* Create a ShellItemArray */
3823 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3824 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3827 IEnumShellItems
*iesi
;
3828 IShellItem
*my_array
[10];
3831 IShellItemArray_GetCount(psia
, &numitems
);
3832 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3835 hr
= IShellItemArray_EnumItems(psia
, &iesi
);
3836 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3837 ok(iesi
!= NULL
, "Got NULL\n");
3840 IEnumShellItems
*iesi2
;
3842 /* This should fail according to the documentation and Win7+ */
3843 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3844 hr
= IEnumShellItems_Next(iesi
, 2, my_array
, NULL
);
3845 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
3846 for(i
= 0; i
< 2; i
++)
3848 ok(my_array
[i
] == (void*)0xdeadbeef ||
3849 broken(my_array
[i
] != (void*)0xdeadbeef && my_array
[i
] != NULL
), /* Vista */
3850 "Got %p (%d)\n", my_array
[i
], i
);
3852 if(my_array
[i
] != (void*)0xdeadbeef)
3853 IShellItem_Release(my_array
[i
]);
3855 ok(my_array
[2] == (void*)0xdeadbeef, "Got %p\n", my_array
[2]);
3857 IEnumShellItems_Reset(iesi
);
3858 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3859 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, NULL
);
3860 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3861 ok(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3862 if(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef)
3863 IShellItem_Release(my_array
[0]);
3864 ok(my_array
[1] == (void*)0xdeadbeef, "Got %p\n", my_array
[1]);
3866 IEnumShellItems_Reset(iesi
);
3868 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3869 hr
= IEnumShellItems_Next(iesi
, numitems
, my_array
, &fetched
);
3870 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3871 ok(fetched
== numitems
, "Got %d\n", fetched
);
3872 for(i
= 0;i
< numitems
; i
++)
3874 ok(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef,
3875 "Got %p at %d\n", my_array
[i
], i
);
3877 if(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef)
3878 IShellItem_Release(my_array
[i
]);
3880 ok(my_array
[i
] == (void*)0xdeadbeef, "Got %p\n", my_array
[i
]);
3882 /* Compare all the items */
3883 IEnumShellItems_Reset(iesi
);
3884 for(i
= 0; i
< numitems
; i
++)
3889 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3890 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3891 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3892 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3893 ok(fetched
== 1, "Got %d\n", fetched
);
3895 hr
= IShellItem_Compare(psi
, my_array
[0], 0, &order
);
3896 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3897 ok(order
== 0, "Got %d\n", order
);
3899 IShellItem_Release(psi
);
3900 IShellItem_Release(my_array
[0]);
3903 my_array
[0] = (void*)0xdeadbeef;
3904 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3905 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3906 ok(fetched
== 0, "Got %d\n", fetched
);
3907 ok(my_array
[0] == (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3909 /* Cloning not implemented anywhere */
3910 iesi2
= (void*)0xdeadbeef;
3911 hr
= IEnumShellItems_Clone(iesi
, &iesi2
);
3912 ok(hr
== E_NOTIMPL
, "Got 0x%08x\n", hr
);
3913 ok(iesi2
== NULL
|| broken(iesi2
== (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2
);
3915 IEnumShellItems_Release(iesi
);
3918 IShellItemArray_Release(psia
);
3921 for(i
= 0; i
< done
; i
++)
3927 static void test_ShellItemBindToHandler(void)
3930 LPITEMIDLIST pidl_desktop
;
3933 if(!pSHCreateShellItem
)
3935 skip("SHCreateShellItem missing.\n");
3939 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3940 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3943 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3944 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3948 IPersistFolder2
*ppf2
;
3953 /* Crashes under Windows 7 */
3954 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3955 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3957 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3958 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3961 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3962 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3963 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3964 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3965 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3968 LPITEMIDLIST pidl_tmp
;
3969 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3970 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3973 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3976 IPersistFolder2_Release(ppf2
);
3979 /* BHID_SFUIObject */
3980 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3981 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3982 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3983 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3984 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3985 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3987 /* BHID_DataObject */
3988 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3989 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3990 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3994 /* BHID_SFViewObject */
3995 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3996 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3997 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3998 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3999 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
4000 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4003 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
4004 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
4005 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4006 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
4007 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4008 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4011 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
4012 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
4013 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4014 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
4015 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4016 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4018 /* BHID_StorageEnum */
4019 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
4020 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4021 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4024 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
4025 supported starting from Win8. */
4026 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferSource
, (void**)&punk
);
4027 ok(hr
== S_OK
|| broken(FAILED(hr
)) /* pre-Vista */, "Got 0x%08x\n", hr
);
4030 IUnknown_Release(punk
);
4032 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferDestination
, (void**)&punk
);
4033 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4034 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4036 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
4037 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Win8 */, "Got 0x%08x\n", hr
);
4038 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4041 /* BHID_EnumItems */
4042 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
4043 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4044 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4047 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
4048 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4049 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4051 /* BHID_LinkTargetItem */
4052 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
4053 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
4054 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4055 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
4056 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
4057 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4059 /* BHID_PropertyStore */
4060 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
4061 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4062 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4063 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
4064 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4065 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4067 /* BHID_ThumbnailHandler */
4068 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
4069 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4070 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4072 /* BHID_AssociationArray */
4073 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
4074 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4075 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4077 /* BHID_EnumAssocHandlers */
4078 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
4079 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4080 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4083 IShellItem_Release(psi
);
4086 skip("Failed to create ShellItem.\n");
4088 pILFree(pidl_desktop
);
4091 static void test_ShellItemGetAttributes(void)
4093 IShellItem
*psi
, *psi_folder1
, *psi_file1
;
4094 IShellFolder
*pdesktopsf
;
4095 LPITEMIDLIST pidl_desktop
, pidl
;
4098 WCHAR curdirW
[MAX_PATH
];
4099 WCHAR buf
[MAX_PATH
];
4100 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4101 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4103 if(!pSHCreateShellItem
)
4105 skip("SHCreateShellItem missing.\n");
4109 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
4110 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4113 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
4114 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4115 pILFree(pidl_desktop
);
4119 skip("Skipping tests.\n");
4125 /* Crashes on native (Win 7) */
4126 IShellItem_GetAttributes(psi
, 0, NULL
);
4129 /* Test GetAttributes on the desktop folder. */
4131 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
4132 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
4133 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
4135 IShellItem_Release(psi
);
4137 CreateFilesFolders();
4139 SHGetDesktopFolder(&pdesktopsf
);
4141 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4142 myPathAddBackslashW(curdirW
);
4144 lstrcpyW(buf
, curdirW
);
4145 lstrcatW(buf
, testdir1W
);
4146 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4147 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4148 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_folder1
);
4149 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4152 lstrcpyW(buf
, curdirW
);
4153 lstrcatW(buf
, testfile1W
);
4154 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4155 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4156 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_file1
);
4157 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4160 IShellFolder_Release(pdesktopsf
);
4163 hr
= IShellItem_GetAttributes(psi_folder1
, 0, &sfgao
);
4164 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4165 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4168 hr
= IShellItem_GetAttributes(psi_folder1
, SFGAO_FOLDER
, &sfgao
);
4169 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4170 ok(sfgao
== SFGAO_FOLDER
, "Got 0x%08x\n", sfgao
);
4173 hr
= IShellItem_GetAttributes(psi_file1
, SFGAO_FOLDER
, &sfgao
);
4174 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
4175 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4177 IShellItem_Release(psi_folder1
);
4178 IShellItem_Release(psi_file1
);
4183 static void test_ShellItemArrayGetAttributes(void)
4185 IShellItemArray
*psia_files
, *psia_folders1
, *psia_folders2
, *psia_all
;
4186 IShellFolder
*pdesktopsf
;
4187 LPCITEMIDLIST pidl_array
[5];
4190 WCHAR curdirW
[MAX_PATH
];
4191 WCHAR buf
[MAX_PATH
];
4193 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4194 static const WCHAR testdir2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
4195 static const WCHAR testdir3W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
4196 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4197 static const WCHAR testfile2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
4198 static const WCHAR
*testfilesW
[5] = { testdir1W
, testdir2W
, testdir3W
, testfile1W
, testfile2W
};
4200 if(!pSHCreateShellItemArrayFromShellItem
)
4202 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
4206 CreateFilesFolders();
4207 CreateDirectoryA(".\\testdir\\testdir3", NULL
);
4209 SHGetDesktopFolder(&pdesktopsf
);
4211 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4212 myPathAddBackslashW(curdirW
);
4214 for(i
= 0; i
< 5; i
++)
4216 lstrcpyW(buf
, curdirW
);
4217 lstrcatW(buf
, testfilesW
[i
]);
4218 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, (LPITEMIDLIST
*)&pidl_array
[i
], NULL
);
4219 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4221 IShellFolder_Release(pdesktopsf
);
4223 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia_folders1
);
4224 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4225 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[1], &psia_folders2
);
4226 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4227 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[3], &psia_files
);
4228 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4229 hr
= pSHCreateShellItemArrayFromIDLists(4, &pidl_array
[1], &psia_all
); /* All except the first */
4230 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4232 for(i
= 0; i
< 5; i
++)
4233 pILFree((LPITEMIDLIST
)pidl_array
[i
]);
4235 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
4237 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4238 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4239 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4241 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4242 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4243 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4245 /* [testfolder/testfolder2, testfolder/testfolder3] works */
4247 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4248 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4249 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4251 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4252 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4253 ok(attr
== 0, "Got 0x%08x\n", attr
);
4255 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4256 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4257 ok(attr
== 0, "Got 0x%08x\n", attr
);
4259 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4260 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4261 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4263 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4264 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4265 ok(attr
== 0, "Got 0x%08x\n", attr
);
4267 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4268 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4269 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4271 IShellItemArray_Release(psia_folders1
);
4272 IShellItemArray_Release(psia_folders2
);
4273 IShellItemArray_Release(psia_files
);
4274 IShellItemArray_Release(psia_all
);
4276 RemoveDirectoryA(".\\testdir\\testdir3");
4280 static void test_SHParseDisplayName(void)
4282 LPITEMIDLIST pidl1
, pidl2
;
4283 IShellFolder
*desktop
;
4284 WCHAR dirW
[MAX_PATH
];
4289 if (!pSHParseDisplayName
)
4291 win_skip("SHParseDisplayName isn't available\n");
4297 /* crashes on native */
4298 pSHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
4300 pSHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
4303 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
4304 hr
= pSHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
4305 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
4306 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
4307 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
4311 hr
= pSHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
4312 ok(hr
== S_OK
, "failed %08x\n", hr
);
4313 hr
= SHGetDesktopFolder(&desktop
);
4314 ok(hr
== S_OK
, "failed %08x\n", hr
);
4315 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
4316 ok(hr
== S_OK
, "failed %08x\n", hr
);
4317 ret
= pILIsEqual(pidl1
, pidl2
);
4318 ok(ret
== TRUE
, "expected equal idls\n");
4323 GetWindowsDirectoryW( dirW
, MAX_PATH
);
4325 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4326 ok(hr
== S_OK
, "failed %08x\n", hr
);
4327 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
4328 ok(hr
== S_OK
, "failed %08x\n", hr
);
4330 ret
= pILIsEqual(pidl1
, pidl2
);
4331 ok(ret
== TRUE
, "expected equal idls\n");
4335 /* system32 is not redirected to syswow64 on WOW64 */
4336 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
4337 if (is_wow64
&& pGetSystemWow64DirectoryW
)
4341 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
4342 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
4343 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4344 ok(hr
== S_OK
, "failed %08x\n", hr
);
4346 len
= pGetSystemWow64DirectoryW(dirW
, MAX_PATH
);
4347 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
4348 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
4349 ok(hr
== S_OK
, "failed %08x\n", hr
);
4350 ret
= pILIsEqual(pidl1
, pidl2
);
4351 ok(ret
== FALSE
, "expected different idls\n");
4356 IShellFolder_Release(desktop
);
4359 static void test_desktop_IPersist(void)
4361 IShellFolder
*desktop
;
4363 IPersistFolder2
*ppf2
;
4367 hr
= SHGetDesktopFolder(&desktop
);
4368 ok(hr
== S_OK
, "failed %08x\n", hr
);
4370 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
4371 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* NT4, W9X */, "failed %08x\n", hr
);
4377 /* crashes on native */
4378 IPersist_GetClassID(persist
, NULL
);
4380 memset(&clsid
, 0, sizeof(clsid
));
4381 hr
= IPersist_GetClassID(persist
, &clsid
);
4382 ok(hr
== S_OK
, "failed %08x\n", hr
);
4383 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
4384 IPersist_Release(persist
);
4387 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
4388 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
4391 IPersistFolder
*ppf
;
4393 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
4394 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
4396 IPersistFolder_Release(ppf
);
4399 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
4400 ok(hr
== S_OK
, "got %08x\n", hr
);
4404 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
4405 ok(hr
== S_OK
, "got %08x\n", hr
);
4406 ok(pidl
!= NULL
, "pidl was NULL.\n");
4407 if(SUCCEEDED(hr
)) pILFree(pidl
);
4409 IPersistFolder2_Release(ppf2
);
4412 IShellFolder_Release(desktop
);
4415 static void test_GetUIObject(void)
4417 IShellFolder
*psf_desktop
;
4421 WCHAR path
[MAX_PATH
];
4422 const WCHAR filename
[] =
4423 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4425 if(!pSHBindToParent
)
4427 win_skip("SHBindToParent missing.\n");
4431 GetCurrentDirectoryW(MAX_PATH
, path
);
4434 skip("GetCurrentDirectoryW returned an empty string.\n");
4437 lstrcatW(path
, filename
);
4438 SHGetDesktopFolder(&psf_desktop
);
4440 CreateFilesFolders();
4442 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4443 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
4447 LPCITEMIDLIST pidl_child
;
4448 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
4449 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4452 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
,
4454 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4457 const int baseItem
= 0x40;
4458 HMENU hmenu
= CreatePopupMenu();
4459 INT max_id
, max_id_check
;
4461 const int id_upper_limit
= 32767;
4462 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, baseItem
, id_upper_limit
, CMF_NORMAL
);
4463 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
4464 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
4465 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
4466 count
= GetMenuItemCount(hmenu
);
4467 ok(count
, "Got %d\n", count
);
4470 for(i
= 0; i
< count
; i
++)
4474 char buf
[255], buf2
[255];
4475 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
4476 mii
.cbSize
= sizeof(MENUITEMINFOA
);
4477 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
| MIIM_STRING
;
4478 mii
.dwTypeData
= buf2
;
4479 mii
.cch
= sizeof(buf2
);
4482 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
4483 ok(res
, "Failed (last error: %d).\n", GetLastError());
4485 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
4486 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
4487 if(!(mii
.fType
& MFT_SEPARATOR
))
4489 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
4490 hr
= IContextMenu_GetCommandString(pcm
, mii
.wID
- baseItem
, GCS_VERBA
, 0, buf
, sizeof(buf
));
4491 ok(SUCCEEDED(hr
) || hr
== E_NOTIMPL
, "for id 0x%x got 0x%08x (menustr: %s)\n", mii
.wID
- baseItem
, hr
, mii
.dwTypeData
);
4493 trace("for id 0x%x got string %s (menu string: %s)\n", mii
.wID
- baseItem
, buf
, mii
.dwTypeData
);
4494 else if (hr
== E_NOTIMPL
)
4495 trace("for id 0x%x got E_NOTIMPL (menu string: %s)\n", mii
.wID
- baseItem
, mii
.dwTypeData
);
4498 max_id_check
-= baseItem
;
4499 ok((max_id_check
== max_id
) ||
4500 (max_id_check
== max_id
-1) || /* Win 7 */
4501 (max_id_check
== max_id
-2), /* Win 8 */
4502 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
4504 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
4506 if(count
&& !is_win2k()) /* Test is interactive on w2k, so skip */
4508 CMINVOKECOMMANDINFO cmi
;
4509 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
4510 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
4512 /* Attempt to execute a nonexistent command */
4513 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
4514 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4515 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4517 cmi
.lpVerb
= "foobar_wine_test";
4518 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4519 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
4520 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
4521 "Got 0x%08x\n", hr
);
4526 IContextMenu_Release(pcm
);
4528 IShellFolder_Release(psf
);
4530 if(pILFree
) pILFree(pidl
);
4533 IShellFolder_Release(psf_desktop
);
4537 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
4538 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
4540 LPCITEMIDLIST child
;
4541 IShellFolder
*parent
;
4545 if(!pSHBindToParent
){
4546 win_skip("SHBindToParent is not available, not performing full PIDL verification\n");
4548 ok_(__FILE__
,l
)(pidl
!= NULL
, "Expected PIDL to be non-NULL\n");
4550 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4556 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
4560 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&parent
, &child
);
4561 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4565 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4566 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4568 IShellFolder_Release(parent
);
4572 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4573 "Got unexpected string type: %d\n", filename
.uType
);
4574 if(filename
.uType
== STRRET_WSTR
){
4575 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4576 "didn't get expected path (%s), instead: %s\n",
4577 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4578 SHFree(U(filename
).pOleStr
);
4579 }else if(filename
.uType
== STRRET_CSTR
){
4580 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4581 "didn't get expected path (%s), instead: %s\n",
4582 wine_dbgstr_w(path
), U(filename
).cStr
);
4585 IShellFolder_Release(parent
);
4587 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4590 static void test_SHSimpleIDListFromPath(void)
4592 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4593 const CHAR adirA
[] = "C:\\sidlfpdir";
4594 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4596 LPITEMIDLIST pidl
= NULL
;
4598 if(!pSHSimpleIDListFromPathAW
){
4599 win_skip("SHSimpleIDListFromPathAW not available\n");
4603 br
= CreateDirectoryA(adirA
, NULL
);
4604 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4607 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4609 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4610 verify_pidl(pidl
, adirW
);
4613 br
= RemoveDirectoryA(adirA
);
4614 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4617 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4619 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4620 verify_pidl(pidl
, adirW
);
4624 /* IFileSystemBindData impl */
4625 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4626 REFIID riid
, void **ppv
)
4628 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4629 IsEqualIID(riid
, &IID_IUnknown
)){
4633 return E_NOINTERFACE
;
4636 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4641 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4646 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4647 const WIN32_FIND_DATAW
*pfd
)
4649 ok(0, "SetFindData called\n");
4653 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4654 WIN32_FIND_DATAW
*pfd
)
4656 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4660 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4661 WIN32_FIND_DATAW
*pfd
)
4663 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4667 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4668 WIN32_FIND_DATAW
*pfd
)
4670 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4671 *pfd
->cFileName
= 'a';
4672 *pfd
->cAlternateFileName
= 'a';
4676 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4677 WIN32_FIND_DATAW
*pfd
)
4679 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4680 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4685 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4686 WIN32_FIND_DATAW
*pfd
)
4691 static IFileSystemBindDataVtbl fsbdVtbl
= {
4692 fsbd_QueryInterface
,
4699 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4701 static void test_ParseDisplayNamePBC(void)
4703 WCHAR wFileSystemBindData
[] =
4704 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4705 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4706 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4707 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4708 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4715 /* Check if we support WCHAR functions */
4716 SetLastError(0xdeadbeef);
4717 lstrcmpiW(adirW
, adirW
);
4718 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4719 win_skip("Most W-calls are not implemented\n");
4723 hres
= SHGetDesktopFolder(&psf
);
4724 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4726 win_skip("Failed to get IShellFolder, can't run tests\n");
4730 /* fails on unknown dir with no IBindCtx */
4731 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4732 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4733 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4734 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4735 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4736 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4737 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4738 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4739 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4741 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4742 hres
= CreateBindCtx(0, &pbc
);
4743 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4745 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4746 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4747 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4748 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4749 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4750 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4751 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4752 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4753 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4755 /* unknown dir with IBindCtx with IFileSystemBindData */
4756 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4757 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4759 /* return E_FAIL from GetFindData */
4760 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4761 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4762 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4763 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4764 "ParseDisplayName failed: 0x%08x\n", hres
);
4765 if(SUCCEEDED(hres
)){
4766 verify_pidl(pidl
, adirW
);
4770 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4771 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4772 "ParseDisplayName failed: 0x%08x\n", hres
);
4773 if(SUCCEEDED(hres
)){
4774 verify_pidl(pidl
, afileW
);
4778 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4779 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4780 "ParseDisplayName failed: 0x%08x\n", hres
);
4781 if(SUCCEEDED(hres
)){
4782 verify_pidl(pidl
, afile2W
);
4786 /* set FIND_DATA struct to NULLs */
4787 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4788 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4789 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4790 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4791 "ParseDisplayName failed: 0x%08x\n", hres
);
4792 if(SUCCEEDED(hres
)){
4793 verify_pidl(pidl
, adirW
);
4797 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4798 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4799 "ParseDisplayName failed: 0x%08x\n", hres
);
4800 if(SUCCEEDED(hres
)){
4801 verify_pidl(pidl
, afileW
);
4805 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4806 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4807 "ParseDisplayName failed: 0x%08x\n", hres
);
4808 if(SUCCEEDED(hres
)){
4809 verify_pidl(pidl
, afile2W
);
4813 /* set FIND_DATA struct to junk */
4814 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4815 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4816 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4817 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4818 "ParseDisplayName failed: 0x%08x\n", hres
);
4819 if(SUCCEEDED(hres
)){
4820 verify_pidl(pidl
, adirW
);
4824 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4825 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4826 "ParseDisplayName failed: 0x%08x\n", hres
);
4827 if(SUCCEEDED(hres
)){
4828 verify_pidl(pidl
, afileW
);
4832 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4833 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4834 "ParseDisplayName failed: 0x%08x\n", hres
);
4835 if(SUCCEEDED(hres
)){
4836 verify_pidl(pidl
, afile2W
);
4840 /* set FIND_DATA struct to invalid data */
4841 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4842 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4843 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4844 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4845 "ParseDisplayName failed: 0x%08x\n", hres
);
4846 if(SUCCEEDED(hres
)){
4847 verify_pidl(pidl
, adirW
);
4851 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4852 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4853 "ParseDisplayName failed: 0x%08x\n", hres
);
4854 if(SUCCEEDED(hres
)){
4855 verify_pidl(pidl
, afileW
);
4859 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4860 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4861 "ParseDisplayName failed: 0x%08x\n", hres
);
4862 if(SUCCEEDED(hres
)){
4863 verify_pidl(pidl
, afile2W
);
4867 /* set FIND_DATA struct to valid data */
4868 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4869 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4870 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4871 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4872 "ParseDisplayName failed: 0x%08x\n", hres
);
4873 if(SUCCEEDED(hres
)){
4874 verify_pidl(pidl
, adirW
);
4878 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4879 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4880 "ParseDisplayName failed: 0x%08x\n", hres
);
4881 if(SUCCEEDED(hres
)){
4882 verify_pidl(pidl
, afileW
);
4886 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4887 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4888 "ParseDisplayName failed: 0x%08x\n", hres
);
4889 if(SUCCEEDED(hres
)){
4890 verify_pidl(pidl
, afile2W
);
4894 IBindCtx_Release(pbc
);
4895 IShellFolder_Release(psf
);
4898 static const CHAR testwindow_class
[] = "testwindow";
4899 #define WM_USER_NOTIFY (WM_APP+1)
4901 struct ChNotifyTest
{
4903 const UINT notify_count
;
4904 UINT missing_events
;
4906 const char path_1
[256];
4907 const char path_2
[256];
4908 } chnotify_tests
[] = {
4909 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
4910 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
4911 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
4914 struct ChNotifyTest
*exp_data
;
4915 BOOL test_new_delivery_flag
;
4917 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4919 LONG signal
= (LONG
)lparam
;
4922 case WM_USER_NOTIFY
:
4923 if(exp_data
->missing_events
> 0) {
4924 WCHAR
*path1
, *path2
;
4925 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
4926 HANDLE hLock
= NULL
;
4928 if(test_new_delivery_flag
) {
4929 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
4930 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
4933 ok(exp_data
->signal
== signal
,
4934 "%s: expected notification type %x, got: %x\n",
4935 exp_data
->id
, exp_data
->signal
, signal
);
4937 trace("verifying pidls for: %s\n", exp_data
->id
);
4938 path1
= make_wstr(exp_data
->path_1
);
4939 path2
= make_wstr(exp_data
->path_2
);
4940 verify_pidl(pidls
[0], path1
);
4941 verify_pidl(pidls
[1], path2
);
4942 HeapFree(GetProcessHeap(), 0, path1
);
4943 HeapFree(GetProcessHeap(), 0, path2
);
4945 exp_data
->missing_events
--;
4947 if(test_new_delivery_flag
)
4948 SHChangeNotification_Unlock(hLock
);
4950 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4953 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
4956 static void register_testwindow_class(void)
4961 ZeroMemory(&cls
, sizeof(cls
));
4962 cls
.cbSize
= sizeof(cls
);
4964 cls
.lpfnWndProc
= testwindow_wndproc
;
4965 cls
.hInstance
= GetModuleHandleA(NULL
);
4966 cls
.lpszClassName
= testwindow_class
;
4969 ret
= RegisterClassExA(&cls
);
4970 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4973 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4974 * have to poll repeatedly for the message to appear */
4975 static void do_events(void)
4978 while (exp_data
->missing_events
&& (c
++ < 10)){
4980 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4981 TranslateMessage(&msg
);
4982 DispatchMessageA(&msg
);
4984 if(exp_data
->missing_events
)
4987 trace("%s: took %d tries\n", exp_data
->id
, c
);
4990 static void test_SHChangeNotify(BOOL test_new_delivery
)
4995 BOOL br
, has_unicode
;
4996 SHChangeNotifyEntry entries
[1];
4997 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4998 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
5000 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
5002 CreateDirectoryW(NULL
, NULL
);
5003 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
5005 test_new_delivery_flag
= test_new_delivery
;
5006 if(!test_new_delivery
)
5007 register_testwindow_class();
5009 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
5010 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
5011 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
5012 ok(wnd
!= NULL
, "Failed to make a window\n");
5014 br
= CreateDirectoryA(root_dirA
, NULL
);
5015 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
5017 entries
[0].pidl
= NULL
;
5019 hr
= pSHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
5021 hr
= pSHILCreateFromPath((LPCVOID
)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
5022 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
5023 entries
[0].fRecursive
= TRUE
;
5025 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
5026 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
5027 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
5029 for(i
= 0; i
< sizeof(chnotify_tests
) / sizeof(*chnotify_tests
); ++i
){
5030 exp_data
= chnotify_tests
+ i
;
5032 exp_data
->missing_events
= exp_data
->notify_count
;
5033 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
5034 exp_data
->path_1
[0] ? exp_data
->path_1
: NULL
,
5035 exp_data
->path_2
[0] ? exp_data
->path_2
: NULL
);
5037 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
5040 WCHAR
*path1
, *path2
;
5042 path1
= make_wstr(exp_data
->path_1
);
5043 path2
= make_wstr(exp_data
->path_2
);
5045 exp_data
->missing_events
= exp_data
->notify_count
;
5046 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
5048 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
5050 HeapFree(GetProcessHeap(), 0, path1
);
5051 HeapFree(GetProcessHeap(), 0, path2
);
5055 SHChangeNotifyDeregister(notifyID
);
5058 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
5059 br
= RemoveDirectoryA(root_dirA
);
5060 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
5063 static void test_SHCreateDefaultContextMenu(void)
5066 WCHAR path
[MAX_PATH
];
5067 IShellFolder
*desktop
,*folder
;
5068 IPersistFolder2
*persist
;
5069 IContextMenu
*cmenu
;
5071 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
5072 DEFCONTEXTMENU cminfo
;
5075 const WCHAR filename
[] =
5076 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
5077 if(!pSHCreateDefaultContextMenu
)
5079 win_skip("SHCreateDefaultContextMenu missing.\n");
5083 if(!pSHBindToParent
)
5085 skip("SHBindToParent missing.\n");
5089 GetCurrentDirectoryW(MAX_PATH
, path
);
5092 skip("GetCurrentDirectoryW returned an empty string.\n");
5095 lstrcatW(path
, filename
);
5096 SHGetDesktopFolder(&desktop
);
5098 CreateFilesFolders();
5100 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
5101 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
5105 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&folder
, (LPCITEMIDLIST
*)&pidl_child
);
5106 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5108 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
5109 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
5110 IPersistFolder2_Release(persist
);
5117 cminfo
.pidlFolder
=NULL
;
5118 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
5122 cminfo
.punkAssociationInfo
=NULL
;
5123 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5124 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5125 IContextMenu_Release(cmenu
);
5126 cminfo
.pidlFolder
=pidlFolder
;
5127 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5128 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5129 IContextMenu_Release(cmenu
);
5130 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
5131 if(status
==ERROR_SUCCESS
){
5136 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5137 RegCloseKey(keys
[0]);
5138 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5139 IContextMenu_Release(cmenu
);
5143 IShellFolder_Release(folder
);
5145 IShellFolder_Release(desktop
);
5150 static void test_SHCreateShellFolderView(void)
5155 IShellFolder
*desktop
;
5158 if (!pSHCreateShellFolderView
)
5160 win_skip("SHCreateShellFolderView missing.\n");
5164 hr
= SHGetDesktopFolder(&desktop
);
5165 ok(hr
== S_OK
, "got (0x%08x)\n", hr
);
5170 pSHCreateShellFolderView(NULL
, NULL
);
5173 psv
= (void *)0xdeadbeef;
5174 hr
= pSHCreateShellFolderView(NULL
, &psv
);
5175 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5176 ok(psv
== NULL
, "psv = %p\n", psv
);
5178 memset(&sfvc
, 0, sizeof(sfvc
));
5179 psv
= (void *)0xdeadbeef;
5180 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5181 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5182 ok(psv
== NULL
, "psv = %p\n", psv
);
5184 memset(&sfvc
, 0, sizeof(sfvc
));
5185 sfvc
.cbSize
= sizeof(sfvc
) - 1;
5186 psv
= (void *)0xdeadbeef;
5187 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5188 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5189 ok(psv
== NULL
, "psv = %p\n", psv
);
5191 memset(&sfvc
, 0, sizeof(sfvc
));
5192 sfvc
.cbSize
= sizeof(sfvc
) + 1;
5193 psv
= (void *)0xdeadbeef;
5194 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5195 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5196 ok(psv
== NULL
, "psv = %p\n", psv
);
5198 memset(&sfvc
, 0, sizeof(sfvc
));
5199 sfvc
.cbSize
= sizeof(sfvc
);
5200 sfvc
.pshf
= desktop
;
5202 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5203 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5204 ok(psv
!= NULL
, "psv = %p\n", psv
);
5207 refCount
= IShellView_Release(psv
);
5208 ok(refCount
== 0, "refCount = %u\n", refCount
);
5211 IShellFolder_Release(desktop
);
5214 static void test_SHCreateShellFolderViewEx(void)
5219 IShellFolder
*desktop
;
5222 if (!pSHCreateShellFolderViewEx
)
5224 win_skip("SHCreateShellFolderViewEx missing.\n");
5228 hr
= SHGetDesktopFolder(&desktop
);
5229 ok(hr
== S_OK
, "got (0x%08x)\n", hr
);
5234 pSHCreateShellFolderViewEx(NULL
, NULL
);
5235 pSHCreateShellFolderViewEx(NULL
, &psv
);
5236 pSHCreateShellFolderViewEx(&csfv
, NULL
);
5239 memset(&csfv
, 0, sizeof(csfv
));
5240 csfv
.pshf
= desktop
;
5242 hr
= pSHCreateShellFolderViewEx(&csfv
, &psv
);
5243 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5244 ok(psv
!= NULL
, "psv = %p\n", psv
);
5247 refCount
= IShellView_Release(psv
);
5248 ok(refCount
== 0, "refCount = %u\n", refCount
);
5251 memset(&csfv
, 0, sizeof(csfv
));
5252 csfv
.cbSize
= sizeof(csfv
);
5253 csfv
.pshf
= desktop
;
5255 hr
= pSHCreateShellFolderViewEx(&csfv
, &psv
);
5256 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5257 ok(psv
!= NULL
, "psv = %p\n", psv
);
5260 refCount
= IShellView_Release(psv
);
5261 ok(refCount
== 0, "refCount = %u\n", refCount
);
5264 IShellFolder_Release(desktop
);
5267 static void test_DataObject(void)
5269 IShellFolder
*desktop
;
5270 IDataObject
*data_obj
;
5275 DWORD cf_shellidlist
;
5278 SHGetDesktopFolder(&desktop
);
5280 hres
= IShellFolder_EnumObjects(desktop
, NULL
,
5281 SHCONTF_NONFOLDERS
|SHCONTF_FOLDERS
|SHCONTF_INCLUDEHIDDEN
, &peidl
);
5282 ok(hres
== S_OK
, "got %x\n", hres
);
5284 if(IEnumIDList_Next(peidl
, 1, &apidl
, NULL
) != S_OK
) {
5285 skip("no files on desktop - skipping GetDataObject tests\n");
5286 IEnumIDList_Release(peidl
);
5287 IShellFolder_Release(desktop
);
5290 IEnumIDList_Release(peidl
);
5292 hres
= IShellFolder_GetUIObjectOf(desktop
, NULL
, 1, (LPCITEMIDLIST
*)&apidl
,
5293 &IID_IDataObject
, NULL
, (void**)&data_obj
);
5294 ok(hres
== S_OK
, "got %x\n", hres
);
5296 IShellFolder_Release(desktop
);
5298 cf_shellidlist
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
5299 fmt
.cfFormat
= cf_shellidlist
;
5301 fmt
.dwAspect
= DVASPECT_CONTENT
;
5303 fmt
.tymed
= TYMED_HGLOBAL
;
5304 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5305 ok(hres
== S_OK
, "got %x\n", hres
);
5307 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5308 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5309 ok(hres
== S_OK
, "got %x\n", hres
);
5311 fmt
.tymed
= TYMED_ISTREAM
;
5312 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5313 todo_wine
ok(hres
== S_FALSE
, "got %x\n", hres
);
5315 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5316 hres
= IDataObject_GetData(data_obj
, &fmt
, &medium
);
5317 ok(hres
== S_OK
, "got %x\n", hres
);
5318 ok(medium
.tymed
== TYMED_HGLOBAL
, "medium.tymed = %x\n", medium
.tymed
);
5319 ReleaseStgMedium(&medium
);
5321 IDataObject_Release(data_obj
);
5324 START_TEST(shlfolder
)
5326 init_function_pointers();
5327 /* if OleInitialize doesn't get called, ParseDisplayName returns
5328 CO_E_NOTINITIALIZED for malformed directory names on win2k. */
5329 OleInitialize(NULL
);
5331 test_ParseDisplayName();
5332 test_SHParseDisplayName();
5333 test_BindToObject();
5334 test_EnumObjects_and_CompareIDs();
5335 test_GetDisplayName();
5336 test_GetAttributesOf();
5337 test_SHGetPathFromIDList();
5338 test_CallForAttributes();
5339 test_FolderShortcut();
5340 test_ITEMIDLIST_format();
5341 test_SHGetFolderPathA();
5342 test_SHGetFolderPathAndSubDirA();
5343 test_LocalizedNames();
5344 test_SHCreateShellItem();
5345 test_SHCreateShellItemArray();
5346 test_ShellItemArrayEnumItems();
5347 test_desktop_IPersist();
5349 test_SHSimpleIDListFromPath();
5350 test_ParseDisplayNamePBC();
5351 test_SHGetNameFromIDList();
5352 test_SHGetItemFromDataObject();
5353 test_SHGetIDListFromObject();
5354 test_SHGetItemFromObject();
5355 test_ShellItemCompare();
5356 test_SHChangeNotify(FALSE
);
5357 test_SHChangeNotify(TRUE
);
5358 test_ShellItemBindToHandler();
5359 test_ShellItemGetAttributes();
5360 test_ShellItemArrayGetAttributes();
5361 test_SHCreateDefaultContextMenu();
5362 test_SHCreateShellFolderView();
5363 test_SHCreateShellFolderViewEx();