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
);
73 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)(LPWSTR
, UINT
);
74 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
76 static WCHAR
*make_wstr(const char *str
)
81 if(!str
|| strlen(str
) == 0)
84 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
88 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
92 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
96 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
99 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
100 return lstrcmpA(stra
, buf
);
103 static void init_function_pointers(void)
109 hmod
= GetModuleHandleA("shell32.dll");
111 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
112 MAKEFUNC(SHBindToParent
);
113 MAKEFUNC(SHCreateItemFromIDList
);
114 MAKEFUNC(SHCreateItemFromParsingName
);
115 MAKEFUNC(SHCreateShellItem
);
116 MAKEFUNC(SHCreateShellItemArray
);
117 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
118 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
119 MAKEFUNC(SHGetFolderPathA
);
120 MAKEFUNC(SHGetFolderPathAndSubDirA
);
121 MAKEFUNC(SHGetPathFromIDListW
);
122 MAKEFUNC(SHGetSpecialFolderPathA
);
123 MAKEFUNC(SHGetSpecialFolderPathW
);
124 MAKEFUNC(SHGetSpecialFolderLocation
);
125 MAKEFUNC(SHParseDisplayName
);
126 MAKEFUNC(SHGetNameFromIDList
);
127 MAKEFUNC(SHGetItemFromDataObject
);
128 MAKEFUNC(SHGetIDListFromObject
);
129 MAKEFUNC(SHGetItemFromObject
);
130 MAKEFUNC(SHCreateDefaultContextMenu
);
133 #define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
134 MAKEFUNC_ORD(ILFindLastID
, 16);
135 MAKEFUNC_ORD(ILIsEqual
, 21);
136 MAKEFUNC_ORD(ILCombine
, 25);
137 MAKEFUNC_ORD(ILFree
, 155);
138 MAKEFUNC_ORD(SHSimpleIDListFromPathAW
, 162);
141 /* test named exports */
142 ptr
= GetProcAddress(hmod
, "ILFree");
143 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
146 #define TESTNAMED(f) \
147 ptr = (void*)GetProcAddress(hmod, #f); \
148 ok(ptr != 0, "expected named export for " #f "\n");
150 TESTNAMED(ILAppendID
);
152 TESTNAMED(ILCloneFirst
);
153 TESTNAMED(ILCombine
);
154 TESTNAMED(ILCreateFromPath
);
155 TESTNAMED(ILCreateFromPathA
);
156 TESTNAMED(ILCreateFromPathW
);
157 TESTNAMED(ILFindChild
);
158 TESTNAMED(ILFindLastID
);
159 TESTNAMED(ILGetNext
);
160 TESTNAMED(ILGetSize
);
161 TESTNAMED(ILIsEqual
);
162 TESTNAMED(ILIsParent
);
163 TESTNAMED(ILRemoveLastID
);
164 TESTNAMED(ILSaveToStream
);
168 hmod
= GetModuleHandleA("shlwapi.dll");
169 pStrRetToBufW
= (void*)GetProcAddress(hmod
, "StrRetToBufW");
171 hmod
= GetModuleHandleA("kernel32.dll");
172 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
173 pGetSystemWow64DirectoryW
= (void*)GetProcAddress(hmod
, "GetSystemWow64DirectoryW");
175 hr
= SHGetMalloc(&ppM
);
176 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
179 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
180 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
184 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
190 if (lpszPath
[-1] != '\\')
199 static void test_ParseDisplayName(void)
202 IShellFolder
*IDesktopFolder
;
203 static const char *cNonExistDir1A
= "c:\\nonexist_subdir";
204 static const char *cNonExistDir2A
= "c:\\\\nonexist_subdir";
205 static const char *cInetTestA
= "http:\\yyy";
206 static const char *cInetTest2A
= "xx:yyy";
208 WCHAR cTestDirW
[MAX_PATH
] = {0};
212 hr
= SHGetDesktopFolder(&IDesktopFolder
);
213 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
214 if(hr
!= S_OK
) return;
216 /* Tests crash on W2K and below (SHCreateShellItem available as of XP) */
217 if (pSHCreateShellItem
)
219 /* null name and pidl */
220 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
221 NULL
, NULL
, NULL
, NULL
, NULL
, 0);
222 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
225 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
226 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
227 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
228 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
229 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
232 win_skip("Tests would crash on W2K and below\n");
234 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
235 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
236 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
237 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
238 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
241 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
242 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
243 IMalloc_Free(ppM
, newPIDL
);
246 MultiByteToWideChar(CP_ACP
, 0, cInetTest2A
, -1, cTestDirW
, MAX_PATH
);
247 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
248 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
249 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
250 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
253 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
254 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
255 IMalloc_Free(ppM
, newPIDL
);
258 res
= GetFileAttributesA(cNonExistDir1A
);
259 if(res
!= INVALID_FILE_ATTRIBUTES
)
261 skip("Test directory unexpectedly exists\n");
265 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
266 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
267 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
268 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
),
269 "ParseDisplayName returned %08x, expected 80070002 or E_FAIL\n", hr
);
271 res
= GetFileAttributesA(cNonExistDir2A
);
272 if(res
!= INVALID_FILE_ATTRIBUTES
)
274 skip("Test directory unexpectedly exists\n");
278 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
279 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
280 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
281 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
282 "ParseDisplayName returned %08x, expected 80070002, E_FAIL or E_INVALIDARG\n", hr
);
284 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
285 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
286 * out it doesn't. The magic seems to happen in the file dialogs, then. */
287 if (!pSHGetSpecialFolderPathW
|| !pILFindLastID
)
289 win_skip("SHGetSpecialFolderPathW and/or ILFindLastID are not available\n");
293 bRes
= pSHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
294 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
295 if (!bRes
) goto finished
;
297 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
298 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
299 if (hr
!= S_OK
) goto finished
;
301 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31 ||
302 pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0xb1, /* Win98 */
303 "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
304 pILFindLastID(newPIDL
)->mkid
.abID
[0]);
305 IMalloc_Free(ppM
, newPIDL
);
308 IShellFolder_Release(IDesktopFolder
);
311 /* creates a file with the specified name for tests */
312 static void CreateTestFile(const CHAR
*name
)
317 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
318 if (file
!= INVALID_HANDLE_VALUE
)
320 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
321 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
327 /* initializes the tests */
328 static void CreateFilesFolders(void)
330 CreateDirectoryA(".\\testdir", NULL
);
331 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
332 CreateTestFile (".\\testdir\\test1.txt ");
333 CreateTestFile (".\\testdir\\test2.txt ");
334 CreateTestFile (".\\testdir\\test3.txt ");
335 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
336 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
339 /* cleans after tests */
340 static void Cleanup(void)
342 DeleteFileA(".\\testdir\\test1.txt");
343 DeleteFileA(".\\testdir\\test2.txt");
344 DeleteFileA(".\\testdir\\test3.txt");
345 RemoveDirectoryA(".\\testdir\\test.txt");
346 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
347 RemoveDirectoryA(".\\testdir\\testdir2");
348 RemoveDirectoryA(".\\testdir");
353 static void test_EnumObjects(IShellFolder
*iFolder
)
355 IEnumIDList
*iEnumList
;
356 LPITEMIDLIST newPIDL
, idlArr
[10];
361 static const WORD iResults
[5][5] =
370 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
371 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
372 static const ULONG attrs
[5] =
374 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
375 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
376 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
377 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
378 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
381 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
382 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
384 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
385 * the filesystem shellfolders return S_OK even if less than 'celt' items are
386 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
387 * only ever returns a single entry per call. */
388 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
390 ok (i
== 5, "i: %d\n", i
);
392 hr
= IEnumIDList_Release(iEnumList
);
393 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
395 /* Sort them first in case of wrong order from system */
396 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
397 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
400 idlArr
[i
] = idlArr
[j
];
404 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
406 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
407 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
411 for (i
= 0; i
< 5; i
++)
414 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
415 /* Native returns all flags no matter what we ask for */
416 flags
= SFGAO_CANCOPY
;
417 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
418 flags
&= SFGAO_testfor
;
419 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
420 ok(flags
== (attrs
[i
]) ||
421 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
) || /* Win9x, NT4 */
422 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
423 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
425 flags
= SFGAO_testfor
;
426 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
427 flags
&= SFGAO_testfor
;
428 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
429 ok(flags
== attrs
[i
] ||
430 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
), /* Win9x, NT4 */
431 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
435 IMalloc_Free(ppM
, idlArr
[i
]);
438 static void test_BindToObject(void)
442 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
443 SHITEMID emptyitem
= { 0, { 0 } };
444 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
445 WCHAR wszSystemDir
[MAX_PATH
];
446 char szSystemDir
[MAX_PATH
];
448 WCHAR path
[MAX_PATH
];
449 CHAR pathA
[MAX_PATH
];
451 WCHAR wszMyComputer
[] = {
452 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
453 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
454 static const CHAR filename_html
[] = "winetest.html";
455 static const CHAR filename_txt
[] = "winetest.txt";
456 static const CHAR filename_foo
[] = "winetest.foo";
458 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
459 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
461 hr
= SHGetDesktopFolder(&psfDesktop
);
462 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
463 if (hr
!= S_OK
) return;
465 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
466 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
468 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
469 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
471 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
472 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
474 IShellFolder_Release(psfDesktop
);
478 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
479 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
480 IShellFolder_Release(psfDesktop
);
481 IMalloc_Free(ppM
, pidlMyComputer
);
482 if (hr
!= S_OK
) return;
484 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
485 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
489 /* this call segfaults on 98SE */
490 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
491 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
494 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
495 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
496 if (cChars
== 0 || cChars
>= MAX_PATH
) {
497 IShellFolder_Release(psfMyComputer
);
500 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
502 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
503 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
505 IShellFolder_Release(psfMyComputer
);
509 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
510 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
511 IShellFolder_Release(psfMyComputer
);
512 IMalloc_Free(ppM
, pidlSystemDir
);
513 if (hr
!= S_OK
) return;
515 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
516 ok (hr
== E_INVALIDARG
,
517 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
521 /* this call segfaults on 98SE */
522 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
523 ok (hr
== E_INVALIDARG
,
524 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
527 IShellFolder_Release(psfSystemDir
);
529 GetCurrentDirectoryA(MAX_PATH
, buf
);
532 skip("Failed to get current directory, skipping tests.\n");
536 SHGetDesktopFolder(&psfDesktop
);
538 /* Attempt BindToObject on files. */
541 lstrcpyA(pathA
, buf
);
542 lstrcatA(pathA
, "\\");
543 lstrcatA(pathA
, filename_html
);
544 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
545 if(hfile
!= INVALID_HANDLE_VALUE
)
548 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
549 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
550 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
553 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
555 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
560 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
562 broken(hr
== E_NOINTERFACE
), /* Win9x, NT4, W2K */
567 hr
= IPersist_GetClassID(pp
, &id
);
568 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
569 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
), "Unexpected classid\n");
570 IPersist_Release(pp
);
573 IShellFolder_Release(psfChild
);
580 win_skip("Failed to create .html testfile.\n");
583 lstrcpyA(pathA
, buf
);
584 lstrcatA(pathA
, "\\");
585 lstrcatA(pathA
, filename_txt
);
586 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
587 if(hfile
!= INVALID_HANDLE_VALUE
)
590 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
591 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
592 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
595 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
596 ok(hr
== E_FAIL
|| /* Vista+ */
597 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
598 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
600 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
606 win_skip("Failed to create .txt testfile.\n");
609 lstrcpyA(pathA
, buf
);
610 lstrcatA(pathA
, "\\");
611 lstrcatA(pathA
, filename_foo
);
612 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
613 if(hfile
!= INVALID_HANDLE_VALUE
)
616 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
617 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
618 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
621 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
622 ok(hr
== E_FAIL
|| /* Vista+ */
623 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
624 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
626 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
632 win_skip("Failed to create .foo testfile.\n");
634 /* And on the desktop */
635 if(pSHGetSpecialFolderPathA
)
637 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
638 lstrcatA(pathA
, "\\");
639 lstrcatA(pathA
, filename_html
);
640 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
641 if(hfile
!= INVALID_HANDLE_VALUE
)
644 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
645 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
646 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
649 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
651 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
653 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
656 if(!DeleteFileA(pathA
))
657 trace("Failed to delete: %d\n", GetLastError());
661 win_skip("Failed to create .html testfile.\n");
663 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
664 lstrcatA(pathA
, "\\");
665 lstrcatA(pathA
, filename_foo
);
666 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
667 if(hfile
!= INVALID_HANDLE_VALUE
)
670 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
671 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
672 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
675 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
676 ok(hr
== E_FAIL
|| /* Vista+ */
677 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
678 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
680 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
686 win_skip("Failed to create .foo testfile.\n");
689 IShellFolder_Release(psfDesktop
);
692 static void test_GetDisplayName(void)
697 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
698 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
701 LPSHELLFOLDER psfDesktop
, psfPersonal
;
703 SHITEMID emptyitem
= { 0, { 0 } };
704 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
705 LPCITEMIDLIST pidlLast
;
706 static const CHAR szFileName
[] = "winetest.foo";
707 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
708 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
710 /* I'm trying to figure if there is a functional difference between calling
711 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
712 * binding to the shellfolder. One thing I thought of was that perhaps
713 * SHGetPathFromIDListW would be able to get the path to a file, which does
714 * not exist anymore, while the other method wouldn't. It turns out there's
715 * no functional difference in this respect.
718 if(!pSHGetSpecialFolderPathA
) {
719 win_skip("SHGetSpecialFolderPathA is not available\n");
723 /* First creating a directory in MyDocuments and a file in this directory. */
724 result
= pSHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
725 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
728 /* Use ANSI file functions so this works on Windows 9x */
729 lstrcatA(szTestDir
, "\\winetest");
730 CreateDirectoryA(szTestDir
, NULL
);
731 attr
=GetFileAttributesA(szTestDir
);
732 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
734 ok(0, "unable to create the '%s' directory\n", szTestDir
);
738 lstrcpyA(szTestFile
, szTestDir
);
739 lstrcatA(szTestFile
, "\\");
740 lstrcatA(szTestFile
, szFileName
);
741 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
742 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
743 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
744 CloseHandle(hTestFile
);
746 /* Getting an itemidlist for the file. */
747 hr
= SHGetDesktopFolder(&psfDesktop
);
748 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
749 if (hr
!= S_OK
) return;
751 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
753 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
754 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
756 IShellFolder_Release(psfDesktop
);
760 pidlLast
= pILFindLastID(pidlTestFile
);
761 ok(pidlLast
->mkid
.cb
>=76 ||
762 broken(pidlLast
->mkid
.cb
== 28) || /* W2K */
763 broken(pidlLast
->mkid
.cb
== 40), /* Win9x, WinME */
764 "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
765 if (pidlLast
->mkid
.cb
>= 28) {
766 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
767 "Filename should be stored as ansi-string at this position!\n");
769 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
770 if (pidlLast
->mkid
.cb
>= 76) {
771 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
772 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
773 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)), /* Win7 */
774 "Filename should be stored as wchar-string at this position!\n");
777 /* It seems as if we cannot bind to regular files on windows, but only directories.
779 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
780 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
781 hr
== E_NOTIMPL
|| /* Vista */
782 broken(hr
== S_OK
), /* Win9x, W2K */
785 IShellFolder_Release(psfFile
);
788 if (!pSHBindToParent
)
790 win_skip("SHBindToParent is missing\n");
791 DeleteFileA(szTestFile
);
792 RemoveDirectoryA(szTestDir
);
796 /* Some tests for IShellFolder::SetNameOf */
797 if (pSHGetFolderPathAndSubDirA
)
799 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
800 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
802 /* It's ok to use this fixed path. Call will fail anyway. */
803 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
804 LPITEMIDLIST pidlNew
;
806 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
807 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
808 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
811 ok (((LPITEMIDLIST
)((LPBYTE
)pidlNew
+pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
812 "pidl returned from SetNameOf should be simple!\n");
814 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
815 * is implemented on top of SHFileOperation in WinXP. */
816 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
,
817 SHGDN_FORPARSING
, NULL
);
818 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
820 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
821 * SHGDN flags specify an absolute path. */
822 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
823 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
828 IShellFolder_Release(psfPersonal
);
832 win_skip("Avoid needs of interaction on Win2k\n");
834 /* Deleting the file and the directory */
835 DeleteFileA(szTestFile
);
836 RemoveDirectoryA(szTestDir
);
838 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
839 if (pSHGetPathFromIDListW
)
841 result
= pSHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
842 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
843 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
846 /* SHBindToParent fails, if called with a NULL PIDL. */
847 hr
= pSHBindToParent(NULL
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
848 ok (hr
!= S_OK
, "SHBindToParent(NULL) should fail!\n");
850 /* But it succeeds with an empty PIDL. */
851 hr
= pSHBindToParent(pidlEmpty
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
852 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
853 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
855 IShellFolder_Release(psfPersonal
);
857 /* Binding to the folder and querying the display name of the file also works. */
858 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
859 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
861 IShellFolder_Release(psfDesktop
);
865 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
866 * pidlTestFile (In accordance with MSDN). */
867 ok (pILFindLastID(pidlTestFile
) == pidlLast
,
868 "SHBindToParent doesn't return the last id of the pidl param!\n");
870 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
871 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
873 IShellFolder_Release(psfDesktop
);
874 IShellFolder_Release(psfPersonal
);
880 hr
= pStrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
881 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
882 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
885 ILFree(pidlTestFile
);
886 IShellFolder_Release(psfDesktop
);
887 IShellFolder_Release(psfPersonal
);
890 static void test_CallForAttributes(void)
896 LPSHELLFOLDER psfDesktop
;
897 LPITEMIDLIST pidlMyDocuments
;
898 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
899 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
900 static const WCHAR wszCallForAttributes
[] = {
901 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
902 static const WCHAR wszMyDocumentsKey
[] = {
903 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
904 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
905 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
906 WCHAR wszMyDocuments
[] = {
907 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
908 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
910 /* For the root of a namespace extension, the attributes are not queried by binding
911 * to the object and calling GetAttributesOf. Instead, the attributes are read from
912 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
914 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
915 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
916 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
917 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
919 hr
= SHGetDesktopFolder(&psfDesktop
);
920 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
921 if (hr
!= S_OK
) return;
923 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
924 &pidlMyDocuments
, NULL
);
926 broken(hr
== E_INVALIDARG
), /* Win95, NT4 */
927 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
929 IShellFolder_Release(psfDesktop
);
933 dwAttributes
= 0xffffffff;
934 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
935 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
936 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
938 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
939 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
940 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
941 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
943 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
944 * key. So the test will return at this point, if run on wine.
946 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
947 ok (lResult
== ERROR_SUCCESS
||
948 lResult
== ERROR_ACCESS_DENIED
,
949 "RegOpenKeyEx failed! result: %08x\n", lResult
);
950 if (lResult
!= ERROR_SUCCESS
) {
951 if (lResult
== ERROR_ACCESS_DENIED
)
952 skip("Not enough rights to open the registry key\n");
953 IMalloc_Free(ppM
, pidlMyDocuments
);
954 IShellFolder_Release(psfDesktop
);
958 /* Query MyDocuments' Attributes value, to be able to restore it later. */
959 dwSize
= sizeof(DWORD
);
960 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
961 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
962 if (lResult
!= ERROR_SUCCESS
) {
964 IMalloc_Free(ppM
, pidlMyDocuments
);
965 IShellFolder_Release(psfDesktop
);
969 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
970 dwSize
= sizeof(DWORD
);
971 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
972 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
973 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
974 if (lResult
!= ERROR_SUCCESS
) {
976 IMalloc_Free(ppM
, pidlMyDocuments
);
977 IShellFolder_Release(psfDesktop
);
981 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
982 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
983 * SFGAO_FILESYSTEM attributes. */
984 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
985 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
986 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
987 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
988 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
990 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
991 * GetAttributesOf. It seems that once there is a single attribute queried, for which
992 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
993 * the flags in Attributes are ignored.
995 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
996 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
997 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
998 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
1000 ok (dwAttributes
== SFGAO_FILESYSTEM
,
1001 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
1004 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
1005 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
1006 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1007 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
1009 IMalloc_Free(ppM
, pidlMyDocuments
);
1010 IShellFolder_Release(psfDesktop
);
1013 static void test_GetAttributesOf(void)
1016 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
1017 SHITEMID emptyitem
= { 0, { 0 } };
1018 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1019 LPITEMIDLIST pidlMyComputer
;
1021 static const DWORD desktopFlags
[] = {
1023 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
|
1024 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1026 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_STREAM
| SFGAO_FILESYSANCESTOR
|
1027 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1028 /* WinMe, Win9x, WinNT*/
1029 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSANCESTOR
|
1030 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1032 static const DWORD myComputerFlags
[] = {
1034 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
1035 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1037 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_STREAM
|
1038 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1039 /* WinMe, Win9x, WinNT */
1040 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1041 SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1042 /* Win95, WinNT when queried directly */
1043 SFGAO_CANLINK
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1044 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1046 WCHAR wszMyComputer
[] = {
1047 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1048 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1049 char cCurrDirA
[MAX_PATH
] = {0};
1050 WCHAR cCurrDirW
[MAX_PATH
];
1051 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
1052 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1053 ITEMIDLIST
*newPIDL
;
1055 BOOL foundFlagsMatch
;
1057 hr
= SHGetDesktopFolder(&psfDesktop
);
1058 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1059 if (hr
!= S_OK
) return;
1061 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
1062 dwFlags
= 0xffffffff;
1063 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
1064 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
1065 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1066 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1068 if (desktopFlags
[i
] == dwFlags
)
1069 foundFlagsMatch
= TRUE
;
1071 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1073 /* .. or with no itemidlist at all. */
1074 dwFlags
= 0xffffffff;
1075 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
1076 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1077 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1078 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1080 if (desktopFlags
[i
] == dwFlags
)
1081 foundFlagsMatch
= TRUE
;
1083 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1085 /* Testing the attributes of the MyComputer shellfolder */
1086 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1087 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1089 IShellFolder_Release(psfDesktop
);
1093 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
1094 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
1096 dwFlags
= 0xffffffff;
1097 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
1098 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
1099 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1100 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1102 if ((myComputerFlags
[i
] | SFGAO_CANLINK
) == dwFlags
)
1103 foundFlagsMatch
= TRUE
;
1106 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1108 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
1109 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
1110 IShellFolder_Release(psfDesktop
);
1111 IMalloc_Free(ppM
, pidlMyComputer
);
1112 if (hr
!= S_OK
) return;
1114 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
1116 ok (hr
== E_INVALIDARG
||
1117 broken(hr
== S_OK
), /* W2K and earlier */
1118 "MyComputer->GetAttributesOf(emtpy pidl) should fail! hr = %08x\n", hr
);
1120 dwFlags
= 0xffffffff;
1121 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
1122 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1123 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1124 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1126 if (myComputerFlags
[i
] == dwFlags
)
1127 foundFlagsMatch
= TRUE
;
1130 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1132 IShellFolder_Release(psfMyComputer
);
1134 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1135 len
= lstrlenA(cCurrDirA
);
1138 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1141 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1142 cCurrDirA
[len
-1] = 0;
1144 /* create test directory */
1145 CreateFilesFolders();
1147 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1149 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1150 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1152 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1153 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1155 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1156 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1158 IMalloc_Free(ppM
, newPIDL
);
1160 /* get relative PIDL */
1161 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1162 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1164 /* test the shell attributes of the test directory using the relative PIDL */
1165 dwFlags
= SFGAO_FOLDER
;
1166 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1167 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1168 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1171 IMalloc_Free(ppM
, newPIDL
);
1173 /* append testdirectory name to path */
1174 if (cCurrDirA
[len
-1] == '\\')
1175 cCurrDirA
[len
-1] = 0;
1176 lstrcatA(cCurrDirA
, "\\testdir");
1177 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1179 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1180 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1182 /* test the shell attributes of the test directory using the absolute PIDL */
1183 dwFlags
= SFGAO_FOLDER
;
1184 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1185 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1186 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1189 IMalloc_Free(ppM
, newPIDL
);
1191 IShellFolder_Release(testIShellFolder
);
1195 IShellFolder_Release(IDesktopFolder
);
1198 static void test_SHGetPathFromIDList(void)
1200 SHITEMID emptyitem
= { 0, { 0 } };
1201 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1202 LPITEMIDLIST pidlMyComputer
;
1203 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1206 LPSHELLFOLDER psfDesktop
;
1207 WCHAR wszMyComputer
[] = {
1208 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1209 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1210 WCHAR wszFileName
[MAX_PATH
];
1211 LPITEMIDLIST pidlTestFile
;
1214 static WCHAR wszTestFile
[] = {
1215 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1216 LPITEMIDLIST pidlPrograms
;
1218 if(!pSHGetPathFromIDListW
|| !pSHGetSpecialFolderPathW
)
1220 win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
1224 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1227 result
= pSHGetPathFromIDListW(NULL
, wszPath
);
1228 ok(!result
, "Expected failure\n");
1229 ok(!wszPath
[0], "Expected empty string\n");
1231 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1232 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1233 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1234 if (!result
) return;
1236 /* Check if we are on Win9x */
1237 SetLastError(0xdeadbeef);
1238 lstrcmpiW(wszDesktop
, wszDesktop
);
1239 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1241 win_skip("Most W-calls are not implemented\n");
1245 result
= pSHGetPathFromIDListW(pidlEmpty
, wszPath
);
1246 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1247 if (!result
) return;
1248 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1250 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1251 hr
= SHGetDesktopFolder(&psfDesktop
);
1252 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1253 if (hr
!= S_OK
) return;
1255 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1256 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1258 IShellFolder_Release(psfDesktop
);
1262 SetLastError(0xdeadbeef);
1265 result
= pSHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1266 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1267 ok (GetLastError()==0xdeadbeef ||
1268 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1269 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1270 ok (!wszPath
[0], "Expected empty path\n");
1272 IShellFolder_Release(psfDesktop
);
1276 IMalloc_Free(ppM
, pidlMyComputer
);
1278 result
= pSHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1279 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1281 IShellFolder_Release(psfDesktop
);
1284 myPathAddBackslashW(wszFileName
);
1285 lstrcatW(wszFileName
, wszTestFile
);
1286 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1287 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1288 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1289 IShellFolder_Release(psfDesktop
);
1292 CloseHandle(hTestFile
);
1294 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1295 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1297 IShellFolder_Release(psfDesktop
);
1298 DeleteFileW(wszFileName
);
1299 IMalloc_Free(ppM
, pidlTestFile
);
1303 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1304 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1305 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1306 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1307 IShellFolder_Release(psfDesktop
);
1308 DeleteFileW(wszFileName
);
1310 IMalloc_Free(ppM
, pidlTestFile
);
1315 pStrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1316 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1317 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1318 "returned incorrect path for file placed on desktop\n");
1321 result
= pSHGetPathFromIDListW(pidlTestFile
, wszPath
);
1322 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1323 IMalloc_Free(ppM
, pidlTestFile
);
1324 if (!result
) return;
1325 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1328 /* Test if we can get the path from the start menu "program files" PIDL. */
1329 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1330 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1332 SetLastError(0xdeadbeef);
1333 result
= pSHGetPathFromIDListW(pidlPrograms
, wszPath
);
1334 IMalloc_Free(ppM
, pidlPrograms
);
1335 ok(result
, "SHGetPathFromIDListW failed\n");
1338 static void test_EnumObjects_and_CompareIDs(void)
1340 ITEMIDLIST
*newPIDL
;
1341 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1342 char cCurrDirA
[MAX_PATH
] = {0};
1343 static const CHAR cTestDirA
[] = "\\testdir";
1344 WCHAR cTestDirW
[MAX_PATH
];
1348 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1349 len
= lstrlenA(cCurrDirA
);
1352 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1355 if(cCurrDirA
[len
-1] == '\\')
1356 cCurrDirA
[len
-1] = 0;
1358 lstrcatA(cCurrDirA
, cTestDirA
);
1359 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1361 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1362 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1364 CreateFilesFolders();
1366 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1367 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1369 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1370 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1372 test_EnumObjects(testIShellFolder
);
1374 IShellFolder_Release(testIShellFolder
);
1378 IMalloc_Free(ppM
, newPIDL
);
1380 IShellFolder_Release(IDesktopFolder
);
1383 /* A simple implementation of an IPropertyBag, which returns fixed values for
1384 * 'Target' and 'Attributes' properties.
1386 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1390 return E_INVALIDARG
;
1392 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1395 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1396 return E_NOINTERFACE
;
1399 IPropertyBag_AddRef(iface
);
1403 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1407 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1411 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1412 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1414 static const WCHAR wszTargetSpecialFolder
[] = {
1415 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1416 static const WCHAR wszTarget
[] = {
1417 'T','a','r','g','e','t',0 };
1418 static const WCHAR wszAttributes
[] = {
1419 'A','t','t','r','i','b','u','t','e','s',0 };
1420 static const WCHAR wszResolveLinkFlags
[] = {
1421 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1422 static const WCHAR wszTargetKnownFolder
[] = {
1423 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1424 static const WCHAR wszCLSID
[] = {
1425 'C','L','S','I','D',0 };
1427 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1428 ok(V_VT(pVar
) == VT_I4
||
1429 broken(V_VT(pVar
) == VT_BSTR
), /* Win2k */
1430 "Wrong variant type for 'TargetSpecialFolder' property!\n");
1431 return E_INVALIDARG
;
1434 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1436 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1437 return E_INVALIDARG
;
1440 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1441 WCHAR wszPath
[MAX_PATH
];
1444 ok(V_VT(pVar
) == VT_BSTR
||
1445 broken(V_VT(pVar
) == VT_EMPTY
), /* Win2k */
1446 "Wrong variant type for 'Target' property!\n");
1447 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1449 result
= pSHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1450 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1451 if (!result
) return E_INVALIDARG
;
1453 V_BSTR(pVar
) = SysAllocString(wszPath
);
1457 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1458 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1459 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1460 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1461 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1465 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1466 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1468 return E_INVALIDARG
;
1471 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1472 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1474 return E_INVALIDARG
;
1477 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1478 return E_INVALIDARG
;
1481 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1484 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1488 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1489 InitPropertyBag_IPropertyBag_QueryInterface
,
1490 InitPropertyBag_IPropertyBag_AddRef
,
1491 InitPropertyBag_IPropertyBag_Release
,
1492 InitPropertyBag_IPropertyBag_Read
,
1493 InitPropertyBag_IPropertyBag_Write
1496 static struct IPropertyBag InitPropertyBag
= {
1497 &InitPropertyBag_IPropertyBagVtbl
1500 static void test_FolderShortcut(void) {
1501 IPersistPropertyBag
*pPersistPropertyBag
;
1502 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1503 IPersistFolder3
*pPersistFolder3
;
1506 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1509 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1511 WCHAR wszWineTestFolder
[] = {
1512 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1513 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1514 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1515 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1516 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1517 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1518 'N','a','m','e','S','p','a','c','e','\\',
1519 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1520 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1522 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1523 static const GUID CLSID_UnixDosFolder
=
1524 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1526 if (!pSHGetSpecialFolderPathW
|| !pStrRetToBufW
) {
1527 win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
1531 if (!pSHGetFolderPathAndSubDirA
)
1533 win_skip("FolderShortcut test doesn't work on Win2k\n");
1537 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1538 * via their IPersistPropertyBag interface. And that the target folder
1539 * is taken from the IPropertyBag's 'Target' property.
1541 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1542 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1543 if (hr
== REGDB_E_CLASSNOTREG
) {
1544 win_skip("CLSID_FolderShortcut is not implemented\n");
1547 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1548 if (hr
!= S_OK
) return;
1550 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1551 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1553 IPersistPropertyBag_Release(pPersistPropertyBag
);
1557 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1558 (LPVOID
*)&pShellFolder
);
1559 IPersistPropertyBag_Release(pPersistPropertyBag
);
1560 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1561 if (hr
!= S_OK
) return;
1563 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1564 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1566 IShellFolder_Release(pShellFolder
);
1570 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1571 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1572 if (!result
) return;
1574 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1575 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1577 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1578 IShellFolder_Release(pShellFolder
);
1579 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1580 if (hr
!= S_OK
) return;
1582 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1583 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1584 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1586 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1587 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1588 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1590 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1591 * shell namespace. The target folder, read from the property bag above, remains untouched.
1592 * The following tests show this: The itemidlist for some imaginary shellfolder object
1593 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1594 * itemidlist, but GetDisplayNameOf still returns the path from above.
1596 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1597 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1598 if (hr
!= S_OK
) return;
1600 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1601 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1602 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1603 RegCloseKey(hShellExtKey
);
1604 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1605 &pidlWineTestFolder
, NULL
);
1606 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1607 IShellFolder_Release(pDesktopFolder
);
1608 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1609 if (hr
!= S_OK
) return;
1611 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1612 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1614 IPersistFolder3_Release(pPersistFolder3
);
1615 pILFree(pidlWineTestFolder
);
1619 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1620 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1621 ok(pILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1622 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1623 pILFree(pidlCurrentFolder
);
1624 pILFree(pidlWineTestFolder
);
1626 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1627 IPersistFolder3_Release(pPersistFolder3
);
1628 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1629 if (hr
!= S_OK
) return;
1631 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1632 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1634 IShellFolder_Release(pShellFolder
);
1638 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1639 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1641 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1642 * but ShellFSFolders. */
1643 myPathAddBackslashW(wszDesktopPath
);
1644 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1645 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1646 IShellFolder_Release(pShellFolder
);
1650 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1651 &pidlSubFolder
, NULL
);
1652 RemoveDirectoryW(wszDesktopPath
);
1653 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1655 IShellFolder_Release(pShellFolder
);
1659 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1660 (LPVOID
*)&pPersistFolder3
);
1661 IShellFolder_Release(pShellFolder
);
1662 pILFree(pidlSubFolder
);
1663 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1667 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1668 * a little bit and also allow CLSID_UnixDosFolder. */
1669 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1670 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1671 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1672 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1674 IPersistFolder3_Release(pPersistFolder3
);
1677 #include "pshpack1.h"
1678 struct FileStructA
{
1682 WORD uFileDate
; /* In our current implementation this is */
1683 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1688 struct FileStructW
{
1689 WORD cbLen
; /* Length of this element. */
1690 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1691 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1692 WORD uTime
; /* (this is currently speculation) */
1693 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1694 WORD uTime2
; /* (this is currently speculation) */
1695 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1696 WCHAR wszName
[1]; /* The long filename in unicode. */
1697 /* Just for documentation: Right after the unicode string: */
1698 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1699 * SHITEMID->cb == uOffset + cbLen */
1701 #include "poppack.h"
1703 static void test_ITEMIDLIST_format(void) {
1704 WCHAR wszPersonal
[MAX_PATH
];
1705 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1706 LPITEMIDLIST pidlPersonal
, pidlFile
;
1710 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1711 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1714 if (!pSHGetSpecialFolderPathW
) return;
1716 bResult
= pSHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1717 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1718 if (!bResult
) return;
1720 SetLastError(0xdeadbeef);
1721 bResult
= SetCurrentDirectoryW(wszPersonal
);
1722 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1723 win_skip("Most W-calls are not implemented\n");
1726 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1727 if (!bResult
) return;
1729 hr
= SHGetDesktopFolder(&psfDesktop
);
1730 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1731 if (hr
!= S_OK
) return;
1733 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1734 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1736 IShellFolder_Release(psfDesktop
);
1740 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1741 (LPVOID
*)&psfPersonal
);
1742 IShellFolder_Release(psfDesktop
);
1743 pILFree(pidlPersonal
);
1744 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1745 if (hr
!= S_OK
) return;
1747 for (i
=0; i
<3; i
++) {
1748 CHAR szFile
[MAX_PATH
];
1749 struct FileStructA
*pFileStructA
;
1752 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1754 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1755 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1756 if (hFile
== INVALID_HANDLE_VALUE
) {
1757 IShellFolder_Release(psfPersonal
);
1762 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1763 DeleteFileW(wszFile
[i
]);
1764 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1766 IShellFolder_Release(psfPersonal
);
1770 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1771 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1772 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1773 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1775 if (i
< 2) /* First two file names are already in valid 8.3 format */
1776 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1778 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1779 * can't implement this correctly, since unix filesystems don't support
1780 * this nasty short/long filename stuff. So we'll probably stay with our
1781 * current habit of storing the long filename here, which seems to work
1784 ok(pidlFile
->mkid
.abID
[18] == '~' ||
1785 broken(pidlFile
->mkid
.abID
[34] == '~'), /* Win2k */
1786 "Should be derived 8.3 name!\n");
1788 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1789 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0' ||
1790 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1), /* Win2k */
1791 "Alignment byte, where there shouldn't be!\n");
1793 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1794 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1795 "There should be an alignment byte, but isn't!\n");
1797 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1798 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1799 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1800 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)) ||
1801 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1) || /* Win2k on short names */
1802 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 12 + 1), /* Win2k on long names */
1803 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1805 if (cbOffset
>= sizeof(struct FileStructA
) &&
1806 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1808 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1809 WCHAR
*name
= pFileStructW
->wszName
;
1811 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1812 "FileStructW's offset and length should add up to the PIDL's length!\n");
1814 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1815 /* Since we just created the file, time of creation,
1816 * time of last access and time of last write access just be the same.
1817 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1818 * after the first run. I do remember something with NTFS keeping the creation time
1819 * if a file is deleted and then created again within a couple of seconds or so.
1820 * Might be the reason. */
1821 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1822 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1823 "Last write time should match creation time!\n");
1825 /* On FAT filesystems the last access time is midnight
1826 local time, so the values of uDate2 and uTime2 will
1827 depend on the local timezone. If the times are exactly
1828 equal then the dates should be identical for both FAT
1829 and NTFS as no timezone is more than 1 day away from UTC.
1831 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1833 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1834 "Last write date and time should match last access date and time!\n");
1838 /* Filesystem may be FAT. Check date within 1 day
1839 and seconds are zero. */
1840 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1841 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1842 "Last access time on FAT filesystems should have zero seconds.\n");
1843 /* TODO: Perform check for date being within one day.*/
1846 ok (!lstrcmpW(wszFile
[i
], name
) ||
1847 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1848 !lstrcmpW(wszFile
[i
], name
+ 11), /* Win7 */
1849 "The filename should be stored in unicode at this position!\n");
1856 IShellFolder_Release(psfPersonal
);
1859 static void test_SHGetFolderPathA(void)
1861 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1863 char path
[MAX_PATH
];
1864 char path_x86
[MAX_PATH
];
1865 char path_key
[MAX_PATH
];
1869 if (!pSHGetFolderPathA
)
1871 win_skip("SHGetFolderPathA not present\n");
1874 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1876 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1877 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1878 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1881 win_skip( "Program Files (x86) not supported\n" );
1884 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1887 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1888 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1889 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1893 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1895 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1897 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1899 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1901 DWORD type
, count
= sizeof(path_x86
);
1902 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1904 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1905 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1907 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1911 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1912 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1913 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1916 win_skip( "Common Files (x86) not supported\n" );
1919 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1922 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1923 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1924 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1928 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1930 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1932 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1934 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1936 DWORD type
, count
= sizeof(path_x86
);
1937 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1939 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1940 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1942 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1946 static void test_SHGetFolderPathAndSubDirA(void)
1952 static char wine
[] = "wine";
1953 static char winetemp
[] = "wine\\temp";
1954 static char appdata
[MAX_PATH
];
1955 static char testpath
[MAX_PATH
];
1956 static char toolongpath
[MAX_PATH
+1];
1958 if(!pSHGetFolderPathAndSubDirA
)
1960 win_skip("SHGetFolderPathAndSubDirA not present!\n");
1964 if(!pSHGetFolderPathA
) {
1965 win_skip("SHGetFolderPathA not present!\n");
1968 if(FAILED(pSHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
1970 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1974 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1975 delret
= RemoveDirectoryA(testpath
);
1976 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
1977 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1981 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1982 delret
= RemoveDirectoryA(testpath
);
1983 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
1984 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1988 /* test invalid second parameter */
1989 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
1990 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
1992 /* test fourth parameter */
1993 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
1995 case S_OK
: /* winvista */
1996 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
1997 "expected %s to start with %s\n", testpath
, appdata
);
1998 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
1999 "expected %s to end with %s\n", testpath
, winetemp
);
2001 case E_INVALIDARG
: /* winxp, win2k3 */
2004 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2007 /* test fifth parameter */
2009 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
2010 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2011 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2014 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
2015 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2016 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2019 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
2020 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2021 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2023 for(i
=0; i
< MAX_PATH
; i
++)
2024 toolongpath
[i
] = '0' + i
% 10;
2025 toolongpath
[MAX_PATH
] = '\0';
2026 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
2027 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
2028 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
2031 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
2032 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2034 /* test a not existing path */
2036 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2037 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
2038 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
2040 /* create a directory inside a not existing directory */
2042 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2043 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2044 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2045 "expected %s to start with %s\n", testpath
, appdata
);
2046 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2047 "expected %s to end with %s\n", testpath
, winetemp
);
2048 dwret
= GetFileAttributes(testpath
);
2049 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
2052 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2053 RemoveDirectoryA(testpath
);
2054 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2055 RemoveDirectoryA(testpath
);
2058 static void test_LocalizedNames(void)
2060 static char cCurrDirA
[MAX_PATH
];
2061 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
2062 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
2063 ITEMIDLIST
*newPIDL
;
2066 static char resourcefile
[MAX_PATH
];
2072 static const char desktopini_contents1
[] =
2073 "[.ShellClassInfo]\r\n"
2074 "LocalizedResourceName=@";
2075 static const char desktopini_contents2
[] =
2077 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
2078 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
2080 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
2081 CreateDirectoryA(".\\testfolder", NULL
);
2083 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
2085 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
2087 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
2088 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2089 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
2090 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
2091 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
2092 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
2093 ok(ret
, "WriteFile failed %i\n", GetLastError());
2096 /* get IShellFolder for parent */
2097 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
2098 len
= lstrlenA(cCurrDirA
);
2101 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
2104 if(cCurrDirA
[len
-1] == '\\')
2105 cCurrDirA
[len
-1] = 0;
2107 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
2109 hr
= SHGetDesktopFolder(&IDesktopFolder
);
2110 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
2112 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
2113 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2115 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
2116 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
2118 IMalloc_Free(ppM
, newPIDL
);
2120 /* windows reads the display name from the resource */
2121 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
2122 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2124 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
2125 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2127 if (hr
== S_OK
&& pStrRetToBufW
)
2129 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2130 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2132 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2133 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2134 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2137 /* editing name is also read from the resource */
2138 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
2139 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2141 if (hr
== S_OK
&& pStrRetToBufW
)
2143 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2144 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2146 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2147 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2148 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2151 /* parsing name is unchanged */
2152 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
2153 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2155 if (hr
== S_OK
&& pStrRetToBufW
)
2157 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2158 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2159 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2162 IShellFolder_Release(IDesktopFolder
);
2163 IShellFolder_Release(testIShellFolder
);
2165 IMalloc_Free(ppM
, newPIDL
);
2168 DeleteFileA(".\\testfolder\\desktop.ini");
2169 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
2170 RemoveDirectoryA(".\\testfolder");
2173 static void test_SHCreateShellItem(void)
2175 IShellItem
*shellitem
, *shellitem2
;
2176 IPersistIDList
*persistidl
;
2177 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2179 char curdirA
[MAX_PATH
];
2180 WCHAR curdirW
[MAX_PATH
];
2181 WCHAR fnbufW
[MAX_PATH
];
2182 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2183 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2185 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2187 if (!pSHCreateShellItem
)
2189 win_skip("SHCreateShellItem isn't available\n");
2193 if (!lstrlenA(curdirA
))
2195 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2199 if(pSHGetSpecialFolderLocation
)
2201 ret
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2202 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2206 win_skip("pSHGetSpecialFolderLocation missing.\n");
2207 pidl_desktop
= NULL
;
2210 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2212 ret
= SHGetDesktopFolder(&desktopfolder
);
2213 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2215 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2216 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2218 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2219 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2221 CreateTestFile(".\\testfile");
2223 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2224 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2226 pidl_abstestfile
= pILCombine(pidl_cwd
, pidl_testfile
);
2228 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2229 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2231 if (0) /* crashes on Windows XP */
2233 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2234 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2235 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2236 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2239 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2240 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2243 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2244 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2247 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2248 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2251 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2254 IPersistIDList_Release(persistidl
);
2256 IShellItem_Release(shellitem
);
2259 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2260 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2263 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2264 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2267 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2268 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2271 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2274 IPersistIDList_Release(persistidl
);
2277 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2278 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2281 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2282 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2285 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2286 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2289 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2292 IPersistIDList_Release(persistidl
);
2294 IShellItem_Release(shellitem2
);
2297 IShellItem_Release(shellitem
);
2300 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2301 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2304 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2305 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2308 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2309 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2312 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2315 IPersistIDList_Release(persistidl
);
2317 IShellItem_Release(shellitem
);
2320 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2321 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2322 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2325 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2326 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2329 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2330 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2333 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2336 IPersistIDList_Release(persistidl
);
2338 IShellItem_Release(shellitem
);
2341 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2342 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2345 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2346 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2349 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2350 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2353 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2356 IPersistIDList_Release(persistidl
);
2359 IShellItem_Release(shellitem
);
2362 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2363 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2366 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2367 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2368 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2369 IShellItem_Release(shellitem
);
2372 /* SHCreateItemFromParsingName */
2373 if(pSHCreateItemFromParsingName
)
2377 /* Crashes under windows 7 */
2378 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2381 shellitem
= (void*)0xdeadbeef;
2382 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2383 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2384 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2386 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2387 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2388 "SHCreateItemFromParsingName returned %x\n", ret
);
2389 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2391 lstrcpyW(fnbufW
, curdirW
);
2392 myPathAddBackslashW(fnbufW
);
2393 lstrcatW(fnbufW
, testfileW
);
2395 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2396 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2400 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2401 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2404 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2405 CoTaskMemFree(tmp_fname
);
2407 IShellItem_Release(shellitem
);
2411 win_skip("No SHCreateItemFromParsingName\n");
2414 /* SHCreateItemFromIDList */
2415 if(pSHCreateItemFromIDList
)
2419 /* Crashes under win7 */
2420 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2423 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2424 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2426 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2427 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2430 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2431 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2434 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2435 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2438 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2441 IPersistIDList_Release(persistidl
);
2443 IShellItem_Release(shellitem
);
2446 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2447 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2450 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2451 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2454 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2455 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2458 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2461 IPersistIDList_Release(persistidl
);
2463 IShellItem_Release(shellitem
);
2467 win_skip("No SHCreateItemFromIDList\n");
2469 DeleteFileA(".\\testfile");
2470 pILFree(pidl_abstestfile
);
2471 pILFree(pidl_testfile
);
2472 pILFree(pidl_desktop
);
2474 IShellFolder_Release(currentfolder
);
2475 IShellFolder_Release(desktopfolder
);
2478 static void test_SHGetNameFromIDList(void)
2480 IShellItem
*shellitem
;
2485 static const DWORD flags
[] = {
2486 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2487 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2488 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2489 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2491 if(!pSHGetNameFromIDList
)
2493 win_skip("SHGetNameFromIDList missing.\n");
2497 /* These should be available on any platform that passed the above test. */
2498 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2499 ok(pSHBindToParent
!= NULL
, "SHBindToParent missing.\n");
2500 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
2501 ok(pStrRetToBufW
!= NULL
, "StrRetToBufW missing.\n");
2505 /* Crashes under win7 */
2506 pSHGetNameFromIDList(NULL
, 0, NULL
);
2509 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2510 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2512 /* Test the desktop */
2513 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2514 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2515 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2516 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2519 WCHAR
*nameSI
, *nameSH
;
2520 WCHAR buf
[MAX_PATH
];
2521 HRESULT hrSI
, hrSH
, hrSF
;
2526 SHGetDesktopFolder(&psf
);
2527 for(i
= 0; flags
[i
] != -1234; i
++)
2529 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2530 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2531 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2532 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2533 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2534 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2536 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2537 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2541 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2543 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2545 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2547 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2548 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2550 IShellFolder_Release(psf
);
2552 if(pSHGetPathFromIDListW
){
2553 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2554 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2555 res
= pSHGetPathFromIDListW(pidl
, buf
);
2556 ok(res
== TRUE
, "Got %d\n", res
);
2557 if(SUCCEEDED(hrSI
) && res
)
2558 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2559 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2561 win_skip("pSHGetPathFromIDListW not available\n");
2563 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2564 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2565 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2567 IShellItem_Release(shellitem
);
2571 /* Test the control panel */
2572 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2573 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2574 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2575 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2578 WCHAR
*nameSI
, *nameSH
;
2579 WCHAR buf
[MAX_PATH
];
2580 HRESULT hrSI
, hrSH
, hrSF
;
2585 SHGetDesktopFolder(&psf
);
2586 for(i
= 0; flags
[i
] != -1234; i
++)
2588 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2589 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2590 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2591 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2592 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2593 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2595 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2596 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2600 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2602 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2604 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2606 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2607 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2609 IShellFolder_Release(psf
);
2611 if(pSHGetPathFromIDListW
){
2612 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2613 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2614 res
= pSHGetPathFromIDListW(pidl
, buf
);
2615 ok(res
== FALSE
, "Got %d\n", res
);
2616 if(SUCCEEDED(hrSI
) && res
)
2617 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2618 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2620 win_skip("pSHGetPathFromIDListW not available\n");
2622 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2623 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2624 "Got 0x%08x\n", hres
);
2625 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2627 IShellItem_Release(shellitem
);
2632 static void test_SHGetItemFromDataObject(void)
2634 IShellFolder
*psfdesktop
;
2639 if(!pSHGetItemFromDataObject
)
2641 win_skip("No SHGetItemFromDataObject.\n");
2647 /* Crashes under win7 */
2648 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2651 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2652 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2654 SHGetDesktopFolder(&psfdesktop
);
2656 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2657 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2664 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2665 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2666 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2669 LPITEMIDLIST apidl
[5];
2672 for(count
= 0; count
< 5; count
++)
2673 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2678 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2679 &IID_IDataObject
, NULL
, (void**)&pdo
);
2680 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2683 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2684 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2685 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2686 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &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_NO_HDROP
, &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_URL
, &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_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2696 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2697 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2699 IDataObject_Release(pdo
);
2703 skip("No file(s) found - skipping single-file test.\n");
2707 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2708 &IID_IDataObject
, NULL
, (void**)&pdo
);
2709 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2712 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2713 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2714 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2715 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2716 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2717 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2718 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2719 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2720 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2721 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2722 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2723 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2724 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2725 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2726 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2727 IDataObject_Release(pdo
);
2731 skip("zero or one file found - skipping multi-file test.\n");
2733 for(i
= 0; i
< count
; i
++)
2736 IEnumIDList_Release(peidl
);
2739 IShellView_Release(psv
);
2742 IShellFolder_Release(psfdesktop
);
2745 static void test_ShellItemCompare(void)
2747 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2748 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2749 IShellFolder
*psf_desktop
, *psf_current
;
2750 LPITEMIDLIST pidl_cwd
;
2751 WCHAR curdirW
[MAX_PATH
];
2754 static const WCHAR filesW
[][9] = {
2755 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2756 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2757 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2761 if(!pSHCreateShellItem
)
2763 win_skip("SHCreateShellItem missing.\n");
2767 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2768 if(!lstrlenW(curdirW
))
2770 skip("Failed to get current directory, skipping.\n");
2774 CreateDirectoryA(".\\a", NULL
);
2775 CreateDirectoryA(".\\b", NULL
);
2776 CreateDirectoryA(".\\c", NULL
);
2777 CreateTestFile(".\\a\\a");
2778 CreateTestFile(".\\a\\b");
2779 CreateTestFile(".\\a\\c");
2780 CreateTestFile(".\\b\\a");
2781 CreateTestFile(".\\b\\b");
2782 CreateTestFile(".\\b\\c");
2783 CreateTestFile(".\\c\\a");
2784 CreateTestFile(".\\c\\b");
2785 CreateTestFile(".\\c\\c");
2787 SHGetDesktopFolder(&psf_desktop
);
2788 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2789 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2790 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2791 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2792 IShellFolder_Release(psf_desktop
);
2795 /* Generate ShellItems for the files */
2796 memset(&psi
, 0, sizeof(psi
));
2798 for(i
= 0; i
< 9; i
++)
2800 LPITEMIDLIST pidl_testfile
= NULL
;
2802 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2803 NULL
, &pidl_testfile
, NULL
);
2804 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2807 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2808 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2809 pILFree(pidl_testfile
);
2811 if(FAILED(hr
)) failed
= TRUE
;
2815 skip("Failed to create all shellitems.\n");
2819 /* Generate ShellItems for the folders */
2820 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2821 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2822 if(FAILED(hr
)) failed
= TRUE
;
2823 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2824 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2825 if(FAILED(hr
)) failed
= TRUE
;
2826 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2827 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2828 if(FAILED(hr
)) failed
= TRUE
;
2832 skip("Failed to create shellitems.\n");
2838 /* Crashes on native (win7, winxp) */
2839 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2840 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2841 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2845 for(i
= 0; i
< 9; i
++)
2847 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
2848 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2849 ok(order
== 0, "Got order %d\n", order
);
2850 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
2851 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2852 ok(order
== 0, "Got order %d\n", order
);
2853 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2854 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2855 ok(order
== 0, "Got order %d\n", order
);
2859 /* a\b:a\a , a\b:a\c, a\b:a\b */
2860 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &order
);
2861 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2862 ok(order
== 1, "Got order %d\n", order
);
2863 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_DISPLAY
, &order
);
2864 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2865 ok(order
== -1, "Got order %d\n", order
);
2866 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2867 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2868 ok(order
== 0, "Got order %d\n", order
);
2870 /* b\b:a\b, b\b:c\b, b\b:c\b */
2871 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
2872 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2873 ok(order
== 1, "Got order %d\n", order
);
2874 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
2875 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2876 ok(order
== -1, "Got order %d\n", order
);
2877 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2878 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2879 ok(order
== 0, "Got order %d\n", order
);
2881 /* b:a\a, b:a\c, b:a\b */
2882 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
2883 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2884 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2885 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
2886 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2887 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2888 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2889 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2890 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2892 /* b:c\a, b:c\c, b:c\b */
2893 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
2894 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2895 ok(order
== -1, "Got order %d\n", order
);
2896 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_DISPLAY
, &order
);
2897 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2898 ok(order
== -1, "Got order %d\n", order
);
2899 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2900 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2901 ok(order
== -1, "Got order %d\n", order
);
2903 /* a\b:a\a , a\b:a\c, a\b:a\b */
2904 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
2905 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2906 ok(order
== 1, "Got order %d\n", order
);
2907 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
2908 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2909 ok(order
== -1, "Got order %d\n", order
);
2910 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2911 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2912 ok(order
== 0, "Got order %d\n", order
);
2914 /* b\b:a\b, b\b:c\b, b\b:c\b */
2915 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
2916 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2917 ok(order
== 1, "Got order %d\n", order
);
2918 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &order
);
2919 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2920 ok(order
== -1, "Got order %d\n", order
);
2921 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2922 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2923 ok(order
== 0, "Got order %d\n", order
);
2925 /* b:a\a, b:a\c, b:a\b */
2926 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
2927 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2928 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2929 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
2930 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2931 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2932 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2933 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2934 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2936 /* b:c\a, b:c\c, b:c\b */
2937 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
2938 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2939 ok(order
== -1, "Got order %d\n", order
);
2940 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_CANONICAL
, &order
);
2941 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2942 ok(order
== -1, "Got order %d\n", order
);
2943 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
2944 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2945 ok(order
== -1, "Got order %d\n", order
);
2948 IShellFolder_Release(psf_current
);
2950 DeleteFileA(".\\a\\a");
2951 DeleteFileA(".\\a\\b");
2952 DeleteFileA(".\\a\\c");
2953 DeleteFileA(".\\b\\a");
2954 DeleteFileA(".\\b\\b");
2955 DeleteFileA(".\\b\\c");
2956 DeleteFileA(".\\c\\a");
2957 DeleteFileA(".\\c\\b");
2958 DeleteFileA(".\\c\\c");
2959 RemoveDirectoryA(".\\a");
2960 RemoveDirectoryA(".\\b");
2961 RemoveDirectoryA(".\\c");
2963 if(psi_a
) IShellItem_Release(psi_a
);
2964 if(psi_b
) IShellItem_Release(psi_b
);
2965 if(psi_c
) IShellItem_Release(psi_c
);
2967 for(i
= 0; i
< 9; i
++)
2968 if(psi
[i
]) IShellItem_Release(psi
[i
]);
2971 /**************************************************************/
2972 /* IUnknown implementation for counting QueryInterface calls. */
2974 IUnknown IUnknown_iface
;
2982 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
2984 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
2987 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
2989 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
2991 for(i
= found
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
2993 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
2995 This
->ifaces
[i
].count
++;
3002 return E_NOINTERFACE
;
3005 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3010 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3015 static const IUnknownVtbl vt_IUnknown
= {
3016 unk_fnQueryInterface
,
3021 static void test_SHGetIDListFromObject(void)
3023 IUnknownImpl
*punkimpl
;
3024 IShellFolder
*psfdesktop
;
3026 LPITEMIDLIST pidl
, pidl_desktop
;
3029 struct if_count ifaces
[] =
3030 { {&IID_IPersistIDList
, 0},
3031 {&IID_IPersistFolder2
, 0},
3032 {&IID_IDataObject
, 0},
3033 {&IID_IParentAndItem
, 0},
3034 {&IID_IFolderView
, 0},
3037 if(!pSHGetIDListFromObject
)
3039 win_skip("SHGetIDListFromObject missing.\n");
3043 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3047 /* Crashes native */
3048 pSHGetIDListFromObject(NULL
, NULL
);
3049 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3052 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3053 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3055 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3056 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3057 punkimpl
->ifaces
= ifaces
;
3058 punkimpl
->unknown
= 0;
3060 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3061 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3062 ok(ifaces
[0].count
, "interface not requested.\n");
3063 ok(ifaces
[1].count
, "interface not requested.\n");
3064 ok(ifaces
[2].count
, "interface not requested.\n");
3066 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3067 "interface not requested.\n");
3068 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3069 "interface not requested.\n");
3071 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3072 HeapFree(GetProcessHeap(), 0, punkimpl
);
3074 pidl_desktop
= NULL
;
3075 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3076 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3078 SHGetDesktopFolder(&psfdesktop
);
3080 /* Test IShellItem */
3081 if(pSHCreateShellItem
)
3083 IShellItem
*shellitem
;
3084 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3085 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3088 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3089 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3092 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3095 IShellItem_Release(shellitem
);
3099 skip("no SHCreateShellItem.\n");
3101 /* Test IShellFolder */
3102 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3103 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3106 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3110 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3111 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3118 /* Test IFolderView */
3119 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3120 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3123 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3127 /* Test IDataObject */
3128 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3129 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3130 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3133 LPITEMIDLIST apidl
[5];
3135 for(count
= 0; count
< 5; count
++)
3136 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3141 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3142 &IID_IDataObject
, NULL
, (void**)&pdo
);
3143 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3146 pidl
= (void*)0xDEADBEEF;
3147 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3148 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3149 ok(pidl
!= NULL
, "pidl is NULL.\n");
3150 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3153 IDataObject_Release(pdo
);
3157 skip("No files found - skipping single-file test.\n");
3161 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3162 &IID_IDataObject
, NULL
, (void**)&pdo
);
3163 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3166 pidl
= (void*)0xDEADBEEF;
3167 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3168 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3169 "got 0x%08x\n", hres
);
3170 ok(pidl
== NULL
, "pidl is not NULL.\n");
3172 IDataObject_Release(pdo
);
3176 skip("zero or one file found - skipping multi-file test.\n");
3178 for(i
= 0; i
< count
; i
++)
3181 IEnumIDList_Release(peidl
);
3184 IShellView_Release(psv
);
3187 IShellFolder_Release(psfdesktop
);
3188 pILFree(pidl_desktop
);
3191 static void test_SHGetItemFromObject(void)
3193 IUnknownImpl
*punkimpl
;
3194 IShellFolder
*psfdesktop
;
3199 struct if_count ifaces
[] =
3200 { {&IID_IPersistIDList
, 0},
3201 {&IID_IPersistFolder2
, 0},
3202 {&IID_IDataObject
, 0},
3203 {&IID_IParentAndItem
, 0},
3204 {&IID_IFolderView
, 0},
3207 if(!pSHGetItemFromObject
)
3209 skip("No SHGetItemFromObject.\n");
3213 SHGetDesktopFolder(&psfdesktop
);
3217 /* Crashes with Windows 7 */
3218 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3219 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3220 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3223 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3224 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3226 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3227 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3228 punkimpl
->ifaces
= ifaces
;
3229 punkimpl
->unknown
= 0;
3231 /* The same as SHGetIDListFromObject */
3232 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3233 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3234 ok(ifaces
[0].count
, "interface not requested.\n");
3235 ok(ifaces
[1].count
, "interface not requested.\n");
3236 ok(ifaces
[2].count
, "interface not requested.\n");
3238 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3239 "interface not requested.\n");
3240 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3241 "interface not requested.\n");
3243 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3244 HeapFree(GetProcessHeap(), 0, punkimpl
);
3246 /* Test IShellItem */
3247 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3248 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3252 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3253 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3257 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3258 IShellItem_Release(psi2
);
3260 IShellItem_Release(psi
);
3263 IShellFolder_Release(psfdesktop
);
3266 static void test_SHCreateShellItemArray(void)
3268 IShellFolder
*pdesktopsf
, *psf
;
3269 IShellItemArray
*psia
;
3272 WCHAR cTestDirW
[MAX_PATH
];
3273 LPITEMIDLIST pidl_testdir
, pidl
;
3274 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3276 if(!pSHCreateShellItemArray
) {
3277 skip("No pSHCreateShellItemArray!\n");
3281 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3285 /* Crashes under native */
3286 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3287 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3288 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3289 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3292 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3293 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3295 SHGetDesktopFolder(&pdesktopsf
);
3296 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3297 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3299 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3300 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3302 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3303 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3304 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3307 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3308 myPathAddBackslashW(cTestDirW
);
3309 lstrcatW(cTestDirW
, testdirW
);
3311 CreateFilesFolders();
3313 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3314 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3317 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3319 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3321 IShellFolder_Release(pdesktopsf
);
3325 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3326 pILFree(pidl_testdir
);
3331 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3332 ok(hr
== S_OK
, "Got %08x\n", hr
);
3335 LPITEMIDLIST apidl
[5];
3336 UINT done
, numitems
, i
;
3338 for(done
= 0; done
< 5; done
++)
3339 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3341 ok(done
== 5, "Got %d pidls\n", done
);
3342 IEnumIDList_Release(peidl
);
3344 /* Create a ShellItemArray */
3345 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3346 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3353 /* Crashes in Windows 7 */
3354 IShellItemArray_GetCount(psia
, NULL
);
3357 IShellItemArray_GetCount(psia
, &numitems
);
3358 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3360 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3361 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3363 /* Compare all the items */
3364 for(i
= 0; i
< numitems
; i
++)
3366 LPITEMIDLIST pidl_abs
;
3367 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3369 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3370 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3373 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3374 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3377 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3380 IShellItem_Release(psi
);
3384 for(i
= 0; i
< done
; i
++)
3386 IShellItemArray_Release(psia
);
3390 /* SHCreateShellItemArrayFromShellItem */
3391 if(pSHCreateShellItemArrayFromShellItem
)
3397 /* Crashes under Windows 7 */
3398 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3399 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3400 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3403 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3404 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3407 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3408 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3413 hr
= IShellItemArray_GetCount(psia
, &count
);
3414 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3415 ok(count
== 1, "Got count %d\n", count
);
3416 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3417 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3419 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3422 LPITEMIDLIST pidl1
, pidl2
;
3423 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3424 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3425 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3426 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3427 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3428 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3429 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3432 IShellItem_Release(psi2
);
3434 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3435 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3436 IShellItemArray_Release(psia
);
3438 IShellItem_Release(psi
);
3442 skip("No SHCreateShellItemArrayFromShellItem.\n");
3444 if(pSHCreateShellItemArrayFromDataObject
)
3450 /* Crashes under Windows 7 */
3451 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3453 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3454 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3456 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3457 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3464 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3465 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3466 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3469 LPITEMIDLIST apidl
[5];
3472 for(count
= 0; count
< 5; count
++)
3473 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3475 ok(count
== 5, "Got %d\n", count
);
3479 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3480 &IID_IDataObject
, NULL
, (void**)&pdo
);
3481 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3484 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3486 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3490 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3491 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3492 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3493 for(i
= 0; i
< count_sia
; i
++)
3495 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3497 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3498 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3502 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3503 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3504 ok(pidl
!= NULL
, "pidl as NULL.\n");
3505 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3507 IShellItem_Release(psi
);
3512 IShellItemArray_Release(psia
);
3515 IDataObject_Release(pdo
);
3517 for(i
= 0; i
< count
; i
++)
3521 skip("No files found - skipping test.\n");
3523 IEnumIDList_Release(peidl
);
3525 IShellView_Release(psv
);
3529 skip("No SHCreateShellItemArrayFromDataObject.\n");
3531 IShellFolder_Release(psf
);
3532 pILFree(pidl_testdir
);
3536 static void test_ShellItemBindToHandler(void)
3539 LPITEMIDLIST pidl_desktop
;
3542 if(!pSHCreateShellItem
)
3544 skip("SHCreateShellItem missing.\n");
3548 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3549 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3552 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3553 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3557 IPersistFolder2
*ppf2
;
3562 /* Crashes under Windows 7 */
3563 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3564 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3566 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3567 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3570 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3571 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3572 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3573 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3574 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3577 LPITEMIDLIST pidl_tmp
;
3578 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3579 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3582 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3585 IPersistFolder2_Release(ppf2
);
3588 /* BHID_SFUIObject */
3589 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3590 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3591 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3592 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3593 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3594 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3596 /* BHID_DataObject */
3597 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3598 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3599 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3603 /* BHID_SFViewObject */
3604 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3605 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3606 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3607 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3608 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3609 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3612 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
3613 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3614 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3615 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
3616 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3617 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3620 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
3621 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3622 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3623 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
3624 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3625 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3627 /* BHID_StorageEnum */
3628 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
3629 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3630 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3633 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
3634 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3635 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3637 /* BHID_EnumItems */
3638 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
3639 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3640 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3643 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
3644 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3645 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3647 /* BHID_LinkTargetItem */
3648 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
3649 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3650 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3651 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
3652 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3653 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3655 /* BHID_PropertyStore */
3656 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
3657 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3658 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3659 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
3660 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3661 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3663 /* BHID_ThumbnailHandler */
3664 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
3665 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3666 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3668 /* BHID_AssociationArray */
3669 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
3670 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3671 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3673 /* BHID_EnumAssocHandlers */
3674 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
3675 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3676 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3679 IShellItem_Release(psi
);
3682 skip("Failed to create ShellItem.\n");
3684 pILFree(pidl_desktop
);
3687 static void test_ShellItemGetAttributes(void)
3690 LPITEMIDLIST pidl_desktop
;
3694 if(!pSHCreateShellItem
)
3696 skip("SHCreateShellItem missing.\n");
3700 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3701 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3704 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3705 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3706 pILFree(pidl_desktop
);
3710 skip("Skipping tests.\n");
3716 /* Crashes on native (Win 7) */
3717 IShellItem_GetAttributes(psi
, 0, NULL
);
3720 /* Test GetAttributes on the desktop folder. */
3722 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
3723 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
3724 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
3726 IShellItem_Release(psi
);
3729 static void test_SHParseDisplayName(void)
3731 LPITEMIDLIST pidl1
, pidl2
;
3732 IShellFolder
*desktop
;
3733 WCHAR dirW
[MAX_PATH
];
3738 if (!pSHParseDisplayName
)
3740 win_skip("SHParseDisplayName isn't available\n");
3746 /* crashes on native */
3747 pSHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
3749 pSHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
3752 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
3753 hr
= pSHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
3754 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
3755 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
3756 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
3760 hr
= pSHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
3761 ok(hr
== S_OK
, "failed %08x\n", hr
);
3762 hr
= SHGetDesktopFolder(&desktop
);
3763 ok(hr
== S_OK
, "failed %08x\n", hr
);
3764 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
3765 ok(hr
== S_OK
, "failed %08x\n", hr
);
3766 ret
= pILIsEqual(pidl1
, pidl2
);
3767 ok(ret
== TRUE
, "expected equal idls\n");
3772 GetWindowsDirectoryW( dirW
, MAX_PATH
);
3774 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
3775 ok(hr
== S_OK
, "failed %08x\n", hr
);
3776 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
3777 ok(hr
== S_OK
, "failed %08x\n", hr
);
3779 ret
= pILIsEqual(pidl1
, pidl2
);
3780 ok(ret
== TRUE
, "expected equal idls\n");
3784 /* system32 is not redirected to syswow64 on WOW64 */
3785 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
3786 if (is_wow64
&& pGetSystemWow64DirectoryW
)
3790 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
3791 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
3792 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
3793 ok(hr
== S_OK
, "failed %08x\n", hr
);
3795 len
= pGetSystemWow64DirectoryW(dirW
, MAX_PATH
);
3796 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
3797 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
3798 ok(hr
== S_OK
, "failed %08x\n", hr
);
3799 ret
= pILIsEqual(pidl1
, pidl2
);
3800 ok(ret
== FALSE
, "expected different idls\n");
3805 IShellFolder_Release(desktop
);
3808 static void test_desktop_IPersist(void)
3810 IShellFolder
*desktop
;
3812 IPersistFolder2
*ppf2
;
3816 hr
= SHGetDesktopFolder(&desktop
);
3817 ok(hr
== S_OK
, "failed %08x\n", hr
);
3819 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
3820 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* NT4, W9X */, "failed %08x\n", hr
);
3826 /* crashes on native */
3827 IPersist_GetClassID(persist
, NULL
);
3829 memset(&clsid
, 0, sizeof(clsid
));
3830 hr
= IPersist_GetClassID(persist
, &clsid
);
3831 ok(hr
== S_OK
, "failed %08x\n", hr
);
3832 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
3833 IPersist_Release(persist
);
3836 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
3837 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
3840 IPersistFolder
*ppf
;
3842 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
3843 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
3845 IPersistFolder_Release(ppf
);
3848 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
3849 ok(hr
== S_OK
, "got %08x\n", hr
);
3853 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
3854 ok(hr
== S_OK
, "got %08x\n", hr
);
3855 ok(pidl
!= NULL
, "pidl was NULL.\n");
3856 if(SUCCEEDED(hr
)) pILFree(pidl
);
3858 IPersistFolder2_Release(ppf2
);
3861 IShellFolder_Release(desktop
);
3864 static void test_GetUIObject(void)
3866 IShellFolder
*psf_desktop
;
3870 WCHAR path
[MAX_PATH
];
3871 const WCHAR filename
[] =
3872 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
3874 if(!pSHBindToParent
)
3876 win_skip("SHBindToParent missing.\n");
3880 GetCurrentDirectoryW(MAX_PATH
, path
);
3883 skip("GetCurrentDirectoryW returned an empty string.\n");
3886 lstrcatW(path
, filename
);
3887 SHGetDesktopFolder(&psf_desktop
);
3889 CreateFilesFolders();
3891 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
3892 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
3896 LPCITEMIDLIST pidl_child
;
3897 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
3898 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3901 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
,
3903 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3906 HMENU hmenu
= CreatePopupMenu();
3907 INT max_id
, max_id_check
;
3909 const int id_upper_limit
= 32767;
3910 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, 0, id_upper_limit
, CMF_NORMAL
);
3911 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
3912 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
3913 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
3914 count
= GetMenuItemCount(hmenu
);
3915 ok(count
, "Got %d\n", count
);
3918 for(i
= 0; i
< count
; i
++)
3922 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
3923 mii
.cbSize
= sizeof(MENUITEMINFOA
);
3924 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
;
3927 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
3928 ok(res
, "Failed (last error: %d).\n", GetLastError());
3930 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
3931 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
3932 if(!(mii
.fType
& MFT_SEPARATOR
))
3933 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
3935 ok((max_id_check
== max_id
) ||
3936 (max_id_check
== max_id
-1 /* Win 7 */),
3937 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
3939 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
3941 if(count
&& !is_win2k()) /* Test is interactive on w2k, so skip */
3943 CMINVOKECOMMANDINFO cmi
;
3944 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
3945 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
3947 /* Attempt to execute a nonexistent command */
3948 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
3949 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
3950 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3952 cmi
.lpVerb
= "foobar_wine_test";
3953 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
3954 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
3955 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
3956 "Got 0x%08x\n", hr
);
3961 IContextMenu_Release(pcm
);
3963 IShellFolder_Release(psf
);
3965 if(pILFree
) pILFree(pidl
);
3968 IShellFolder_Release(psf_desktop
);
3972 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
3973 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
3975 LPCITEMIDLIST child
;
3976 IShellFolder
*parent
;
3980 if(!pSHBindToParent
){
3981 win_skip("SHBindToParent is not available, not performing full PIDL verification\n");
3983 ok_(__FILE__
,l
)(pidl
!= NULL
, "Expected PIDL to be non-NULL\n");
3985 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
3991 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
3995 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&parent
, &child
);
3996 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4000 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4001 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4003 IShellFolder_Release(parent
);
4007 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4008 "Got unexpected string type: %d\n", filename
.uType
);
4009 if(filename
.uType
== STRRET_WSTR
){
4010 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4011 "didn't get expected path (%s), instead: %s\n",
4012 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4013 SHFree(U(filename
).pOleStr
);
4014 }else if(filename
.uType
== STRRET_CSTR
){
4015 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4016 "didn't get expected path (%s), instead: %s\n",
4017 wine_dbgstr_w(path
), U(filename
).cStr
);
4020 IShellFolder_Release(parent
);
4022 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4025 static void test_SHSimpleIDListFromPath(void)
4027 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4028 const CHAR adirA
[] = "C:\\sidlfpdir";
4029 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4031 LPITEMIDLIST pidl
= NULL
;
4033 if(!pSHSimpleIDListFromPathAW
){
4034 win_skip("SHSimpleIDListFromPathAW not available\n");
4038 br
= CreateDirectoryA(adirA
, NULL
);
4039 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4042 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4044 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4045 verify_pidl(pidl
, adirW
);
4048 br
= RemoveDirectoryA(adirA
);
4049 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4052 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4054 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4055 verify_pidl(pidl
, adirW
);
4059 /* IFileSystemBindData impl */
4060 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4061 REFIID riid
, void **ppv
)
4063 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4064 IsEqualIID(riid
, &IID_IUnknown
)){
4068 return E_NOINTERFACE
;
4071 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4076 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4081 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4082 const WIN32_FIND_DATAW
*pfd
)
4084 ok(0, "SetFindData called\n");
4088 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4089 WIN32_FIND_DATAW
*pfd
)
4091 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4095 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4096 WIN32_FIND_DATAW
*pfd
)
4098 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4102 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4103 WIN32_FIND_DATAW
*pfd
)
4105 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4106 *pfd
->cFileName
= 'a';
4107 *pfd
->cAlternateFileName
= 'a';
4111 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4112 WIN32_FIND_DATAW
*pfd
)
4114 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4115 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4120 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4121 WIN32_FIND_DATAW
*pfd
)
4126 static IFileSystemBindDataVtbl fsbdVtbl
= {
4127 fsbd_QueryInterface
,
4134 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4136 static void test_ParseDisplayNamePBC(void)
4138 WCHAR wFileSystemBindData
[] =
4139 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4140 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4141 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4142 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4143 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4150 /* Check if we support WCHAR functions */
4151 SetLastError(0xdeadbeef);
4152 lstrcmpiW(adirW
, adirW
);
4153 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4154 win_skip("Most W-calls are not implemented\n");
4158 hres
= SHGetDesktopFolder(&psf
);
4159 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4161 win_skip("Failed to get IShellFolder, can't run tests\n");
4165 /* fails on unknown dir with no IBindCtx */
4166 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4167 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4168 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4169 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4170 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4171 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4172 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4173 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4174 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4176 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4177 hres
= CreateBindCtx(0, &pbc
);
4178 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4180 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4181 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4182 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4183 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4184 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4185 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4186 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4187 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4188 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4190 /* unknown dir with IBindCtx with IFileSystemBindData */
4191 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4192 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4194 /* return E_FAIL from GetFindData */
4195 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4196 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4197 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4198 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4199 "ParseDisplayName failed: 0x%08x\n", hres
);
4200 if(SUCCEEDED(hres
)){
4201 verify_pidl(pidl
, adirW
);
4205 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4206 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4207 "ParseDisplayName failed: 0x%08x\n", hres
);
4208 if(SUCCEEDED(hres
)){
4209 verify_pidl(pidl
, afileW
);
4213 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4214 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4215 "ParseDisplayName failed: 0x%08x\n", hres
);
4216 if(SUCCEEDED(hres
)){
4217 verify_pidl(pidl
, afile2W
);
4221 /* set FIND_DATA struct to NULLs */
4222 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4223 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4224 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4225 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4226 "ParseDisplayName failed: 0x%08x\n", hres
);
4227 if(SUCCEEDED(hres
)){
4228 verify_pidl(pidl
, adirW
);
4232 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4233 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4234 "ParseDisplayName failed: 0x%08x\n", hres
);
4235 if(SUCCEEDED(hres
)){
4236 verify_pidl(pidl
, afileW
);
4240 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4241 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4242 "ParseDisplayName failed: 0x%08x\n", hres
);
4243 if(SUCCEEDED(hres
)){
4244 verify_pidl(pidl
, afile2W
);
4248 /* set FIND_DATA struct to junk */
4249 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4250 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4251 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4252 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4253 "ParseDisplayName failed: 0x%08x\n", hres
);
4254 if(SUCCEEDED(hres
)){
4255 verify_pidl(pidl
, adirW
);
4259 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4260 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4261 "ParseDisplayName failed: 0x%08x\n", hres
);
4262 if(SUCCEEDED(hres
)){
4263 verify_pidl(pidl
, afileW
);
4267 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4268 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4269 "ParseDisplayName failed: 0x%08x\n", hres
);
4270 if(SUCCEEDED(hres
)){
4271 verify_pidl(pidl
, afile2W
);
4275 /* set FIND_DATA struct to invalid data */
4276 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4277 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4278 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4279 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4280 "ParseDisplayName failed: 0x%08x\n", hres
);
4281 if(SUCCEEDED(hres
)){
4282 verify_pidl(pidl
, adirW
);
4286 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4287 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4288 "ParseDisplayName failed: 0x%08x\n", hres
);
4289 if(SUCCEEDED(hres
)){
4290 verify_pidl(pidl
, afileW
);
4294 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4295 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4296 "ParseDisplayName failed: 0x%08x\n", hres
);
4297 if(SUCCEEDED(hres
)){
4298 verify_pidl(pidl
, afile2W
);
4302 /* set FIND_DATA struct to valid data */
4303 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4304 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4305 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4306 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4307 "ParseDisplayName failed: 0x%08x\n", hres
);
4308 if(SUCCEEDED(hres
)){
4309 verify_pidl(pidl
, adirW
);
4313 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4314 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4315 "ParseDisplayName failed: 0x%08x\n", hres
);
4316 if(SUCCEEDED(hres
)){
4317 verify_pidl(pidl
, afileW
);
4321 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4322 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4323 "ParseDisplayName failed: 0x%08x\n", hres
);
4324 if(SUCCEEDED(hres
)){
4325 verify_pidl(pidl
, afile2W
);
4329 IBindCtx_Release(pbc
);
4330 IShellFolder_Release(psf
);
4333 static const CHAR testwindow_class
[] = "testwindow";
4334 #define WM_USER_NOTIFY (WM_APP+1)
4336 struct ChNotifyTest
{
4338 const UINT notify_count
;
4339 UINT missing_events
;
4341 const char path_1
[256];
4342 const char path_2
[256];
4343 } chnotify_tests
[] = {
4344 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
4345 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
4346 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
4349 struct ChNotifyTest
*exp_data
;
4350 BOOL test_new_delivery_flag
;
4352 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4354 LONG signal
= (LONG
)lparam
;
4357 case WM_USER_NOTIFY
:
4358 if(exp_data
->missing_events
> 0) {
4359 WCHAR
*path1
, *path2
;
4360 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
4361 HANDLE hLock
= NULL
;
4363 if(test_new_delivery_flag
) {
4364 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
4365 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
4368 ok(exp_data
->signal
== signal
,
4369 "%s: expected notification type %x, got: %x\n",
4370 exp_data
->id
, exp_data
->signal
, signal
);
4372 trace("verifying pidls for: %s\n", exp_data
->id
);
4373 path1
= make_wstr(exp_data
->path_1
);
4374 path2
= make_wstr(exp_data
->path_2
);
4375 verify_pidl(pidls
[0], path1
);
4376 verify_pidl(pidls
[1], path2
);
4377 HeapFree(GetProcessHeap(), 0, path1
);
4378 HeapFree(GetProcessHeap(), 0, path2
);
4380 exp_data
->missing_events
--;
4382 if(test_new_delivery_flag
)
4383 SHChangeNotification_Unlock(hLock
);
4385 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4388 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
4391 static void register_testwindow_class(void)
4396 ZeroMemory(&cls
, sizeof(cls
));
4397 cls
.cbSize
= sizeof(cls
);
4399 cls
.lpfnWndProc
= testwindow_wndproc
;
4400 cls
.hInstance
= GetModuleHandleA(NULL
);
4401 cls
.lpszClassName
= testwindow_class
;
4404 ret
= RegisterClassExA(&cls
);
4405 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4408 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4409 * have to poll repeatedly for the message to appear */
4410 static void do_events(void)
4413 while (exp_data
->missing_events
&& (c
++ < 10)){
4415 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4416 TranslateMessage(&msg
);
4417 DispatchMessageA(&msg
);
4419 if(exp_data
->missing_events
)
4422 trace("%s: took %d tries\n", exp_data
->id
, c
);
4425 static void test_SHChangeNotify(BOOL test_new_delivery
)
4430 BOOL br
, has_unicode
;
4431 SHChangeNotifyEntry entries
[1];
4432 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4433 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4435 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
4437 CreateDirectoryW(NULL
, NULL
);
4438 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
4440 test_new_delivery_flag
= test_new_delivery
;
4441 if(!test_new_delivery
)
4442 register_testwindow_class();
4444 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
4445 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
4446 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
4447 ok(wnd
!= NULL
, "Failed to make a window\n");
4449 br
= CreateDirectoryA(root_dirA
, NULL
);
4450 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4452 entries
[0].pidl
= NULL
;
4454 hr
= SHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4456 hr
= SHILCreateFromPath((LPCVOID
)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4457 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
4458 entries
[0].fRecursive
= TRUE
;
4460 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
4461 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
4462 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
4464 for(i
= 0; i
< sizeof(chnotify_tests
) / sizeof(*chnotify_tests
); ++i
){
4465 exp_data
= chnotify_tests
+ i
;
4467 exp_data
->missing_events
= exp_data
->notify_count
;
4468 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
4469 strlen(exp_data
->path_1
) > 0 ? exp_data
->path_1
: NULL
,
4470 strlen(exp_data
->path_2
) > 0 ? exp_data
->path_2
: NULL
);
4472 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4475 WCHAR
*path1
, *path2
;
4477 path1
= make_wstr(exp_data
->path_1
);
4478 path2
= make_wstr(exp_data
->path_2
);
4480 exp_data
->missing_events
= exp_data
->notify_count
;
4481 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
4483 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4485 HeapFree(GetProcessHeap(), 0, path1
);
4486 HeapFree(GetProcessHeap(), 0, path2
);
4490 SHChangeNotifyDeregister(notifyID
);
4493 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
4494 br
= RemoveDirectoryA(root_dirA
);
4495 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4498 static void test_SHCreateDefaultContextMenu(void)
4501 WCHAR path
[MAX_PATH
];
4502 IShellFolder
*desktop
,*folder
;
4503 IPersistFolder2
*persist
;
4504 IContextMenu
*cmenu
;
4506 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
4507 DEFCONTEXTMENU cminfo
;
4510 const WCHAR filename
[] =
4511 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4512 if(!pSHCreateDefaultContextMenu
)
4514 win_skip("SHCreateDefaultContextMenu missing.\n");
4518 if(!pSHBindToParent
)
4520 skip("SHBindToParent missing.\n");
4524 GetCurrentDirectoryW(MAX_PATH
, path
);
4527 skip("GetCurrentDirectoryW returned an empty string.\n");
4530 lstrcatW(path
, filename
);
4531 SHGetDesktopFolder(&desktop
);
4533 CreateFilesFolders();
4535 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4536 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
4540 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&folder
, (LPCITEMIDLIST
*)&pidl_child
);
4541 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4543 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
4544 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
4545 IPersistFolder2_Release(persist
);
4552 cminfo
.pidlFolder
=NULL
;
4553 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
4557 cminfo
.punkAssociationInfo
=NULL
;
4558 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
4559 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
4560 IContextMenu_Release(cmenu
);
4561 cminfo
.pidlFolder
=pidlFolder
;
4562 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
4563 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
4564 IContextMenu_Release(cmenu
);
4565 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
4566 if(status
==ERROR_SUCCESS
){
4571 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
4572 RegCloseKey(keys
[0]);
4573 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
4574 IContextMenu_Release(cmenu
);
4578 IShellFolder_Release(folder
);
4580 IShellFolder_Release(desktop
);
4585 START_TEST(shlfolder
)
4587 init_function_pointers();
4588 /* if OleInitialize doesn't get called, ParseDisplayName returns
4589 CO_E_NOTINITIALIZED for malformed directory names on win2k. */
4590 OleInitialize(NULL
);
4592 test_ParseDisplayName();
4593 test_SHParseDisplayName();
4594 test_BindToObject();
4595 test_EnumObjects_and_CompareIDs();
4596 test_GetDisplayName();
4597 test_GetAttributesOf();
4598 test_SHGetPathFromIDList();
4599 test_CallForAttributes();
4600 test_FolderShortcut();
4601 test_ITEMIDLIST_format();
4602 test_SHGetFolderPathA();
4603 test_SHGetFolderPathAndSubDirA();
4604 test_LocalizedNames();
4605 test_SHCreateShellItem();
4606 test_SHCreateShellItemArray();
4607 test_desktop_IPersist();
4609 test_SHSimpleIDListFromPath();
4610 test_ParseDisplayNamePBC();
4611 test_SHGetNameFromIDList();
4612 test_SHGetItemFromDataObject();
4613 test_SHGetIDListFromObject();
4614 test_SHGetItemFromObject();
4615 test_ShellItemCompare();
4616 test_SHChangeNotify(FALSE
);
4617 test_SHChangeNotify(TRUE
);
4618 test_ShellItemBindToHandler();
4619 test_ShellItemGetAttributes();
4620 test_SHCreateDefaultContextMenu();