2 * Unit test of the IShellFolder functions.
4 * Copyright 2004 Vitaliy Margolen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
40 #include "wine/test.h"
43 DEFINE_GUID(IID_IParentAndItem
, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
44 DEFINE_GUID(CLSID_ShellDocObjView
, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
48 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
49 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
50 static HRESULT (WINAPI
*pSHCreateItemFromRelativeName
)(IShellItem
*,PCWSTR
,IBindCtx
*,REFIID
,void**);
51 static HRESULT (WINAPI
*pSHCreateItemInKnownFolder
)(REFKNOWNFOLDERID
,DWORD
,PCWSTR
,REFIID
,void **);
52 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
53 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
54 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromIDLists
)(UINT
, PCIDLIST_ABSOLUTE
*, IShellItemArray
**);
55 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
56 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
57 static HRESULT (WINAPI
*pSHGetKnownFolderPath
)(REFKNOWNFOLDERID
,DWORD
,HANDLE
,PWSTR
*);
58 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
59 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
60 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
61 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
62 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
63 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
64 static BOOL (WINAPI
*pSHGetPathFromIDListEx
)(PCIDLIST_ABSOLUTE
,WCHAR
*,DWORD
,GPFIDL_FLAGS
);
66 static WCHAR
*make_wstr(const char *str
)
74 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
78 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
82 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
86 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
89 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
90 return lstrcmpA(stra
, buf
);
93 static void init_function_pointers(void)
99 hmod
= GetModuleHandleA("shell32.dll");
101 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
102 MAKEFUNC(SHCreateItemFromIDList
);
103 MAKEFUNC(SHCreateItemFromParsingName
);
104 MAKEFUNC(SHCreateItemFromRelativeName
);
105 MAKEFUNC(SHCreateItemInKnownFolder
);
106 MAKEFUNC(SHCreateShellItem
);
107 MAKEFUNC(SHCreateShellItemArray
);
108 MAKEFUNC(SHCreateShellItemArrayFromIDLists
);
109 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
110 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
111 MAKEFUNC(SHGetKnownFolderPath
);
112 MAKEFUNC(SHGetNameFromIDList
);
113 MAKEFUNC(SHGetItemFromDataObject
);
114 MAKEFUNC(SHGetIDListFromObject
);
115 MAKEFUNC(SHGetItemFromObject
);
116 MAKEFUNC(SHCreateDefaultContextMenu
);
117 MAKEFUNC(SHGetPathFromIDListEx
);
120 /* test named exports */
121 ptr
= GetProcAddress(hmod
, "ILFree");
122 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
125 #define TESTNAMED(f) \
126 ptr = (void*)GetProcAddress(hmod, #f); \
127 ok(ptr != 0, "expected named export for " #f "\n");
129 TESTNAMED(ILAppendID
);
131 TESTNAMED(ILCloneFirst
);
132 TESTNAMED(ILCombine
);
133 TESTNAMED(ILCreateFromPath
);
134 TESTNAMED(ILCreateFromPathA
);
135 TESTNAMED(ILCreateFromPathW
);
136 TESTNAMED(ILFindChild
);
137 TESTNAMED(ILFindLastID
);
138 TESTNAMED(ILGetNext
);
139 TESTNAMED(ILGetSize
);
140 TESTNAMED(ILIsEqual
);
141 TESTNAMED(ILIsParent
);
142 TESTNAMED(ILRemoveLastID
);
143 TESTNAMED(ILSaveToStream
);
147 hmod
= GetModuleHandleA("kernel32.dll");
148 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
150 hr
= SHGetMalloc(&ppM
);
151 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
154 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
155 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
159 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
165 if (lpszPath
[-1] != '\\')
174 static void test_ParseDisplayName(void)
177 IShellFolder
*IDesktopFolder
;
178 static const char *cNonExistDir1A
= "c:\\nonexist_subdir";
179 static const char *cNonExistDir2A
= "c:\\\\nonexist_subdir";
180 static const char *cInetTestA
= "http:\\yyy";
181 static const char *cInetTest2A
= "xx:yyy";
183 WCHAR cTestDirW
[MAX_PATH
] = {0};
187 hr
= SHGetDesktopFolder(&IDesktopFolder
);
188 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
189 if(hr
!= S_OK
) return;
191 if (pSHCreateShellItem
)
195 /* null name and pidl, crashes on Windows 8 */
196 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
,
197 NULL
, NULL
, NULL
, 0);
198 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
202 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
203 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
204 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
205 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
206 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
209 win_skip("SHCreateShellItem requires XP SP1 or later\n");
211 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
212 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
213 todo_wine
ok(hr
== S_OK
, "ParseDisplayName returned %08x, expected SUCCESS\n", hr
);
216 ok(ILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
217 "PT_IESPECIAL1, but is: %02x\n", ILFindLastID(newPIDL
)->mkid
.abID
[0]);
218 IMalloc_Free(ppM
, newPIDL
);
221 MultiByteToWideChar(CP_ACP
, 0, cInetTest2A
, -1, cTestDirW
, MAX_PATH
);
222 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
223 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
224 todo_wine
ok(hr
== S_OK
, "ParseDisplayName returned %08x, expected SUCCESS\n", hr
);
227 ok(ILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
228 "PT_IESPECIAL1, but is: %02x\n", ILFindLastID(newPIDL
)->mkid
.abID
[0]);
229 IMalloc_Free(ppM
, newPIDL
);
232 res
= GetFileAttributesA(cNonExistDir1A
);
233 if(res
!= INVALID_FILE_ATTRIBUTES
)
235 skip("Test directory unexpectedly exists\n");
239 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
240 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
241 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
242 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
243 "ParseDisplayName returned %08x, expected 0x80070002\n", hr
);
245 res
= GetFileAttributesA(cNonExistDir2A
);
246 if(res
!= INVALID_FILE_ATTRIBUTES
)
248 skip("Test directory unexpectedly exists\n");
252 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
253 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
254 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
255 todo_wine
ok(hr
== E_INVALIDARG
, "ParseDisplayName returned %08x, expected E_INVALIDARG\n", hr
);
257 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
258 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
259 * out it doesn't. The magic seems to happen in the file dialogs, then. */
261 bRes
= SHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
262 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
263 if (!bRes
) goto finished
;
265 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
266 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
267 if (hr
!= S_OK
) goto finished
;
269 ok(ILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31,
270 "Last pidl should be of type PT_FOLDER, but is: %02x\n",
271 ILFindLastID(newPIDL
)->mkid
.abID
[0]);
272 IMalloc_Free(ppM
, newPIDL
);
275 IShellFolder_Release(IDesktopFolder
);
278 /* creates a file with the specified name for tests */
279 static void CreateTestFile(const CHAR
*name
)
284 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
285 if (file
!= INVALID_HANDLE_VALUE
)
287 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
288 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
294 /* initializes the tests */
295 static void CreateFilesFolders(void)
297 CreateDirectoryA(".\\testdir", NULL
);
298 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
299 CreateTestFile (".\\testdir\\test1.txt ");
300 CreateTestFile (".\\testdir\\test2.txt ");
301 CreateTestFile (".\\testdir\\test3.txt ");
302 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
303 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
306 /* cleans after tests */
307 static void Cleanup(void)
309 DeleteFileA(".\\testdir\\test1.txt");
310 DeleteFileA(".\\testdir\\test2.txt");
311 DeleteFileA(".\\testdir\\test3.txt");
312 RemoveDirectoryA(".\\testdir\\test.txt");
313 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
314 RemoveDirectoryA(".\\testdir\\testdir2");
315 RemoveDirectoryA(".\\testdir");
320 static void test_EnumObjects(IShellFolder
*iFolder
)
322 IEnumIDList
*iEnumList
;
323 LPITEMIDLIST newPIDL
, idlArr
[10];
328 static const WORD iResults
[5][5] =
337 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
338 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
339 static const ULONG attrs
[5] =
341 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
342 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
343 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
344 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
345 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
347 static const ULONG full_attrs
[5] =
349 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
350 SFGAO_CAPABILITYMASK
| SFGAO_STORAGE
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
351 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
352 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
353 SFGAO_CAPABILITYMASK
| SFGAO_STREAM
| SFGAO_FILESYSTEM
,
356 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
357 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
359 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
360 * the filesystem shellfolders return S_OK even if less than 'celt' items are
361 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
362 * only ever returns a single entry per call. */
363 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
365 ok (i
== 5, "i: %d\n", i
);
367 hr
= IEnumIDList_Release(iEnumList
);
368 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
370 /* Sort them first in case of wrong order from system */
371 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
372 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
375 idlArr
[i
] = idlArr
[j
];
379 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
381 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
382 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
386 for (i
= 0; i
< 5; i
++)
389 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
390 /* Native returns all flags no matter what we ask for */
391 flags
= SFGAO_CANCOPY
;
392 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
393 flags
&= SFGAO_testfor
;
394 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
395 ok(flags
== (attrs
[i
]) ||
396 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
397 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
399 flags
= SFGAO_testfor
;
400 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
401 flags
&= SFGAO_testfor
;
402 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
403 ok(flags
== attrs
[i
], "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
406 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
407 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
408 ok((flags
& ~(SFGAO_HASSUBFOLDER
|SFGAO_COMPRESSED
)) == full_attrs
[i
], "%d: got %08x expected %08x\n", i
, flags
, full_attrs
[i
]);
412 IMalloc_Free(ppM
, idlArr
[i
]);
415 static void test_BindToObject(void)
419 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
420 SHITEMID emptyitem
= { 0, { 0 } };
421 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
422 WCHAR wszSystemDir
[MAX_PATH
];
423 char szSystemDir
[MAX_PATH
];
425 WCHAR path
[MAX_PATH
];
426 CHAR pathA
[MAX_PATH
];
428 WCHAR wszMyComputer
[] = {
429 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
430 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
431 static const CHAR filename_html
[] = "winetest.html";
432 static const CHAR filename_txt
[] = "winetest.txt";
433 static const CHAR filename_foo
[] = "winetest.foo";
435 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
436 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
438 hr
= SHGetDesktopFolder(&psfDesktop
);
439 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
440 if (hr
!= S_OK
) return;
442 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
443 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
445 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
446 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
448 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
449 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
451 IShellFolder_Release(psfDesktop
);
455 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
456 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
457 IShellFolder_Release(psfDesktop
);
458 IMalloc_Free(ppM
, pidlMyComputer
);
459 if (hr
!= S_OK
) return;
461 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
462 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
464 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
465 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
467 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
468 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
469 if (cChars
== 0 || cChars
>= MAX_PATH
) {
470 IShellFolder_Release(psfMyComputer
);
473 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
475 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
476 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
478 IShellFolder_Release(psfMyComputer
);
482 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
483 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
484 IShellFolder_Release(psfMyComputer
);
485 IMalloc_Free(ppM
, pidlSystemDir
);
486 if (hr
!= S_OK
) return;
488 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
489 ok (hr
== E_INVALIDARG
,
490 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
492 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
493 ok (hr
== E_INVALIDARG
,
494 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
496 IShellFolder_Release(psfSystemDir
);
498 cChars
= GetCurrentDirectoryA(MAX_PATH
, buf
);
501 skip("Failed to get current directory, skipping tests.\n");
504 if(buf
[cChars
-1] != '\\') lstrcatA(buf
, "\\");
506 SHGetDesktopFolder(&psfDesktop
);
508 /* Attempt BindToObject on files. */
511 lstrcpyA(pathA
, buf
);
512 lstrcatA(pathA
, filename_html
);
513 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
514 if(hfile
!= INVALID_HANDLE_VALUE
)
517 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
518 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
519 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
522 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
524 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
529 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
530 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
534 hr
= IPersist_GetClassID(pp
, &id
);
535 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
536 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
), "Unexpected classid %s\n", wine_dbgstr_guid(&id
));
537 IPersist_Release(pp
);
540 IShellFolder_Release(psfChild
);
547 win_skip("Failed to create .html testfile.\n");
550 lstrcpyA(pathA
, buf
);
551 lstrcatA(pathA
, filename_txt
);
552 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
553 if(hfile
!= INVALID_HANDLE_VALUE
)
556 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
557 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
558 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
561 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
562 ok(hr
== E_FAIL
|| /* Vista+ */
563 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
565 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
571 win_skip("Failed to create .txt testfile.\n");
574 lstrcpyA(pathA
, buf
);
575 lstrcatA(pathA
, filename_foo
);
576 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
577 if(hfile
!= INVALID_HANDLE_VALUE
)
580 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
581 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
582 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
585 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
586 ok(hr
== E_FAIL
|| /* Vista+ */
587 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
589 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
595 win_skip("Failed to create .foo testfile.\n");
597 /* And on the desktop */
598 SHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
599 lstrcatA(pathA
, "\\");
600 lstrcatA(pathA
, filename_html
);
601 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
604 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
605 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
606 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
608 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void **)&psfChild
);
610 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
612 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
614 if(!DeleteFileA(pathA
))
615 trace("Failed to delete: %d\n", GetLastError());
617 SHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
618 lstrcatA(pathA
, "\\");
619 lstrcatA(pathA
, filename_foo
);
620 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
623 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
624 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
625 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
627 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void **)&psfChild
);
628 ok(hr
== E_FAIL
|| /* Vista+ */
629 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
631 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
635 IShellFolder_Release(psfDesktop
);
638 static void test_GetDisplayName(void)
643 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
644 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
647 LPSHELLFOLDER psfDesktop
, psfPersonal
;
649 SHITEMID emptyitem
= { 0, { 0 } };
650 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
651 LPCITEMIDLIST pidlLast
;
652 static const CHAR szFileName
[] = "winetest.foo";
653 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
654 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
656 /* It's ok to use this fixed path. Call will fail anyway. */
657 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
658 LPITEMIDLIST pidlNew
;
660 /* I'm trying to figure if there is a functional difference between calling
661 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
662 * binding to the shellfolder. One thing I thought of was that perhaps
663 * SHGetPathFromIDListW would be able to get the path to a file, which does
664 * not exist anymore, while the other method wouldn't. It turns out there's
665 * no functional difference in this respect.
668 /* First creating a directory in MyDocuments and a file in this directory. */
669 result
= SHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
670 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
673 /* Use ANSI file functions so this works on Windows 9x */
674 lstrcatA(szTestDir
, "\\winetest");
675 CreateDirectoryA(szTestDir
, NULL
);
676 attr
=GetFileAttributesA(szTestDir
);
677 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
679 ok(0, "unable to create the '%s' directory\n", szTestDir
);
683 lstrcpyA(szTestFile
, szTestDir
);
684 lstrcatA(szTestFile
, "\\");
685 lstrcatA(szTestFile
, szFileName
);
686 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
687 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
688 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
689 CloseHandle(hTestFile
);
691 /* Getting an itemidlist for the file. */
692 hr
= SHGetDesktopFolder(&psfDesktop
);
693 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
694 if (hr
!= S_OK
) return;
696 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
698 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
699 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
701 IShellFolder_Release(psfDesktop
);
705 pidlLast
= ILFindLastID(pidlTestFile
);
706 ok(pidlLast
->mkid
.cb
>= 76, "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
707 if (pidlLast
->mkid
.cb
>= 28) {
708 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
709 "Filename should be stored as ansi-string at this position!\n");
711 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
712 if (pidlLast
->mkid
.cb
>= 76) {
713 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
714 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
715 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)) || /* Win7 */
716 (pidlLast
->mkid
.cb
>= 102 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[72], wszFileName
)), /* Win8 */
717 "Filename should be stored as wchar-string at this position!\n");
720 /* It seems as if we cannot bind to regular files on windows, but only directories.
722 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
723 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
724 hr
== E_NOTIMPL
, /* Vista */
727 IUnknown_Release(psfFile
);
730 /* Some tests for IShellFolder::SetNameOf */
731 hr
= SHBindToParent(pidlTestFile
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
732 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
734 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
735 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
736 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
738 ok (((ITEMIDLIST
*)((BYTE
*)pidlNew
+ pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
739 "pidl returned from SetNameOf should be simple!\n");
741 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
742 * is implemented on top of SHFileOperation in WinXP. */
743 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
, SHGDN_FORPARSING
, NULL
);
744 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
746 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
747 * SHGDN flags specify an absolute path. */
748 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
749 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
752 IShellFolder_Release(psfPersonal
);
754 /* Deleting the file and the directory */
755 DeleteFileA(szTestFile
);
756 RemoveDirectoryA(szTestDir
);
758 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
759 result
= SHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
760 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
761 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
763 /* SHBindToParent fails, if called with a NULL PIDL. */
764 hr
= SHBindToParent(NULL
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
765 ok (hr
== E_INVALIDARG
|| broken(hr
== E_OUTOFMEMORY
) /* XP */,
766 "SHBindToParent(NULL) should fail! hr = %08x\n", hr
);
768 /* But it succeeds with an empty PIDL. */
769 hr
= SHBindToParent(pidlEmpty
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
770 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
771 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
773 IShellFolder_Release(psfPersonal
);
775 /* Binding to the folder and querying the display name of the file also works. */
776 hr
= SHBindToParent(pidlTestFile
, &IID_IShellFolder
, (void **)&psfPersonal
, &pidlLast
);
777 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
779 IShellFolder_Release(psfDesktop
);
783 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
784 * pidlTestFile (In accordance with MSDN). */
785 ok (ILFindLastID(pidlTestFile
) == pidlLast
,
786 "SHBindToParent doesn't return the last id of the pidl param!\n");
788 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
789 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
791 IShellFolder_Release(psfDesktop
);
792 IShellFolder_Release(psfPersonal
);
796 hr
= StrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
797 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
798 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
800 ILFree(pidlTestFile
);
801 IShellFolder_Release(psfDesktop
);
802 IShellFolder_Release(psfPersonal
);
805 static void test_CallForAttributes(void)
811 LPSHELLFOLDER psfDesktop
;
812 LPITEMIDLIST pidlMyDocuments
;
813 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
814 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
815 static const WCHAR wszCallForAttributes
[] = {
816 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
817 static const WCHAR wszMyDocumentsKey
[] = {
818 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
819 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
820 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
821 WCHAR wszMyDocuments
[] = {
822 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
823 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
825 /* For the root of a namespace extension, the attributes are not queried by binding
826 * to the object and calling GetAttributesOf. Instead, the attributes are read from
827 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
829 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
830 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
831 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
832 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
834 hr
= SHGetDesktopFolder(&psfDesktop
);
835 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
836 if (hr
!= S_OK
) return;
838 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
839 &pidlMyDocuments
, NULL
);
841 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
843 IShellFolder_Release(psfDesktop
);
847 dwAttributes
= 0xffffffff;
848 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
849 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
850 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
852 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
853 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
854 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
855 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
857 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
858 * key. So the test will return at this point, if run on wine.
860 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
861 ok (lResult
== ERROR_SUCCESS
||
862 lResult
== ERROR_ACCESS_DENIED
,
863 "RegOpenKeyEx failed! result: %08x\n", lResult
);
864 if (lResult
!= ERROR_SUCCESS
) {
865 if (lResult
== ERROR_ACCESS_DENIED
)
866 skip("Not enough rights to open the registry key\n");
867 IMalloc_Free(ppM
, pidlMyDocuments
);
868 IShellFolder_Release(psfDesktop
);
872 /* Query MyDocuments' Attributes value, to be able to restore it later. */
873 dwSize
= sizeof(DWORD
);
874 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
875 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
876 if (lResult
!= ERROR_SUCCESS
) {
878 IMalloc_Free(ppM
, pidlMyDocuments
);
879 IShellFolder_Release(psfDesktop
);
883 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
884 dwSize
= sizeof(DWORD
);
885 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
886 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
887 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
888 if (lResult
!= ERROR_SUCCESS
) {
890 IMalloc_Free(ppM
, pidlMyDocuments
);
891 IShellFolder_Release(psfDesktop
);
895 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
896 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
897 * SFGAO_FILESYSTEM attributes. */
898 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
899 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
900 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
901 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
902 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
904 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
905 * GetAttributesOf. It seems that once there is a single attribute queried, for which
906 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
907 * the flags in Attributes are ignored.
909 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
910 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
911 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
912 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
914 ok (dwAttributes
== SFGAO_FILESYSTEM
,
915 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
918 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
919 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
920 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
921 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
923 IMalloc_Free(ppM
, pidlMyDocuments
);
924 IShellFolder_Release(psfDesktop
);
927 static void test_GetAttributesOf(void)
930 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
931 SHITEMID emptyitem
= { 0, { 0 } };
932 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
933 LPITEMIDLIST pidlMyComputer
;
935 static const DWORD desktopFlags
= SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
|
936 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
;
937 static const DWORD myComputerFlags
= SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
|
938 SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
939 WCHAR wszMyComputer
[] = {
940 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
941 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
942 char cCurrDirA
[MAX_PATH
] = {0};
943 WCHAR cCurrDirW
[MAX_PATH
];
944 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
945 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
949 hr
= SHGetDesktopFolder(&psfDesktop
);
950 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
951 if (hr
!= S_OK
) return;
953 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
954 dwFlags
= 0xffffffff;
955 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
956 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
957 ok (dwFlags
== desktopFlags
, "Wrong Desktop attributes: %08x\n", dwFlags
);
959 /* .. or with no itemidlist at all. */
960 dwFlags
= 0xffffffff;
961 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
962 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
963 ok (dwFlags
== desktopFlags
, "Wrong Desktop attributes: %08x\n", dwFlags
);
965 /* Testing the attributes of the MyComputer shellfolder */
966 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
967 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
969 IShellFolder_Release(psfDesktop
);
973 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
974 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
976 dwFlags
= 0xffffffff;
977 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
978 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
980 ok (dwFlags
== (myComputerFlags
| SFGAO_CANLINK
), "Wrong MyComputer attributes: %08x\n", dwFlags
);
982 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
983 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
984 IShellFolder_Release(psfDesktop
);
985 IMalloc_Free(ppM
, pidlMyComputer
);
986 if (hr
!= S_OK
) return;
988 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
990 ok (hr
== E_INVALIDARG
, "MyComputer->GetAttributesOf(empty pidl) should fail! hr = %08x\n", hr
);
992 dwFlags
= 0xffffffff;
993 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
994 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
996 ok (dwFlags
== myComputerFlags
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
998 IShellFolder_Release(psfMyComputer
);
1000 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1001 len
= lstrlenA(cCurrDirA
);
1004 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1007 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1008 cCurrDirA
[len
-1] = 0;
1010 /* create test directory */
1011 CreateFilesFolders();
1013 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1015 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1016 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1018 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1019 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1021 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1022 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1024 IMalloc_Free(ppM
, newPIDL
);
1026 /* get relative PIDL */
1027 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1028 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1030 /* test the shell attributes of the test directory using the relative PIDL */
1031 dwFlags
= SFGAO_FOLDER
;
1032 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1033 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1034 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1037 IMalloc_Free(ppM
, newPIDL
);
1039 /* append testdirectory name to path */
1040 if (cCurrDirA
[len
-1] == '\\')
1041 cCurrDirA
[len
-1] = 0;
1042 lstrcatA(cCurrDirA
, "\\testdir");
1043 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1045 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1046 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1048 /* test the shell attributes of the test directory using the absolute PIDL */
1049 dwFlags
= SFGAO_FOLDER
;
1050 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1051 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1052 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1055 IMalloc_Free(ppM
, newPIDL
);
1057 IShellFolder_Release(testIShellFolder
);
1061 IShellFolder_Release(IDesktopFolder
);
1064 static void test_SHGetPathFromIDList(void)
1066 SHITEMID emptyitem
= { 0, { 0 } };
1067 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1068 LPITEMIDLIST pidlMyComputer
;
1069 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1072 LPSHELLFOLDER psfDesktop
;
1073 WCHAR wszMyComputer
[] = {
1074 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1075 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1076 WCHAR wszFileName
[MAX_PATH
];
1077 LPITEMIDLIST pidlTestFile
;
1080 static WCHAR wszTestFile
[] = {
1081 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1082 LPITEMIDLIST pidlPrograms
;
1084 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1087 result
= SHGetPathFromIDListW(NULL
, wszPath
);
1088 ok(!result
, "Expected failure\n");
1089 ok(!wszPath
[0], "Expected empty string\n");
1091 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1092 result
= SHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1093 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1094 if (!result
) return;
1096 result
= SHGetPathFromIDListW(pidlEmpty
, wszPath
);
1097 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1098 if (!result
) return;
1099 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1101 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1102 hr
= SHGetDesktopFolder(&psfDesktop
);
1103 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1104 if (hr
!= S_OK
) return;
1106 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1107 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1109 IShellFolder_Release(psfDesktop
);
1113 SetLastError(0xdeadbeef);
1116 result
= SHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1117 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1118 ok (GetLastError()==0xdeadbeef ||
1119 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1120 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1121 ok (!wszPath
[0], "Expected empty path\n");
1123 IShellFolder_Release(psfDesktop
);
1127 IMalloc_Free(ppM
, pidlMyComputer
);
1129 result
= SHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1130 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1132 IShellFolder_Release(psfDesktop
);
1135 myPathAddBackslashW(wszFileName
);
1136 lstrcatW(wszFileName
, wszTestFile
);
1137 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1138 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1139 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1140 IShellFolder_Release(psfDesktop
);
1143 CloseHandle(hTestFile
);
1145 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1146 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1148 IShellFolder_Release(psfDesktop
);
1149 DeleteFileW(wszFileName
);
1150 IMalloc_Free(ppM
, pidlTestFile
);
1154 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1155 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1156 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1157 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1158 IShellFolder_Release(psfDesktop
);
1159 DeleteFileW(wszFileName
);
1161 IMalloc_Free(ppM
, pidlTestFile
);
1164 StrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1165 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1166 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1167 "returned incorrect path for file placed on desktop\n");
1169 result
= SHGetPathFromIDListW(pidlTestFile
, wszPath
);
1170 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1171 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1173 if (pSHGetPathFromIDListEx
)
1175 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1176 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1177 ok(!lstrcmpiW(wszDesktop
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1178 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszDesktop
));
1180 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, MAX_PATH
, SFGAO_FILESYSTEM
);
1181 ok(result
, "SHGetPathFromIDListEx failed: %u\n", GetLastError());
1182 ok(!lstrcmpiW(wszFileName
, wszPath
), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n",
1183 wine_dbgstr_w(wszPath
), wine_dbgstr_w(wszFileName
));
1185 SetLastError(0xdeadbeef);
1186 memset(wszPath
, 0x55, sizeof(wszPath
));
1187 result
= pSHGetPathFromIDListEx(pidlTestFile
, wszPath
, 5, SFGAO_FILESYSTEM
);
1188 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1190 SetLastError(0xdeadbeef);
1191 memset(wszPath
, 0x55, sizeof(wszPath
));
1192 result
= pSHGetPathFromIDListEx(pidlEmpty
, wszPath
, 5, SFGAO_FILESYSTEM
);
1193 ok(!result
, "SHGetPathFromIDListEx returned: %x(%u)\n", result
, GetLastError());
1196 win_skip("SHGetPathFromIDListEx not available\n");
1198 IMalloc_Free(ppM
, pidlTestFile
);
1200 /* Test if we can get the path from the start menu "program files" PIDL. */
1201 hr
= SHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1202 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1204 SetLastError(0xdeadbeef);
1205 result
= SHGetPathFromIDListW(pidlPrograms
, wszPath
);
1206 IMalloc_Free(ppM
, pidlPrograms
);
1207 ok(result
, "SHGetPathFromIDListW failed\n");
1210 static void test_EnumObjects_and_CompareIDs(void)
1212 ITEMIDLIST
*newPIDL
;
1213 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1214 char cCurrDirA
[MAX_PATH
] = {0};
1215 static const CHAR cTestDirA
[] = "\\testdir";
1216 WCHAR cTestDirW
[MAX_PATH
];
1220 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1221 len
= lstrlenA(cCurrDirA
);
1224 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1227 if(cCurrDirA
[len
-1] == '\\')
1228 cCurrDirA
[len
-1] = 0;
1230 lstrcatA(cCurrDirA
, cTestDirA
);
1231 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1233 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1234 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1236 CreateFilesFolders();
1238 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1239 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1241 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1242 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1244 test_EnumObjects(testIShellFolder
);
1246 IShellFolder_Release(testIShellFolder
);
1250 IMalloc_Free(ppM
, newPIDL
);
1252 IShellFolder_Release(IDesktopFolder
);
1255 /* A simple implementation of an IPropertyBag, which returns fixed values for
1256 * 'Target' and 'Attributes' properties.
1258 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1262 return E_INVALIDARG
;
1264 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1267 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1268 return E_NOINTERFACE
;
1271 IPropertyBag_AddRef(iface
);
1275 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1279 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1283 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1284 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1286 static const WCHAR wszTargetSpecialFolder
[] = {
1287 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1288 static const WCHAR wszTarget
[] = {
1289 'T','a','r','g','e','t',0 };
1290 static const WCHAR wszAttributes
[] = {
1291 'A','t','t','r','i','b','u','t','e','s',0 };
1292 static const WCHAR wszResolveLinkFlags
[] = {
1293 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1294 static const WCHAR wszTargetKnownFolder
[] = {
1295 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1296 static const WCHAR wszCLSID
[] = {
1297 'C','L','S','I','D',0 };
1299 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1300 ok(V_VT(pVar
) == VT_I4
, "Wrong variant type for 'TargetSpecialFolder' property!\n");
1301 return E_INVALIDARG
;
1304 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1306 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1307 return E_INVALIDARG
;
1310 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1311 WCHAR wszPath
[MAX_PATH
];
1314 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'Target' property!\n");
1315 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1317 result
= SHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1318 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1319 if (!result
) return E_INVALIDARG
;
1321 V_BSTR(pVar
) = SysAllocString(wszPath
);
1325 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1326 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1327 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1328 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1329 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1333 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1334 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1336 return E_INVALIDARG
;
1339 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1340 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1342 return E_INVALIDARG
;
1345 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1346 return E_INVALIDARG
;
1349 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1352 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1356 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1357 InitPropertyBag_IPropertyBag_QueryInterface
,
1358 InitPropertyBag_IPropertyBag_AddRef
,
1359 InitPropertyBag_IPropertyBag_Release
,
1360 InitPropertyBag_IPropertyBag_Read
,
1361 InitPropertyBag_IPropertyBag_Write
1364 static struct IPropertyBag InitPropertyBag
= {
1365 &InitPropertyBag_IPropertyBagVtbl
1368 static void test_FolderShortcut(void) {
1369 IPersistPropertyBag
*pPersistPropertyBag
;
1370 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1371 IPersistFolder3
*pPersistFolder3
;
1374 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1377 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1379 WCHAR wszWineTestFolder
[] = {
1380 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1381 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1382 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1383 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1384 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1385 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1386 'N','a','m','e','S','p','a','c','e','\\',
1387 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1388 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1390 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1391 static const GUID CLSID_UnixDosFolder
=
1392 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1394 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1395 * via their IPersistPropertyBag interface. And that the target folder
1396 * is taken from the IPropertyBag's 'Target' property.
1398 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1399 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1400 if (hr
== REGDB_E_CLASSNOTREG
) {
1401 win_skip("CLSID_FolderShortcut is not implemented\n");
1404 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1405 if (hr
!= S_OK
) return;
1407 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1408 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1410 IPersistPropertyBag_Release(pPersistPropertyBag
);
1414 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1415 (LPVOID
*)&pShellFolder
);
1416 IPersistPropertyBag_Release(pPersistPropertyBag
);
1417 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1418 if (hr
!= S_OK
) return;
1420 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1421 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* win10 */,
1422 "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1424 IShellFolder_Release(pShellFolder
);
1428 result
= SHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1429 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1430 if (!result
) return;
1432 StrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1433 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1435 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1436 IShellFolder_Release(pShellFolder
);
1437 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1438 if (hr
!= S_OK
) return;
1440 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1441 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1442 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1444 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1445 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1446 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1448 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1449 * shell namespace. The target folder, read from the property bag above, remains untouched.
1450 * The following tests show this: The itemidlist for some imaginary shellfolder object
1451 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1452 * itemidlist, but GetDisplayNameOf still returns the path from above.
1454 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1455 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1456 if (hr
!= S_OK
) return;
1458 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1459 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1460 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1461 RegCloseKey(hShellExtKey
);
1462 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1463 &pidlWineTestFolder
, NULL
);
1464 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1465 IShellFolder_Release(pDesktopFolder
);
1466 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1467 if (hr
!= S_OK
) return;
1469 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1470 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1472 IPersistFolder3_Release(pPersistFolder3
);
1473 ILFree(pidlWineTestFolder
);
1477 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1478 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1479 ok(ILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1480 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1481 ILFree(pidlCurrentFolder
);
1482 ILFree(pidlWineTestFolder
);
1484 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1485 IPersistFolder3_Release(pPersistFolder3
);
1486 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1487 if (hr
!= S_OK
) return;
1489 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1490 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1492 IShellFolder_Release(pShellFolder
);
1496 StrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1497 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1499 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1500 * but ShellFSFolders. */
1501 myPathAddBackslashW(wszDesktopPath
);
1502 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1503 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1504 IShellFolder_Release(pShellFolder
);
1508 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1509 &pidlSubFolder
, NULL
);
1510 RemoveDirectoryW(wszDesktopPath
);
1511 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1513 IShellFolder_Release(pShellFolder
);
1517 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1518 (LPVOID
*)&pPersistFolder3
);
1519 IShellFolder_Release(pShellFolder
);
1520 ILFree(pidlSubFolder
);
1521 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1525 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1526 * a little bit and also allow CLSID_UnixDosFolder. */
1527 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1528 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1529 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1530 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1532 IPersistFolder3_Release(pPersistFolder3
);
1535 #include "pshpack1.h"
1536 struct FileStructA
{
1540 WORD uFileDate
; /* In our current implementation this is */
1541 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1546 struct FileStructW
{
1547 WORD cbLen
; /* Length of this element. */
1548 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1549 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1550 WORD uTime
; /* (this is currently speculation) */
1551 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1552 WORD uTime2
; /* (this is currently speculation) */
1553 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1554 WCHAR wszName
[1]; /* The long filename in unicode. */
1555 /* Just for documentation: Right after the unicode string: */
1556 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1557 * SHITEMID->cb == uOffset + cbLen */
1559 #include "poppack.h"
1561 static void test_ITEMIDLIST_format(void) {
1562 WCHAR wszPersonal
[MAX_PATH
];
1563 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1564 LPITEMIDLIST pidlPersonal
, pidlFile
;
1568 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1569 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1572 bResult
= SHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1573 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1574 if (!bResult
) return;
1576 SetLastError(0xdeadbeef);
1577 bResult
= SetCurrentDirectoryW(wszPersonal
);
1578 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1579 win_skip("Most W-calls are not implemented\n");
1582 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1583 if (!bResult
) return;
1585 hr
= SHGetDesktopFolder(&psfDesktop
);
1586 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1587 if (hr
!= S_OK
) return;
1589 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1590 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1592 IShellFolder_Release(psfDesktop
);
1596 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1597 (LPVOID
*)&psfPersonal
);
1598 IShellFolder_Release(psfDesktop
);
1599 ILFree(pidlPersonal
);
1600 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1601 if (hr
!= S_OK
) return;
1603 for (i
=0; i
<3; i
++) {
1604 CHAR szFile
[MAX_PATH
];
1605 struct FileStructA
*pFileStructA
;
1608 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1610 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1611 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1612 if (hFile
== INVALID_HANDLE_VALUE
) {
1613 IShellFolder_Release(psfPersonal
);
1618 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1619 DeleteFileW(wszFile
[i
]);
1620 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1622 IShellFolder_Release(psfPersonal
);
1626 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1627 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1628 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1629 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1631 if (i
< 2) /* First two file names are already in valid 8.3 format */
1632 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1634 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1635 * can't implement this correctly, since unix filesystems don't support
1636 * this nasty short/long filename stuff. So we'll probably stay with our
1637 * current habit of storing the long filename here, which seems to work
1640 ok(pidlFile
->mkid
.abID
[18] == '~', "Should be derived 8.3 name!\n");
1642 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1643 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0',
1644 "Alignment byte, where there shouldn't be!\n");
1646 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1647 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1648 "There should be an alignment byte, but isn't!\n");
1650 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1651 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1652 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1653 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)),
1654 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1656 if (cbOffset
>= sizeof(struct FileStructA
) &&
1657 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1659 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1660 WCHAR
*name
= pFileStructW
->wszName
;
1662 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1663 "FileStructW's offset and length should add up to the PIDL's length!\n");
1665 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1666 /* Since we just created the file, time of creation,
1667 * time of last access and time of last write access just be the same.
1668 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1669 * after the first run. I do remember something with NTFS keeping the creation time
1670 * if a file is deleted and then created again within a couple of seconds or so.
1671 * Might be the reason. */
1672 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1673 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1674 "Last write time should match creation time!\n");
1676 /* On FAT filesystems the last access time is midnight
1677 local time, so the values of uDate2 and uTime2 will
1678 depend on the local timezone. If the times are exactly
1679 equal then the dates should be identical for both FAT
1680 and NTFS as no timezone is more than 1 day away from UTC.
1682 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1684 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1685 "Last write date and time should match last access date and time!\n");
1689 /* Filesystem may be FAT. Check date within 1 day
1690 and seconds are zero. */
1691 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1692 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1693 "Last access time on FAT filesystems should have zero seconds.\n");
1694 /* TODO: Perform check for date being within one day.*/
1697 ok (!lstrcmpW(wszFile
[i
], name
) ||
1698 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1699 !lstrcmpW(wszFile
[i
], name
+ 11) || /* Win7 */
1700 !lstrcmpW(wszFile
[i
], name
+ 13), /* Win8 */
1701 "The filename should be stored in unicode at this position!\n");
1708 IShellFolder_Release(psfPersonal
);
1711 static void test_SHGetFolderPathA(void)
1713 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1715 char path
[MAX_PATH
];
1716 char path_x86
[MAX_PATH
];
1717 char path_key
[MAX_PATH
];
1721 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1723 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1724 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1725 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1728 win_skip( "Program Files (x86) not supported\n" );
1731 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1734 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1735 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1736 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1740 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1742 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1744 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1746 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1748 DWORD type
, count
= sizeof(path_x86
);
1749 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1751 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1752 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1754 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1758 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1759 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1760 hr
= SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1763 win_skip( "Common Files (x86) not supported\n" );
1766 ok( hr
== S_OK
, "SHGetFolderPathA failed %x\n", hr
);
1769 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1770 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1771 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1775 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1777 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1779 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1781 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1783 DWORD type
, count
= sizeof(path_x86
);
1784 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1786 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1787 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1789 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1793 static void test_SHGetFolderPathAndSubDirA(void)
1799 static const char wine
[] = "wine";
1800 static const char winetemp
[] = "wine\\temp";
1801 static char appdata
[MAX_PATH
];
1802 static char testpath
[MAX_PATH
];
1803 static char toolongpath
[MAX_PATH
+1];
1805 if(FAILED(SHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
1807 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1811 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1812 delret
= RemoveDirectoryA(testpath
);
1813 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
1814 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1818 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1819 delret
= RemoveDirectoryA(testpath
);
1820 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
1821 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1825 /* test invalid second parameter */
1826 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
1827 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
1829 /* test fourth parameter */
1830 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
1832 case S_OK
: /* winvista */
1833 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
1834 "expected %s to start with %s\n", testpath
, appdata
);
1835 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
1836 "expected %s to end with %s\n", testpath
, winetemp
);
1838 case E_INVALIDARG
: /* winxp, win2k3 */
1841 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
1844 /* test fifth parameter */
1846 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
1847 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1848 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1851 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
1852 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1853 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1856 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
1857 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1858 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1860 for(i
=0; i
< MAX_PATH
; i
++)
1861 toolongpath
[i
] = '0' + i
% 10;
1862 toolongpath
[MAX_PATH
] = '\0';
1863 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
1864 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
1865 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
1868 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
1869 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
1871 /* test a not existing path */
1873 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
1874 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
1875 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
1877 /* create a directory inside a not existing directory */
1879 ret
= SHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
1880 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1881 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
1882 "expected %s to start with %s\n", testpath
, appdata
);
1883 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
1884 "expected %s to end with %s\n", testpath
, winetemp
);
1885 dwret
= GetFileAttributesA(testpath
);
1886 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
1889 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1890 RemoveDirectoryA(testpath
);
1891 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1892 RemoveDirectoryA(testpath
);
1895 static void test_LocalizedNames(void)
1897 static char cCurrDirA
[MAX_PATH
];
1898 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
1899 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1900 ITEMIDLIST
*newPIDL
;
1903 static char resourcefile
[MAX_PATH
];
1909 static const char desktopini_contents1
[] =
1910 "[.ShellClassInfo]\r\n"
1911 "LocalizedResourceName=@";
1912 static const char desktopini_contents2
[] =
1914 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
1915 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
1917 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
1918 CreateDirectoryA(".\\testfolder", NULL
);
1920 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
1922 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
1924 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
1925 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1926 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
1927 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
1928 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
1929 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
1930 ok(ret
, "WriteFile failed %i\n", GetLastError());
1933 /* get IShellFolder for parent */
1934 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1935 len
= lstrlenA(cCurrDirA
);
1938 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
1941 if(cCurrDirA
[len
-1] == '\\')
1942 cCurrDirA
[len
-1] = 0;
1944 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1946 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1947 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1949 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1950 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1952 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1953 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1955 IMalloc_Free(ppM
, newPIDL
);
1957 /* windows reads the display name from the resource */
1958 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
1959 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1961 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
1962 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
1964 hr
= StrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
1965 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
1967 ok (!lstrcmpiW(tempbufW
, folderdisplayW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
1969 /* editing name is also read from the resource */
1970 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
1971 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
1973 hr
= StrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
1974 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
1976 ok (!lstrcmpiW(tempbufW
, folderdisplayW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
1978 /* parsing name is unchanged */
1979 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
1980 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
1982 hr
= StrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
1983 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
1984 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
1986 IShellFolder_Release(IDesktopFolder
);
1987 IShellFolder_Release(testIShellFolder
);
1989 IMalloc_Free(ppM
, newPIDL
);
1992 DeleteFileA(".\\testfolder\\desktop.ini");
1993 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
1994 RemoveDirectoryA(".\\testfolder");
1997 static void test_SHCreateShellItem(void)
1999 IShellItem
*shellitem
, *shellitem2
;
2000 IPersistIDList
*persistidl
;
2001 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2003 char curdirA
[MAX_PATH
];
2004 WCHAR curdirW
[MAX_PATH
];
2005 WCHAR fnbufW
[MAX_PATH
];
2006 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2007 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2009 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2011 if (!pSHCreateShellItem
)
2013 win_skip("SHCreateShellItem isn't available\n");
2019 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2023 ret
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2024 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2026 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2028 ret
= SHGetDesktopFolder(&desktopfolder
);
2029 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2031 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2032 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2034 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2035 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2037 CreateTestFile(".\\testfile");
2039 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2040 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2042 pidl_abstestfile
= ILCombine(pidl_cwd
, pidl_testfile
);
2044 shellitem
= (void*)0xdeadbeef;
2045 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2046 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2047 ok(shellitem
== 0, "Got %p\n", shellitem
);
2049 if (0) /* crashes on Windows XP */
2051 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2052 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2053 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2054 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2057 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2058 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2061 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2062 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2065 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2066 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2069 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2072 IPersistIDList_Release(persistidl
);
2074 IShellItem_Release(shellitem
);
2077 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2078 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2081 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2082 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2085 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2086 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2089 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2092 IPersistIDList_Release(persistidl
);
2095 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2096 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2099 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2100 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2103 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2104 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2107 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2110 IPersistIDList_Release(persistidl
);
2112 IShellItem_Release(shellitem2
);
2115 IShellItem_Release(shellitem
);
2118 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2119 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2122 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2123 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2126 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2127 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2130 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2133 IPersistIDList_Release(persistidl
);
2135 IShellItem_Release(shellitem
);
2138 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2139 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2140 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2143 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2144 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2147 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2148 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2151 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2154 IPersistIDList_Release(persistidl
);
2156 IShellItem_Release(shellitem
);
2159 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2160 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2163 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2164 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2167 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2168 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2171 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2174 IPersistIDList_Release(persistidl
);
2177 IShellItem_Release(shellitem
);
2180 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2181 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2184 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2185 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2186 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2187 IShellItem_Release(shellitem
);
2190 /* SHCreateItemFromParsingName */
2191 if(pSHCreateItemFromParsingName
)
2195 /* Crashes under windows 7 */
2196 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2199 shellitem
= (void*)0xdeadbeef;
2200 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2201 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2202 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2204 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2205 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2206 "SHCreateItemFromParsingName returned %x\n", ret
);
2207 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2209 lstrcpyW(fnbufW
, curdirW
);
2210 myPathAddBackslashW(fnbufW
);
2211 lstrcatW(fnbufW
, testfileW
);
2213 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2214 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2218 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2219 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2222 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2223 CoTaskMemFree(tmp_fname
);
2225 IShellItem_Release(shellitem
);
2229 win_skip("No SHCreateItemFromParsingName\n");
2232 /* SHCreateItemFromIDList */
2233 if(pSHCreateItemFromIDList
)
2237 /* Crashes under win7 */
2238 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2241 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2242 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2244 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2245 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2248 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2249 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2252 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2253 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2256 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2259 IPersistIDList_Release(persistidl
);
2261 IShellItem_Release(shellitem
);
2264 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2265 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2268 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2269 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2272 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2273 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2276 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2279 IPersistIDList_Release(persistidl
);
2281 IShellItem_Release(shellitem
);
2285 win_skip("No SHCreateItemFromIDList\n");
2287 /* SHCreateItemFromRelativeName */
2288 if(pSHCreateItemFromRelativeName
&& pSHGetKnownFolderPath
)
2290 IShellItem
*shellitem_desktop
= NULL
;
2291 WCHAR
*desktop_path
, *displayname
;
2292 WCHAR testfile_path
[MAX_PATH
] = {0};
2294 LPITEMIDLIST pidl_desktop_testfile
= NULL
;
2297 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem_desktop
);
2298 ok(ret
== S_OK
, "SHCreateShellItem failed: 0x%08x.\n", ret
);
2300 shellitem
= (void*)0xdeadbeef;
2301 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, NULL
, NULL
, &IID_IShellItem
,
2302 (void**)&shellitem
);
2303 ok(ret
== E_INVALIDARG
, "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n",
2305 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2307 /* Test with a non-existent file */
2308 shellitem
= (void*)0xdeadbeef;
2309 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2310 (void**)&shellitem
);
2311 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2312 "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n",
2313 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), ret
);
2314 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2316 /* Create a file for testing in desktop folder */
2317 pSHGetKnownFolderPath(&FOLDERID_Desktop
, 0, NULL
, &desktop_path
);
2318 lstrcatW(testfile_path
, desktop_path
);
2319 myPathAddBackslashW(testfile_path
);
2320 lstrcatW(testfile_path
, testfileW
);
2321 file
= CreateFileW(testfile_path
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
2322 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError());
2325 shellitem
= (void*)0xdeadbeef;
2326 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2327 (void**)&shellitem
);
2328 ok(ret
== S_OK
, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret
);
2329 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2332 ret
= IShellItem_GetDisplayName(shellitem
, 0, &displayname
);
2333 ok(ret
== S_OK
, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret
);
2334 ok(!lstrcmpW(displayname
, testfileW
), "got wrong display name: %s.\n", wine_dbgstr_w(displayname
));
2335 CoTaskMemFree(displayname
);
2337 shellitem2
= (void*)0xdeadbeef;
2338 ret
= pSHCreateItemFromRelativeName(shellitem_desktop
, testfileW
, NULL
, &IID_IShellItem
,
2339 (void**)&shellitem2
);
2340 ok(ret
== S_OK
, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret
);
2341 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2342 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2343 ok(!order
, "order got wrong value: %d.\n", order
);
2344 IShellItem_Release(shellitem2
);
2346 shellitem2
= (void*)0xdeadbeef;
2347 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, testfileW
, NULL
,
2348 &pidl_desktop_testfile
, NULL
);
2349 ok(ret
== S_OK
, "ParseDisplayName failed 0x%08x.\n", ret
);
2350 ret
= pSHCreateItemFromIDList(pidl_desktop_testfile
, &IID_IShellItem
, (void**)&shellitem2
);
2351 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2352 ok(ret
== S_OK
, "IShellItem_Compare fail: 0x%08x.\n", ret
);
2353 ok(!order
, "order got wrong value: %d.\n", order
);
2354 ILFree(pidl_desktop_testfile
);
2355 IShellItem_Release(shellitem2
);
2357 IShellItem_Release(shellitem
);
2360 DeleteFileW(testfile_path
);
2361 CoTaskMemFree(desktop_path
);
2362 IShellItem_Release(shellitem_desktop
);
2365 win_skip("No SHCreateItemFromRelativeName or SHGetKnownFolderPath\n");
2367 /* SHCreateItemInKnownFolder */
2368 if(pSHCreateItemInKnownFolder
&& pSHGetKnownFolderPath
)
2370 WCHAR
*desktop_path
;
2371 WCHAR testfile_path
[MAX_PATH
] = {0};
2373 WCHAR
*displayname
= NULL
;
2375 LPITEMIDLIST pidl_desktop_testfile
= NULL
;
2377 shellitem
= (void*)0xdeadbeef;
2378 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, NULL
, &IID_IShellItem
,
2379 (void**)&shellitem
);
2380 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2381 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2384 shellitem2
= (void*)0xdeadbeef;
2385 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem2
);
2386 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2389 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2390 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2391 ok(!order
, "order got wrong value: %d.\n", order
);
2392 IShellItem_Release(shellitem2
);
2394 IShellItem_Release(shellitem
);
2397 /* Test with a non-existent file */
2398 shellitem
= (void*)0xdeadbeef;
2399 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2400 (void**)&shellitem
);
2401 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2402 "Expected 0x%08x but SHCreateItemInKnownFolder return: 0x%08x.\n",
2403 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), ret
);
2404 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2406 pSHGetKnownFolderPath(&FOLDERID_Desktop
, 0, NULL
, &desktop_path
);
2407 lstrcatW(testfile_path
, desktop_path
);
2408 myPathAddBackslashW(testfile_path
);
2409 lstrcatW(testfile_path
, testfileW
);
2410 file
= CreateFileW(testfile_path
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
2411 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError());
2414 shellitem
= (void*)0xdeadbeef;
2415 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2416 (void**)&shellitem
);
2417 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2418 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2421 ret
= IShellItem_GetDisplayName(shellitem
, 0, &displayname
);
2422 ok(ret
== S_OK
, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret
);
2423 ok(!lstrcmpW(displayname
, testfileW
), "got wrong display name: %s.\n",
2424 wine_dbgstr_w(displayname
));
2425 CoTaskMemFree(displayname
);
2427 shellitem2
= (void*)0xdeadbeef;
2428 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Desktop
, 0, testfileW
, &IID_IShellItem
,
2429 (void**)&shellitem2
);
2430 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2431 ok(shellitem2
!= NULL
, "shellitem was %p.\n", shellitem
);
2432 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2433 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2434 ok(!order
, "order got wrong value: %d.\n", order
);
2435 IShellItem_Release(shellitem2
);
2437 shellitem2
= (void*)0xdeadbeef;
2438 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, testfileW
, NULL
,
2439 &pidl_desktop_testfile
, NULL
);
2440 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x.\n", ret
);
2441 ret
= pSHCreateItemFromIDList(pidl_desktop_testfile
, &IID_IShellItem
, (void**)&shellitem2
);
2442 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2443 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2444 ok(!order
, "order got wrong value: %d.\n", order
);
2445 ILFree(pidl_desktop_testfile
);
2446 IShellItem_Release(shellitem2
);
2448 IShellItem_Release(shellitem
);
2451 shellitem
= (void*)0xdeadbeef;
2452 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Documents
, 0, NULL
, &IID_IShellItem
,
2453 (void**)&shellitem
);
2454 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2455 ok(shellitem
!= NULL
, "shellitem was %p.\n", shellitem
);
2458 shellitem2
= (void*)0xdeadbeef;
2459 ret
= pSHCreateItemInKnownFolder(&FOLDERID_Documents
, 0, NULL
, &IID_IShellItem
,
2460 (void**)&shellitem2
);
2461 ok(ret
== S_OK
, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret
);
2462 ok(shellitem2
!= NULL
, "shellitem was %p.\n", shellitem
);
2463 ret
= IShellItem_Compare(shellitem
, shellitem2
, 0, &order
);
2464 ok(ret
== S_OK
, "IShellItem_Compare failed: 0x%08x.\n", ret
);
2465 ok(!order
, "order got wrong value: %d.\n", order
);
2466 IShellItem_Release(shellitem2
);
2468 IShellItem_Release(shellitem
);
2470 DeleteFileW(testfile_path
);
2471 CoTaskMemFree(desktop_path
);
2474 win_skip("No SHCreateItemInKnownFolder or SHGetKnownFolderPath\n");
2476 DeleteFileA(".\\testfile");
2477 ILFree(pidl_abstestfile
);
2478 ILFree(pidl_testfile
);
2479 ILFree(pidl_desktop
);
2481 IShellFolder_Release(currentfolder
);
2482 IShellFolder_Release(desktopfolder
);
2485 static void test_SHGetNameFromIDList(void)
2487 IShellItem
*shellitem
;
2492 static const DWORD flags
[] = {
2493 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2494 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2495 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2496 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2498 if(!pSHGetNameFromIDList
)
2500 win_skip("SHGetNameFromIDList missing.\n");
2504 /* This should be available on any platform that passed the above test. */
2505 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2509 /* Crashes under win7 */
2510 pSHGetNameFromIDList(NULL
, 0, NULL
);
2513 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2514 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2516 /* Test the desktop */
2517 hres
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2518 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2519 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2520 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2523 WCHAR
*nameSI
, *nameSH
;
2524 WCHAR buf
[MAX_PATH
];
2525 HRESULT hrSI
, hrSH
, hrSF
;
2530 SHGetDesktopFolder(&psf
);
2531 for(i
= 0; flags
[i
] != -1234; i
++)
2533 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2534 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2535 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2536 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2537 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2538 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2540 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2541 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2545 StrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2547 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2549 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2551 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2552 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2554 IShellFolder_Release(psf
);
2556 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2557 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2558 res
= SHGetPathFromIDListW(pidl
, buf
);
2559 ok(res
== TRUE
, "Got %d\n", res
);
2560 if(SUCCEEDED(hrSI
) && res
)
2561 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2562 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2564 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2565 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2566 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2568 IShellItem_Release(shellitem
);
2572 /* Test the control panel */
2573 hres
= SHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2574 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2575 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2576 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2579 WCHAR
*nameSI
, *nameSH
;
2580 WCHAR buf
[MAX_PATH
];
2581 HRESULT hrSI
, hrSH
, hrSF
;
2586 SHGetDesktopFolder(&psf
);
2587 for(i
= 0; flags
[i
] != -1234; i
++)
2589 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2590 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2591 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2592 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2593 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2594 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2596 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2597 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2601 StrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2603 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2605 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2607 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2608 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2610 IShellFolder_Release(psf
);
2612 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2613 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2614 res
= SHGetPathFromIDListW(pidl
, buf
);
2615 ok(res
== FALSE
, "Got %d\n", res
);
2616 if(SUCCEEDED(hrSI
) && res
)
2617 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2618 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2620 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2621 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2622 "Got 0x%08x\n", hres
);
2623 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2625 IShellItem_Release(shellitem
);
2630 static void test_SHGetItemFromDataObject(void)
2632 IShellFolder
*psfdesktop
;
2637 if(!pSHGetItemFromDataObject
)
2639 win_skip("No SHGetItemFromDataObject.\n");
2645 /* Crashes under win7 */
2646 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2649 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2650 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2652 SHGetDesktopFolder(&psfdesktop
);
2654 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2655 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2662 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2663 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2664 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2667 LPITEMIDLIST apidl
[5];
2670 for(count
= 0; count
< 5; count
++)
2671 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2676 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2677 &IID_IDataObject
, NULL
, (void**)&pdo
);
2678 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2681 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2682 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2683 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2684 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2685 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2686 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2687 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2688 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2689 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2690 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2691 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2692 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2693 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2694 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2695 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2697 IDataObject_Release(pdo
);
2701 skip("No file(s) found - skipping single-file test.\n");
2705 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2706 &IID_IDataObject
, NULL
, (void**)&pdo
);
2707 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2710 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2711 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2712 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2713 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2714 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2715 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2716 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2717 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2718 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2719 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2720 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2721 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2722 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2723 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2724 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2725 IDataObject_Release(pdo
);
2729 skip("zero or one file found - skipping multi-file test.\n");
2731 for(i
= 0; i
< count
; i
++)
2734 IEnumIDList_Release(peidl
);
2737 IShellView_Release(psv
);
2740 IShellFolder_Release(psfdesktop
);
2743 static void test_ShellItemCompare(void)
2745 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2746 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2747 IShellFolder
*psf_desktop
, *psf_current
;
2748 LPITEMIDLIST pidl_cwd
;
2749 WCHAR curdirW
[MAX_PATH
];
2752 static const WCHAR filesW
[][9] = {
2753 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2754 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2755 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2759 if(!pSHCreateShellItem
)
2761 win_skip("SHCreateShellItem missing.\n");
2765 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2768 skip("Failed to get current directory, skipping.\n");
2772 CreateDirectoryA(".\\a", NULL
);
2773 CreateDirectoryA(".\\b", NULL
);
2774 CreateDirectoryA(".\\c", NULL
);
2775 CreateTestFile(".\\a\\a");
2776 CreateTestFile(".\\a\\b");
2777 CreateTestFile(".\\a\\c");
2778 CreateTestFile(".\\b\\a");
2779 CreateTestFile(".\\b\\b");
2780 CreateTestFile(".\\b\\c");
2781 CreateTestFile(".\\c\\a");
2782 CreateTestFile(".\\c\\b");
2783 CreateTestFile(".\\c\\c");
2785 SHGetDesktopFolder(&psf_desktop
);
2786 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2787 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2788 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2789 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2790 IShellFolder_Release(psf_desktop
);
2793 /* Generate ShellItems for the files */
2794 memset(&psi
, 0, sizeof(psi
));
2796 for(i
= 0; i
< 9; i
++)
2798 LPITEMIDLIST pidl_testfile
= NULL
;
2800 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2801 NULL
, &pidl_testfile
, NULL
);
2802 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2805 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2806 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2807 ILFree(pidl_testfile
);
2809 if(FAILED(hr
)) failed
= TRUE
;
2813 skip("Failed to create all shellitems.\n");
2817 /* Generate ShellItems for the folders */
2818 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2819 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2820 if(FAILED(hr
)) failed
= TRUE
;
2821 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2822 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2823 if(FAILED(hr
)) failed
= TRUE
;
2824 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2825 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2826 if(FAILED(hr
)) failed
= TRUE
;
2830 skip("Failed to create shellitems.\n");
2836 /* Crashes on native (win7, winxp) */
2837 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2838 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2839 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2843 for(i
= 0; i
< 9; i
++)
2845 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
2846 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2847 ok(order
== 0, "Got order %d\n", order
);
2848 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
2849 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2850 ok(order
== 0, "Got order %d\n", order
);
2851 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2852 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2853 ok(order
== 0, "Got order %d\n", order
);
2857 /* a\b:a\a , a\b:a\c, a\b:a\b */
2858 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &order
);
2859 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2860 ok(order
== 1, "Got order %d\n", order
);
2861 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_DISPLAY
, &order
);
2862 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2863 ok(order
== -1, "Got order %d\n", order
);
2864 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2865 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2866 ok(order
== 0, "Got order %d\n", order
);
2868 /* b\b:a\b, b\b:c\b, b\b:c\b */
2869 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
2870 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2871 ok(order
== 1, "Got order %d\n", order
);
2872 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
2873 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2874 ok(order
== -1, "Got order %d\n", order
);
2875 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2876 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2877 ok(order
== 0, "Got order %d\n", order
);
2879 /* b:a\a, b:a\c, b:a\b */
2880 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
2881 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2882 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2883 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
2884 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2885 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2886 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2887 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2888 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2890 /* b:c\a, b:c\c, b:c\b */
2891 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
2892 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2893 ok(order
== -1, "Got order %d\n", order
);
2894 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_DISPLAY
, &order
);
2895 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2896 ok(order
== -1, "Got order %d\n", order
);
2897 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2898 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2899 ok(order
== -1, "Got order %d\n", order
);
2901 /* a\b:a\a , a\b:a\c, a\b:a\b */
2902 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
2903 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2904 ok(order
== 1, "Got order %d\n", order
);
2905 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
2906 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2907 ok(order
== -1, "Got order %d\n", order
);
2908 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2909 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2910 ok(order
== 0, "Got order %d\n", order
);
2912 /* b\b:a\b, b\b:c\b, b\b:c\b */
2913 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
2914 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2915 ok(order
== 1, "Got order %d\n", order
);
2916 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &order
);
2917 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2918 ok(order
== -1, "Got order %d\n", order
);
2919 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2920 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2921 ok(order
== 0, "Got order %d\n", order
);
2923 /* b:a\a, b:a\c, b:a\b */
2924 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
2925 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2926 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2927 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
2928 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2929 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2930 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2931 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2932 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2934 /* b:c\a, b:c\c, b:c\b */
2935 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
2936 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2937 ok(order
== -1, "Got order %d\n", order
);
2938 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_CANONICAL
, &order
);
2939 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2940 ok(order
== -1, "Got order %d\n", order
);
2941 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
2942 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2943 ok(order
== -1, "Got order %d\n", order
);
2946 IShellFolder_Release(psf_current
);
2948 DeleteFileA(".\\a\\a");
2949 DeleteFileA(".\\a\\b");
2950 DeleteFileA(".\\a\\c");
2951 DeleteFileA(".\\b\\a");
2952 DeleteFileA(".\\b\\b");
2953 DeleteFileA(".\\b\\c");
2954 DeleteFileA(".\\c\\a");
2955 DeleteFileA(".\\c\\b");
2956 DeleteFileA(".\\c\\c");
2957 RemoveDirectoryA(".\\a");
2958 RemoveDirectoryA(".\\b");
2959 RemoveDirectoryA(".\\c");
2961 if(psi_a
) IShellItem_Release(psi_a
);
2962 if(psi_b
) IShellItem_Release(psi_b
);
2963 if(psi_c
) IShellItem_Release(psi_c
);
2965 for(i
= 0; i
< 9; i
++)
2966 if(psi
[i
]) IShellItem_Release(psi
[i
]);
2969 /**************************************************************/
2970 /* IUnknown implementation for counting QueryInterface calls. */
2972 IUnknown IUnknown_iface
;
2980 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
2982 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
2985 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
2987 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
2990 for(i
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
2992 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
2994 This
->ifaces
[i
].count
++;
3001 return E_NOINTERFACE
;
3004 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3009 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3014 static const IUnknownVtbl vt_IUnknown
= {
3015 unk_fnQueryInterface
,
3020 static void test_SHGetIDListFromObject(void)
3022 IUnknownImpl
*punkimpl
;
3023 IShellFolder
*psfdesktop
;
3025 LPITEMIDLIST pidl
, pidl_desktop
;
3028 struct if_count ifaces
[] =
3029 { {&IID_IPersistIDList
, 0},
3030 {&IID_IPersistFolder2
, 0},
3031 {&IID_IDataObject
, 0},
3032 {&IID_IParentAndItem
, 0},
3033 {&IID_IFolderView
, 0},
3036 if(!pSHGetIDListFromObject
)
3038 win_skip("SHGetIDListFromObject missing.\n");
3044 /* Crashes native */
3045 pSHGetIDListFromObject(NULL
, NULL
);
3046 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3049 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3050 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3052 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3053 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3054 punkimpl
->ifaces
= ifaces
;
3055 punkimpl
->unknown
= 0;
3057 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3058 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3059 ok(ifaces
[0].count
, "interface not requested.\n");
3060 ok(ifaces
[1].count
, "interface not requested.\n");
3061 ok(ifaces
[2].count
, "interface not requested.\n");
3063 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3064 "interface not requested.\n");
3065 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3066 "interface not requested.\n");
3068 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3069 HeapFree(GetProcessHeap(), 0, punkimpl
);
3071 pidl_desktop
= NULL
;
3072 SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3073 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3075 SHGetDesktopFolder(&psfdesktop
);
3077 /* Test IShellItem */
3078 if(pSHCreateShellItem
)
3080 IShellItem
*shellitem
;
3081 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3082 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3085 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3086 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3089 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3092 IShellItem_Release(shellitem
);
3096 skip("no SHCreateShellItem.\n");
3098 /* Test IShellFolder */
3099 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3100 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3103 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3107 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3108 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3115 /* Test IFolderView */
3116 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3117 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3120 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3124 /* Test IDataObject */
3125 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3126 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3127 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3130 LPITEMIDLIST apidl
[5];
3132 for(count
= 0; count
< 5; count
++)
3133 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3138 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3139 &IID_IDataObject
, NULL
, (void**)&pdo
);
3140 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3143 pidl
= (void*)0xDEADBEEF;
3144 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3145 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3146 ok(pidl
!= NULL
, "pidl is NULL.\n");
3147 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3150 IDataObject_Release(pdo
);
3154 skip("No files found - skipping single-file test.\n");
3158 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3159 &IID_IDataObject
, NULL
, (void**)&pdo
);
3160 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3163 pidl
= (void*)0xDEADBEEF;
3164 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3165 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3166 "got 0x%08x\n", hres
);
3167 ok(pidl
== NULL
, "pidl is not NULL.\n");
3169 IDataObject_Release(pdo
);
3173 skip("zero or one file found - skipping multi-file test.\n");
3175 for(i
= 0; i
< count
; i
++)
3178 IEnumIDList_Release(peidl
);
3181 IShellView_Release(psv
);
3184 IShellFolder_Release(psfdesktop
);
3185 ILFree(pidl_desktop
);
3188 static void test_SHGetItemFromObject(void)
3190 IUnknownImpl
*punkimpl
;
3191 IShellFolder
*psfdesktop
;
3196 struct if_count ifaces
[] =
3197 { {&IID_IPersistIDList
, 0},
3198 {&IID_IPersistFolder2
, 0},
3199 {&IID_IDataObject
, 0},
3200 {&IID_IParentAndItem
, 0},
3201 {&IID_IFolderView
, 0},
3204 if(!pSHGetItemFromObject
)
3206 skip("No SHGetItemFromObject.\n");
3210 SHGetDesktopFolder(&psfdesktop
);
3214 /* Crashes with Windows 7 */
3215 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3216 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3217 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3220 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3221 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3223 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3224 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3225 punkimpl
->ifaces
= ifaces
;
3226 punkimpl
->unknown
= 0;
3228 /* The same as SHGetIDListFromObject */
3229 hres
= pSHGetIDListFromObject(&punkimpl
->IUnknown_iface
, &pidl
);
3230 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3231 ok(ifaces
[0].count
, "interface not requested.\n");
3232 ok(ifaces
[1].count
, "interface not requested.\n");
3233 ok(ifaces
[2].count
, "interface not requested.\n");
3235 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3236 "interface not requested.\n");
3237 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3238 "interface not requested.\n");
3240 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3241 HeapFree(GetProcessHeap(), 0, punkimpl
);
3243 /* Test IShellItem */
3244 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3245 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3249 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3250 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3254 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3255 IShellItem_Release(psi2
);
3257 IShellItem_Release(psi
);
3260 IShellFolder_Release(psfdesktop
);
3263 static void test_SHCreateShellItemArray(void)
3265 IShellFolder
*pdesktopsf
, *psf
;
3266 IShellItemArray
*psia
;
3269 WCHAR cTestDirW
[MAX_PATH
];
3270 LPITEMIDLIST pidl_testdir
, pidl
;
3271 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3273 if(!pSHCreateShellItemArray
) {
3274 skip("No pSHCreateShellItemArray!\n");
3280 /* Crashes under native */
3281 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3282 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3283 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3284 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3287 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3288 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3290 SHGetDesktopFolder(&pdesktopsf
);
3291 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3292 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3294 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3295 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3297 SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3298 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3299 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3302 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3303 myPathAddBackslashW(cTestDirW
);
3304 lstrcatW(cTestDirW
, testdirW
);
3306 CreateFilesFolders();
3308 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3309 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3312 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3314 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3316 IShellFolder_Release(pdesktopsf
);
3320 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3321 ILFree(pidl_testdir
);
3326 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3327 ok(hr
== S_OK
, "Got %08x\n", hr
);
3330 LPITEMIDLIST apidl
[5];
3331 UINT done
, numitems
, i
;
3333 for(done
= 0; done
< 5; done
++)
3334 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3336 ok(done
== 5, "Got %d pidls\n", done
);
3337 IEnumIDList_Release(peidl
);
3339 /* Create a ShellItemArray */
3340 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3341 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3348 /* Crashes in Windows 7 */
3349 IShellItemArray_GetCount(psia
, NULL
);
3352 IShellItemArray_GetCount(psia
, &numitems
);
3353 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3355 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3356 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3358 /* Compare all the items */
3359 for(i
= 0; i
< numitems
; i
++)
3361 LPITEMIDLIST pidl_abs
;
3362 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3364 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3365 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3368 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3369 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3372 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3375 IShellItem_Release(psi
);
3379 for(i
= 0; i
< done
; i
++)
3381 IShellItemArray_Release(psia
);
3385 /* SHCreateShellItemArrayFromShellItem */
3386 if(pSHCreateShellItemArrayFromShellItem
)
3392 /* Crashes under Windows 7 */
3393 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3394 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3395 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3398 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3399 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3402 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3403 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3408 hr
= IShellItemArray_GetCount(psia
, &count
);
3409 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3410 ok(count
== 1, "Got count %d\n", count
);
3411 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3412 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3414 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3417 LPITEMIDLIST pidl1
, pidl2
;
3418 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3419 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3420 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3421 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3422 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3423 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3424 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3427 IShellItem_Release(psi2
);
3429 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3430 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3431 IShellItemArray_Release(psia
);
3433 IShellItem_Release(psi
);
3437 skip("No SHCreateShellItemArrayFromShellItem.\n");
3439 if(pSHCreateShellItemArrayFromDataObject
)
3445 /* Crashes under Windows 7 */
3446 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3448 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3449 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3451 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3452 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3459 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3460 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3464 LPITEMIDLIST apidl
[5];
3467 for(count
= 0; count
< 5; count
++)
3468 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3470 ok(count
== 5, "Got %d\n", count
);
3474 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3475 &IID_IDataObject
, NULL
, (void**)&pdo
);
3476 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3479 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3481 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3485 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3486 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3487 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3488 for(i
= 0; i
< count_sia
; i
++)
3490 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3492 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3493 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3497 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3498 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3499 ok(pidl
!= NULL
, "pidl as NULL.\n");
3500 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3502 IShellItem_Release(psi
);
3507 IShellItemArray_Release(psia
);
3510 IDataObject_Release(pdo
);
3512 for(i
= 0; i
< count
; i
++)
3516 skip("No files found - skipping test.\n");
3518 IEnumIDList_Release(peidl
);
3520 IShellView_Release(psv
);
3524 skip("No SHCreateShellItemArrayFromDataObject.\n");
3526 if(pSHCreateShellItemArrayFromIDLists
)
3528 WCHAR test1W
[] = {'t','e','s','t','1','.','t','x','t',0};
3529 WCHAR test1pathW
[MAX_PATH
];
3530 LPITEMIDLIST pidltest1
;
3531 LPCITEMIDLIST pidl_array
[2];
3536 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, NULL
);
3539 psia
= (void*)0xdeadbeef;
3540 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, &psia
);
3541 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3542 ok(psia
== NULL
, "Got %p\n", psia
);
3544 psia
= (void*)0xdeadbeef;
3545 hr
= pSHCreateShellItemArrayFromIDLists(0, pidl_array
, &psia
);
3546 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3547 ok(psia
== NULL
, "Got %p\n", psia
);
3549 psia
= (void*)0xdeadbeef;
3550 pidl_array
[0] = NULL
;
3551 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3552 todo_wine
ok(hr
== E_OUTOFMEMORY
, "Got 0x%08x\n", hr
);
3553 ok(psia
== NULL
, "Got %p\n", psia
);
3555 psia
= (void*)0xdeadbeef;
3556 pidl_array
[0] = pidl_testdir
;
3557 pidl_array
[1] = NULL
;
3558 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3559 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Vista */, "Got 0x%08x\n", hr
);
3560 todo_wine
ok(psia
!= NULL
|| broken(psia
== NULL
) /* Vista */, "Got %p\n", psia
);
3566 hr
= IShellItemArray_GetCount(psia
, &count
);
3567 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3568 ok(count
== 2, "Got %d\n", count
);
3570 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3571 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3575 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3576 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3577 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3579 CoTaskMemFree(path
);
3581 IShellItem_Release(psi
);
3584 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3585 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3589 WCHAR desktoppath
[MAX_PATH
];
3592 result
= SHGetSpecialFolderPathW(NULL
, desktoppath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
3593 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
3595 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3596 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3597 ok(!lstrcmpW(path
, desktoppath
), "Got %s\n", wine_dbgstr_w(path
));
3599 CoTaskMemFree(path
);
3601 IShellItem_Release(psi
);
3605 IShellItemArray_Release(psia
);
3610 psia
= (void*)0xdeadbeef;
3611 pidl_array
[0] = pidl_testdir
;
3612 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3613 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3619 hr
= IShellItemArray_GetCount(psia
, &count
);
3620 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3621 ok(count
== 1, "Got %d\n", count
);
3623 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3624 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3628 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3629 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3630 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3632 CoTaskMemFree(path
);
3634 IShellItem_Release(psi
);
3637 IShellItemArray_Release(psia
);
3641 lstrcpyW(test1pathW
, cTestDirW
);
3642 myPathAddBackslashW(test1pathW
);
3643 lstrcatW(test1pathW
, test1W
);
3645 SHGetDesktopFolder(&pdesktopsf
);
3647 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, test1pathW
, NULL
, &pidltest1
, NULL
);
3648 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3651 psia
= (void*)0xdeadbeef;
3652 pidl_array
[0] = pidl_testdir
;
3653 pidl_array
[1] = pidltest1
;
3654 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3655 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3661 hr
= IShellItemArray_GetCount(psia
, &count
);
3662 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3663 ok(count
== 2, "Got %d\n", count
);
3665 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3666 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3670 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3671 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3672 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3674 CoTaskMemFree(path
);
3676 IShellItem_Release(psi
);
3679 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3680 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3684 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3685 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3686 ok(!lstrcmpW(path
, test1pathW
), "Got %s\n", wine_dbgstr_w(path
));
3688 CoTaskMemFree(path
);
3690 IShellItem_Release(psi
);
3694 IShellItemArray_Release(psia
);
3700 IShellFolder_Release(pdesktopsf
);
3703 skip("No SHCreateShellItemArrayFromIDLists.\n");
3705 IShellFolder_Release(psf
);
3706 ILFree(pidl_testdir
);
3710 static void test_ShellItemArrayEnumItems(void)
3712 IShellFolder
*pdesktopsf
, *psf
;
3714 WCHAR cTestDirW
[MAX_PATH
];
3716 LPITEMIDLIST pidl_testdir
;
3717 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3719 if(!pSHCreateShellItemArray
)
3721 win_skip("No SHCreateShellItemArray, skipping test...\n");
3725 CreateFilesFolders();
3727 SHGetDesktopFolder(&pdesktopsf
);
3729 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3730 myPathAddBackslashW(cTestDirW
);
3731 lstrcatW(cTestDirW
, testdirW
);
3733 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3734 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3737 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3739 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3740 ILFree(pidl_testdir
);
3742 IShellFolder_Release(pdesktopsf
);
3743 if (FAILED(hr
)) return;
3745 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3746 ok(hr
== S_OK
, "Got %08x\n", hr
);
3749 IShellItemArray
*psia
;
3750 LPITEMIDLIST apidl
[5];
3751 UINT done
, numitems
, i
;
3753 for(done
= 0; done
< 5; done
++)
3754 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3756 ok(done
== 5, "Got %d pidls\n", done
);
3757 IEnumIDList_Release(peidl
);
3759 /* Create a ShellItemArray */
3760 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3761 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3764 IEnumShellItems
*iesi
;
3765 IShellItem
*my_array
[10];
3768 IShellItemArray_GetCount(psia
, &numitems
);
3769 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3772 hr
= IShellItemArray_EnumItems(psia
, &iesi
);
3773 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3774 ok(iesi
!= NULL
, "Got NULL\n");
3777 IEnumShellItems
*iesi2
;
3779 /* This should fail according to the documentation and Win7+ */
3780 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3781 hr
= IEnumShellItems_Next(iesi
, 2, my_array
, NULL
);
3782 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
3783 for(i
= 0; i
< 2; i
++)
3785 ok(my_array
[i
] == (void*)0xdeadbeef ||
3786 broken(my_array
[i
] != (void*)0xdeadbeef && my_array
[i
] != NULL
), /* Vista */
3787 "Got %p (%d)\n", my_array
[i
], i
);
3789 if(my_array
[i
] != (void*)0xdeadbeef)
3790 IShellItem_Release(my_array
[i
]);
3792 ok(my_array
[2] == (void*)0xdeadbeef, "Got %p\n", my_array
[2]);
3794 IEnumShellItems_Reset(iesi
);
3795 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3796 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, NULL
);
3797 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3798 ok(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3799 if(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef)
3800 IShellItem_Release(my_array
[0]);
3801 ok(my_array
[1] == (void*)0xdeadbeef, "Got %p\n", my_array
[1]);
3803 IEnumShellItems_Reset(iesi
);
3805 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3806 hr
= IEnumShellItems_Next(iesi
, numitems
, my_array
, &fetched
);
3807 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3808 ok(fetched
== numitems
, "Got %d\n", fetched
);
3809 for(i
= 0;i
< numitems
; i
++)
3811 ok(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef,
3812 "Got %p at %d\n", my_array
[i
], i
);
3814 if(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef)
3815 IShellItem_Release(my_array
[i
]);
3817 ok(my_array
[i
] == (void*)0xdeadbeef, "Got %p\n", my_array
[i
]);
3819 /* Compare all the items */
3820 IEnumShellItems_Reset(iesi
);
3821 for(i
= 0; i
< numitems
; i
++)
3826 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3827 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3828 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3829 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3830 ok(fetched
== 1, "Got %d\n", fetched
);
3832 hr
= IShellItem_Compare(psi
, my_array
[0], 0, &order
);
3833 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3834 ok(order
== 0, "Got %d\n", order
);
3836 IShellItem_Release(psi
);
3837 IShellItem_Release(my_array
[0]);
3840 my_array
[0] = (void*)0xdeadbeef;
3841 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3842 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3843 ok(fetched
== 0, "Got %d\n", fetched
);
3844 ok(my_array
[0] == (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3846 /* Cloning not implemented anywhere */
3847 iesi2
= (void*)0xdeadbeef;
3848 hr
= IEnumShellItems_Clone(iesi
, &iesi2
);
3849 ok(hr
== E_NOTIMPL
, "Got 0x%08x\n", hr
);
3850 ok(iesi2
== NULL
|| broken(iesi2
== (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2
);
3852 IEnumShellItems_Release(iesi
);
3855 IShellItemArray_Release(psia
);
3858 for(i
= 0; i
< done
; i
++)
3864 static void test_ShellItemBindToHandler(void)
3867 LPITEMIDLIST pidl_desktop
;
3870 if(!pSHCreateShellItem
)
3872 skip("SHCreateShellItem missing.\n");
3876 hr
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3877 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3880 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3881 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3885 IPersistFolder2
*ppf2
;
3890 /* Crashes under Windows 7 */
3891 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3892 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3894 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3895 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3898 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3899 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3900 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3901 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3902 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3905 LPITEMIDLIST pidl_tmp
;
3906 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3907 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3910 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3913 IPersistFolder2_Release(ppf2
);
3916 /* BHID_SFUIObject */
3917 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3918 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3919 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3920 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3921 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3922 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3924 /* BHID_DataObject */
3925 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3926 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3927 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3931 /* BHID_SFViewObject */
3932 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3933 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3934 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3935 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3936 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3937 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3940 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
3941 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3942 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3943 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
3944 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3945 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3948 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
3949 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3950 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3951 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
3952 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3953 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3955 /* BHID_StorageEnum */
3956 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
3957 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3958 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3961 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
3962 supported starting from Win8. */
3963 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferSource
, (void**)&punk
);
3964 ok(hr
== S_OK
|| broken(FAILED(hr
)) /* pre-Vista */, "Got 0x%08x\n", hr
);
3967 IUnknown_Release(punk
);
3969 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferDestination
, (void**)&punk
);
3970 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3971 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3973 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
3974 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Win8 */, "Got 0x%08x\n", hr
);
3975 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3978 /* BHID_EnumItems */
3979 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
3980 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3981 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3984 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
3985 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3986 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3988 /* BHID_LinkTargetItem */
3989 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
3990 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3991 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3992 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
3993 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3994 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3996 /* BHID_PropertyStore */
3997 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
3998 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3999 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4000 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
4001 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4002 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4004 /* BHID_ThumbnailHandler */
4005 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
4006 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4007 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4009 /* BHID_AssociationArray */
4010 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
4011 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4012 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4014 /* BHID_EnumAssocHandlers */
4015 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
4016 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4017 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4020 IShellItem_Release(psi
);
4023 skip("Failed to create ShellItem.\n");
4025 ILFree(pidl_desktop
);
4028 static void test_ShellItemGetAttributes(void)
4030 IShellItem
*psi
, *psi_folder1
, *psi_file1
;
4031 IShellFolder
*pdesktopsf
;
4032 LPITEMIDLIST pidl_desktop
, pidl
;
4035 WCHAR curdirW
[MAX_PATH
];
4036 WCHAR buf
[MAX_PATH
];
4037 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4038 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4040 if(!pSHCreateShellItem
)
4042 skip("SHCreateShellItem missing.\n");
4046 hr
= SHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
4047 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4050 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
4051 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4052 ILFree(pidl_desktop
);
4056 skip("Skipping tests.\n");
4062 /* Crashes on native (Win 7) */
4063 IShellItem_GetAttributes(psi
, 0, NULL
);
4066 /* Test GetAttributes on the desktop folder. */
4068 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
4069 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
4070 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
4072 IShellItem_Release(psi
);
4074 CreateFilesFolders();
4076 SHGetDesktopFolder(&pdesktopsf
);
4078 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4079 myPathAddBackslashW(curdirW
);
4081 lstrcpyW(buf
, curdirW
);
4082 lstrcatW(buf
, testdir1W
);
4083 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4085 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_folder1
);
4086 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4089 lstrcpyW(buf
, curdirW
);
4090 lstrcatW(buf
, testfile1W
);
4091 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4092 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4093 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_file1
);
4094 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4097 IShellFolder_Release(pdesktopsf
);
4100 hr
= IShellItem_GetAttributes(psi_folder1
, 0, &sfgao
);
4101 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4102 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4105 hr
= IShellItem_GetAttributes(psi_folder1
, SFGAO_FOLDER
, &sfgao
);
4106 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4107 ok(sfgao
== SFGAO_FOLDER
, "Got 0x%08x\n", sfgao
);
4110 hr
= IShellItem_GetAttributes(psi_file1
, SFGAO_FOLDER
, &sfgao
);
4111 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
4112 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4114 IShellItem_Release(psi_folder1
);
4115 IShellItem_Release(psi_file1
);
4120 static void test_ShellItemArrayGetAttributes(void)
4122 IShellItemArray
*psia_files
, *psia_folders1
, *psia_folders2
, *psia_all
;
4123 IShellFolder
*pdesktopsf
;
4124 LPCITEMIDLIST pidl_array
[5];
4127 WCHAR curdirW
[MAX_PATH
];
4128 WCHAR buf
[MAX_PATH
];
4130 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4131 static const WCHAR testdir2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
4132 static const WCHAR testdir3W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
4133 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4134 static const WCHAR testfile2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
4135 static const WCHAR
*testfilesW
[5] = { testdir1W
, testdir2W
, testdir3W
, testfile1W
, testfile2W
};
4137 if(!pSHCreateShellItemArrayFromShellItem
)
4139 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
4143 CreateFilesFolders();
4144 CreateDirectoryA(".\\testdir\\testdir3", NULL
);
4146 SHGetDesktopFolder(&pdesktopsf
);
4148 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4149 myPathAddBackslashW(curdirW
);
4151 for(i
= 0; i
< 5; i
++)
4153 lstrcpyW(buf
, curdirW
);
4154 lstrcatW(buf
, testfilesW
[i
]);
4155 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, (LPITEMIDLIST
*)&pidl_array
[i
], NULL
);
4156 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4158 IShellFolder_Release(pdesktopsf
);
4160 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia_folders1
);
4161 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4162 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[1], &psia_folders2
);
4163 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4164 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[3], &psia_files
);
4165 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4166 hr
= pSHCreateShellItemArrayFromIDLists(4, &pidl_array
[1], &psia_all
); /* All except the first */
4167 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4169 for(i
= 0; i
< 5; i
++)
4170 ILFree((LPITEMIDLIST
)pidl_array
[i
]);
4172 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
4174 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4175 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4176 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4178 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4179 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4180 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4182 /* [testfolder/testfolder2, testfolder/testfolder3] works */
4184 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4185 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4186 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4188 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4189 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4190 ok(attr
== 0, "Got 0x%08x\n", attr
);
4192 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4193 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4194 ok(attr
== 0, "Got 0x%08x\n", attr
);
4196 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4197 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4198 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4200 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4201 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4202 ok(attr
== 0, "Got 0x%08x\n", attr
);
4204 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4205 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4206 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4208 IShellItemArray_Release(psia_folders1
);
4209 IShellItemArray_Release(psia_folders2
);
4210 IShellItemArray_Release(psia_files
);
4211 IShellItemArray_Release(psia_all
);
4213 RemoveDirectoryA(".\\testdir\\testdir3");
4217 static void test_SHParseDisplayName(void)
4219 LPITEMIDLIST pidl1
, pidl2
;
4220 IShellFolder
*desktop
;
4221 WCHAR dirW
[MAX_PATH
];
4228 /* crashes on native */
4229 SHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
4231 SHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
4234 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
4235 hr
= SHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
4236 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
4237 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
4238 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
4242 hr
= SHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
4243 ok(hr
== S_OK
, "failed %08x\n", hr
);
4244 hr
= SHGetDesktopFolder(&desktop
);
4245 ok(hr
== S_OK
, "failed %08x\n", hr
);
4246 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
4247 ok(hr
== S_OK
, "failed %08x\n", hr
);
4248 ret
= ILIsEqual(pidl1
, pidl2
);
4249 ok(ret
== TRUE
, "expected equal idls\n");
4254 GetWindowsDirectoryW( dirW
, MAX_PATH
);
4256 hr
= SHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4257 ok(hr
== S_OK
, "failed %08x\n", hr
);
4258 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
4259 ok(hr
== S_OK
, "failed %08x\n", hr
);
4261 ret
= ILIsEqual(pidl1
, pidl2
);
4262 ok(ret
== TRUE
, "expected equal idls\n");
4266 /* system32 is not redirected to syswow64 on WOW64 */
4267 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
4272 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
4273 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
4274 hr
= SHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4275 ok(hr
== S_OK
, "failed %08x\n", hr
);
4277 len
= GetSystemWow64DirectoryW(dirW
, MAX_PATH
);
4278 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
4279 hr
= SHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
4280 ok(hr
== S_OK
, "failed %08x\n", hr
);
4281 ret
= ILIsEqual(pidl1
, pidl2
);
4282 ok(ret
== FALSE
, "expected different idls\n");
4287 IShellFolder_Release(desktop
);
4290 static void test_desktop_IPersist(void)
4292 IShellFolder
*desktop
;
4294 IPersistFolder2
*ppf2
;
4298 hr
= SHGetDesktopFolder(&desktop
);
4299 ok(hr
== S_OK
, "failed %08x\n", hr
);
4301 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
4302 ok(hr
== S_OK
, "failed %08x\n", hr
);
4308 /* crashes on native */
4309 IPersist_GetClassID(persist
, NULL
);
4311 memset(&clsid
, 0, sizeof(clsid
));
4312 hr
= IPersist_GetClassID(persist
, &clsid
);
4313 ok(hr
== S_OK
, "failed %08x\n", hr
);
4314 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
4315 IPersist_Release(persist
);
4318 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
4319 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
4322 IPersistFolder
*ppf
;
4324 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
4325 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
4327 IPersistFolder_Release(ppf
);
4330 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
4331 ok(hr
== S_OK
, "got %08x\n", hr
);
4335 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
4336 ok(hr
== S_OK
, "got %08x\n", hr
);
4337 ok(pidl
!= NULL
, "pidl was NULL.\n");
4338 if(SUCCEEDED(hr
)) ILFree(pidl
);
4340 IPersistFolder2_Release(ppf2
);
4343 IShellFolder_Release(desktop
);
4346 static void test_GetUIObject(void)
4348 IShellFolder
*psf_desktop
;
4352 WCHAR path
[MAX_PATH
];
4353 const WCHAR filename
[] =
4354 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4356 GetCurrentDirectoryW(MAX_PATH
, path
);
4359 skip("GetCurrentDirectoryW returned an empty string.\n");
4362 lstrcatW(path
, filename
);
4363 SHGetDesktopFolder(&psf_desktop
);
4365 CreateFilesFolders();
4367 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4368 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4372 LPCITEMIDLIST pidl_child
;
4373 hr
= SHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
4374 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4377 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
,
4379 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4382 const int baseItem
= 0x40;
4383 HMENU hmenu
= CreatePopupMenu();
4384 INT max_id
, max_id_check
;
4386 const int id_upper_limit
= 32767;
4387 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, baseItem
, id_upper_limit
, CMF_NORMAL
);
4388 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
4389 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
4390 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
4391 count
= GetMenuItemCount(hmenu
);
4392 ok(count
, "Got %d\n", count
);
4395 for(i
= 0; i
< count
; i
++)
4399 char buf
[255], buf2
[255];
4400 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
4401 mii
.cbSize
= sizeof(MENUITEMINFOA
);
4402 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
| MIIM_STRING
;
4403 mii
.dwTypeData
= buf2
;
4404 mii
.cch
= sizeof(buf2
);
4407 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
4408 ok(res
, "Failed (last error: %d).\n", GetLastError());
4410 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
4411 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
4412 if(!(mii
.fType
& MFT_SEPARATOR
))
4414 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
4415 hr
= IContextMenu_GetCommandString(pcm
, mii
.wID
- baseItem
, GCS_VERBA
, 0, buf
, sizeof(buf
));
4416 ok(SUCCEEDED(hr
) || hr
== E_NOTIMPL
, "for id 0x%x got 0x%08x (menustr: %s)\n", mii
.wID
- baseItem
, hr
, mii
.dwTypeData
);
4418 trace("for id 0x%x got string %s (menu string: %s)\n", mii
.wID
- baseItem
, buf
, mii
.dwTypeData
);
4419 else if (hr
== E_NOTIMPL
)
4420 trace("for id 0x%x got E_NOTIMPL (menu string: %s)\n", mii
.wID
- baseItem
, mii
.dwTypeData
);
4423 max_id_check
-= baseItem
;
4424 ok((max_id_check
== max_id
) ||
4425 (max_id_check
== max_id
-1) || /* Win 7 */
4426 (max_id_check
== max_id
-2), /* Win 8 */
4427 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
4431 CMINVOKECOMMANDINFO cmi
;
4432 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
4433 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
4435 /* Attempt to execute a nonexistent command */
4436 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
4437 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4438 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4440 cmi
.lpVerb
= "foobar_wine_test";
4441 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4442 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
4443 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
4444 "Got 0x%08x\n", hr
);
4448 IContextMenu_Release(pcm
);
4450 IShellFolder_Release(psf
);
4455 IShellFolder_Release(psf_desktop
);
4459 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
4460 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
4462 LPCITEMIDLIST child
;
4463 IShellFolder
*parent
;
4469 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
4473 hr
= SHBindToParent(pidl
, &IID_IShellFolder
, (void **)&parent
, &child
);
4474 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4478 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4479 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4481 IShellFolder_Release(parent
);
4485 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4486 "Got unexpected string type: %d\n", filename
.uType
);
4487 if(filename
.uType
== STRRET_WSTR
){
4488 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4489 "didn't get expected path (%s), instead: %s\n",
4490 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4491 SHFree(U(filename
).pOleStr
);
4492 }else if(filename
.uType
== STRRET_CSTR
){
4493 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4494 "didn't get expected path (%s), instead: %s\n",
4495 wine_dbgstr_w(path
), U(filename
).cStr
);
4498 IShellFolder_Release(parent
);
4500 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4503 static void test_SHSimpleIDListFromPath(void)
4505 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4506 const CHAR adirA
[] = "C:\\sidlfpdir";
4507 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4509 LPITEMIDLIST pidl
= NULL
;
4511 br
= CreateDirectoryA(adirA
, NULL
);
4512 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4515 pidl
= SHSimpleIDListFromPath(adirW
);
4517 pidl
= SHSimpleIDListFromPath((const WCHAR
*)adirA
);
4518 verify_pidl(pidl
, adirW
);
4521 br
= RemoveDirectoryA(adirA
);
4522 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4525 pidl
= SHSimpleIDListFromPath(adirW
);
4527 pidl
= SHSimpleIDListFromPath((const WCHAR
*)adirA
);
4528 verify_pidl(pidl
, adirW
);
4532 /* IFileSystemBindData impl */
4533 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4534 REFIID riid
, void **ppv
)
4536 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4537 IsEqualIID(riid
, &IID_IUnknown
)){
4541 return E_NOINTERFACE
;
4544 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4549 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4554 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4555 const WIN32_FIND_DATAW
*pfd
)
4557 ok(0, "SetFindData called\n");
4561 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4562 WIN32_FIND_DATAW
*pfd
)
4564 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4568 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4569 WIN32_FIND_DATAW
*pfd
)
4571 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4575 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4576 WIN32_FIND_DATAW
*pfd
)
4578 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4579 *pfd
->cFileName
= 'a';
4580 *pfd
->cAlternateFileName
= 'a';
4584 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4585 WIN32_FIND_DATAW
*pfd
)
4587 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4588 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4593 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4594 WIN32_FIND_DATAW
*pfd
)
4599 static IFileSystemBindDataVtbl fsbdVtbl
= {
4600 fsbd_QueryInterface
,
4607 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4609 static void test_ParseDisplayNamePBC(void)
4611 WCHAR wFileSystemBindData
[] =
4612 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4613 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4614 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4615 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4616 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4623 /* Check if we support WCHAR functions */
4624 SetLastError(0xdeadbeef);
4625 lstrcmpiW(adirW
, adirW
);
4626 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4627 win_skip("Most W-calls are not implemented\n");
4631 hres
= SHGetDesktopFolder(&psf
);
4632 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4634 win_skip("Failed to get IShellFolder, can't run tests\n");
4638 /* fails on unknown dir with no IBindCtx */
4639 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4640 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4641 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4642 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4643 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4644 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4646 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4647 hres
= CreateBindCtx(0, &pbc
);
4648 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4650 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4651 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4652 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4653 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4654 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4655 ok(hres
== exp_err
, "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4657 /* unknown dir with IBindCtx with IFileSystemBindData */
4658 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4659 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4661 /* return E_FAIL from GetFindData */
4662 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4663 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4664 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4665 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4666 if(SUCCEEDED(hres
)){
4667 verify_pidl(pidl
, adirW
);
4671 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4672 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4673 if(SUCCEEDED(hres
)){
4674 verify_pidl(pidl
, afileW
);
4678 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4679 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4680 if(SUCCEEDED(hres
)){
4681 verify_pidl(pidl
, afile2W
);
4685 /* set FIND_DATA struct to NULLs */
4686 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4687 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4688 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4689 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4690 if(SUCCEEDED(hres
)){
4691 verify_pidl(pidl
, adirW
);
4695 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4696 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4697 if(SUCCEEDED(hres
)){
4698 verify_pidl(pidl
, afileW
);
4702 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4703 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4704 if(SUCCEEDED(hres
)){
4705 verify_pidl(pidl
, afile2W
);
4709 /* set FIND_DATA struct to junk */
4710 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4711 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4712 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4713 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4714 if(SUCCEEDED(hres
)){
4715 verify_pidl(pidl
, adirW
);
4719 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4720 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4721 if(SUCCEEDED(hres
)){
4722 verify_pidl(pidl
, afileW
);
4726 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4727 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4728 if(SUCCEEDED(hres
)){
4729 verify_pidl(pidl
, afile2W
);
4733 /* set FIND_DATA struct to invalid data */
4734 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4735 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4736 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4737 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4738 if(SUCCEEDED(hres
)){
4739 verify_pidl(pidl
, adirW
);
4743 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4744 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4745 if(SUCCEEDED(hres
)){
4746 verify_pidl(pidl
, afileW
);
4750 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4751 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4752 if(SUCCEEDED(hres
)){
4753 verify_pidl(pidl
, afile2W
);
4757 /* set FIND_DATA struct to valid data */
4758 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4759 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4760 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4761 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4762 if(SUCCEEDED(hres
)){
4763 verify_pidl(pidl
, adirW
);
4767 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4768 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4769 if(SUCCEEDED(hres
)){
4770 verify_pidl(pidl
, afileW
);
4774 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4775 ok(hres
== S_OK
, "ParseDisplayName failed: 0x%08x\n", hres
);
4776 if(SUCCEEDED(hres
)){
4777 verify_pidl(pidl
, afile2W
);
4781 IBindCtx_Release(pbc
);
4782 IShellFolder_Release(psf
);
4785 static const CHAR testwindow_class
[] = "testwindow";
4786 #define WM_USER_NOTIFY (WM_APP+1)
4788 struct ChNotifyTest
{
4790 const UINT notify_count
;
4791 UINT missing_events
;
4793 const char path_1
[256];
4794 const char path_2
[256];
4795 } chnotify_tests
[] = {
4796 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
4797 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
4798 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
4801 struct ChNotifyTest
*exp_data
;
4802 BOOL test_new_delivery_flag
;
4804 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4806 LONG signal
= (LONG
)lparam
;
4809 case WM_USER_NOTIFY
:
4810 if(exp_data
->missing_events
> 0) {
4811 WCHAR
*path1
, *path2
;
4812 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
4813 HANDLE hLock
= NULL
;
4815 if(test_new_delivery_flag
) {
4816 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
4817 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
4820 ok(exp_data
->signal
== signal
,
4821 "%s: expected notification type %x, got: %x\n",
4822 exp_data
->id
, exp_data
->signal
, signal
);
4824 trace("verifying pidls for: %s\n", exp_data
->id
);
4825 path1
= make_wstr(exp_data
->path_1
);
4826 path2
= make_wstr(exp_data
->path_2
);
4827 verify_pidl(pidls
[0], path1
);
4828 verify_pidl(pidls
[1], path2
);
4829 HeapFree(GetProcessHeap(), 0, path1
);
4830 HeapFree(GetProcessHeap(), 0, path2
);
4832 exp_data
->missing_events
--;
4834 if(test_new_delivery_flag
)
4835 SHChangeNotification_Unlock(hLock
);
4837 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4840 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
4843 static void register_testwindow_class(void)
4848 ZeroMemory(&cls
, sizeof(cls
));
4849 cls
.cbSize
= sizeof(cls
);
4851 cls
.lpfnWndProc
= testwindow_wndproc
;
4852 cls
.hInstance
= GetModuleHandleA(NULL
);
4853 cls
.lpszClassName
= testwindow_class
;
4856 ret
= RegisterClassExA(&cls
);
4857 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4860 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4861 * have to poll repeatedly for the message to appear */
4862 static void do_events(void)
4865 while (exp_data
->missing_events
&& (c
++ < 10)){
4867 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4868 TranslateMessage(&msg
);
4869 DispatchMessageA(&msg
);
4871 if(exp_data
->missing_events
)
4874 trace("%s: took %d tries\n", exp_data
->id
, c
);
4877 static void test_SHChangeNotify(BOOL test_new_delivery
)
4882 BOOL br
, has_unicode
;
4883 SHChangeNotifyEntry entries
[1];
4884 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4885 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4887 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
4889 CreateDirectoryW(NULL
, NULL
);
4890 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
4892 test_new_delivery_flag
= test_new_delivery
;
4893 if(!test_new_delivery
)
4894 register_testwindow_class();
4896 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
4897 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
4898 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
4899 ok(wnd
!= NULL
, "Failed to make a window\n");
4901 br
= CreateDirectoryA(root_dirA
, NULL
);
4902 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4904 entries
[0].pidl
= NULL
;
4906 hr
= SHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4908 hr
= SHILCreateFromPath((const void *)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4909 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
4910 entries
[0].fRecursive
= TRUE
;
4912 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
4913 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
4914 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
4916 for(i
= 0; i
< sizeof(chnotify_tests
) / sizeof(*chnotify_tests
); ++i
){
4917 exp_data
= chnotify_tests
+ i
;
4919 exp_data
->missing_events
= exp_data
->notify_count
;
4920 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
4921 exp_data
->path_1
[0] ? exp_data
->path_1
: NULL
,
4922 exp_data
->path_2
[0] ? exp_data
->path_2
: NULL
);
4924 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4927 WCHAR
*path1
, *path2
;
4929 path1
= make_wstr(exp_data
->path_1
);
4930 path2
= make_wstr(exp_data
->path_2
);
4932 exp_data
->missing_events
= exp_data
->notify_count
;
4933 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
4935 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4937 HeapFree(GetProcessHeap(), 0, path1
);
4938 HeapFree(GetProcessHeap(), 0, path2
);
4942 SHChangeNotifyDeregister(notifyID
);
4945 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
4946 br
= RemoveDirectoryA(root_dirA
);
4947 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4950 static void test_SHCreateDefaultContextMenu(void)
4953 WCHAR path
[MAX_PATH
];
4954 IShellFolder
*desktop
,*folder
;
4955 IPersistFolder2
*persist
;
4956 IContextMenu
*cmenu
;
4958 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
4959 DEFCONTEXTMENU cminfo
;
4962 const WCHAR filename
[] =
4963 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4964 if(!pSHCreateDefaultContextMenu
)
4966 win_skip("SHCreateDefaultContextMenu missing.\n");
4970 GetCurrentDirectoryW(MAX_PATH
, path
);
4973 skip("GetCurrentDirectoryW returned an empty string.\n");
4976 lstrcatW(path
, filename
);
4977 SHGetDesktopFolder(&desktop
);
4979 CreateFilesFolders();
4981 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4982 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4985 hr
= SHBindToParent(pidl
, &IID_IShellFolder
, (void **)&folder
, (const ITEMIDLIST
**)&pidl_child
);
4986 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4988 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
4989 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
4990 IPersistFolder2_Release(persist
);
4997 cminfo
.pidlFolder
=NULL
;
4998 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
5002 cminfo
.punkAssociationInfo
=NULL
;
5003 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5004 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5005 IContextMenu_Release(cmenu
);
5006 cminfo
.pidlFolder
=pidlFolder
;
5007 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5008 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5009 IContextMenu_Release(cmenu
);
5010 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
5011 if(status
==ERROR_SUCCESS
){
5016 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5017 RegCloseKey(keys
[0]);
5018 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5019 IContextMenu_Release(cmenu
);
5023 IShellFolder_Release(folder
);
5025 IShellFolder_Release(desktop
);
5030 static void test_DataObject(void)
5032 IShellFolder
*desktop
;
5033 IDataObject
*data_obj
;
5038 DWORD cf_shellidlist
;
5041 SHGetDesktopFolder(&desktop
);
5043 hres
= IShellFolder_EnumObjects(desktop
, NULL
,
5044 SHCONTF_NONFOLDERS
|SHCONTF_FOLDERS
|SHCONTF_INCLUDEHIDDEN
, &peidl
);
5045 ok(hres
== S_OK
, "got %x\n", hres
);
5047 if(IEnumIDList_Next(peidl
, 1, &apidl
, NULL
) != S_OK
) {
5048 skip("no files on desktop - skipping GetDataObject tests\n");
5049 IEnumIDList_Release(peidl
);
5050 IShellFolder_Release(desktop
);
5053 IEnumIDList_Release(peidl
);
5055 hres
= IShellFolder_GetUIObjectOf(desktop
, NULL
, 1, (LPCITEMIDLIST
*)&apidl
,
5056 &IID_IDataObject
, NULL
, (void**)&data_obj
);
5057 ok(hres
== S_OK
, "got %x\n", hres
);
5059 IShellFolder_Release(desktop
);
5061 cf_shellidlist
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
5062 fmt
.cfFormat
= cf_shellidlist
;
5064 fmt
.dwAspect
= DVASPECT_CONTENT
;
5066 fmt
.tymed
= TYMED_HGLOBAL
;
5067 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5068 ok(hres
== S_OK
, "got %x\n", hres
);
5070 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5071 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5072 ok(hres
== S_OK
, "got %x\n", hres
);
5074 fmt
.tymed
= TYMED_ISTREAM
;
5075 hres
= IDataObject_QueryGetData(data_obj
, &fmt
);
5076 todo_wine
ok(hres
== S_FALSE
, "got %x\n", hres
);
5078 fmt
.tymed
= TYMED_HGLOBAL
| TYMED_ISTREAM
;
5079 hres
= IDataObject_GetData(data_obj
, &fmt
, &medium
);
5080 ok(hres
== S_OK
, "got %x\n", hres
);
5081 ok(medium
.tymed
== TYMED_HGLOBAL
, "medium.tymed = %x\n", medium
.tymed
);
5082 ReleaseStgMedium(&medium
);
5084 IDataObject_Release(data_obj
);
5087 static void test_GetDefaultColumn(void)
5089 static const CLSID
*folders
[] =
5093 &CLSID_ControlPanel
,
5094 &CLSID_NetworkPlaces
,
5097 &CLSID_ShellDesktop
,
5104 for (i
= 0; i
< sizeof(folders
)/sizeof(folders
[0]); i
++)
5106 IShellFolder2
*folder
;
5107 ULONG sort
, display
;
5109 hr
= CoCreateInstance(folders
[i
], NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellFolder2
, (void **)&folder
);
5112 win_skip("Failed to create folder %s, hr %#x.\n", wine_dbgstr_guid(folders
[i
]), hr
);
5116 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, NULL
, NULL
);
5117 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5119 sort
= display
= 123;
5120 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, &sort
, &display
);
5121 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5122 ok(sort
== 123 && display
== 123, "Unexpected default column.\n");
5125 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, NULL
, &display
);
5126 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5127 ok(display
== 123, "Unexpected default column.\n");
5130 hr
= IShellFolder2_GetDefaultColumn(folder
, 0, &sort
, NULL
);
5131 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5132 ok(sort
== 123, "Unexpected default column.\n");
5138 static void test_GetDefaultSearchGUID(void)
5140 static const CLSID
*folders
[] =
5144 &CLSID_ControlPanel
,
5145 &CLSID_NetworkPlaces
,
5148 &CLSID_ShellDesktop
,
5155 for (i
= 0; i
< sizeof(folders
)/sizeof(folders
[0]); i
++)
5157 IShellFolder2
*folder
;
5160 hr
= CoCreateInstance(folders
[i
], NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellFolder2
, (void **)&folder
);
5163 win_skip("Failed to create folder %s, hr %#x.\n", wine_dbgstr_guid(folders
[i
]), hr
);
5170 hr
= IShellFolder2_GetDefaultSearchGUID(folder
, NULL
);
5171 ok(hr
== E_NOTIMPL
, "Unexpected hr %#x.\n", hr
);
5174 memcpy(&guid
, &CLSID_MyComputer
, sizeof(guid
));
5175 hr
= IShellFolder2_GetDefaultSearchGUID(folder
, &guid
);
5176 ok(hr
== E_NOTIMPL
|| broken(hr
== S_OK
) /* Method was last supported on XP */, "Unexpected hr %#x.\n", hr
);
5177 if (hr
== E_NOTIMPL
)
5178 ok(IsEqualGUID(&guid
, &CLSID_MyComputer
), "Unexpected guid %s.\n", wine_dbgstr_guid(&guid
));
5180 IShellFolder2_Release(folder
);
5186 START_TEST(shlfolder
)
5188 init_function_pointers();
5189 /* if OleInitialize doesn't get called, ParseDisplayName returns
5190 CO_E_NOTINITIALIZED for malformed directory names */
5191 OleInitialize(NULL
);
5193 test_ParseDisplayName();
5194 test_SHParseDisplayName();
5195 test_BindToObject();
5196 test_EnumObjects_and_CompareIDs();
5197 test_GetDisplayName();
5198 test_GetAttributesOf();
5199 test_SHGetPathFromIDList();
5200 test_CallForAttributes();
5201 test_FolderShortcut();
5202 test_ITEMIDLIST_format();
5203 test_SHGetFolderPathA();
5204 test_SHGetFolderPathAndSubDirA();
5205 test_LocalizedNames();
5206 test_SHCreateShellItem();
5207 test_SHCreateShellItemArray();
5208 test_ShellItemArrayEnumItems();
5209 test_desktop_IPersist();
5211 test_SHSimpleIDListFromPath();
5212 test_ParseDisplayNamePBC();
5213 test_SHGetNameFromIDList();
5214 test_SHGetItemFromDataObject();
5215 test_SHGetIDListFromObject();
5216 test_SHGetItemFromObject();
5217 test_ShellItemCompare();
5218 test_SHChangeNotify(FALSE
);
5219 test_SHChangeNotify(TRUE
);
5220 test_ShellItemBindToHandler();
5221 test_ShellItemGetAttributes();
5222 test_ShellItemArrayGetAttributes();
5223 test_SHCreateDefaultContextMenu();
5225 test_GetDefaultColumn();
5226 test_GetDefaultSearchGUID();