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
24 DEFINE_GUID(IID_IParentAndItem
, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
25 DEFINE_GUID(CLSID_ShellDocObjView
, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
29 static HRESULT (WINAPI
*pSHBindToParent
)(LPCITEMIDLIST
, REFIID
, LPVOID
*, LPCITEMIDLIST
*);
30 static HRESULT (WINAPI
*pSHGetFolderPathA
)(HWND
, int, HANDLE
, DWORD
, LPSTR
);
31 static HRESULT (WINAPI
*pSHGetFolderPathAndSubDirA
)(HWND
, int, HANDLE
, DWORD
, LPCSTR
, LPSTR
);
32 static BOOL (WINAPI
*pSHGetPathFromIDListW
)(LPCITEMIDLIST
,LPWSTR
);
33 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
34 static BOOL (WINAPI
*pSHGetSpecialFolderPathA
)(HWND
, LPSTR
, int, BOOL
);
35 static BOOL (WINAPI
*pSHGetSpecialFolderPathW
)(HWND
, LPWSTR
, int, BOOL
);
36 static HRESULT (WINAPI
*pStrRetToBufW
)(STRRET
*,LPCITEMIDLIST
,LPWSTR
,UINT
);
37 static LPITEMIDLIST (WINAPI
*pILFindLastID
)(LPCITEMIDLIST
);
38 static void (WINAPI
*pILFree
)(LPITEMIDLIST
);
39 static BOOL (WINAPI
*pILIsEqual
)(LPCITEMIDLIST
, LPCITEMIDLIST
);
40 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
41 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
42 static HRESULT (WINAPI
*pSHCreateItemFromRelativeName
)(IShellItem
*,PCWSTR
,IBindCtx
*,REFIID
,void**);
43 static HRESULT (WINAPI
*pSHCreateItemInKnownFolder
)(REFKNOWNFOLDERID
,DWORD
,PCWSTR
,REFIID
,void **);
44 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
45 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
46 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromIDLists
)(UINT
, PCIDLIST_ABSOLUTE
*, IShellItemArray
**);
47 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
48 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
49 static LPITEMIDLIST (WINAPI
*pILCombine
)(LPCITEMIDLIST
,LPCITEMIDLIST
);
50 static HRESULT (WINAPI
*pSHParseDisplayName
)(LPCWSTR
,IBindCtx
*,LPITEMIDLIST
*,SFGAOF
,SFGAOF
*);
51 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathAW
)(LPCVOID
);
52 static HRESULT (WINAPI
*pSHGetKnownFolderPath
)(REFKNOWNFOLDERID
,DWORD
,HANDLE
,PWSTR
*);
53 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
54 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
55 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
56 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
57 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
58 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)(LPWSTR
, UINT
);
59 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
60 static HRESULT (WINAPI
*pSHILCreateFromPath
)(LPCWSTR
, LPITEMIDLIST
*,DWORD
*);
61 static BOOL (WINAPI
*pSHGetPathFromIDListEx
)(PCIDLIST_ABSOLUTE
,WCHAR
*,DWORD
,GPFIDL_FLAGS
);
63 static WCHAR
*make_wstr(const char *str
)
71 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
75 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
79 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
83 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
86 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
87 return lstrcmpA(stra
, buf
);
90 static void init_function_pointers(void)
96 hmod
= GetModuleHandleA("shell32.dll");
98 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
99 MAKEFUNC(SHBindToParent
);
100 MAKEFUNC(SHCreateItemFromIDList
);
101 MAKEFUNC(SHCreateItemFromParsingName
);
102 MAKEFUNC(SHCreateItemFromRelativeName
);
103 MAKEFUNC(SHCreateItemInKnownFolder
);
104 MAKEFUNC(SHCreateShellItem
);
105 MAKEFUNC(SHCreateShellItemArray
);
106 MAKEFUNC(SHCreateShellItemArrayFromIDLists
);
107 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
108 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
109 MAKEFUNC(SHGetFolderPathA
);
110 MAKEFUNC(SHGetFolderPathAndSubDirA
);
111 MAKEFUNC(SHGetPathFromIDListW
);
112 MAKEFUNC(SHGetSpecialFolderPathA
);
113 MAKEFUNC(SHGetSpecialFolderPathW
);
114 MAKEFUNC(SHGetSpecialFolderLocation
);
115 MAKEFUNC(SHParseDisplayName
);
116 MAKEFUNC(SHGetKnownFolderPath
);
117 MAKEFUNC(SHGetNameFromIDList
);
118 MAKEFUNC(SHGetItemFromDataObject
);
119 MAKEFUNC(SHGetIDListFromObject
);
120 MAKEFUNC(SHGetItemFromObject
);
121 MAKEFUNC(SHCreateDefaultContextMenu
);
122 MAKEFUNC(SHGetPathFromIDListEx
);
125 #define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
126 MAKEFUNC_ORD(ILFindLastID
, 16);
127 MAKEFUNC_ORD(ILIsEqual
, 21);
128 MAKEFUNC_ORD(ILCombine
, 25);
129 MAKEFUNC_ORD(SHILCreateFromPath
, 28);
130 MAKEFUNC_ORD(ILFree
, 155);
131 MAKEFUNC_ORD(SHSimpleIDListFromPathAW
, 162);
134 /* test named exports */
135 ptr
= GetProcAddress(hmod
, "ILFree");
136 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
139 #define TESTNAMED(f) \
140 ptr = (void*)GetProcAddress(hmod, #f); \
141 ok(ptr != 0, "expected named export for " #f "\n");
143 TESTNAMED(ILAppendID
);
145 TESTNAMED(ILCloneFirst
);
146 TESTNAMED(ILCombine
);
147 TESTNAMED(ILCreateFromPath
);
148 TESTNAMED(ILCreateFromPathA
);
149 TESTNAMED(ILCreateFromPathW
);
150 TESTNAMED(ILFindChild
);
151 TESTNAMED(ILFindLastID
);
152 TESTNAMED(ILGetNext
);
153 TESTNAMED(ILGetSize
);
154 TESTNAMED(ILIsEqual
);
155 TESTNAMED(ILIsParent
);
156 TESTNAMED(ILRemoveLastID
);
157 TESTNAMED(ILSaveToStream
);
161 hmod
= GetModuleHandleA("shlwapi.dll");
162 pStrRetToBufW
= (void*)GetProcAddress(hmod
, "StrRetToBufW");
164 hmod
= GetModuleHandleA("kernel32.dll");
165 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
166 pGetSystemWow64DirectoryW
= (void*)GetProcAddress(hmod
, "GetSystemWow64DirectoryW");
168 hr
= SHGetMalloc(&ppM
);
169 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
172 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
173 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
177 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
183 if (lpszPath
[-1] != '\\')
192 static void test_ParseDisplayName(void)
195 IShellFolder
*IDesktopFolder
;
196 static const char *cNonExistDir1A
= "c:\\nonexist_subdir";
197 static const char *cNonExistDir2A
= "c:\\\\nonexist_subdir";
198 static const char *cInetTestA
= "http:\\yyy";
199 static const char *cInetTest2A
= "xx:yyy";
201 WCHAR cTestDirW
[MAX_PATH
] = {0};
205 hr
= SHGetDesktopFolder(&IDesktopFolder
);
206 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
207 if(hr
!= S_OK
) return;
209 /* Tests crash on W2K and below (SHCreateShellItem available as of XP) */
210 if (pSHCreateShellItem
)
214 /* null name and pidl, also crashes on Windows 8 */
215 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
,
216 NULL
, NULL
, NULL
, 0);
217 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
221 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
222 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
223 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
224 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
225 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
228 win_skip("Tests would crash on W2K and below\n");
230 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
231 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
232 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
233 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
234 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
237 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
238 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
239 IMalloc_Free(ppM
, newPIDL
);
242 MultiByteToWideChar(CP_ACP
, 0, cInetTest2A
, -1, cTestDirW
, MAX_PATH
);
243 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
244 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
245 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
246 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
249 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
250 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
251 IMalloc_Free(ppM
, newPIDL
);
254 res
= GetFileAttributesA(cNonExistDir1A
);
255 if(res
!= INVALID_FILE_ATTRIBUTES
)
257 skip("Test directory unexpectedly exists\n");
261 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
262 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
263 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
264 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
),
265 "ParseDisplayName returned %08x, expected 80070002 or E_FAIL\n", hr
);
267 res
= GetFileAttributesA(cNonExistDir2A
);
268 if(res
!= INVALID_FILE_ATTRIBUTES
)
270 skip("Test directory unexpectedly exists\n");
274 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
275 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
276 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
277 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
278 "ParseDisplayName returned %08x, expected 80070002, E_FAIL or E_INVALIDARG\n", hr
);
280 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
281 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
282 * out it doesn't. The magic seems to happen in the file dialogs, then. */
283 if (!pSHGetSpecialFolderPathW
|| !pILFindLastID
)
285 win_skip("SHGetSpecialFolderPathW and/or ILFindLastID are not available\n");
289 bRes
= pSHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
290 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
291 if (!bRes
) goto finished
;
293 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
294 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
295 if (hr
!= S_OK
) goto finished
;
297 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31 ||
298 pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0xb1, /* Win98 */
299 "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
300 pILFindLastID(newPIDL
)->mkid
.abID
[0]);
301 IMalloc_Free(ppM
, newPIDL
);
304 IShellFolder_Release(IDesktopFolder
);
307 /* creates a file with the specified name for tests */
308 static void CreateTestFile(const CHAR
*name
)
313 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
314 if (file
!= INVALID_HANDLE_VALUE
)
316 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
317 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
323 /* initializes the tests */
324 static void CreateFilesFolders(void)
326 CreateDirectoryA(".\\testdir", NULL
);
327 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
328 CreateTestFile (".\\testdir\\test1.txt ");
329 CreateTestFile (".\\testdir\\test2.txt ");
330 CreateTestFile (".\\testdir\\test3.txt ");
331 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
332 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
335 /* cleans after tests */
336 static void Cleanup(void)
338 DeleteFileA(".\\testdir\\test1.txt");
339 DeleteFileA(".\\testdir\\test2.txt");
340 DeleteFileA(".\\testdir\\test3.txt");
341 RemoveDirectoryA(".\\testdir\\test.txt");
342 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
343 RemoveDirectoryA(".\\testdir\\testdir2");
344 RemoveDirectoryA(".\\testdir");
349 static void test_EnumObjects(IShellFolder
*iFolder
)
351 IEnumIDList
*iEnumList
;
352 LPITEMIDLIST newPIDL
, idlArr
[10];
357 static const WORD iResults
[5][5] =
366 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
367 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
368 static const ULONG attrs
[5] =
370 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
371 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
372 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
373 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
374 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
376 static const ULONG full_attrs
[5] =
378 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
379 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
380 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
381 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
382 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
385 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
386 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
388 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
389 * the filesystem shellfolders return S_OK even if less than 'celt' items are
390 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
391 * only ever returns a single entry per call. */
392 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
394 ok (i
== 5, "i: %d\n", i
);
396 hr
= IEnumIDList_Release(iEnumList
);
397 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
399 /* Sort them first in case of wrong order from system */
400 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
401 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
404 idlArr
[i
] = idlArr
[j
];
408 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
410 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
411 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
415 for (i
= 0; i
< 5; i
++)
418 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
419 /* Native returns all flags no matter what we ask for */
420 flags
= SFGAO_CANCOPY
;
421 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
422 flags
&= SFGAO_testfor
;
423 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
424 ok(flags
== (attrs
[i
]) ||
425 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
) || /* Win9x, NT4 */
426 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
427 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
429 flags
= SFGAO_testfor
;
430 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
431 flags
&= SFGAO_testfor
;
432 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
433 ok(flags
== attrs
[i
] ||
434 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
), /* Win9x, NT4 */
435 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
438 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
439 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
440 ok((flags
& ~(SFGAO_HASSUBFOLDER
|SFGAO_COMPRESSED
)) == full_attrs
[i
], "%d: got %08x expected %08x\n", i
, flags
, full_attrs
[i
]);
444 IMalloc_Free(ppM
, idlArr
[i
]);
447 static void test_BindToObject(void)
451 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
452 SHITEMID emptyitem
= { 0, { 0 } };
453 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
454 WCHAR wszSystemDir
[MAX_PATH
];
455 char szSystemDir
[MAX_PATH
];
457 WCHAR path
[MAX_PATH
];
458 CHAR pathA
[MAX_PATH
];
460 WCHAR wszMyComputer
[] = {
461 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
462 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
463 static const CHAR filename_html
[] = "winetest.html";
464 static const CHAR filename_txt
[] = "winetest.txt";
465 static const CHAR filename_foo
[] = "winetest.foo";
467 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
468 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
470 hr
= SHGetDesktopFolder(&psfDesktop
);
471 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
472 if (hr
!= S_OK
) return;
474 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
475 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
477 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
478 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
480 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
481 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
483 IShellFolder_Release(psfDesktop
);
487 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
488 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
489 IShellFolder_Release(psfDesktop
);
490 IMalloc_Free(ppM
, pidlMyComputer
);
491 if (hr
!= S_OK
) return;
493 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
494 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
498 /* this call segfaults on 98SE */
499 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
500 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
503 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
504 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
505 if (cChars
== 0 || cChars
>= MAX_PATH
) {
506 IShellFolder_Release(psfMyComputer
);
509 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
511 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
512 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
514 IShellFolder_Release(psfMyComputer
);
518 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
519 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
520 IShellFolder_Release(psfMyComputer
);
521 IMalloc_Free(ppM
, pidlSystemDir
);
522 if (hr
!= S_OK
) return;
524 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
525 ok (hr
== E_INVALIDARG
,
526 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
530 /* this call segfaults on 98SE */
531 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
532 ok (hr
== E_INVALIDARG
,
533 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
536 IShellFolder_Release(psfSystemDir
);
538 cChars
= GetCurrentDirectoryA(MAX_PATH
, buf
);
541 skip("Failed to get current directory, skipping tests.\n");
544 if(buf
[cChars
-1] != '\\') lstrcatA(buf
, "\\");
546 SHGetDesktopFolder(&psfDesktop
);
548 /* Attempt BindToObject on files. */
551 lstrcpyA(pathA
, buf
);
552 lstrcatA(pathA
, filename_html
);
553 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
554 if(hfile
!= INVALID_HANDLE_VALUE
)
557 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
558 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
559 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
562 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
564 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
569 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
571 broken(hr
== E_NOINTERFACE
), /* Win9x, NT4, W2K */
576 hr
= IPersist_GetClassID(pp
, &id
);
577 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
578 /* CLSID_ShellFSFolder on some w2k systems */
579 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
) || broken(IsEqualIID(&id
, &CLSID_ShellFSFolder
)),
580 "Unexpected classid %s\n", wine_dbgstr_guid(&id
));
581 IPersist_Release(pp
);
584 IShellFolder_Release(psfChild
);
591 win_skip("Failed to create .html testfile.\n");
594 lstrcpyA(pathA
, buf
);
595 lstrcatA(pathA
, filename_txt
);
596 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
597 if(hfile
!= INVALID_HANDLE_VALUE
)
600 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
601 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
602 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
605 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
606 ok(hr
== E_FAIL
|| /* Vista+ */
607 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
608 hr
== E_INVALIDARG
|| /* W2K item in top dir */
609 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
611 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
617 win_skip("Failed to create .txt testfile.\n");
620 lstrcpyA(pathA
, buf
);
621 lstrcatA(pathA
, filename_foo
);
622 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
623 if(hfile
!= INVALID_HANDLE_VALUE
)
626 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
627 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
628 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
631 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
632 ok(hr
== E_FAIL
|| /* Vista+ */
633 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
634 hr
== E_INVALIDARG
|| /* W2K item in top dir */
635 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
637 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
643 win_skip("Failed to create .foo testfile.\n");
645 /* And on the desktop */
646 if(pSHGetSpecialFolderPathA
)
648 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
649 lstrcatA(pathA
, "\\");
650 lstrcatA(pathA
, filename_html
);
651 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
652 if(hfile
!= INVALID_HANDLE_VALUE
)
655 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
656 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
657 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
660 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
662 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
664 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
667 if(!DeleteFileA(pathA
))
668 trace("Failed to delete: %d\n", GetLastError());
672 win_skip("Failed to create .html testfile.\n");
674 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
675 lstrcatA(pathA
, "\\");
676 lstrcatA(pathA
, filename_foo
);
677 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
678 if(hfile
!= INVALID_HANDLE_VALUE
)
681 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
682 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
683 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
686 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
687 ok(hr
== E_FAIL
|| /* Vista+ */
688 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
689 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
691 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
697 win_skip("Failed to create .foo testfile.\n");
700 IShellFolder_Release(psfDesktop
);
703 static void test_GetDisplayName(void)
708 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
709 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
712 LPSHELLFOLDER psfDesktop
, psfPersonal
;
714 SHITEMID emptyitem
= { 0, { 0 } };
715 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
716 LPCITEMIDLIST pidlLast
;
717 static const CHAR szFileName
[] = "winetest.foo";
718 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
719 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
721 /* I'm trying to figure if there is a functional difference between calling
722 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
723 * binding to the shellfolder. One thing I thought of was that perhaps
724 * SHGetPathFromIDListW would be able to get the path to a file, which does
725 * not exist anymore, while the other method wouldn't. It turns out there's
726 * no functional difference in this respect.
729 if(!pSHGetSpecialFolderPathA
) {
730 win_skip("SHGetSpecialFolderPathA is not available\n");
734 /* First creating a directory in MyDocuments and a file in this directory. */
735 result
= pSHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
736 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
739 /* Use ANSI file functions so this works on Windows 9x */
740 lstrcatA(szTestDir
, "\\winetest");
741 CreateDirectoryA(szTestDir
, NULL
);
742 attr
=GetFileAttributesA(szTestDir
);
743 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
745 ok(0, "unable to create the '%s' directory\n", szTestDir
);
749 lstrcpyA(szTestFile
, szTestDir
);
750 lstrcatA(szTestFile
, "\\");
751 lstrcatA(szTestFile
, szFileName
);
752 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
753 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
754 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
755 CloseHandle(hTestFile
);
757 /* Getting an itemidlist for the file. */
758 hr
= SHGetDesktopFolder(&psfDesktop
);
759 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
760 if (hr
!= S_OK
) return;
762 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
764 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
765 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
767 IShellFolder_Release(psfDesktop
);
771 pidlLast
= pILFindLastID(pidlTestFile
);
772 ok(pidlLast
->mkid
.cb
>=76 ||
773 broken(pidlLast
->mkid
.cb
== 28) || /* W2K */
774 broken(pidlLast
->mkid
.cb
== 40), /* Win9x, WinME */
775 "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
776 if (pidlLast
->mkid
.cb
>= 28) {
777 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
778 "Filename should be stored as ansi-string at this position!\n");
780 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
781 if (pidlLast
->mkid
.cb
>= 76) {
782 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
783 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
784 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)) || /* Win7 */
785 (pidlLast
->mkid
.cb
>= 102 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[72], wszFileName
)), /* Win8 */
786 "Filename should be stored as wchar-string at this position!\n");
789 /* It seems as if we cannot bind to regular files on windows, but only directories.
791 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
792 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
793 hr
== E_NOTIMPL
|| /* Vista */
794 broken(hr
== S_OK
), /* Win9x, W2K */
797 IUnknown_Release(psfFile
);
800 if (!pSHBindToParent
)
802 win_skip("SHBindToParent is missing\n");
803 DeleteFileA(szTestFile
);
804 RemoveDirectoryA(szTestDir
);
808 /* Some tests for IShellFolder::SetNameOf */
809 if (pSHGetFolderPathAndSubDirA
)
811 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
812 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
814 /* It's ok to use this fixed path. Call will fail anyway. */
815 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
816 LPITEMIDLIST pidlNew
;
818 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
819 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
820 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
823 ok (((LPITEMIDLIST
)((LPBYTE
)pidlNew
+pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
824 "pidl returned from SetNameOf should be simple!\n");
826 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
827 * is implemented on top of SHFileOperation in WinXP. */
828 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
,
829 SHGDN_FORPARSING
, NULL
);
830 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
832 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
833 * SHGDN flags specify an absolute path. */
834 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
835 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
840 IShellFolder_Release(psfPersonal
);
844 win_skip("Avoid needs of interaction on Win2k\n");
846 /* Deleting the file and the directory */
847 DeleteFileA(szTestFile
);
848 RemoveDirectoryA(szTestDir
);
850 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
851 if (pSHGetPathFromIDListW
)
853 result
= pSHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
854 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
855 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
858 /* SHBindToParent fails, if called with a NULL PIDL. */
859 hr
= pSHBindToParent(NULL
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
860 ok (hr
!= S_OK
, "SHBindToParent(NULL) should fail!\n");
862 /* But it succeeds with an empty PIDL. */
863 hr
= pSHBindToParent(pidlEmpty
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
864 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
865 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
867 IShellFolder_Release(psfPersonal
);
869 /* Binding to the folder and querying the display name of the file also works. */
870 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
871 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
873 IShellFolder_Release(psfDesktop
);
877 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
878 * pidlTestFile (In accordance with MSDN). */
879 ok (pILFindLastID(pidlTestFile
) == pidlLast
,
880 "SHBindToParent doesn't return the last id of the pidl param!\n");
882 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
883 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
885 IShellFolder_Release(psfDesktop
);
886 IShellFolder_Release(psfPersonal
);
892 hr
= pStrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
893 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
894 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
897 ILFree(pidlTestFile
);
898 IShellFolder_Release(psfDesktop
);
899 IShellFolder_Release(psfPersonal
);
902 static void test_CallForAttributes(void)
908 LPSHELLFOLDER psfDesktop
;
909 LPITEMIDLIST pidlMyDocuments
;
910 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
911 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
912 static const WCHAR wszCallForAttributes
[] = {
913 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
914 static const WCHAR wszMyDocumentsKey
[] = {
915 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
916 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
917 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
918 WCHAR wszMyDocuments
[] = {
919 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
920 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
922 /* For the root of a namespace extension, the attributes are not queried by binding
923 * to the object and calling GetAttributesOf. Instead, the attributes are read from
924 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
926 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
927 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
928 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
929 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
931 hr
= SHGetDesktopFolder(&psfDesktop
);
932 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
933 if (hr
!= S_OK
) return;
935 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
936 &pidlMyDocuments
, NULL
);
938 broken(hr
== E_INVALIDARG
), /* Win95, NT4 */
939 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
941 IShellFolder_Release(psfDesktop
);
945 dwAttributes
= 0xffffffff;
946 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
947 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
948 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
950 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
951 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
952 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
953 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
955 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
956 * key. So the test will return at this point, if run on wine.
958 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
959 ok (lResult
== ERROR_SUCCESS
||
960 lResult
== ERROR_ACCESS_DENIED
,
961 "RegOpenKeyEx failed! result: %08x\n", lResult
);
962 if (lResult
!= ERROR_SUCCESS
) {
963 if (lResult
== ERROR_ACCESS_DENIED
)
964 skip("Not enough rights to open the registry key\n");
965 IMalloc_Free(ppM
, pidlMyDocuments
);
966 IShellFolder_Release(psfDesktop
);
970 /* Query MyDocuments' Attributes value, to be able to restore it later. */
971 dwSize
= sizeof(DWORD
);
972 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
973 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
974 if (lResult
!= ERROR_SUCCESS
) {
976 IMalloc_Free(ppM
, pidlMyDocuments
);
977 IShellFolder_Release(psfDesktop
);
981 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
982 dwSize
= sizeof(DWORD
);
983 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
984 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
985 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
986 if (lResult
!= ERROR_SUCCESS
) {
988 IMalloc_Free(ppM
, pidlMyDocuments
);
989 IShellFolder_Release(psfDesktop
);
993 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
994 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
995 * SFGAO_FILESYSTEM attributes. */
996 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
997 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
998 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
999 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1000 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
1002 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
1003 * GetAttributesOf. It seems that once there is a single attribute queried, for which
1004 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
1005 * the flags in Attributes are ignored.
1007 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
1008 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
1009 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
1010 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
1012 ok (dwAttributes
== SFGAO_FILESYSTEM
,
1013 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
1016 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
1017 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
1018 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1019 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
1021 IMalloc_Free(ppM
, pidlMyDocuments
);
1022 IShellFolder_Release(psfDesktop
);
1025 static void test_GetAttributesOf(void)
1028 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
1029 SHITEMID emptyitem
= { 0, { 0 } };
1030 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1031 LPITEMIDLIST pidlMyComputer
;
1033 static const DWORD desktopFlags
[] = {
1035 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
|
1036 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1038 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_STREAM
| SFGAO_FILESYSANCESTOR
|
1039 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1040 /* WinMe, Win9x, WinNT*/
1041 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSANCESTOR
|
1042 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1044 static const DWORD myComputerFlags
[] = {
1046 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
1047 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1049 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_STREAM
|
1050 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1051 /* WinMe, Win9x, WinNT */
1052 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1053 SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1054 /* Win95, WinNT when queried directly */
1055 SFGAO_CANLINK
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1056 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1058 WCHAR wszMyComputer
[] = {
1059 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1060 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1061 char cCurrDirA
[MAX_PATH
] = {0};
1062 WCHAR cCurrDirW
[MAX_PATH
];
1063 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
1064 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1065 ITEMIDLIST
*newPIDL
;
1067 BOOL foundFlagsMatch
;
1069 hr
= SHGetDesktopFolder(&psfDesktop
);
1070 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1071 if (hr
!= S_OK
) return;
1073 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
1074 dwFlags
= 0xffffffff;
1075 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
1076 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
1077 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1078 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1080 if (desktopFlags
[i
] == dwFlags
)
1081 foundFlagsMatch
= TRUE
;
1083 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1085 /* .. or with no itemidlist at all. */
1086 dwFlags
= 0xffffffff;
1087 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
1088 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1089 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1090 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1092 if (desktopFlags
[i
] == dwFlags
)
1093 foundFlagsMatch
= TRUE
;
1095 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1097 /* Testing the attributes of the MyComputer shellfolder */
1098 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1099 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1101 IShellFolder_Release(psfDesktop
);
1105 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
1106 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
1108 dwFlags
= 0xffffffff;
1109 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
1110 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
1111 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1112 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1114 if ((myComputerFlags
[i
] | SFGAO_CANLINK
) == dwFlags
)
1115 foundFlagsMatch
= TRUE
;
1118 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1120 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
1121 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
1122 IShellFolder_Release(psfDesktop
);
1123 IMalloc_Free(ppM
, pidlMyComputer
);
1124 if (hr
!= S_OK
) return;
1126 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
1128 ok (hr
== E_INVALIDARG
||
1129 broken(hr
== S_OK
), /* W2K and earlier */
1130 "MyComputer->GetAttributesOf(empty pidl) should fail! hr = %08x\n", hr
);
1132 dwFlags
= 0xffffffff;
1133 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
1134 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1135 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1136 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1138 if (myComputerFlags
[i
] == dwFlags
)
1139 foundFlagsMatch
= TRUE
;
1142 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1144 IShellFolder_Release(psfMyComputer
);
1146 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1147 len
= lstrlenA(cCurrDirA
);
1150 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1153 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1154 cCurrDirA
[len
-1] = 0;
1156 /* create test directory */
1157 CreateFilesFolders();
1159 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1161 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1162 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1164 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1165 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1167 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1168 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1170 IMalloc_Free(ppM
, newPIDL
);
1172 /* get relative PIDL */
1173 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1174 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1176 /* test the shell attributes of the test directory using the relative PIDL */
1177 dwFlags
= SFGAO_FOLDER
;
1178 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1179 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1180 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1183 IMalloc_Free(ppM
, newPIDL
);
1185 /* append testdirectory name to path */
1186 if (cCurrDirA
[len
-1] == '\\')
1187 cCurrDirA
[len
-1] = 0;
1188 lstrcatA(cCurrDirA
, "\\testdir");
1189 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1191 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1192 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1194 /* test the shell attributes of the test directory using the absolute PIDL */
1195 dwFlags
= SFGAO_FOLDER
;
1196 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1197 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1198 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1201 IMalloc_Free(ppM
, newPIDL
);
1203 IShellFolder_Release(testIShellFolder
);
1207 IShellFolder_Release(IDesktopFolder
);
1210 static void test_SHGetPathFromIDList(void)
1212 SHITEMID emptyitem
= { 0, { 0 } };
1213 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1214 LPITEMIDLIST pidlMyComputer
;
1215 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1218 LPSHELLFOLDER psfDesktop
;
1219 WCHAR wszMyComputer
[] = {
1220 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1221 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1222 WCHAR wszFileName
[MAX_PATH
];
1223 LPITEMIDLIST pidlTestFile
;
1226 static WCHAR wszTestFile
[] = {
1227 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1228 LPITEMIDLIST pidlPrograms
;
1230 if(!pSHGetPathFromIDListW
|| !pSHGetSpecialFolderPathW
)
1232 win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
1236 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1239 result
= pSHGetPathFromIDListW(NULL
, wszPath
);
1240 ok(!result
, "Expected failure\n");
1241 ok(!wszPath
[0], "Expected empty string\n");
1243 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1244 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1245 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1246 if (!result
) return;
1248 /* Check if we are on Win9x */
1249 SetLastError(0xdeadbeef);
1250 lstrcmpiW(wszDesktop
, wszDesktop
);
1251 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1253 win_skip("Most W-calls are not implemented\n");
1257 result
= pSHGetPathFromIDListW(pidlEmpty
, wszPath
);
1258 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1259 if (!result
) return;
1260 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1262 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1263 hr
= SHGetDesktopFolder(&psfDesktop
);
1264 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1265 if (hr
!= S_OK
) return;
1267 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1268 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1270 IShellFolder_Release(psfDesktop
);
1274 SetLastError(0xdeadbeef);
1277 result
= pSHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1278 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1279 ok (GetLastError()==0xdeadbeef ||
1280 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1281 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1282 ok (!wszPath
[0], "Expected empty path\n");
1284 IShellFolder_Release(psfDesktop
);
1288 IMalloc_Free(ppM
, pidlMyComputer
);
1290 result
= pSHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1291 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1293 IShellFolder_Release(psfDesktop
);
1296 myPathAddBackslashW(wszFileName
);
1297 lstrcatW(wszFileName
, wszTestFile
);
1298 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1299 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1300 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1301 IShellFolder_Release(psfDesktop
);
1304 CloseHandle(hTestFile
);
1306 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1307 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1309 IShellFolder_Release(psfDesktop
);
1310 DeleteFileW(wszFileName
);
1311 IMalloc_Free(ppM
, pidlTestFile
);
1315 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1316 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1317 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1318 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1319 IShellFolder_Release(psfDesktop
);
1320 DeleteFileW(wszFileName
);
1322 IMalloc_Free(ppM
, pidlTestFile
);
1327 pStrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1328 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1329 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1330 "returned incorrect path for file placed on desktop\n");
1333 result
= pSHGetPathFromIDListW(pidlTestFile
, wszPath
);
1334 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1335 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1337 if (pSHGetPathFromIDListEx
)
1339 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1340 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1341 ok(!lstrcmpiW(wszDesktop
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1342 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszDesktop
));
1344 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1345 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1346 ok(!lstrcmpiW(wszFileName
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1347 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszFileName
));
1349 SetLastError(0xdeadbeef);
1350 memset(wszPath
, 0x55, sizeof(wszPath
));
1351 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, 5, SFGAO_FILESYSTEM
);
1352 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1354 SetLastError(0xdeadbeef);
1355 memset(wszPath
, 0x55, sizeof(wszPath
));
1356 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, 5, SFGAO_FILESYSTEM
);
1357 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1360 win_skip("SHGetPathFromIDListEx not available\n");
1362 IMalloc_Free(ppM
, pidlTestFile
);
1364 /* Test if we can get the path from the start menu "program files" PIDL. */
1365 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1366 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1368 SetLastError(0xdeadbeef);
1369 result
= pSHGetPathFromIDListW(pidlPrograms
, wszPath
);
1370 IMalloc_Free(ppM
, pidlPrograms
);
1371 ok(result
, "SHGetPathFromIDListW failed\n");
1374 static void test_EnumObjects_and_CompareIDs(void)
1376 ITEMIDLIST
*newPIDL
;
1377 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1378 char cCurrDirA
[MAX_PATH
] = {0};
1379 static const CHAR cTestDirA
[] = "\\testdir";
1380 WCHAR cTestDirW
[MAX_PATH
];
1384 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1385 len
= lstrlenA(cCurrDirA
);
1388 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1391 if(cCurrDirA
[len
-1] == '\\')
1392 cCurrDirA
[len
-1] = 0;
1394 lstrcatA(cCurrDirA
, cTestDirA
);
1395 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1397 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1398 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1400 CreateFilesFolders();
1402 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1403 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1405 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1406 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1408 test_EnumObjects(testIShellFolder
);
1410 IShellFolder_Release(testIShellFolder
);
1414 IMalloc_Free(ppM
, newPIDL
);
1416 IShellFolder_Release(IDesktopFolder
);
1419 /* A simple implementation of an IPropertyBag, which returns fixed values for
1420 * 'Target' and 'Attributes' properties.
1422 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1426 return E_INVALIDARG
;
1428 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1431 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1432 return E_NOINTERFACE
;
1435 IPropertyBag_AddRef(iface
);
1439 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1443 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1447 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1448 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1450 static const WCHAR wszTargetSpecialFolder
[] = {
1451 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1452 static const WCHAR wszTarget
[] = {
1453 'T','a','r','g','e','t',0 };
1454 static const WCHAR wszAttributes
[] = {
1455 'A','t','t','r','i','b','u','t','e','s',0 };
1456 static const WCHAR wszResolveLinkFlags
[] = {
1457 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1458 static const WCHAR wszTargetKnownFolder
[] = {
1459 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1460 static const WCHAR wszCLSID
[] = {
1461 'C','L','S','I','D',0 };
1463 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1464 ok(V_VT(pVar
) == VT_I4
||
1465 broken(V_VT(pVar
) == VT_BSTR
), /* Win2k */
1466 "Wrong variant type for 'TargetSpecialFolder' property!\n");
1467 return E_INVALIDARG
;
1470 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1472 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1473 return E_INVALIDARG
;
1476 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1477 WCHAR wszPath
[MAX_PATH
];
1480 ok(V_VT(pVar
) == VT_BSTR
||
1481 broken(V_VT(pVar
) == VT_EMPTY
), /* Win2k */
1482 "Wrong variant type for 'Target' property!\n");
1483 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1485 result
= pSHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1486 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1487 if (!result
) return E_INVALIDARG
;
1489 V_BSTR(pVar
) = SysAllocString(wszPath
);
1493 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1494 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1495 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1496 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1497 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1501 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1502 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1504 return E_INVALIDARG
;
1507 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1508 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1510 return E_INVALIDARG
;
1513 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1514 return E_INVALIDARG
;
1517 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1520 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1524 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1525 InitPropertyBag_IPropertyBag_QueryInterface
,
1526 InitPropertyBag_IPropertyBag_AddRef
,
1527 InitPropertyBag_IPropertyBag_Release
,
1528 InitPropertyBag_IPropertyBag_Read
,
1529 InitPropertyBag_IPropertyBag_Write
1532 static struct IPropertyBag InitPropertyBag
= {
1533 &InitPropertyBag_IPropertyBagVtbl
1536 static void test_FolderShortcut(void) {
1537 IPersistPropertyBag
*pPersistPropertyBag
;
1538 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1539 IPersistFolder3
*pPersistFolder3
;
1542 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1545 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1547 WCHAR wszWineTestFolder
[] = {
1548 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1549 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1550 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1551 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1552 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1553 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1554 'N','a','m','e','S','p','a','c','e','\\',
1555 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1556 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1558 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1559 static const GUID CLSID_UnixDosFolder
=
1560 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1562 if (!pSHGetSpecialFolderPathW
|| !pStrRetToBufW
) {
1563 win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
1567 if (!pSHGetFolderPathAndSubDirA
)
1569 win_skip("FolderShortcut test doesn't work on Win2k\n");
1573 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1574 * via their IPersistPropertyBag interface. And that the target folder
1575 * is taken from the IPropertyBag's 'Target' property.
1577 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1578 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1579 if (hr
== REGDB_E_CLASSNOTREG
) {
1580 win_skip("CLSID_FolderShortcut is not implemented\n");
1583 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1584 if (hr
!= S_OK
) return;
1586 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1587 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1589 IPersistPropertyBag_Release(pPersistPropertyBag
);
1593 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1594 (LPVOID
*)&pShellFolder
);
1595 IPersistPropertyBag_Release(pPersistPropertyBag
);
1596 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1597 if (hr
!= S_OK
) return;
1599 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1600 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* win10 */,
1601 "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1603 IShellFolder_Release(pShellFolder
);
1607 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1608 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1609 if (!result
) return;
1611 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1612 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1614 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1615 IShellFolder_Release(pShellFolder
);
1616 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1617 if (hr
!= S_OK
) return;
1619 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1620 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1621 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1623 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1624 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1625 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1627 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1628 * shell namespace. The target folder, read from the property bag above, remains untouched.
1629 * The following tests show this: The itemidlist for some imaginary shellfolder object
1630 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1631 * itemidlist, but GetDisplayNameOf still returns the path from above.
1633 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1634 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1635 if (hr
!= S_OK
) return;
1637 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1638 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1639 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1640 RegCloseKey(hShellExtKey
);
1641 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1642 &pidlWineTestFolder
, NULL
);
1643 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1644 IShellFolder_Release(pDesktopFolder
);
1645 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1646 if (hr
!= S_OK
) return;
1648 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1649 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1651 IPersistFolder3_Release(pPersistFolder3
);
1652 pILFree(pidlWineTestFolder
);
1656 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1657 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1658 ok(pILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1659 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1660 pILFree(pidlCurrentFolder
);
1661 pILFree(pidlWineTestFolder
);
1663 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1664 IPersistFolder3_Release(pPersistFolder3
);
1665 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1666 if (hr
!= S_OK
) return;
1668 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1669 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1671 IShellFolder_Release(pShellFolder
);
1675 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1676 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1678 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1679 * but ShellFSFolders. */
1680 myPathAddBackslashW(wszDesktopPath
);
1681 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1682 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1683 IShellFolder_Release(pShellFolder
);
1687 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1688 &pidlSubFolder
, NULL
);
1689 RemoveDirectoryW(wszDesktopPath
);
1690 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1692 IShellFolder_Release(pShellFolder
);
1696 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1697 (LPVOID
*)&pPersistFolder3
);
1698 IShellFolder_Release(pShellFolder
);
1699 pILFree(pidlSubFolder
);
1700 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1704 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1705 * a little bit and also allow CLSID_UnixDosFolder. */
1706 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1707 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1708 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1709 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1711 IPersistFolder3_Release(pPersistFolder3
);
1714 #include "pshpack1.h"
1715 struct FileStructA
{
1719 WORD uFileDate
; /* In our current implementation this is */
1720 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1725 struct FileStructW
{
1726 WORD cbLen
; /* Length of this element. */
1727 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1728 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1729 WORD uTime
; /* (this is currently speculation) */
1730 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1731 WORD uTime2
; /* (this is currently speculation) */
1732 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1733 WCHAR wszName
[1]; /* The long filename in unicode. */
1734 /* Just for documentation: Right after the unicode string: */
1735 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1736 * SHITEMID->cb == uOffset + cbLen */
1738 #include "poppack.h"
1740 static void test_ITEMIDLIST_format(void) {
1741 WCHAR wszPersonal
[MAX_PATH
];
1742 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1743 LPITEMIDLIST pidlPersonal
, pidlFile
;
1747 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1748 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1751 if (!pSHGetSpecialFolderPathW
) return;
1753 bResult
= pSHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1754 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1755 if (!bResult
) return;
1757 SetLastError(0xdeadbeef);
1758 bResult
= SetCurrentDirectoryW(wszPersonal
);
1759 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1760 win_skip("Most W-calls are not implemented\n");
1763 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1764 if (!bResult
) return;
1766 hr
= SHGetDesktopFolder(&psfDesktop
);
1767 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1768 if (hr
!= S_OK
) return;
1770 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1771 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1773 IShellFolder_Release(psfDesktop
);
1777 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1778 (LPVOID
*)&psfPersonal
);
1779 IShellFolder_Release(psfDesktop
);
1780 pILFree(pidlPersonal
);
1781 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1782 if (hr
!= S_OK
) return;
1784 for (i
=0; i
<3; i
++) {
1785 CHAR szFile
[MAX_PATH
];
1786 struct FileStructA
*pFileStructA
;
1789 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1791 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1792 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1793 if (hFile
== INVALID_HANDLE_VALUE
) {
1794 IShellFolder_Release(psfPersonal
);
1799 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1800 DeleteFileW(wszFile
[i
]);
1801 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1803 IShellFolder_Release(psfPersonal
);
1807 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1808 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1809 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1810 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1812 if (i
< 2) /* First two file names are already in valid 8.3 format */
1813 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1815 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1816 * can't implement this correctly, since unix filesystems don't support
1817 * this nasty short/long filename stuff. So we'll probably stay with our
1818 * current habit of storing the long filename here, which seems to work
1821 ok(pidlFile
->mkid
.abID
[18] == '~' ||
1822 broken(pidlFile
->mkid
.abID
[34] == '~'), /* Win2k */
1823 "Should be derived 8.3 name!\n");
1825 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1826 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0' ||
1827 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1), /* Win2k */
1828 "Alignment byte, where there shouldn't be!\n");
1830 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1831 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1832 "There should be an alignment byte, but isn't!\n");
1834 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1835 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1836 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1837 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)) ||
1838 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1) || /* Win2k on short names */
1839 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 12 + 1), /* Win2k on long names */
1840 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1842 if (cbOffset
>= sizeof(struct FileStructA
) &&
1843 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1845 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1846 WCHAR
*name
= pFileStructW
->wszName
;
1848 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1849 "FileStructW's offset and length should add up to the PIDL's length!\n");
1851 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1852 /* Since we just created the file, time of creation,
1853 * time of last access and time of last write access just be the same.
1854 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1855 * after the first run. I do remember something with NTFS keeping the creation time
1856 * if a file is deleted and then created again within a couple of seconds or so.
1857 * Might be the reason. */
1858 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1859 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1860 "Last write time should match creation time!\n");
1862 /* On FAT filesystems the last access time is midnight
1863 local time, so the values of uDate2 and uTime2 will
1864 depend on the local timezone. If the times are exactly
1865 equal then the dates should be identical for both FAT
1866 and NTFS as no timezone is more than 1 day away from UTC.
1868 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1870 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1871 "Last write date and time should match last access date and time!\n");
1875 /* Filesystem may be FAT. Check date within 1 day
1876 and seconds are zero. */
1877 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1878 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1879 "Last access time on FAT filesystems should have zero seconds.\n");
1880 /* TODO: Perform check for date being within one day.*/
1883 ok (!lstrcmpW(wszFile
[i
], name
) ||
1884 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1885 !lstrcmpW(wszFile
[i
], name
+ 11) || /* Win7 */
1886 !lstrcmpW(wszFile
[i
], name
+ 13), /* Win8 */
1887 "The filename should be stored in unicode at this position!\n");
1894 IShellFolder_Release(psfPersonal
);
1897 static void test_SHGetFolderPathA(void)
1899 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1901 char path
[MAX_PATH
];
1902 char path_x86
[MAX_PATH
];
1903 char path_key
[MAX_PATH
];
1907 if (!pSHGetFolderPathA
)
1909 win_skip("SHGetFolderPathA not present\n");
1912 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1914 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1915 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1916 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1919 win_skip( "Program Files (x86) not supported\n" );
1922 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1925 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1926 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1927 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1931 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1933 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1935 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1937 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1939 DWORD type
, count
= sizeof(path_x86
);
1940 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1942 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1943 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1945 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1949 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1950 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1951 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1954 win_skip( "Common Files (x86) not supported\n" );
1957 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1960 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1961 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1962 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1966 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1968 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1970 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1972 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1974 DWORD type
, count
= sizeof(path_x86
);
1975 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1977 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1978 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1980 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1984 static void test_SHGetFolderPathAndSubDirA(void)
1990 static const char wine
[] = "wine";
1991 static const char winetemp
[] = "wine\\temp";
1992 static char appdata
[MAX_PATH
];
1993 static char testpath
[MAX_PATH
];
1994 static char toolongpath
[MAX_PATH
+1];
1996 if(!pSHGetFolderPathAndSubDirA
)
1998 win_skip("SHGetFolderPathAndSubDirA not present!\n");
2002 if(!pSHGetFolderPathA
) {
2003 win_skip("SHGetFolderPathA not present!\n");
2006 if(FAILED(pSHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
2008 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
2012 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2013 delret
= RemoveDirectoryA(testpath
);
2014 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
2015 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
2019 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2020 delret
= RemoveDirectoryA(testpath
);
2021 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
2022 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
2026 /* test invalid second parameter */
2027 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
2028 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
2030 /* test fourth parameter */
2031 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
2033 case S_OK
: /* winvista */
2034 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2035 "expected %s to start with %s\n", testpath
, appdata
);
2036 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2037 "expected %s to end with %s\n", testpath
, winetemp
);
2039 case E_INVALIDARG
: /* winxp, win2k3 */
2042 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2045 /* test fifth parameter */
2047 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
2048 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2049 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2052 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
2053 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2054 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2057 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
2058 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2059 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2061 for(i
=0; i
< MAX_PATH
; i
++)
2062 toolongpath
[i
] = '0' + i
% 10;
2063 toolongpath
[MAX_PATH
] = '\0';
2064 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
2065 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
2066 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
2069 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
2070 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2072 /* test a not existing path */
2074 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2075 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
2076 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
2078 /* create a directory inside a not existing directory */
2080 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2081 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2082 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2083 "expected %s to start with %s\n", testpath
, appdata
);
2084 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2085 "expected %s to end with %s\n", testpath
, winetemp
);
2086 dwret
= GetFileAttributesA(testpath
);
2087 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
2090 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2091 RemoveDirectoryA(testpath
);
2092 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2093 RemoveDirectoryA(testpath
);
2096 static void test_LocalizedNames(void)
2098 static char cCurrDirA
[MAX_PATH
];
2099 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
2100 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
2101 ITEMIDLIST
*newPIDL
;
2104 static char resourcefile
[MAX_PATH
];
2110 static const char desktopini_contents1
[] =
2111 "[.ShellClassInfo]\r\n"
2112 "LocalizedResourceName=@";
2113 static const char desktopini_contents2
[] =
2115 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
2116 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
2118 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
2119 CreateDirectoryA(".\\testfolder", NULL
);
2121 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
2123 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
2125 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
2126 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2127 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
2128 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
2129 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
2130 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
2131 ok(ret
, "WriteFile failed %i\n", GetLastError());
2134 /* get IShellFolder for parent */
2135 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
2136 len
= lstrlenA(cCurrDirA
);
2139 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
2142 if(cCurrDirA
[len
-1] == '\\')
2143 cCurrDirA
[len
-1] = 0;
2145 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
2147 hr
= SHGetDesktopFolder(&IDesktopFolder
);
2148 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
2150 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
2151 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2153 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
2154 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
2156 IMalloc_Free(ppM
, newPIDL
);
2158 /* windows reads the display name from the resource */
2159 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
2160 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2162 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
2163 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2165 if (hr
== S_OK
&& pStrRetToBufW
)
2167 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2168 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2170 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2171 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2172 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2175 /* editing name is also read from the resource */
2176 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
2177 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2179 if (hr
== S_OK
&& pStrRetToBufW
)
2181 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2182 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2184 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2185 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2186 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2189 /* parsing name is unchanged */
2190 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
2191 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2193 if (hr
== S_OK
&& pStrRetToBufW
)
2195 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2196 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2197 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2200 IShellFolder_Release(IDesktopFolder
);
2201 IShellFolder_Release(testIShellFolder
);
2203 IMalloc_Free(ppM
, newPIDL
);
2206 DeleteFileA(".\\testfolder\\desktop.ini");
2207 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
2208 RemoveDirectoryA(".\\testfolder");
2211 static void test_SHCreateShellItem(void)
2213 IShellItem
*shellitem
, *shellitem2
;
2214 IPersistIDList
*persistidl
;
2215 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2217 char curdirA
[MAX_PATH
];
2218 WCHAR curdirW
[MAX_PATH
];
2219 WCHAR fnbufW
[MAX_PATH
];
2220 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2221 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2223 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2225 if (!pSHCreateShellItem
)
2227 win_skip("SHCreateShellItem isn't available\n");
2233 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2237 if(pSHGetSpecialFolderLocation
)
2239 ret
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2240 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2244 win_skip("pSHGetSpecialFolderLocation missing.\n");
2245 pidl_desktop
= NULL
;
2248 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2250 ret
= SHGetDesktopFolder(&desktopfolder
);
2251 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2253 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2254 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2256 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2257 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2259 CreateTestFile(".\\testfile");
2261 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2262 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2264 pidl_abstestfile
= pILCombine(pidl_cwd
, pidl_testfile
);
2266 shellitem
= (void*)0xdeadbeef;
2267 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2268 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2269 ok(shellitem
== 0, "Got %p\n", shellitem
);
2271 if (0) /* crashes on Windows XP */
2273 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2274 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2275 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2276 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2279 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2280 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2283 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2284 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2287 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2288 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2291 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2294 IPersistIDList_Release(persistidl
);
2296 IShellItem_Release(shellitem
);
2299 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2300 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2303 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2304 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2307 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2308 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2311 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2314 IPersistIDList_Release(persistidl
);
2317 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2318 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2321 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2322 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2325 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2326 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2329 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2332 IPersistIDList_Release(persistidl
);
2334 IShellItem_Release(shellitem2
);
2337 IShellItem_Release(shellitem
);
2340 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2341 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2344 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2345 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2348 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2349 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2352 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2355 IPersistIDList_Release(persistidl
);
2357 IShellItem_Release(shellitem
);
2360 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2361 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2362 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2365 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2366 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2369 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2370 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2373 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2376 IPersistIDList_Release(persistidl
);
2378 IShellItem_Release(shellitem
);
2381 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2382 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2385 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2386 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2389 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2390 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2393 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2396 IPersistIDList_Release(persistidl
);
2399 IShellItem_Release(shellitem
);
2402 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2403 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2406 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2407 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2408 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2409 IShellItem_Release(shellitem
);
2412 /* SHCreateItemFromParsingName */
2413 if(pSHCreateItemFromParsingName
)
2417 /* Crashes under windows 7 */
2418 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2421 shellitem
= (void*)0xdeadbeef;
2422 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2423 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2424 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2426 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2427 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2428 "SHCreateItemFromParsingName returned %x\n", ret
);
2429 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2431 lstrcpyW(fnbufW
, curdirW
);
2432 myPathAddBackslashW(fnbufW
);
2433 lstrcatW(fnbufW
, testfileW
);
2435 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2436 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2440 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2441 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2444 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2445 CoTaskMemFree(tmp_fname
);
2447 IShellItem_Release(shellitem
);
2451 win_skip("No SHCreateItemFromParsingName\n");
2454 /* SHCreateItemFromIDList */
2455 if(pSHCreateItemFromIDList
)
2459 /* Crashes under win7 */
2460 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2463 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2464 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2466 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2467 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2470 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2471 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2474 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2475 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2478 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2481 IPersistIDList_Release(persistidl
);
2483 IShellItem_Release(shellitem
);
2486 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2487 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2490 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2491 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2494 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2495 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2498 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2501 IPersistIDList_Release(persistidl
);
2503 IShellItem_Release(shellitem
);
2507 win_skip("No SHCreateItemFromIDList\n");
2509 /* SHCreateItemFromRelativeName */
2510 if(pSHCreateItemFromRelativeName
&& pSHGetKnownFolderPath
)
2512 IShellItem
*shellitem_desktop
= NULL
;
2513 WCHAR
*desktop_path
, *displayname
;
2514 WCHAR testfile_path
[MAX_PATH
] = {0};
2516 LPITEMIDLIST pidl_desktop_testfile
= NULL
;
2519 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem_desktop
);
2520 ok(ret
== S_OK
, "SHCreateShellItem failed: 0x%08x.\n", ret
);
2522 shellitem
= (void*)0xdeadbeef;
2523 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, NULL
, NULL
, &IID_IShellItem
,
2524 (void**)&shellitem
);
2525 ok(ret
== E_INVALIDARG
, "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n",
2527 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2529 /* Test with a non-existent file */
2530 shellitem
= (void*)0xdeadbeef;
2531 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2532 (void**)&shellitem
);
2533 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2534 "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n",
2535 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), ret
);
2536 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2538 /* Create a file for testing in desktop folder */
2539 pSHGetKnownFolderPath(&FOLDERID_Desktop
, 0, NULL
, &desktop_path
);
2540 lstrcatW(testfile_path
, desktop_path
);
2541 myPathAddBackslashW(testfile_path
);
2542 lstrcatW(testfile_path
, testfileW
);
2543 file
= CreateFileW(testfile_path
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
2544 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError());
2547 shellitem
= (void*)0xdeadbeef;
2548 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2549 (void**)&shellitem
);
2550 ok(ret
== S_OK
, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret
);
2551 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2554 ret
= IShellItem_GetDisplayName(shellitem
, 0, &displayname
);
2555 ok(ret
== S_OK
, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret
);
2556 ok(!lstrcmpW(displayname
, testfileW
), "got wrong display name: %s.\n", wine_dbgstr_w(displayname
));
2557 CoTaskMemFree(displayname
);
2559 shellitem2
= (void*)0xdeadbeef;
2560 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2561 (void**)&shellitem2
);
2562 ok(ret
== S_OK
, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret
);
2563 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2564 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2565 ok(!order
, "order got wrong value: %d.\n", order
);
2566 IShellItem_Release(shellitem2
);
2568 shellitem2
= (void*)0xdeadbeef;
2569 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, testfileW
, NULL
,
2570 &pidl_desktop_testfile
, NULL
);
2571 ok(ret
== S_OK
, "ParseDisplayName failed 0x%08x.\n", ret
);
2572 ret
= pSHCreateItemFromIDList(pidl_desktop_testfile
, &IID_IShellItem
, (void**)&shellitem2
);
2573 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2574 ok(ret
== S_OK
, "IShellItem_Compare fail: 0x%08x.\n", ret
);
2575 ok(!order
, "order got wrong value: %d.\n", order
);
2576 pILFree(pidl_desktop_testfile
);
2577 IShellItem_Release(shellitem2
);
2579 IShellItem_Release(shellitem
);
2582 DeleteFileW(testfile_path
);
2583 CoTaskMemFree(desktop_path
);
2584 IShellItem_Release(shellitem_desktop
);
2587 win_skip("No SHCreateItemFromRelativeName or SHGetKnownFolderPath\n");
2589 /* SHCreateItemInKnownFolder */
2590 if(pSHCreateItemInKnownFolder
&& pSHGetKnownFolderPath
)
2592 WCHAR
*desktop_path
;
2593 WCHAR testfile_path
[MAX_PATH
] = {0};
2595 WCHAR
*displayname
= NULL
;
2597 LPITEMIDLIST pidl_desktop_testfile
= NULL
;
2599 shellitem
= (void*)0xdeadbeef;
2600 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, NULL
, &IID_IShellItem
,
2601 (void**)&shellitem
);
2602 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2603 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2606 shellitem2
= (void*)0xdeadbeef;
2607 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem2
);
2608 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2611 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2612 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2613 ok(!order
, "order got wrong value: %d.\n", order
);
2614 IShellItem_Release(shellitem2
);
2616 IShellItem_Release(shellitem
);
2619 /* Test with a non-existent file */
2620 shellitem
= (void*)0xdeadbeef;
2621 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2622 (void**)&shellitem
);
2623 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2624 "Expected 0x%08x but SHCreateItemInKnownFolder return: 0x%08x.\n",
2625 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), ret
);
2626 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2628 pSHGetKnownFolderPath(&FOLDERID_Desktop
, 0, NULL
, &desktop_path
);
2629 lstrcatW(testfile_path
, desktop_path
);
2630 myPathAddBackslashW(testfile_path
);
2631 lstrcatW(testfile_path
, testfileW
);
2632 file
= CreateFileW(testfile_path
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
2633 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError());
2636 shellitem
= (void*)0xdeadbeef;
2637 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2638 (void**)&shellitem
);
2639 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2640 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2643 ret
= IShellItem_GetDisplayName(shellitem
, 0, &displayname
);
2644 ok(ret
== S_OK
, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret
);
2645 ok(!lstrcmpW(displayname
, testfileW
), "got wrong display name: %s.\n",
2646 wine_dbgstr_w(displayname
));
2647 CoTaskMemFree(displayname
);
2649 shellitem2
= (void*)0xdeadbeef;
2650 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2651 (void**)&shellitem2
);
2652 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2653 ok(shellitem2
!= NULL
, "shellitem was %p.\n", shellitem
);
2654 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2655 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2656 ok(!order
, "order got wrong value: %d.\n", order
);
2657 IShellItem_Release(shellitem2
);
2659 shellitem2
= (void*)0xdeadbeef;
2660 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, testfileW
, NULL
,
2661 &pidl_desktop_testfile
, NULL
);
2662 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x.\n", ret
);
2663 ret
= pSHCreateItemFromIDList(pidl_desktop_testfile
, &IID_IShellItem
, (void**)&shellitem2
);
2664 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2665 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2666 ok(!order
, "order got wrong value: %d.\n", order
);
2667 pILFree(pidl_desktop_testfile
);
2668 IShellItem_Release(shellitem2
);
2670 IShellItem_Release(shellitem
);
2673 shellitem
= (void*)0xdeadbeef;
2674 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Documents
, 0, NULL
, &IID_IShellItem
,
2675 (void**)&shellitem
);
2676 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2677 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2680 shellitem2
= (void*)0xdeadbeef;
2681 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Documents
, 0, NULL
, &IID_IShellItem
,
2682 (void**)&shellitem2
);
2683 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2684 ok(shellitem2
!= NULL
, "shellitem was %p.\n", shellitem
);
2685 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2686 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2687 ok(!order
, "order got wrong value: %d.\n", order
);
2688 IShellItem_Release(shellitem2
);
2690 IShellItem_Release(shellitem
);
2692 DeleteFileW(testfile_path
);
2693 CoTaskMemFree(desktop_path
);
2696 win_skip("No SHCreateItemInKnownFolder or SHGetKnownFolderPath\n");
2698 DeleteFileA(".\\testfile");
2699 pILFree(pidl_abstestfile
);
2700 pILFree(pidl_testfile
);
2701 pILFree(pidl_desktop
);
2703 IShellFolder_Release(currentfolder
);
2704 IShellFolder_Release(desktopfolder
);
2707 static void test_SHGetNameFromIDList(void)
2709 IShellItem
*shellitem
;
2714 static const DWORD flags
[] = {
2715 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2716 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2717 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2718 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2720 if(!pSHGetNameFromIDList
)
2722 win_skip("SHGetNameFromIDList missing.\n");
2726 /* These should be available on any platform that passed the above test. */
2727 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2728 ok(pSHBindToParent
!= NULL
, "SHBindToParent missing.\n");
2729 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
2730 ok(pStrRetToBufW
!= NULL
, "StrRetToBufW missing.\n");
2734 /* Crashes under win7 */
2735 pSHGetNameFromIDList(NULL
, 0, NULL
);
2738 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2739 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2741 /* Test the desktop */
2742 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2743 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2744 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2745 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2748 WCHAR
*nameSI
, *nameSH
;
2749 WCHAR buf
[MAX_PATH
];
2750 HRESULT hrSI
, hrSH
, hrSF
;
2755 SHGetDesktopFolder(&psf
);
2756 for(i
= 0; flags
[i
] != -1234; i
++)
2758 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2759 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2760 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2761 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2762 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2763 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2765 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2766 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2770 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2772 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2774 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2776 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2777 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2779 IShellFolder_Release(psf
);
2781 if(pSHGetPathFromIDListW
){
2782 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2783 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2784 res
= pSHGetPathFromIDListW(pidl
, buf
);
2785 ok(res
== TRUE
, "Got %d\n", res
);
2786 if(SUCCEEDED(hrSI
) && res
)
2787 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2788 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2790 win_skip("pSHGetPathFromIDListW not available\n");
2792 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2793 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2794 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2796 IShellItem_Release(shellitem
);
2800 /* Test the control panel */
2801 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2802 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2803 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2804 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2807 WCHAR
*nameSI
, *nameSH
;
2808 WCHAR buf
[MAX_PATH
];
2809 HRESULT hrSI
, hrSH
, hrSF
;
2814 SHGetDesktopFolder(&psf
);
2815 for(i
= 0; flags
[i
] != -1234; i
++)
2817 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2818 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2819 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2820 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2821 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2822 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2824 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2825 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2829 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2831 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2833 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2835 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2836 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2838 IShellFolder_Release(psf
);
2840 if(pSHGetPathFromIDListW
){
2841 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2842 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2843 res
= pSHGetPathFromIDListW(pidl
, buf
);
2844 ok(res
== FALSE
, "Got %d\n", res
);
2845 if(SUCCEEDED(hrSI
) && res
)
2846 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2847 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2849 win_skip("pSHGetPathFromIDListW not available\n");
2851 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2852 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2853 "Got 0x%08x\n", hres
);
2854 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2856 IShellItem_Release(shellitem
);
2861 static void test_SHGetItemFromDataObject(void)
2863 IShellFolder
*psfdesktop
;
2868 if(!pSHGetItemFromDataObject
)
2870 win_skip("No SHGetItemFromDataObject.\n");
2876 /* Crashes under win7 */
2877 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2880 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2881 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2883 SHGetDesktopFolder(&psfdesktop
);
2885 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2886 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2893 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2894 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2895 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2898 LPITEMIDLIST apidl
[5];
2901 for(count
= 0; count
< 5; count
++)
2902 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2907 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2908 &IID_IDataObject
, NULL
, (void**)&pdo
);
2909 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2912 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2913 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2914 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2915 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2916 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2917 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2918 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2919 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2920 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2921 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2922 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2923 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2924 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2925 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2926 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2928 IDataObject_Release(pdo
);
2932 skip("No file(s) found - skipping single-file test.\n");
2936 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2937 &IID_IDataObject
, NULL
, (void**)&pdo
);
2938 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2941 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2942 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2943 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2944 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2945 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2946 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2947 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2948 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2949 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2950 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2951 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2952 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2953 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2954 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2955 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2956 IDataObject_Release(pdo
);
2960 skip("zero or one file found - skipping multi-file test.\n");
2962 for(i
= 0; i
< count
; i
++)
2965 IEnumIDList_Release(peidl
);
2968 IShellView_Release(psv
);
2971 IShellFolder_Release(psfdesktop
);
2974 static void test_ShellItemCompare(void)
2976 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2977 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2978 IShellFolder
*psf_desktop
, *psf_current
;
2979 LPITEMIDLIST pidl_cwd
;
2980 WCHAR curdirW
[MAX_PATH
];
2983 static const WCHAR filesW
[][9] = {
2984 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2985 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2986 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2990 if(!pSHCreateShellItem
)
2992 win_skip("SHCreateShellItem missing.\n");
2996 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2999 skip("Failed to get current directory, skipping.\n");
3003 CreateDirectoryA(".\\a", NULL
);
3004 CreateDirectoryA(".\\b", NULL
);
3005 CreateDirectoryA(".\\c", NULL
);
3006 CreateTestFile(".\\a\\a");
3007 CreateTestFile(".\\a\\b");
3008 CreateTestFile(".\\a\\c");
3009 CreateTestFile(".\\b\\a");
3010 CreateTestFile(".\\b\\b");
3011 CreateTestFile(".\\b\\c");
3012 CreateTestFile(".\\c\\a");
3013 CreateTestFile(".\\c\\b");
3014 CreateTestFile(".\\c\\c");
3016 SHGetDesktopFolder(&psf_desktop
);
3017 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
3018 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
3019 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
3020 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
3021 IShellFolder_Release(psf_desktop
);
3024 /* Generate ShellItems for the files */
3025 memset(&psi
, 0, sizeof(psi
));
3027 for(i
= 0; i
< 9; i
++)
3029 LPITEMIDLIST pidl_testfile
= NULL
;
3031 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
3032 NULL
, &pidl_testfile
, NULL
);
3033 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
3036 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
3037 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3038 pILFree(pidl_testfile
);
3040 if(FAILED(hr
)) failed
= TRUE
;
3044 skip("Failed to create all shellitems.\n");
3048 /* Generate ShellItems for the folders */
3049 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
3050 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3051 if(FAILED(hr
)) failed
= TRUE
;
3052 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
3053 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3054 if(FAILED(hr
)) failed
= TRUE
;
3055 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
3056 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3057 if(FAILED(hr
)) failed
= TRUE
;
3061 skip("Failed to create shellitems.\n");
3067 /* Crashes on native (win7, winxp) */
3068 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
3069 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
3070 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
3074 for(i
= 0; i
< 9; i
++)
3076 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
3077 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3078 ok(order
== 0, "Got order %d\n", order
);
3079 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
3080 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3081 ok(order
== 0, "Got order %d\n", order
);
3082 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
3083 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3084 ok(order
== 0, "Got order %d\n", order
);
3088 /* a\b:a\a , a\b:a\c, a\b:a\b */
3089 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &order
);
3090 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3091 ok(order
== 1, "Got order %d\n", order
);
3092 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_DISPLAY
, &order
);
3093 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3094 ok(order
== -1, "Got order %d\n", order
);
3095 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
3096 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3097 ok(order
== 0, "Got order %d\n", order
);
3099 /* b\b:a\b, b\b:c\b, b\b:c\b */
3100 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
3101 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3102 ok(order
== 1, "Got order %d\n", order
);
3103 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
3104 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3105 ok(order
== -1, "Got order %d\n", order
);
3106 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
3107 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3108 ok(order
== 0, "Got order %d\n", order
);
3110 /* b:a\a, b:a\c, b:a\b */
3111 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
3112 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3113 todo_wine
ok(order
== 1, "Got order %d\n", order
);
3114 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
3115 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3116 todo_wine
ok(order
== 1, "Got order %d\n", order
);
3117 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
3118 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3119 todo_wine
ok(order
== 1, "Got order %d\n", order
);
3121 /* b:c\a, b:c\c, b:c\b */
3122 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
3123 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3124 ok(order
== -1, "Got order %d\n", order
);
3125 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_DISPLAY
, &order
);
3126 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3127 ok(order
== -1, "Got order %d\n", order
);
3128 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
3129 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3130 ok(order
== -1, "Got order %d\n", order
);
3132 /* a\b:a\a , a\b:a\c, a\b:a\b */
3133 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
3134 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3135 ok(order
== 1, "Got order %d\n", order
);
3136 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
3137 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3138 ok(order
== -1, "Got order %d\n", order
);
3139 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
3140 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3141 ok(order
== 0, "Got order %d\n", order
);
3143 /* b\b:a\b, b\b:c\b, b\b:c\b */
3144 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
3145 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3146 ok(order
== 1, "Got order %d\n", order
);
3147 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &order
);
3148 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3149 ok(order
== -1, "Got order %d\n", order
);
3150 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
3151 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3152 ok(order
== 0, "Got order %d\n", order
);
3154 /* b:a\a, b:a\c, b:a\b */
3155 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
3156 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3157 todo_wine
ok(order
== 1, "Got order %d\n", order
);
3158 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
3159 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3160 todo_wine
ok(order
== 1, "Got order %d\n", order
);
3161 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
3162 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3163 todo_wine
ok(order
== 1, "Got order %d\n", order
);
3165 /* b:c\a, b:c\c, b:c\b */
3166 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
3167 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3168 ok(order
== -1, "Got order %d\n", order
);
3169 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_CANONICAL
, &order
);
3170 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3171 ok(order
== -1, "Got order %d\n", order
);
3172 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
3173 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3174 ok(order
== -1, "Got order %d\n", order
);
3177 IShellFolder_Release(psf_current
);
3179 DeleteFileA(".\\a\\a");
3180 DeleteFileA(".\\a\\b");
3181 DeleteFileA(".\\a\\c");
3182 DeleteFileA(".\\b\\a");
3183 DeleteFileA(".\\b\\b");
3184 DeleteFileA(".\\b\\c");
3185 DeleteFileA(".\\c\\a");
3186 DeleteFileA(".\\c\\b");
3187 DeleteFileA(".\\c\\c");
3188 RemoveDirectoryA(".\\a");
3189 RemoveDirectoryA(".\\b");
3190 RemoveDirectoryA(".\\c");
3192 if(psi_a
) IShellItem_Release(psi_a
);
3193 if(psi_b
) IShellItem_Release(psi_b
);
3194 if(psi_c
) IShellItem_Release(psi_c
);
3196 for(i
= 0; i
< 9; i
++)
3197 if(psi
[i
]) IShellItem_Release(psi
[i
]);
3200 /**************************************************************/
3201 /* IUnknown implementation for counting QueryInterface calls. */
3203 IUnknown IUnknown_iface
;
3211 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
3213 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
3216 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
3218 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
3221 for(i
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
3223 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
3225 This
->ifaces
[i
].count
++;
3232 return E_NOINTERFACE
;
3235 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3240 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3245 static const IUnknownVtbl vt_IUnknown
= {
3246 unk_fnQueryInterface
,
3251 static void test_SHGetIDListFromObject(void)
3253 IUnknownImpl
*punkimpl
;
3254 IShellFolder
*psfdesktop
;
3256 LPITEMIDLIST pidl
, pidl_desktop
;
3259 struct if_count ifaces
[] =
3260 { {&IID_IPersistIDList
, 0},
3261 {&IID_IPersistFolder2
, 0},
3262 {&IID_IDataObject
, 0},
3263 {&IID_IParentAndItem
, 0},
3264 {&IID_IFolderView
, 0},
3267 if(!pSHGetIDListFromObject
)
3269 win_skip("SHGetIDListFromObject missing.\n");
3273 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3277 /* Crashes native */
3278 pSHGetIDListFromObject(NULL
, NULL
);
3279 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3282 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3283 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3285 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3286 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3287 punkimpl
->ifaces
= ifaces
;
3288 punkimpl
->unknown
= 0;
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 pidl_desktop
= NULL
;
3305 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3306 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3308 SHGetDesktopFolder(&psfdesktop
);
3310 /* Test IShellItem */
3311 if(pSHCreateShellItem
)
3313 IShellItem
*shellitem
;
3314 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3315 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3318 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3319 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3322 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3325 IShellItem_Release(shellitem
);
3329 skip("no SHCreateShellItem.\n");
3331 /* Test IShellFolder */
3332 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3333 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3336 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3340 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3341 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3348 /* Test IFolderView */
3349 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3350 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3353 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3357 /* Test IDataObject */
3358 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3359 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3360 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3363 LPITEMIDLIST apidl
[5];
3365 for(count
= 0; count
< 5; count
++)
3366 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3371 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3372 &IID_IDataObject
, NULL
, (void**)&pdo
);
3373 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3376 pidl
= (void*)0xDEADBEEF;
3377 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3378 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3379 ok(pidl
!= NULL
, "pidl is NULL.\n");
3380 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3383 IDataObject_Release(pdo
);
3387 skip("No files found - skipping single-file test.\n");
3391 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3392 &IID_IDataObject
, NULL
, (void**)&pdo
);
3393 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3396 pidl
= (void*)0xDEADBEEF;
3397 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3398 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3399 "got 0x%08x\n", hres
);
3400 ok(pidl
== NULL
, "pidl is not NULL.\n");
3402 IDataObject_Release(pdo
);
3406 skip("zero or one file found - skipping multi-file test.\n");
3408 for(i
= 0; i
< count
; i
++)
3411 IEnumIDList_Release(peidl
);
3414 IShellView_Release(psv
);
3417 IShellFolder_Release(psfdesktop
);
3418 pILFree(pidl_desktop
);
3421 static void test_SHGetItemFromObject(void)
3423 IUnknownImpl
*punkimpl
;
3424 IShellFolder
*psfdesktop
;
3429 struct if_count ifaces
[] =
3430 { {&IID_IPersistIDList
, 0},
3431 {&IID_IPersistFolder2
, 0},
3432 {&IID_IDataObject
, 0},
3433 {&IID_IParentAndItem
, 0},
3434 {&IID_IFolderView
, 0},
3437 if(!pSHGetItemFromObject
)
3439 skip("No SHGetItemFromObject.\n");
3443 SHGetDesktopFolder(&psfdesktop
);
3447 /* Crashes with Windows 7 */
3448 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3449 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3450 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3453 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3454 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3456 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3457 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3458 punkimpl
->ifaces
= ifaces
;
3459 punkimpl
->unknown
= 0;
3461 /* The same as SHGetIDListFromObject */
3462 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3463 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3464 ok(ifaces
[0].count
, "interface not requested.\n");
3465 ok(ifaces
[1].count
, "interface not requested.\n");
3466 ok(ifaces
[2].count
, "interface not requested.\n");
3468 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3469 "interface not requested.\n");
3470 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3471 "interface not requested.\n");
3473 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3474 HeapFree(GetProcessHeap(), 0, punkimpl
);
3476 /* Test IShellItem */
3477 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3478 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3482 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3483 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3487 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3488 IShellItem_Release(psi2
);
3490 IShellItem_Release(psi
);
3493 IShellFolder_Release(psfdesktop
);
3496 static void test_SHCreateShellItemArray(void)
3498 IShellFolder
*pdesktopsf
, *psf
;
3499 IShellItemArray
*psia
;
3502 WCHAR cTestDirW
[MAX_PATH
];
3503 LPITEMIDLIST pidl_testdir
, pidl
;
3504 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3506 if(!pSHCreateShellItemArray
) {
3507 skip("No pSHCreateShellItemArray!\n");
3511 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3515 /* Crashes under native */
3516 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3517 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3518 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3519 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3522 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3523 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3525 SHGetDesktopFolder(&pdesktopsf
);
3526 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3527 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3529 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3530 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3532 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3533 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3534 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3537 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3538 myPathAddBackslashW(cTestDirW
);
3539 lstrcatW(cTestDirW
, testdirW
);
3541 CreateFilesFolders();
3543 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3544 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3547 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3549 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3551 IShellFolder_Release(pdesktopsf
);
3555 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3556 pILFree(pidl_testdir
);
3561 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3562 ok(hr
== S_OK
, "Got %08x\n", hr
);
3565 LPITEMIDLIST apidl
[5];
3566 UINT done
, numitems
, i
;
3568 for(done
= 0; done
< 5; done
++)
3569 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3571 ok(done
== 5, "Got %d pidls\n", done
);
3572 IEnumIDList_Release(peidl
);
3574 /* Create a ShellItemArray */
3575 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3576 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3583 /* Crashes in Windows 7 */
3584 IShellItemArray_GetCount(psia
, NULL
);
3587 IShellItemArray_GetCount(psia
, &numitems
);
3588 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3590 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3591 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3593 /* Compare all the items */
3594 for(i
= 0; i
< numitems
; i
++)
3596 LPITEMIDLIST pidl_abs
;
3597 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3599 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3600 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3603 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3604 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3607 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3610 IShellItem_Release(psi
);
3614 for(i
= 0; i
< done
; i
++)
3616 IShellItemArray_Release(psia
);
3620 /* SHCreateShellItemArrayFromShellItem */
3621 if(pSHCreateShellItemArrayFromShellItem
)
3627 /* Crashes under Windows 7 */
3628 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3629 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3630 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3633 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3634 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3637 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3638 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3643 hr
= IShellItemArray_GetCount(psia
, &count
);
3644 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3645 ok(count
== 1, "Got count %d\n", count
);
3646 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3647 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3649 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3652 LPITEMIDLIST pidl1
, pidl2
;
3653 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3654 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3655 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3656 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3657 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3658 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3659 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3662 IShellItem_Release(psi2
);
3664 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3665 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3666 IShellItemArray_Release(psia
);
3668 IShellItem_Release(psi
);
3672 skip("No SHCreateShellItemArrayFromShellItem.\n");
3674 if(pSHCreateShellItemArrayFromDataObject
)
3680 /* Crashes under Windows 7 */
3681 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3683 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3684 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3686 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3687 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3694 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3695 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3699 LPITEMIDLIST apidl
[5];
3702 for(count
= 0; count
< 5; count
++)
3703 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3705 ok(count
== 5, "Got %d\n", count
);
3709 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3710 &IID_IDataObject
, NULL
, (void**)&pdo
);
3711 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3714 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3716 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3720 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3721 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3722 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3723 for(i
= 0; i
< count_sia
; i
++)
3725 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3727 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3728 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3732 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3733 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3734 ok(pidl
!= NULL
, "pidl as NULL.\n");
3735 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3737 IShellItem_Release(psi
);
3742 IShellItemArray_Release(psia
);
3745 IDataObject_Release(pdo
);
3747 for(i
= 0; i
< count
; i
++)
3751 skip("No files found - skipping test.\n");
3753 IEnumIDList_Release(peidl
);
3755 IShellView_Release(psv
);
3759 skip("No SHCreateShellItemArrayFromDataObject.\n");
3761 if(pSHCreateShellItemArrayFromIDLists
)
3763 WCHAR test1W
[] = {'t','e','s','t','1','.','t','x','t',0};
3764 WCHAR test1pathW
[MAX_PATH
];
3765 LPITEMIDLIST pidltest1
;
3766 LPCITEMIDLIST pidl_array
[2];
3771 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, NULL
);
3774 psia
= (void*)0xdeadbeef;
3775 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, &psia
);
3776 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3777 ok(psia
== NULL
, "Got %p\n", psia
);
3779 psia
= (void*)0xdeadbeef;
3780 hr
= pSHCreateShellItemArrayFromIDLists(0, pidl_array
, &psia
);
3781 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3782 ok(psia
== NULL
, "Got %p\n", psia
);
3784 psia
= (void*)0xdeadbeef;
3785 pidl_array
[0] = NULL
;
3786 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3787 todo_wine
ok(hr
== E_OUTOFMEMORY
, "Got 0x%08x\n", hr
);
3788 ok(psia
== NULL
, "Got %p\n", psia
);
3790 psia
= (void*)0xdeadbeef;
3791 pidl_array
[0] = pidl_testdir
;
3792 pidl_array
[1] = NULL
;
3793 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3794 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Vista */, "Got 0x%08x\n", hr
);
3795 todo_wine
ok(psia
!= NULL
|| broken(psia
== NULL
) /* Vista */, "Got %p\n", psia
);
3801 hr
= IShellItemArray_GetCount(psia
, &count
);
3802 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3803 ok(count
== 2, "Got %d\n", count
);
3805 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3806 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3810 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3811 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3812 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3814 CoTaskMemFree(path
);
3816 IShellItem_Release(psi
);
3819 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3820 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3824 WCHAR desktoppath
[MAX_PATH
];
3827 result
= pSHGetSpecialFolderPathW(NULL
, desktoppath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
3828 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
3830 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3831 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3832 ok(!lstrcmpW(path
, desktoppath
), "Got %s\n", wine_dbgstr_w(path
));
3834 CoTaskMemFree(path
);
3836 IShellItem_Release(psi
);
3840 IShellItemArray_Release(psia
);
3845 psia
= (void*)0xdeadbeef;
3846 pidl_array
[0] = pidl_testdir
;
3847 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3848 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3854 hr
= IShellItemArray_GetCount(psia
, &count
);
3855 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3856 ok(count
== 1, "Got %d\n", count
);
3858 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3859 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3863 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3864 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3865 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3867 CoTaskMemFree(path
);
3869 IShellItem_Release(psi
);
3872 IShellItemArray_Release(psia
);
3876 lstrcpyW(test1pathW
, cTestDirW
);
3877 myPathAddBackslashW(test1pathW
);
3878 lstrcatW(test1pathW
, test1W
);
3880 SHGetDesktopFolder(&pdesktopsf
);
3882 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, test1pathW
, NULL
, &pidltest1
, NULL
);
3883 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3886 psia
= (void*)0xdeadbeef;
3887 pidl_array
[0] = pidl_testdir
;
3888 pidl_array
[1] = pidltest1
;
3889 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3890 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3896 hr
= IShellItemArray_GetCount(psia
, &count
);
3897 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3898 ok(count
== 2, "Got %d\n", count
);
3900 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3901 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3905 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3906 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3907 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3909 CoTaskMemFree(path
);
3911 IShellItem_Release(psi
);
3914 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3915 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3919 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3920 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3921 ok(!lstrcmpW(path
, test1pathW
), "Got %s\n", wine_dbgstr_w(path
));
3923 CoTaskMemFree(path
);
3925 IShellItem_Release(psi
);
3929 IShellItemArray_Release(psia
);
3935 IShellFolder_Release(pdesktopsf
);
3938 skip("No SHCreateShellItemArrayFromIDLists.\n");
3940 IShellFolder_Release(psf
);
3941 pILFree(pidl_testdir
);
3945 static void test_ShellItemArrayEnumItems(void)
3947 IShellFolder
*pdesktopsf
, *psf
;
3949 WCHAR cTestDirW
[MAX_PATH
];
3951 LPITEMIDLIST pidl_testdir
;
3952 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3954 if(!pSHCreateShellItemArray
)
3956 win_skip("No SHCreateShellItemArray, skipping test...\n");
3960 CreateFilesFolders();
3962 SHGetDesktopFolder(&pdesktopsf
);
3964 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3965 myPathAddBackslashW(cTestDirW
);
3966 lstrcatW(cTestDirW
, testdirW
);
3968 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3969 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3972 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3974 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3975 pILFree(pidl_testdir
);
3977 IShellFolder_Release(pdesktopsf
);
3978 if (FAILED(hr
)) return;
3980 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3981 ok(hr
== S_OK
, "Got %08x\n", hr
);
3984 IShellItemArray
*psia
;
3985 LPITEMIDLIST apidl
[5];
3986 UINT done
, numitems
, i
;
3988 for(done
= 0; done
< 5; done
++)
3989 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3991 ok(done
== 5, "Got %d pidls\n", done
);
3992 IEnumIDList_Release(peidl
);
3994 /* Create a ShellItemArray */
3995 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3996 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3999 IEnumShellItems
*iesi
;
4000 IShellItem
*my_array
[10];
4003 IShellItemArray_GetCount(psia
, &numitems
);
4004 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
4007 hr
= IShellItemArray_EnumItems(psia
, &iesi
);
4008 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4009 ok(iesi
!= NULL
, "Got NULL\n");
4012 IEnumShellItems
*iesi2
;
4014 /* This should fail according to the documentation and Win7+ */
4015 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
4016 hr
= IEnumShellItems_Next(iesi
, 2, my_array
, NULL
);
4017 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4018 for(i
= 0; i
< 2; i
++)
4020 ok(my_array
[i
] == (void*)0xdeadbeef ||
4021 broken(my_array
[i
] != (void*)0xdeadbeef && my_array
[i
] != NULL
), /* Vista */
4022 "Got %p (%d)\n", my_array
[i
], i
);
4024 if(my_array
[i
] != (void*)0xdeadbeef)
4025 IShellItem_Release(my_array
[i
]);
4027 ok(my_array
[2] == (void*)0xdeadbeef, "Got %p\n", my_array
[2]);
4029 IEnumShellItems_Reset(iesi
);
4030 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
4031 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, NULL
);
4032 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4033 ok(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
4034 if(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef)
4035 IShellItem_Release(my_array
[0]);
4036 ok(my_array
[1] == (void*)0xdeadbeef, "Got %p\n", my_array
[1]);
4038 IEnumShellItems_Reset(iesi
);
4040 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
4041 hr
= IEnumShellItems_Next(iesi
, numitems
, my_array
, &fetched
);
4042 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4043 ok(fetched
== numitems
, "Got %d\n", fetched
);
4044 for(i
= 0;i
< numitems
; i
++)
4046 ok(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef,
4047 "Got %p at %d\n", my_array
[i
], i
);
4049 if(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef)
4050 IShellItem_Release(my_array
[i
]);
4052 ok(my_array
[i
] == (void*)0xdeadbeef, "Got %p\n", my_array
[i
]);
4054 /* Compare all the items */
4055 IEnumShellItems_Reset(iesi
);
4056 for(i
= 0; i
< numitems
; i
++)
4061 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
4062 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4063 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
4064 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4065 ok(fetched
== 1, "Got %d\n", fetched
);
4067 hr
= IShellItem_Compare(psi
, my_array
[0], 0, &order
);
4068 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4069 ok(order
== 0, "Got %d\n", order
);
4071 IShellItem_Release(psi
);
4072 IShellItem_Release(my_array
[0]);
4075 my_array
[0] = (void*)0xdeadbeef;
4076 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
4077 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
4078 ok(fetched
== 0, "Got %d\n", fetched
);
4079 ok(my_array
[0] == (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
4081 /* Cloning not implemented anywhere */
4082 iesi2
= (void*)0xdeadbeef;
4083 hr
= IEnumShellItems_Clone(iesi
, &iesi2
);
4084 ok(hr
== E_NOTIMPL
, "Got 0x%08x\n", hr
);
4085 ok(iesi2
== NULL
|| broken(iesi2
== (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2
);
4087 IEnumShellItems_Release(iesi
);
4090 IShellItemArray_Release(psia
);
4093 for(i
= 0; i
< done
; i
++)
4099 static void test_ShellItemBindToHandler(void)
4102 LPITEMIDLIST pidl_desktop
;
4105 if(!pSHCreateShellItem
)
4107 skip("SHCreateShellItem missing.\n");
4111 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
4112 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4115 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
4116 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4120 IPersistFolder2
*ppf2
;
4125 /* Crashes under Windows 7 */
4126 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
4127 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
4129 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
4130 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
4133 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
4134 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4135 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4136 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
4137 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4140 LPITEMIDLIST pidl_tmp
;
4141 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
4142 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4145 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
4148 IPersistFolder2_Release(ppf2
);
4151 /* BHID_SFUIObject */
4152 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
4153 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
4154 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4155 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
4156 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
4157 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4159 /* BHID_DataObject */
4160 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
4161 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4162 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4166 /* BHID_SFViewObject */
4167 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
4168 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4169 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4170 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
4171 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
4172 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4175 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
4176 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
4177 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4178 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
4179 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4180 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4183 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
4184 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
4185 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4186 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
4187 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4188 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4190 /* BHID_StorageEnum */
4191 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
4192 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4193 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4196 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
4197 supported starting from Win8. */
4198 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferSource
, (void**)&punk
);
4199 ok(hr
== S_OK
|| broken(FAILED(hr
)) /* pre-Vista */, "Got 0x%08x\n", hr
);
4202 IUnknown_Release(punk
);
4204 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferDestination
, (void**)&punk
);
4205 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4206 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4208 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
4209 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Win8 */, "Got 0x%08x\n", hr
);
4210 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4213 /* BHID_EnumItems */
4214 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
4215 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4216 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4219 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
4220 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4221 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4223 /* BHID_LinkTargetItem */
4224 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
4225 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
4226 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4227 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
4228 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
4229 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4231 /* BHID_PropertyStore */
4232 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
4233 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4234 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4235 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
4236 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4237 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4239 /* BHID_ThumbnailHandler */
4240 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
4241 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4242 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4244 /* BHID_AssociationArray */
4245 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
4246 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4247 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4249 /* BHID_EnumAssocHandlers */
4250 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
4251 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4252 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4255 IShellItem_Release(psi
);
4258 skip("Failed to create ShellItem.\n");
4260 pILFree(pidl_desktop
);
4263 static void test_ShellItemGetAttributes(void)
4265 IShellItem
*psi
, *psi_folder1
, *psi_file1
;
4266 IShellFolder
*pdesktopsf
;
4267 LPITEMIDLIST pidl_desktop
, pidl
;
4270 WCHAR curdirW
[MAX_PATH
];
4271 WCHAR buf
[MAX_PATH
];
4272 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4273 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4275 if(!pSHCreateShellItem
)
4277 skip("SHCreateShellItem missing.\n");
4281 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
4282 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4285 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
4286 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4287 pILFree(pidl_desktop
);
4291 skip("Skipping tests.\n");
4297 /* Crashes on native (Win 7) */
4298 IShellItem_GetAttributes(psi
, 0, NULL
);
4301 /* Test GetAttributes on the desktop folder. */
4303 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
4304 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
4305 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
4307 IShellItem_Release(psi
);
4309 CreateFilesFolders();
4311 SHGetDesktopFolder(&pdesktopsf
);
4313 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4314 myPathAddBackslashW(curdirW
);
4316 lstrcpyW(buf
, curdirW
);
4317 lstrcatW(buf
, testdir1W
);
4318 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4319 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4320 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_folder1
);
4321 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4324 lstrcpyW(buf
, curdirW
);
4325 lstrcatW(buf
, testfile1W
);
4326 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4327 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4328 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_file1
);
4329 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4332 IShellFolder_Release(pdesktopsf
);
4335 hr
= IShellItem_GetAttributes(psi_folder1
, 0, &sfgao
);
4336 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4337 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4340 hr
= IShellItem_GetAttributes(psi_folder1
, SFGAO_FOLDER
, &sfgao
);
4341 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4342 ok(sfgao
== SFGAO_FOLDER
, "Got 0x%08x\n", sfgao
);
4345 hr
= IShellItem_GetAttributes(psi_file1
, SFGAO_FOLDER
, &sfgao
);
4346 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
4347 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4349 IShellItem_Release(psi_folder1
);
4350 IShellItem_Release(psi_file1
);
4355 static void test_ShellItemArrayGetAttributes(void)
4357 IShellItemArray
*psia_files
, *psia_folders1
, *psia_folders2
, *psia_all
;
4358 IShellFolder
*pdesktopsf
;
4359 LPCITEMIDLIST pidl_array
[5];
4362 WCHAR curdirW
[MAX_PATH
];
4363 WCHAR buf
[MAX_PATH
];
4365 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4366 static const WCHAR testdir2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
4367 static const WCHAR testdir3W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
4368 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4369 static const WCHAR testfile2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
4370 static const WCHAR
*testfilesW
[5] = { testdir1W
, testdir2W
, testdir3W
, testfile1W
, testfile2W
};
4372 if(!pSHCreateShellItemArrayFromShellItem
)
4374 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
4378 CreateFilesFolders();
4379 CreateDirectoryA(".\\testdir\\testdir3", NULL
);
4381 SHGetDesktopFolder(&pdesktopsf
);
4383 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4384 myPathAddBackslashW(curdirW
);
4386 for(i
= 0; i
< 5; i
++)
4388 lstrcpyW(buf
, curdirW
);
4389 lstrcatW(buf
, testfilesW
[i
]);
4390 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, (LPITEMIDLIST
*)&pidl_array
[i
], NULL
);
4391 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4393 IShellFolder_Release(pdesktopsf
);
4395 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia_folders1
);
4396 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4397 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[1], &psia_folders2
);
4398 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4399 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[3], &psia_files
);
4400 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4401 hr
= pSHCreateShellItemArrayFromIDLists(4, &pidl_array
[1], &psia_all
); /* All except the first */
4402 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4404 for(i
= 0; i
< 5; i
++)
4405 pILFree((LPITEMIDLIST
)pidl_array
[i
]);
4407 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
4409 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4410 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4411 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4413 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4414 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4415 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4417 /* [testfolder/testfolder2, testfolder/testfolder3] works */
4419 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4420 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4421 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4423 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4424 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4425 ok(attr
== 0, "Got 0x%08x\n", attr
);
4427 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4428 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4429 ok(attr
== 0, "Got 0x%08x\n", attr
);
4431 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4432 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4433 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4435 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4436 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4437 ok(attr
== 0, "Got 0x%08x\n", attr
);
4439 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4440 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4441 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4443 IShellItemArray_Release(psia_folders1
);
4444 IShellItemArray_Release(psia_folders2
);
4445 IShellItemArray_Release(psia_files
);
4446 IShellItemArray_Release(psia_all
);
4448 RemoveDirectoryA(".\\testdir\\testdir3");
4452 static WCHAR
*get_empty_cddrive(void)
4454 static WCHAR cdrom_drive
[] = {'A',':','\\',0};
4455 DWORD drives
= GetLogicalDrives();
4457 cdrom_drive
[0] = 'A';
4461 GetDriveTypeW(cdrom_drive
) == DRIVE_CDROM
&&
4462 GetFileAttributesW(cdrom_drive
) == INVALID_FILE_ATTRIBUTES
)
4467 drives
= drives
>> 1;
4473 static void test_SHParseDisplayName(void)
4475 LPITEMIDLIST pidl1
, pidl2
;
4476 IShellFolder
*desktop
;
4477 WCHAR dirW
[MAX_PATH
];
4483 if (!pSHParseDisplayName
)
4485 win_skip("SHParseDisplayName isn't available\n");
4491 /* crashes on native */
4492 pSHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
4494 pSHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
4497 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
4498 hr
= pSHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
4499 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
4500 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
4501 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
4505 hr
= pSHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
4506 ok(hr
== S_OK
, "failed %08x\n", hr
);
4507 hr
= SHGetDesktopFolder(&desktop
);
4508 ok(hr
== S_OK
, "failed %08x\n", hr
);
4509 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
4510 ok(hr
== S_OK
, "failed %08x\n", hr
);
4511 ret
= pILIsEqual(pidl1
, pidl2
);
4512 ok(ret
== TRUE
, "expected equal idls\n");
4517 GetWindowsDirectoryW( dirW
, MAX_PATH
);
4519 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4520 ok(hr
== S_OK
, "failed %08x\n", hr
);
4521 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
4522 ok(hr
== S_OK
, "failed %08x\n", hr
);
4524 ret
= pILIsEqual(pidl1
, pidl2
);
4525 ok(ret
== TRUE
, "expected equal idls\n");
4529 /* system32 is not redirected to syswow64 on WOW64 */
4530 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
4531 if (is_wow64
&& pGetSystemWow64DirectoryW
)
4535 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
4536 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
4537 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4538 ok(hr
== S_OK
, "failed %08x\n", hr
);
4540 len
= pGetSystemWow64DirectoryW(dirW
, MAX_PATH
);
4541 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
4542 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
4543 ok(hr
== S_OK
, "failed %08x\n", hr
);
4544 ret
= pILIsEqual(pidl1
, pidl2
);
4545 ok(ret
== FALSE
, "expected different idls\n");
4550 IShellFolder_Release(desktop
);
4552 cdrom
= get_empty_cddrive();
4554 skip("No empty cdrom drive found, skipping test\n");
4557 hr
= pSHParseDisplayName(cdrom
, NULL
, &pidl1
, 0, NULL
);
4558 ok(hr
== S_OK
, "failed %08x\n", hr
);
4559 if (SUCCEEDED(hr
)) pILFree(pidl1
);
4563 static void test_desktop_IPersist(void)
4565 IShellFolder
*desktop
;
4567 IPersistFolder2
*ppf2
;
4571 hr
= SHGetDesktopFolder(&desktop
);
4572 ok(hr
== S_OK
, "failed %08x\n", hr
);
4574 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
4575 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* NT4, W9X */, "failed %08x\n", hr
);
4581 /* crashes on native */
4582 IPersist_GetClassID(persist
, NULL
);
4584 memset(&clsid
, 0, sizeof(clsid
));
4585 hr
= IPersist_GetClassID(persist
, &clsid
);
4586 ok(hr
== S_OK
, "failed %08x\n", hr
);
4587 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
4588 IPersist_Release(persist
);
4591 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
4592 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
4595 IPersistFolder
*ppf
;
4597 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
4598 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
4600 IPersistFolder_Release(ppf
);
4603 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
4604 ok(hr
== S_OK
, "got %08x\n", hr
);
4608 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
4609 ok(hr
== S_OK
, "got %08x\n", hr
);
4610 ok(pidl
!= NULL
, "pidl was NULL.\n");
4611 if(SUCCEEDED(hr
)) pILFree(pidl
);
4613 IPersistFolder2_Release(ppf2
);
4616 IShellFolder_Release(desktop
);
4619 static void test_GetUIObject(void)
4621 IShellFolder
*psf_desktop
;
4625 WCHAR path
[MAX_PATH
];
4626 const WCHAR filename
[] =
4627 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4629 if(!pSHBindToParent
)
4631 win_skip("SHBindToParent missing.\n");
4635 GetCurrentDirectoryW(MAX_PATH
, path
);
4638 skip("GetCurrentDirectoryW returned an empty string.\n");
4641 lstrcatW(path
, filename
);
4642 SHGetDesktopFolder(&psf_desktop
);
4644 CreateFilesFolders();
4646 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4647 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
4651 LPCITEMIDLIST pidl_child
;
4652 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
4653 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4656 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
,
4658 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4661 const int baseItem
= 0x40;
4662 HMENU hmenu
= CreatePopupMenu();
4663 INT max_id
, max_id_check
;
4665 const int id_upper_limit
= 32767;
4666 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, baseItem
, id_upper_limit
, CMF_NORMAL
);
4667 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
4668 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
4669 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
4670 count
= GetMenuItemCount(hmenu
);
4671 ok(count
, "Got %d\n", count
);
4674 for(i
= 0; i
< count
; i
++)
4678 char buf
[255], buf2
[255];
4679 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
4680 mii
.cbSize
= sizeof(MENUITEMINFOA
);
4681 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
| MIIM_STRING
;
4682 mii
.dwTypeData
= buf2
;
4683 mii
.cch
= sizeof(buf2
);
4686 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
4687 ok(res
, "Failed (last error: %d).\n", GetLastError());
4689 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
4690 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
4691 if(!(mii
.fType
& MFT_SEPARATOR
))
4693 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
4694 hr
= IContextMenu_GetCommandString(pcm
, mii
.wID
- baseItem
, GCS_VERBA
, 0, buf
, sizeof(buf
));
4695 ok(SUCCEEDED(hr
) || hr
== E_NOTIMPL
, "for id 0x%x got 0x%08x (menustr: %s)\n", mii
.wID
- baseItem
, hr
, mii
.dwTypeData
);
4697 trace("for id 0x%x got string %s (menu string: %s)\n", mii
.wID
- baseItem
, buf
, mii
.dwTypeData
);
4698 else if (hr
== E_NOTIMPL
)
4699 trace("for id 0x%x got E_NOTIMPL (menu string: %s)\n", mii
.wID
- baseItem
, mii
.dwTypeData
);
4702 max_id_check
-= baseItem
;
4703 ok((max_id_check
== max_id
) ||
4704 (max_id_check
== max_id
-1) || /* Win 7 */
4705 (max_id_check
== max_id
-2), /* Win 8 */
4706 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
4708 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
4710 if(count
&& !is_win2k()) /* Test is interactive on w2k, so skip */
4712 CMINVOKECOMMANDINFO cmi
;
4713 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
4714 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
4716 /* Attempt to execute a nonexistent command */
4717 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
4718 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4719 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4721 cmi
.lpVerb
= "foobar_wine_test";
4722 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4723 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
4724 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
4725 "Got 0x%08x\n", hr
);
4730 IContextMenu_Release(pcm
);
4732 IShellFolder_Release(psf
);
4734 if(pILFree
) pILFree(pidl
);
4737 IShellFolder_Release(psf_desktop
);
4741 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
4742 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
4744 LPCITEMIDLIST child
;
4745 IShellFolder
*parent
;
4749 if(!pSHBindToParent
){
4750 win_skip("SHBindToParent is not available, not performing full PIDL verification\n");
4752 ok_(__FILE__
,l
)(pidl
!= NULL
, "Expected PIDL to be non-NULL\n");
4754 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4760 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
4764 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&parent
, &child
);
4765 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4769 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4770 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4772 IShellFolder_Release(parent
);
4776 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4777 "Got unexpected string type: %d\n", filename
.uType
);
4778 if(filename
.uType
== STRRET_WSTR
){
4779 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4780 "didn't get expected path (%s), instead: %s\n",
4781 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4782 SHFree(U(filename
).pOleStr
);
4783 }else if(filename
.uType
== STRRET_CSTR
){
4784 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4785 "didn't get expected path (%s), instead: %s\n",
4786 wine_dbgstr_w(path
), U(filename
).cStr
);
4789 IShellFolder_Release(parent
);
4791 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4794 static void test_SHSimpleIDListFromPath(void)
4796 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4797 const CHAR adirA
[] = "C:\\sidlfpdir";
4798 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4800 LPITEMIDLIST pidl
= NULL
;
4802 if(!pSHSimpleIDListFromPathAW
){
4803 win_skip("SHSimpleIDListFromPathAW not available\n");
4807 br
= CreateDirectoryA(adirA
, NULL
);
4808 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4811 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4813 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4814 verify_pidl(pidl
, adirW
);
4817 br
= RemoveDirectoryA(adirA
);
4818 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4821 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4823 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4824 verify_pidl(pidl
, adirW
);
4828 /* IFileSystemBindData impl */
4829 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4830 REFIID riid
, void **ppv
)
4832 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4833 IsEqualIID(riid
, &IID_IUnknown
)){
4837 return E_NOINTERFACE
;
4840 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4845 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4850 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4851 const WIN32_FIND_DATAW
*pfd
)
4853 ok(0, "SetFindData called\n");
4857 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4858 WIN32_FIND_DATAW
*pfd
)
4860 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4864 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4865 WIN32_FIND_DATAW
*pfd
)
4867 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4871 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4872 WIN32_FIND_DATAW
*pfd
)
4874 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4875 *pfd
->cFileName
= 'a';
4876 *pfd
->cAlternateFileName
= 'a';
4880 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4881 WIN32_FIND_DATAW
*pfd
)
4883 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4884 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4889 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4890 WIN32_FIND_DATAW
*pfd
)
4895 static IFileSystemBindDataVtbl fsbdVtbl
= {
4896 fsbd_QueryInterface
,
4903 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4905 static void test_ParseDisplayNamePBC(void)
4907 WCHAR wFileSystemBindData
[] =
4908 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4909 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4910 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4911 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4912 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4919 /* Check if we support WCHAR functions */
4920 SetLastError(0xdeadbeef);
4921 lstrcmpiW(adirW
, adirW
);
4922 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4923 win_skip("Most W-calls are not implemented\n");
4927 hres
= SHGetDesktopFolder(&psf
);
4928 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4930 win_skip("Failed to get IShellFolder, can't run tests\n");
4934 /* fails on unknown dir with no IBindCtx */
4935 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4936 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4937 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4938 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4939 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4940 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4941 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4942 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4943 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4945 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4946 hres
= CreateBindCtx(0, &pbc
);
4947 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4949 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4950 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4951 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4952 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4953 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4954 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4955 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4956 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4957 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4959 /* unknown dir with IBindCtx with IFileSystemBindData */
4960 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4961 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4963 /* return E_FAIL from GetFindData */
4964 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4965 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4966 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4967 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4968 "ParseDisplayName failed: 0x%08x\n", hres
);
4969 if(SUCCEEDED(hres
)){
4970 verify_pidl(pidl
, adirW
);
4974 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4975 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4976 "ParseDisplayName failed: 0x%08x\n", hres
);
4977 if(SUCCEEDED(hres
)){
4978 verify_pidl(pidl
, afileW
);
4982 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4983 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4984 "ParseDisplayName failed: 0x%08x\n", hres
);
4985 if(SUCCEEDED(hres
)){
4986 verify_pidl(pidl
, afile2W
);
4990 /* set FIND_DATA struct to NULLs */
4991 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4992 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4993 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4994 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4995 "ParseDisplayName failed: 0x%08x\n", hres
);
4996 if(SUCCEEDED(hres
)){
4997 verify_pidl(pidl
, adirW
);
5001 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
5002 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5003 "ParseDisplayName failed: 0x%08x\n", hres
);
5004 if(SUCCEEDED(hres
)){
5005 verify_pidl(pidl
, afileW
);
5009 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
5010 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5011 "ParseDisplayName failed: 0x%08x\n", hres
);
5012 if(SUCCEEDED(hres
)){
5013 verify_pidl(pidl
, afile2W
);
5017 /* set FIND_DATA struct to junk */
5018 pidl
= (ITEMIDLIST
*)0xdeadbeef;
5019 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
5020 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
5021 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5022 "ParseDisplayName failed: 0x%08x\n", hres
);
5023 if(SUCCEEDED(hres
)){
5024 verify_pidl(pidl
, adirW
);
5028 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
5029 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5030 "ParseDisplayName failed: 0x%08x\n", hres
);
5031 if(SUCCEEDED(hres
)){
5032 verify_pidl(pidl
, afileW
);
5036 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
5037 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5038 "ParseDisplayName failed: 0x%08x\n", hres
);
5039 if(SUCCEEDED(hres
)){
5040 verify_pidl(pidl
, afile2W
);
5044 /* set FIND_DATA struct to invalid data */
5045 pidl
= (ITEMIDLIST
*)0xdeadbeef;
5046 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
5047 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
5048 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5049 "ParseDisplayName failed: 0x%08x\n", hres
);
5050 if(SUCCEEDED(hres
)){
5051 verify_pidl(pidl
, adirW
);
5055 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
5056 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5057 "ParseDisplayName failed: 0x%08x\n", hres
);
5058 if(SUCCEEDED(hres
)){
5059 verify_pidl(pidl
, afileW
);
5063 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
5064 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5065 "ParseDisplayName failed: 0x%08x\n", hres
);
5066 if(SUCCEEDED(hres
)){
5067 verify_pidl(pidl
, afile2W
);
5071 /* set FIND_DATA struct to valid data */
5072 pidl
= (ITEMIDLIST
*)0xdeadbeef;
5073 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
5074 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
5075 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5076 "ParseDisplayName failed: 0x%08x\n", hres
);
5077 if(SUCCEEDED(hres
)){
5078 verify_pidl(pidl
, adirW
);
5082 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
5083 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5084 "ParseDisplayName failed: 0x%08x\n", hres
);
5085 if(SUCCEEDED(hres
)){
5086 verify_pidl(pidl
, afileW
);
5090 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
5091 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
5092 "ParseDisplayName failed: 0x%08x\n", hres
);
5093 if(SUCCEEDED(hres
)){
5094 verify_pidl(pidl
, afile2W
);
5098 IBindCtx_Release(pbc
);
5099 IShellFolder_Release(psf
);
5102 static const CHAR testwindow_class
[] = "testwindow";
5103 #define WM_USER_NOTIFY (WM_APP+1)
5105 struct ChNotifyTest
{
5107 const UINT notify_count
;
5108 UINT missing_events
;
5110 const char path_1
[256];
5111 const char path_2
[256];
5112 } chnotify_tests
[] = {
5113 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
5114 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
5115 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
5118 struct ChNotifyTest
*exp_data
;
5119 BOOL test_new_delivery_flag
;
5121 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
5123 LONG signal
= (LONG
)lparam
;
5126 case WM_USER_NOTIFY
:
5127 if(exp_data
->missing_events
> 0) {
5128 WCHAR
*path1
, *path2
;
5129 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
5130 HANDLE hLock
= NULL
;
5132 if(test_new_delivery_flag
) {
5133 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
5134 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
5137 ok(exp_data
->signal
== signal
,
5138 "%s: expected notification type %x, got: %x\n",
5139 exp_data
->id
, exp_data
->signal
, signal
);
5141 trace("verifying pidls for: %s\n", exp_data
->id
);
5142 path1
= make_wstr(exp_data
->path_1
);
5143 path2
= make_wstr(exp_data
->path_2
);
5144 verify_pidl(pidls
[0], path1
);
5145 verify_pidl(pidls
[1], path2
);
5146 HeapFree(GetProcessHeap(), 0, path1
);
5147 HeapFree(GetProcessHeap(), 0, path2
);
5149 exp_data
->missing_events
--;
5151 if(test_new_delivery_flag
)
5152 SHChangeNotification_Unlock(hLock
);
5154 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
5157 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
5160 static void register_testwindow_class(void)
5165 ZeroMemory(&cls
, sizeof(cls
));
5166 cls
.cbSize
= sizeof(cls
);
5168 cls
.lpfnWndProc
= testwindow_wndproc
;
5169 cls
.hInstance
= GetModuleHandleA(NULL
);
5170 cls
.lpszClassName
= testwindow_class
;
5173 ret
= RegisterClassExA(&cls
);
5174 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
5177 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
5178 * have to poll repeatedly for the message to appear */
5179 static void do_events(void)
5182 while (exp_data
->missing_events
&& (c
++ < 10)){
5184 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
5185 TranslateMessage(&msg
);
5186 DispatchMessageA(&msg
);
5188 if(exp_data
->missing_events
)
5191 trace("%s: took %d tries\n", exp_data
->id
, c
);
5194 static void test_SHChangeNotify(BOOL test_new_delivery
)
5199 BOOL br
, has_unicode
;
5200 SHChangeNotifyEntry entries
[1];
5201 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
5202 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
5204 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
5206 CreateDirectoryW(NULL
, NULL
);
5207 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
5209 test_new_delivery_flag
= test_new_delivery
;
5210 if(!test_new_delivery
)
5211 register_testwindow_class();
5213 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
5214 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
5215 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
5216 ok(wnd
!= NULL
, "Failed to make a window\n");
5218 br
= CreateDirectoryA(root_dirA
, NULL
);
5219 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
5221 entries
[0].pidl
= NULL
;
5223 hr
= pSHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
5225 hr
= pSHILCreateFromPath((LPCVOID
)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
5226 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
5227 entries
[0].fRecursive
= TRUE
;
5229 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
5230 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
5231 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
5233 for(i
= 0; i
< sizeof(chnotify_tests
) / sizeof(*chnotify_tests
); ++i
){
5234 exp_data
= chnotify_tests
+ i
;
5236 exp_data
->missing_events
= exp_data
->notify_count
;
5237 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
5238 exp_data
->path_1
[0] ? exp_data
->path_1
: NULL
,
5239 exp_data
->path_2
[0] ? exp_data
->path_2
: NULL
);
5241 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
5244 WCHAR
*path1
, *path2
;
5246 path1
= make_wstr(exp_data
->path_1
);
5247 path2
= make_wstr(exp_data
->path_2
);
5249 exp_data
->missing_events
= exp_data
->notify_count
;
5250 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
5252 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
5254 HeapFree(GetProcessHeap(), 0, path1
);
5255 HeapFree(GetProcessHeap(), 0, path2
);
5259 SHChangeNotifyDeregister(notifyID
);
5262 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
5263 br
= RemoveDirectoryA(root_dirA
);
5264 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
5267 static void test_SHCreateDefaultContextMenu(void)
5270 WCHAR path
[MAX_PATH
];
5271 IShellFolder
*desktop
,*folder
;
5272 IPersistFolder2
*persist
;
5273 IContextMenu
*cmenu
;
5275 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
5276 DEFCONTEXTMENU cminfo
;
5279 const WCHAR filename
[] =
5280 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
5281 if(!pSHCreateDefaultContextMenu
)
5283 win_skip("SHCreateDefaultContextMenu missing.\n");
5287 if(!pSHBindToParent
)
5289 skip("SHBindToParent missing.\n");
5293 GetCurrentDirectoryW(MAX_PATH
, path
);
5296 skip("GetCurrentDirectoryW returned an empty string.\n");
5299 lstrcatW(path
, filename
);
5300 SHGetDesktopFolder(&desktop
);
5302 CreateFilesFolders();
5304 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
5305 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
5309 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&folder
, (LPCITEMIDLIST
*)&pidl_child
);
5310 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5312 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
5313 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
5314 IPersistFolder2_Release(persist
);
5321 cminfo
.pidlFolder
=NULL
;
5322 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
5326 cminfo
.punkAssociationInfo
=NULL
;
5327 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5328 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5329 IContextMenu_Release(cmenu
);
5330 cminfo
.pidlFolder
=pidlFolder
;
5331 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5332 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5333 IContextMenu_Release(cmenu
);
5334 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
5335 if(status
==ERROR_SUCCESS
){
5340 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5341 RegCloseKey(keys
[0]);
5342 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5343 IContextMenu_Release(cmenu
);
5347 IShellFolder_Release(folder
);
5349 IShellFolder_Release(desktop
);
5354 static void test_DataObject(void)
5356 IShellFolder
*desktop
;
5357 IDataObject
*data_obj
;
5362 DWORD cf_shellidlist
;
5365 SHGetDesktopFolder(&desktop
);
5367 hres
= IShellFolder_EnumObjects(desktop
, NULL
,
5368 SHCONTF_NONFOLDERS
|SHCONTF_FOLDERS
|SHCONTF_INCLUDEHIDDEN
, &peidl
);
5369 ok(hres
== S_OK
, "got %x\n", hres
);
5371 if(IEnumIDList_Next(peidl
, 1, &apidl
, NULL
) != S_OK
) {
5372 skip("no files on desktop - skipping GetDataObject tests\n");
5373 IEnumIDList_Release(peidl
);
5374 IShellFolder_Release(desktop
);
5377 IEnumIDList_Release(peidl
);
5379 hres
= IShellFolder_GetUIObjectOf(desktop
, NULL
, 1, (LPCITEMIDLIST
*)&apidl
,
5380 &IID_IDataObject
, NULL
, (void**)&data_obj
);
5381 ok(hres
== S_OK
, "got %x\n", hres
);
5383 IShellFolder_Release(desktop
);
5385 cf_shellidlist
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
5386 fmt
.cfFormat
= cf_shellidlist
;
5388 fmt
.dwAspect
= DVASPECT_CONTENT
;
5390 fmt
.tymed
= TYMED_HGLOBAL
;
5391 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5392 ok(hres
== S_OK
, "got %x\n", hres
);
5394 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5395 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5396 ok(hres
== S_OK
, "got %x\n", hres
);
5398 fmt
.tymed
= TYMED_ISTREAM
;
5399 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5400 todo_wine
ok(hres
== S_FALSE
, "got %x\n", hres
);
5402 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5403 hres
= IDataObject_GetData(data_obj
, &fmt
, &medium
);
5404 ok(hres
== S_OK
, "got %x\n", hres
);
5405 ok(medium
.tymed
== TYMED_HGLOBAL
, "medium.tymed = %x\n", medium
.tymed
);
5406 ReleaseStgMedium(&medium
);
5408 IDataObject_Release(data_obj
);
5411 START_TEST(shlfolder
)
5413 init_function_pointers();
5414 /* if OleInitialize doesn't get called, ParseDisplayName returns
5415 CO_E_NOTINITIALIZED for malformed directory names on win2k. */
5416 OleInitialize(NULL
);
5418 test_ParseDisplayName();
5419 test_SHParseDisplayName();
5420 test_BindToObject();
5421 test_EnumObjects_and_CompareIDs();
5422 test_GetDisplayName();
5423 test_GetAttributesOf();
5424 test_SHGetPathFromIDList();
5425 test_CallForAttributes();
5426 test_FolderShortcut();
5427 test_ITEMIDLIST_format();
5428 test_SHGetFolderPathA();
5429 test_SHGetFolderPathAndSubDirA();
5430 test_LocalizedNames();
5431 test_SHCreateShellItem();
5432 test_SHCreateShellItemArray();
5433 test_ShellItemArrayEnumItems();
5434 test_desktop_IPersist();
5436 test_SHSimpleIDListFromPath();
5437 test_ParseDisplayNamePBC();
5438 test_SHGetNameFromIDList();
5439 test_SHGetItemFromDataObject();
5440 test_SHGetIDListFromObject();
5441 test_SHGetItemFromObject();
5442 test_ShellItemCompare();
5443 test_SHChangeNotify(FALSE
);
5444 test_SHChangeNotify(TRUE
);
5445 test_ShellItemBindToHandler();
5446 test_ShellItemGetAttributes();
5447 test_ShellItemArrayGetAttributes();
5448 test_SHCreateDefaultContextMenu();