2 * Unit test of the IShellFolder functions.
4 * Copyright 2004 Vitaliy Margolen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
40 #include "wine/test.h"
43 DEFINE_GUID(IID_IParentAndItem
, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
44 DEFINE_GUID(CLSID_ShellDocObjView
, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
48 static HRESULT (WINAPI
*pSHBindToParent
)(LPCITEMIDLIST
, REFIID
, LPVOID
*, LPCITEMIDLIST
*);
49 static HRESULT (WINAPI
*pSHGetFolderPathA
)(HWND
, int, HANDLE
, DWORD
, LPSTR
);
50 static HRESULT (WINAPI
*pSHGetFolderPathAndSubDirA
)(HWND
, int, HANDLE
, DWORD
, LPCSTR
, LPSTR
);
51 static BOOL (WINAPI
*pSHGetPathFromIDListW
)(LPCITEMIDLIST
,LPWSTR
);
52 static HRESULT (WINAPI
*pSHGetSpecialFolderLocation
)(HWND
, int, LPITEMIDLIST
*);
53 static BOOL (WINAPI
*pSHGetSpecialFolderPathA
)(HWND
, LPSTR
, int, BOOL
);
54 static BOOL (WINAPI
*pSHGetSpecialFolderPathW
)(HWND
, LPWSTR
, int, BOOL
);
55 static HRESULT (WINAPI
*pStrRetToBufW
)(STRRET
*,LPCITEMIDLIST
,LPWSTR
,UINT
);
56 static LPITEMIDLIST (WINAPI
*pILFindLastID
)(LPCITEMIDLIST
);
57 static void (WINAPI
*pILFree
)(LPITEMIDLIST
);
58 static BOOL (WINAPI
*pILIsEqual
)(LPCITEMIDLIST
, LPCITEMIDLIST
);
59 static HRESULT (WINAPI
*pSHCreateItemFromIDList
)(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
);
60 static HRESULT (WINAPI
*pSHCreateItemFromParsingName
)(PCWSTR
,IBindCtx
*,REFIID
,void**);
61 static HRESULT (WINAPI
*pSHCreateShellItem
)(LPCITEMIDLIST
,IShellFolder
*,LPCITEMIDLIST
,IShellItem
**);
62 static HRESULT (WINAPI
*pSHCreateShellItemArray
)(LPCITEMIDLIST
,IShellFolder
*,UINT
,LPCITEMIDLIST
*,IShellItemArray
**);
63 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromDataObject
)(IDataObject
*, REFIID
, void **);
64 static HRESULT (WINAPI
*pSHCreateShellItemArrayFromShellItem
)(IShellItem
*, REFIID
, void **);
65 static LPITEMIDLIST (WINAPI
*pILCombine
)(LPCITEMIDLIST
,LPCITEMIDLIST
);
66 static HRESULT (WINAPI
*pSHParseDisplayName
)(LPCWSTR
,IBindCtx
*,LPITEMIDLIST
*,SFGAOF
,SFGAOF
*);
67 static LPITEMIDLIST (WINAPI
*pSHSimpleIDListFromPathAW
)(LPCVOID
);
68 static HRESULT (WINAPI
*pSHGetNameFromIDList
)(PCIDLIST_ABSOLUTE
,SIGDN
,PWSTR
*);
69 static HRESULT (WINAPI
*pSHGetItemFromDataObject
)(IDataObject
*,DATAOBJ_GET_ITEM_FLAGS
,REFIID
,void**);
70 static HRESULT (WINAPI
*pSHGetIDListFromObject
)(IUnknown
*, PIDLIST_ABSOLUTE
*);
71 static HRESULT (WINAPI
*pSHGetItemFromObject
)(IUnknown
*,REFIID
,void**);
72 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, PBOOL
);
73 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)(LPWSTR
, UINT
);
74 static HRESULT (WINAPI
*pSHCreateDefaultContextMenu
)(const DEFCONTEXTMENU
*,REFIID
,void**);
75 static HRESULT (WINAPI
*pSHCreateShellFolderView
)(const SFV_CREATE
*pcsfv
, IShellView
**ppsv
);
76 static HRESULT (WINAPI
*pSHCreateShellFolderViewEx
)(LPCSFV psvcbi
, IShellView
**ppv
);
78 static const char *debugstr_guid(REFIID riid
)
82 sprintf(buf
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
83 riid
->Data1
, riid
->Data2
, riid
->Data3
, riid
->Data4
[0],
84 riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3], riid
->Data4
[4],
85 riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
90 static WCHAR
*make_wstr(const char *str
)
95 if(!str
|| strlen(str
) == 0)
98 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
102 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
106 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
110 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
113 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
114 return lstrcmpA(stra
, buf
);
117 static void init_function_pointers(void)
123 hmod
= GetModuleHandleA("shell32.dll");
125 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
126 MAKEFUNC(SHBindToParent
);
127 MAKEFUNC(SHCreateItemFromIDList
);
128 MAKEFUNC(SHCreateItemFromParsingName
);
129 MAKEFUNC(SHCreateShellItem
);
130 MAKEFUNC(SHCreateShellItemArray
);
131 MAKEFUNC(SHCreateShellItemArrayFromDataObject
);
132 MAKEFUNC(SHCreateShellItemArrayFromShellItem
);
133 MAKEFUNC(SHGetFolderPathA
);
134 MAKEFUNC(SHGetFolderPathAndSubDirA
);
135 MAKEFUNC(SHGetPathFromIDListW
);
136 MAKEFUNC(SHGetSpecialFolderPathA
);
137 MAKEFUNC(SHGetSpecialFolderPathW
);
138 MAKEFUNC(SHGetSpecialFolderLocation
);
139 MAKEFUNC(SHParseDisplayName
);
140 MAKEFUNC(SHGetNameFromIDList
);
141 MAKEFUNC(SHGetItemFromDataObject
);
142 MAKEFUNC(SHGetIDListFromObject
);
143 MAKEFUNC(SHGetItemFromObject
);
144 MAKEFUNC(SHCreateDefaultContextMenu
);
145 MAKEFUNC(SHCreateShellFolderView
);
146 MAKEFUNC(SHCreateShellFolderViewEx
);
149 #define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
150 MAKEFUNC_ORD(ILFindLastID
, 16);
151 MAKEFUNC_ORD(ILIsEqual
, 21);
152 MAKEFUNC_ORD(ILCombine
, 25);
153 MAKEFUNC_ORD(ILFree
, 155);
154 MAKEFUNC_ORD(SHSimpleIDListFromPathAW
, 162);
157 /* test named exports */
158 ptr
= GetProcAddress(hmod
, "ILFree");
159 ok(broken(ptr
== 0) || ptr
!= 0, "expected named export for ILFree\n");
162 #define TESTNAMED(f) \
163 ptr = (void*)GetProcAddress(hmod, #f); \
164 ok(ptr != 0, "expected named export for " #f "\n");
166 TESTNAMED(ILAppendID
);
168 TESTNAMED(ILCloneFirst
);
169 TESTNAMED(ILCombine
);
170 TESTNAMED(ILCreateFromPath
);
171 TESTNAMED(ILCreateFromPathA
);
172 TESTNAMED(ILCreateFromPathW
);
173 TESTNAMED(ILFindChild
);
174 TESTNAMED(ILFindLastID
);
175 TESTNAMED(ILGetNext
);
176 TESTNAMED(ILGetSize
);
177 TESTNAMED(ILIsEqual
);
178 TESTNAMED(ILIsParent
);
179 TESTNAMED(ILRemoveLastID
);
180 TESTNAMED(ILSaveToStream
);
184 hmod
= GetModuleHandleA("shlwapi.dll");
185 pStrRetToBufW
= (void*)GetProcAddress(hmod
, "StrRetToBufW");
187 hmod
= GetModuleHandleA("kernel32.dll");
188 pIsWow64Process
= (void*)GetProcAddress(hmod
, "IsWow64Process");
189 pGetSystemWow64DirectoryW
= (void*)GetProcAddress(hmod
, "GetSystemWow64DirectoryW");
191 hr
= SHGetMalloc(&ppM
);
192 ok(hr
== S_OK
, "SHGetMalloc failed %08x\n", hr
);
195 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
196 static LPWSTR
myPathAddBackslashW( LPWSTR lpszPath
)
200 if (!lpszPath
|| (iLen
= lstrlenW(lpszPath
)) >= MAX_PATH
)
206 if (lpszPath
[-1] != '\\')
215 static void test_ParseDisplayName(void)
218 IShellFolder
*IDesktopFolder
;
219 static const char *cNonExistDir1A
= "c:\\nonexist_subdir";
220 static const char *cNonExistDir2A
= "c:\\\\nonexist_subdir";
221 static const char *cInetTestA
= "http:\\yyy";
222 static const char *cInetTest2A
= "xx:yyy";
224 WCHAR cTestDirW
[MAX_PATH
] = {0};
228 hr
= SHGetDesktopFolder(&IDesktopFolder
);
229 ok(hr
== S_OK
, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr
);
230 if(hr
!= S_OK
) return;
232 /* Tests crash on W2K and below (SHCreateShellItem available as of XP) */
233 if (pSHCreateShellItem
)
235 /* null name and pidl */
236 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
237 NULL
, NULL
, NULL
, NULL
, NULL
, 0);
238 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
241 newPIDL
= (ITEMIDLIST
*)0xdeadbeef;
242 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
243 NULL
, NULL
, NULL
, NULL
, &newPIDL
, 0);
244 ok(newPIDL
== 0, "expected null, got %p\n", newPIDL
);
245 ok(hr
== E_INVALIDARG
, "returned %08x, expected E_INVALIDARG\n", hr
);
248 win_skip("Tests would crash on W2K and below\n");
250 MultiByteToWideChar(CP_ACP
, 0, cInetTestA
, -1, cTestDirW
, MAX_PATH
);
251 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
252 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
253 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
254 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
257 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
258 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
259 IMalloc_Free(ppM
, newPIDL
);
262 MultiByteToWideChar(CP_ACP
, 0, cInetTest2A
, -1, cTestDirW
, MAX_PATH
);
263 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
264 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
265 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* NT4 */,
266 "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr
);
269 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x61, "Last pidl should be of type "
270 "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL
)->mkid
.abID
[0]);
271 IMalloc_Free(ppM
, newPIDL
);
274 res
= GetFileAttributesA(cNonExistDir1A
);
275 if(res
!= INVALID_FILE_ATTRIBUTES
)
277 skip("Test directory unexpectedly exists\n");
281 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir1A
, -1, cTestDirW
, MAX_PATH
);
282 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
283 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
284 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
),
285 "ParseDisplayName returned %08x, expected 80070002 or E_FAIL\n", hr
);
287 res
= GetFileAttributesA(cNonExistDir2A
);
288 if(res
!= INVALID_FILE_ATTRIBUTES
)
290 skip("Test directory unexpectedly exists\n");
294 MultiByteToWideChar(CP_ACP
, 0, cNonExistDir2A
, -1, cTestDirW
, MAX_PATH
);
295 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
,
296 NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
297 ok((hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
)) || (hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
298 "ParseDisplayName returned %08x, expected 80070002, E_FAIL or E_INVALIDARG\n", hr
);
300 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the
301 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns
302 * out it doesn't. The magic seems to happen in the file dialogs, then. */
303 if (!pSHGetSpecialFolderPathW
|| !pILFindLastID
)
305 win_skip("SHGetSpecialFolderPathW and/or ILFindLastID are not available\n");
309 bRes
= pSHGetSpecialFolderPathW(NULL
, cTestDirW
, CSIDL_PERSONAL
, FALSE
);
310 ok(bRes
, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError());
311 if (!bRes
) goto finished
;
313 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
314 ok(hr
== S_OK
, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr
);
315 if (hr
!= S_OK
) goto finished
;
317 ok(pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0x31 ||
318 pILFindLastID(newPIDL
)->mkid
.abID
[0] == 0xb1, /* Win98 */
319 "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
320 pILFindLastID(newPIDL
)->mkid
.abID
[0]);
321 IMalloc_Free(ppM
, newPIDL
);
324 IShellFolder_Release(IDesktopFolder
);
327 /* creates a file with the specified name for tests */
328 static void CreateTestFile(const CHAR
*name
)
333 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
334 if (file
!= INVALID_HANDLE_VALUE
)
336 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
337 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
343 /* initializes the tests */
344 static void CreateFilesFolders(void)
346 CreateDirectoryA(".\\testdir", NULL
);
347 CreateDirectoryA(".\\testdir\\test.txt", NULL
);
348 CreateTestFile (".\\testdir\\test1.txt ");
349 CreateTestFile (".\\testdir\\test2.txt ");
350 CreateTestFile (".\\testdir\\test3.txt ");
351 CreateDirectoryA(".\\testdir\\testdir2 ", NULL
);
352 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL
);
355 /* cleans after tests */
356 static void Cleanup(void)
358 DeleteFileA(".\\testdir\\test1.txt");
359 DeleteFileA(".\\testdir\\test2.txt");
360 DeleteFileA(".\\testdir\\test3.txt");
361 RemoveDirectoryA(".\\testdir\\test.txt");
362 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
363 RemoveDirectoryA(".\\testdir\\testdir2");
364 RemoveDirectoryA(".\\testdir");
369 static void test_EnumObjects(IShellFolder
*iFolder
)
371 IEnumIDList
*iEnumList
;
372 LPITEMIDLIST newPIDL
, idlArr
[10];
377 static const WORD iResults
[5][5] =
386 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK
387 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */
388 static const ULONG attrs
[5] =
390 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
391 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
,
392 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
393 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
394 SFGAO_CAPABILITYMASK
| SFGAO_FILESYSTEM
,
397 hr
= IShellFolder_EnumObjects(iFolder
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &iEnumList
);
398 ok(hr
== S_OK
, "EnumObjects failed %08x\n", hr
);
400 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next,
401 * the filesystem shellfolders return S_OK even if less than 'celt' items are
402 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP
403 * only ever returns a single entry per call. */
404 while (IEnumIDList_Next(iEnumList
, 10-i
, &idlArr
[i
], &NumPIDLs
) == S_OK
)
406 ok (i
== 5, "i: %d\n", i
);
408 hr
= IEnumIDList_Release(iEnumList
);
409 ok(hr
== S_OK
, "IEnumIDList_Release failed %08x\n", hr
);
411 /* Sort them first in case of wrong order from system */
412 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
413 if ((SHORT
)IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]) < 0)
416 idlArr
[i
] = idlArr
[j
];
420 for (i
=0;i
<5;i
++) for (j
=0;j
<5;j
++)
422 hr
= IShellFolder_CompareIDs(iFolder
, 0, idlArr
[i
], idlArr
[j
]);
423 ok(hr
== iResults
[i
][j
], "Got %x expected [%d]-[%d]=%x\n", hr
, i
, j
, iResults
[i
][j
]);
427 for (i
= 0; i
< 5; i
++)
430 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY
431 /* Native returns all flags no matter what we ask for */
432 flags
= SFGAO_CANCOPY
;
433 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
434 flags
&= SFGAO_testfor
;
435 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
436 ok(flags
== (attrs
[i
]) ||
437 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
) || /* Win9x, NT4 */
438 flags
== ((attrs
[i
] & ~SFGAO_CAPABILITYMASK
) | SFGAO_VISTA
), /* Vista and higher */
439 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
441 flags
= SFGAO_testfor
;
442 hr
= IShellFolder_GetAttributesOf(iFolder
, 1, (LPCITEMIDLIST
*)(idlArr
+ i
), &flags
);
443 flags
&= SFGAO_testfor
;
444 ok(hr
== S_OK
, "GetAttributesOf returns %08x\n", hr
);
445 ok(flags
== attrs
[i
] ||
446 flags
== (attrs
[i
] & ~SFGAO_FILESYSANCESTOR
), /* Win9x, NT4 */
447 "GetAttributesOf[%i] got %08x, expected %08x\n", i
, flags
, attrs
[i
]);
451 IMalloc_Free(ppM
, idlArr
[i
]);
454 static void test_BindToObject(void)
458 IShellFolder
*psfDesktop
, *psfChild
, *psfMyComputer
, *psfSystemDir
;
459 SHITEMID emptyitem
= { 0, { 0 } };
460 LPITEMIDLIST pidlMyComputer
, pidlSystemDir
, pidl
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
461 WCHAR wszSystemDir
[MAX_PATH
];
462 char szSystemDir
[MAX_PATH
];
464 WCHAR path
[MAX_PATH
];
465 CHAR pathA
[MAX_PATH
];
467 WCHAR wszMyComputer
[] = {
468 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
469 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
470 static const CHAR filename_html
[] = "winetest.html";
471 static const CHAR filename_txt
[] = "winetest.txt";
472 static const CHAR filename_foo
[] = "winetest.foo";
474 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
475 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
477 hr
= SHGetDesktopFolder(&psfDesktop
);
478 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
479 if (hr
!= S_OK
) return;
481 hr
= IShellFolder_BindToObject(psfDesktop
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
482 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
484 hr
= IShellFolder_BindToObject(psfDesktop
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
485 ok (hr
== E_INVALIDARG
, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
487 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
488 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
490 IShellFolder_Release(psfDesktop
);
494 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
495 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
496 IShellFolder_Release(psfDesktop
);
497 IMalloc_Free(ppM
, pidlMyComputer
);
498 if (hr
!= S_OK
) return;
500 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
501 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
505 /* this call segfaults on 98SE */
506 hr
= IShellFolder_BindToObject(psfMyComputer
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
507 ok (hr
== E_INVALIDARG
, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
510 cChars
= GetSystemDirectoryA(szSystemDir
, MAX_PATH
);
511 ok (cChars
> 0 && cChars
< MAX_PATH
, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError());
512 if (cChars
== 0 || cChars
>= MAX_PATH
) {
513 IShellFolder_Release(psfMyComputer
);
516 MultiByteToWideChar(CP_ACP
, 0, szSystemDir
, -1, wszSystemDir
, MAX_PATH
);
518 hr
= IShellFolder_ParseDisplayName(psfMyComputer
, NULL
, NULL
, wszSystemDir
, NULL
, &pidlSystemDir
, NULL
);
519 ok (hr
== S_OK
, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr
);
521 IShellFolder_Release(psfMyComputer
);
525 hr
= IShellFolder_BindToObject(psfMyComputer
, pidlSystemDir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfSystemDir
);
526 ok (hr
== S_OK
, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr
);
527 IShellFolder_Release(psfMyComputer
);
528 IMalloc_Free(ppM
, pidlSystemDir
);
529 if (hr
!= S_OK
) return;
531 hr
= IShellFolder_BindToObject(psfSystemDir
, pidlEmpty
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
532 ok (hr
== E_INVALIDARG
,
533 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr
);
537 /* this call segfaults on 98SE */
538 hr
= IShellFolder_BindToObject(psfSystemDir
, NULL
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfChild
);
539 ok (hr
== E_INVALIDARG
,
540 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr
);
543 IShellFolder_Release(psfSystemDir
);
545 GetCurrentDirectoryA(MAX_PATH
, buf
);
548 skip("Failed to get current directory, skipping tests.\n");
552 SHGetDesktopFolder(&psfDesktop
);
554 /* Attempt BindToObject on files. */
557 lstrcpyA(pathA
, buf
);
558 lstrcatA(pathA
, "\\");
559 lstrcatA(pathA
, filename_html
);
560 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
561 if(hfile
!= INVALID_HANDLE_VALUE
)
564 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
565 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
566 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
569 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
571 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
576 hr
= IShellFolder_QueryInterface(psfChild
, &IID_IPersist
, (void**)&pp
);
578 broken(hr
== E_NOINTERFACE
), /* Win9x, NT4, W2K */
583 hr
= IPersist_GetClassID(pp
, &id
);
584 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
585 /* CLSID_ShellFSFolder on some w2k systems */
586 ok(IsEqualIID(&id
, &CLSID_ShellDocObjView
) || broken(IsEqualIID(&id
, &CLSID_ShellFSFolder
)),
587 "Unexpected classid %s\n", debugstr_guid(&id
));
588 IPersist_Release(pp
);
591 IShellFolder_Release(psfChild
);
598 win_skip("Failed to create .html testfile.\n");
601 lstrcpyA(pathA
, buf
);
602 lstrcatA(pathA
, "\\");
603 lstrcatA(pathA
, filename_txt
);
604 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
605 if(hfile
!= INVALID_HANDLE_VALUE
)
608 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
609 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
610 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
613 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
614 ok(hr
== E_FAIL
|| /* Vista+ */
615 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
616 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
618 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
624 win_skip("Failed to create .txt testfile.\n");
627 lstrcpyA(pathA
, buf
);
628 lstrcatA(pathA
, "\\");
629 lstrcatA(pathA
, filename_foo
);
630 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
631 if(hfile
!= INVALID_HANDLE_VALUE
)
634 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
635 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
636 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
639 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
640 ok(hr
== E_FAIL
|| /* Vista+ */
641 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
642 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
644 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
650 win_skip("Failed to create .foo testfile.\n");
652 /* And on the desktop */
653 if(pSHGetSpecialFolderPathA
)
655 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
656 lstrcatA(pathA
, "\\");
657 lstrcatA(pathA
, filename_html
);
658 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
659 if(hfile
!= INVALID_HANDLE_VALUE
)
662 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
663 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
664 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
667 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
669 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), /* XP, W2K3 */
671 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
674 if(!DeleteFileA(pathA
))
675 trace("Failed to delete: %d\n", GetLastError());
679 win_skip("Failed to create .html testfile.\n");
681 pSHGetSpecialFolderPathA(NULL
, pathA
, CSIDL_DESKTOP
, FALSE
);
682 lstrcatA(pathA
, "\\");
683 lstrcatA(pathA
, filename_foo
);
684 hfile
= CreateFileA(pathA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
685 if(hfile
!= INVALID_HANDLE_VALUE
)
688 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
689 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, path
, NULL
, &pidl
, NULL
);
690 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
693 hr
= IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (void**)&psfChild
);
694 ok(hr
== E_FAIL
|| /* Vista+ */
695 hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) || /* XP, W2K3 */
696 broken(hr
== S_OK
), /* Win9x, NT4, W2K */
698 if(SUCCEEDED(hr
)) IShellFolder_Release(psfChild
);
704 win_skip("Failed to create .foo testfile.\n");
707 IShellFolder_Release(psfDesktop
);
710 static void test_GetDisplayName(void)
715 WCHAR wszTestFile
[MAX_PATH
], wszTestFile2
[MAX_PATH
];
716 char szTestFile
[MAX_PATH
], szTestDir
[MAX_PATH
];
719 LPSHELLFOLDER psfDesktop
, psfPersonal
;
721 SHITEMID emptyitem
= { 0, { 0 } };
722 LPITEMIDLIST pidlTestFile
, pidlEmpty
= (LPITEMIDLIST
)&emptyitem
;
723 LPCITEMIDLIST pidlLast
;
724 static const CHAR szFileName
[] = "winetest.foo";
725 static const WCHAR wszFileName
[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
726 static const WCHAR wszDirName
[] = { 'w','i','n','e','t','e','s','t',0 };
728 /* I'm trying to figure if there is a functional difference between calling
729 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after
730 * binding to the shellfolder. One thing I thought of was that perhaps
731 * SHGetPathFromIDListW would be able to get the path to a file, which does
732 * not exist anymore, while the other method wouldn't. It turns out there's
733 * no functional difference in this respect.
736 if(!pSHGetSpecialFolderPathA
) {
737 win_skip("SHGetSpecialFolderPathA is not available\n");
741 /* First creating a directory in MyDocuments and a file in this directory. */
742 result
= pSHGetSpecialFolderPathA(NULL
, szTestDir
, CSIDL_PERSONAL
, FALSE
);
743 ok(result
, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
746 /* Use ANSI file functions so this works on Windows 9x */
747 lstrcatA(szTestDir
, "\\winetest");
748 CreateDirectoryA(szTestDir
, NULL
);
749 attr
=GetFileAttributesA(szTestDir
);
750 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
752 ok(0, "unable to create the '%s' directory\n", szTestDir
);
756 lstrcpyA(szTestFile
, szTestDir
);
757 lstrcatA(szTestFile
, "\\");
758 lstrcatA(szTestFile
, szFileName
);
759 hTestFile
= CreateFileA(szTestFile
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
760 ok((hTestFile
!= INVALID_HANDLE_VALUE
), "CreateFileA failed! Last error: %u\n", GetLastError());
761 if (hTestFile
== INVALID_HANDLE_VALUE
) return;
762 CloseHandle(hTestFile
);
764 /* Getting an itemidlist for the file. */
765 hr
= SHGetDesktopFolder(&psfDesktop
);
766 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
767 if (hr
!= S_OK
) return;
769 MultiByteToWideChar(CP_ACP
, 0, szTestFile
, -1, wszTestFile
, MAX_PATH
);
771 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
772 ok(hr
== S_OK
, "Desktop->ParseDisplayName failed! hr = %08x\n", hr
);
774 IShellFolder_Release(psfDesktop
);
778 pidlLast
= pILFindLastID(pidlTestFile
);
779 ok(pidlLast
->mkid
.cb
>=76 ||
780 broken(pidlLast
->mkid
.cb
== 28) || /* W2K */
781 broken(pidlLast
->mkid
.cb
== 40), /* Win9x, WinME */
782 "Expected pidl length of at least 76, got %d.\n", pidlLast
->mkid
.cb
);
783 if (pidlLast
->mkid
.cb
>= 28) {
784 ok(!lstrcmpA((CHAR
*)&pidlLast
->mkid
.abID
[12], szFileName
),
785 "Filename should be stored as ansi-string at this position!\n");
787 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
788 if (pidlLast
->mkid
.cb
>= 76) {
789 ok(!lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[46], wszFileName
) ||
790 (pidlLast
->mkid
.cb
>= 94 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[64], wszFileName
)) || /* Vista */
791 (pidlLast
->mkid
.cb
>= 98 && !lstrcmpW((WCHAR
*)&pidlLast
->mkid
.abID
[68], wszFileName
)), /* Win7 */
792 "Filename should be stored as wchar-string at this position!\n");
795 /* It seems as if we cannot bind to regular files on windows, but only directories.
797 hr
= IShellFolder_BindToObject(psfDesktop
, pidlTestFile
, NULL
, &IID_IUnknown
, (VOID
**)&psfFile
);
798 ok (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
799 hr
== E_NOTIMPL
|| /* Vista */
800 broken(hr
== S_OK
), /* Win9x, W2K */
803 IUnknown_Release(psfFile
);
806 if (!pSHBindToParent
)
808 win_skip("SHBindToParent is missing\n");
809 DeleteFileA(szTestFile
);
810 RemoveDirectoryA(szTestDir
);
814 /* Some tests for IShellFolder::SetNameOf */
815 if (pSHGetFolderPathAndSubDirA
)
817 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
818 ok(hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
820 /* It's ok to use this fixed path. Call will fail anyway. */
821 WCHAR wszAbsoluteFilename
[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
822 LPITEMIDLIST pidlNew
;
824 /* The pidl returned through the last parameter of SetNameOf is a simple one. */
825 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlLast
, wszDirName
, SHGDN_NORMAL
, &pidlNew
);
826 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
829 ok (((LPITEMIDLIST
)((LPBYTE
)pidlNew
+pidlNew
->mkid
.cb
))->mkid
.cb
== 0,
830 "pidl returned from SetNameOf should be simple!\n");
832 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
833 * is implemented on top of SHFileOperation in WinXP. */
834 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszAbsoluteFilename
,
835 SHGDN_FORPARSING
, NULL
);
836 ok (hr
== HRESULT_FROM_WIN32(ERROR_CANCELLED
), "SetNameOf succeeded! hr = %08x\n", hr
);
838 /* Rename the file back to its original name. SetNameOf ignores the fact, that the
839 * SHGDN flags specify an absolute path. */
840 hr
= IShellFolder_SetNameOf(psfPersonal
, NULL
, pidlNew
, wszFileName
, SHGDN_FORPARSING
, NULL
);
841 ok (hr
== S_OK
, "SetNameOf failed! hr = %08x\n", hr
);
846 IShellFolder_Release(psfPersonal
);
850 win_skip("Avoid needs of interaction on Win2k\n");
852 /* Deleting the file and the directory */
853 DeleteFileA(szTestFile
);
854 RemoveDirectoryA(szTestDir
);
856 /* SHGetPathFromIDListW still works, although the file is not present anymore. */
857 if (pSHGetPathFromIDListW
)
859 result
= pSHGetPathFromIDListW(pidlTestFile
, wszTestFile2
);
860 ok (result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
861 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "SHGetPathFromIDListW returns incorrect path!\n");
864 /* SHBindToParent fails, if called with a NULL PIDL. */
865 hr
= pSHBindToParent(NULL
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
866 ok (hr
!= S_OK
, "SHBindToParent(NULL) should fail!\n");
868 /* But it succeeds with an empty PIDL. */
869 hr
= pSHBindToParent(pidlEmpty
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
870 ok (hr
== S_OK
, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr
);
871 ok (pidlLast
== pidlEmpty
, "The last element of an empty PIDL should be the PIDL itself!\n");
873 IShellFolder_Release(psfPersonal
);
875 /* Binding to the folder and querying the display name of the file also works. */
876 hr
= pSHBindToParent(pidlTestFile
, &IID_IShellFolder
, (VOID
**)&psfPersonal
, &pidlLast
);
877 ok (hr
== S_OK
, "SHBindToParent failed! hr = %08x\n", hr
);
879 IShellFolder_Release(psfDesktop
);
883 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into
884 * pidlTestFile (In accordance with MSDN). */
885 ok (pILFindLastID(pidlTestFile
) == pidlLast
,
886 "SHBindToParent doesn't return the last id of the pidl param!\n");
888 hr
= IShellFolder_GetDisplayNameOf(psfPersonal
, pidlLast
, SHGDN_FORPARSING
, &strret
);
889 ok (hr
== S_OK
, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr
);
891 IShellFolder_Release(psfDesktop
);
892 IShellFolder_Release(psfPersonal
);
898 hr
= pStrRetToBufW(&strret
, pidlLast
, wszTestFile2
, MAX_PATH
);
899 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
900 ok (!lstrcmpiW(wszTestFile
, wszTestFile2
), "GetDisplayNameOf returns incorrect path!\n");
903 ILFree(pidlTestFile
);
904 IShellFolder_Release(psfDesktop
);
905 IShellFolder_Release(psfPersonal
);
908 static void test_CallForAttributes(void)
914 LPSHELLFOLDER psfDesktop
;
915 LPITEMIDLIST pidlMyDocuments
;
916 DWORD dwAttributes
, dwCallForAttributes
, dwOrigAttributes
, dwOrigCallForAttributes
;
917 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
918 static const WCHAR wszCallForAttributes
[] = {
919 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
920 static const WCHAR wszMyDocumentsKey
[] = {
921 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-',
922 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',
923 '\\','S','h','e','l','l','F','o','l','d','e','r',0 };
924 WCHAR wszMyDocuments
[] = {
925 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-',
926 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 };
928 /* For the root of a namespace extension, the attributes are not queried by binding
929 * to the object and calling GetAttributesOf. Instead, the attributes are read from
930 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN.
932 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes
933 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes,
934 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented
935 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2.
937 hr
= SHGetDesktopFolder(&psfDesktop
);
938 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
939 if (hr
!= S_OK
) return;
941 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyDocuments
, NULL
,
942 &pidlMyDocuments
, NULL
);
944 broken(hr
== E_INVALIDARG
), /* Win95, NT4 */
945 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr
);
947 IShellFolder_Release(psfDesktop
);
951 dwAttributes
= 0xffffffff;
952 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
953 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
954 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
956 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */
957 ok (dwAttributes
& SFGAO_FILESYSTEM
, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n");
958 ok (!(dwAttributes
& SFGAO_ISSLOW
), "SFGAO_ISSLOW attribute is set for MyDocuments!\n");
959 ok (!(dwAttributes
& SFGAO_GHOSTED
), "SFGAO_GHOSTED attribute is set for MyDocuments!\n");
961 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry
962 * key. So the test will return at this point, if run on wine.
964 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszMyDocumentsKey
, 0, KEY_WRITE
|KEY_READ
, &hKey
);
965 ok (lResult
== ERROR_SUCCESS
||
966 lResult
== ERROR_ACCESS_DENIED
,
967 "RegOpenKeyEx failed! result: %08x\n", lResult
);
968 if (lResult
!= ERROR_SUCCESS
) {
969 if (lResult
== ERROR_ACCESS_DENIED
)
970 skip("Not enough rights to open the registry key\n");
971 IMalloc_Free(ppM
, pidlMyDocuments
);
972 IShellFolder_Release(psfDesktop
);
976 /* Query MyDocuments' Attributes value, to be able to restore it later. */
977 dwSize
= sizeof(DWORD
);
978 lResult
= RegQueryValueExW(hKey
, wszAttributes
, NULL
, NULL
, (LPBYTE
)&dwOrigAttributes
, &dwSize
);
979 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
980 if (lResult
!= ERROR_SUCCESS
) {
982 IMalloc_Free(ppM
, pidlMyDocuments
);
983 IShellFolder_Release(psfDesktop
);
987 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */
988 dwSize
= sizeof(DWORD
);
989 lResult
= RegQueryValueExW(hKey
, wszCallForAttributes
, NULL
, NULL
,
990 (LPBYTE
)&dwOrigCallForAttributes
, &dwSize
);
991 ok (lResult
== ERROR_SUCCESS
, "RegQueryValueEx failed! result: %08x\n", lResult
);
992 if (lResult
!= ERROR_SUCCESS
) {
994 IMalloc_Free(ppM
, pidlMyDocuments
);
995 IShellFolder_Release(psfDesktop
);
999 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and
1000 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and
1001 * SFGAO_FILESYSTEM attributes. */
1002 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
;
1003 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwAttributes
, sizeof(DWORD
));
1004 dwCallForAttributes
= SFGAO_ISSLOW
|SFGAO_FILESYSTEM
;
1005 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1006 (LPBYTE
)&dwCallForAttributes
, sizeof(DWORD
));
1008 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by
1009 * GetAttributesOf. It seems that once there is a single attribute queried, for which
1010 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and
1011 * the flags in Attributes are ignored.
1013 dwAttributes
= SFGAO_ISSLOW
|SFGAO_GHOSTED
|SFGAO_FILESYSTEM
;
1014 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1,
1015 (LPCITEMIDLIST
*)&pidlMyDocuments
, &dwAttributes
);
1016 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr
);
1018 ok (dwAttributes
== SFGAO_FILESYSTEM
,
1019 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n",
1022 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */
1023 RegSetValueExW(hKey
, wszAttributes
, 0, REG_DWORD
, (LPBYTE
)&dwOrigAttributes
, sizeof(DWORD
));
1024 RegSetValueExW(hKey
, wszCallForAttributes
, 0, REG_DWORD
,
1025 (LPBYTE
)&dwOrigCallForAttributes
, sizeof(DWORD
));
1027 IMalloc_Free(ppM
, pidlMyDocuments
);
1028 IShellFolder_Release(psfDesktop
);
1031 static void test_GetAttributesOf(void)
1034 LPSHELLFOLDER psfDesktop
, psfMyComputer
;
1035 SHITEMID emptyitem
= { 0, { 0 } };
1036 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1037 LPITEMIDLIST pidlMyComputer
;
1039 static const DWORD desktopFlags
[] = {
1041 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
|
1042 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1044 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_STREAM
| SFGAO_FILESYSANCESTOR
|
1045 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
,
1046 /* WinMe, Win9x, WinNT*/
1047 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSANCESTOR
|
1048 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1050 static const DWORD myComputerFlags
[] = {
1052 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
1053 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1055 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_STREAM
|
1056 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1057 /* WinMe, Win9x, WinNT */
1058 SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1059 SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
,
1060 /* Win95, WinNT when queried directly */
1061 SFGAO_CANLINK
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
| SFGAO_FILESYSANCESTOR
|
1062 SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
1064 WCHAR wszMyComputer
[] = {
1065 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1066 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1067 char cCurrDirA
[MAX_PATH
] = {0};
1068 WCHAR cCurrDirW
[MAX_PATH
];
1069 static WCHAR cTestDirW
[] = {'t','e','s','t','d','i','r',0};
1070 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1071 ITEMIDLIST
*newPIDL
;
1073 BOOL foundFlagsMatch
;
1075 hr
= SHGetDesktopFolder(&psfDesktop
);
1076 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1077 if (hr
!= S_OK
) return;
1079 /* The Desktop attributes can be queried with a single empty itemidlist, .. */
1080 dwFlags
= 0xffffffff;
1081 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, &pidlEmpty
, &dwFlags
);
1082 ok (hr
== S_OK
, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr
);
1083 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1084 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1086 if (desktopFlags
[i
] == dwFlags
)
1087 foundFlagsMatch
= TRUE
;
1089 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1091 /* .. or with no itemidlist at all. */
1092 dwFlags
= 0xffffffff;
1093 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 0, NULL
, &dwFlags
);
1094 ok (hr
== S_OK
, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1095 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1096 i
< sizeof(desktopFlags
) / sizeof(desktopFlags
[0]); i
++)
1098 if (desktopFlags
[i
] == dwFlags
)
1099 foundFlagsMatch
= TRUE
;
1101 ok (foundFlagsMatch
, "Wrong Desktop attributes: %08x\n", dwFlags
);
1103 /* Testing the attributes of the MyComputer shellfolder */
1104 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1105 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1107 IShellFolder_Release(psfDesktop
);
1111 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
1112 * folder object. It doesn't do this, if MyComputer is queried directly (see below).
1114 dwFlags
= 0xffffffff;
1115 hr
= IShellFolder_GetAttributesOf(psfDesktop
, 1, (LPCITEMIDLIST
*)&pidlMyComputer
, &dwFlags
);
1116 ok (hr
== S_OK
, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr
);
1117 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1118 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1120 if ((myComputerFlags
[i
] | SFGAO_CANLINK
) == dwFlags
)
1121 foundFlagsMatch
= TRUE
;
1124 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1126 hr
= IShellFolder_BindToObject(psfDesktop
, pidlMyComputer
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfMyComputer
);
1127 ok (hr
== S_OK
, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr
);
1128 IShellFolder_Release(psfDesktop
);
1129 IMalloc_Free(ppM
, pidlMyComputer
);
1130 if (hr
!= S_OK
) return;
1132 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 1, &pidlEmpty
, &dwFlags
);
1134 ok (hr
== E_INVALIDARG
||
1135 broken(hr
== S_OK
), /* W2K and earlier */
1136 "MyComputer->GetAttributesOf(emtpy pidl) should fail! hr = %08x\n", hr
);
1138 dwFlags
= 0xffffffff;
1139 hr
= IShellFolder_GetAttributesOf(psfMyComputer
, 0, NULL
, &dwFlags
);
1140 ok (hr
== S_OK
, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr
);
1141 for (i
= 0, foundFlagsMatch
= FALSE
; !foundFlagsMatch
&&
1142 i
< sizeof(myComputerFlags
) / sizeof(myComputerFlags
[0]); i
++)
1144 if (myComputerFlags
[i
] == dwFlags
)
1145 foundFlagsMatch
= TRUE
;
1148 ok (foundFlagsMatch
, "Wrong MyComputer attributes: %08x\n", dwFlags
);
1150 IShellFolder_Release(psfMyComputer
);
1152 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1153 len
= lstrlenA(cCurrDirA
);
1156 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
1159 if (len
> 3 && cCurrDirA
[len
-1] == '\\')
1160 cCurrDirA
[len
-1] = 0;
1162 /* create test directory */
1163 CreateFilesFolders();
1165 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1167 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1168 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1170 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1171 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1173 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1174 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1176 IMalloc_Free(ppM
, newPIDL
);
1178 /* get relative PIDL */
1179 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1180 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1182 /* test the shell attributes of the test directory using the relative PIDL */
1183 dwFlags
= SFGAO_FOLDER
;
1184 hr
= IShellFolder_GetAttributesOf(testIShellFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1185 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1186 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags
);
1189 IMalloc_Free(ppM
, newPIDL
);
1191 /* append testdirectory name to path */
1192 if (cCurrDirA
[len
-1] == '\\')
1193 cCurrDirA
[len
-1] = 0;
1194 lstrcatA(cCurrDirA
, "\\testdir");
1195 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
1197 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
1198 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1200 /* test the shell attributes of the test directory using the absolute PIDL */
1201 dwFlags
= SFGAO_FOLDER
;
1202 hr
= IShellFolder_GetAttributesOf(IDesktopFolder
, 1, (LPCITEMIDLIST
*)&newPIDL
, &dwFlags
);
1203 ok (hr
== S_OK
, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr
);
1204 ok ((dwFlags
&SFGAO_FOLDER
), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags
);
1207 IMalloc_Free(ppM
, newPIDL
);
1209 IShellFolder_Release(testIShellFolder
);
1213 IShellFolder_Release(IDesktopFolder
);
1216 static void test_SHGetPathFromIDList(void)
1218 SHITEMID emptyitem
= { 0, { 0 } };
1219 LPCITEMIDLIST pidlEmpty
= (LPCITEMIDLIST
)&emptyitem
;
1220 LPITEMIDLIST pidlMyComputer
;
1221 WCHAR wszPath
[MAX_PATH
], wszDesktop
[MAX_PATH
];
1224 LPSHELLFOLDER psfDesktop
;
1225 WCHAR wszMyComputer
[] = {
1226 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
1227 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
1228 WCHAR wszFileName
[MAX_PATH
];
1229 LPITEMIDLIST pidlTestFile
;
1232 static WCHAR wszTestFile
[] = {
1233 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
1234 LPITEMIDLIST pidlPrograms
;
1236 if(!pSHGetPathFromIDListW
|| !pSHGetSpecialFolderPathW
)
1238 win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
1242 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */
1245 result
= pSHGetPathFromIDListW(NULL
, wszPath
);
1246 ok(!result
, "Expected failure\n");
1247 ok(!wszPath
[0], "Expected empty string\n");
1249 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */
1250 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktop
, CSIDL_DESKTOP
, FALSE
);
1251 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
1252 if (!result
) return;
1254 /* Check if we are on Win9x */
1255 SetLastError(0xdeadbeef);
1256 lstrcmpiW(wszDesktop
, wszDesktop
);
1257 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1259 win_skip("Most W-calls are not implemented\n");
1263 result
= pSHGetPathFromIDListW(pidlEmpty
, wszPath
);
1264 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1265 if (!result
) return;
1266 ok(!lstrcmpiW(wszDesktop
, wszPath
), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n");
1268 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */
1269 hr
= SHGetDesktopFolder(&psfDesktop
);
1270 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1271 if (hr
!= S_OK
) return;
1273 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszMyComputer
, NULL
, &pidlMyComputer
, NULL
);
1274 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr
);
1276 IShellFolder_Release(psfDesktop
);
1280 SetLastError(0xdeadbeef);
1283 result
= pSHGetPathFromIDListW(pidlMyComputer
, wszPath
);
1284 ok (!result
, "SHGetPathFromIDListW succeeded where it shouldn't!\n");
1285 ok (GetLastError()==0xdeadbeef ||
1286 GetLastError()==ERROR_SUCCESS
, /* Vista and higher */
1287 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError());
1288 ok (!wszPath
[0], "Expected empty path\n");
1290 IShellFolder_Release(psfDesktop
);
1294 IMalloc_Free(ppM
, pidlMyComputer
);
1296 result
= pSHGetSpecialFolderPathW(NULL
, wszFileName
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1297 ok(result
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1299 IShellFolder_Release(psfDesktop
);
1302 myPathAddBackslashW(wszFileName
);
1303 lstrcatW(wszFileName
, wszTestFile
);
1304 hTestFile
= CreateFileW(wszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1305 ok(hTestFile
!= INVALID_HANDLE_VALUE
, "CreateFileW failed! Last error: %u\n", GetLastError());
1306 if (hTestFile
== INVALID_HANDLE_VALUE
) {
1307 IShellFolder_Release(psfDesktop
);
1310 CloseHandle(hTestFile
);
1312 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszTestFile
, NULL
, &pidlTestFile
, NULL
);
1313 ok (hr
== S_OK
, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr
);
1315 IShellFolder_Release(psfDesktop
);
1316 DeleteFileW(wszFileName
);
1317 IMalloc_Free(ppM
, pidlTestFile
);
1321 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY
1322 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */
1323 hr
= IShellFolder_GetDisplayNameOf(psfDesktop
, pidlTestFile
, SHGDN_FORPARSING
, &strret
);
1324 ok (hr
== S_OK
, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr
);
1325 IShellFolder_Release(psfDesktop
);
1326 DeleteFileW(wszFileName
);
1328 IMalloc_Free(ppM
, pidlTestFile
);
1333 pStrRetToBufW(&strret
, pidlTestFile
, wszPath
, MAX_PATH
);
1334 ok(0 == lstrcmpW(wszFileName
, wszPath
),
1335 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) "
1336 "returned incorrect path for file placed on desktop\n");
1339 result
= pSHGetPathFromIDListW(pidlTestFile
, wszPath
);
1340 ok(result
, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
1341 IMalloc_Free(ppM
, pidlTestFile
);
1342 if (!result
) return;
1343 ok(0 == lstrcmpW(wszFileName
, wszPath
), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
1346 /* Test if we can get the path from the start menu "program files" PIDL. */
1347 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidlPrograms
);
1348 ok(hr
== S_OK
, "SHGetFolderLocation failed: 0x%08x\n", hr
);
1350 SetLastError(0xdeadbeef);
1351 result
= pSHGetPathFromIDListW(pidlPrograms
, wszPath
);
1352 IMalloc_Free(ppM
, pidlPrograms
);
1353 ok(result
, "SHGetPathFromIDListW failed\n");
1356 static void test_EnumObjects_and_CompareIDs(void)
1358 ITEMIDLIST
*newPIDL
;
1359 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
1360 char cCurrDirA
[MAX_PATH
] = {0};
1361 static const CHAR cTestDirA
[] = "\\testdir";
1362 WCHAR cTestDirW
[MAX_PATH
];
1366 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
1367 len
= lstrlenA(cCurrDirA
);
1370 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
1373 if(cCurrDirA
[len
-1] == '\\')
1374 cCurrDirA
[len
-1] = 0;
1376 lstrcatA(cCurrDirA
, cTestDirA
);
1377 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cTestDirW
, MAX_PATH
);
1379 hr
= SHGetDesktopFolder(&IDesktopFolder
);
1380 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
1382 CreateFilesFolders();
1384 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cTestDirW
, NULL
, &newPIDL
, 0);
1385 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
1387 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
1388 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
1390 test_EnumObjects(testIShellFolder
);
1392 IShellFolder_Release(testIShellFolder
);
1396 IMalloc_Free(ppM
, newPIDL
);
1398 IShellFolder_Release(IDesktopFolder
);
1401 /* A simple implementation of an IPropertyBag, which returns fixed values for
1402 * 'Target' and 'Attributes' properties.
1404 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag
*iface
, REFIID riid
,
1408 return E_INVALIDARG
;
1410 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPropertyBag
, riid
)) {
1413 ok (FALSE
, "InitPropertyBag asked for unknown interface!\n");
1414 return E_NOINTERFACE
;
1417 IPropertyBag_AddRef(iface
);
1421 static ULONG WINAPI
InitPropertyBag_IPropertyBag_AddRef(IPropertyBag
*iface
) {
1425 static ULONG WINAPI
InitPropertyBag_IPropertyBag_Release(IPropertyBag
*iface
) {
1429 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Read(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1430 VARIANT
*pVar
, IErrorLog
*pErrorLog
)
1432 static const WCHAR wszTargetSpecialFolder
[] = {
1433 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 };
1434 static const WCHAR wszTarget
[] = {
1435 'T','a','r','g','e','t',0 };
1436 static const WCHAR wszAttributes
[] = {
1437 'A','t','t','r','i','b','u','t','e','s',0 };
1438 static const WCHAR wszResolveLinkFlags
[] = {
1439 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
1440 static const WCHAR wszTargetKnownFolder
[] = {
1441 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 };
1442 static const WCHAR wszCLSID
[] = {
1443 'C','L','S','I','D',0 };
1445 if (!lstrcmpW(pszPropName
, wszTargetSpecialFolder
)) {
1446 ok(V_VT(pVar
) == VT_I4
||
1447 broken(V_VT(pVar
) == VT_BSTR
), /* Win2k */
1448 "Wrong variant type for 'TargetSpecialFolder' property!\n");
1449 return E_INVALIDARG
;
1452 if (!lstrcmpW(pszPropName
, wszResolveLinkFlags
))
1454 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'ResolveLinkFlags' property!\n");
1455 return E_INVALIDARG
;
1458 if (!lstrcmpW(pszPropName
, wszTarget
)) {
1459 WCHAR wszPath
[MAX_PATH
];
1462 ok(V_VT(pVar
) == VT_BSTR
||
1463 broken(V_VT(pVar
) == VT_EMPTY
), /* Win2k */
1464 "Wrong variant type for 'Target' property!\n");
1465 if (V_VT(pVar
) != VT_BSTR
) return E_INVALIDARG
;
1467 result
= pSHGetSpecialFolderPathW(NULL
, wszPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1468 ok(result
, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1469 if (!result
) return E_INVALIDARG
;
1471 V_BSTR(pVar
) = SysAllocString(wszPath
);
1475 if (!lstrcmpW(pszPropName
, wszAttributes
)) {
1476 ok(V_VT(pVar
) == VT_UI4
, "Wrong variant type for 'Attributes' property!\n");
1477 if (V_VT(pVar
) != VT_UI4
) return E_INVALIDARG
;
1478 V_UI4(pVar
) = SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
|SFGAO_FILESYSANCESTOR
|
1479 SFGAO_CANRENAME
|SFGAO_FILESYSTEM
;
1483 if (!lstrcmpW(pszPropName
, wszTargetKnownFolder
)) {
1484 ok(V_VT(pVar
) == VT_BSTR
, "Wrong variant type for 'TargetKnownFolder' property!\n");
1486 return E_INVALIDARG
;
1489 if (!lstrcmpW(pszPropName
, wszCLSID
)) {
1490 ok(V_VT(pVar
) == VT_EMPTY
, "Wrong variant type for 'CLSID' property!\n");
1492 return E_INVALIDARG
;
1495 ok(FALSE
, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName
), V_VT(pVar
));
1496 return E_INVALIDARG
;
1499 static HRESULT WINAPI
InitPropertyBag_IPropertyBag_Write(IPropertyBag
*iface
, LPCOLESTR pszPropName
,
1502 ok(FALSE
, "Unexpected call to IPropertyBag_Write\n");
1506 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl
= {
1507 InitPropertyBag_IPropertyBag_QueryInterface
,
1508 InitPropertyBag_IPropertyBag_AddRef
,
1509 InitPropertyBag_IPropertyBag_Release
,
1510 InitPropertyBag_IPropertyBag_Read
,
1511 InitPropertyBag_IPropertyBag_Write
1514 static struct IPropertyBag InitPropertyBag
= {
1515 &InitPropertyBag_IPropertyBagVtbl
1518 static void test_FolderShortcut(void) {
1519 IPersistPropertyBag
*pPersistPropertyBag
;
1520 IShellFolder
*pShellFolder
, *pDesktopFolder
;
1521 IPersistFolder3
*pPersistFolder3
;
1524 WCHAR wszDesktopPath
[MAX_PATH
], wszBuffer
[MAX_PATH
];
1527 LPITEMIDLIST pidlCurrentFolder
, pidlWineTestFolder
, pidlSubFolder
;
1529 WCHAR wszWineTestFolder
[] = {
1530 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
1531 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
1532 WCHAR wszShellExtKey
[] = { 'S','o','f','t','w','a','r','e','\\',
1533 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1534 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1535 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
1536 'N','a','m','e','S','p','a','c','e','\\',
1537 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-',
1538 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 };
1540 WCHAR wszSomeSubFolder
[] = { 'S','u','b','F','o','l','d','e','r', 0};
1541 static const GUID CLSID_UnixDosFolder
=
1542 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
1544 if (!pSHGetSpecialFolderPathW
|| !pStrRetToBufW
) {
1545 win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
1549 if (!pSHGetFolderPathAndSubDirA
)
1551 win_skip("FolderShortcut test doesn't work on Win2k\n");
1555 /* These tests basically show, that CLSID_FolderShortcuts are initialized
1556 * via their IPersistPropertyBag interface. And that the target folder
1557 * is taken from the IPropertyBag's 'Target' property.
1559 hr
= CoCreateInstance(&CLSID_FolderShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
1560 &IID_IPersistPropertyBag
, (LPVOID
*)&pPersistPropertyBag
);
1561 if (hr
== REGDB_E_CLASSNOTREG
) {
1562 win_skip("CLSID_FolderShortcut is not implemented\n");
1565 ok (hr
== S_OK
, "CoCreateInstance failed! hr = 0x%08x\n", hr
);
1566 if (hr
!= S_OK
) return;
1568 hr
= IPersistPropertyBag_Load(pPersistPropertyBag
, &InitPropertyBag
, NULL
);
1569 ok(hr
== S_OK
, "IPersistPropertyBag_Load failed! hr = %08x\n", hr
);
1571 IPersistPropertyBag_Release(pPersistPropertyBag
);
1575 hr
= IPersistPropertyBag_QueryInterface(pPersistPropertyBag
, &IID_IShellFolder
,
1576 (LPVOID
*)&pShellFolder
);
1577 IPersistPropertyBag_Release(pPersistPropertyBag
);
1578 ok(hr
== S_OK
, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1579 if (hr
!= S_OK
) return;
1581 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1582 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1584 IShellFolder_Release(pShellFolder
);
1588 result
= pSHGetSpecialFolderPathW(NULL
, wszDesktopPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
1589 ok(result
, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
1590 if (!result
) return;
1592 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1593 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1595 hr
= IShellFolder_QueryInterface(pShellFolder
, &IID_IPersistFolder3
, (LPVOID
*)&pPersistFolder3
);
1596 IShellFolder_Release(pShellFolder
);
1597 ok(hr
== S_OK
, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr
);
1598 if (hr
!= S_OK
) return;
1600 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1601 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1602 ok(IsEqualCLSID(&clsid
, &CLSID_FolderShortcut
), "Unexpected CLSID!\n");
1604 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1605 todo_wine
ok(hr
== S_FALSE
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1606 ok(!pidlCurrentFolder
, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n");
1608 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the
1609 * shell namespace. The target folder, read from the property bag above, remains untouched.
1610 * The following tests show this: The itemidlist for some imaginary shellfolder object
1611 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this
1612 * itemidlist, but GetDisplayNameOf still returns the path from above.
1614 hr
= SHGetDesktopFolder(&pDesktopFolder
);
1615 ok (hr
== S_OK
, "SHGetDesktopFolder failed! hr = %08x\n", hr
);
1616 if (hr
!= S_OK
) return;
1618 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop.
1619 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */
1620 RegCreateKeyW(HKEY_CURRENT_USER
, wszShellExtKey
, &hShellExtKey
);
1621 RegCloseKey(hShellExtKey
);
1622 hr
= IShellFolder_ParseDisplayName(pDesktopFolder
, NULL
, NULL
, wszWineTestFolder
, NULL
,
1623 &pidlWineTestFolder
, NULL
);
1624 RegDeleteKeyW(HKEY_CURRENT_USER
, wszShellExtKey
);
1625 IShellFolder_Release(pDesktopFolder
);
1626 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1627 if (hr
!= S_OK
) return;
1629 hr
= IPersistFolder3_Initialize(pPersistFolder3
, pidlWineTestFolder
);
1630 ok (hr
== S_OK
, "IPersistFolder3::Initialize failed! hr = %08x\n", hr
);
1632 IPersistFolder3_Release(pPersistFolder3
);
1633 pILFree(pidlWineTestFolder
);
1637 hr
= IPersistFolder3_GetCurFolder(pPersistFolder3
, &pidlCurrentFolder
);
1638 ok(hr
== S_OK
, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr
);
1639 ok(pILIsEqual(pidlCurrentFolder
, pidlWineTestFolder
),
1640 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n");
1641 pILFree(pidlCurrentFolder
);
1642 pILFree(pidlWineTestFolder
);
1644 hr
= IPersistFolder3_QueryInterface(pPersistFolder3
, &IID_IShellFolder
, (LPVOID
*)&pShellFolder
);
1645 IPersistFolder3_Release(pPersistFolder3
);
1646 ok(hr
== S_OK
, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr
);
1647 if (hr
!= S_OK
) return;
1649 hr
= IShellFolder_GetDisplayNameOf(pShellFolder
, NULL
, SHGDN_FORPARSING
, &strret
);
1650 ok(hr
== S_OK
, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr
);
1652 IShellFolder_Release(pShellFolder
);
1656 pStrRetToBufW(&strret
, NULL
, wszBuffer
, MAX_PATH
);
1657 ok(!lstrcmpiW(wszDesktopPath
, wszBuffer
), "FolderShortcut returned incorrect folder!\n");
1659 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts,
1660 * but ShellFSFolders. */
1661 myPathAddBackslashW(wszDesktopPath
);
1662 lstrcatW(wszDesktopPath
, wszSomeSubFolder
);
1663 if (!CreateDirectoryW(wszDesktopPath
, NULL
)) {
1664 IShellFolder_Release(pShellFolder
);
1668 hr
= IShellFolder_ParseDisplayName(pShellFolder
, NULL
, NULL
, wszSomeSubFolder
, NULL
,
1669 &pidlSubFolder
, NULL
);
1670 RemoveDirectoryW(wszDesktopPath
);
1671 ok (hr
== S_OK
, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr
);
1673 IShellFolder_Release(pShellFolder
);
1677 hr
= IShellFolder_BindToObject(pShellFolder
, pidlSubFolder
, NULL
, &IID_IPersistFolder3
,
1678 (LPVOID
*)&pPersistFolder3
);
1679 IShellFolder_Release(pShellFolder
);
1680 pILFree(pidlSubFolder
);
1681 ok (hr
== S_OK
, "IShellFolder::BindToObject failed! hr = %08x\n", hr
);
1685 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
1686 * a little bit and also allow CLSID_UnixDosFolder. */
1687 hr
= IPersistFolder3_GetClassID(pPersistFolder3
, &clsid
);
1688 ok(hr
== S_OK
, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr
);
1689 ok(IsEqualCLSID(&clsid
, &CLSID_ShellFSFolder
) || IsEqualCLSID(&clsid
, &CLSID_UnixDosFolder
),
1690 "IPersistFolder3::GetClassID returned unexpected CLSID!\n");
1692 IPersistFolder3_Release(pPersistFolder3
);
1695 #include "pshpack1.h"
1696 struct FileStructA
{
1700 WORD uFileDate
; /* In our current implementation this is */
1701 WORD uFileTime
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */
1706 struct FileStructW
{
1707 WORD cbLen
; /* Length of this element. */
1708 BYTE abFooBar1
[6]; /* Beyond any recognition. */
1709 WORD uDate
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */
1710 WORD uTime
; /* (this is currently speculation) */
1711 WORD uDate2
; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */
1712 WORD uTime2
; /* (this is currently speculation) */
1713 BYTE abFooBar2
[4]; /* Beyond any recognition. */
1714 WCHAR wszName
[1]; /* The long filename in unicode. */
1715 /* Just for documentation: Right after the unicode string: */
1716 WORD cbOffset
; /* FileStructW's offset from the beginning of the SHITMEID.
1717 * SHITEMID->cb == uOffset + cbLen */
1719 #include "poppack.h"
1721 static void test_ITEMIDLIST_format(void) {
1722 WCHAR wszPersonal
[MAX_PATH
];
1723 LPSHELLFOLDER psfDesktop
, psfPersonal
;
1724 LPITEMIDLIST pidlPersonal
, pidlFile
;
1728 WCHAR wszFile
[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
1729 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
1732 if (!pSHGetSpecialFolderPathW
) return;
1734 bResult
= pSHGetSpecialFolderPathW(NULL
, wszPersonal
, CSIDL_PERSONAL
, FALSE
);
1735 ok(bResult
, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
1736 if (!bResult
) return;
1738 SetLastError(0xdeadbeef);
1739 bResult
= SetCurrentDirectoryW(wszPersonal
);
1740 if (!bResult
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1741 win_skip("Most W-calls are not implemented\n");
1744 ok(bResult
, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
1745 if (!bResult
) return;
1747 hr
= SHGetDesktopFolder(&psfDesktop
);
1748 ok(hr
== S_OK
, "SHGetDesktopFolder failed! hr: %08x\n", hr
);
1749 if (hr
!= S_OK
) return;
1751 hr
= IShellFolder_ParseDisplayName(psfDesktop
, NULL
, NULL
, wszPersonal
, NULL
, &pidlPersonal
, NULL
);
1752 ok(hr
== S_OK
, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr
);
1754 IShellFolder_Release(psfDesktop
);
1758 hr
= IShellFolder_BindToObject(psfDesktop
, pidlPersonal
, NULL
, &IID_IShellFolder
,
1759 (LPVOID
*)&psfPersonal
);
1760 IShellFolder_Release(psfDesktop
);
1761 pILFree(pidlPersonal
);
1762 ok(hr
== S_OK
, "psfDesktop->BindToObject failed! hr = %08x\n", hr
);
1763 if (hr
!= S_OK
) return;
1765 for (i
=0; i
<3; i
++) {
1766 CHAR szFile
[MAX_PATH
];
1767 struct FileStructA
*pFileStructA
;
1770 WideCharToMultiByte(CP_ACP
, 0, wszFile
[i
], -1, szFile
, MAX_PATH
, NULL
, NULL
);
1772 hFile
= CreateFileW(wszFile
[i
], GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_FLAG_WRITE_THROUGH
, NULL
);
1773 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed! (%u)\n", GetLastError());
1774 if (hFile
== INVALID_HANDLE_VALUE
) {
1775 IShellFolder_Release(psfPersonal
);
1780 hr
= IShellFolder_ParseDisplayName(psfPersonal
, NULL
, NULL
, wszFile
[i
], NULL
, &pidlFile
, NULL
);
1781 DeleteFileW(wszFile
[i
]);
1782 ok(hr
== S_OK
, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr
);
1784 IShellFolder_Release(psfPersonal
);
1788 pFileStructA
= (struct FileStructA
*)pidlFile
->mkid
.abID
;
1789 ok(pFileStructA
->type
== 0x32, "PIDLTYPE should be 0x32!\n");
1790 ok(pFileStructA
->dummy
== 0x00, "Dummy Byte should be 0x00!\n");
1791 ok(pFileStructA
->dwFileSize
== 0, "Filesize should be zero!\n");
1793 if (i
< 2) /* First two file names are already in valid 8.3 format */
1794 ok(!strcmp(szFile
, (CHAR
*)&pidlFile
->mkid
.abID
[12]), "Wrong file name!\n");
1796 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
1797 * can't implement this correctly, since unix filesystems don't support
1798 * this nasty short/long filename stuff. So we'll probably stay with our
1799 * current habit of storing the long filename here, which seems to work
1802 ok(pidlFile
->mkid
.abID
[18] == '~' ||
1803 broken(pidlFile
->mkid
.abID
[34] == '~'), /* Win2k */
1804 "Should be derived 8.3 name!\n");
1806 if (i
== 0) /* First file name has an even number of chars. No need for alignment. */
1807 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] != '\0' ||
1808 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1), /* Win2k */
1809 "Alignment byte, where there shouldn't be!\n");
1811 if (i
== 1) /* Second file name has an uneven number of chars => alignment byte */
1812 ok(pidlFile
->mkid
.abID
[12 + strlen(szFile
) + 1] == '\0',
1813 "There should be an alignment byte, but isn't!\n");
1815 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
1816 cbOffset
= *(WORD
*)(((LPBYTE
)pidlFile
)+pidlFile
->mkid
.cb
-sizeof(WORD
));
1817 ok ((cbOffset
>= sizeof(struct FileStructA
) &&
1818 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
)) ||
1819 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 1) || /* Win2k on short names */
1820 broken(pidlFile
->mkid
.cb
== 2 + 12 + strlen(szFile
) + 1 + 12 + 1), /* Win2k on long names */
1821 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset
);
1823 if (cbOffset
>= sizeof(struct FileStructA
) &&
1824 cbOffset
<= pidlFile
->mkid
.cb
- sizeof(struct FileStructW
))
1826 struct FileStructW
*pFileStructW
= (struct FileStructW
*)(((LPBYTE
)pidlFile
)+cbOffset
);
1827 WCHAR
*name
= pFileStructW
->wszName
;
1829 ok(pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
,
1830 "FileStructW's offset and length should add up to the PIDL's length!\n");
1832 if (pidlFile
->mkid
.cb
== cbOffset
+ pFileStructW
->cbLen
) {
1833 /* Since we just created the file, time of creation,
1834 * time of last access and time of last write access just be the same.
1835 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
1836 * after the first run. I do remember something with NTFS keeping the creation time
1837 * if a file is deleted and then created again within a couple of seconds or so.
1838 * Might be the reason. */
1839 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate
&&
1840 pFileStructA
->uFileTime
== pFileStructW
->uTime
,
1841 "Last write time should match creation time!\n");
1843 /* On FAT filesystems the last access time is midnight
1844 local time, so the values of uDate2 and uTime2 will
1845 depend on the local timezone. If the times are exactly
1846 equal then the dates should be identical for both FAT
1847 and NTFS as no timezone is more than 1 day away from UTC.
1849 if (pFileStructA
->uFileTime
== pFileStructW
->uTime2
)
1851 ok (pFileStructA
->uFileDate
== pFileStructW
->uDate2
,
1852 "Last write date and time should match last access date and time!\n");
1856 /* Filesystem may be FAT. Check date within 1 day
1857 and seconds are zero. */
1858 trace ("Filesystem may be FAT. Performing less strict atime test.\n");
1859 ok ((pFileStructW
->uTime2
& 0x1F) == 0,
1860 "Last access time on FAT filesystems should have zero seconds.\n");
1861 /* TODO: Perform check for date being within one day.*/
1864 ok (!lstrcmpW(wszFile
[i
], name
) ||
1865 !lstrcmpW(wszFile
[i
], name
+ 9) || /* Vista */
1866 !lstrcmpW(wszFile
[i
], name
+ 11), /* Win7 */
1867 "The filename should be stored in unicode at this position!\n");
1874 IShellFolder_Release(psfPersonal
);
1877 static void test_SHGetFolderPathA(void)
1879 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
1881 char path
[MAX_PATH
];
1882 char path_x86
[MAX_PATH
];
1883 char path_key
[MAX_PATH
];
1887 if (!pSHGetFolderPathA
)
1889 win_skip("SHGetFolderPathA not present\n");
1892 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
1894 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES
, 0, SHGFP_TYPE_CURRENT
, path
);
1895 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1896 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1899 win_skip( "Program Files (x86) not supported\n" );
1902 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1905 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1906 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1907 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1911 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1913 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1915 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1917 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1919 DWORD type
, count
= sizeof(path_x86
);
1920 if (!RegQueryValueExA( key
, "ProgramFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1922 ok( is_win64
|| is_wow64
, "ProgramFilesDir (x86) exists on 32-bit setup\n" );
1923 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1925 else ok( !is_win64
&& !is_wow64
, "ProgramFilesDir (x86) should exist on 64-bit setup\n" );
1929 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON
, 0, SHGFP_TYPE_CURRENT
, path
);
1930 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1931 hr
= pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86
, 0, SHGFP_TYPE_CURRENT
, path_x86
);
1934 win_skip( "Common Files (x86) not supported\n" );
1937 ok( !hr
, "SHGetFolderPathA failed %x\n", hr
);
1940 ok( lstrcmpiA( path
, path_x86
), "paths are identical '%s'\n", path
);
1941 ok( strstr( path
, "x86" ) == NULL
, "64-bit path '%s' contains x86\n", path
);
1942 ok( strstr( path_x86
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path_x86
);
1946 ok( !lstrcmpiA( path
, path_x86
), "paths differ '%s' != '%s'\n", path
, path_x86
);
1948 ok( strstr( path
, "x86" ) != NULL
, "32-bit path '%s' doesn't contain x86\n", path
);
1950 ok( strstr( path
, "x86" ) == NULL
, "32-bit path '%s' contains x86\n", path
);
1952 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion", &key
))
1954 DWORD type
, count
= sizeof(path_x86
);
1955 if (!RegQueryValueExA( key
, "CommonFilesDir (x86)", NULL
, &type
, (BYTE
*)path_key
, &count
))
1957 ok( is_win64
|| is_wow64
, "CommonFilesDir (x86) exists on 32-bit setup\n" );
1958 ok( !lstrcmpiA( path_key
, path_x86
), "paths differ '%s' != '%s'\n", path_key
, path_x86
);
1960 else ok( !is_win64
&& !is_wow64
, "CommonFilesDir (x86) should exist on 64-bit setup\n" );
1964 static void test_SHGetFolderPathAndSubDirA(void)
1970 static char wine
[] = "wine";
1971 static char winetemp
[] = "wine\\temp";
1972 static char appdata
[MAX_PATH
];
1973 static char testpath
[MAX_PATH
];
1974 static char toolongpath
[MAX_PATH
+1];
1976 if(!pSHGetFolderPathAndSubDirA
)
1978 win_skip("SHGetFolderPathAndSubDirA not present!\n");
1982 if(!pSHGetFolderPathA
) {
1983 win_skip("SHGetFolderPathA not present!\n");
1986 if(FAILED(pSHGetFolderPathA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdata
)))
1988 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
1992 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
1993 delret
= RemoveDirectoryA(testpath
);
1994 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) ) {
1995 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
1999 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2000 delret
= RemoveDirectoryA(testpath
);
2001 if(!delret
&& (ERROR_PATH_NOT_FOUND
!= GetLastError()) && (ERROR_FILE_NOT_FOUND
!= GetLastError())) {
2002 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath
, GetLastError());
2006 /* test invalid second parameter */
2007 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| 0xff, NULL
, SHGFP_TYPE_CURRENT
, wine
, testpath
);
2008 ok(E_INVALIDARG
== ret
, "expected E_INVALIDARG, got %x\n", ret
);
2010 /* test fourth parameter */
2011 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, 2, winetemp
, testpath
);
2013 case S_OK
: /* winvista */
2014 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2015 "expected %s to start with %s\n", testpath
, appdata
);
2016 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2017 "expected %s to end with %s\n", testpath
, winetemp
);
2019 case E_INVALIDARG
: /* winxp, win2k3 */
2022 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2025 /* test fifth parameter */
2027 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, NULL
, 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
);
2037 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, "\\", testpath
);
2038 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2039 ok(!lstrcmpA(appdata
, testpath
), "expected %s, got %s\n", appdata
, testpath
);
2041 for(i
=0; i
< MAX_PATH
; i
++)
2042 toolongpath
[i
] = '0' + i
% 10;
2043 toolongpath
[MAX_PATH
] = '\0';
2044 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, toolongpath
, testpath
);
2045 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
) == ret
,
2046 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), ret
);
2049 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_DONT_VERIFY
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, wine
, NULL
);
2050 ok((S_OK
== ret
) || (E_INVALIDARG
== ret
), "expected S_OK or E_INVALIDARG, got %x\n", ret
);
2052 /* test a not existing path */
2054 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2055 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) == ret
,
2056 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), ret
);
2058 /* create a directory inside a not existing directory */
2060 ret
= pSHGetFolderPathAndSubDirA(NULL
, CSIDL_FLAG_CREATE
| CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, winetemp
, testpath
);
2061 ok(S_OK
== ret
, "expected S_OK, got %x\n", ret
);
2062 ok(!strncmp(appdata
, testpath
, strlen(appdata
)),
2063 "expected %s to start with %s\n", testpath
, appdata
);
2064 ok(!lstrcmpA(&testpath
[1 + strlen(appdata
)], winetemp
),
2065 "expected %s to end with %s\n", testpath
, winetemp
);
2066 dwret
= GetFileAttributes(testpath
);
2067 ok(FILE_ATTRIBUTE_DIRECTORY
| dwret
, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret
);
2070 sprintf(testpath
, "%s\\%s", appdata
, winetemp
);
2071 RemoveDirectoryA(testpath
);
2072 sprintf(testpath
, "%s\\%s", appdata
, wine
);
2073 RemoveDirectoryA(testpath
);
2076 static void test_LocalizedNames(void)
2078 static char cCurrDirA
[MAX_PATH
];
2079 WCHAR cCurrDirW
[MAX_PATH
], tempbufW
[25];
2080 IShellFolder
*IDesktopFolder
, *testIShellFolder
;
2081 ITEMIDLIST
*newPIDL
;
2084 static char resourcefile
[MAX_PATH
];
2090 static const char desktopini_contents1
[] =
2091 "[.ShellClassInfo]\r\n"
2092 "LocalizedResourceName=@";
2093 static const char desktopini_contents2
[] =
2095 static WCHAR foldernameW
[] = {'t','e','s','t','f','o','l','d','e','r',0};
2096 static const WCHAR folderdisplayW
[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
2098 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
2099 CreateDirectoryA(".\\testfolder", NULL
);
2101 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM
);
2103 GetModuleFileNameA(NULL
, resourcefile
, MAX_PATH
);
2105 file
= CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE
, 0, NULL
,
2106 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2107 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed %i\n", GetLastError());
2108 ret
= WriteFile(file
, desktopini_contents1
, strlen(desktopini_contents1
), &res
, NULL
) &&
2109 WriteFile(file
, resourcefile
, strlen(resourcefile
), &res
, NULL
) &&
2110 WriteFile(file
, desktopini_contents2
, strlen(desktopini_contents2
), &res
, NULL
);
2111 ok(ret
, "WriteFile failed %i\n", GetLastError());
2114 /* get IShellFolder for parent */
2115 GetCurrentDirectoryA(MAX_PATH
, cCurrDirA
);
2116 len
= lstrlenA(cCurrDirA
);
2119 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
2122 if(cCurrDirA
[len
-1] == '\\')
2123 cCurrDirA
[len
-1] = 0;
2125 MultiByteToWideChar(CP_ACP
, 0, cCurrDirA
, -1, cCurrDirW
, MAX_PATH
);
2127 hr
= SHGetDesktopFolder(&IDesktopFolder
);
2128 ok(hr
== S_OK
, "SHGetDesktopfolder failed %08x\n", hr
);
2130 hr
= IShellFolder_ParseDisplayName(IDesktopFolder
, NULL
, NULL
, cCurrDirW
, NULL
, &newPIDL
, 0);
2131 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2133 hr
= IShellFolder_BindToObject(IDesktopFolder
, newPIDL
, NULL
, (REFIID
)&IID_IShellFolder
, (LPVOID
*)&testIShellFolder
);
2134 ok(hr
== S_OK
, "BindToObject failed %08x\n", hr
);
2136 IMalloc_Free(ppM
, newPIDL
);
2138 /* windows reads the display name from the resource */
2139 hr
= IShellFolder_ParseDisplayName(testIShellFolder
, NULL
, NULL
, foldernameW
, NULL
, &newPIDL
, 0);
2140 ok(hr
== S_OK
, "ParseDisplayName failed %08x\n", hr
);
2142 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
, &strret
);
2143 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2145 if (hr
== S_OK
&& pStrRetToBufW
)
2147 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2148 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2150 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2151 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2152 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2155 /* editing name is also read from the resource */
2156 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FOREDITING
, &strret
);
2157 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2159 if (hr
== S_OK
&& pStrRetToBufW
)
2161 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2162 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2164 ok (!lstrcmpiW(tempbufW
, folderdisplayW
) ||
2165 broken(!lstrcmpiW(tempbufW
, foldernameW
)), /* W2K */
2166 "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2169 /* parsing name is unchanged */
2170 hr
= IShellFolder_GetDisplayNameOf(testIShellFolder
, newPIDL
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, &strret
);
2171 ok(hr
== S_OK
, "GetDisplayNameOf failed %08x\n", hr
);
2173 if (hr
== S_OK
&& pStrRetToBufW
)
2175 hr
= pStrRetToBufW(&strret
, newPIDL
, tempbufW
, sizeof(tempbufW
)/sizeof(WCHAR
));
2176 ok (hr
== S_OK
, "StrRetToBufW failed! hr = %08x\n", hr
);
2177 ok (!lstrcmpiW(tempbufW
, foldernameW
), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW
));
2180 IShellFolder_Release(IDesktopFolder
);
2181 IShellFolder_Release(testIShellFolder
);
2183 IMalloc_Free(ppM
, newPIDL
);
2186 DeleteFileA(".\\testfolder\\desktop.ini");
2187 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM
);
2188 RemoveDirectoryA(".\\testfolder");
2191 static void test_SHCreateShellItem(void)
2193 IShellItem
*shellitem
, *shellitem2
;
2194 IPersistIDList
*persistidl
;
2195 LPITEMIDLIST pidl_cwd
=NULL
, pidl_testfile
, pidl_abstestfile
, pidl_test
, pidl_desktop
;
2197 char curdirA
[MAX_PATH
];
2198 WCHAR curdirW
[MAX_PATH
];
2199 WCHAR fnbufW
[MAX_PATH
];
2200 IShellFolder
*desktopfolder
=NULL
, *currentfolder
=NULL
;
2201 static WCHAR testfileW
[] = {'t','e','s','t','f','i','l','e',0};
2203 GetCurrentDirectoryA(MAX_PATH
, curdirA
);
2205 if (!pSHCreateShellItem
)
2207 win_skip("SHCreateShellItem isn't available\n");
2211 if (!lstrlenA(curdirA
))
2213 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
2217 if(pSHGetSpecialFolderLocation
)
2219 ret
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
2220 ok(ret
== S_OK
, "Got 0x%08x\n", ret
);
2224 win_skip("pSHGetSpecialFolderLocation missing.\n");
2225 pidl_desktop
= NULL
;
2228 MultiByteToWideChar(CP_ACP
, 0, curdirA
, -1, curdirW
, MAX_PATH
);
2230 ret
= SHGetDesktopFolder(&desktopfolder
);
2231 ok(SUCCEEDED(ret
), "SHGetShellFolder returned %x\n", ret
);
2233 ret
= IShellFolder_ParseDisplayName(desktopfolder
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2234 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2236 ret
= IShellFolder_BindToObject(desktopfolder
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)¤tfolder
);
2237 ok(SUCCEEDED(ret
), "BindToObject returned %x\n", ret
);
2239 CreateTestFile(".\\testfile");
2241 ret
= IShellFolder_ParseDisplayName(currentfolder
, NULL
, NULL
, testfileW
, NULL
, &pidl_testfile
, NULL
);
2242 ok(SUCCEEDED(ret
), "ParseDisplayName returned %x\n", ret
);
2244 pidl_abstestfile
= pILCombine(pidl_cwd
, pidl_testfile
);
2246 ret
= pSHCreateShellItem(NULL
, NULL
, NULL
, &shellitem
);
2247 ok(ret
== E_INVALIDARG
, "SHCreateShellItem returned %x\n", ret
);
2249 if (0) /* crashes on Windows XP */
2251 pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, NULL
);
2252 pSHCreateShellItem(pidl_cwd
, NULL
, NULL
, &shellitem
);
2253 pSHCreateShellItem(NULL
, currentfolder
, NULL
, &shellitem
);
2254 pSHCreateShellItem(pidl_cwd
, currentfolder
, NULL
, &shellitem
);
2257 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_cwd
, &shellitem
);
2258 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2261 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2262 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2265 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2266 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2269 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2272 IPersistIDList_Release(persistidl
);
2274 IShellItem_Release(shellitem
);
2277 ret
= pSHCreateShellItem(pidl_cwd
, NULL
, pidl_testfile
, &shellitem
);
2278 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2281 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2282 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2285 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2286 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2289 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2292 IPersistIDList_Release(persistidl
);
2295 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2296 ok(SUCCEEDED(ret
), "GetParent returned %x\n", ret
);
2299 ret
= IShellItem_QueryInterface(shellitem2
, &IID_IPersistIDList
, (void**)&persistidl
);
2300 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2303 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2304 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2307 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2310 IPersistIDList_Release(persistidl
);
2312 IShellItem_Release(shellitem2
);
2315 IShellItem_Release(shellitem
);
2318 ret
= pSHCreateShellItem(NULL
, currentfolder
, pidl_testfile
, &shellitem
);
2319 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2322 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2323 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2326 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2327 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2330 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2333 IPersistIDList_Release(persistidl
);
2335 IShellItem_Release(shellitem
);
2338 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */
2339 ret
= pSHCreateShellItem(pidl_cwd
, desktopfolder
, pidl_testfile
, &shellitem
);
2340 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2343 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2344 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2347 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2348 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2351 ok(ILIsEqual(pidl_abstestfile
, pidl_test
), "id lists are not equal\n");
2354 IPersistIDList_Release(persistidl
);
2356 IShellItem_Release(shellitem
);
2359 ret
= pSHCreateShellItem(NULL
, desktopfolder
, pidl_testfile
, &shellitem
);
2360 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2363 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2364 ok(SUCCEEDED(ret
), "QueryInterface returned %x\n", ret
);
2367 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2368 ok(SUCCEEDED(ret
), "GetIDList returned %x\n", ret
);
2371 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2374 IPersistIDList_Release(persistidl
);
2377 IShellItem_Release(shellitem
);
2380 ret
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
2381 ok(SUCCEEDED(ret
), "SHCreateShellItem returned %x\n", ret
);
2384 ret
= IShellItem_GetParent(shellitem
, &shellitem2
);
2385 ok(FAILED(ret
), "Got 0x%08x\n", ret
);
2386 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem2
);
2387 IShellItem_Release(shellitem
);
2390 /* SHCreateItemFromParsingName */
2391 if(pSHCreateItemFromParsingName
)
2395 /* Crashes under windows 7 */
2396 pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, NULL
);
2399 shellitem
= (void*)0xdeadbeef;
2400 ret
= pSHCreateItemFromParsingName(NULL
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2401 ok(ret
== E_INVALIDARG
, "SHCreateItemFromParsingName returned %x\n", ret
);
2402 ok(shellitem
== NULL
, "shellitem was %p.\n", shellitem
);
2404 ret
= pSHCreateItemFromParsingName(testfileW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2405 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
2406 "SHCreateItemFromParsingName returned %x\n", ret
);
2407 if(SUCCEEDED(ret
)) IShellItem_Release(shellitem
);
2409 lstrcpyW(fnbufW
, curdirW
);
2410 myPathAddBackslashW(fnbufW
);
2411 lstrcatW(fnbufW
, testfileW
);
2413 ret
= pSHCreateItemFromParsingName(fnbufW
, NULL
, &IID_IShellItem
, (void**)&shellitem
);
2414 ok(ret
== S_OK
, "SHCreateItemFromParsingName returned %x\n", ret
);
2418 ret
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &tmp_fname
);
2419 ok(ret
== S_OK
, "GetDisplayName returned %x\n", ret
);
2422 ok(!lstrcmpW(fnbufW
, tmp_fname
), "strings not equal\n");
2423 CoTaskMemFree(tmp_fname
);
2425 IShellItem_Release(shellitem
);
2429 win_skip("No SHCreateItemFromParsingName\n");
2432 /* SHCreateItemFromIDList */
2433 if(pSHCreateItemFromIDList
)
2437 /* Crashes under win7 */
2438 pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, NULL
);
2441 ret
= pSHCreateItemFromIDList(NULL
, &IID_IShellItem
, (void**)&shellitem
);
2442 ok(ret
== E_INVALIDARG
, "SHCreateItemFromIDList returned %x\n", ret
);
2444 ret
= pSHCreateItemFromIDList(pidl_cwd
, &IID_IShellItem
, (void**)&shellitem
);
2445 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2448 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2449 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2452 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2453 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2456 ok(ILIsEqual(pidl_cwd
, pidl_test
), "id lists are not equal\n");
2459 IPersistIDList_Release(persistidl
);
2461 IShellItem_Release(shellitem
);
2464 ret
= pSHCreateItemFromIDList(pidl_testfile
, &IID_IShellItem
, (void**)&shellitem
);
2465 ok(ret
== S_OK
, "SHCreateItemFromIDList returned %x\n", ret
);
2468 ret
= IShellItem_QueryInterface(shellitem
, &IID_IPersistIDList
, (void**)&persistidl
);
2469 ok(ret
== S_OK
, "QueryInterface returned %x\n", ret
);
2472 ret
= IPersistIDList_GetIDList(persistidl
, &pidl_test
);
2473 ok(ret
== S_OK
, "GetIDList returned %x\n", ret
);
2476 ok(ILIsEqual(pidl_testfile
, pidl_test
), "id lists are not equal\n");
2479 IPersistIDList_Release(persistidl
);
2481 IShellItem_Release(shellitem
);
2485 win_skip("No SHCreateItemFromIDList\n");
2487 DeleteFileA(".\\testfile");
2488 pILFree(pidl_abstestfile
);
2489 pILFree(pidl_testfile
);
2490 pILFree(pidl_desktop
);
2492 IShellFolder_Release(currentfolder
);
2493 IShellFolder_Release(desktopfolder
);
2496 static void test_SHGetNameFromIDList(void)
2498 IShellItem
*shellitem
;
2503 static const DWORD flags
[] = {
2504 SIGDN_NORMALDISPLAY
, SIGDN_PARENTRELATIVEPARSING
,
2505 SIGDN_DESKTOPABSOLUTEPARSING
,SIGDN_PARENTRELATIVEEDITING
,
2506 SIGDN_DESKTOPABSOLUTEEDITING
, /*SIGDN_FILESYSPATH, SIGDN_URL, */
2507 SIGDN_PARENTRELATIVEFORADDRESSBAR
,SIGDN_PARENTRELATIVE
, -1234};
2509 if(!pSHGetNameFromIDList
)
2511 win_skip("SHGetNameFromIDList missing.\n");
2515 /* These should be available on any platform that passed the above test. */
2516 ok(pSHCreateShellItem
!= NULL
, "SHCreateShellItem missing.\n");
2517 ok(pSHBindToParent
!= NULL
, "SHBindToParent missing.\n");
2518 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
2519 ok(pStrRetToBufW
!= NULL
, "StrRetToBufW missing.\n");
2523 /* Crashes under win7 */
2524 pSHGetNameFromIDList(NULL
, 0, NULL
);
2527 hres
= pSHGetNameFromIDList(NULL
, 0, &name_string
);
2528 ok(hres
== E_INVALIDARG
, "Got 0x%08x\n", hres
);
2530 /* Test the desktop */
2531 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
2532 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2533 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2534 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2537 WCHAR
*nameSI
, *nameSH
;
2538 WCHAR buf
[MAX_PATH
];
2539 HRESULT hrSI
, hrSH
, hrSF
;
2544 SHGetDesktopFolder(&psf
);
2545 for(i
= 0; flags
[i
] != -1234; i
++)
2547 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2548 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2549 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2550 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2551 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2552 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2554 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2555 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2559 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2561 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2563 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2565 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2566 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2568 IShellFolder_Release(psf
);
2570 if(pSHGetPathFromIDListW
){
2571 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2572 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2573 res
= pSHGetPathFromIDListW(pidl
, buf
);
2574 ok(res
== TRUE
, "Got %d\n", res
);
2575 if(SUCCEEDED(hrSI
) && res
)
2576 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2577 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2579 win_skip("pSHGetPathFromIDListW not available\n");
2581 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2582 todo_wine
ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2583 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2585 IShellItem_Release(shellitem
);
2589 /* Test the control panel */
2590 hres
= pSHGetSpecialFolderLocation(NULL
, CSIDL_CONTROLS
, &pidl
);
2591 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2592 hres
= pSHCreateShellItem(NULL
, NULL
, pidl
, &shellitem
);
2593 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
2596 WCHAR
*nameSI
, *nameSH
;
2597 WCHAR buf
[MAX_PATH
];
2598 HRESULT hrSI
, hrSH
, hrSF
;
2603 SHGetDesktopFolder(&psf
);
2604 for(i
= 0; flags
[i
] != -1234; i
++)
2606 hrSI
= IShellItem_GetDisplayName(shellitem
, flags
[i
], &nameSI
);
2607 ok(hrSI
== S_OK
, "Got 0x%08x\n", hrSI
);
2608 hrSH
= pSHGetNameFromIDList(pidl
, flags
[i
], &nameSH
);
2609 ok(hrSH
== S_OK
, "Got 0x%08x\n", hrSH
);
2610 hrSF
= IShellFolder_GetDisplayNameOf(psf
, pidl
, flags
[i
] & 0xffff, &strret
);
2611 ok(hrSF
== S_OK
, "Got 0x%08x\n", hrSF
);
2613 if(SUCCEEDED(hrSI
) && SUCCEEDED(hrSH
))
2614 ok(!lstrcmpW(nameSI
, nameSH
), "Strings differ.\n");
2618 pStrRetToBufW(&strret
, NULL
, buf
, MAX_PATH
);
2620 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2622 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2624 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2625 if(SUCCEEDED(hrSH
)) CoTaskMemFree(nameSH
);
2627 IShellFolder_Release(psf
);
2629 if(pSHGetPathFromIDListW
){
2630 hrSI
= pSHGetNameFromIDList(pidl
, SIGDN_FILESYSPATH
, &nameSI
);
2631 ok(hrSI
== E_INVALIDARG
, "Got 0x%08x\n", hrSI
);
2632 res
= pSHGetPathFromIDListW(pidl
, buf
);
2633 ok(res
== FALSE
, "Got %d\n", res
);
2634 if(SUCCEEDED(hrSI
) && res
)
2635 ok(!lstrcmpW(nameSI
, buf
), "Strings differ.\n");
2636 if(SUCCEEDED(hrSI
)) CoTaskMemFree(nameSI
);
2638 win_skip("pSHGetPathFromIDListW not available\n");
2640 hres
= pSHGetNameFromIDList(pidl
, SIGDN_URL
, &name_string
);
2641 todo_wine
ok(hres
== E_NOTIMPL
/* Win7 */ || hres
== S_OK
/* Vista */,
2642 "Got 0x%08x\n", hres
);
2643 if(SUCCEEDED(hres
)) CoTaskMemFree(name_string
);
2645 IShellItem_Release(shellitem
);
2650 static void test_SHGetItemFromDataObject(void)
2652 IShellFolder
*psfdesktop
;
2657 if(!pSHGetItemFromDataObject
)
2659 win_skip("No SHGetItemFromDataObject.\n");
2665 /* Crashes under win7 */
2666 pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, NULL
);
2669 hres
= pSHGetItemFromDataObject(NULL
, 0, &IID_IShellItem
, (void**)&psv
);
2670 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
2672 SHGetDesktopFolder(&psfdesktop
);
2674 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
2675 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2682 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
2683 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
2684 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2687 LPITEMIDLIST apidl
[5];
2690 for(count
= 0; count
< 5; count
++)
2691 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
2696 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
2697 &IID_IDataObject
, NULL
, (void**)&pdo
);
2698 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2701 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &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_TRAVERSE_LINK
, &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_HDROP
, &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_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2711 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2712 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2713 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2714 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2715 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2717 IDataObject_Release(pdo
);
2721 skip("No file(s) found - skipping single-file test.\n");
2725 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
2726 &IID_IDataObject
, NULL
, (void**)&pdo
);
2727 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2730 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_DEFAULT
, &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_TRAVERSE_LINK
, &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_HDROP
, &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_NO_URL
, &IID_IShellItem
, (void**)&psi
);
2740 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2741 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2742 hres
= pSHGetItemFromDataObject(pdo
, DOGIF_ONLY_IF_ONE
, &IID_IShellItem
, (void**)&psi
);
2743 ok(hres
== E_FAIL
, "got 0x%08x\n", hres
);
2744 if(SUCCEEDED(hres
)) IShellItem_Release(psi
);
2745 IDataObject_Release(pdo
);
2749 skip("zero or one file found - skipping multi-file test.\n");
2751 for(i
= 0; i
< count
; i
++)
2754 IEnumIDList_Release(peidl
);
2757 IShellView_Release(psv
);
2760 IShellFolder_Release(psfdesktop
);
2763 static void test_ShellItemCompare(void)
2765 IShellItem
*psi
[9]; /* a\a, a\b, a\c, b\a, .. */
2766 IShellItem
*psi_a
= NULL
, *psi_b
= NULL
, *psi_c
= NULL
;
2767 IShellFolder
*psf_desktop
, *psf_current
;
2768 LPITEMIDLIST pidl_cwd
;
2769 WCHAR curdirW
[MAX_PATH
];
2772 static const WCHAR filesW
[][9] = {
2773 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0},
2774 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0},
2775 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} };
2779 if(!pSHCreateShellItem
)
2781 win_skip("SHCreateShellItem missing.\n");
2785 GetCurrentDirectoryW(MAX_PATH
, curdirW
);
2786 if(!lstrlenW(curdirW
))
2788 skip("Failed to get current directory, skipping.\n");
2792 CreateDirectoryA(".\\a", NULL
);
2793 CreateDirectoryA(".\\b", NULL
);
2794 CreateDirectoryA(".\\c", NULL
);
2795 CreateTestFile(".\\a\\a");
2796 CreateTestFile(".\\a\\b");
2797 CreateTestFile(".\\a\\c");
2798 CreateTestFile(".\\b\\a");
2799 CreateTestFile(".\\b\\b");
2800 CreateTestFile(".\\b\\c");
2801 CreateTestFile(".\\c\\a");
2802 CreateTestFile(".\\c\\b");
2803 CreateTestFile(".\\c\\c");
2805 SHGetDesktopFolder(&psf_desktop
);
2806 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, curdirW
, NULL
, &pidl_cwd
, NULL
);
2807 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2808 hr
= IShellFolder_BindToObject(psf_desktop
, pidl_cwd
, NULL
, &IID_IShellFolder
, (void**)&psf_current
);
2809 ok(SUCCEEDED(hr
), "BindToObject returned %x\n", hr
);
2810 IShellFolder_Release(psf_desktop
);
2813 /* Generate ShellItems for the files */
2814 memset(&psi
, 0, sizeof(psi
));
2816 for(i
= 0; i
< 9; i
++)
2818 LPITEMIDLIST pidl_testfile
= NULL
;
2820 hr
= IShellFolder_ParseDisplayName(psf_current
, NULL
, NULL
, (LPWSTR
)filesW
[i
],
2821 NULL
, &pidl_testfile
, NULL
);
2822 ok(SUCCEEDED(hr
), "ParseDisplayName returned %x\n", hr
);
2825 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_testfile
, &psi
[i
]);
2826 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2827 pILFree(pidl_testfile
);
2829 if(FAILED(hr
)) failed
= TRUE
;
2833 skip("Failed to create all shellitems.\n");
2837 /* Generate ShellItems for the folders */
2838 hr
= IShellItem_GetParent(psi
[0], &psi_a
);
2839 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2840 if(FAILED(hr
)) failed
= TRUE
;
2841 hr
= IShellItem_GetParent(psi
[3], &psi_b
);
2842 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2843 if(FAILED(hr
)) failed
= TRUE
;
2844 hr
= IShellItem_GetParent(psi
[6], &psi_c
);
2845 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2846 if(FAILED(hr
)) failed
= TRUE
;
2850 skip("Failed to create shellitems.\n");
2856 /* Crashes on native (win7, winxp) */
2857 IShellItem_Compare(psi_a
, NULL
, 0, NULL
);
2858 IShellItem_Compare(psi_a
, psi_b
, 0, NULL
);
2859 IShellItem_Compare(psi_a
, NULL
, 0, &order
);
2863 for(i
= 0; i
< 9; i
++)
2865 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_DISPLAY
, &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_CANONICAL
, &order
);
2869 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2870 ok(order
== 0, "Got order %d\n", order
);
2871 hr
= IShellItem_Compare(psi
[i
], psi
[i
], SICHINT_ALLFIELDS
, &order
);
2872 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2873 ok(order
== 0, "Got order %d\n", order
);
2877 /* a\b:a\a , a\b:a\c, a\b:a\b */
2878 hr
= IShellItem_Compare(psi
[1], psi
[0], 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
[2], SICHINT_DISPLAY
, &order
);
2882 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2883 ok(order
== -1, "Got order %d\n", order
);
2884 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_DISPLAY
, &order
);
2885 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2886 ok(order
== 0, "Got order %d\n", order
);
2888 /* b\b:a\b, b\b:c\b, b\b:c\b */
2889 hr
= IShellItem_Compare(psi
[4], psi
[1], 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
[7], SICHINT_DISPLAY
, &order
);
2893 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2894 ok(order
== -1, "Got order %d\n", order
);
2895 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_DISPLAY
, &order
);
2896 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2897 ok(order
== 0, "Got order %d\n", order
);
2899 /* b:a\a, b:a\c, b:a\b */
2900 hr
= IShellItem_Compare(psi_b
, psi
[0], 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
[2], SICHINT_DISPLAY
, &order
);
2904 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2905 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2906 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_DISPLAY
, &order
);
2907 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2908 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2910 /* b:c\a, b:c\c, b:c\b */
2911 hr
= IShellItem_Compare(psi_b
, psi
[6], 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
[8], SICHINT_DISPLAY
, &order
);
2915 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2916 ok(order
== -1, "Got order %d\n", order
);
2917 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_DISPLAY
, &order
);
2918 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2919 ok(order
== -1, "Got order %d\n", order
);
2921 /* a\b:a\a , a\b:a\c, a\b:a\b */
2922 hr
= IShellItem_Compare(psi
[1], psi
[0], 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
[2], SICHINT_CANONICAL
, &order
);
2926 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2927 ok(order
== -1, "Got order %d\n", order
);
2928 hr
= IShellItem_Compare(psi
[1], psi
[1], SICHINT_CANONICAL
, &order
);
2929 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2930 ok(order
== 0, "Got order %d\n", order
);
2932 /* b\b:a\b, b\b:c\b, b\b:c\b */
2933 hr
= IShellItem_Compare(psi
[4], psi
[1], 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
[7], SICHINT_CANONICAL
, &order
);
2937 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2938 ok(order
== -1, "Got order %d\n", order
);
2939 hr
= IShellItem_Compare(psi
[4], psi
[4], SICHINT_CANONICAL
, &order
);
2940 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2941 ok(order
== 0, "Got order %d\n", order
);
2943 /* b:a\a, b:a\c, b:a\b */
2944 hr
= IShellItem_Compare(psi_b
, psi
[0], 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
[2], SICHINT_CANONICAL
, &order
);
2948 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2949 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2950 hr
= IShellItem_Compare(psi_b
, psi
[1], SICHINT_CANONICAL
, &order
);
2951 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2952 todo_wine
ok(order
== 1, "Got order %d\n", order
);
2954 /* b:c\a, b:c\c, b:c\b */
2955 hr
= IShellItem_Compare(psi_b
, psi
[6], 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
[8], SICHINT_CANONICAL
, &order
);
2959 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2960 ok(order
== -1, "Got order %d\n", order
);
2961 hr
= IShellItem_Compare(psi_b
, psi
[7], SICHINT_CANONICAL
, &order
);
2962 ok(hr
== S_FALSE
, "Got 0x%08x\n", hr
);
2963 ok(order
== -1, "Got order %d\n", order
);
2966 IShellFolder_Release(psf_current
);
2968 DeleteFileA(".\\a\\a");
2969 DeleteFileA(".\\a\\b");
2970 DeleteFileA(".\\a\\c");
2971 DeleteFileA(".\\b\\a");
2972 DeleteFileA(".\\b\\b");
2973 DeleteFileA(".\\b\\c");
2974 DeleteFileA(".\\c\\a");
2975 DeleteFileA(".\\c\\b");
2976 DeleteFileA(".\\c\\c");
2977 RemoveDirectoryA(".\\a");
2978 RemoveDirectoryA(".\\b");
2979 RemoveDirectoryA(".\\c");
2981 if(psi_a
) IShellItem_Release(psi_a
);
2982 if(psi_b
) IShellItem_Release(psi_b
);
2983 if(psi_c
) IShellItem_Release(psi_c
);
2985 for(i
= 0; i
< 9; i
++)
2986 if(psi
[i
]) IShellItem_Release(psi
[i
]);
2989 /**************************************************************/
2990 /* IUnknown implementation for counting QueryInterface calls. */
2992 IUnknown IUnknown_iface
;
3000 static inline IUnknownImpl
*impl_from_IUnknown(IUnknown
*iface
)
3002 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
3005 static HRESULT WINAPI
unk_fnQueryInterface(IUnknown
*iunk
, REFIID riid
, void** punk
)
3007 IUnknownImpl
*This
= impl_from_IUnknown(iunk
);
3009 for(i
= found
= 0; This
->ifaces
[i
].id
!= NULL
; i
++)
3011 if(IsEqualIID(This
->ifaces
[i
].id
, riid
))
3013 This
->ifaces
[i
].count
++;
3020 return E_NOINTERFACE
;
3023 static ULONG WINAPI
unk_fnAddRef(IUnknown
*iunk
)
3028 static ULONG WINAPI
unk_fnRelease(IUnknown
*iunk
)
3033 static const IUnknownVtbl vt_IUnknown
= {
3034 unk_fnQueryInterface
,
3039 static void test_SHGetIDListFromObject(void)
3041 IUnknownImpl
*punkimpl
;
3042 IShellFolder
*psfdesktop
;
3044 LPITEMIDLIST pidl
, pidl_desktop
;
3047 struct if_count ifaces
[] =
3048 { {&IID_IPersistIDList
, 0},
3049 {&IID_IPersistFolder2
, 0},
3050 {&IID_IDataObject
, 0},
3051 {&IID_IParentAndItem
, 0},
3052 {&IID_IFolderView
, 0},
3055 if(!pSHGetIDListFromObject
)
3057 win_skip("SHGetIDListFromObject missing.\n");
3061 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3065 /* Crashes native */
3066 pSHGetIDListFromObject(NULL
, NULL
);
3067 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL
);
3070 hres
= pSHGetIDListFromObject(NULL
, &pidl
);
3071 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3073 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3074 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3075 punkimpl
->ifaces
= ifaces
;
3076 punkimpl
->unknown
= 0;
3078 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3079 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3080 ok(ifaces
[0].count
, "interface not requested.\n");
3081 ok(ifaces
[1].count
, "interface not requested.\n");
3082 ok(ifaces
[2].count
, "interface not requested.\n");
3084 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3085 "interface not requested.\n");
3086 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3087 "interface not requested.\n");
3089 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3090 HeapFree(GetProcessHeap(), 0, punkimpl
);
3092 pidl_desktop
= NULL
;
3093 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3094 ok(pidl_desktop
!= NULL
, "Failed to get desktop pidl.\n");
3096 SHGetDesktopFolder(&psfdesktop
);
3098 /* Test IShellItem */
3099 if(pSHCreateShellItem
)
3101 IShellItem
*shellitem
;
3102 hres
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &shellitem
);
3103 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3106 hres
= pSHGetIDListFromObject((IUnknown
*)shellitem
, &pidl
);
3107 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3110 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3113 IShellItem_Release(shellitem
);
3117 skip("no SHCreateShellItem.\n");
3119 /* Test IShellFolder */
3120 hres
= pSHGetIDListFromObject((IUnknown
*)psfdesktop
, &pidl
);
3121 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3124 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3128 hres
= IShellFolder_CreateViewObject(psfdesktop
, NULL
, &IID_IShellView
, (void**)&psv
);
3129 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3136 /* Test IFolderView */
3137 hres
= pSHGetIDListFromObject((IUnknown
*)psv
, &pidl
);
3138 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3141 ok(ILIsEqual(pidl_desktop
, pidl
), "pidl not equal.\n");
3145 /* Test IDataObject */
3146 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3147 hres
= IShellFolder_EnumObjects(psfdesktop
, NULL
, enum_flags
, &peidl
);
3148 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3151 LPITEMIDLIST apidl
[5];
3153 for(count
= 0; count
< 5; count
++)
3154 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3159 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, 1, (LPCITEMIDLIST
*)apidl
,
3160 &IID_IDataObject
, NULL
, (void**)&pdo
);
3161 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3164 pidl
= (void*)0xDEADBEEF;
3165 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3166 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3167 ok(pidl
!= NULL
, "pidl is NULL.\n");
3168 ok(ILIsEqual(pidl
, apidl
[0]), "pidl not equal.\n");
3171 IDataObject_Release(pdo
);
3175 skip("No files found - skipping single-file test.\n");
3179 hres
= IShellFolder_GetUIObjectOf(psfdesktop
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3180 &IID_IDataObject
, NULL
, (void**)&pdo
);
3181 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
3184 pidl
= (void*)0xDEADBEEF;
3185 hres
= pSHGetIDListFromObject((IUnknown
*)pdo
, &pidl
);
3186 ok(hres
== E_NOINTERFACE
|| hres
== E_FAIL
/*Vista*/,
3187 "got 0x%08x\n", hres
);
3188 ok(pidl
== NULL
, "pidl is not NULL.\n");
3190 IDataObject_Release(pdo
);
3194 skip("zero or one file found - skipping multi-file test.\n");
3196 for(i
= 0; i
< count
; i
++)
3199 IEnumIDList_Release(peidl
);
3202 IShellView_Release(psv
);
3205 IShellFolder_Release(psfdesktop
);
3206 pILFree(pidl_desktop
);
3209 static void test_SHGetItemFromObject(void)
3211 IUnknownImpl
*punkimpl
;
3212 IShellFolder
*psfdesktop
;
3217 struct if_count ifaces
[] =
3218 { {&IID_IPersistIDList
, 0},
3219 {&IID_IPersistFolder2
, 0},
3220 {&IID_IDataObject
, 0},
3221 {&IID_IParentAndItem
, 0},
3222 {&IID_IFolderView
, 0},
3225 if(!pSHGetItemFromObject
)
3227 skip("No SHGetItemFromObject.\n");
3231 SHGetDesktopFolder(&psfdesktop
);
3235 /* Crashes with Windows 7 */
3236 pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IUnknown
, NULL
);
3237 pSHGetItemFromObject(NULL
, &IID_IUnknown
, NULL
);
3238 pSHGetItemFromObject((IUnknown
*)psfdesktop
, NULL
, (void**)&punk
);
3241 hres
= pSHGetItemFromObject(NULL
, &IID_IUnknown
, (void**)&punk
);
3242 ok(hres
== E_NOINTERFACE
, "Got 0x%08x\n", hres
);
3244 punkimpl
= HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl
));
3245 punkimpl
->IUnknown_iface
.lpVtbl
= &vt_IUnknown
;
3246 punkimpl
->ifaces
= ifaces
;
3247 punkimpl
->unknown
= 0;
3249 /* The same as SHGetIDListFromObject */
3250 hres
= pSHGetIDListFromObject((IUnknown
*)punkimpl
, &pidl
);
3251 ok(hres
== E_NOINTERFACE
, "Got %x\n", hres
);
3252 ok(ifaces
[0].count
, "interface not requested.\n");
3253 ok(ifaces
[1].count
, "interface not requested.\n");
3254 ok(ifaces
[2].count
, "interface not requested.\n");
3256 ok(ifaces
[3].count
|| broken(!ifaces
[3].count
/*vista*/),
3257 "interface not requested.\n");
3258 ok(ifaces
[4].count
|| broken(!ifaces
[4].count
/*vista*/),
3259 "interface not requested.\n");
3261 ok(!punkimpl
->unknown
, "Got %d unknown.\n", punkimpl
->unknown
);
3262 HeapFree(GetProcessHeap(), 0, punkimpl
);
3264 /* Test IShellItem */
3265 hres
= pSHGetItemFromObject((IUnknown
*)psfdesktop
, &IID_IShellItem
, (void**)&psi
);
3266 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3270 hres
= pSHGetItemFromObject((IUnknown
*)psi
, &IID_IShellItem
, (void**)&psi2
);
3271 ok(hres
== S_OK
, "Got 0x%08x\n", hres
);
3275 ok(psi
== psi2
, "Different instances (%p != %p).\n", psi
, psi2
);
3276 IShellItem_Release(psi2
);
3278 IShellItem_Release(psi
);
3281 IShellFolder_Release(psfdesktop
);
3284 static void test_SHCreateShellItemArray(void)
3286 IShellFolder
*pdesktopsf
, *psf
;
3287 IShellItemArray
*psia
;
3290 WCHAR cTestDirW
[MAX_PATH
];
3291 LPITEMIDLIST pidl_testdir
, pidl
;
3292 static const WCHAR testdirW
[] = {'t','e','s','t','d','i','r',0};
3294 if(!pSHCreateShellItemArray
) {
3295 skip("No pSHCreateShellItemArray!\n");
3299 ok(pSHGetSpecialFolderLocation
!= NULL
, "SHGetSpecialFolderLocation missing.\n");
3303 /* Crashes under native */
3304 pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, NULL
);
3305 pSHCreateShellItemArray(NULL
, NULL
, 1, NULL
, NULL
);
3306 pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, NULL
);
3307 pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, NULL
);
3310 hr
= pSHCreateShellItemArray(NULL
, NULL
, 0, NULL
, &psia
);
3311 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
3313 SHGetDesktopFolder(&pdesktopsf
);
3314 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 0, NULL
, &psia
);
3315 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3317 hr
= pSHCreateShellItemArray(NULL
, pdesktopsf
, 1, NULL
, &psia
);
3318 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3320 pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl
);
3321 hr
= pSHCreateShellItemArray(pidl
, NULL
, 0, NULL
, &psia
);
3322 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3325 GetCurrentDirectoryW(MAX_PATH
, cTestDirW
);
3326 myPathAddBackslashW(cTestDirW
);
3327 lstrcatW(cTestDirW
, testdirW
);
3329 CreateFilesFolders();
3331 hr
= IShellFolder_ParseDisplayName(pdesktopsf
, NULL
, NULL
, cTestDirW
, NULL
, &pidl_testdir
, 0);
3332 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3335 hr
= IShellFolder_BindToObject(pdesktopsf
, pidl_testdir
, NULL
, (REFIID
)&IID_IShellFolder
,
3337 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3339 IShellFolder_Release(pdesktopsf
);
3343 skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
3344 pILFree(pidl_testdir
);
3349 hr
= IShellFolder_EnumObjects(psf
, NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &peidl
);
3350 ok(hr
== S_OK
, "Got %08x\n", hr
);
3353 LPITEMIDLIST apidl
[5];
3354 UINT done
, numitems
, i
;
3356 for(done
= 0; done
< 5; done
++)
3357 if(IEnumIDList_Next(peidl
, 1, &apidl
[done
], NULL
) != S_OK
)
3359 ok(done
== 5, "Got %d pidls\n", done
);
3360 IEnumIDList_Release(peidl
);
3362 /* Create a ShellItemArray */
3363 hr
= pSHCreateShellItemArray(NULL
, psf
, done
, (LPCITEMIDLIST
*)apidl
, &psia
);
3364 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3371 /* Crashes in Windows 7 */
3372 IShellItemArray_GetCount(psia
, NULL
);
3375 IShellItemArray_GetCount(psia
, &numitems
);
3376 ok(numitems
== done
, "Got %d, expected %d\n", numitems
, done
);
3378 hr
= IShellItemArray_GetItemAt(psia
, numitems
, &psi
);
3379 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3381 /* Compare all the items */
3382 for(i
= 0; i
< numitems
; i
++)
3384 LPITEMIDLIST pidl_abs
;
3385 pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3387 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3388 ok(hr
== S_OK
, "(%d) Failed with 0x%08x\n", i
, hr
);
3391 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3392 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3395 ok(ILIsEqual(pidl_abs
, pidl
), "Pidl not equal.\n");
3398 IShellItem_Release(psi
);
3402 for(i
= 0; i
< done
; i
++)
3404 IShellItemArray_Release(psia
);
3408 /* SHCreateShellItemArrayFromShellItem */
3409 if(pSHCreateShellItemArrayFromShellItem
)
3415 /* Crashes under Windows 7 */
3416 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, NULL
);
3417 pSHCreateShellItemArrayFromShellItem(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3418 pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, NULL
);
3421 hr
= pSHCreateItemFromIDList(pidl_testdir
, &IID_IShellItem
, (void**)&psi
);
3422 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3425 hr
= pSHCreateShellItemArrayFromShellItem(psi
, &IID_IShellItemArray
, (void**)&psia
);
3426 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3431 hr
= IShellItemArray_GetCount(psia
, &count
);
3432 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3433 ok(count
== 1, "Got count %d\n", count
);
3434 hr
= IShellItemArray_GetItemAt(psia
, 0, &psi2
);
3435 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3437 ok(psi
!= psi2
, "ShellItems are of the same instance.\n");
3440 LPITEMIDLIST pidl1
, pidl2
;
3441 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl1
);
3442 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3443 ok(pidl1
!= NULL
, "pidl1 was null.\n");
3444 hr
= pSHGetIDListFromObject((IUnknown
*)psi2
, &pidl2
);
3445 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3446 ok(pidl2
!= NULL
, "pidl2 was null.\n");
3447 ok(ILIsEqual(pidl1
, pidl2
), "pidls not equal.\n");
3450 IShellItem_Release(psi2
);
3452 hr
= IShellItemArray_GetItemAt(psia
, 1, &psi2
);
3453 ok(hr
== E_FAIL
, "Got 0x%08x\n", hr
);
3454 IShellItemArray_Release(psia
);
3456 IShellItem_Release(psi
);
3460 skip("No SHCreateShellItemArrayFromShellItem.\n");
3462 if(pSHCreateShellItemArrayFromDataObject
)
3468 /* Crashes under Windows 7 */
3469 pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, NULL
);
3471 hr
= pSHCreateShellItemArrayFromDataObject(NULL
, &IID_IShellItemArray
, (void**)&psia
);
3472 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3474 hr
= IShellFolder_CreateViewObject(psf
, NULL
, &IID_IShellView
, (void**)&psv
);
3475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3482 enum_flags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
| SHCONTF_INCLUDEHIDDEN
;
3483 hr
= IShellFolder_EnumObjects(psf
, NULL
, enum_flags
, &peidl
);
3484 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3487 LPITEMIDLIST apidl
[5];
3490 for(count
= 0; count
< 5; count
++)
3491 if(IEnumIDList_Next(peidl
, 1, &apidl
[count
], NULL
) != S_OK
)
3493 ok(count
== 5, "Got %d\n", count
);
3497 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, count
, (LPCITEMIDLIST
*)apidl
,
3498 &IID_IDataObject
, NULL
, (void**)&pdo
);
3499 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3502 hr
= pSHCreateShellItemArrayFromDataObject(pdo
, &IID_IShellItemArray
,
3504 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3508 hr
= IShellItemArray_GetCount(psia
, &count_sia
);
3509 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3510 ok(count_sia
== count
, "Counts differ (%d, %d)\n", count
, count_sia
);
3511 for(i
= 0; i
< count_sia
; i
++)
3513 LPITEMIDLIST pidl_abs
= ILCombine(pidl_testdir
, apidl
[i
]);
3515 hr
= IShellItemArray_GetItemAt(psia
, i
, &psi
);
3516 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3520 hr
= pSHGetIDListFromObject((IUnknown
*)psi
, &pidl
);
3521 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3522 ok(pidl
!= NULL
, "pidl as NULL.\n");
3523 ok(ILIsEqual(pidl
, pidl_abs
), "pidls differ.\n");
3525 IShellItem_Release(psi
);
3530 IShellItemArray_Release(psia
);
3533 IDataObject_Release(pdo
);
3535 for(i
= 0; i
< count
; i
++)
3539 skip("No files found - skipping test.\n");
3541 IEnumIDList_Release(peidl
);
3543 IShellView_Release(psv
);
3547 skip("No SHCreateShellItemArrayFromDataObject.\n");
3549 IShellFolder_Release(psf
);
3550 pILFree(pidl_testdir
);
3554 static void test_ShellItemBindToHandler(void)
3557 LPITEMIDLIST pidl_desktop
;
3560 if(!pSHCreateShellItem
)
3562 skip("SHCreateShellItem missing.\n");
3566 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3567 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3570 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3571 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3575 IPersistFolder2
*ppf2
;
3580 /* Crashes under Windows 7 */
3581 IShellItem_BindToHandler(psi
, NULL
, NULL
, NULL
, NULL
);
3582 IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, NULL
);
3584 hr
= IShellItem_BindToHandler(psi
, NULL
, &IID_IUnknown
, &IID_IUnknown
, (void**)&punk
);
3585 ok(hr
== MK_E_NOOBJECT
, "Got 0x%08x\n", hr
);
3588 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IShellFolder
, (void**)&punk
);
3589 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3590 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3591 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFObject
, &IID_IPersistFolder2
, (void**)&ppf2
);
3592 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3595 LPITEMIDLIST pidl_tmp
;
3596 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl_tmp
);
3597 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3600 ok(ILIsEqual(pidl_desktop
, pidl_tmp
), "Pidl not equal (%p, %p)\n", pidl_desktop
, pidl_tmp
);
3603 IPersistFolder2_Release(ppf2
);
3606 /* BHID_SFUIObject */
3607 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IDataObject
, (void**)&punk
);
3608 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3609 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3610 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFUIObject
, &IID_IContextMenu
, (void**)&punk
);
3611 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
/* XP */), "Got 0x%08x\n", hr
);
3612 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3614 /* BHID_DataObject */
3615 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_DataObject
, &IID_IDataObject
, (void**)&punk
);
3616 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3617 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3621 /* BHID_SFViewObject */
3622 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellView
, (void**)&punk
);
3623 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3624 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3625 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_SFViewObject
, &IID_IShellFolderView
, (void**)&punk
);
3626 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3627 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3630 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IStream
, (void**)&punk
);
3631 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3632 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3633 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Storage
, &IID_IUnknown
, (void**)&punk
);
3634 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3635 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3638 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IStream
, (void**)&punk
);
3639 ok(hr
== E_NOINTERFACE
, "Got 0x%08x\n", hr
);
3640 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3641 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Stream
, &IID_IUnknown
, (void**)&punk
);
3642 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3643 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3645 /* BHID_StorageEnum */
3646 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_StorageEnum
, &IID_IEnumShellItems
, (void**)&punk
);
3647 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3648 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3651 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Transfer
, &IID_IUnknown
, (void**)&punk
);
3652 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3653 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3655 /* BHID_EnumItems */
3656 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumItems
, &IID_IEnumShellItems
, (void**)&punk
);
3657 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3658 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3661 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_Filter
, &IID_IUnknown
, (void**)&punk
);
3662 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3663 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3665 /* BHID_LinkTargetItem */
3666 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IShellItem
, (void**)&punk
);
3667 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3668 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3669 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_LinkTargetItem
, &IID_IUnknown
, (void**)&punk
);
3670 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_INVALIDARG
/* XP */), "Got 0x%08x\n", hr
);
3671 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3673 /* BHID_PropertyStore */
3674 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStore
, (void**)&punk
);
3675 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3676 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3677 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_PropertyStore
, &IID_IPropertyStoreFactory
, (void**)&punk
);
3678 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3679 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3681 /* BHID_ThumbnailHandler */
3682 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_ThumbnailHandler
, &IID_IUnknown
, (void**)&punk
);
3683 ok(hr
== E_INVALIDARG
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3684 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3686 /* BHID_AssociationArray */
3687 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_AssociationArray
, &IID_IQueryAssociations
, (void**)&punk
);
3688 ok(hr
== S_OK
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3689 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3691 /* BHID_EnumAssocHandlers */
3692 hr
= IShellItem_BindToHandler(psi
, NULL
, &BHID_EnumAssocHandlers
, &IID_IUnknown
, (void**)&punk
);
3693 ok(hr
== E_NOINTERFACE
|| broken(hr
== MK_E_NOOBJECT
/* XP */), "Got 0x%08x\n", hr
);
3694 if(SUCCEEDED(hr
)) IUnknown_Release(punk
);
3697 IShellItem_Release(psi
);
3700 skip("Failed to create ShellItem.\n");
3702 pILFree(pidl_desktop
);
3705 static void test_ShellItemGetAttributes(void)
3708 LPITEMIDLIST pidl_desktop
;
3712 if(!pSHCreateShellItem
)
3714 skip("SHCreateShellItem missing.\n");
3718 hr
= pSHGetSpecialFolderLocation(NULL
, CSIDL_DESKTOP
, &pidl_desktop
);
3719 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3722 hr
= pSHCreateShellItem(NULL
, NULL
, pidl_desktop
, &psi
);
3723 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3724 pILFree(pidl_desktop
);
3728 skip("Skipping tests.\n");
3734 /* Crashes on native (Win 7) */
3735 IShellItem_GetAttributes(psi
, 0, NULL
);
3738 /* Test GetAttributes on the desktop folder. */
3740 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &sfgao
);
3741 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* <Vista */, "Got 0x%08x\n", hr
);
3742 ok(sfgao
== SFGAO_FOLDER
|| broken(sfgao
== 0) /* <Vista */, "Got 0x%08x\n", sfgao
);
3744 IShellItem_Release(psi
);
3747 static void test_SHParseDisplayName(void)
3749 LPITEMIDLIST pidl1
, pidl2
;
3750 IShellFolder
*desktop
;
3751 WCHAR dirW
[MAX_PATH
];
3756 if (!pSHParseDisplayName
)
3758 win_skip("SHParseDisplayName isn't available\n");
3764 /* crashes on native */
3765 pSHParseDisplayName(NULL
, NULL
, NULL
, 0, NULL
);
3767 pSHParseDisplayName(nameW
, NULL
, NULL
, 0, NULL
);
3770 pidl1
= (LPITEMIDLIST
)0xdeadbeef;
3771 hr
= pSHParseDisplayName(NULL
, NULL
, &pidl1
, 0, NULL
);
3772 ok(broken(hr
== E_OUTOFMEMORY
) /* < Vista */ ||
3773 hr
== E_INVALIDARG
, "failed %08x\n", hr
);
3774 ok(pidl1
== 0, "expected null ptr, got %p\n", pidl1
);
3778 hr
= pSHParseDisplayName(nameW
, NULL
, &pidl1
, 0, NULL
);
3779 ok(hr
== S_OK
, "failed %08x\n", hr
);
3780 hr
= SHGetDesktopFolder(&desktop
);
3781 ok(hr
== S_OK
, "failed %08x\n", hr
);
3782 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, nameW
, NULL
, &pidl2
, NULL
);
3783 ok(hr
== S_OK
, "failed %08x\n", hr
);
3784 ret
= pILIsEqual(pidl1
, pidl2
);
3785 ok(ret
== TRUE
, "expected equal idls\n");
3790 GetWindowsDirectoryW( dirW
, MAX_PATH
);
3792 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
3793 ok(hr
== S_OK
, "failed %08x\n", hr
);
3794 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, dirW
, NULL
, &pidl2
, NULL
);
3795 ok(hr
== S_OK
, "failed %08x\n", hr
);
3797 ret
= pILIsEqual(pidl1
, pidl2
);
3798 ok(ret
== TRUE
, "expected equal idls\n");
3802 /* system32 is not redirected to syswow64 on WOW64 */
3803 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
3804 if (is_wow64
&& pGetSystemWow64DirectoryW
)
3808 len
= GetSystemDirectoryW(dirW
, MAX_PATH
);
3809 ok(len
> 0, "GetSystemDirectoryW failed: %u\n", GetLastError());
3810 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl1
, 0, NULL
);
3811 ok(hr
== S_OK
, "failed %08x\n", hr
);
3813 len
= pGetSystemWow64DirectoryW(dirW
, MAX_PATH
);
3814 ok(len
> 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError());
3815 hr
= pSHParseDisplayName(dirW
, NULL
, &pidl2
, 0, NULL
);
3816 ok(hr
== S_OK
, "failed %08x\n", hr
);
3817 ret
= pILIsEqual(pidl1
, pidl2
);
3818 ok(ret
== FALSE
, "expected different idls\n");
3823 IShellFolder_Release(desktop
);
3826 static void test_desktop_IPersist(void)
3828 IShellFolder
*desktop
;
3830 IPersistFolder2
*ppf2
;
3834 hr
= SHGetDesktopFolder(&desktop
);
3835 ok(hr
== S_OK
, "failed %08x\n", hr
);
3837 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersist
, (void**)&persist
);
3838 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* NT4, W9X */, "failed %08x\n", hr
);
3844 /* crashes on native */
3845 IPersist_GetClassID(persist
, NULL
);
3847 memset(&clsid
, 0, sizeof(clsid
));
3848 hr
= IPersist_GetClassID(persist
, &clsid
);
3849 ok(hr
== S_OK
, "failed %08x\n", hr
);
3850 ok(IsEqualIID(&CLSID_ShellDesktop
, &clsid
), "Expected CLSID_ShellDesktop\n");
3851 IPersist_Release(persist
);
3854 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder2
, (void**)&ppf2
);
3855 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* pre-Vista */, "failed %08x\n", hr
);
3858 IPersistFolder
*ppf
;
3860 hr
= IShellFolder_QueryInterface(desktop
, &IID_IPersistFolder
, (void**)&ppf
);
3861 ok(hr
== S_OK
, "IID_IPersistFolder2 without IID_IPersistFolder.\n");
3863 IPersistFolder_Release(ppf
);
3866 hr
= IPersistFolder2_Initialize(ppf2
, NULL
);
3867 ok(hr
== S_OK
, "got %08x\n", hr
);
3871 hr
= IPersistFolder2_GetCurFolder(ppf2
, &pidl
);
3872 ok(hr
== S_OK
, "got %08x\n", hr
);
3873 ok(pidl
!= NULL
, "pidl was NULL.\n");
3874 if(SUCCEEDED(hr
)) pILFree(pidl
);
3876 IPersistFolder2_Release(ppf2
);
3879 IShellFolder_Release(desktop
);
3882 static void test_GetUIObject(void)
3884 IShellFolder
*psf_desktop
;
3888 WCHAR path
[MAX_PATH
];
3889 const WCHAR filename
[] =
3890 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
3892 if(!pSHBindToParent
)
3894 win_skip("SHBindToParent missing.\n");
3898 GetCurrentDirectoryW(MAX_PATH
, path
);
3901 skip("GetCurrentDirectoryW returned an empty string.\n");
3904 lstrcatW(path
, filename
);
3905 SHGetDesktopFolder(&psf_desktop
);
3907 CreateFilesFolders();
3909 hr
= IShellFolder_ParseDisplayName(psf_desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
3910 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
3914 LPCITEMIDLIST pidl_child
;
3915 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&psf
, &pidl_child
);
3916 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3919 hr
= IShellFolder_GetUIObjectOf(psf
, NULL
, 1, &pidl_child
, &IID_IContextMenu
, NULL
,
3921 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3924 HMENU hmenu
= CreatePopupMenu();
3925 INT max_id
, max_id_check
;
3927 const int id_upper_limit
= 32767;
3928 hr
= IContextMenu_QueryContextMenu(pcm
, hmenu
, 0, 0, id_upper_limit
, CMF_NORMAL
);
3929 ok(SUCCEEDED(hr
), "Got 0x%08x\n", hr
);
3930 max_id
= HRESULT_CODE(hr
) - 1; /* returns max_id + 1 */
3931 ok(max_id
<= id_upper_limit
, "Got %d\n", max_id
);
3932 count
= GetMenuItemCount(hmenu
);
3933 ok(count
, "Got %d\n", count
);
3936 for(i
= 0; i
< count
; i
++)
3940 ZeroMemory(&mii
, sizeof(MENUITEMINFOA
));
3941 mii
.cbSize
= sizeof(MENUITEMINFOA
);
3942 mii
.fMask
= MIIM_ID
| MIIM_FTYPE
;
3945 res
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
3946 ok(res
, "Failed (last error: %d).\n", GetLastError());
3948 ok( (mii
.wID
<= id_upper_limit
) || (mii
.fType
& MFT_SEPARATOR
),
3949 "Got non-separator ID out of range: %d (type: %x)\n", mii
.wID
, mii
.fType
);
3950 if(!(mii
.fType
& MFT_SEPARATOR
))
3951 max_id_check
= (mii
.wID
>max_id_check
)?mii
.wID
:max_id_check
;
3953 ok((max_id_check
== max_id
) ||
3954 (max_id_check
== max_id
-1 /* Win 7 */),
3955 "Not equal (or near equal), got %d and %d\n", max_id_check
, max_id
);
3957 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
3959 if(count
&& !is_win2k()) /* Test is interactive on w2k, so skip */
3961 CMINVOKECOMMANDINFO cmi
;
3962 ZeroMemory(&cmi
, sizeof(CMINVOKECOMMANDINFO
));
3963 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
3965 /* Attempt to execute a nonexistent command */
3966 cmi
.lpVerb
= MAKEINTRESOURCEA(9999);
3967 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
3968 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
3970 cmi
.lpVerb
= "foobar_wine_test";
3971 hr
= IContextMenu_InvokeCommand(pcm
, &cmi
);
3972 ok( (hr
== E_INVALIDARG
) || (hr
== E_FAIL
/* Win7 */) ||
3973 (hr
== HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION
) /* Vista */),
3974 "Got 0x%08x\n", hr
);
3979 IContextMenu_Release(pcm
);
3981 IShellFolder_Release(psf
);
3983 if(pILFree
) pILFree(pidl
);
3986 IShellFolder_Release(psf_desktop
);
3990 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p)
3991 static void r_verify_pidl(unsigned l
, LPCITEMIDLIST pidl
, const WCHAR
*path
)
3993 LPCITEMIDLIST child
;
3994 IShellFolder
*parent
;
3998 if(!pSHBindToParent
){
3999 win_skip("SHBindToParent is not available, not performing full PIDL verification\n");
4001 ok_(__FILE__
,l
)(pidl
!= NULL
, "Expected PIDL to be non-NULL\n");
4003 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4009 ok_(__FILE__
,l
)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path
));
4013 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&parent
, &child
);
4014 ok_(__FILE__
,l
)(hr
== S_OK
, "SHBindToParent failed: 0x%08x\n", hr
);
4018 hr
= IShellFolder_GetDisplayNameOf(parent
, child
, SHGDN_FORPARSING
, &filename
);
4019 ok_(__FILE__
,l
)(hr
== S_OK
, "GetDisplayNameOf failed: 0x%08x\n", hr
);
4021 IShellFolder_Release(parent
);
4025 ok_(__FILE__
,l
)(filename
.uType
== STRRET_WSTR
|| filename
.uType
== STRRET_CSTR
,
4026 "Got unexpected string type: %d\n", filename
.uType
);
4027 if(filename
.uType
== STRRET_WSTR
){
4028 ok_(__FILE__
,l
)(lstrcmpW(path
, U(filename
).pOleStr
) == 0,
4029 "didn't get expected path (%s), instead: %s\n",
4030 wine_dbgstr_w(path
), wine_dbgstr_w(U(filename
).pOleStr
));
4031 SHFree(U(filename
).pOleStr
);
4032 }else if(filename
.uType
== STRRET_CSTR
){
4033 ok_(__FILE__
,l
)(strcmp_wa(path
, U(filename
).cStr
) == 0,
4034 "didn't get expected path (%s), instead: %s\n",
4035 wine_dbgstr_w(path
), U(filename
).cStr
);
4038 IShellFolder_Release(parent
);
4040 ok_(__FILE__
,l
)(pidl
== NULL
, "Expected PIDL to be NULL\n");
4043 static void test_SHSimpleIDListFromPath(void)
4045 const WCHAR adirW
[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0};
4046 const CHAR adirA
[] = "C:\\sidlfpdir";
4047 BOOL br
, is_unicode
= !(GetVersion() & 0x80000000);
4049 LPITEMIDLIST pidl
= NULL
;
4051 if(!pSHSimpleIDListFromPathAW
){
4052 win_skip("SHSimpleIDListFromPathAW not available\n");
4056 br
= CreateDirectoryA(adirA
, NULL
);
4057 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4060 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4062 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4063 verify_pidl(pidl
, adirW
);
4066 br
= RemoveDirectoryA(adirA
);
4067 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4070 pidl
= pSHSimpleIDListFromPathAW(adirW
);
4072 pidl
= pSHSimpleIDListFromPathAW(adirA
);
4073 verify_pidl(pidl
, adirW
);
4077 /* IFileSystemBindData impl */
4078 static HRESULT WINAPI
fsbd_QueryInterface(IFileSystemBindData
*fsbd
,
4079 REFIID riid
, void **ppv
)
4081 if(IsEqualIID(riid
, &IID_IFileSystemBindData
) ||
4082 IsEqualIID(riid
, &IID_IUnknown
)){
4086 return E_NOINTERFACE
;
4089 static ULONG WINAPI
fsbd_AddRef(IFileSystemBindData
*fsbd
)
4094 static ULONG WINAPI
fsbd_Release(IFileSystemBindData
*fsbd
)
4099 static HRESULT WINAPI
fsbd_SetFindData(IFileSystemBindData
*fsbd
,
4100 const WIN32_FIND_DATAW
*pfd
)
4102 ok(0, "SetFindData called\n");
4106 static HRESULT WINAPI
fsbd_GetFindData_nul(IFileSystemBindData
*fsbd
,
4107 WIN32_FIND_DATAW
*pfd
)
4109 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4113 static HRESULT WINAPI
fsbd_GetFindData_junk(IFileSystemBindData
*fsbd
,
4114 WIN32_FIND_DATAW
*pfd
)
4116 memset(pfd
, 0xef, sizeof(WIN32_FIND_DATAW
));
4120 static HRESULT WINAPI
fsbd_GetFindData_invalid(IFileSystemBindData
*fsbd
,
4121 WIN32_FIND_DATAW
*pfd
)
4123 memset(pfd
, 0, sizeof(WIN32_FIND_DATAW
));
4124 *pfd
->cFileName
= 'a';
4125 *pfd
->cAlternateFileName
= 'a';
4129 static HRESULT WINAPI
fsbd_GetFindData_valid(IFileSystemBindData
*fsbd
,
4130 WIN32_FIND_DATAW
*pfd
)
4132 static const WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4133 HANDLE handle
= FindFirstFileW(adirW
, pfd
);
4138 static HRESULT WINAPI
fsbd_GetFindData_fail(IFileSystemBindData
*fsbd
,
4139 WIN32_FIND_DATAW
*pfd
)
4144 static IFileSystemBindDataVtbl fsbdVtbl
= {
4145 fsbd_QueryInterface
,
4152 static IFileSystemBindData fsbd
= { &fsbdVtbl
};
4154 static void test_ParseDisplayNamePBC(void)
4156 WCHAR wFileSystemBindData
[] =
4157 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0};
4158 WCHAR adirW
[] = {'C',':','\\','f','s','b','d','d','i','r',0};
4159 WCHAR afileW
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0};
4160 WCHAR afile2W
[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0};
4161 const HRESULT exp_err
= HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4168 /* Check if we support WCHAR functions */
4169 SetLastError(0xdeadbeef);
4170 lstrcmpiW(adirW
, adirW
);
4171 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
){
4172 win_skip("Most W-calls are not implemented\n");
4176 hres
= SHGetDesktopFolder(&psf
);
4177 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
4179 win_skip("Failed to get IShellFolder, can't run tests\n");
4183 /* fails on unknown dir with no IBindCtx */
4184 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, adirW
, NULL
, &pidl
, NULL
);
4185 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4186 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4187 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afileW
, NULL
, &pidl
, NULL
);
4188 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4189 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4190 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, NULL
, afile2W
, NULL
, &pidl
, NULL
);
4191 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4192 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4194 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */
4195 hres
= CreateBindCtx(0, &pbc
);
4196 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
4198 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4199 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4200 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4201 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4202 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4203 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4204 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4205 ok(hres
== exp_err
|| broken(hres
== E_FAIL
) /* NT4 */,
4206 "ParseDisplayName failed with wrong error: 0x%08x\n", hres
);
4208 /* unknown dir with IBindCtx with IFileSystemBindData */
4209 hres
= IBindCtx_RegisterObjectParam(pbc
, wFileSystemBindData
, (IUnknown
*)&fsbd
);
4210 ok(hres
== S_OK
, "RegisterObjectParam failed: 0x%08x\n", hres
);
4212 /* return E_FAIL from GetFindData */
4213 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4214 fsbdVtbl
.GetFindData
= fsbd_GetFindData_fail
;
4215 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4216 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4217 "ParseDisplayName failed: 0x%08x\n", hres
);
4218 if(SUCCEEDED(hres
)){
4219 verify_pidl(pidl
, adirW
);
4223 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4224 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4225 "ParseDisplayName failed: 0x%08x\n", hres
);
4226 if(SUCCEEDED(hres
)){
4227 verify_pidl(pidl
, afileW
);
4231 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4232 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4233 "ParseDisplayName failed: 0x%08x\n", hres
);
4234 if(SUCCEEDED(hres
)){
4235 verify_pidl(pidl
, afile2W
);
4239 /* set FIND_DATA struct to NULLs */
4240 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4241 fsbdVtbl
.GetFindData
= fsbd_GetFindData_nul
;
4242 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4243 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4244 "ParseDisplayName failed: 0x%08x\n", hres
);
4245 if(SUCCEEDED(hres
)){
4246 verify_pidl(pidl
, adirW
);
4250 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4251 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4252 "ParseDisplayName failed: 0x%08x\n", hres
);
4253 if(SUCCEEDED(hres
)){
4254 verify_pidl(pidl
, afileW
);
4258 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4259 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4260 "ParseDisplayName failed: 0x%08x\n", hres
);
4261 if(SUCCEEDED(hres
)){
4262 verify_pidl(pidl
, afile2W
);
4266 /* set FIND_DATA struct to junk */
4267 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4268 fsbdVtbl
.GetFindData
= fsbd_GetFindData_junk
;
4269 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4270 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4271 "ParseDisplayName failed: 0x%08x\n", hres
);
4272 if(SUCCEEDED(hres
)){
4273 verify_pidl(pidl
, adirW
);
4277 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4278 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4279 "ParseDisplayName failed: 0x%08x\n", hres
);
4280 if(SUCCEEDED(hres
)){
4281 verify_pidl(pidl
, afileW
);
4285 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4286 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4287 "ParseDisplayName failed: 0x%08x\n", hres
);
4288 if(SUCCEEDED(hres
)){
4289 verify_pidl(pidl
, afile2W
);
4293 /* set FIND_DATA struct to invalid data */
4294 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4295 fsbdVtbl
.GetFindData
= fsbd_GetFindData_invalid
;
4296 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4297 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4298 "ParseDisplayName failed: 0x%08x\n", hres
);
4299 if(SUCCEEDED(hres
)){
4300 verify_pidl(pidl
, adirW
);
4304 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4305 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4306 "ParseDisplayName failed: 0x%08x\n", hres
);
4307 if(SUCCEEDED(hres
)){
4308 verify_pidl(pidl
, afileW
);
4312 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4313 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4314 "ParseDisplayName failed: 0x%08x\n", hres
);
4315 if(SUCCEEDED(hres
)){
4316 verify_pidl(pidl
, afile2W
);
4320 /* set FIND_DATA struct to valid data */
4321 pidl
= (ITEMIDLIST
*)0xdeadbeef;
4322 fsbdVtbl
.GetFindData
= fsbd_GetFindData_valid
;
4323 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, adirW
, NULL
, &pidl
, NULL
);
4324 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4325 "ParseDisplayName failed: 0x%08x\n", hres
);
4326 if(SUCCEEDED(hres
)){
4327 verify_pidl(pidl
, adirW
);
4331 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afileW
, NULL
, &pidl
, NULL
);
4332 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4333 "ParseDisplayName failed: 0x%08x\n", hres
);
4334 if(SUCCEEDED(hres
)){
4335 verify_pidl(pidl
, afileW
);
4339 hres
= IShellFolder_ParseDisplayName(psf
, NULL
, pbc
, afile2W
, NULL
, &pidl
, NULL
);
4340 ok(hres
== S_OK
|| broken(hres
== E_FAIL
) /* NT4 */,
4341 "ParseDisplayName failed: 0x%08x\n", hres
);
4342 if(SUCCEEDED(hres
)){
4343 verify_pidl(pidl
, afile2W
);
4347 IBindCtx_Release(pbc
);
4348 IShellFolder_Release(psf
);
4351 static const CHAR testwindow_class
[] = "testwindow";
4352 #define WM_USER_NOTIFY (WM_APP+1)
4354 struct ChNotifyTest
{
4356 const UINT notify_count
;
4357 UINT missing_events
;
4359 const char path_1
[256];
4360 const char path_2
[256];
4361 } chnotify_tests
[] = {
4362 {"MKDIR", 1, 0, SHCNE_MKDIR
, "C:\\shell32_cn_test\\test", ""},
4363 {"CREATE", 1, 0, SHCNE_CREATE
, "C:\\shell32_cn_test\\test\\file.txt", ""},
4364 {"RMDIR", 1, 0, SHCNE_RMDIR
, "C:\\shell32_cn_test\\test", ""},
4367 struct ChNotifyTest
*exp_data
;
4368 BOOL test_new_delivery_flag
;
4370 static LRESULT CALLBACK
testwindow_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
4372 LONG signal
= (LONG
)lparam
;
4375 case WM_USER_NOTIFY
:
4376 if(exp_data
->missing_events
> 0) {
4377 WCHAR
*path1
, *path2
;
4378 LPITEMIDLIST
*pidls
= (LPITEMIDLIST
*)wparam
;
4379 HANDLE hLock
= NULL
;
4381 if(test_new_delivery_flag
) {
4382 hLock
= SHChangeNotification_Lock((HANDLE
)wparam
, lparam
, &pidls
, &signal
);
4383 ok(hLock
!= NULL
, "SHChangeNotification_Lock returned NULL\n");
4386 ok(exp_data
->signal
== signal
,
4387 "%s: expected notification type %x, got: %x\n",
4388 exp_data
->id
, exp_data
->signal
, signal
);
4390 trace("verifying pidls for: %s\n", exp_data
->id
);
4391 path1
= make_wstr(exp_data
->path_1
);
4392 path2
= make_wstr(exp_data
->path_2
);
4393 verify_pidl(pidls
[0], path1
);
4394 verify_pidl(pidls
[1], path2
);
4395 HeapFree(GetProcessHeap(), 0, path1
);
4396 HeapFree(GetProcessHeap(), 0, path2
);
4398 exp_data
->missing_events
--;
4400 if(test_new_delivery_flag
)
4401 SHChangeNotification_Unlock(hLock
);
4403 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal
);
4406 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
4409 static void register_testwindow_class(void)
4414 ZeroMemory(&cls
, sizeof(cls
));
4415 cls
.cbSize
= sizeof(cls
);
4417 cls
.lpfnWndProc
= testwindow_wndproc
;
4418 cls
.hInstance
= GetModuleHandleA(NULL
);
4419 cls
.lpszClassName
= testwindow_class
;
4422 ret
= RegisterClassExA(&cls
);
4423 ok(ret
!= 0, "RegisterClassExA failed: %d\n", GetLastError());
4426 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we
4427 * have to poll repeatedly for the message to appear */
4428 static void do_events(void)
4431 while (exp_data
->missing_events
&& (c
++ < 10)){
4433 while(PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)){
4434 TranslateMessage(&msg
);
4435 DispatchMessageA(&msg
);
4437 if(exp_data
->missing_events
)
4440 trace("%s: took %d tries\n", exp_data
->id
, c
);
4443 static void test_SHChangeNotify(BOOL test_new_delivery
)
4448 BOOL br
, has_unicode
;
4449 SHChangeNotifyEntry entries
[1];
4450 const CHAR root_dirA
[] = "C:\\shell32_cn_test";
4451 const WCHAR root_dirW
[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0};
4453 trace("SHChangeNotify tests (%x)\n", test_new_delivery
);
4455 CreateDirectoryW(NULL
, NULL
);
4456 has_unicode
= !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
);
4458 test_new_delivery_flag
= test_new_delivery
;
4459 if(!test_new_delivery
)
4460 register_testwindow_class();
4462 wnd
= CreateWindowExA(0, testwindow_class
, testwindow_class
, 0,
4463 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105,
4464 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
4465 ok(wnd
!= NULL
, "Failed to make a window\n");
4467 br
= CreateDirectoryA(root_dirA
, NULL
);
4468 ok(br
== TRUE
, "CreateDirectory failed: %d\n", GetLastError());
4470 entries
[0].pidl
= NULL
;
4472 hr
= SHILCreateFromPath(root_dirW
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4474 hr
= SHILCreateFromPath((LPCVOID
)root_dirA
, (LPITEMIDLIST
*)&entries
[0].pidl
, 0);
4475 ok(hr
== S_OK
, "SHILCreateFromPath failed: 0x%08x\n", hr
);
4476 entries
[0].fRecursive
= TRUE
;
4478 notifyID
= SHChangeNotifyRegister(wnd
, !test_new_delivery
? SHCNRF_ShellLevel
: SHCNRF_ShellLevel
|SHCNRF_NewDelivery
,
4479 SHCNE_ALLEVENTS
, WM_USER_NOTIFY
, 1, entries
);
4480 ok(notifyID
!= 0, "Failed to register a window for change notifications\n");
4482 for(i
= 0; i
< sizeof(chnotify_tests
) / sizeof(*chnotify_tests
); ++i
){
4483 exp_data
= chnotify_tests
+ i
;
4485 exp_data
->missing_events
= exp_data
->notify_count
;
4486 SHChangeNotify(exp_data
->signal
, SHCNF_PATHA
| SHCNF_FLUSH
,
4487 strlen(exp_data
->path_1
) > 0 ? exp_data
->path_1
: NULL
,
4488 strlen(exp_data
->path_2
) > 0 ? exp_data
->path_2
: NULL
);
4490 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4493 WCHAR
*path1
, *path2
;
4495 path1
= make_wstr(exp_data
->path_1
);
4496 path2
= make_wstr(exp_data
->path_2
);
4498 exp_data
->missing_events
= exp_data
->notify_count
;
4499 SHChangeNotify(exp_data
->signal
, SHCNF_PATHW
| SHCNF_FLUSH
, path1
, path2
);
4501 ok(exp_data
->missing_events
== 0, "%s: Expected wndproc to be called\n", exp_data
->id
);
4503 HeapFree(GetProcessHeap(), 0, path1
);
4504 HeapFree(GetProcessHeap(), 0, path2
);
4508 SHChangeNotifyDeregister(notifyID
);
4511 ILFree((LPITEMIDLIST
)entries
[0].pidl
);
4512 br
= RemoveDirectoryA(root_dirA
);
4513 ok(br
== TRUE
, "RemoveDirectory failed: %d\n", GetLastError());
4516 static void test_SHCreateDefaultContextMenu(void)
4519 WCHAR path
[MAX_PATH
];
4520 IShellFolder
*desktop
,*folder
;
4521 IPersistFolder2
*persist
;
4522 IContextMenu
*cmenu
;
4524 LPITEMIDLIST pidlFolder
, pidl_child
, pidl
;
4525 DEFCONTEXTMENU cminfo
;
4528 const WCHAR filename
[] =
4529 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
4530 if(!pSHCreateDefaultContextMenu
)
4532 win_skip("SHCreateDefaultContextMenu missing.\n");
4536 if(!pSHBindToParent
)
4538 skip("SHBindToParent missing.\n");
4542 GetCurrentDirectoryW(MAX_PATH
, path
);
4545 skip("GetCurrentDirectoryW returned an empty string.\n");
4548 lstrcatW(path
, filename
);
4549 SHGetDesktopFolder(&desktop
);
4551 CreateFilesFolders();
4553 hr
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &pidl
, 0);
4554 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* WinME */, "Got 0x%08x\n", hr
);
4558 hr
= pSHBindToParent(pidl
, &IID_IShellFolder
, (void**)&folder
, (LPCITEMIDLIST
*)&pidl_child
);
4559 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4561 IShellFolder_QueryInterface(folder
,&IID_IPersistFolder2
,(void**)&persist
);
4562 IPersistFolder2_GetCurFolder(persist
,&pidlFolder
);
4563 IPersistFolder2_Release(persist
);
4570 cminfo
.pidlFolder
=NULL
;
4571 cminfo
.apidl
=(LPCITEMIDLIST
*)&pidl_child
;
4575 cminfo
.punkAssociationInfo
=NULL
;
4576 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
4577 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
4578 IContextMenu_Release(cmenu
);
4579 cminfo
.pidlFolder
=pidlFolder
;
4580 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
4581 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
4582 IContextMenu_Release(cmenu
);
4583 status
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,"*",0,KEY_READ
,keys
);
4584 if(status
==ERROR_SUCCESS
){
4589 hr
= pSHCreateDefaultContextMenu(&cminfo
,&IID_IContextMenu
,(void**)&cmenu
);
4590 RegCloseKey(keys
[0]);
4591 ok(hr
==S_OK
,"Got 0x%08x\n", hr
);
4592 IContextMenu_Release(cmenu
);
4596 IShellFolder_Release(folder
);
4598 IShellFolder_Release(desktop
);
4603 static void test_SHCreateShellFolderView(void)
4608 IShellFolder
*desktop
;
4611 if (!pSHCreateShellFolderView
)
4613 win_skip("SHCreateShellFolderView missing.\n");
4617 hr
= SHGetDesktopFolder(&desktop
);
4618 ok(hr
== S_OK
, "got (0x%08x)\n", hr
);
4623 pSHCreateShellFolderView(NULL
, NULL
);
4626 psv
= (void *)0xdeadbeef;
4627 hr
= pSHCreateShellFolderView(NULL
, &psv
);
4628 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4629 ok(psv
== NULL
, "psv = %p\n", psv
);
4631 memset(&sfvc
, 0, sizeof(sfvc
));
4632 psv
= (void *)0xdeadbeef;
4633 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
4634 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4635 ok(psv
== NULL
, "psv = %p\n", psv
);
4637 memset(&sfvc
, 0, sizeof(sfvc
));
4638 sfvc
.cbSize
= sizeof(sfvc
) - 1;
4639 psv
= (void *)0xdeadbeef;
4640 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
4641 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4642 ok(psv
== NULL
, "psv = %p\n", psv
);
4644 memset(&sfvc
, 0, sizeof(sfvc
));
4645 sfvc
.cbSize
= sizeof(sfvc
) + 1;
4646 psv
= (void *)0xdeadbeef;
4647 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
4648 ok(hr
== E_INVALIDARG
, "Got 0x%08x\n", hr
);
4649 ok(psv
== NULL
, "psv = %p\n", psv
);
4651 memset(&sfvc
, 0, sizeof(sfvc
));
4652 sfvc
.cbSize
= sizeof(sfvc
);
4653 sfvc
.pshf
= desktop
;
4655 hr
= pSHCreateShellFolderView(&sfvc
, &psv
);
4656 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4657 ok(psv
!= NULL
, "psv = %p\n", psv
);
4660 refCount
= IShellView_Release(psv
);
4661 ok(refCount
== 0, "refCount = %u\n", refCount
);
4664 IShellFolder_Release(desktop
);
4667 static void test_SHCreateShellFolderViewEx(void)
4672 IShellFolder
*desktop
;
4675 if (!pSHCreateShellFolderViewEx
)
4677 win_skip("SHCreateShellFolderViewEx missing.\n");
4681 hr
= SHGetDesktopFolder(&desktop
);
4682 ok(hr
== S_OK
, "got (0x%08x)\n", hr
);
4687 pSHCreateShellFolderViewEx(NULL
, NULL
);
4688 pSHCreateShellFolderViewEx(NULL
, &psv
);
4689 pSHCreateShellFolderViewEx(&csfv
, NULL
);
4692 memset(&csfv
, 0, sizeof(csfv
));
4693 csfv
.pshf
= desktop
;
4695 hr
= pSHCreateShellFolderViewEx(&csfv
, &psv
);
4696 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4697 ok(psv
!= NULL
, "psv = %p\n", psv
);
4700 refCount
= IShellView_Release(psv
);
4701 ok(refCount
== 0, "refCount = %u\n", refCount
);
4704 memset(&csfv
, 0, sizeof(csfv
));
4705 csfv
.cbSize
= sizeof(csfv
);
4706 csfv
.pshf
= desktop
;
4708 hr
= pSHCreateShellFolderViewEx(&csfv
, &psv
);
4709 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4710 ok(psv
!= NULL
, "psv = %p\n", psv
);
4713 refCount
= IShellView_Release(psv
);
4714 ok(refCount
== 0, "refCount = %u\n", refCount
);
4717 IShellFolder_Release(desktop
);
4720 START_TEST(shlfolder
)
4722 init_function_pointers();
4723 /* if OleInitialize doesn't get called, ParseDisplayName returns
4724 CO_E_NOTINITIALIZED for malformed directory names on win2k. */
4725 OleInitialize(NULL
);
4727 test_ParseDisplayName();
4728 test_SHParseDisplayName();
4729 test_BindToObject();
4730 test_EnumObjects_and_CompareIDs();
4731 test_GetDisplayName();
4732 test_GetAttributesOf();
4733 test_SHGetPathFromIDList();
4734 test_CallForAttributes();
4735 test_FolderShortcut();
4736 test_ITEMIDLIST_format();
4737 test_SHGetFolderPathA();
4738 test_SHGetFolderPathAndSubDirA();
4739 test_LocalizedNames();
4740 test_SHCreateShellItem();
4741 test_SHCreateShellItemArray();
4742 test_desktop_IPersist();
4744 test_SHSimpleIDListFromPath();
4745 test_ParseDisplayNamePBC();
4746 test_SHGetNameFromIDList();
4747 test_SHGetItemFromDataObject();
4748 test_SHGetIDListFromObject();
4749 test_SHGetItemFromObject();
4750 test_ShellItemCompare();
4751 test_SHChangeNotify(FALSE
);
4752 test_SHChangeNotify(TRUE
);
4753 test_ShellItemBindToHandler();
4754 test_ShellItemGetAttributes();
4755 test_SHCreateDefaultContextMenu();
4756 test_SHCreateShellFolderView();
4757 test_SHCreateShellFolderViewEx();