2 * Unit test of the IShellFolder functions.
4 * Copyright 2004 Vitaliy Margolen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
40 #include "wine/test.h"
43 DEFINE_GUID(IID_IParentAndItem
, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
44 DEFINE_GUID(CLSID_ShellDocObjView
, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
48 static HRESULT (WINAPI
*pSHBindToParent
)(LPCITEMIDLIST
, REFIID
, LPVOID
*, LPCITEMIDLIST
*);
49 static HRESULT (WINAPI
*pSHGetFolderPathA
)(HWND
, int, HANDLE
, DWORD
, LPSTR
);
50 static HRESULT (WINAPI
*pSHGetFolderPathAndSubDirA
)(HWND
, int, HANDLE
, DWORD
, LPCSTR
, LPSTR
);
51 static BOOL (WINAPI
*pSHGetPathFromIDListW
)(LPCITEMIDLIST
,LPWSTR
);
52 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
53 static BOOL (WINAPI
*pSHGetSpecialFolderPathA
)(HWND
, LPSTR
, int, BOOL
);
54 static BOOL (WINAPI
*pSHGetSpecialFolderPathW
)(HWND
, LPWSTR
, int, BOOL
);
55 static HRESULT (WINAPI
*pStrRetToBufW
)(STRRET
*,LPCITEMIDLIST
,LPWSTR
,UINT
);
56 static LPITEMIDLIST (WINAPI
*pILFindLastID
)(LPCITEMIDLIST
);
57 static void (WINAPI
*pILFree
)(LPITEMIDLIST
);
58 static BOOL (WINAPI
*pILIsEqual
)(LPCITEMIDLIST
, LPCITEMIDLIST
);
59 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
60 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
61 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
62 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
63 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromIDLists
)(UINT
, PCIDLIST_ABSOLUTE
*, IShellItemArray
**);
64 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
65 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
66 static LPITEMIDLIST (WINAPI
*pILCombine
)(LPCITEMIDLIST
,LPCITEMIDLIST
);
67 static HRESULT (WINAPI
*pSHParseDisplayName
)(LPCWSTR
,IBindCtx
*,LPITEMIDLIST
*,SFGAOF
,SFGAOF
*);
68 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathAW
)(LPCVOID
);
69 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
70 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
71 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
72 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
73 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
74 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)(LPWSTR
, UINT
);
75 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
76 static HRESULT (WINAPI
*pSHCreateShellFolderView
)(const SFV_CREATE
*pcsfv
, IShellView
**ppsv
);
77 static HRESULT (WINAPI
*pSHCreateShellFolderViewEx
)(LPCSFV psvcbi
, IShellView
**ppv
);
79 static WCHAR
*make_wstr(const char *str
)
87 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
91 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
95 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
99 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
102 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
103 return lstrcmpA(stra
, buf
);
106 static void init_function_pointers(void)
112 hmod
= GetModuleHandleA("shell32.dll");
114 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
115 MAKEFUNC(SHBindToParent
);
116 MAKEFUNC(SHCreateItemFromIDList
);
117 MAKEFUNC(SHCreateItemFromParsingName
);
118 MAKEFUNC(SHCreateShellItem
);
119 MAKEFUNC(SHCreateShellItemArray
);
120 MAKEFUNC(SHCreateShellItemArrayFromIDLists
);
121 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
122 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
123 MAKEFUNC(SHGetFolderPathA
);
124 MAKEFUNC(SHGetFolderPathAndSubDirA
);
125 MAKEFUNC(SHGetPathFromIDListW
);
126 MAKEFUNC(SHGetSpecialFolderPathA
);
127 MAKEFUNC(SHGetSpecialFolderPathW
);
128 MAKEFUNC(SHGetSpecialFolderLocation
);
129 MAKEFUNC(SHParseDisplayName
);
130 MAKEFUNC(SHGetNameFromIDList
);
131 MAKEFUNC(SHGetItemFromDataObject
);
132 MAKEFUNC(SHGetIDListFromObject
);
133 MAKEFUNC(SHGetItemFromObject
);
134 MAKEFUNC(SHCreateDefaultContextMenu
);
135 MAKEFUNC(SHCreateShellFolderView
);
136 MAKEFUNC(SHCreateShellFolderViewEx
);
139 #define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
140 MAKEFUNC_ORD(ILFindLastID
, 16);
141 MAKEFUNC_ORD(ILIsEqual
, 21);
142 MAKEFUNC_ORD(ILCombine
, 25);
143 MAKEFUNC_ORD(ILFree
, 155);
144 MAKEFUNC_ORD(SHSimpleIDListFromPathAW
, 162);
147 /* test named exports */
148 ptr
= GetProcAddress(hmod
, "ILFree");
149 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
152 #define TESTNAMED(f) \
153 ptr = (void*)GetProcAddress(hmod, #f); \
154 ok(ptr != 0, "expected named export for " #f "\n");
156 TESTNAMED(ILAppendID
);
158 TESTNAMED(ILCloneFirst
);
159 TESTNAMED(ILCombine
);
160 TESTNAMED(ILCreateFromPath
);
161 TESTNAMED(ILCreateFromPathA
);
162 TESTNAMED(ILCreateFromPathW
);
163 TESTNAMED(ILFindChild
);
164 TESTNAMED(ILFindLastID
);
165 TESTNAMED(ILGetNext
);
166 TESTNAMED(ILGetSize
);
167 TESTNAMED(ILIsEqual
);
168 TESTNAMED(ILIsParent
);
169 TESTNAMED(ILRemoveLastID
);
170 TESTNAMED(ILSaveToStream
);
174 hmod
= GetModuleHandleA("shlwapi.dll");
175 pStrRetToBufW
= (void*)GetProcAddress(hmod
, "StrRetToBufW");
177 hmod
= GetModuleHandleA("kernel32.dll");
178 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
179 pGetSystemWow64DirectoryW
= (void*)GetProcAddress(hmod
, "GetSystemWow64DirectoryW");
181 hr
= SHGetMalloc(&ppM
);
182 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
185 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
186 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
190 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
196 if (lpszPath
[-1] != '\\')
205 static void test_ParseDisplayName(void)
208 IShellFolder
*IDesktopFolder
;
209 static const char *cNonExistDir1A
= "c:\\nonexist_subdir";
210 static const char *cNonExistDir2A
= "c:\\\\nonexist_subdir";
211 static const char *cInetTestA
= "http:\\yyy";
212 static const char *cInetTest2A
= "xx:yyy";
214 WCHAR cTestDirW
[MAX_PATH
] = {0};
218 hr
= SHGetDesktopFolder(&IDesktopFolder
);
219 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
220 if(hr
!= S_OK
) return;
222 /* Tests crash on W2K and below (SHCreateShellItem available as of XP) */
223 if (pSHCreateShellItem
)
227 /* null name and pidl, also crashes on Windows 8 */
228 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
,
229 NULL
, NULL
, NULL
, 0);
230 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
234 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
235 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
236 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
237 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
238 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
241 win_skip("Tests would crash on W2K and below\n");
243 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
244 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
245 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
246 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
247 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
250 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
251 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
252 IMalloc_Free(ppM
, newPIDL
);
255 MultiByteToWideChar(CP_ACP
, 0, cInetTest2A
, -1, cTestDirW
, MAX_PATH
);
256 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
257 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
258 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
259 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
262 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
263 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
264 IMalloc_Free(ppM
, newPIDL
);
267 res
= GetFileAttributesA(cNonExistDir1A
);
268 if(res
!= INVALID_FILE_ATTRIBUTES
)
270 skip("Test directory unexpectedly exists\n");
274 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
275 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
276 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
277 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
),
278 "ParseDisplayName returned %08x, expected 80070002 or E_FAIL\n", hr
);
280 res
= GetFileAttributesA(cNonExistDir2A
);
281 if(res
!= INVALID_FILE_ATTRIBUTES
)
283 skip("Test directory unexpectedly exists\n");
287 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
288 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
289 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
290 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
291 "ParseDisplayName returned %08x, expected 80070002, E_FAIL or E_INVALIDARG\n", hr
);
293 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
294 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
295 * out it doesn't. The magic seems to happen in the file dialogs, then. */
296 if (!pSHGetSpecialFolderPathW
|| !pILFindLastID
)
298 win_skip("SHGetSpecialFolderPathW and/or ILFindLastID are not available\n");
302 bRes
= pSHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
303 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
304 if (!bRes
) goto finished
;
306 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
307 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
308 if (hr
!= S_OK
) goto finished
;
310 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31 ||
311 pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0xb1, /* Win98 */
312 "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
313 pILFindLastID(newPIDL
)->mkid
.abID
[0]);
314 IMalloc_Free(ppM
, newPIDL
);
317 IShellFolder_Release(IDesktopFolder
);
320 /* creates a file with the specified name for tests */
321 static void CreateTestFile(const CHAR
*name
)
326 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
327 if (file
!= INVALID_HANDLE_VALUE
)
329 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
330 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
336 /* initializes the tests */
337 static void CreateFilesFolders(void)
339 CreateDirectoryA(".\\testdir", NULL
);
340 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
341 CreateTestFile (".\\testdir\\test1.txt ");
342 CreateTestFile (".\\testdir\\test2.txt ");
343 CreateTestFile (".\\testdir\\test3.txt ");
344 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
345 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
348 /* cleans after tests */
349 static void Cleanup(void)
351 DeleteFileA(".\\testdir\\test1.txt");
352 DeleteFileA(".\\testdir\\test2.txt");
353 DeleteFileA(".\\testdir\\test3.txt");
354 RemoveDirectoryA(".\\testdir\\test.txt");
355 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
356 RemoveDirectoryA(".\\testdir\\testdir2");
357 RemoveDirectoryA(".\\testdir");
362 static void test_EnumObjects(IShellFolder
*iFolder
)
364 IEnumIDList
*iEnumList
;
365 LPITEMIDLIST newPIDL
, idlArr
[10];
370 static const WORD iResults
[5][5] =
379 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
380 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
381 static const ULONG attrs
[5] =
383 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
384 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
385 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
386 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
387 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
390 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
391 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
393 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
394 * the filesystem shellfolders return S_OK even if less than 'celt' items are
395 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
396 * only ever returns a single entry per call. */
397 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
399 ok (i
== 5, "i: %d\n", i
);
401 hr
= IEnumIDList_Release(iEnumList
);
402 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
404 /* Sort them first in case of wrong order from system */
405 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
406 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
409 idlArr
[i
] = idlArr
[j
];
413 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
415 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
416 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
420 for (i
= 0; i
< 5; i
++)
423 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
424 /* Native returns all flags no matter what we ask for */
425 flags
= SFGAO_CANCOPY
;
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 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
432 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
434 flags
= SFGAO_testfor
;
435 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
436 flags
&= SFGAO_testfor
;
437 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
438 ok(flags
== attrs
[i
] ||
439 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
), /* Win9x, NT4 */
440 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
444 IMalloc_Free(ppM
, idlArr
[i
]);
447 static void test_BindToObject(void)
451 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
452 SHITEMID emptyitem
= { 0, { 0 } };
453 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
454 WCHAR wszSystemDir
[MAX_PATH
];
455 char szSystemDir
[MAX_PATH
];
457 WCHAR path
[MAX_PATH
];
458 CHAR pathA
[MAX_PATH
];
460 WCHAR wszMyComputer
[] = {
461 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
462 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
463 static const CHAR filename_html
[] = "winetest.html";
464 static const CHAR filename_txt
[] = "winetest.txt";
465 static const CHAR filename_foo
[] = "winetest.foo";
467 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
468 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
470 hr
= SHGetDesktopFolder(&psfDesktop
);
471 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
472 if (hr
!= S_OK
) return;
474 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
475 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
477 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
478 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
480 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
481 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
483 IShellFolder_Release(psfDesktop
);
487 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
488 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
489 IShellFolder_Release(psfDesktop
);
490 IMalloc_Free(ppM
, pidlMyComputer
);
491 if (hr
!= S_OK
) return;
493 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
494 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
498 /* this call segfaults on 98SE */
499 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
500 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
503 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
504 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
505 if (cChars
== 0 || cChars
>= MAX_PATH
) {
506 IShellFolder_Release(psfMyComputer
);
509 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
511 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
512 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
514 IShellFolder_Release(psfMyComputer
);
518 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
519 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
520 IShellFolder_Release(psfMyComputer
);
521 IMalloc_Free(ppM
, pidlSystemDir
);
522 if (hr
!= S_OK
) return;
524 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
525 ok (hr
== E_INVALIDARG
,
526 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
530 /* this call segfaults on 98SE */
531 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
532 ok (hr
== E_INVALIDARG
,
533 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
536 IShellFolder_Release(psfSystemDir
);
538 cChars
= GetCurrentDirectoryA(MAX_PATH
, buf
);
541 skip("Failed to get current directory, skipping tests.\n");
544 if(buf
[cChars
-1] != '\\') lstrcatA(buf
, "\\");
546 SHGetDesktopFolder(&psfDesktop
);
548 /* Attempt BindToObject on files. */
551 lstrcpyA(pathA
, buf
);
552 lstrcatA(pathA
, filename_html
);
553 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
554 if(hfile
!= INVALID_HANDLE_VALUE
)
557 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
558 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
559 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
562 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
564 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
569 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
571 broken(hr
== E_NOINTERFACE
), /* Win9x, NT4, W2K */
576 hr
= IPersist_GetClassID(pp
, &id
);
577 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
578 /* CLSID_ShellFSFolder on some w2k systems */
579 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
) || broken(IsEqualIID(&id
, &CLSID_ShellFSFolder
)),
580 "Unexpected classid %s\n", wine_dbgstr_guid(&id
));
581 IPersist_Release(pp
);
584 IShellFolder_Release(psfChild
);
591 win_skip("Failed to create .html testfile.\n");
594 lstrcpyA(pathA
, buf
);
595 lstrcatA(pathA
, filename_txt
);
596 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
597 if(hfile
!= INVALID_HANDLE_VALUE
)
600 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
601 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
602 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
605 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
606 ok(hr
== E_FAIL
|| /* Vista+ */
607 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
608 hr
== E_INVALIDARG
|| /* W2K item in top dir */
609 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
611 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
617 win_skip("Failed to create .txt testfile.\n");
620 lstrcpyA(pathA
, buf
);
621 lstrcatA(pathA
, filename_foo
);
622 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
623 if(hfile
!= INVALID_HANDLE_VALUE
)
626 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
627 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
628 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
631 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
632 ok(hr
== E_FAIL
|| /* Vista+ */
633 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
634 hr
== E_INVALIDARG
|| /* W2K item in top dir */
635 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
637 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
643 win_skip("Failed to create .foo testfile.\n");
645 /* And on the desktop */
646 if(pSHGetSpecialFolderPathA
)
648 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
649 lstrcatA(pathA
, "\\");
650 lstrcatA(pathA
, filename_html
);
651 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
652 if(hfile
!= INVALID_HANDLE_VALUE
)
655 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
656 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
657 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
660 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
662 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
664 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
667 if(!DeleteFileA(pathA
))
668 trace("Failed to delete: %d\n", GetLastError());
672 win_skip("Failed to create .html testfile.\n");
674 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
675 lstrcatA(pathA
, "\\");
676 lstrcatA(pathA
, filename_foo
);
677 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
678 if(hfile
!= INVALID_HANDLE_VALUE
)
681 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
682 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
683 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
686 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
687 ok(hr
== E_FAIL
|| /* Vista+ */
688 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
689 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
691 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
697 win_skip("Failed to create .foo testfile.\n");
700 IShellFolder_Release(psfDesktop
);
703 static void test_GetDisplayName(void)
708 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
709 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
712 LPSHELLFOLDER psfDesktop
, psfPersonal
;
714 SHITEMID emptyitem
= { 0, { 0 } };
715 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
716 LPCITEMIDLIST pidlLast
;
717 static const CHAR szFileName
[] = "winetest.foo";
718 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
719 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
721 /* I'm trying to figure if there is a functional difference between calling
722 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
723 * binding to the shellfolder. One thing I thought of was that perhaps
724 * SHGetPathFromIDListW would be able to get the path to a file, which does
725 * not exist anymore, while the other method wouldn't. It turns out there's
726 * no functional difference in this respect.
729 if(!pSHGetSpecialFolderPathA
) {
730 win_skip("SHGetSpecialFolderPathA is not available\n");
734 /* First creating a directory in MyDocuments and a file in this directory. */
735 result
= pSHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
736 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
739 /* Use ANSI file functions so this works on Windows 9x */
740 lstrcatA(szTestDir
, "\\winetest");
741 CreateDirectoryA(szTestDir
, NULL
);
742 attr
=GetFileAttributesA(szTestDir
);
743 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
745 ok(0, "unable to create the '%s' directory\n", szTestDir
);
749 lstrcpyA(szTestFile
, szTestDir
);
750 lstrcatA(szTestFile
, "\\");
751 lstrcatA(szTestFile
, szFileName
);
752 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
753 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
754 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
755 CloseHandle(hTestFile
);
757 /* Getting an itemidlist for the file. */
758 hr
= SHGetDesktopFolder(&psfDesktop
);
759 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
760 if (hr
!= S_OK
) return;
762 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
764 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
765 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
767 IShellFolder_Release(psfDesktop
);
771 pidlLast
= pILFindLastID(pidlTestFile
);
772 ok(pidlLast
->mkid
.cb
>=76 ||
773 broken(pidlLast
->mkid
.cb
== 28) || /* W2K */
774 broken(pidlLast
->mkid
.cb
== 40), /* Win9x, WinME */
775 "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
776 if (pidlLast
->mkid
.cb
>= 28) {
777 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
778 "Filename should be stored as ansi-string at this position!\n");
780 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
781 if (pidlLast
->mkid
.cb
>= 76) {
782 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
783 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
784 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)) || /* Win7 */
785 (pidlLast
->mkid
.cb
>= 102 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[72], wszFileName
)), /* Win8 */
786 "Filename should be stored as wchar-string at this position!\n");
789 /* It seems as if we cannot bind to regular files on windows, but only directories.
791 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
792 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
793 hr
== E_NOTIMPL
|| /* Vista */
794 broken(hr
== S_OK
), /* Win9x, W2K */
797 IUnknown_Release(psfFile
);
800 if (!pSHBindToParent
)
802 win_skip("SHBindToParent is missing\n");
803 DeleteFileA(szTestFile
);
804 RemoveDirectoryA(szTestDir
);
808 /* Some tests for IShellFolder::SetNameOf */
809 if (pSHGetFolderPathAndSubDirA
)
811 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
812 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
814 /* It's ok to use this fixed path. Call will fail anyway. */
815 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
816 LPITEMIDLIST pidlNew
;
818 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
819 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
820 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
823 ok (((LPITEMIDLIST
)((LPBYTE
)pidlNew
+pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
824 "pidl returned from SetNameOf should be simple!\n");
826 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
827 * is implemented on top of SHFileOperation in WinXP. */
828 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
,
829 SHGDN_FORPARSING
, NULL
);
830 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
832 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
833 * SHGDN flags specify an absolute path. */
834 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
835 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
840 IShellFolder_Release(psfPersonal
);
844 win_skip("Avoid needs of interaction on Win2k\n");
846 /* Deleting the file and the directory */
847 DeleteFileA(szTestFile
);
848 RemoveDirectoryA(szTestDir
);
850 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
851 if (pSHGetPathFromIDListW
)
853 result
= pSHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
854 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
855 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
858 /* SHBindToParent fails, if called with a NULL PIDL. */
859 hr
= pSHBindToParent(NULL
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
860 ok (hr
!= S_OK
, "SHBindToParent(NULL) should fail!\n");
862 /* But it succeeds with an empty PIDL. */
863 hr
= pSHBindToParent(pidlEmpty
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
864 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
865 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
867 IShellFolder_Release(psfPersonal
);
869 /* Binding to the folder and querying the display name of the file also works. */
870 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
871 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
873 IShellFolder_Release(psfDesktop
);
877 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
878 * pidlTestFile (In accordance with MSDN). */
879 ok (pILFindLastID(pidlTestFile
) == pidlLast
,
880 "SHBindToParent doesn't return the last id of the pidl param!\n");
882 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
883 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
885 IShellFolder_Release(psfDesktop
);
886 IShellFolder_Release(psfPersonal
);
892 hr
= pStrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
893 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
894 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
897 ILFree(pidlTestFile
);
898 IShellFolder_Release(psfDesktop
);
899 IShellFolder_Release(psfPersonal
);
902 static void test_CallForAttributes(void)
908 LPSHELLFOLDER psfDesktop
;
909 LPITEMIDLIST pidlMyDocuments
;
910 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
911 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
912 static const WCHAR wszCallForAttributes
[] = {
913 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
914 static const WCHAR wszMyDocumentsKey
[] = {
915 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
916 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
917 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
918 WCHAR wszMyDocuments
[] = {
919 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
920 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
922 /* For the root of a namespace extension, the attributes are not queried by binding
923 * to the object and calling GetAttributesOf. Instead, the attributes are read from
924 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
926 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
927 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
928 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
929 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
931 hr
= SHGetDesktopFolder(&psfDesktop
);
932 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
933 if (hr
!= S_OK
) return;
935 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
936 &pidlMyDocuments
, NULL
);
938 broken(hr
== E_INVALIDARG
), /* Win95, NT4 */
939 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
941 IShellFolder_Release(psfDesktop
);
945 dwAttributes
= 0xffffffff;
946 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
947 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
948 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
950 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
951 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
952 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
953 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
955 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
956 * key. So the test will return at this point, if run on wine.
958 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
959 ok (lResult
== ERROR_SUCCESS
||
960 lResult
== ERROR_ACCESS_DENIED
,
961 "RegOpenKeyEx failed! result: %08x\n", lResult
);
962 if (lResult
!= ERROR_SUCCESS
) {
963 if (lResult
== ERROR_ACCESS_DENIED
)
964 skip("Not enough rights to open the registry key\n");
965 IMalloc_Free(ppM
, pidlMyDocuments
);
966 IShellFolder_Release(psfDesktop
);
970 /* Query MyDocuments' Attributes value, to be able to restore it later. */
971 dwSize
= sizeof(DWORD
);
972 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
973 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
974 if (lResult
!= ERROR_SUCCESS
) {
976 IMalloc_Free(ppM
, pidlMyDocuments
);
977 IShellFolder_Release(psfDesktop
);
981 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
982 dwSize
= sizeof(DWORD
);
983 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
984 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
985 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
986 if (lResult
!= ERROR_SUCCESS
) {
988 IMalloc_Free(ppM
, pidlMyDocuments
);
989 IShellFolder_Release(psfDesktop
);
993 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
994 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
995 * SFGAO_FILESYSTEM attributes. */
996 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
997 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
998 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
999 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1000 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
1002 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
1003 * GetAttributesOf. It seems that once there is a single attribute queried, for which
1004 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
1005 * the flags in Attributes are ignored.
1007 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
1008 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
1009 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
1010 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
1012 ok (dwAttributes
== SFGAO_FILESYSTEM
,
1013 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
1016 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
1017 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
1018 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1019 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
1021 IMalloc_Free(ppM
, pidlMyDocuments
);
1022 IShellFolder_Release(psfDesktop
);
1025 static void test_GetAttributesOf(void)
1028 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
1029 SHITEMID emptyitem
= { 0, { 0 } };
1030 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1031 LPITEMIDLIST pidlMyComputer
;
1033 static const DWORD desktopFlags
[] = {
1035 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
|
1036 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1038 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_STREAM
| SFGAO_FILESYSANCESTOR
|
1039 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1040 /* WinMe, Win9x, WinNT*/
1041 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSANCESTOR
|
1042 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1044 static const DWORD myComputerFlags
[] = {
1046 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
1047 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1049 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_STREAM
|
1050 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1051 /* WinMe, Win9x, WinNT */
1052 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1053 SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1054 /* Win95, WinNT when queried directly */
1055 SFGAO_CANLINK
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1056 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1058 WCHAR wszMyComputer
[] = {
1059 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1060 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1061 char cCurrDirA
[MAX_PATH
] = {0};
1062 WCHAR cCurrDirW
[MAX_PATH
];
1063 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
1064 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1065 ITEMIDLIST
*newPIDL
;
1067 BOOL foundFlagsMatch
;
1069 hr
= SHGetDesktopFolder(&psfDesktop
);
1070 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1071 if (hr
!= S_OK
) return;
1073 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
1074 dwFlags
= 0xffffffff;
1075 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
1076 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
1077 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1078 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1080 if (desktopFlags
[i
] == dwFlags
)
1081 foundFlagsMatch
= TRUE
;
1083 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1085 /* .. or with no itemidlist at all. */
1086 dwFlags
= 0xffffffff;
1087 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
1088 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1089 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1090 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1092 if (desktopFlags
[i
] == dwFlags
)
1093 foundFlagsMatch
= TRUE
;
1095 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1097 /* Testing the attributes of the MyComputer shellfolder */
1098 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1099 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1101 IShellFolder_Release(psfDesktop
);
1105 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
1106 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
1108 dwFlags
= 0xffffffff;
1109 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
1110 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
1111 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1112 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1114 if ((myComputerFlags
[i
] | SFGAO_CANLINK
) == dwFlags
)
1115 foundFlagsMatch
= TRUE
;
1118 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1120 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
1121 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
1122 IShellFolder_Release(psfDesktop
);
1123 IMalloc_Free(ppM
, pidlMyComputer
);
1124 if (hr
!= S_OK
) return;
1126 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
1128 ok (hr
== E_INVALIDARG
||
1129 broken(hr
== S_OK
), /* W2K and earlier */
1130 "MyComputer->GetAttributesOf(emtpy pidl) should fail! hr = %08x\n", hr
);
1132 dwFlags
= 0xffffffff;
1133 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
1134 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1135 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1136 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1138 if (myComputerFlags
[i
] == dwFlags
)
1139 foundFlagsMatch
= TRUE
;
1142 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1144 IShellFolder_Release(psfMyComputer
);
1146 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1147 len
= lstrlenA(cCurrDirA
);
1150 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1153 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1154 cCurrDirA
[len
-1] = 0;
1156 /* create test directory */
1157 CreateFilesFolders();
1159 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1161 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1162 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1164 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1165 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1167 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1168 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1170 IMalloc_Free(ppM
, newPIDL
);
1172 /* get relative PIDL */
1173 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1174 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1176 /* test the shell attributes of the test directory using the relative PIDL */
1177 dwFlags
= SFGAO_FOLDER
;
1178 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1179 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1180 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1183 IMalloc_Free(ppM
, newPIDL
);
1185 /* append testdirectory name to path */
1186 if (cCurrDirA
[len
-1] == '\\')
1187 cCurrDirA
[len
-1] = 0;
1188 lstrcatA(cCurrDirA
, "\\testdir");
1189 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1191 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1192 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1194 /* test the shell attributes of the test directory using the absolute PIDL */
1195 dwFlags
= SFGAO_FOLDER
;
1196 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1197 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1198 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1201 IMalloc_Free(ppM
, newPIDL
);
1203 IShellFolder_Release(testIShellFolder
);
1207 IShellFolder_Release(IDesktopFolder
);
1210 static void test_SHGetPathFromIDList(void)
1212 SHITEMID emptyitem
= { 0, { 0 } };
1213 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1214 LPITEMIDLIST pidlMyComputer
;
1215 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1218 LPSHELLFOLDER psfDesktop
;
1219 WCHAR wszMyComputer
[] = {
1220 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1221 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1222 WCHAR wszFileName
[MAX_PATH
];
1223 LPITEMIDLIST pidlTestFile
;
1226 static WCHAR wszTestFile
[] = {
1227 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1228 LPITEMIDLIST pidlPrograms
;
1230 if(!pSHGetPathFromIDListW
|| !pSHGetSpecialFolderPathW
)
1232 win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
1236 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1239 result
= pSHGetPathFromIDListW(NULL
, wszPath
);
1240 ok(!result
, "Expected failure\n");
1241 ok(!wszPath
[0], "Expected empty string\n");
1243 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1244 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1245 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1246 if (!result
) return;
1248 /* Check if we are on Win9x */
1249 SetLastError(0xdeadbeef);
1250 lstrcmpiW(wszDesktop
, wszDesktop
);
1251 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1253 win_skip("Most W-calls are not implemented\n");
1257 result
= pSHGetPathFromIDListW(pidlEmpty
, wszPath
);
1258 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1259 if (!result
) return;
1260 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1262 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1263 hr
= SHGetDesktopFolder(&psfDesktop
);
1264 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1265 if (hr
!= S_OK
) return;
1267 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1268 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1270 IShellFolder_Release(psfDesktop
);
1274 SetLastError(0xdeadbeef);
1277 result
= pSHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1278 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1279 ok (GetLastError()==0xdeadbeef ||
1280 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1281 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1282 ok (!wszPath
[0], "Expected empty path\n");
1284 IShellFolder_Release(psfDesktop
);
1288 IMalloc_Free(ppM
, pidlMyComputer
);
1290 result
= pSHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1291 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1293 IShellFolder_Release(psfDesktop
);
1296 myPathAddBackslashW(wszFileName
);
1297 lstrcatW(wszFileName
, wszTestFile
);
1298 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1299 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1300 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1301 IShellFolder_Release(psfDesktop
);
1304 CloseHandle(hTestFile
);
1306 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1307 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1309 IShellFolder_Release(psfDesktop
);
1310 DeleteFileW(wszFileName
);
1311 IMalloc_Free(ppM
, pidlTestFile
);
1315 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1316 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1317 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1318 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1319 IShellFolder_Release(psfDesktop
);
1320 DeleteFileW(wszFileName
);
1322 IMalloc_Free(ppM
, pidlTestFile
);
1327 pStrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1328 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1329 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1330 "returned incorrect path for file placed on desktop\n");
1333 result
= pSHGetPathFromIDListW(pidlTestFile
, wszPath
);
1334 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1335 IMalloc_Free(ppM
, pidlTestFile
);
1336 if (!result
) return;
1337 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1340 /* Test if we can get the path from the start menu "program files" PIDL. */
1341 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1342 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1344 SetLastError(0xdeadbeef);
1345 result
= pSHGetPathFromIDListW(pidlPrograms
, wszPath
);
1346 IMalloc_Free(ppM
, pidlPrograms
);
1347 ok(result
, "SHGetPathFromIDListW failed\n");
1350 static void test_EnumObjects_and_CompareIDs(void)
1352 ITEMIDLIST
*newPIDL
;
1353 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1354 char cCurrDirA
[MAX_PATH
] = {0};
1355 static const CHAR cTestDirA
[] = "\\testdir";
1356 WCHAR cTestDirW
[MAX_PATH
];
1360 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1361 len
= lstrlenA(cCurrDirA
);
1364 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1367 if(cCurrDirA
[len
-1] == '\\')
1368 cCurrDirA
[len
-1] = 0;
1370 lstrcatA(cCurrDirA
, cTestDirA
);
1371 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1373 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1374 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1376 CreateFilesFolders();
1378 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1379 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1381 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1382 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1384 test_EnumObjects(testIShellFolder
);
1386 IShellFolder_Release(testIShellFolder
);
1390 IMalloc_Free(ppM
, newPIDL
);
1392 IShellFolder_Release(IDesktopFolder
);
1395 /* A simple implementation of an IPropertyBag, which returns fixed values for
1396 * 'Target' and 'Attributes' properties.
1398 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1402 return E_INVALIDARG
;
1404 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1407 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1408 return E_NOINTERFACE
;
1411 IPropertyBag_AddRef(iface
);
1415 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1419 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1423 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1424 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1426 static const WCHAR wszTargetSpecialFolder
[] = {
1427 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1428 static const WCHAR wszTarget
[] = {
1429 'T','a','r','g','e','t',0 };
1430 static const WCHAR wszAttributes
[] = {
1431 'A','t','t','r','i','b','u','t','e','s',0 };
1432 static const WCHAR wszResolveLinkFlags
[] = {
1433 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1434 static const WCHAR wszTargetKnownFolder
[] = {
1435 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1436 static const WCHAR wszCLSID
[] = {
1437 'C','L','S','I','D',0 };
1439 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1440 ok(V_VT(pVar
) == VT_I4
||
1441 broken(V_VT(pVar
) == VT_BSTR
), /* Win2k */
1442 "Wrong variant type for 'TargetSpecialFolder' property!\n");
1443 return E_INVALIDARG
;
1446 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1448 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1449 return E_INVALIDARG
;
1452 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1453 WCHAR wszPath
[MAX_PATH
];
1456 ok(V_VT(pVar
) == VT_BSTR
||
1457 broken(V_VT(pVar
) == VT_EMPTY
), /* Win2k */
1458 "Wrong variant type for 'Target' property!\n");
1459 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1461 result
= pSHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1462 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1463 if (!result
) return E_INVALIDARG
;
1465 V_BSTR(pVar
) = SysAllocString(wszPath
);
1469 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1470 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1471 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1472 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1473 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1477 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1478 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1480 return E_INVALIDARG
;
1483 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1484 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1486 return E_INVALIDARG
;
1489 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1490 return E_INVALIDARG
;
1493 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1496 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1500 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1501 InitPropertyBag_IPropertyBag_QueryInterface
,
1502 InitPropertyBag_IPropertyBag_AddRef
,
1503 InitPropertyBag_IPropertyBag_Release
,
1504 InitPropertyBag_IPropertyBag_Read
,
1505 InitPropertyBag_IPropertyBag_Write
1508 static struct IPropertyBag InitPropertyBag
= {
1509 &InitPropertyBag_IPropertyBagVtbl
1512 static void test_FolderShortcut(void) {
1513 IPersistPropertyBag
*pPersistPropertyBag
;
1514 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1515 IPersistFolder3
*pPersistFolder3
;
1518 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1521 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1523 WCHAR wszWineTestFolder
[] = {
1524 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1525 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1526 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1527 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1528 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1529 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1530 'N','a','m','e','S','p','a','c','e','\\',
1531 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1532 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1534 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1535 static const GUID CLSID_UnixDosFolder
=
1536 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1538 if (!pSHGetSpecialFolderPathW
|| !pStrRetToBufW
) {
1539 win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
1543 if (!pSHGetFolderPathAndSubDirA
)
1545 win_skip("FolderShortcut test doesn't work on Win2k\n");
1549 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1550 * via their IPersistPropertyBag interface. And that the target folder
1551 * is taken from the IPropertyBag's 'Target' property.
1553 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1554 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1555 if (hr
== REGDB_E_CLASSNOTREG
) {
1556 win_skip("CLSID_FolderShortcut is not implemented\n");
1559 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1560 if (hr
!= S_OK
) return;
1562 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1563 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1565 IPersistPropertyBag_Release(pPersistPropertyBag
);
1569 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1570 (LPVOID
*)&pShellFolder
);
1571 IPersistPropertyBag_Release(pPersistPropertyBag
);
1572 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1573 if (hr
!= S_OK
) return;
1575 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1576 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1578 IShellFolder_Release(pShellFolder
);
1582 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1583 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1584 if (!result
) return;
1586 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1587 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1589 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1590 IShellFolder_Release(pShellFolder
);
1591 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1592 if (hr
!= S_OK
) return;
1594 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1595 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1596 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1598 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1599 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1600 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1602 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1603 * shell namespace. The target folder, read from the property bag above, remains untouched.
1604 * The following tests show this: The itemidlist for some imaginary shellfolder object
1605 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1606 * itemidlist, but GetDisplayNameOf still returns the path from above.
1608 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1609 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1610 if (hr
!= S_OK
) return;
1612 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1613 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1614 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1615 RegCloseKey(hShellExtKey
);
1616 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1617 &pidlWineTestFolder
, NULL
);
1618 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1619 IShellFolder_Release(pDesktopFolder
);
1620 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1621 if (hr
!= S_OK
) return;
1623 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1624 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1626 IPersistFolder3_Release(pPersistFolder3
);
1627 pILFree(pidlWineTestFolder
);
1631 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1632 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1633 ok(pILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1634 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1635 pILFree(pidlCurrentFolder
);
1636 pILFree(pidlWineTestFolder
);
1638 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1639 IPersistFolder3_Release(pPersistFolder3
);
1640 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1641 if (hr
!= S_OK
) return;
1643 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1644 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1646 IShellFolder_Release(pShellFolder
);
1650 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1651 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1653 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1654 * but ShellFSFolders. */
1655 myPathAddBackslashW(wszDesktopPath
);
1656 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1657 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1658 IShellFolder_Release(pShellFolder
);
1662 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1663 &pidlSubFolder
, NULL
);
1664 RemoveDirectoryW(wszDesktopPath
);
1665 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1667 IShellFolder_Release(pShellFolder
);
1671 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1672 (LPVOID
*)&pPersistFolder3
);
1673 IShellFolder_Release(pShellFolder
);
1674 pILFree(pidlSubFolder
);
1675 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1679 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1680 * a little bit and also allow CLSID_UnixDosFolder. */
1681 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1682 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1683 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1684 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1686 IPersistFolder3_Release(pPersistFolder3
);
1689 #include "pshpack1.h"
1690 struct FileStructA
{
1694 WORD uFileDate
; /* In our current implementation this is */
1695 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1700 struct FileStructW
{
1701 WORD cbLen
; /* Length of this element. */
1702 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1703 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1704 WORD uTime
; /* (this is currently speculation) */
1705 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1706 WORD uTime2
; /* (this is currently speculation) */
1707 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1708 WCHAR wszName
[1]; /* The long filename in unicode. */
1709 /* Just for documentation: Right after the unicode string: */
1710 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1711 * SHITEMID->cb == uOffset + cbLen */
1713 #include "poppack.h"
1715 static void test_ITEMIDLIST_format(void) {
1716 WCHAR wszPersonal
[MAX_PATH
];
1717 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1718 LPITEMIDLIST pidlPersonal
, pidlFile
;
1722 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1723 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1726 if (!pSHGetSpecialFolderPathW
) return;
1728 bResult
= pSHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1729 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1730 if (!bResult
) return;
1732 SetLastError(0xdeadbeef);
1733 bResult
= SetCurrentDirectoryW(wszPersonal
);
1734 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1735 win_skip("Most W-calls are not implemented\n");
1738 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1739 if (!bResult
) return;
1741 hr
= SHGetDesktopFolder(&psfDesktop
);
1742 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1743 if (hr
!= S_OK
) return;
1745 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1746 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1748 IShellFolder_Release(psfDesktop
);
1752 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1753 (LPVOID
*)&psfPersonal
);
1754 IShellFolder_Release(psfDesktop
);
1755 pILFree(pidlPersonal
);
1756 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1757 if (hr
!= S_OK
) return;
1759 for (i
=0; i
<3; i
++) {
1760 CHAR szFile
[MAX_PATH
];
1761 struct FileStructA
*pFileStructA
;
1764 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1766 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1767 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1768 if (hFile
== INVALID_HANDLE_VALUE
) {
1769 IShellFolder_Release(psfPersonal
);
1774 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1775 DeleteFileW(wszFile
[i
]);
1776 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1778 IShellFolder_Release(psfPersonal
);
1782 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1783 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1784 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1785 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1787 if (i
< 2) /* First two file names are already in valid 8.3 format */
1788 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1790 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1791 * can't implement this correctly, since unix filesystems don't support
1792 * this nasty short/long filename stuff. So we'll probably stay with our
1793 * current habit of storing the long filename here, which seems to work
1796 ok(pidlFile
->mkid
.abID
[18] == '~' ||
1797 broken(pidlFile
->mkid
.abID
[34] == '~'), /* Win2k */
1798 "Should be derived 8.3 name!\n");
1800 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1801 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0' ||
1802 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1), /* Win2k */
1803 "Alignment byte, where there shouldn't be!\n");
1805 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1806 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1807 "There should be an alignment byte, but isn't!\n");
1809 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1810 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1811 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1812 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)) ||
1813 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1) || /* Win2k on short names */
1814 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 12 + 1), /* Win2k on long names */
1815 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1817 if (cbOffset
>= sizeof(struct FileStructA
) &&
1818 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1820 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1821 WCHAR
*name
= pFileStructW
->wszName
;
1823 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1824 "FileStructW's offset and length should add up to the PIDL's length!\n");
1826 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1827 /* Since we just created the file, time of creation,
1828 * time of last access and time of last write access just be the same.
1829 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1830 * after the first run. I do remember something with NTFS keeping the creation time
1831 * if a file is deleted and then created again within a couple of seconds or so.
1832 * Might be the reason. */
1833 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1834 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1835 "Last write time should match creation time!\n");
1837 /* On FAT filesystems the last access time is midnight
1838 local time, so the values of uDate2 and uTime2 will
1839 depend on the local timezone. If the times are exactly
1840 equal then the dates should be identical for both FAT
1841 and NTFS as no timezone is more than 1 day away from UTC.
1843 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1845 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1846 "Last write date and time should match last access date and time!\n");
1850 /* Filesystem may be FAT. Check date within 1 day
1851 and seconds are zero. */
1852 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1853 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1854 "Last access time on FAT filesystems should have zero seconds.\n");
1855 /* TODO: Perform check for date being within one day.*/
1858 ok (!lstrcmpW(wszFile
[i
], name
) ||
1859 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1860 !lstrcmpW(wszFile
[i
], name
+ 11) || /* Win7 */
1861 !lstrcmpW(wszFile
[i
], name
+ 13), /* Win8 */
1862 "The filename should be stored in unicode at this position!\n");
1869 IShellFolder_Release(psfPersonal
);
1872 static void test_SHGetFolderPathA(void)
1874 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1876 char path
[MAX_PATH
];
1877 char path_x86
[MAX_PATH
];
1878 char path_key
[MAX_PATH
];
1882 if (!pSHGetFolderPathA
)
1884 win_skip("SHGetFolderPathA not present\n");
1887 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1889 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1890 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1891 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1894 win_skip( "Program Files (x86) not supported\n" );
1897 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1900 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1901 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1902 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1906 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1908 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1910 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1912 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1914 DWORD type
, count
= sizeof(path_x86
);
1915 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1917 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1918 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1920 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1924 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1925 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1926 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1929 win_skip( "Common Files (x86) not supported\n" );
1932 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1935 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1936 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1937 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1941 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1943 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1945 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1947 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1949 DWORD type
, count
= sizeof(path_x86
);
1950 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1952 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1953 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1955 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1959 static void test_SHGetFolderPathAndSubDirA(void)
1965 static const char wine
[] = "wine";
1966 static const char winetemp
[] = "wine\\temp";
1967 static char appdata
[MAX_PATH
];
1968 static char testpath
[MAX_PATH
];
1969 static char toolongpath
[MAX_PATH
+1];
1971 if(!pSHGetFolderPathAndSubDirA
)
1973 win_skip("SHGetFolderPathAndSubDirA not present!\n");
1977 if(!pSHGetFolderPathA
) {
1978 win_skip("SHGetFolderPathA not present!\n");
1981 if(FAILED(pSHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
1983 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1987 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1988 delret
= RemoveDirectoryA(testpath
);
1989 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
1990 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1994 sprintf(testpath
, "%s\\%s", appdata
, wine
);
1995 delret
= RemoveDirectoryA(testpath
);
1996 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
1997 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
2001 /* test invalid second parameter */
2002 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
2003 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
2005 /* test fourth parameter */
2006 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
2008 case S_OK
: /* winvista */
2009 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2010 "expected %s to start with %s\n", testpath
, appdata
);
2011 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2012 "expected %s to end with %s\n", testpath
, winetemp
);
2014 case E_INVALIDARG
: /* winxp, win2k3 */
2017 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2020 /* test fifth parameter */
2022 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, testpath
);
2023 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2024 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2027 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "", testpath
);
2028 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2029 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2032 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
2033 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2034 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2036 for(i
=0; i
< MAX_PATH
; i
++)
2037 toolongpath
[i
] = '0' + i
% 10;
2038 toolongpath
[MAX_PATH
] = '\0';
2039 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
2040 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
2041 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
2044 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
2045 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2047 /* test a not existing path */
2049 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2050 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
2051 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
2053 /* create a directory inside a not existing directory */
2055 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2056 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2057 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2058 "expected %s to start with %s\n", testpath
, appdata
);
2059 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2060 "expected %s to end with %s\n", testpath
, winetemp
);
2061 dwret
= GetFileAttributesA(testpath
);
2062 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
2065 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2066 RemoveDirectoryA(testpath
);
2067 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2068 RemoveDirectoryA(testpath
);
2071 static void test_LocalizedNames(void)
2073 static char cCurrDirA
[MAX_PATH
];
2074 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
2075 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
2076 ITEMIDLIST
*newPIDL
;
2079 static char resourcefile
[MAX_PATH
];
2085 static const char desktopini_contents1
[] =
2086 "[.ShellClassInfo]\r\n"
2087 "LocalizedResourceName=@";
2088 static const char desktopini_contents2
[] =
2090 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
2091 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
2093 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
2094 CreateDirectoryA(".\\testfolder", NULL
);
2096 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
2098 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
2100 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
2101 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2102 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
2103 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
2104 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
2105 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
2106 ok(ret
, "WriteFile failed %i\n", GetLastError());
2109 /* get IShellFolder for parent */
2110 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
2111 len
= lstrlenA(cCurrDirA
);
2114 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
2117 if(cCurrDirA
[len
-1] == '\\')
2118 cCurrDirA
[len
-1] = 0;
2120 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
2122 hr
= SHGetDesktopFolder(&IDesktopFolder
);
2123 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
2125 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
2126 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2128 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
2129 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
2131 IMalloc_Free(ppM
, newPIDL
);
2133 /* windows reads the display name from the resource */
2134 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
2135 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2137 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
2138 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2140 if (hr
== S_OK
&& pStrRetToBufW
)
2142 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2143 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2145 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2146 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2147 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2150 /* editing name is also read from the resource */
2151 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
2152 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2154 if (hr
== S_OK
&& pStrRetToBufW
)
2156 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2157 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2159 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2160 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2161 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2164 /* parsing name is unchanged */
2165 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
2166 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2168 if (hr
== S_OK
&& pStrRetToBufW
)
2170 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2171 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2172 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2175 IShellFolder_Release(IDesktopFolder
);
2176 IShellFolder_Release(testIShellFolder
);
2178 IMalloc_Free(ppM
, newPIDL
);
2181 DeleteFileA(".\\testfolder\\desktop.ini");
2182 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
2183 RemoveDirectoryA(".\\testfolder");
2186 static void test_SHCreateShellItem(void)
2188 IShellItem
*shellitem
, *shellitem2
;
2189 IPersistIDList
*persistidl
;
2190 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2192 char curdirA
[MAX_PATH
];
2193 WCHAR curdirW
[MAX_PATH
];
2194 WCHAR fnbufW
[MAX_PATH
];
2195 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2196 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2198 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2200 if (!pSHCreateShellItem
)
2202 win_skip("SHCreateShellItem isn't available\n");
2208 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2212 if(pSHGetSpecialFolderLocation
)
2214 ret
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2215 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2219 win_skip("pSHGetSpecialFolderLocation missing.\n");
2220 pidl_desktop
= NULL
;
2223 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2225 ret
= SHGetDesktopFolder(&desktopfolder
);
2226 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2228 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2229 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2231 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2232 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2234 CreateTestFile(".\\testfile");
2236 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2237 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2239 pidl_abstestfile
= pILCombine(pidl_cwd
, pidl_testfile
);
2241 shellitem
= (void*)0xdeadbeef;
2242 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2243 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2244 ok(shellitem
== 0, "Got %p\n", shellitem
);
2246 if (0) /* crashes on Windows XP */
2248 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2249 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2250 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2251 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2254 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2255 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2258 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2259 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2262 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2263 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2266 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2269 IPersistIDList_Release(persistidl
);
2271 IShellItem_Release(shellitem
);
2274 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2275 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2278 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2279 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2282 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2283 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2286 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2289 IPersistIDList_Release(persistidl
);
2292 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2293 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2296 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2297 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2300 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2301 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2304 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2307 IPersistIDList_Release(persistidl
);
2309 IShellItem_Release(shellitem2
);
2312 IShellItem_Release(shellitem
);
2315 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2316 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2319 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2320 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2323 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2324 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2327 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2330 IPersistIDList_Release(persistidl
);
2332 IShellItem_Release(shellitem
);
2335 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2336 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2337 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2340 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2341 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2344 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2345 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2348 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2351 IPersistIDList_Release(persistidl
);
2353 IShellItem_Release(shellitem
);
2356 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2357 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2360 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2361 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2364 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2365 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2368 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2371 IPersistIDList_Release(persistidl
);
2374 IShellItem_Release(shellitem
);
2377 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2378 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2381 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2382 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2383 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2384 IShellItem_Release(shellitem
);
2387 /* SHCreateItemFromParsingName */
2388 if(pSHCreateItemFromParsingName
)
2392 /* Crashes under windows 7 */
2393 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2396 shellitem
= (void*)0xdeadbeef;
2397 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2398 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2399 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2401 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2402 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2403 "SHCreateItemFromParsingName returned %x\n", ret
);
2404 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2406 lstrcpyW(fnbufW
, curdirW
);
2407 myPathAddBackslashW(fnbufW
);
2408 lstrcatW(fnbufW
, testfileW
);
2410 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2411 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2415 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2416 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2419 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2420 CoTaskMemFree(tmp_fname
);
2422 IShellItem_Release(shellitem
);
2426 win_skip("No SHCreateItemFromParsingName\n");
2429 /* SHCreateItemFromIDList */
2430 if(pSHCreateItemFromIDList
)
2434 /* Crashes under win7 */
2435 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2438 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2439 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2441 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2442 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2445 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2446 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2449 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2450 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2453 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2456 IPersistIDList_Release(persistidl
);
2458 IShellItem_Release(shellitem
);
2461 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2462 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2465 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2466 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2469 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2470 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2473 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2476 IPersistIDList_Release(persistidl
);
2478 IShellItem_Release(shellitem
);
2482 win_skip("No SHCreateItemFromIDList\n");
2484 DeleteFileA(".\\testfile");
2485 pILFree(pidl_abstestfile
);
2486 pILFree(pidl_testfile
);
2487 pILFree(pidl_desktop
);
2489 IShellFolder_Release(currentfolder
);
2490 IShellFolder_Release(desktopfolder
);
2493 static void test_SHGetNameFromIDList(void)
2495 IShellItem
*shellitem
;
2500 static const DWORD flags
[] = {
2501 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2502 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2503 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2504 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2506 if(!pSHGetNameFromIDList
)
2508 win_skip("SHGetNameFromIDList missing.\n");
2512 /* These should be available on any platform that passed the above test. */
2513 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2514 ok(pSHBindToParent
!= NULL
, "SHBindToParent missing.\n");
2515 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
2516 ok(pStrRetToBufW
!= NULL
, "StrRetToBufW missing.\n");
2520 /* Crashes under win7 */
2521 pSHGetNameFromIDList(NULL
, 0, NULL
);
2524 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2525 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2527 /* Test the desktop */
2528 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2529 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2530 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2531 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2534 WCHAR
*nameSI
, *nameSH
;
2535 WCHAR buf
[MAX_PATH
];
2536 HRESULT hrSI
, hrSH
, hrSF
;
2541 SHGetDesktopFolder(&psf
);
2542 for(i
= 0; flags
[i
] != -1234; i
++)
2544 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2545 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2546 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2547 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2548 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2549 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2551 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2552 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2556 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2558 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2560 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2562 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2563 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2565 IShellFolder_Release(psf
);
2567 if(pSHGetPathFromIDListW
){
2568 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2569 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2570 res
= pSHGetPathFromIDListW(pidl
, buf
);
2571 ok(res
== TRUE
, "Got %d\n", res
);
2572 if(SUCCEEDED(hrSI
) && res
)
2573 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2574 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2576 win_skip("pSHGetPathFromIDListW not available\n");
2578 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2579 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2580 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2582 IShellItem_Release(shellitem
);
2586 /* Test the control panel */
2587 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2588 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2589 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2590 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2593 WCHAR
*nameSI
, *nameSH
;
2594 WCHAR buf
[MAX_PATH
];
2595 HRESULT hrSI
, hrSH
, hrSF
;
2600 SHGetDesktopFolder(&psf
);
2601 for(i
= 0; flags
[i
] != -1234; i
++)
2603 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2604 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2605 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2606 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2607 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2608 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2610 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2611 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2615 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2617 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2619 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2621 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2622 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2624 IShellFolder_Release(psf
);
2626 if(pSHGetPathFromIDListW
){
2627 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2628 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2629 res
= pSHGetPathFromIDListW(pidl
, buf
);
2630 ok(res
== FALSE
, "Got %d\n", res
);
2631 if(SUCCEEDED(hrSI
) && res
)
2632 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2633 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2635 win_skip("pSHGetPathFromIDListW not available\n");
2637 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2638 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2639 "Got 0x%08x\n", hres
);
2640 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2642 IShellItem_Release(shellitem
);
2647 static void test_SHGetItemFromDataObject(void)
2649 IShellFolder
*psfdesktop
;
2654 if(!pSHGetItemFromDataObject
)
2656 win_skip("No SHGetItemFromDataObject.\n");
2662 /* Crashes under win7 */
2663 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2666 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2667 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2669 SHGetDesktopFolder(&psfdesktop
);
2671 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2672 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2679 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2680 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2681 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2684 LPITEMIDLIST apidl
[5];
2687 for(count
= 0; count
< 5; count
++)
2688 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2693 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2694 &IID_IDataObject
, NULL
, (void**)&pdo
);
2695 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2698 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2699 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2700 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2701 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2702 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2703 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2704 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2705 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2706 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2707 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2708 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2709 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2710 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2711 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2712 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2714 IDataObject_Release(pdo
);
2718 skip("No file(s) found - skipping single-file test.\n");
2722 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2723 &IID_IDataObject
, NULL
, (void**)&pdo
);
2724 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2727 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &IID_IShellItem
, (void**)&psi
);
2728 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2729 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2730 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_TRAVERSE_LINK
, &IID_IShellItem
, (void**)&psi
);
2731 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2732 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2733 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_HDROP
, &IID_IShellItem
, (void**)&psi
);
2734 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2735 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2736 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2737 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2738 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2739 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2740 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2741 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2742 IDataObject_Release(pdo
);
2746 skip("zero or one file found - skipping multi-file test.\n");
2748 for(i
= 0; i
< count
; i
++)
2751 IEnumIDList_Release(peidl
);
2754 IShellView_Release(psv
);
2757 IShellFolder_Release(psfdesktop
);
2760 static void test_ShellItemCompare(void)
2762 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2763 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2764 IShellFolder
*psf_desktop
, *psf_current
;
2765 LPITEMIDLIST pidl_cwd
;
2766 WCHAR curdirW
[MAX_PATH
];
2769 static const WCHAR filesW
[][9] = {
2770 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2771 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2772 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2776 if(!pSHCreateShellItem
)
2778 win_skip("SHCreateShellItem missing.\n");
2782 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2785 skip("Failed to get current directory, skipping.\n");
2789 CreateDirectoryA(".\\a", NULL
);
2790 CreateDirectoryA(".\\b", NULL
);
2791 CreateDirectoryA(".\\c", NULL
);
2792 CreateTestFile(".\\a\\a");
2793 CreateTestFile(".\\a\\b");
2794 CreateTestFile(".\\a\\c");
2795 CreateTestFile(".\\b\\a");
2796 CreateTestFile(".\\b\\b");
2797 CreateTestFile(".\\b\\c");
2798 CreateTestFile(".\\c\\a");
2799 CreateTestFile(".\\c\\b");
2800 CreateTestFile(".\\c\\c");
2802 SHGetDesktopFolder(&psf_desktop
);
2803 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2804 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2805 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2806 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2807 IShellFolder_Release(psf_desktop
);
2810 /* Generate ShellItems for the files */
2811 memset(&psi
, 0, sizeof(psi
));
2813 for(i
= 0; i
< 9; i
++)
2815 LPITEMIDLIST pidl_testfile
= NULL
;
2817 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2818 NULL
, &pidl_testfile
, NULL
);
2819 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2822 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2823 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2824 pILFree(pidl_testfile
);
2826 if(FAILED(hr
)) failed
= TRUE
;
2830 skip("Failed to create all shellitems.\n");
2834 /* Generate ShellItems for the folders */
2835 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2836 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2837 if(FAILED(hr
)) failed
= TRUE
;
2838 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2839 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2840 if(FAILED(hr
)) failed
= TRUE
;
2841 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2842 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2843 if(FAILED(hr
)) failed
= TRUE
;
2847 skip("Failed to create shellitems.\n");
2853 /* Crashes on native (win7, winxp) */
2854 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2855 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2856 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2860 for(i
= 0; i
< 9; i
++)
2862 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &order
);
2863 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2864 ok(order
== 0, "Got order %d\n", order
);
2865 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_CANONICAL
, &order
);
2866 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2867 ok(order
== 0, "Got order %d\n", order
);
2868 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2869 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2870 ok(order
== 0, "Got order %d\n", order
);
2874 /* a\b:a\a , a\b:a\c, a\b:a\b */
2875 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_DISPLAY
, &order
);
2876 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2877 ok(order
== 1, "Got order %d\n", order
);
2878 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_DISPLAY
, &order
);
2879 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2880 ok(order
== -1, "Got order %d\n", order
);
2881 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2882 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2883 ok(order
== 0, "Got order %d\n", order
);
2885 /* b\b:a\b, b\b:c\b, b\b:c\b */
2886 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_DISPLAY
, &order
);
2887 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2888 ok(order
== 1, "Got order %d\n", order
);
2889 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_DISPLAY
, &order
);
2890 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2891 ok(order
== -1, "Got order %d\n", order
);
2892 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2893 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2894 ok(order
== 0, "Got order %d\n", order
);
2896 /* b:a\a, b:a\c, b:a\b */
2897 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_DISPLAY
, &order
);
2898 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2899 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2900 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_DISPLAY
, &order
);
2901 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2902 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2903 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2904 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2905 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2907 /* b:c\a, b:c\c, b:c\b */
2908 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_DISPLAY
, &order
);
2909 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2910 ok(order
== -1, "Got order %d\n", order
);
2911 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_DISPLAY
, &order
);
2912 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2913 ok(order
== -1, "Got order %d\n", order
);
2914 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2915 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2916 ok(order
== -1, "Got order %d\n", order
);
2918 /* a\b:a\a , a\b:a\c, a\b:a\b */
2919 hr
= IShellItem_Compare(psi
[1], psi
[0], SICHINT_CANONICAL
, &order
);
2920 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2921 ok(order
== 1, "Got order %d\n", order
);
2922 hr
= IShellItem_Compare(psi
[1], psi
[2], SICHINT_CANONICAL
, &order
);
2923 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2924 ok(order
== -1, "Got order %d\n", order
);
2925 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2926 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2927 ok(order
== 0, "Got order %d\n", order
);
2929 /* b\b:a\b, b\b:c\b, b\b:c\b */
2930 hr
= IShellItem_Compare(psi
[4], psi
[1], SICHINT_CANONICAL
, &order
);
2931 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2932 ok(order
== 1, "Got order %d\n", order
);
2933 hr
= IShellItem_Compare(psi
[4], psi
[7], SICHINT_CANONICAL
, &order
);
2934 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2935 ok(order
== -1, "Got order %d\n", order
);
2936 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2937 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2938 ok(order
== 0, "Got order %d\n", order
);
2940 /* b:a\a, b:a\c, b:a\b */
2941 hr
= IShellItem_Compare(psi_b
, psi
[0], SICHINT_CANONICAL
, &order
);
2942 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2943 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2944 hr
= IShellItem_Compare(psi_b
, psi
[2], SICHINT_CANONICAL
, &order
);
2945 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2946 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2947 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2948 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2949 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2951 /* b:c\a, b:c\c, b:c\b */
2952 hr
= IShellItem_Compare(psi_b
, psi
[6], SICHINT_CANONICAL
, &order
);
2953 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2954 ok(order
== -1, "Got order %d\n", order
);
2955 hr
= IShellItem_Compare(psi_b
, psi
[8], SICHINT_CANONICAL
, &order
);
2956 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2957 ok(order
== -1, "Got order %d\n", order
);
2958 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
2959 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2960 ok(order
== -1, "Got order %d\n", order
);
2963 IShellFolder_Release(psf_current
);
2965 DeleteFileA(".\\a\\a");
2966 DeleteFileA(".\\a\\b");
2967 DeleteFileA(".\\a\\c");
2968 DeleteFileA(".\\b\\a");
2969 DeleteFileA(".\\b\\b");
2970 DeleteFileA(".\\b\\c");
2971 DeleteFileA(".\\c\\a");
2972 DeleteFileA(".\\c\\b");
2973 DeleteFileA(".\\c\\c");
2974 RemoveDirectoryA(".\\a");
2975 RemoveDirectoryA(".\\b");
2976 RemoveDirectoryA(".\\c");
2978 if(psi_a
) IShellItem_Release(psi_a
);
2979 if(psi_b
) IShellItem_Release(psi_b
);
2980 if(psi_c
) IShellItem_Release(psi_c
);
2982 for(i
= 0; i
< 9; i
++)
2983 if(psi
[i
]) IShellItem_Release(psi
[i
]);
2986 /**************************************************************/
2987 /* IUnknown implementation for counting QueryInterface calls. */
2989 IUnknown IUnknown_iface
;
2997 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
2999 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
3002 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
3004 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
3007 for(i
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
3009 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
3011 This
->ifaces
[i
].count
++;
3018 return E_NOINTERFACE
;
3021 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3026 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3031 static const IUnknownVtbl vt_IUnknown
= {
3032 unk_fnQueryInterface
,
3037 static void test_SHGetIDListFromObject(void)
3039 IUnknownImpl
*punkimpl
;
3040 IShellFolder
*psfdesktop
;
3042 LPITEMIDLIST pidl
, pidl_desktop
;
3045 struct if_count ifaces
[] =
3046 { {&IID_IPersistIDList
, 0},
3047 {&IID_IPersistFolder2
, 0},
3048 {&IID_IDataObject
, 0},
3049 {&IID_IParentAndItem
, 0},
3050 {&IID_IFolderView
, 0},
3053 if(!pSHGetIDListFromObject
)
3055 win_skip("SHGetIDListFromObject missing.\n");
3059 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3063 /* Crashes native */
3064 pSHGetIDListFromObject(NULL
, NULL
);
3065 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3068 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3069 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3071 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3072 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3073 punkimpl
->ifaces
= ifaces
;
3074 punkimpl
->unknown
= 0;
3076 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3077 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3078 ok(ifaces
[0].count
, "interface not requested.\n");
3079 ok(ifaces
[1].count
, "interface not requested.\n");
3080 ok(ifaces
[2].count
, "interface not requested.\n");
3082 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3083 "interface not requested.\n");
3084 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3085 "interface not requested.\n");
3087 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3088 HeapFree(GetProcessHeap(), 0, punkimpl
);
3090 pidl_desktop
= NULL
;
3091 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3092 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3094 SHGetDesktopFolder(&psfdesktop
);
3096 /* Test IShellItem */
3097 if(pSHCreateShellItem
)
3099 IShellItem
*shellitem
;
3100 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3101 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3104 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3105 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3108 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3111 IShellItem_Release(shellitem
);
3115 skip("no SHCreateShellItem.\n");
3117 /* Test IShellFolder */
3118 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3119 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3122 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3126 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3127 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3134 /* Test IFolderView */
3135 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3136 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3139 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3143 /* Test IDataObject */
3144 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3145 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3146 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3149 LPITEMIDLIST apidl
[5];
3151 for(count
= 0; count
< 5; count
++)
3152 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3157 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3158 &IID_IDataObject
, NULL
, (void**)&pdo
);
3159 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3162 pidl
= (void*)0xDEADBEEF;
3163 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3164 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3165 ok(pidl
!= NULL
, "pidl is NULL.\n");
3166 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3169 IDataObject_Release(pdo
);
3173 skip("No files found - skipping single-file test.\n");
3177 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3178 &IID_IDataObject
, NULL
, (void**)&pdo
);
3179 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3182 pidl
= (void*)0xDEADBEEF;
3183 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3184 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3185 "got 0x%08x\n", hres
);
3186 ok(pidl
== NULL
, "pidl is not NULL.\n");
3188 IDataObject_Release(pdo
);
3192 skip("zero or one file found - skipping multi-file test.\n");
3194 for(i
= 0; i
< count
; i
++)
3197 IEnumIDList_Release(peidl
);
3200 IShellView_Release(psv
);
3203 IShellFolder_Release(psfdesktop
);
3204 pILFree(pidl_desktop
);
3207 static void test_SHGetItemFromObject(void)
3209 IUnknownImpl
*punkimpl
;
3210 IShellFolder
*psfdesktop
;
3215 struct if_count ifaces
[] =
3216 { {&IID_IPersistIDList
, 0},
3217 {&IID_IPersistFolder2
, 0},
3218 {&IID_IDataObject
, 0},
3219 {&IID_IParentAndItem
, 0},
3220 {&IID_IFolderView
, 0},
3223 if(!pSHGetItemFromObject
)
3225 skip("No SHGetItemFromObject.\n");
3229 SHGetDesktopFolder(&psfdesktop
);
3233 /* Crashes with Windows 7 */
3234 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3235 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3236 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3239 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3240 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3242 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3243 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3244 punkimpl
->ifaces
= ifaces
;
3245 punkimpl
->unknown
= 0;
3247 /* The same as SHGetIDListFromObject */
3248 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3249 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3250 ok(ifaces
[0].count
, "interface not requested.\n");
3251 ok(ifaces
[1].count
, "interface not requested.\n");
3252 ok(ifaces
[2].count
, "interface not requested.\n");
3254 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3255 "interface not requested.\n");
3256 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3257 "interface not requested.\n");
3259 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3260 HeapFree(GetProcessHeap(), 0, punkimpl
);
3262 /* Test IShellItem */
3263 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3264 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3268 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3269 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3273 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3274 IShellItem_Release(psi2
);
3276 IShellItem_Release(psi
);
3279 IShellFolder_Release(psfdesktop
);
3282 static void test_SHCreateShellItemArray(void)
3284 IShellFolder
*pdesktopsf
, *psf
;
3285 IShellItemArray
*psia
;
3288 WCHAR cTestDirW
[MAX_PATH
];
3289 LPITEMIDLIST pidl_testdir
, pidl
;
3290 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3292 if(!pSHCreateShellItemArray
) {
3293 skip("No pSHCreateShellItemArray!\n");
3297 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3301 /* Crashes under native */
3302 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3303 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3304 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3305 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3308 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3309 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3311 SHGetDesktopFolder(&pdesktopsf
);
3312 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3313 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3315 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3316 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3318 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3319 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3320 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3323 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3324 myPathAddBackslashW(cTestDirW
);
3325 lstrcatW(cTestDirW
, testdirW
);
3327 CreateFilesFolders();
3329 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3330 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3333 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3335 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3337 IShellFolder_Release(pdesktopsf
);
3341 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3342 pILFree(pidl_testdir
);
3347 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3348 ok(hr
== S_OK
, "Got %08x\n", hr
);
3351 LPITEMIDLIST apidl
[5];
3352 UINT done
, numitems
, i
;
3354 for(done
= 0; done
< 5; done
++)
3355 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3357 ok(done
== 5, "Got %d pidls\n", done
);
3358 IEnumIDList_Release(peidl
);
3360 /* Create a ShellItemArray */
3361 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3362 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3369 /* Crashes in Windows 7 */
3370 IShellItemArray_GetCount(psia
, NULL
);
3373 IShellItemArray_GetCount(psia
, &numitems
);
3374 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3376 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3377 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3379 /* Compare all the items */
3380 for(i
= 0; i
< numitems
; i
++)
3382 LPITEMIDLIST pidl_abs
;
3383 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3385 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3386 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3389 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3390 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3393 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3396 IShellItem_Release(psi
);
3400 for(i
= 0; i
< done
; i
++)
3402 IShellItemArray_Release(psia
);
3406 /* SHCreateShellItemArrayFromShellItem */
3407 if(pSHCreateShellItemArrayFromShellItem
)
3413 /* Crashes under Windows 7 */
3414 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3415 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3416 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3419 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3420 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3423 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3424 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3429 hr
= IShellItemArray_GetCount(psia
, &count
);
3430 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3431 ok(count
== 1, "Got count %d\n", count
);
3432 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3433 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3435 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3438 LPITEMIDLIST pidl1
, pidl2
;
3439 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3440 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3441 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3442 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3443 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3444 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3445 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3448 IShellItem_Release(psi2
);
3450 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3451 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3452 IShellItemArray_Release(psia
);
3454 IShellItem_Release(psi
);
3458 skip("No SHCreateShellItemArrayFromShellItem.\n");
3460 if(pSHCreateShellItemArrayFromDataObject
)
3466 /* Crashes under Windows 7 */
3467 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3469 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3470 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3472 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3473 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3480 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3481 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3482 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3485 LPITEMIDLIST apidl
[5];
3488 for(count
= 0; count
< 5; count
++)
3489 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3491 ok(count
== 5, "Got %d\n", count
);
3495 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3496 &IID_IDataObject
, NULL
, (void**)&pdo
);
3497 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3500 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3502 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3506 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3507 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3508 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3509 for(i
= 0; i
< count_sia
; i
++)
3511 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3513 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3514 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3518 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3519 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3520 ok(pidl
!= NULL
, "pidl as NULL.\n");
3521 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3523 IShellItem_Release(psi
);
3528 IShellItemArray_Release(psia
);
3531 IDataObject_Release(pdo
);
3533 for(i
= 0; i
< count
; i
++)
3537 skip("No files found - skipping test.\n");
3539 IEnumIDList_Release(peidl
);
3541 IShellView_Release(psv
);
3545 skip("No SHCreateShellItemArrayFromDataObject.\n");
3547 if(pSHCreateShellItemArrayFromIDLists
)
3549 WCHAR test1W
[] = {'t','e','s','t','1','.','t','x','t',0};
3550 WCHAR test1pathW
[MAX_PATH
];
3551 LPITEMIDLIST pidltest1
;
3552 LPCITEMIDLIST pidl_array
[2];
3557 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, NULL
);
3560 psia
= (void*)0xdeadbeef;
3561 hr
= pSHCreateShellItemArrayFromIDLists(0, NULL
, &psia
);
3562 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3563 ok(psia
== NULL
, "Got %p\n", psia
);
3565 psia
= (void*)0xdeadbeef;
3566 hr
= pSHCreateShellItemArrayFromIDLists(0, pidl_array
, &psia
);
3567 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3568 ok(psia
== NULL
, "Got %p\n", psia
);
3570 psia
= (void*)0xdeadbeef;
3571 pidl_array
[0] = NULL
;
3572 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3573 todo_wine
ok(hr
== E_OUTOFMEMORY
, "Got 0x%08x\n", hr
);
3574 ok(psia
== NULL
, "Got %p\n", psia
);
3576 psia
= (void*)0xdeadbeef;
3577 pidl_array
[0] = pidl_testdir
;
3578 pidl_array
[1] = NULL
;
3579 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3580 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
) /* Vista */, "Got 0x%08x\n", hr
);
3581 todo_wine
ok(psia
!= NULL
|| broken(psia
== NULL
) /* Vista */, "Got %p\n", psia
);
3587 hr
= IShellItemArray_GetCount(psia
, &count
);
3588 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3589 ok(count
== 2, "Got %d\n", count
);
3591 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3592 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3596 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3597 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3598 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3600 CoTaskMemFree(path
);
3602 IShellItem_Release(psi
);
3605 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3606 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3610 WCHAR desktoppath
[MAX_PATH
];
3613 result
= pSHGetSpecialFolderPathW(NULL
, desktoppath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
3614 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
3616 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3617 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3618 ok(!lstrcmpW(path
, desktoppath
), "Got %s\n", wine_dbgstr_w(path
));
3620 CoTaskMemFree(path
);
3622 IShellItem_Release(psi
);
3626 IShellItemArray_Release(psia
);
3631 psia
= (void*)0xdeadbeef;
3632 pidl_array
[0] = pidl_testdir
;
3633 hr
= pSHCreateShellItemArrayFromIDLists(1, pidl_array
, &psia
);
3634 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3640 hr
= IShellItemArray_GetCount(psia
, &count
);
3641 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3642 ok(count
== 1, "Got %d\n", count
);
3644 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3645 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3649 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3650 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3651 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3653 CoTaskMemFree(path
);
3655 IShellItem_Release(psi
);
3658 IShellItemArray_Release(psia
);
3662 lstrcpyW(test1pathW
, cTestDirW
);
3663 myPathAddBackslashW(test1pathW
);
3664 lstrcatW(test1pathW
, test1W
);
3666 SHGetDesktopFolder(&pdesktopsf
);
3668 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, test1pathW
, NULL
, &pidltest1
, NULL
);
3669 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3672 psia
= (void*)0xdeadbeef;
3673 pidl_array
[0] = pidl_testdir
;
3674 pidl_array
[1] = pidltest1
;
3675 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia
);
3676 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3682 hr
= IShellItemArray_GetCount(psia
, &count
);
3683 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3684 ok(count
== 2, "Got %d\n", count
);
3686 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi
);
3687 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3691 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3692 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3693 ok(!lstrcmpW(path
, cTestDirW
), "Got %s\n", wine_dbgstr_w(path
));
3695 CoTaskMemFree(path
);
3697 IShellItem_Release(psi
);
3700 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi
);
3701 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3705 hr
= IShellItem_GetDisplayName(psi
, SIGDN_DESKTOPABSOLUTEPARSING
, &path
);
3706 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3707 ok(!lstrcmpW(path
, test1pathW
), "Got %s\n", wine_dbgstr_w(path
));
3709 CoTaskMemFree(path
);
3711 IShellItem_Release(psi
);
3715 IShellItemArray_Release(psia
);
3721 IShellFolder_Release(pdesktopsf
);
3724 skip("No SHCreateShellItemArrayFromIDLists.\n");
3726 IShellFolder_Release(psf
);
3727 pILFree(pidl_testdir
);
3731 static void test_ShellItemArrayEnumItems(void)
3733 IShellFolder
*pdesktopsf
, *psf
;
3735 WCHAR cTestDirW
[MAX_PATH
];
3737 LPITEMIDLIST pidl_testdir
;
3738 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3740 if(!pSHCreateShellItemArray
)
3742 win_skip("No SHCreateShellItemArray, skipping test...\n");
3746 CreateFilesFolders();
3748 SHGetDesktopFolder(&pdesktopsf
);
3750 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3751 myPathAddBackslashW(cTestDirW
);
3752 lstrcatW(cTestDirW
, testdirW
);
3754 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3758 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3760 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3762 pILFree(pidl_testdir
);
3764 IShellFolder_Release(pdesktopsf
);
3766 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3767 ok(hr
== S_OK
, "Got %08x\n", hr
);
3770 IShellItemArray
*psia
;
3771 LPITEMIDLIST apidl
[5];
3772 UINT done
, numitems
, i
;
3774 for(done
= 0; done
< 5; done
++)
3775 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3777 ok(done
== 5, "Got %d pidls\n", done
);
3778 IEnumIDList_Release(peidl
);
3780 /* Create a ShellItemArray */
3781 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3782 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3785 IEnumShellItems
*iesi
;
3786 IShellItem
*my_array
[10];
3789 IShellItemArray_GetCount(psia
, &numitems
);
3790 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3793 hr
= IShellItemArray_EnumItems(psia
, &iesi
);
3794 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3795 ok(iesi
!= NULL
, "Got NULL\n");
3798 IEnumShellItems
*iesi2
;
3800 /* This should fail according to the documentation and Win7+ */
3801 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3802 hr
= IEnumShellItems_Next(iesi
, 2, my_array
, NULL
);
3803 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
3804 for(i
= 0; i
< 2; i
++)
3806 ok(my_array
[i
] == (void*)0xdeadbeef ||
3807 broken(my_array
[i
] != (void*)0xdeadbeef && my_array
[i
] != NULL
), /* Vista */
3808 "Got %p (%d)\n", my_array
[i
], i
);
3810 if(my_array
[i
] != (void*)0xdeadbeef)
3811 IShellItem_Release(my_array
[i
]);
3813 ok(my_array
[2] == (void*)0xdeadbeef, "Got %p\n", my_array
[2]);
3815 IEnumShellItems_Reset(iesi
);
3816 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3817 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, NULL
);
3818 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3819 ok(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3820 if(my_array
[0] != NULL
&& my_array
[0] != (void*)0xdeadbeef)
3821 IShellItem_Release(my_array
[0]);
3822 ok(my_array
[1] == (void*)0xdeadbeef, "Got %p\n", my_array
[1]);
3824 IEnumShellItems_Reset(iesi
);
3826 for(i
= 0; i
< 10; i
++) my_array
[i
] = (void*)0xdeadbeef;
3827 hr
= IEnumShellItems_Next(iesi
, numitems
, my_array
, &fetched
);
3828 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3829 ok(fetched
== numitems
, "Got %d\n", fetched
);
3830 for(i
= 0;i
< numitems
; i
++)
3832 ok(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef,
3833 "Got %p at %d\n", my_array
[i
], i
);
3835 if(my_array
[i
] != NULL
&& my_array
[i
] != (void*)0xdeadbeef)
3836 IShellItem_Release(my_array
[i
]);
3838 ok(my_array
[i
] == (void*)0xdeadbeef, "Got %p\n", my_array
[i
]);
3840 /* Compare all the items */
3841 IEnumShellItems_Reset(iesi
);
3842 for(i
= 0; i
< numitems
; i
++)
3847 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3848 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3849 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3850 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3851 ok(fetched
== 1, "Got %d\n", fetched
);
3853 hr
= IShellItem_Compare(psi
, my_array
[0], 0, &order
);
3854 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3855 ok(order
== 0, "Got %d\n", order
);
3857 IShellItem_Release(psi
);
3858 IShellItem_Release(my_array
[0]);
3861 my_array
[0] = (void*)0xdeadbeef;
3862 hr
= IEnumShellItems_Next(iesi
, 1, my_array
, &fetched
);
3863 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
3864 ok(fetched
== 0, "Got %d\n", fetched
);
3865 ok(my_array
[0] == (void*)0xdeadbeef, "Got %p\n", my_array
[0]);
3867 /* Cloning not implemented anywhere */
3868 iesi2
= (void*)0xdeadbeef;
3869 hr
= IEnumShellItems_Clone(iesi
, &iesi2
);
3870 ok(hr
== E_NOTIMPL
, "Got 0x%08x\n", hr
);
3871 ok(iesi2
== NULL
|| broken(iesi2
== (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2
);
3873 IEnumShellItems_Release(iesi
);
3876 IShellItemArray_Release(psia
);
3879 for(i
= 0; i
< done
; i
++)
3885 static void test_ShellItemBindToHandler(void)
3888 LPITEMIDLIST pidl_desktop
;
3891 if(!pSHCreateShellItem
)
3893 skip("SHCreateShellItem missing.\n");
3897 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3898 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3901 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3902 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3906 IPersistFolder2
*ppf2
;
3911 /* Crashes under Windows 7 */
3912 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3913 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3915 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3916 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3919 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3920 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3921 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3922 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3923 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3926 LPITEMIDLIST pidl_tmp
;
3927 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3928 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3931 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3934 IPersistFolder2_Release(ppf2
);
3937 /* BHID_SFUIObject */
3938 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3939 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3940 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3941 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3942 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3943 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3945 /* BHID_DataObject */
3946 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3947 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3948 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3952 /* BHID_SFViewObject */
3953 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3954 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3955 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3956 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3957 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3958 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3961 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
3962 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3963 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3964 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
3965 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3966 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3969 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
3970 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3971 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3972 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
3973 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3974 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3976 /* BHID_StorageEnum */
3977 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
3978 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3979 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3982 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
3983 supported starting from Win8. */
3984 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferSource
, (void**)&punk
);
3985 ok(hr
== S_OK
|| broken(FAILED(hr
)) /* pre-Vista */, "Got 0x%08x\n", hr
);
3988 IUnknown_Release(punk
);
3990 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_ITransferDestination
, (void**)&punk
);
3991 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3992 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3994 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
3995 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Win8 */, "Got 0x%08x\n", hr
);
3996 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3999 /* BHID_EnumItems */
4000 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
4001 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4002 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4005 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
4006 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4007 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4009 /* BHID_LinkTargetItem */
4010 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
4011 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
4012 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4013 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
4014 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
4015 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4017 /* BHID_PropertyStore */
4018 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
4019 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4020 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4021 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
4022 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4023 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4025 /* BHID_ThumbnailHandler */
4026 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
4027 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4028 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4030 /* BHID_AssociationArray */
4031 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
4032 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4033 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4035 /* BHID_EnumAssocHandlers */
4036 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
4037 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
4038 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
4041 IShellItem_Release(psi
);
4044 skip("Failed to create ShellItem.\n");
4046 pILFree(pidl_desktop
);
4049 static void test_ShellItemGetAttributes(void)
4051 IShellItem
*psi
, *psi_folder1
, *psi_file1
;
4052 IShellFolder
*pdesktopsf
;
4053 LPITEMIDLIST pidl_desktop
, pidl
;
4056 WCHAR curdirW
[MAX_PATH
];
4057 WCHAR buf
[MAX_PATH
];
4058 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4059 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4061 if(!pSHCreateShellItem
)
4063 skip("SHCreateShellItem missing.\n");
4067 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
4068 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4071 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
4072 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4073 pILFree(pidl_desktop
);
4077 skip("Skipping tests.\n");
4083 /* Crashes on native (Win 7) */
4084 IShellItem_GetAttributes(psi
, 0, NULL
);
4087 /* Test GetAttributes on the desktop folder. */
4089 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
4090 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
4091 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
4093 IShellItem_Release(psi
);
4095 CreateFilesFolders();
4097 SHGetDesktopFolder(&pdesktopsf
);
4099 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4100 myPathAddBackslashW(curdirW
);
4102 lstrcpyW(buf
, curdirW
);
4103 lstrcatW(buf
, testdir1W
);
4104 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4105 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4106 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_folder1
);
4107 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4110 lstrcpyW(buf
, curdirW
);
4111 lstrcatW(buf
, testfile1W
);
4112 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, &pidl
, NULL
);
4113 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4114 hr
= pSHCreateShellItem(NULL
, NULL
, pidl
, &psi_file1
);
4115 ok(hr
== S_OK
, "Got 0x%08x\n", sfgao
);
4118 IShellFolder_Release(pdesktopsf
);
4121 hr
= IShellItem_GetAttributes(psi_folder1
, 0, &sfgao
);
4122 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4123 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4126 hr
= IShellItem_GetAttributes(psi_folder1
, SFGAO_FOLDER
, &sfgao
);
4127 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4128 ok(sfgao
== SFGAO_FOLDER
, "Got 0x%08x\n", sfgao
);
4131 hr
= IShellItem_GetAttributes(psi_file1
, SFGAO_FOLDER
, &sfgao
);
4132 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
4133 ok(sfgao
== 0, "Got 0x%08x\n", sfgao
);
4135 IShellItem_Release(psi_folder1
);
4136 IShellItem_Release(psi_file1
);
4141 static void test_ShellItemArrayGetAttributes(void)
4143 IShellItemArray
*psia_files
, *psia_folders1
, *psia_folders2
, *psia_all
;
4144 IShellFolder
*pdesktopsf
;
4145 LPCITEMIDLIST pidl_array
[5];
4148 WCHAR curdirW
[MAX_PATH
];
4149 WCHAR buf
[MAX_PATH
];
4151 static const WCHAR testdir1W
[] = {'t','e','s','t','d','i','r',0};
4152 static const WCHAR testdir2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
4153 static const WCHAR testdir3W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
4154 static const WCHAR testfile1W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4155 static const WCHAR testfile2W
[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
4156 static const WCHAR
*testfilesW
[5] = { testdir1W
, testdir2W
, testdir3W
, testfile1W
, testfile2W
};
4158 if(!pSHCreateShellItemArrayFromShellItem
)
4160 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
4164 CreateFilesFolders();
4165 CreateDirectoryA(".\\testdir\\testdir3", NULL
);
4167 SHGetDesktopFolder(&pdesktopsf
);
4169 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
4170 myPathAddBackslashW(curdirW
);
4172 for(i
= 0; i
< 5; i
++)
4174 lstrcpyW(buf
, curdirW
);
4175 lstrcatW(buf
, testfilesW
[i
]);
4176 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, buf
, NULL
, (LPITEMIDLIST
*)&pidl_array
[i
], NULL
);
4177 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4179 IShellFolder_Release(pdesktopsf
);
4181 hr
= pSHCreateShellItemArrayFromIDLists(2, pidl_array
, &psia_folders1
);
4182 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4183 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[1], &psia_folders2
);
4184 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4185 hr
= pSHCreateShellItemArrayFromIDLists(2, &pidl_array
[3], &psia_files
);
4186 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4187 hr
= pSHCreateShellItemArrayFromIDLists(4, &pidl_array
[1], &psia_all
); /* All except the first */
4188 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4190 for(i
= 0; i
< 5; i
++)
4191 pILFree((LPITEMIDLIST
)pidl_array
[i
]);
4193 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
4195 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4196 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4197 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4199 hr
= IShellItemArray_GetAttributes(psia_folders1
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4200 ok(hr
== S_OK
|| broken(hr
== E_UNEXPECTED
) /* Vista */, "Got 0x%08x\n", hr
);
4201 ok(attr
== SFGAO_FOLDER
|| broken(attr
== 0) /* Vista */, "Got 0x%08x\n", attr
);
4203 /* [testfolder/testfolder2, testfolder/testfolder3] works */
4205 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4206 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4207 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4209 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4210 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4211 ok(attr
== 0, "Got 0x%08x\n", attr
);
4213 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attr
);
4214 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4215 ok(attr
== 0, "Got 0x%08x\n", attr
);
4217 hr
= IShellItemArray_GetAttributes(psia_folders2
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4218 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4219 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4221 hr
= IShellItemArray_GetAttributes(psia_files
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4222 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* Vista */, "Got 0x%08x\n", hr
);
4223 ok(attr
== 0, "Got 0x%08x\n", attr
);
4225 hr
= IShellItemArray_GetAttributes(psia_all
, SIATTRIBFLAGS_OR
, SFGAO_FOLDER
, &attr
);
4226 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4227 ok(attr
== SFGAO_FOLDER
, "Got 0x%08x\n", attr
);
4229 IShellItemArray_Release(psia_folders1
);
4230 IShellItemArray_Release(psia_folders2
);
4231 IShellItemArray_Release(psia_files
);
4232 IShellItemArray_Release(psia_all
);
4234 RemoveDirectoryA(".\\testdir\\testdir3");
4238 static void test_SHParseDisplayName(void)
4240 LPITEMIDLIST pidl1
, pidl2
;
4241 IShellFolder
*desktop
;
4242 WCHAR dirW
[MAX_PATH
];
4247 if (!pSHParseDisplayName
)
4249 win_skip("SHParseDisplayName isn't available\n");
4255 /* crashes on native */
4256 pSHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
4258 pSHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
4261 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
4262 hr
= pSHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
4263 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
4264 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
4265 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
4269 hr
= pSHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
4270 ok(hr
== S_OK
, "failed %08x\n", hr
);
4271 hr
= SHGetDesktopFolder(&desktop
);
4272 ok(hr
== S_OK
, "failed %08x\n", hr
);
4273 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
4274 ok(hr
== S_OK
, "failed %08x\n", hr
);
4275 ret
= pILIsEqual(pidl1
, pidl2
);
4276 ok(ret
== TRUE
, "expected equal idls\n");
4281 GetWindowsDirectoryW( dirW
, MAX_PATH
);
4283 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4284 ok(hr
== S_OK
, "failed %08x\n", hr
);
4285 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
4286 ok(hr
== S_OK
, "failed %08x\n", hr
);
4288 ret
= pILIsEqual(pidl1
, pidl2
);
4289 ok(ret
== TRUE
, "expected equal idls\n");
4293 /* system32 is not redirected to syswow64 on WOW64 */
4294 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
4295 if (is_wow64
&& pGetSystemWow64DirectoryW
)
4299 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
4300 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
4301 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
4302 ok(hr
== S_OK
, "failed %08x\n", hr
);
4304 len
= pGetSystemWow64DirectoryW(dirW
, MAX_PATH
);
4305 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
4306 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
4307 ok(hr
== S_OK
, "failed %08x\n", hr
);
4308 ret
= pILIsEqual(pidl1
, pidl2
);
4309 ok(ret
== FALSE
, "expected different idls\n");
4314 IShellFolder_Release(desktop
);
4317 static void test_desktop_IPersist(void)
4319 IShellFolder
*desktop
;
4321 IPersistFolder2
*ppf2
;
4325 hr
= SHGetDesktopFolder(&desktop
);
4326 ok(hr
== S_OK
, "failed %08x\n", hr
);
4328 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
4329 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* NT4, W9X */, "failed %08x\n", hr
);
4335 /* crashes on native */
4336 IPersist_GetClassID(persist
, NULL
);
4338 memset(&clsid
, 0, sizeof(clsid
));
4339 hr
= IPersist_GetClassID(persist
, &clsid
);
4340 ok(hr
== S_OK
, "failed %08x\n", hr
);
4341 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
4342 IPersist_Release(persist
);
4345 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
4346 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
4349 IPersistFolder
*ppf
;
4351 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
4352 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
4354 IPersistFolder_Release(ppf
);
4357 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
4358 ok(hr
== S_OK
, "got %08x\n", hr
);
4362 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
4363 ok(hr
== S_OK
, "got %08x\n", hr
);
4364 ok(pidl
!= NULL
, "pidl was NULL.\n");
4365 if(SUCCEEDED(hr
)) pILFree(pidl
);
4367 IPersistFolder2_Release(ppf2
);
4370 IShellFolder_Release(desktop
);
4373 static void test_GetUIObject(void)
4375 IShellFolder
*psf_desktop
;
4379 WCHAR path
[MAX_PATH
];
4380 const WCHAR filename
[] =
4381 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4383 if(!pSHBindToParent
)
4385 win_skip("SHBindToParent missing.\n");
4389 GetCurrentDirectoryW(MAX_PATH
, path
);
4392 skip("GetCurrentDirectoryW returned an empty string.\n");
4395 lstrcatW(path
, filename
);
4396 SHGetDesktopFolder(&psf_desktop
);
4398 CreateFilesFolders();
4400 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4401 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
4405 LPCITEMIDLIST pidl_child
;
4406 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
4407 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4410 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
,
4412 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4415 const int baseItem
= 0x40;
4416 HMENU hmenu
= CreatePopupMenu();
4417 INT max_id
, max_id_check
;
4419 const int id_upper_limit
= 32767;
4420 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, baseItem
, id_upper_limit
, CMF_NORMAL
);
4421 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
4422 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
4423 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
4424 count
= GetMenuItemCount(hmenu
);
4425 ok(count
, "Got %d\n", count
);
4428 for(i
= 0; i
< count
; i
++)
4432 char buf
[255], buf2
[255];
4433 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
4434 mii
.cbSize
= sizeof(MENUITEMINFOA
);
4435 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
| MIIM_STRING
;
4436 mii
.dwTypeData
= buf2
;
4437 mii
.cch
= sizeof(buf2
);
4440 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
4441 ok(res
, "Failed (last error: %d).\n", GetLastError());
4443 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
4444 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
4445 if(!(mii
.fType
& MFT_SEPARATOR
))
4447 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
4448 hr
= IContextMenu_GetCommandString(pcm
, mii
.wID
- baseItem
, GCS_VERBA
, 0, buf
, sizeof(buf
));
4449 ok(SUCCEEDED(hr
) || hr
== E_NOTIMPL
, "for id 0x%x got 0x%08x (menustr: %s)\n", mii
.wID
- baseItem
, hr
, mii
.dwTypeData
);
4451 trace("for id 0x%x got string %s (menu string: %s)\n", mii
.wID
- baseItem
, buf
, mii
.dwTypeData
);
4452 else if (hr
== E_NOTIMPL
)
4453 trace("for id 0x%x got E_NOTIMPL (menu string: %s)\n", mii
.wID
- baseItem
, mii
.dwTypeData
);
4456 max_id_check
-= baseItem
;
4457 ok((max_id_check
== max_id
) ||
4458 (max_id_check
== max_id
-1) || /* Win 7 */
4459 (max_id_check
== max_id
-2), /* Win 8 */
4460 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
4462 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
4464 if(count
&& !is_win2k()) /* Test is interactive on w2k, so skip */
4466 CMINVOKECOMMANDINFO cmi
;
4467 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
4468 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
4470 /* Attempt to execute a nonexistent command */
4471 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
4472 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4473 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4475 cmi
.lpVerb
= "foobar_wine_test";
4476 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
4477 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
4478 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
4479 "Got 0x%08x\n", hr
);
4484 IContextMenu_Release(pcm
);
4486 IShellFolder_Release(psf
);
4488 if(pILFree
) pILFree(pidl
);
4491 IShellFolder_Release(psf_desktop
);
4495 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
4496 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
4498 LPCITEMIDLIST child
;
4499 IShellFolder
*parent
;
4503 if(!pSHBindToParent
){
4504 win_skip("SHBindToParent is not available, not performing full PIDL verification\n");
4506 ok_(__FILE__
,l
)(pidl
!= NULL
, "Expected PIDL to be non-NULL\n");
4508 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4514 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
4518 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&parent
, &child
);
4519 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4523 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4524 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4526 IShellFolder_Release(parent
);
4530 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4531 "Got unexpected string type: %d\n", filename
.uType
);
4532 if(filename
.uType
== STRRET_WSTR
){
4533 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4534 "didn't get expected path (%s), instead: %s\n",
4535 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4536 SHFree(U(filename
).pOleStr
);
4537 }else if(filename
.uType
== STRRET_CSTR
){
4538 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4539 "didn't get expected path (%s), instead: %s\n",
4540 wine_dbgstr_w(path
), U(filename
).cStr
);
4543 IShellFolder_Release(parent
);
4545 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4548 static void test_SHSimpleIDListFromPath(void)
4550 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4551 const CHAR adirA
[] = "C:\\sidlfpdir";
4552 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4554 LPITEMIDLIST pidl
= NULL
;
4556 if(!pSHSimpleIDListFromPathAW
){
4557 win_skip("SHSimpleIDListFromPathAW not available\n");
4561 br
= CreateDirectoryA(adirA
, NULL
);
4562 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4565 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4567 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4568 verify_pidl(pidl
, adirW
);
4571 br
= RemoveDirectoryA(adirA
);
4572 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4575 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4577 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4578 verify_pidl(pidl
, adirW
);
4582 /* IFileSystemBindData impl */
4583 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4584 REFIID riid
, void **ppv
)
4586 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4587 IsEqualIID(riid
, &IID_IUnknown
)){
4591 return E_NOINTERFACE
;
4594 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4599 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4604 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4605 const WIN32_FIND_DATAW
*pfd
)
4607 ok(0, "SetFindData called\n");
4611 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4612 WIN32_FIND_DATAW
*pfd
)
4614 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4618 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4619 WIN32_FIND_DATAW
*pfd
)
4621 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4625 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4626 WIN32_FIND_DATAW
*pfd
)
4628 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4629 *pfd
->cFileName
= 'a';
4630 *pfd
->cAlternateFileName
= 'a';
4634 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4635 WIN32_FIND_DATAW
*pfd
)
4637 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4638 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4643 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4644 WIN32_FIND_DATAW
*pfd
)
4649 static IFileSystemBindDataVtbl fsbdVtbl
= {
4650 fsbd_QueryInterface
,
4657 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4659 static void test_ParseDisplayNamePBC(void)
4661 WCHAR wFileSystemBindData
[] =
4662 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4663 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4664 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4665 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4666 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4673 /* Check if we support WCHAR functions */
4674 SetLastError(0xdeadbeef);
4675 lstrcmpiW(adirW
, adirW
);
4676 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4677 win_skip("Most W-calls are not implemented\n");
4681 hres
= SHGetDesktopFolder(&psf
);
4682 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4684 win_skip("Failed to get IShellFolder, can't run tests\n");
4688 /* fails on unknown dir with no IBindCtx */
4689 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4690 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4691 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4692 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4693 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4694 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4695 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4696 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4697 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4699 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4700 hres
= CreateBindCtx(0, &pbc
);
4701 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4703 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4704 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4705 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4706 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4707 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4708 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4709 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4710 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4711 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4713 /* unknown dir with IBindCtx with IFileSystemBindData */
4714 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4715 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4717 /* return E_FAIL from GetFindData */
4718 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4719 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4720 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4721 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4722 "ParseDisplayName failed: 0x%08x\n", hres
);
4723 if(SUCCEEDED(hres
)){
4724 verify_pidl(pidl
, adirW
);
4728 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4729 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4730 "ParseDisplayName failed: 0x%08x\n", hres
);
4731 if(SUCCEEDED(hres
)){
4732 verify_pidl(pidl
, afileW
);
4736 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4737 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4738 "ParseDisplayName failed: 0x%08x\n", hres
);
4739 if(SUCCEEDED(hres
)){
4740 verify_pidl(pidl
, afile2W
);
4744 /* set FIND_DATA struct to NULLs */
4745 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4746 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4747 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4748 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4749 "ParseDisplayName failed: 0x%08x\n", hres
);
4750 if(SUCCEEDED(hres
)){
4751 verify_pidl(pidl
, adirW
);
4755 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4756 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4757 "ParseDisplayName failed: 0x%08x\n", hres
);
4758 if(SUCCEEDED(hres
)){
4759 verify_pidl(pidl
, afileW
);
4763 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4764 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4765 "ParseDisplayName failed: 0x%08x\n", hres
);
4766 if(SUCCEEDED(hres
)){
4767 verify_pidl(pidl
, afile2W
);
4771 /* set FIND_DATA struct to junk */
4772 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4773 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4774 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4775 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4776 "ParseDisplayName failed: 0x%08x\n", hres
);
4777 if(SUCCEEDED(hres
)){
4778 verify_pidl(pidl
, adirW
);
4782 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4783 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4784 "ParseDisplayName failed: 0x%08x\n", hres
);
4785 if(SUCCEEDED(hres
)){
4786 verify_pidl(pidl
, afileW
);
4790 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4791 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4792 "ParseDisplayName failed: 0x%08x\n", hres
);
4793 if(SUCCEEDED(hres
)){
4794 verify_pidl(pidl
, afile2W
);
4798 /* set FIND_DATA struct to invalid data */
4799 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4800 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4801 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4802 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4803 "ParseDisplayName failed: 0x%08x\n", hres
);
4804 if(SUCCEEDED(hres
)){
4805 verify_pidl(pidl
, adirW
);
4809 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4810 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4811 "ParseDisplayName failed: 0x%08x\n", hres
);
4812 if(SUCCEEDED(hres
)){
4813 verify_pidl(pidl
, afileW
);
4817 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4818 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4819 "ParseDisplayName failed: 0x%08x\n", hres
);
4820 if(SUCCEEDED(hres
)){
4821 verify_pidl(pidl
, afile2W
);
4825 /* set FIND_DATA struct to valid data */
4826 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4827 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4828 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4829 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4830 "ParseDisplayName failed: 0x%08x\n", hres
);
4831 if(SUCCEEDED(hres
)){
4832 verify_pidl(pidl
, adirW
);
4836 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4837 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4838 "ParseDisplayName failed: 0x%08x\n", hres
);
4839 if(SUCCEEDED(hres
)){
4840 verify_pidl(pidl
, afileW
);
4844 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4845 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4846 "ParseDisplayName failed: 0x%08x\n", hres
);
4847 if(SUCCEEDED(hres
)){
4848 verify_pidl(pidl
, afile2W
);
4852 IBindCtx_Release(pbc
);
4853 IShellFolder_Release(psf
);
4856 static const CHAR testwindow_class
[] = "testwindow";
4857 #define WM_USER_NOTIFY (WM_APP+1)
4859 struct ChNotifyTest
{
4861 const UINT notify_count
;
4862 UINT missing_events
;
4864 const char path_1
[256];
4865 const char path_2
[256];
4866 } chnotify_tests
[] = {
4867 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
4868 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
4869 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
4872 struct ChNotifyTest
*exp_data
;
4873 BOOL test_new_delivery_flag
;
4875 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4877 LONG signal
= (LONG
)lparam
;
4880 case WM_USER_NOTIFY
:
4881 if(exp_data
->missing_events
> 0) {
4882 WCHAR
*path1
, *path2
;
4883 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
4884 HANDLE hLock
= NULL
;
4886 if(test_new_delivery_flag
) {
4887 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
4888 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
4891 ok(exp_data
->signal
== signal
,
4892 "%s: expected notification type %x, got: %x\n",
4893 exp_data
->id
, exp_data
->signal
, signal
);
4895 trace("verifying pidls for: %s\n", exp_data
->id
);
4896 path1
= make_wstr(exp_data
->path_1
);
4897 path2
= make_wstr(exp_data
->path_2
);
4898 verify_pidl(pidls
[0], path1
);
4899 verify_pidl(pidls
[1], path2
);
4900 HeapFree(GetProcessHeap(), 0, path1
);
4901 HeapFree(GetProcessHeap(), 0, path2
);
4903 exp_data
->missing_events
--;
4905 if(test_new_delivery_flag
)
4906 SHChangeNotification_Unlock(hLock
);
4908 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4911 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
4914 static void register_testwindow_class(void)
4919 ZeroMemory(&cls
, sizeof(cls
));
4920 cls
.cbSize
= sizeof(cls
);
4922 cls
.lpfnWndProc
= testwindow_wndproc
;
4923 cls
.hInstance
= GetModuleHandleA(NULL
);
4924 cls
.lpszClassName
= testwindow_class
;
4927 ret
= RegisterClassExA(&cls
);
4928 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4931 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4932 * have to poll repeatedly for the message to appear */
4933 static void do_events(void)
4936 while (exp_data
->missing_events
&& (c
++ < 10)){
4938 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4939 TranslateMessage(&msg
);
4940 DispatchMessageA(&msg
);
4942 if(exp_data
->missing_events
)
4945 trace("%s: took %d tries\n", exp_data
->id
, c
);
4948 static void test_SHChangeNotify(BOOL test_new_delivery
)
4953 BOOL br
, has_unicode
;
4954 SHChangeNotifyEntry entries
[1];
4955 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4956 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4958 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
4960 CreateDirectoryW(NULL
, NULL
);
4961 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
4963 test_new_delivery_flag
= test_new_delivery
;
4964 if(!test_new_delivery
)
4965 register_testwindow_class();
4967 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
4968 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
4969 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
4970 ok(wnd
!= NULL
, "Failed to make a window\n");
4972 br
= CreateDirectoryA(root_dirA
, NULL
);
4973 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4975 entries
[0].pidl
= NULL
;
4977 hr
= SHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4979 hr
= SHILCreateFromPath((LPCVOID
)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4980 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
4981 entries
[0].fRecursive
= TRUE
;
4983 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
4984 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
4985 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
4987 for(i
= 0; i
< sizeof(chnotify_tests
) / sizeof(*chnotify_tests
); ++i
){
4988 exp_data
= chnotify_tests
+ i
;
4990 exp_data
->missing_events
= exp_data
->notify_count
;
4991 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
4992 exp_data
->path_1
[0] ? exp_data
->path_1
: NULL
,
4993 exp_data
->path_2
[0] ? exp_data
->path_2
: NULL
);
4995 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4998 WCHAR
*path1
, *path2
;
5000 path1
= make_wstr(exp_data
->path_1
);
5001 path2
= make_wstr(exp_data
->path_2
);
5003 exp_data
->missing_events
= exp_data
->notify_count
;
5004 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
5006 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
5008 HeapFree(GetProcessHeap(), 0, path1
);
5009 HeapFree(GetProcessHeap(), 0, path2
);
5013 SHChangeNotifyDeregister(notifyID
);
5016 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
5017 br
= RemoveDirectoryA(root_dirA
);
5018 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
5021 static void test_SHCreateDefaultContextMenu(void)
5024 WCHAR path
[MAX_PATH
];
5025 IShellFolder
*desktop
,*folder
;
5026 IPersistFolder2
*persist
;
5027 IContextMenu
*cmenu
;
5029 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
5030 DEFCONTEXTMENU cminfo
;
5033 const WCHAR filename
[] =
5034 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
5035 if(!pSHCreateDefaultContextMenu
)
5037 win_skip("SHCreateDefaultContextMenu missing.\n");
5041 if(!pSHBindToParent
)
5043 skip("SHBindToParent missing.\n");
5047 GetCurrentDirectoryW(MAX_PATH
, path
);
5050 skip("GetCurrentDirectoryW returned an empty string.\n");
5053 lstrcatW(path
, filename
);
5054 SHGetDesktopFolder(&desktop
);
5056 CreateFilesFolders();
5058 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
5059 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
5063 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&folder
, (LPCITEMIDLIST
*)&pidl_child
);
5064 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5066 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
5067 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
5068 IPersistFolder2_Release(persist
);
5075 cminfo
.pidlFolder
=NULL
;
5076 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
5080 cminfo
.punkAssociationInfo
=NULL
;
5081 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5082 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5083 IContextMenu_Release(cmenu
);
5084 cminfo
.pidlFolder
=pidlFolder
;
5085 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5086 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5087 IContextMenu_Release(cmenu
);
5088 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
5089 if(status
==ERROR_SUCCESS
){
5094 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
5095 RegCloseKey(keys
[0]);
5096 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
5097 IContextMenu_Release(cmenu
);
5101 IShellFolder_Release(folder
);
5103 IShellFolder_Release(desktop
);
5108 static void test_SHCreateShellFolderView(void)
5113 IShellFolder
*desktop
;
5116 if (!pSHCreateShellFolderView
)
5118 win_skip("SHCreateShellFolderView missing.\n");
5122 hr
= SHGetDesktopFolder(&desktop
);
5123 ok(hr
== S_OK
, "got (0x%08x)\n", hr
);
5128 pSHCreateShellFolderView(NULL
, NULL
);
5131 psv
= (void *)0xdeadbeef;
5132 hr
= pSHCreateShellFolderView(NULL
, &psv
);
5133 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5134 ok(psv
== NULL
, "psv = %p\n", psv
);
5136 memset(&sfvc
, 0, sizeof(sfvc
));
5137 psv
= (void *)0xdeadbeef;
5138 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5139 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5140 ok(psv
== NULL
, "psv = %p\n", psv
);
5142 memset(&sfvc
, 0, sizeof(sfvc
));
5143 sfvc
.cbSize
= sizeof(sfvc
) - 1;
5144 psv
= (void *)0xdeadbeef;
5145 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5146 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5147 ok(psv
== NULL
, "psv = %p\n", psv
);
5149 memset(&sfvc
, 0, sizeof(sfvc
));
5150 sfvc
.cbSize
= sizeof(sfvc
) + 1;
5151 psv
= (void *)0xdeadbeef;
5152 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5153 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
5154 ok(psv
== NULL
, "psv = %p\n", psv
);
5156 memset(&sfvc
, 0, sizeof(sfvc
));
5157 sfvc
.cbSize
= sizeof(sfvc
);
5158 sfvc
.pshf
= desktop
;
5160 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
5161 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5162 ok(psv
!= NULL
, "psv = %p\n", psv
);
5165 refCount
= IShellView_Release(psv
);
5166 ok(refCount
== 0, "refCount = %u\n", refCount
);
5169 IShellFolder_Release(desktop
);
5172 static void test_SHCreateShellFolderViewEx(void)
5177 IShellFolder
*desktop
;
5180 if (!pSHCreateShellFolderViewEx
)
5182 win_skip("SHCreateShellFolderViewEx missing.\n");
5186 hr
= SHGetDesktopFolder(&desktop
);
5187 ok(hr
== S_OK
, "got (0x%08x)\n", hr
);
5192 pSHCreateShellFolderViewEx(NULL
, NULL
);
5193 pSHCreateShellFolderViewEx(NULL
, &psv
);
5194 pSHCreateShellFolderViewEx(&csfv
, NULL
);
5197 memset(&csfv
, 0, sizeof(csfv
));
5198 csfv
.pshf
= desktop
;
5200 hr
= pSHCreateShellFolderViewEx(&csfv
, &psv
);
5201 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5202 ok(psv
!= NULL
, "psv = %p\n", psv
);
5205 refCount
= IShellView_Release(psv
);
5206 ok(refCount
== 0, "refCount = %u\n", refCount
);
5209 memset(&csfv
, 0, sizeof(csfv
));
5210 csfv
.cbSize
= sizeof(csfv
);
5211 csfv
.pshf
= desktop
;
5213 hr
= pSHCreateShellFolderViewEx(&csfv
, &psv
);
5214 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
5215 ok(psv
!= NULL
, "psv = %p\n", psv
);
5218 refCount
= IShellView_Release(psv
);
5219 ok(refCount
== 0, "refCount = %u\n", refCount
);
5222 IShellFolder_Release(desktop
);
5225 START_TEST(shlfolder
)
5227 init_function_pointers();
5228 /* if OleInitialize doesn't get called, ParseDisplayName returns
5229 CO_E_NOTINITIALIZED for malformed directory names on win2k. */
5230 OleInitialize(NULL
);
5232 test_ParseDisplayName();
5233 test_SHParseDisplayName();
5234 test_BindToObject();
5235 test_EnumObjects_and_CompareIDs();
5236 test_GetDisplayName();
5237 test_GetAttributesOf();
5238 test_SHGetPathFromIDList();
5239 test_CallForAttributes();
5240 test_FolderShortcut();
5241 test_ITEMIDLIST_format();
5242 test_SHGetFolderPathA();
5243 test_SHGetFolderPathAndSubDirA();
5244 test_LocalizedNames();
5245 test_SHCreateShellItem();
5246 test_SHCreateShellItemArray();
5247 test_ShellItemArrayEnumItems();
5248 test_desktop_IPersist();
5250 test_SHSimpleIDListFromPath();
5251 test_ParseDisplayNamePBC();
5252 test_SHGetNameFromIDList();
5253 test_SHGetItemFromDataObject();
5254 test_SHGetIDListFromObject();
5255 test_SHGetItemFromObject();
5256 test_ShellItemCompare();
5257 test_SHChangeNotify(FALSE
);
5258 test_SHChangeNotify(TRUE
);
5259 test_ShellItemBindToHandler();
5260 test_ShellItemGetAttributes();
5261 test_ShellItemArrayGetAttributes();
5262 test_SHCreateDefaultContextMenu();
5263 test_SHCreateShellFolderView();
5264 test_SHCreateShellFolderViewEx();