2 * Unit test of the IShellFolder functions.
4 * Copyright 2004 Vitaliy Margolen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
40 #include "wine/test.h"
43 DEFINE_GUID(IID_IParentAndItem
, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
44 DEFINE_GUID(CLSID_ShellDocObjView
, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
48 static HRESULT (WINAPI
*pSHBindToParent
)(LPCITEMIDLIST
, REFIID
, LPVOID
*, LPCITEMIDLIST
*);
49 static HRESULT (WINAPI
*pSHGetFolderPathA
)(HWND
, int, HANDLE
, DWORD
, LPSTR
);
50 static HRESULT (WINAPI
*pSHGetFolderPathAndSubDirA
)(HWND
, int, HANDLE
, DWORD
, LPCSTR
, LPSTR
);
51 static BOOL (WINAPI
*pSHGetPathFromIDListW
)(LPCITEMIDLIST
,LPWSTR
);
52 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
53 static BOOL (WINAPI
*pSHGetSpecialFolderPathA
)(HWND
, LPSTR
, int, BOOL
);
54 static BOOL (WINAPI
*pSHGetSpecialFolderPathW
)(HWND
, LPWSTR
, int, BOOL
);
55 static HRESULT (WINAPI
*pStrRetToBufW
)(STRRET
*,LPCITEMIDLIST
,LPWSTR
,UINT
);
56 static LPITEMIDLIST (WINAPI
*pILFindLastID
)(LPCITEMIDLIST
);
57 static void (WINAPI
*pILFree
)(LPITEMIDLIST
);
58 static BOOL (WINAPI
*pILIsEqual
)(LPCITEMIDLIST
, LPCITEMIDLIST
);
59 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
60 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
61 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
62 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
63 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
64 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
65 static LPITEMIDLIST (WINAPI
*pILCombine
)(LPCITEMIDLIST
,LPCITEMIDLIST
);
66 static HRESULT (WINAPI
*pSHParseDisplayName
)(LPCWSTR
,IBindCtx
*,LPITEMIDLIST
*,SFGAOF
,SFGAOF
*);
67 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathAW
)(LPCVOID
);
68 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
69 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
70 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
71 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
72 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
74 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
77 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
78 return lstrcmpA(stra
, buf
);
81 static void init_function_pointers(void)
87 hmod
= GetModuleHandleA("shell32.dll");
89 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
90 MAKEFUNC(SHBindToParent
);
91 MAKEFUNC(SHCreateItemFromIDList
);
92 MAKEFUNC(SHCreateItemFromParsingName
);
93 MAKEFUNC(SHCreateShellItem
);
94 MAKEFUNC(SHCreateShellItemArray
);
95 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
96 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
97 MAKEFUNC(SHGetFolderPathA
);
98 MAKEFUNC(SHGetFolderPathAndSubDirA
);
99 MAKEFUNC(SHGetPathFromIDListW
);
100 MAKEFUNC(SHGetSpecialFolderPathA
);
101 MAKEFUNC(SHGetSpecialFolderPathW
);
102 MAKEFUNC(SHGetSpecialFolderLocation
);
103 MAKEFUNC(SHParseDisplayName
);
104 MAKEFUNC(SHGetNameFromIDList
);
105 MAKEFUNC(SHGetItemFromDataObject
);
106 MAKEFUNC(SHGetIDListFromObject
);
107 MAKEFUNC(SHGetItemFromObject
);
110 #define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
111 MAKEFUNC_ORD(ILFindLastID
, 16);
112 MAKEFUNC_ORD(ILIsEqual
, 21);
113 MAKEFUNC_ORD(ILCombine
, 25);
114 MAKEFUNC_ORD(ILFree
, 155);
115 MAKEFUNC_ORD(SHSimpleIDListFromPathAW
, 162);
118 /* test named exports */
119 ptr
= GetProcAddress(hmod
, "ILFree");
120 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
123 #define TESTNAMED(f) \
124 ptr = (void*)GetProcAddress(hmod, #f); \
125 ok(ptr != 0, "expected named export for " #f "\n");
127 TESTNAMED(ILAppendID
);
129 TESTNAMED(ILCloneFirst
);
130 TESTNAMED(ILCombine
);
131 TESTNAMED(ILCreateFromPath
);
132 TESTNAMED(ILCreateFromPathA
);
133 TESTNAMED(ILCreateFromPathW
);
134 TESTNAMED(ILFindChild
);
135 TESTNAMED(ILFindLastID
);
136 TESTNAMED(ILGetNext
);
137 TESTNAMED(ILGetSize
);
138 TESTNAMED(ILIsEqual
);
139 TESTNAMED(ILIsParent
);
140 TESTNAMED(ILRemoveLastID
);
141 TESTNAMED(ILSaveToStream
);
145 hmod
= GetModuleHandleA("shlwapi.dll");
146 pStrRetToBufW
= (void*)GetProcAddress(hmod
, "StrRetToBufW");
148 pIsWow64Process
= (void*)GetProcAddress(GetModuleHandleA("kernel32.dll"), "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 /* Tests crash on W2K and below (SHCreateShellItem available as of XP) */
192 if (pSHCreateShellItem
)
194 /* null name and pidl */
195 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
196 NULL
, NULL
, NULL
, NULL
, NULL
, 0);
197 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
200 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
201 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
202 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
203 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
204 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
207 win_skip("Tests would crash on W2K and below\n");
209 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
210 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
211 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
212 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
213 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
216 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
217 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(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
|| broken(hr
== E_FAIL
) /* NT4 */,
225 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
228 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
229 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
230 IMalloc_Free(ppM
, newPIDL
);
233 res
= GetFileAttributesA(cNonExistDir1A
);
234 if(res
!= INVALID_FILE_ATTRIBUTES
)
236 skip("Test directory unexpectedly exists\n");
240 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
241 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
242 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
243 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
),
244 "ParseDisplayName returned %08x, expected 80070002 or E_FAIL\n", hr
);
246 res
= GetFileAttributesA(cNonExistDir2A
);
247 if(res
!= INVALID_FILE_ATTRIBUTES
)
249 skip("Test directory unexpectedly exists\n");
253 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
254 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
255 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
256 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
257 "ParseDisplayName returned %08x, expected 80070002, E_FAIL or E_INVALIDARG\n", hr
);
259 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
260 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
261 * out it doesn't. The magic seems to happen in the file dialogs, then. */
262 if (!pSHGetSpecialFolderPathW
|| !pILFindLastID
)
264 win_skip("SHGetSpecialFolderPathW and/or ILFindLastID are not available\n");
268 bRes
= pSHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
269 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
270 if (!bRes
) goto finished
;
272 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
273 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
274 if (hr
!= S_OK
) goto finished
;
276 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31 ||
277 pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0xb1, /* Win98 */
278 "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
279 pILFindLastID(newPIDL
)->mkid
.abID
[0]);
280 IMalloc_Free(ppM
, newPIDL
);
283 IShellFolder_Release(IDesktopFolder
);
286 /* creates a file with the specified name for tests */
287 static void CreateTestFile(const CHAR
*name
)
292 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
293 if (file
!= INVALID_HANDLE_VALUE
)
295 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
296 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
302 /* initializes the tests */
303 static void CreateFilesFolders(void)
305 CreateDirectoryA(".\\testdir", NULL
);
306 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
307 CreateTestFile (".\\testdir\\test1.txt ");
308 CreateTestFile (".\\testdir\\test2.txt ");
309 CreateTestFile (".\\testdir\\test3.txt ");
310 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
311 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
314 /* cleans after tests */
315 static void Cleanup(void)
317 DeleteFileA(".\\testdir\\test1.txt");
318 DeleteFileA(".\\testdir\\test2.txt");
319 DeleteFileA(".\\testdir\\test3.txt");
320 RemoveDirectoryA(".\\testdir\\test.txt");
321 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
322 RemoveDirectoryA(".\\testdir\\testdir2");
323 RemoveDirectoryA(".\\testdir");
328 static void test_EnumObjects(IShellFolder
*iFolder
)
330 IEnumIDList
*iEnumList
;
331 LPITEMIDLIST newPIDL
, idlArr
[10];
336 static const WORD iResults
[5][5] =
345 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
346 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
347 static const ULONG attrs
[5] =
349 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
350 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
351 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
352 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
353 SFGAO_CAPABILITYMASK
| 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_FILESYSANCESTOR
) || /* Win9x, NT4 */
397 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
398 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
400 flags
= SFGAO_testfor
;
401 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
402 flags
&= SFGAO_testfor
;
403 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
404 ok(flags
== attrs
[i
] ||
405 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
), /* Win9x, NT4 */
406 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
410 IMalloc_Free(ppM
, idlArr
[i
]);
413 static void test_BindToObject(void)
417 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
418 SHITEMID emptyitem
= { 0, { 0 } };
419 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
420 WCHAR wszSystemDir
[MAX_PATH
];
421 char szSystemDir
[MAX_PATH
];
424 WCHAR path
[MAX_PATH
];
426 WCHAR wszMyComputer
[] = {
427 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
428 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
429 static const WCHAR filename_html
[] = {'w','i','n','e','t','e','s','t','.','h','t','m','l',0};
430 static const WCHAR filename_txt
[] = {'w','i','n','e','t','e','s','t','.','t','x','t',0};
431 static const WCHAR filename_foo
[] = {'w','i','n','e','t','e','s','t','.','f','o','o',0};
433 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
434 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
436 hr
= SHGetDesktopFolder(&psfDesktop
);
437 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
438 if (hr
!= S_OK
) return;
440 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
441 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
443 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
444 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
446 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
447 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
449 IShellFolder_Release(psfDesktop
);
453 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
454 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
455 IShellFolder_Release(psfDesktop
);
456 IMalloc_Free(ppM
, pidlMyComputer
);
457 if (hr
!= S_OK
) return;
459 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
460 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
464 /* this call segfaults on 98SE */
465 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
466 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
469 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
470 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
471 if (cChars
== 0 || cChars
>= MAX_PATH
) {
472 IShellFolder_Release(psfMyComputer
);
475 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
477 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
478 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
480 IShellFolder_Release(psfMyComputer
);
484 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
485 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
486 IShellFolder_Release(psfMyComputer
);
487 IMalloc_Free(ppM
, pidlSystemDir
);
488 if (hr
!= S_OK
) return;
490 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
491 ok (hr
== E_INVALIDARG
,
492 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
496 /* this call segfaults on 98SE */
497 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
498 ok (hr
== E_INVALIDARG
,
499 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
502 IShellFolder_Release(psfSystemDir
);
504 GetCurrentDirectoryA(MAX_PATH
, buf
);
507 skip("Failed to get current directory, skipping tests.\n");
510 MultiByteToWideChar(CP_ACP
, 0, buf
, -1, cwd
, MAX_PATH
);
512 SHGetDesktopFolder(&psfDesktop
);
514 /* Attempt BindToObject on files. */
518 myPathAddBackslashW(path
);
519 lstrcatW(path
, filename_html
);
520 hfile
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
521 if(hfile
!= (HANDLE
)INVALID_FILE_ATTRIBUTES
)
524 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
526 broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* Win98SE */ ||
527 broken(hr
== E_FAIL
) /* Win95 */,
531 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
532 ok(hr
== S_OK
/* Win 7 */ || hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) /* WinXP */,
537 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
538 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* W2K */, "Got 0x%08x\n", hr
);
542 hr
= IPersist_GetClassID(pp
, &id
);
543 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
544 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
), "Unexpected classid\n");
545 IPersist_Release(pp
);
548 IShellFolder_Release(psfChild
);
555 win_skip("Failed to create .html testfile.\n");
559 myPathAddBackslashW(path
);
560 lstrcatW(path
, filename_txt
);
561 hfile
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
562 if(hfile
!= (HANDLE
)INVALID_FILE_ATTRIBUTES
)
565 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
567 broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* Win98SE */ ||
568 broken(hr
== E_FAIL
) /* Win95 */,
572 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
573 ok(hr
== E_FAIL
|| hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)
574 || broken(hr
== S_OK
) /* W2K */,
576 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
582 win_skip("Failed to create .txt testfile.\n");
586 myPathAddBackslashW(path
);
587 lstrcatW(path
, filename_foo
);
588 hfile
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
589 if(hfile
!= (HANDLE
)INVALID_FILE_ATTRIBUTES
)
592 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
594 broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* Win98SE */ ||
595 broken(hr
== E_FAIL
) /* Win95 */,
599 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
600 ok(hr
== E_FAIL
|| hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)
601 || broken(hr
== S_OK
) /* W2K */,
603 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
609 win_skip("Failed to create .foo testfile.\n");
611 /* And on the desktop */
612 if(pSHGetSpecialFolderPathW
)
615 pSHGetSpecialFolderPathW(NULL
, path
, CSIDL_DESKTOP
, FALSE
);
616 myPathAddBackslashW(path
);
617 lstrcatW(path
, filename_html
);
618 hfile
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
619 if(hfile
!= (HANDLE
)INVALID_FILE_ATTRIBUTES
)
622 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
623 ok(hr
== S_OK
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* Win98SE */,
627 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
628 ok(hr
== S_OK
|| hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
630 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
633 if(!DeleteFileW(path
))
634 trace("Failed to delete: %d\n", GetLastError());
638 win_skip("Failed to create .html testfile.\n");
640 pSHGetSpecialFolderPathW(NULL
, path
, CSIDL_DESKTOP
, FALSE
);
641 myPathAddBackslashW(path
);
642 lstrcatW(path
, filename_foo
);
643 hfile
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
644 if(hfile
!= (HANDLE
)INVALID_FILE_ATTRIBUTES
)
647 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
648 ok(hr
== S_OK
|| broken(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) /* Win98SE */,
652 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
653 ok(hr
== E_FAIL
|| hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)
654 || broken(hr
== S_OK
) /* W2K */,
656 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
662 win_skip("Failed to create .foo testfile.\n");
665 IShellFolder_Release(psfDesktop
);
668 static void test_GetDisplayName(void)
673 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
674 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
677 LPSHELLFOLDER psfDesktop
, psfPersonal
;
679 SHITEMID emptyitem
= { 0, { 0 } };
680 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
681 LPCITEMIDLIST pidlLast
;
682 static const CHAR szFileName
[] = "winetest.foo";
683 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
684 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
686 /* I'm trying to figure if there is a functional difference between calling
687 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
688 * binding to the shellfolder. One thing I thought of was that perhaps
689 * SHGetPathFromIDListW would be able to get the path to a file, which does
690 * not exist anymore, while the other method wouldn't. It turns out there's
691 * no functional difference in this respect.
694 if(!pSHGetSpecialFolderPathA
) {
695 win_skip("SHGetSpecialFolderPathA is not available\n");
699 /* First creating a directory in MyDocuments and a file in this directory. */
700 result
= pSHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
701 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
704 /* Use ANSI file functions so this works on Windows 9x */
705 lstrcatA(szTestDir
, "\\winetest");
706 CreateDirectoryA(szTestDir
, NULL
);
707 attr
=GetFileAttributesA(szTestDir
);
708 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
710 ok(0, "unable to create the '%s' directory\n", szTestDir
);
714 lstrcpyA(szTestFile
, szTestDir
);
715 lstrcatA(szTestFile
, "\\");
716 lstrcatA(szTestFile
, szFileName
);
717 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
718 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
719 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
720 CloseHandle(hTestFile
);
722 /* Getting an itemidlist for the file. */
723 hr
= SHGetDesktopFolder(&psfDesktop
);
724 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
725 if (hr
!= S_OK
) return;
727 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
729 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
730 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
732 IShellFolder_Release(psfDesktop
);
736 pidlLast
= pILFindLastID(pidlTestFile
);
737 ok(pidlLast
->mkid
.cb
>=76 ||
738 broken(pidlLast
->mkid
.cb
== 28) || /* W2K */
739 broken(pidlLast
->mkid
.cb
== 40), /* Win9x, WinME */
740 "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
741 if (pidlLast
->mkid
.cb
>= 28) {
742 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
743 "Filename should be stored as ansi-string at this position!\n");
745 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
746 if (pidlLast
->mkid
.cb
>= 76) {
747 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
748 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
749 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)), /* Win7 */
750 "Filename should be stored as wchar-string at this position!\n");
753 /* It seems as if we cannot bind to regular files on windows, but only directories.
755 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
756 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
757 hr
== E_NOTIMPL
|| /* Vista */
758 broken(hr
== S_OK
), /* Win9x, W2K */
761 IShellFolder_Release(psfFile
);
764 if (!pSHBindToParent
)
766 win_skip("SHBindToParent is missing\n");
767 DeleteFileA(szTestFile
);
768 RemoveDirectoryA(szTestDir
);
772 /* Some tests for IShellFolder::SetNameOf */
773 if (pSHGetFolderPathAndSubDirA
)
775 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
776 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
778 /* It's ok to use this fixed path. Call will fail anyway. */
779 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
780 LPITEMIDLIST pidlNew
;
782 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
783 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
784 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
787 ok (((LPITEMIDLIST
)((LPBYTE
)pidlNew
+pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
788 "pidl returned from SetNameOf should be simple!\n");
790 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
791 * is implemented on top of SHFileOperation in WinXP. */
792 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
,
793 SHGDN_FORPARSING
, NULL
);
794 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
796 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
797 * SHGDN flags specify an absolute path. */
798 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
799 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
804 IShellFolder_Release(psfPersonal
);
808 win_skip("Avoid needs of interaction on Win2k\n");
810 /* Deleting the file and the directory */
811 DeleteFileA(szTestFile
);
812 RemoveDirectoryA(szTestDir
);
814 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
815 if (pSHGetPathFromIDListW
)
817 result
= pSHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
818 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
819 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
822 /* SHBindToParent fails, if called with a NULL PIDL. */
823 hr
= pSHBindToParent(NULL
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
824 ok (hr
!= S_OK
, "SHBindToParent(NULL) should fail!\n");
826 /* But it succeeds with an empty PIDL. */
827 hr
= pSHBindToParent(pidlEmpty
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
828 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
829 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
831 IShellFolder_Release(psfPersonal
);
833 /* Binding to the folder and querying the display name of the file also works. */
834 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
835 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
837 IShellFolder_Release(psfDesktop
);
841 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
842 * pidlTestFile (In accordance with MSDN). */
843 ok (pILFindLastID(pidlTestFile
) == pidlLast
,
844 "SHBindToParent doesn't return the last id of the pidl param!\n");
846 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
847 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
849 IShellFolder_Release(psfDesktop
);
850 IShellFolder_Release(psfPersonal
);
856 hr
= pStrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
857 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
858 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
861 ILFree(pidlTestFile
);
862 IShellFolder_Release(psfDesktop
);
863 IShellFolder_Release(psfPersonal
);
866 static void test_CallForAttributes(void)
872 LPSHELLFOLDER psfDesktop
;
873 LPITEMIDLIST pidlMyDocuments
;
874 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
875 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
876 static const WCHAR wszCallForAttributes
[] = {
877 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
878 static const WCHAR wszMyDocumentsKey
[] = {
879 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
880 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
881 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
882 WCHAR wszMyDocuments
[] = {
883 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
884 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
886 /* For the root of a namespace extension, the attributes are not queried by binding
887 * to the object and calling GetAttributesOf. Instead, the attributes are read from
888 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
890 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
891 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
892 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
893 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
895 hr
= SHGetDesktopFolder(&psfDesktop
);
896 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
897 if (hr
!= S_OK
) return;
899 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
900 &pidlMyDocuments
, NULL
);
902 broken(hr
== E_INVALIDARG
), /* Win95, NT4 */
903 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
905 IShellFolder_Release(psfDesktop
);
909 dwAttributes
= 0xffffffff;
910 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
911 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
912 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
914 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
915 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
916 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
917 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
919 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
920 * key. So the test will return at this point, if run on wine.
922 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
923 ok (lResult
== ERROR_SUCCESS
||
924 lResult
== ERROR_ACCESS_DENIED
,
925 "RegOpenKeyEx failed! result: %08x\n", lResult
);
926 if (lResult
!= ERROR_SUCCESS
) {
927 if (lResult
== ERROR_ACCESS_DENIED
)
928 skip("Not enough rights to open the registry key\n");
929 IMalloc_Free(ppM
, pidlMyDocuments
);
930 IShellFolder_Release(psfDesktop
);
934 /* Query MyDocuments' Attributes value, to be able to restore it later. */
935 dwSize
= sizeof(DWORD
);
936 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
937 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
938 if (lResult
!= ERROR_SUCCESS
) {
940 IMalloc_Free(ppM
, pidlMyDocuments
);
941 IShellFolder_Release(psfDesktop
);
945 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
946 dwSize
= sizeof(DWORD
);
947 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
948 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
949 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
950 if (lResult
!= ERROR_SUCCESS
) {
952 IMalloc_Free(ppM
, pidlMyDocuments
);
953 IShellFolder_Release(psfDesktop
);
957 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
958 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
959 * SFGAO_FILESYSTEM attributes. */
960 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
961 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
962 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
963 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
964 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
966 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
967 * GetAttributesOf. It seems that once there is a single attribute queried, for which
968 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
969 * the flags in Attributes are ignored.
971 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
972 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
973 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
974 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
976 ok (dwAttributes
== SFGAO_FILESYSTEM
,
977 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
980 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
981 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
982 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
983 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
985 IMalloc_Free(ppM
, pidlMyDocuments
);
986 IShellFolder_Release(psfDesktop
);
989 static void test_GetAttributesOf(void)
992 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
993 SHITEMID emptyitem
= { 0, { 0 } };
994 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
995 LPITEMIDLIST pidlMyComputer
;
997 static const DWORD desktopFlags
[] = {
999 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
|
1000 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1002 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_STREAM
| SFGAO_FILESYSANCESTOR
|
1003 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1004 /* WinMe, Win9x, WinNT*/
1005 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSANCESTOR
|
1006 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1008 static const DWORD myComputerFlags
[] = {
1010 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
1011 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1013 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_STREAM
|
1014 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1015 /* WinMe, Win9x, WinNT */
1016 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1017 SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1018 /* Win95, WinNT when queried directly */
1019 SFGAO_CANLINK
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1020 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1022 WCHAR wszMyComputer
[] = {
1023 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1024 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1025 char cCurrDirA
[MAX_PATH
] = {0};
1026 WCHAR cCurrDirW
[MAX_PATH
];
1027 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
1028 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1029 ITEMIDLIST
*newPIDL
;
1031 BOOL foundFlagsMatch
;
1033 hr
= SHGetDesktopFolder(&psfDesktop
);
1034 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1035 if (hr
!= S_OK
) return;
1037 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
1038 dwFlags
= 0xffffffff;
1039 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
1040 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
1041 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1042 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1044 if (desktopFlags
[i
] == dwFlags
)
1045 foundFlagsMatch
= TRUE
;
1047 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1049 /* .. or with no itemidlist at all. */
1050 dwFlags
= 0xffffffff;
1051 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
1052 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1053 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1054 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1056 if (desktopFlags
[i
] == dwFlags
)
1057 foundFlagsMatch
= TRUE
;
1059 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1061 /* Testing the attributes of the MyComputer shellfolder */
1062 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1063 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1065 IShellFolder_Release(psfDesktop
);
1069 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
1070 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
1072 dwFlags
= 0xffffffff;
1073 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
1074 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
1075 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1076 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1078 if ((myComputerFlags
[i
] | SFGAO_CANLINK
) == dwFlags
)
1079 foundFlagsMatch
= TRUE
;
1082 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1084 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
1085 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
1086 IShellFolder_Release(psfDesktop
);
1087 IMalloc_Free(ppM
, pidlMyComputer
);
1088 if (hr
!= S_OK
) return;
1090 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
1092 ok (hr
== E_INVALIDARG
||
1093 broken(hr
== S_OK
), /* W2K and earlier */
1094 "MyComputer->GetAttributesOf(emtpy pidl) should fail! hr = %08x\n", hr
);
1096 dwFlags
= 0xffffffff;
1097 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
1098 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1099 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1100 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1102 if (myComputerFlags
[i
] == dwFlags
)
1103 foundFlagsMatch
= TRUE
;
1106 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1108 IShellFolder_Release(psfMyComputer
);
1110 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1111 len
= lstrlenA(cCurrDirA
);
1114 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1117 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1118 cCurrDirA
[len
-1] = 0;
1120 /* create test directory */
1121 CreateFilesFolders();
1123 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1125 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1126 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1128 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1129 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1131 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1132 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1134 IMalloc_Free(ppM
, newPIDL
);
1136 /* get relative PIDL */
1137 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1138 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1140 /* test the shell attributes of the test directory using the relative PIDL */
1141 dwFlags
= SFGAO_FOLDER
;
1142 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1143 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1144 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1147 IMalloc_Free(ppM
, newPIDL
);
1149 /* append testdirectory name to path */
1150 if (cCurrDirA
[len
-1] == '\\')
1151 cCurrDirA
[len
-1] = 0;
1152 lstrcatA(cCurrDirA
, "\\testdir");
1153 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1155 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1156 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1158 /* test the shell attributes of the test directory using the absolute PIDL */
1159 dwFlags
= SFGAO_FOLDER
;
1160 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1161 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1162 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1165 IMalloc_Free(ppM
, newPIDL
);
1167 IShellFolder_Release(testIShellFolder
);
1171 IShellFolder_Release(IDesktopFolder
);
1174 static void test_SHGetPathFromIDList(void)
1176 SHITEMID emptyitem
= { 0, { 0 } };
1177 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1178 LPITEMIDLIST pidlMyComputer
;
1179 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1182 LPSHELLFOLDER psfDesktop
;
1183 WCHAR wszMyComputer
[] = {
1184 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1185 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1186 WCHAR wszFileName
[MAX_PATH
];
1187 LPITEMIDLIST pidlTestFile
;
1190 static WCHAR wszTestFile
[] = {
1191 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1192 LPITEMIDLIST pidlPrograms
;
1194 if(!pSHGetPathFromIDListW
|| !pSHGetSpecialFolderPathW
)
1196 win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
1200 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1203 result
= pSHGetPathFromIDListW(NULL
, wszPath
);
1204 ok(!result
, "Expected failure\n");
1205 ok(!wszPath
[0], "Expected empty string\n");
1207 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1208 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1209 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1210 if (!result
) return;
1212 /* Check if we are on Win9x */
1213 SetLastError(0xdeadbeef);
1214 lstrcmpiW(wszDesktop
, wszDesktop
);
1215 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1217 win_skip("Most W-calls are not implemented\n");
1221 result
= pSHGetPathFromIDListW(pidlEmpty
, wszPath
);
1222 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1223 if (!result
) return;
1224 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1226 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1227 hr
= SHGetDesktopFolder(&psfDesktop
);
1228 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1229 if (hr
!= S_OK
) return;
1231 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1232 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1234 IShellFolder_Release(psfDesktop
);
1238 SetLastError(0xdeadbeef);
1241 result
= pSHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1242 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1243 ok (GetLastError()==0xdeadbeef ||
1244 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1245 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1246 ok (!wszPath
[0], "Expected empty path\n");
1248 IShellFolder_Release(psfDesktop
);
1252 IMalloc_Free(ppM
, pidlMyComputer
);
1254 result
= pSHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1255 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1257 IShellFolder_Release(psfDesktop
);
1260 myPathAddBackslashW(wszFileName
);
1261 lstrcatW(wszFileName
, wszTestFile
);
1262 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1263 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1264 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1265 IShellFolder_Release(psfDesktop
);
1268 CloseHandle(hTestFile
);
1270 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1271 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1273 IShellFolder_Release(psfDesktop
);
1274 DeleteFileW(wszFileName
);
1275 IMalloc_Free(ppM
, pidlTestFile
);
1279 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1280 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1281 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1282 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1283 IShellFolder_Release(psfDesktop
);
1284 DeleteFileW(wszFileName
);
1286 IMalloc_Free(ppM
, pidlTestFile
);
1291 pStrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1292 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1293 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1294 "returned incorrect path for file placed on desktop\n");
1297 result
= pSHGetPathFromIDListW(pidlTestFile
, wszPath
);
1298 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1299 IMalloc_Free(ppM
, pidlTestFile
);
1300 if (!result
) return;
1301 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1304 /* Test if we can get the path from the start menu "program files" PIDL. */
1305 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1306 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1308 SetLastError(0xdeadbeef);
1309 result
= pSHGetPathFromIDListW(pidlPrograms
, wszPath
);
1310 IMalloc_Free(ppM
, pidlPrograms
);
1311 ok(result
, "SHGetPathFromIDListW failed\n");
1314 static void test_EnumObjects_and_CompareIDs(void)
1316 ITEMIDLIST
*newPIDL
;
1317 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1318 char cCurrDirA
[MAX_PATH
] = {0};
1319 static const CHAR cTestDirA
[] = "\\testdir";
1320 WCHAR cTestDirW
[MAX_PATH
];
1324 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1325 len
= lstrlenA(cCurrDirA
);
1328 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1331 if(cCurrDirA
[len
-1] == '\\')
1332 cCurrDirA
[len
-1] = 0;
1334 lstrcatA(cCurrDirA
, cTestDirA
);
1335 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1337 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1338 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1340 CreateFilesFolders();
1342 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1343 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1345 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1346 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1348 test_EnumObjects(testIShellFolder
);
1350 IShellFolder_Release(testIShellFolder
);
1354 IMalloc_Free(ppM
, newPIDL
);
1356 IShellFolder_Release(IDesktopFolder
);
1359 /* A simple implementation of an IPropertyBag, which returns fixed values for
1360 * 'Target' and 'Attributes' properties.
1362 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1366 return E_INVALIDARG
;
1368 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1371 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1372 return E_NOINTERFACE
;
1375 IPropertyBag_AddRef(iface
);
1379 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1383 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1387 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1388 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1390 static const WCHAR wszTargetSpecialFolder
[] = {
1391 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1392 static const WCHAR wszTarget
[] = {
1393 'T','a','r','g','e','t',0 };
1394 static const WCHAR wszAttributes
[] = {
1395 'A','t','t','r','i','b','u','t','e','s',0 };
1396 static const WCHAR wszResolveLinkFlags
[] = {
1397 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1398 static const WCHAR wszTargetKnownFolder
[] = {
1399 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1400 static const WCHAR wszCLSID
[] = {
1401 'C','L','S','I','D',0 };
1403 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1404 ok(V_VT(pVar
) == VT_I4
||
1405 broken(V_VT(pVar
) == VT_BSTR
), /* Win2k */
1406 "Wrong variant type for 'TargetSpecialFolder' property!\n");
1407 return E_INVALIDARG
;
1410 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1412 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1413 return E_INVALIDARG
;
1416 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1417 WCHAR wszPath
[MAX_PATH
];
1420 ok(V_VT(pVar
) == VT_BSTR
||
1421 broken(V_VT(pVar
) == VT_EMPTY
), /* Win2k */
1422 "Wrong variant type for 'Target' property!\n");
1423 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1425 result
= pSHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1426 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1427 if (!result
) return E_INVALIDARG
;
1429 V_BSTR(pVar
) = SysAllocString(wszPath
);
1433 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1434 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1435 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1436 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1437 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1441 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1442 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1444 return E_INVALIDARG
;
1447 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1448 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1450 return E_INVALIDARG
;
1453 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1454 return E_INVALIDARG
;
1457 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1460 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1464 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1465 InitPropertyBag_IPropertyBag_QueryInterface
,
1466 InitPropertyBag_IPropertyBag_AddRef
,
1467 InitPropertyBag_IPropertyBag_Release
,
1468 InitPropertyBag_IPropertyBag_Read
,
1469 InitPropertyBag_IPropertyBag_Write
1472 static struct IPropertyBag InitPropertyBag
= {
1473 &InitPropertyBag_IPropertyBagVtbl
1476 static void test_FolderShortcut(void) {
1477 IPersistPropertyBag
*pPersistPropertyBag
;
1478 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1479 IPersistFolder3
*pPersistFolder3
;
1482 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1485 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1487 WCHAR wszWineTestFolder
[] = {
1488 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1489 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1490 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1491 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1492 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1493 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1494 'N','a','m','e','S','p','a','c','e','\\',
1495 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1496 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1498 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1499 static const GUID CLSID_UnixDosFolder
=
1500 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1502 if (!pSHGetSpecialFolderPathW
|| !pStrRetToBufW
) {
1503 win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
1507 if (!pSHGetFolderPathAndSubDirA
)
1509 win_skip("FolderShortcut test doesn't work on Win2k\n");
1513 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1514 * via their IPersistPropertyBag interface. And that the target folder
1515 * is taken from the IPropertyBag's 'Target' property.
1517 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1518 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1519 if (hr
== REGDB_E_CLASSNOTREG
) {
1520 win_skip("CLSID_FolderShortcut is not implemented\n");
1523 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1524 if (hr
!= S_OK
) return;
1526 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1527 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1529 IPersistPropertyBag_Release(pPersistPropertyBag
);
1533 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1534 (LPVOID
*)&pShellFolder
);
1535 IPersistPropertyBag_Release(pPersistPropertyBag
);
1536 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1537 if (hr
!= S_OK
) return;
1539 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1540 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1542 IShellFolder_Release(pShellFolder
);
1546 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1547 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1548 if (!result
) return;
1550 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1551 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1553 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1554 IShellFolder_Release(pShellFolder
);
1555 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1556 if (hr
!= S_OK
) return;
1558 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1559 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1560 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1562 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1563 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1564 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1566 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1567 * shell namespace. The target folder, read from the property bag above, remains untouched.
1568 * The following tests show this: The itemidlist for some imaginary shellfolder object
1569 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1570 * itemidlist, but GetDisplayNameOf still returns the path from above.
1572 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1573 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1574 if (hr
!= S_OK
) return;
1576 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1577 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1578 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1579 RegCloseKey(hShellExtKey
);
1580 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1581 &pidlWineTestFolder
, NULL
);
1582 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1583 IShellFolder_Release(pDesktopFolder
);
1584 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1585 if (hr
!= S_OK
) return;
1587 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1588 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1590 IPersistFolder3_Release(pPersistFolder3
);
1591 pILFree(pidlWineTestFolder
);
1595 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1596 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1597 ok(pILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1598 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1599 pILFree(pidlCurrentFolder
);
1600 pILFree(pidlWineTestFolder
);
1602 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1603 IPersistFolder3_Release(pPersistFolder3
);
1604 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1605 if (hr
!= S_OK
) return;
1607 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1608 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1610 IShellFolder_Release(pShellFolder
);
1614 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1615 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1617 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1618 * but ShellFSFolders. */
1619 myPathAddBackslashW(wszDesktopPath
);
1620 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1621 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1622 IShellFolder_Release(pShellFolder
);
1626 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1627 &pidlSubFolder
, NULL
);
1628 RemoveDirectoryW(wszDesktopPath
);
1629 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1631 IShellFolder_Release(pShellFolder
);
1635 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1636 (LPVOID
*)&pPersistFolder3
);
1637 IShellFolder_Release(pShellFolder
);
1638 pILFree(pidlSubFolder
);
1639 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1643 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1644 * a little bit and also allow CLSID_UnixDosFolder. */
1645 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1646 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1647 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1648 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1650 IPersistFolder3_Release(pPersistFolder3
);
1653 #include "pshpack1.h"
1654 struct FileStructA
{
1658 WORD uFileDate
; /* In our current implementation this is */
1659 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1664 struct FileStructW
{
1665 WORD cbLen
; /* Length of this element. */
1666 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1667 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1668 WORD uTime
; /* (this is currently speculation) */
1669 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1670 WORD uTime2
; /* (this is currently speculation) */
1671 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1672 WCHAR wszName
[1]; /* The long filename in unicode. */
1673 /* Just for documentation: Right after the unicode string: */
1674 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1675 * SHITEMID->cb == uOffset + cbLen */
1677 #include "poppack.h"
1679 static void test_ITEMIDLIST_format(void) {
1680 WCHAR wszPersonal
[MAX_PATH
];
1681 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1682 LPITEMIDLIST pidlPersonal
, pidlFile
;
1686 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1687 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1690 if (!pSHGetSpecialFolderPathW
) return;
1692 bResult
= pSHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1693 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1694 if (!bResult
) return;
1696 SetLastError(0xdeadbeef);
1697 bResult
= SetCurrentDirectoryW(wszPersonal
);
1698 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1699 win_skip("Most W-calls are not implemented\n");
1702 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1703 if (!bResult
) return;
1705 hr
= SHGetDesktopFolder(&psfDesktop
);
1706 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1707 if (hr
!= S_OK
) return;
1709 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1710 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1712 IShellFolder_Release(psfDesktop
);
1716 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1717 (LPVOID
*)&psfPersonal
);
1718 IShellFolder_Release(psfDesktop
);
1719 pILFree(pidlPersonal
);
1720 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1721 if (hr
!= S_OK
) return;
1723 for (i
=0; i
<3; i
++) {
1724 CHAR szFile
[MAX_PATH
];
1725 struct FileStructA
*pFileStructA
;
1728 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1730 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1731 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1732 if (hFile
== INVALID_HANDLE_VALUE
) {
1733 IShellFolder_Release(psfPersonal
);
1738 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1739 DeleteFileW(wszFile
[i
]);
1740 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1742 IShellFolder_Release(psfPersonal
);
1746 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1747 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1748 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1749 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1751 if (i
< 2) /* First two file names are already in valid 8.3 format */
1752 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1754 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1755 * can't implement this correctly, since unix filesystems don't support
1756 * this nasty short/long filename stuff. So we'll probably stay with our
1757 * current habbit of storing the long filename here, which seems to work
1760 ok(pidlFile
->mkid
.abID
[18] == '~' ||
1761 broken(pidlFile
->mkid
.abID
[34] == '~'), /* Win2k */
1762 "Should be derived 8.3 name!\n");
1764 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1765 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0' ||
1766 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1), /* Win2k */
1767 "Alignment byte, where there shouldn't be!\n");
1769 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1770 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1771 "There should be an alignment byte, but isn't!\n");
1773 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1774 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1775 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1776 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)) ||
1777 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1) || /* Win2k on short names */
1778 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 12 + 1), /* Win2k on long names */
1779 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1781 if (cbOffset
>= sizeof(struct FileStructA
) &&
1782 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1784 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1786 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1787 "FileStructW's offset and length should add up to the PIDL's length!\n");
1789 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1790 /* Since we just created the file, time of creation,
1791 * time of last access and time of last write access just be the same.
1792 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1793 * after the first run. I do remember something with NTFS keeping the creation time
1794 * if a file is deleted and then created again within a couple of seconds or so.
1795 * Might be the reason. */
1796 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1797 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1798 "Last write time should match creation time!\n");
1800 /* On FAT filesystems the last access time is midnight
1801 local time, so the values of uDate2 and uTime2 will
1802 depend on the local timezone. If the times are exactly
1803 equal then the dates should be identical for both FAT
1804 and NTFS as no timezone is more than 1 day away from UTC.
1806 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1808 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1809 "Last write date and time should match last access date and time!\n");
1813 /* Filesystem may be FAT. Check date within 1 day
1814 and seconds are zero. */
1815 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1816 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1817 "Last access time on FAT filesystems should have zero seconds.\n");
1818 /* TODO: Perform check for date being within one day.*/
1821 ok (!lstrcmpW(wszFile
[i
], pFileStructW
->wszName
) ||
1822 !lstrcmpW(wszFile
[i
], (WCHAR
*)(pFileStructW
->abFooBar2
+ 22)) || /* Vista */
1823 !lstrcmpW(wszFile
[i
], (WCHAR
*)(pFileStructW
->abFooBar2
+ 26)), /* Win7 */
1824 "The filename should be stored in unicode at this position!\n");
1831 IShellFolder_Release(psfPersonal
);
1834 static void test_SHGetFolderPathA(void)
1836 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1838 char path
[MAX_PATH
];
1839 char path_x86
[MAX_PATH
];
1840 char path_key
[MAX_PATH
];
1844 if (!pSHGetFolderPathA
)
1846 win_skip("SHGetFolderPathA not present\n");
1849 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1851 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1852 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1853 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1856 win_skip( "Program Files (x86) not supported\n" );
1859 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1862 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1863 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1864 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1868 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1870 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1872 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1874 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1876 DWORD type
, count
= sizeof(path_x86
);
1877 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1879 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1880 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1882 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1886 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1887 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1888 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1891 win_skip( "Common Files (x86) not supported\n" );
1894 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1897 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1898 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1899 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1903 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1905 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1907 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1909 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1911 DWORD type
, count
= sizeof(path_x86
);
1912 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1914 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1915 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1917 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1921 static void test_SHGetFolderPathAndSubDirA(void)
1927 static char wine
[] = "wine";
1928 static char winetemp
[] = "wine\\temp";
1929 static char appdata
[MAX_PATH
];
1930 static char testpath
[MAX_PATH
];
1931 static char toolongpath
[MAX_PATH
+1];
1933 if(!pSHGetFolderPathAndSubDirA
)
1935 win_skip("SHGetFolderPathAndSubDirA not present!\n");
1939 if(!pSHGetFolderPathA
) {
1940 win_skip("SHGetFolderPathA not present!\n");
1943 if(FAILED(pSHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
1945 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1949 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1950 delret
= RemoveDirectoryA(testpath
);
1951 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
1952 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1956 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1957 delret
= RemoveDirectoryA(testpath
);
1958 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
1959 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1963 /* test invalid second parameter */
1964 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
1965 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
1967 /* test fourth parameter */
1968 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
1970 case S_OK
: /* winvista */
1971 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
1972 "expected %s to start with %s\n", testpath
, appdata
);
1973 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
1974 "expected %s to end with %s\n", testpath
, winetemp
);
1976 case E_INVALIDARG
: /* winxp, win2k3 */
1979 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
1982 /* test fifth parameter */
1984 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
1985 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1986 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1989 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
1990 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1991 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1994 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
1995 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
1996 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
1998 for(i
=0; i
< MAX_PATH
; i
++)
1999 toolongpath
[i
] = '0' + i
% 10;
2000 toolongpath
[MAX_PATH
] = '\0';
2001 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
2002 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
2003 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
2006 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
2007 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2009 /* test a not existing path */
2011 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2012 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
2013 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
2015 /* create a directory inside a not existing directory */
2017 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2018 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2019 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2020 "expected %s to start with %s\n", testpath
, appdata
);
2021 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2022 "expected %s to end with %s\n", testpath
, winetemp
);
2023 dwret
= GetFileAttributes(testpath
);
2024 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
2027 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2028 RemoveDirectoryA(testpath
);
2029 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2030 RemoveDirectoryA(testpath
);
2033 static void test_LocalizedNames(void)
2035 static char cCurrDirA
[MAX_PATH
];
2036 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
2037 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
2038 ITEMIDLIST
*newPIDL
;
2041 static char resourcefile
[MAX_PATH
];
2046 static const char desktopini_contents1
[] =
2047 "[.ShellClassInfo]\r\n"
2048 "LocalizedResourceName=@";
2049 static const char desktopini_contents2
[] =
2051 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
2052 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
2054 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
2055 CreateDirectoryA(".\\testfolder", NULL
);
2057 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
2059 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
2061 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
2062 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2063 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
2064 ok(WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
2065 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
2066 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
),
2067 "WriteFile failed %i\n", GetLastError());
2070 /* get IShellFolder for parent */
2071 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
2072 len
= lstrlenA(cCurrDirA
);
2075 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
2078 if(cCurrDirA
[len
-1] == '\\')
2079 cCurrDirA
[len
-1] = 0;
2081 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
2083 hr
= SHGetDesktopFolder(&IDesktopFolder
);
2084 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
2086 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
2087 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2089 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
2090 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
2092 IMalloc_Free(ppM
, newPIDL
);
2094 /* windows reads the display name from the resource */
2095 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
2096 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2098 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
2099 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2101 if (hr
== S_OK
&& pStrRetToBufW
)
2103 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2104 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2106 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2107 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2108 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2111 /* editing name is also read from the resource */
2112 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
2113 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2115 if (hr
== S_OK
&& pStrRetToBufW
)
2117 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2118 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2120 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2121 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2122 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2125 /* parsing name is unchanged */
2126 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
2127 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2129 if (hr
== S_OK
&& pStrRetToBufW
)
2131 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2132 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2133 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2136 IShellFolder_Release(IDesktopFolder
);
2137 IShellFolder_Release(testIShellFolder
);
2139 IMalloc_Free(ppM
, newPIDL
);
2142 DeleteFileA(".\\testfolder\\desktop.ini");
2143 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
2144 RemoveDirectoryA(".\\testfolder");
2147 static void test_SHCreateShellItem(void)
2149 IShellItem
*shellitem
, *shellitem2
;
2150 IPersistIDList
*persistidl
;
2151 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2153 char curdirA
[MAX_PATH
];
2154 WCHAR curdirW
[MAX_PATH
];
2155 WCHAR fnbufW
[MAX_PATH
];
2156 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2157 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2159 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2161 if (!pSHCreateShellItem
)
2163 win_skip("SHCreateShellItem isn't available\n");
2167 if (!lstrlenA(curdirA
))
2169 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2173 if(pSHGetSpecialFolderLocation
)
2175 ret
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2176 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2180 win_skip("pSHGetSpecialFolderLocation missing.\n");
2181 pidl_desktop
= NULL
;
2184 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2186 ret
= SHGetDesktopFolder(&desktopfolder
);
2187 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2189 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2190 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2192 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2193 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2195 CreateTestFile(".\\testfile");
2197 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2198 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2200 pidl_abstestfile
= pILCombine(pidl_cwd
, pidl_testfile
);
2202 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2203 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2205 if (0) /* crashes on Windows XP */
2207 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2208 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2209 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2210 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2213 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2214 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2217 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2218 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2221 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2222 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2225 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2228 IPersistIDList_Release(persistidl
);
2230 IShellItem_Release(shellitem
);
2233 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2234 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2237 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2238 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2241 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2242 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2245 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2248 IPersistIDList_Release(persistidl
);
2251 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2252 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2255 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2256 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2259 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2260 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2263 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2266 IPersistIDList_Release(persistidl
);
2268 IShellItem_Release(shellitem2
);
2271 IShellItem_Release(shellitem
);
2274 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2275 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2278 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2279 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2282 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2283 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2286 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2289 IPersistIDList_Release(persistidl
);
2291 IShellItem_Release(shellitem
);
2294 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2295 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2296 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2299 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2300 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2303 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2304 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2307 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2310 IPersistIDList_Release(persistidl
);
2312 IShellItem_Release(shellitem
);
2315 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2316 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2319 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2320 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2323 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2324 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2327 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2330 IPersistIDList_Release(persistidl
);
2333 IShellItem_Release(shellitem
);
2336 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2337 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2340 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2341 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2342 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2343 IShellItem_Release(shellitem
);
2346 /* SHCreateItemFromParsingName */
2347 if(pSHCreateItemFromParsingName
)
2351 /* Crashes under windows 7 */
2352 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2355 shellitem
= (void*)0xdeadbeef;
2356 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2357 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2358 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2360 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2361 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2362 "SHCreateItemFromParsingName returned %x\n", ret
);
2363 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2365 lstrcpyW(fnbufW
, curdirW
);
2366 myPathAddBackslashW(fnbufW
);
2367 lstrcatW(fnbufW
, testfileW
);
2369 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2370 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2374 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2375 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2378 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2379 CoTaskMemFree(tmp_fname
);
2381 IShellItem_Release(shellitem
);
2385 win_skip("No SHCreateItemFromParsingName\n");
2388 /* SHCreateItemFromIDList */
2389 if(pSHCreateItemFromIDList
)
2393 /* Crashes under win7 */
2394 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2397 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2398 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2400 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2401 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2404 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2405 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2408 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2409 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2412 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2415 IPersistIDList_Release(persistidl
);
2417 IShellItem_Release(shellitem
);
2420 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2421 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2424 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2425 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2428 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2429 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2432 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2435 IPersistIDList_Release(persistidl
);
2437 IShellItem_Release(shellitem
);
2441 win_skip("No SHCreateItemFromIDList\n");
2443 DeleteFileA(".\\testfile");
2444 pILFree(pidl_abstestfile
);
2445 pILFree(pidl_testfile
);
2446 pILFree(pidl_desktop
);
2448 IShellFolder_Release(currentfolder
);
2449 IShellFolder_Release(desktopfolder
);
2452 static void test_SHGetNameFromIDList(void)
2454 IShellItem
*shellitem
;
2459 static const DWORD flags
[] = {
2460 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2461 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2462 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2463 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2465 if(!pSHGetNameFromIDList
)
2467 win_skip("SHGetNameFromIDList missing.\n");
2471 /* These should be available on any platform that passed the above test. */
2472 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2473 ok(pSHBindToParent
!= NULL
, "SHBindToParent missing.\n");
2474 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
2475 ok(pStrRetToBufW
!= NULL
, "StrRetToBufW missing.\n");
2479 /* Crashes under win7 */
2480 hres
= pSHGetNameFromIDList(NULL
, 0, NULL
);
2483 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2484 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2486 /* Test the desktop */
2487 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2488 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2489 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2490 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2493 WCHAR
*nameSI
, *nameSH
;
2494 WCHAR buf
[MAX_PATH
];
2495 HRESULT hrSI
, hrSH
, hrSF
;
2500 SHGetDesktopFolder(&psf
);
2501 for(i
= 0; flags
[i
] != -1234; i
++)
2503 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2504 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2505 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2506 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2507 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2508 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2510 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2511 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2515 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2517 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2519 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2521 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2522 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2524 IShellFolder_Release(psf
);
2526 if(pSHGetPathFromIDListW
){
2527 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2528 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2529 res
= pSHGetPathFromIDListW(pidl
, buf
);
2530 ok(res
== TRUE
, "Got %d\n", res
);
2531 if(SUCCEEDED(hrSI
) && res
)
2532 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2533 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2535 win_skip("pSHGetPathFromIDListW not available\n");
2537 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2538 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2539 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2541 IShellItem_Release(shellitem
);
2545 /* Test the control panel */
2546 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2547 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2548 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2549 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2552 WCHAR
*nameSI
, *nameSH
;
2553 WCHAR buf
[MAX_PATH
];
2554 HRESULT hrSI
, hrSH
, hrSF
;
2559 SHGetDesktopFolder(&psf
);
2560 for(i
= 0; flags
[i
] != -1234; i
++)
2562 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2563 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2564 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2565 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2566 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2567 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2569 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2570 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2574 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2576 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2578 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2580 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2581 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2583 IShellFolder_Release(psf
);
2585 if(pSHGetPathFromIDListW
){
2586 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2587 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2588 res
= pSHGetPathFromIDListW(pidl
, buf
);
2589 ok(res
== FALSE
, "Got %d\n", res
);
2590 if(SUCCEEDED(hrSI
) && res
)
2591 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2592 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2594 win_skip("pSHGetPathFromIDListW not available\n");
2596 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2597 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2598 "Got 0x%08x\n", hres
);
2599 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2601 IShellItem_Release(shellitem
);
2606 static void test_SHGetItemFromDataObject(void)
2608 IShellFolder
*psfdesktop
;
2613 if(!pSHGetItemFromDataObject
)
2615 win_skip("No SHGetItemFromDataObject.\n");
2621 /* Crashes under win7 */
2622 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2625 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2626 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2628 SHGetDesktopFolder(&psfdesktop
);
2630 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2631 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2638 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2639 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2640 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2643 LPITEMIDLIST apidl
[5];
2646 for(count
= 0; count
< 5; count
++)
2647 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2652 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2653 &IID_IDataObject
, NULL
, (void**)&pdo
);
2654 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2657 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2658 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2659 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2660 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2661 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2662 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2663 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2664 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2665 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2666 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2667 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2668 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2669 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2670 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2671 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2673 IDataObject_Release(pdo
);
2677 skip("No file(s) found - skipping single-file test.\n");
2681 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2682 &IID_IDataObject
, NULL
, (void**)&pdo
);
2683 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2686 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2687 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2688 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2689 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2690 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2691 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2692 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2693 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2694 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2695 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2696 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2697 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2698 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2699 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2700 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2701 IDataObject_Release(pdo
);
2705 skip("zero or one file found - skipping multi-file test.\n");
2707 for(i
= 0; i
< count
; i
++)
2710 IEnumIDList_Release(peidl
);
2713 IShellView_Release(psv
);
2716 IShellFolder_Release(psfdesktop
);
2719 static void test_ShellItemCompare(void)
2721 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2722 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2723 IShellFolder
*psf_desktop
, *psf_current
;
2724 LPITEMIDLIST pidl_cwd
;
2725 WCHAR curdirW
[MAX_PATH
];
2728 static const WCHAR filesW
[][9] = {
2729 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2730 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2731 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2735 if(!pSHCreateShellItem
)
2737 win_skip("SHCreateShellItem missing.\n");
2741 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2742 if(!lstrlenW(curdirW
))
2744 skip("Failed to get current directory, skipping.\n");
2748 CreateDirectoryA(".\\a", NULL
);
2749 CreateDirectoryA(".\\b", NULL
);
2750 CreateDirectoryA(".\\c", NULL
);
2751 CreateTestFile(".\\a\\a");
2752 CreateTestFile(".\\a\\b");
2753 CreateTestFile(".\\a\\c");
2754 CreateTestFile(".\\b\\a");
2755 CreateTestFile(".\\b\\b");
2756 CreateTestFile(".\\b\\c");
2757 CreateTestFile(".\\c\\a");
2758 CreateTestFile(".\\c\\b");
2759 CreateTestFile(".\\c\\c");
2761 SHGetDesktopFolder(&psf_desktop
);
2762 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2763 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2764 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2765 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2766 IShellFolder_Release(psf_desktop
);
2768 /* Generate ShellItems for the files */
2769 ZeroMemory(&psi
, sizeof(IShellItem
*)*9);
2771 for(i
= 0; i
< 9; i
++)
2773 LPITEMIDLIST pidl_testfile
= NULL
;
2775 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2776 NULL
, &pidl_testfile
, NULL
);
2777 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2780 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2781 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2782 pILFree(pidl_testfile
);
2784 if(FAILED(hr
)) failed
= TRUE
;
2788 skip("Failed to create all shellitems.\n");
2792 /* Generate ShellItems for the folders */
2793 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2794 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2795 if(FAILED(hr
)) failed
= TRUE
;
2796 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2797 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2798 if(FAILED(hr
)) failed
= TRUE
;
2799 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2800 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2801 if(FAILED(hr
)) failed
= TRUE
;
2805 skip("Failed to create shellitems.\n");
2811 /* Crashes on native (win7, winxp) */
2812 hr
= IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2813 hr
= IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2814 hr
= IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2818 for(i
= 0; i
< 9; i
++)
2820 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
2821 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2822 ok(order
== 0, "Got order %d\n", order
);
2823 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
2824 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2825 ok(order
== 0, "Got order %d\n", order
);
2826 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2827 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2828 ok(order
== 0, "Got order %d\n", order
);
2832 /* a\b:a\a , a\b:a\c, a\b:a\b */
2833 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &order
);
2834 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2835 ok(order
== 1, "Got order %d\n", order
);
2836 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_DISPLAY
, &order
);
2837 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2838 ok(order
== -1, "Got order %d\n", order
);
2839 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2840 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2841 ok(order
== 0, "Got order %d\n", order
);
2843 /* b\b:a\b, b\b:c\b, b\b:c\b */
2844 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
2845 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2846 ok(order
== 1, "Got order %d\n", order
);
2847 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
2848 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2849 ok(order
== -1, "Got order %d\n", order
);
2850 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2851 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2852 ok(order
== 0, "Got order %d\n", order
);
2854 /* b:a\a, b:a\c, b:a\b */
2855 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
2856 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2857 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2858 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
2859 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2860 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2861 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2862 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2863 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2865 /* b:c\a, b:c\c, b:c\b */
2866 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
2867 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2868 ok(order
== -1, "Got order %d\n", order
);
2869 hr
= IShellItem_Compare(psi_b
, psi
[8], 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_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2873 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2874 ok(order
== -1, "Got order %d\n", order
);
2876 /* a\b:a\a , a\b:a\c, a\b:a\b */
2877 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
2878 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2879 ok(order
== 1, "Got order %d\n", order
);
2880 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
2881 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2882 ok(order
== -1, "Got order %d\n", order
);
2883 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2884 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2885 ok(order
== 0, "Got order %d\n", order
);
2887 /* b\b:a\b, b\b:c\b, b\b:c\b */
2888 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
2889 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2890 ok(order
== 1, "Got order %d\n", order
);
2891 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &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
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2895 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2896 ok(order
== 0, "Got order %d\n", order
);
2898 /* b:a\a, b:a\c, b:a\b */
2899 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
2900 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2901 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2902 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
2903 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2904 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2905 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2906 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2907 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2909 /* b:c\a, b:c\c, b:c\b */
2910 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
2911 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2912 ok(order
== -1, "Got order %d\n", order
);
2913 hr
= IShellItem_Compare(psi_b
, psi
[8], 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_b
, psi
[7], SICHINT_CANONICAL
, &order
);
2917 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2918 ok(order
== -1, "Got order %d\n", order
);
2921 IShellFolder_Release(psf_current
);
2923 DeleteFileA(".\\a\\a");
2924 DeleteFileA(".\\a\\b");
2925 DeleteFileA(".\\a\\c");
2926 DeleteFileA(".\\b\\a");
2927 DeleteFileA(".\\b\\b");
2928 DeleteFileA(".\\b\\c");
2929 DeleteFileA(".\\c\\a");
2930 DeleteFileA(".\\c\\b");
2931 DeleteFileA(".\\c\\c");
2932 RemoveDirectoryA(".\\a");
2933 RemoveDirectoryA(".\\b");
2934 RemoveDirectoryA(".\\c");
2936 if(psi_a
) IShellItem_Release(psi_a
);
2937 if(psi_b
) IShellItem_Release(psi_b
);
2938 if(psi_c
) IShellItem_Release(psi_c
);
2940 for(i
= 0; i
< 9; i
++)
2941 if(psi
[i
]) IShellItem_Release(psi
[i
]);
2944 /**************************************************************/
2945 /* IUnknown implementation for counting QueryInterface calls. */
2947 const IUnknownVtbl
*lpVtbl
;
2955 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
2957 IUnknownImpl
*This
= (IUnknownImpl
*)iunk
;
2959 for(i
= found
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
2961 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
2963 This
->ifaces
[i
].count
++;
2970 return E_NOINTERFACE
;
2973 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
2978 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
2983 static const IUnknownVtbl vt_IUnknown
= {
2984 unk_fnQueryInterface
,
2989 static void test_SHGetIDListFromObject(void)
2991 IUnknownImpl
*punkimpl
;
2992 IShellFolder
*psfdesktop
;
2994 LPITEMIDLIST pidl
, pidl_desktop
;
2997 struct if_count ifaces
[] =
2998 { {&IID_IPersistIDList
, 0},
2999 {&IID_IPersistFolder2
, 0},
3000 {&IID_IDataObject
, 0},
3001 {&IID_IParentAndItem
, 0},
3002 {&IID_IFolderView
, 0},
3005 if(!pSHGetIDListFromObject
)
3007 win_skip("SHGetIDListFromObject missing.\n");
3011 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3015 /* Crashes native */
3016 pSHGetIDListFromObject(NULL
, NULL
);
3017 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3020 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3021 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3023 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3024 punkimpl
->lpVtbl
= &vt_IUnknown
;
3025 punkimpl
->ifaces
= ifaces
;
3026 punkimpl
->unknown
= 0;
3028 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3029 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3030 ok(ifaces
[0].count
, "interface not requested.\n");
3031 ok(ifaces
[1].count
, "interface not requested.\n");
3032 ok(ifaces
[2].count
, "interface not requested.\n");
3034 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3035 "interface not requested.\n");
3036 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3037 "interface not requested.\n");
3039 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3040 HeapFree(GetProcessHeap(), 0, punkimpl
);
3042 pidl_desktop
= NULL
;
3043 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3044 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3046 SHGetDesktopFolder(&psfdesktop
);
3048 /* Test IShellItem */
3049 if(pSHCreateShellItem
)
3051 IShellItem
*shellitem
;
3052 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3053 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3056 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3057 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3060 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3063 IShellItem_Release(shellitem
);
3067 skip("no SHCreateShellItem.\n");
3069 /* Test IShellFolder */
3070 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3071 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3074 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3078 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3079 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3086 /* Test IFolderView */
3087 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3088 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3091 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3095 /* Test IDataObject */
3096 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3097 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3098 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3101 LPITEMIDLIST apidl
[5];
3103 for(count
= 0; count
< 5; count
++)
3104 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3109 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3110 &IID_IDataObject
, NULL
, (void**)&pdo
);
3111 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3114 pidl
= (void*)0xDEADBEEF;
3115 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3116 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3117 ok(pidl
!= NULL
, "pidl is NULL.\n");
3118 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3121 IDataObject_Release(pdo
);
3125 skip("No files found - skipping single-file test.\n");
3129 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3130 &IID_IDataObject
, NULL
, (void**)&pdo
);
3131 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3134 pidl
= (void*)0xDEADBEEF;
3135 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3136 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3137 "got 0x%08x\n", hres
);
3138 ok(pidl
== NULL
, "pidl is not NULL.\n");
3140 IDataObject_Release(pdo
);
3144 skip("zero or one file found - skipping multi-file test.\n");
3146 for(i
= 0; i
< count
; i
++)
3149 IEnumIDList_Release(peidl
);
3152 IShellView_Release(psv
);
3155 IShellFolder_Release(psfdesktop
);
3156 pILFree(pidl_desktop
);
3159 static void test_SHGetItemFromObject(void)
3161 IUnknownImpl
*punkimpl
;
3162 IShellFolder
*psfdesktop
;
3167 struct if_count ifaces
[] =
3168 { {&IID_IPersistIDList
, 0},
3169 {&IID_IPersistFolder2
, 0},
3170 {&IID_IDataObject
, 0},
3171 {&IID_IParentAndItem
, 0},
3172 {&IID_IFolderView
, 0},
3175 if(!pSHGetItemFromObject
)
3177 skip("No SHGetItemFromObject.\n");
3181 SHGetDesktopFolder(&psfdesktop
);
3185 /* Crashes with Windows 7 */
3186 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3187 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3188 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3191 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3192 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3194 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3195 punkimpl
->lpVtbl
= &vt_IUnknown
;
3196 punkimpl
->ifaces
= ifaces
;
3197 punkimpl
->unknown
= 0;
3199 /* The same as SHGetIDListFromObject */
3200 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3201 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3202 ok(ifaces
[0].count
, "interface not requested.\n");
3203 ok(ifaces
[1].count
, "interface not requested.\n");
3204 ok(ifaces
[2].count
, "interface not requested.\n");
3206 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3207 "interface not requested.\n");
3208 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3209 "interface not requested.\n");
3211 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3212 HeapFree(GetProcessHeap(), 0, punkimpl
);
3214 /* Test IShellItem */
3215 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3216 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3220 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3221 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3225 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3226 IShellItem_Release(psi2
);
3228 IShellItem_Release(psi
);
3231 IShellFolder_Release(psfdesktop
);
3234 static void test_SHCreateShellItemArray(void)
3236 IShellFolder
*pdesktopsf
, *psf
;
3237 IShellItemArray
*psia
;
3240 WCHAR cTestDirW
[MAX_PATH
];
3241 LPITEMIDLIST pidl_testdir
, pidl
;
3242 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3244 if(!pSHCreateShellItemArray
) {
3245 skip("No pSHCreateShellItemArray!\n");
3249 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3253 /* Crashes under native */
3254 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3255 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3256 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3257 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3260 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3261 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3263 SHGetDesktopFolder(&pdesktopsf
);
3264 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3265 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3267 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3268 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3270 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3271 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3272 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3275 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3276 myPathAddBackslashW(cTestDirW
);
3277 lstrcatW(cTestDirW
, testdirW
);
3279 CreateFilesFolders();
3281 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3282 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3285 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3287 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3289 IShellFolder_Release(pdesktopsf
);
3293 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3294 pILFree(pidl_testdir
);
3299 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3300 ok(hr
== S_OK
, "Got %08x\n", hr
);
3303 LPITEMIDLIST apidl
[5];
3304 UINT done
, numitems
, i
;
3306 for(done
= 0; done
< 5; done
++)
3307 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3309 ok(done
== 5, "Got %d pidls\n", done
);
3310 IEnumIDList_Release(peidl
);
3312 /* Create a ShellItemArray */
3313 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3314 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3321 /* Crashes in Windows 7 */
3322 hr
= IShellItemArray_GetCount(psia
, NULL
);
3325 IShellItemArray_GetCount(psia
, &numitems
);
3326 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3328 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3329 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3331 /* Compare all the items */
3332 for(i
= 0; i
< numitems
; i
++)
3334 LPITEMIDLIST pidl_abs
;
3335 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3337 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3338 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3341 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3342 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3345 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3348 IShellItem_Release(psi
);
3352 for(i
= 0; i
< done
; i
++)
3354 IShellItemArray_Release(psia
);
3358 /* SHCreateShellItemArrayFromShellItem */
3359 if(pSHCreateShellItemArrayFromShellItem
)
3365 /* Crashes under Windows 7 */
3366 hr
= pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3367 hr
= pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3368 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3371 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3372 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3375 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3376 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3381 hr
= IShellItemArray_GetCount(psia
, &count
);
3382 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3383 ok(count
== 1, "Got count %d\n", count
);
3384 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3385 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3387 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3390 LPITEMIDLIST pidl1
, pidl2
;
3391 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3392 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3393 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3394 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3395 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3396 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3397 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3400 IShellItem_Release(psi2
);
3402 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3403 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3404 IShellItemArray_Release(psia
);
3406 IShellItem_Release(psi
);
3410 skip("No SHCreateShellItemArrayFromShellItem.\n");
3412 if(pSHCreateShellItemArrayFromDataObject
)
3418 /* Crashes under Windows 7 */
3419 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3421 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3422 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3424 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3432 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3433 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3434 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3437 LPITEMIDLIST apidl
[5];
3440 for(count
= 0; count
< 5; count
++)
3441 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3443 ok(count
== 5, "Got %d\n", count
);
3447 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3448 &IID_IDataObject
, NULL
, (void**)&pdo
);
3449 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3452 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3454 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3458 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3459 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3460 for(i
= 0; i
< count_sia
; i
++)
3462 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3464 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3465 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3469 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3470 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3471 ok(pidl
!= NULL
, "pidl as NULL.\n");
3472 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3474 IShellItem_Release(psi
);
3479 IShellItemArray_Release(psia
);
3482 IDataObject_Release(pdo
);
3484 for(i
= 0; i
< count
; i
++)
3488 skip("No files found - skipping test.\n");
3490 IEnumIDList_Release(peidl
);
3492 IShellView_Release(psv
);
3496 skip("No SHCreateShellItemArrayFromDataObject.\n");
3498 IShellFolder_Release(psf
);
3499 pILFree(pidl_testdir
);
3503 static void test_ShellItemBindToHandler(void)
3506 LPITEMIDLIST pidl_desktop
;
3509 if(!pSHCreateShellItem
)
3511 skip("SHCreateShellItem missing.\n");
3515 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3516 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3519 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3520 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3524 IPersistFolder2
*ppf2
;
3529 /* Crashes under Windows 7 */
3530 hr
= IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3531 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3533 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3534 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3537 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3538 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3539 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3540 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3541 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3544 LPITEMIDLIST pidl_tmp
;
3545 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3546 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3549 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3552 IPersistFolder2_Release(ppf2
);
3555 /* BHID_SFUIObject */
3556 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3557 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3558 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3559 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3560 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3561 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3563 /* BHID_DataObject */
3564 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3565 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3566 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3570 /* BHID_SFViewObject */
3571 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3572 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3573 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3574 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3575 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3576 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3579 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
3580 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3581 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3582 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
3583 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3584 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3587 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
3588 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3589 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3590 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
3591 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3592 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3594 /* BHID_StorageEnum */
3595 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
3596 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3597 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3600 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
3601 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3602 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3604 /* BHID_EnumItems */
3605 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
3606 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3607 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3610 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
3611 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3612 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3614 /* BHID_LinkTargetItem */
3615 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
3616 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3617 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3618 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
3619 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3620 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3622 /* BHID_PropertyStore */
3623 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
3624 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3625 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3626 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
3627 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3628 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3630 /* BHID_ThumbnailHandler */
3631 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
3632 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3633 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3635 /* BHID_AssociationArray */
3636 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
3637 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3638 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3640 /* BHID_EnumAssocHandlers */
3641 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
3642 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3643 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3646 IShellItem_Release(psi
);
3649 skip("Failed to create ShellItem.\n");
3651 pILFree(pidl_desktop
);
3654 static void test_SHParseDisplayName(void)
3656 LPITEMIDLIST pidl1
, pidl2
;
3657 IShellFolder
*desktop
;
3658 WCHAR dirW
[MAX_PATH
];
3663 if (!pSHParseDisplayName
)
3665 win_skip("SHParseDisplayName isn't available\n");
3671 /* crashes on native */
3672 hr
= pSHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
3674 hr
= pSHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
3677 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
3678 hr
= pSHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
3679 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
3680 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
3681 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
3685 hr
= pSHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
3686 ok(hr
== S_OK
, "failed %08x\n", hr
);
3687 hr
= SHGetDesktopFolder(&desktop
);
3688 ok(hr
== S_OK
, "failed %08x\n", hr
);
3689 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
3690 ok(hr
== S_OK
, "failed %08x\n", hr
);
3691 ret
= pILIsEqual(pidl1
, pidl2
);
3692 ok(ret
== TRUE
, "expected equal idls\n");
3697 GetWindowsDirectoryW( dirW
, MAX_PATH
);
3699 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
3700 ok(hr
== S_OK
, "failed %08x\n", hr
);
3701 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
3702 ok(hr
== S_OK
, "failed %08x\n", hr
);
3704 ret
= pILIsEqual(pidl1
, pidl2
);
3705 ok(ret
== TRUE
, "expected equal idls\n");
3709 IShellFolder_Release(desktop
);
3712 static void test_desktop_IPersist(void)
3714 IShellFolder
*desktop
;
3716 IPersistFolder2
*ppf2
;
3720 hr
= SHGetDesktopFolder(&desktop
);
3721 ok(hr
== S_OK
, "failed %08x\n", hr
);
3723 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
3724 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* NT4, W9X */, "failed %08x\n", hr
);
3730 /* crashes on native */
3731 hr
= IPersist_GetClassID(persist
, NULL
);
3733 memset(&clsid
, 0, sizeof(clsid
));
3734 hr
= IPersist_GetClassID(persist
, &clsid
);
3735 ok(hr
== S_OK
, "failed %08x\n", hr
);
3736 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
3737 IPersist_Release(persist
);
3740 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
3741 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
3744 IPersistFolder
*ppf
;
3746 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
3747 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
3749 IPersistFolder_Release(ppf
);
3752 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
3753 ok(hr
== S_OK
, "got %08x\n", hr
);
3757 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
3758 ok(hr
== S_OK
, "got %08x\n", hr
);
3759 ok(pidl
!= NULL
, "pidl was NULL.\n");
3760 if(SUCCEEDED(hr
)) pILFree(pidl
);
3762 IPersistFolder2_Release(ppf2
);
3765 IShellFolder_Release(desktop
);
3768 static void test_GetUIObject(void)
3770 IShellFolder
*psf_desktop
;
3774 WCHAR path
[MAX_PATH
];
3775 const WCHAR filename
[] =
3776 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
3778 if(!pSHBindToParent
)
3780 win_skip("SHBindToParent missing.\n");
3784 GetCurrentDirectoryW(MAX_PATH
, path
);
3787 skip("GetCurrentDirectoryW returned an empty string.\n");
3790 lstrcatW(path
, filename
);
3791 SHGetDesktopFolder(&psf_desktop
);
3793 CreateFilesFolders();
3795 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
3796 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
3800 LPCITEMIDLIST pidl_child
;
3801 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
3802 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3805 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, (LPCITEMIDLIST
*)&pidl_child
,
3806 &IID_IContextMenu
, NULL
, (void**)&pcm
);
3807 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3810 HMENU hmenu
= CreatePopupMenu();
3811 INT max_id
, max_id_check
;
3813 const int id_upper_limit
= 32767;
3814 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, 0, id_upper_limit
, CMF_NORMAL
);
3815 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
3816 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
3817 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
3818 count
= GetMenuItemCount(hmenu
);
3819 ok(count
, "Got %d\n", count
);
3822 for(i
= 0; i
< count
; i
++)
3826 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
3827 mii
.cbSize
= sizeof(MENUITEMINFOA
);
3828 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
;
3831 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
3832 ok(res
, "Failed (last error: %d).\n", GetLastError());
3834 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
3835 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
3836 if(!(mii
.fType
& MFT_SEPARATOR
))
3837 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
3839 ok((max_id_check
== max_id
) ||
3840 (max_id_check
== max_id
-1 /* Win 7 */),
3841 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
3843 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
3845 if(count
&& !is_win2k()) /* Test is interactive on w2k, so skip */
3847 CMINVOKECOMMANDINFO cmi
;
3848 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
3849 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
3851 /* Attempt to execute a nonexistent command */
3852 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
3853 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
3854 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3856 cmi
.lpVerb
= "foobar_wine_test";
3857 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
3858 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
3859 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
3860 "Got 0x%08x\n", hr
);
3865 IContextMenu_Release(pcm
);
3867 IShellFolder_Release(psf
);
3869 if(pILFree
) pILFree(pidl
);
3872 IShellFolder_Release(psf_desktop
);
3876 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
3877 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
3879 LPCITEMIDLIST child
;
3880 IShellFolder
*parent
;
3884 if(!pSHBindToParent
){
3885 win_skip("SHBindToParent is not available, not performing full PIDL verification\n");
3887 ok_(__FILE__
,l
)(pidl
!= NULL
, "Expected PIDL to be non-NULL\n");
3889 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
3895 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
3899 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&parent
, &child
);
3900 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
3904 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
3905 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
3907 IShellFolder_Release(parent
);
3911 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
3912 "Got unexpected string type: %d\n", filename
.uType
);
3913 if(filename
.uType
== STRRET_WSTR
){
3914 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
3915 "didn't get expected path (%s), instead: %s\n",
3916 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
3917 }else if(filename
.uType
== STRRET_CSTR
){
3918 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
3919 "didn't get expected path (%s), instead: %s\n",
3920 wine_dbgstr_w(path
), U(filename
).cStr
);
3923 IShellFolder_Release(parent
);
3925 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
3928 static void test_SHSimpleIDListFromPath(void)
3930 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
3931 const CHAR adirA
[] = "C:\\sidlfpdir";
3932 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
3934 LPITEMIDLIST pidl
= NULL
;
3936 if(!pSHSimpleIDListFromPathAW
){
3937 win_skip("SHSimpleIDListFromPathAW not available\n");
3941 br
= CreateDirectoryA(adirA
, NULL
);
3942 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
3945 pidl
= pSHSimpleIDListFromPathAW(adirW
);
3947 pidl
= pSHSimpleIDListFromPathAW(adirA
);
3948 verify_pidl(pidl
, adirW
);
3951 br
= RemoveDirectoryA(adirA
);
3952 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
3955 pidl
= pSHSimpleIDListFromPathAW(adirW
);
3957 pidl
= pSHSimpleIDListFromPathAW(adirA
);
3958 verify_pidl(pidl
, adirW
);
3962 /* IFileSystemBindData impl */
3963 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
3964 REFIID riid
, void **ppv
)
3966 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
3967 IsEqualIID(riid
, &IID_IUnknown
)){
3971 return E_NOINTERFACE
;
3974 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
3979 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
3984 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
3985 const WIN32_FIND_DATAW
*pfd
)
3987 ok(0, "SetFindData called\n");
3991 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
3992 WIN32_FIND_DATAW
*pfd
)
3994 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
3998 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
3999 WIN32_FIND_DATAW
*pfd
)
4001 memset(pfd
, 0xdeadbeef, sizeof(WIN32_FIND_DATAW
));
4005 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4006 WIN32_FIND_DATAW
*pfd
)
4008 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4009 *pfd
->cFileName
= 'a';
4010 *pfd
->cAlternateFileName
= 'a';
4014 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4015 WIN32_FIND_DATAW
*pfd
)
4017 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4018 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4023 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4024 WIN32_FIND_DATAW
*pfd
)
4029 static IFileSystemBindDataVtbl fsbdVtbl
= {
4030 fsbd_QueryInterface
,
4037 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4039 static void test_ParseDisplayNamePBC(void)
4041 WCHAR wFileSystemBindData
[] =
4042 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4043 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4044 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4045 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4052 /* Check if we support WCHAR functions */
4053 SetLastError(0xdeadbeef);
4054 lstrcmpiW(adirW
, adirW
);
4055 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4056 win_skip("Most W-calls are not implemented\n");
4060 hres
= SHGetDesktopFolder(&psf
);
4061 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4063 win_skip("Failed to get IShellFolder, can't run tests\n");
4067 /* fails on unknown dir with no IBindCtx */
4068 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4069 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4070 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4071 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4072 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4073 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4075 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4076 hres
= CreateBindCtx(0, &pbc
);
4077 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4079 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4080 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4081 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4082 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4083 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4084 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4086 /* unknown dir with IBindCtx with IFileSystemBindData */
4087 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4088 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4090 /* return E_FAIL from GetFindData */
4091 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4092 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4093 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4094 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4095 "ParseDisplayName failed: 0x%08x\n", hres
);
4096 if(SUCCEEDED(hres
)){
4097 verify_pidl(pidl
, adirW
);
4101 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4102 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4103 "ParseDisplayName failed: 0x%08x\n", hres
);
4104 if(SUCCEEDED(hres
)){
4105 verify_pidl(pidl
, afileW
);
4109 /* set FIND_DATA struct to NULLs */
4110 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4111 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4112 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4113 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4114 "ParseDisplayName failed: 0x%08x\n", hres
);
4115 if(SUCCEEDED(hres
)){
4116 verify_pidl(pidl
, adirW
);
4120 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4121 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4122 "ParseDisplayName failed: 0x%08x\n", hres
);
4123 if(SUCCEEDED(hres
)){
4124 verify_pidl(pidl
, afileW
);
4128 /* set FIND_DATA struct to junk */
4129 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4130 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4131 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4132 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4133 "ParseDisplayName failed: 0x%08x\n", hres
);
4134 if(SUCCEEDED(hres
)){
4135 verify_pidl(pidl
, adirW
);
4139 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4140 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4141 "ParseDisplayName failed: 0x%08x\n", hres
);
4142 if(SUCCEEDED(hres
)){
4143 verify_pidl(pidl
, afileW
);
4147 /* set FIND_DATA struct to invalid data */
4148 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4149 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4150 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4151 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4152 "ParseDisplayName failed: 0x%08x\n", hres
);
4153 if(SUCCEEDED(hres
)){
4154 verify_pidl(pidl
, adirW
);
4158 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4159 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4160 "ParseDisplayName failed: 0x%08x\n", hres
);
4161 if(SUCCEEDED(hres
)){
4162 verify_pidl(pidl
, afileW
);
4166 /* set FIND_DATA struct to valid data */
4167 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4168 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4169 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4170 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4171 "ParseDisplayName failed: 0x%08x\n", hres
);
4172 if(SUCCEEDED(hres
)){
4173 verify_pidl(pidl
, adirW
);
4177 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4178 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4179 "ParseDisplayName failed: 0x%08x\n", hres
);
4180 if(SUCCEEDED(hres
)){
4181 verify_pidl(pidl
, afileW
);
4185 IBindCtx_Release(pbc
);
4186 IShellFolder_Release(psf
);
4189 static const CHAR testwindow_class
[] = "testwindow";
4190 #define WM_USER_NOTIFY (WM_APP+1)
4196 const WCHAR
*path_1
;
4197 const WCHAR
*path_2
;
4200 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4202 UINT signal
= (UINT
)lparam
;
4205 case WM_USER_NOTIFY
:
4206 if(exp_data
.exp_notify
){
4207 LPCITEMIDLIST
*pidls
= (LPCITEMIDLIST
*)wparam
;
4209 ok(exp_data
.signal
== signal
,
4210 "%s: expected notification type %x, got: %x\n",
4211 exp_data
.id
, exp_data
.signal
, signal
);
4213 trace("verifying pidls for: %s\n", exp_data
.id
);
4214 verify_pidl(pidls
[0], exp_data
.path_1
);
4215 verify_pidl(pidls
[1], exp_data
.path_2
);
4217 exp_data
.exp_notify
= FALSE
;
4219 ok(exp_data
.exp_notify
, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4222 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
4225 static void register_testwindow_class(void)
4230 ZeroMemory(&cls
, sizeof(cls
));
4231 cls
.cbSize
= sizeof(cls
);
4233 cls
.lpfnWndProc
= testwindow_wndproc
;
4234 cls
.hInstance
= GetModuleHandleA(NULL
);
4235 cls
.lpszClassName
= testwindow_class
;
4238 ret
= RegisterClassExA(&cls
);
4239 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4242 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4243 * have to poll repeatedly for the message to appear */
4244 static void do_events(void)
4247 while (exp_data
.exp_notify
&& (c
++ < 10)){
4249 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4250 TranslateMessage(&msg
);
4251 DispatchMessageA(&msg
);
4253 if(exp_data
.exp_notify
)
4256 trace("%s: took %d tries\n", exp_data
.id
, c
);
4259 static void test_SHChangeNotify(void)
4264 BOOL br
, has_unicode
;
4265 SHChangeNotifyEntry entries
[1];
4266 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4267 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4268 const CHAR test_dirA
[] = "C:\\shell32_cn_test\\test";
4269 const WCHAR test_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t','\\','t','e','s','t',0};
4271 CreateDirectoryW(NULL
, NULL
);
4272 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
4274 /* set up the root directory & window */
4275 br
= CreateDirectoryA(root_dirA
, NULL
);
4276 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4278 register_testwindow_class();
4280 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
4281 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
4282 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
4283 ok(wnd
!= NULL
, "Failed to make a window\n");
4285 entries
[0].pidl
= NULL
;
4287 hr
= SHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4289 hr
= SHILCreateFromPath((LPCVOID
)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4290 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
4291 entries
[0].fRecursive
= TRUE
;
4293 notifyID
= SHChangeNotifyRegister(wnd
, SHCNRF_ShellLevel
,
4294 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
4295 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
4298 br
= CreateDirectoryA(test_dirA
, NULL
);
4299 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4302 exp_data
.id
= "MKDIR PATHW";
4303 exp_data
.signal
= SHCNE_MKDIR
;
4304 exp_data
.exp_notify
= TRUE
;
4305 exp_data
.path_1
= test_dirW
;
4306 exp_data
.path_2
= NULL
;
4307 SHChangeNotify(SHCNE_MKDIR
, SHCNF_PATHW
| SHCNF_FLUSH
, test_dirW
, NULL
);
4309 ok(exp_data
.exp_notify
== FALSE
, "Expected wndproc to be called\n");
4311 win_skip("skipping WCHAR tests\n");
4313 exp_data
.id
= "MKDIR PATHA";
4314 exp_data
.signal
= SHCNE_MKDIR
;
4315 exp_data
.exp_notify
= TRUE
;
4316 exp_data
.path_1
= test_dirW
;
4317 exp_data
.path_2
= NULL
;
4318 SHChangeNotify(SHCNE_MKDIR
, SHCNF_PATHA
| SHCNF_FLUSH
, test_dirA
, NULL
);
4320 ok(exp_data
.exp_notify
== FALSE
, "Expected wndproc to be called\n");
4323 br
= RemoveDirectoryA(test_dirA
);
4324 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4327 exp_data
.id
= "RMDIR PATHW";
4328 exp_data
.signal
= SHCNE_RMDIR
;
4329 exp_data
.exp_notify
= TRUE
;
4330 exp_data
.path_1
= test_dirW
;
4331 exp_data
.path_2
= NULL
;
4332 SHChangeNotify(SHCNE_RMDIR
, SHCNF_PATHW
| SHCNF_FLUSH
, test_dirW
, NULL
);
4334 ok(exp_data
.exp_notify
== FALSE
, "Expected wndproc to be called\n");
4336 win_skip("skipping WCHAR tests\n");
4338 exp_data
.id
= "RMDIR PATHA";
4339 exp_data
.signal
= SHCNE_RMDIR
;
4340 exp_data
.exp_notify
= TRUE
;
4341 exp_data
.path_1
= test_dirW
;
4342 exp_data
.path_2
= NULL
;
4343 SHChangeNotify(SHCNE_RMDIR
, SHCNF_PATHA
| SHCNF_FLUSH
, test_dirA
, NULL
);
4345 ok(exp_data
.exp_notify
== FALSE
, "Expected wndproc to be called\n");
4347 SHChangeNotifyDeregister(notifyID
);
4350 br
= RemoveDirectoryA(root_dirA
);
4351 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4354 START_TEST(shlfolder
)
4356 init_function_pointers();
4357 /* if OleInitialize doesn't get called, ParseDisplayName returns
4358 CO_E_NOTINITIALIZED for malformed directory names on win2k. */
4359 OleInitialize(NULL
);
4361 test_ParseDisplayName();
4362 test_SHParseDisplayName();
4363 test_BindToObject();
4364 test_EnumObjects_and_CompareIDs();
4365 test_GetDisplayName();
4366 test_GetAttributesOf();
4367 test_SHGetPathFromIDList();
4368 test_CallForAttributes();
4369 test_FolderShortcut();
4370 test_ITEMIDLIST_format();
4371 test_SHGetFolderPathA();
4372 test_SHGetFolderPathAndSubDirA();
4373 test_LocalizedNames();
4374 test_SHCreateShellItem();
4375 test_SHCreateShellItemArray();
4376 test_desktop_IPersist();
4378 test_SHSimpleIDListFromPath();
4379 test_ParseDisplayNamePBC();
4380 test_SHGetNameFromIDList();
4381 test_SHGetItemFromDataObject();
4382 test_SHGetIDListFromObject();
4383 test_SHGetItemFromObject();
4384 test_ShellItemCompare();
4385 test_SHChangeNotify();
4386 test_ShellItemBindToHandler();