1 /* 2 * Unit test of the IShellFolder functions. 3 * 4 * Copyright 2004 Vitaliy Margolen 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 24 #define COBJMACROS 25 #define CONST_VTABLE 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "wtypes.h" 30 #include "shellapi.h" 31 32 33 #include "shlguid.h" 34 #include "shlobj.h" 35 #include "shobjidl.h" 36 #include "shlwapi.h" 37 #include "ocidl.h" 38 #include "oleauto.h" 39 40 #include "wine/heap.h" 41 #include "wine/test.h" 42 43 #include <initguid.h> 44 DEFINE_GUID(IID_IParentAndItem, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36); 45 DEFINE_GUID(CLSID_ShellDocObjView, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37); 46 47 static IMalloc *ppM; 48 49 static HRESULT (WINAPI *pSHCreateItemFromIDList)(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv); 50 static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**); 51 static HRESULT (WINAPI *pSHCreateItemFromRelativeName)(IShellItem*,PCWSTR,IBindCtx*,REFIID,void**); 52 static HRESULT (WINAPI *pSHCreateItemInKnownFolder)(REFKNOWNFOLDERID,DWORD,PCWSTR,REFIID,void **); 53 static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**); 54 static HRESULT (WINAPI *pSHCreateShellItemArray)(LPCITEMIDLIST,IShellFolder*,UINT,LPCITEMIDLIST*,IShellItemArray**); 55 static HRESULT (WINAPI *pSHCreateShellItemArrayFromIDLists)(UINT, PCIDLIST_ABSOLUTE*, IShellItemArray**); 56 static HRESULT (WINAPI *pSHCreateShellItemArrayFromDataObject)(IDataObject*, REFIID, void **); 57 static HRESULT (WINAPI *pSHCreateShellItemArrayFromShellItem)(IShellItem*, REFIID, void **); 58 static HRESULT (WINAPI *pSHGetKnownFolderPath)(REFKNOWNFOLDERID,DWORD,HANDLE,PWSTR*); 59 static HRESULT (WINAPI *pSHGetNameFromIDList)(PCIDLIST_ABSOLUTE,SIGDN,PWSTR*); 60 static HRESULT (WINAPI *pSHGetItemFromDataObject)(IDataObject*,DATAOBJ_GET_ITEM_FLAGS,REFIID,void**); 61 static HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*); 62 static HRESULT (WINAPI *pSHGetItemFromObject)(IUnknown*,REFIID,void**); 63 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); 64 static HRESULT (WINAPI *pSHCreateDefaultContextMenu)(const DEFCONTEXTMENU*,REFIID,void**); 65 static BOOL (WINAPI *pSHGetPathFromIDListEx)(PCIDLIST_ABSOLUTE,WCHAR*,DWORD,GPFIDL_FLAGS); 66 #ifdef __REACTOS__ 67 typedef SHFOLDERCUSTOMSETTINGSW SHFOLDERCUSTOMSETTINGS, *LPSHFOLDERCUSTOMSETTINGS; 68 #endif 69 static HRESULT (WINAPI *pSHGetSetFolderCustomSettings)(LPSHFOLDERCUSTOMSETTINGS,PCWSTR,DWORD); 70 71 static WCHAR *make_wstr(const char *str) 72 { 73 WCHAR *ret; 74 int len; 75 76 if (!str || !str[0]) 77 return NULL; 78 79 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 80 if(!len || len < 0) 81 return NULL; 82 83 ret = heap_alloc(len * sizeof(WCHAR)); 84 if(!ret) 85 return NULL; 86 87 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); 88 return ret; 89 } 90 91 static int strcmp_wa(LPCWSTR strw, const char *stra) 92 { 93 CHAR buf[512]; 94 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); 95 return lstrcmpA(stra, buf); 96 } 97 98 static void init_function_pointers(void) 99 { 100 HMODULE hmod; 101 HRESULT hr; 102 void *ptr; 103 104 hmod = GetModuleHandleA("shell32.dll"); 105 106 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f)) 107 MAKEFUNC(SHCreateItemFromIDList); 108 MAKEFUNC(SHCreateItemFromParsingName); 109 MAKEFUNC(SHCreateItemFromRelativeName); 110 MAKEFUNC(SHCreateItemInKnownFolder); 111 MAKEFUNC(SHCreateShellItem); 112 MAKEFUNC(SHCreateShellItemArray); 113 MAKEFUNC(SHCreateShellItemArrayFromIDLists); 114 MAKEFUNC(SHCreateShellItemArrayFromDataObject); 115 MAKEFUNC(SHCreateShellItemArrayFromShellItem); 116 MAKEFUNC(SHGetKnownFolderPath); 117 MAKEFUNC(SHGetNameFromIDList); 118 MAKEFUNC(SHGetItemFromDataObject); 119 MAKEFUNC(SHGetIDListFromObject); 120 MAKEFUNC(SHGetItemFromObject); 121 MAKEFUNC(SHCreateDefaultContextMenu); 122 MAKEFUNC(SHGetPathFromIDListEx); 123 MAKEFUNC(SHGetSetFolderCustomSettings); 124 #undef MAKEFUNC 125 126 /* test named exports */ 127 ptr = GetProcAddress(hmod, "ILFree"); 128 ok(broken(ptr == 0) || ptr != 0, "expected named export for ILFree\n"); 129 if (ptr) 130 { 131 #define TESTNAMED(f) \ 132 ptr = (void*)GetProcAddress(hmod, #f); \ 133 ok(ptr != 0, "expected named export for " #f "\n"); 134 135 TESTNAMED(ILAppendID); 136 TESTNAMED(ILClone); 137 TESTNAMED(ILCloneFirst); 138 TESTNAMED(ILCombine); 139 TESTNAMED(ILCreateFromPath); 140 TESTNAMED(ILCreateFromPathA); 141 TESTNAMED(ILCreateFromPathW); 142 TESTNAMED(ILFindChild); 143 TESTNAMED(ILFindLastID); 144 TESTNAMED(ILGetNext); 145 TESTNAMED(ILGetSize); 146 TESTNAMED(ILIsEqual); 147 TESTNAMED(ILIsParent); 148 TESTNAMED(ILRemoveLastID); 149 TESTNAMED(ILSaveToStream); 150 #undef TESTNAMED 151 } 152 153 hmod = GetModuleHandleA("kernel32.dll"); 154 pIsWow64Process = (void*)GetProcAddress(hmod, "IsWow64Process"); 155 156 hr = SHGetMalloc(&ppM); 157 ok(hr == S_OK, "SHGetMalloc failed %08x\n", hr); 158 } 159 160 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */ 161 static LPWSTR myPathAddBackslashW( LPWSTR lpszPath ) 162 { 163 size_t iLen; 164 165 if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH) 166 return NULL; 167 168 if (iLen) 169 { 170 lpszPath += iLen; 171 if (lpszPath[-1] != '\\') 172 { 173 *lpszPath++ = '\\'; 174 *lpszPath = '\0'; 175 } 176 } 177 return lpszPath; 178 } 179 180 static struct 181 { 182 WCHAR path[MAX_PATH]; 183 HRESULT hr; 184 int todo; 185 } parse_tests[] = { 186 {{'c',':','\\',0}, S_OK}, 187 {{'c',':','\\','\\',0}, E_INVALIDARG, 1}, 188 {{'c',':','\\','f','a','k','e',0}, 0x80070002}, /* ERROR_FILE_NOT_FOUND */ 189 {{'c',':','f','a','k','e',0}, E_INVALIDARG, 1}, 190 {{'c',':','/',0}, E_INVALIDARG, 1}, 191 {{'c',':','\\','w','i','n','d','o','w','s',0}, S_OK}, 192 {{'c',':','\\','w','i','n','d','o','w','s','\\',0}, S_OK}, 193 {{'c',':','\\','w','i','n','d','o','w','s','\\','.',0}, E_INVALIDARG, 1}, 194 {{'c',':','\\','w','i','n','d','o','w','s','\\','.','.',0}, E_INVALIDARG, 1}, 195 {{'.',0}, E_INVALIDARG, 1}, 196 {{'.','.',0}, E_INVALIDARG, 1}, 197 {{'t','e','s','t',0}, 0x80070002}, 198 {{'t','e','s','t','\\',0}, 0x80070002}, 199 {{'s','u','b','\\','d','i','r',0}, 0x80070002}, 200 {{'s','u','b','/','d','i','r',0}, E_INVALIDARG, 1}, 201 {{'h','t','t','p',':',0}, S_OK, 1}, 202 {{'h','t','t','p',':','t','e','s','t',0}, S_OK, 1}, 203 {{'h','t','t','p',':','\\','t','e','s','t',0}, S_OK, 1}, 204 {{'x','x',':',0}, S_OK, 1}, 205 }; 206 207 static void test_ParseDisplayName(void) 208 { 209 static WCHAR testdirW[] = {'p','a','r','s','e','t','e','s','t',0}; 210 static WCHAR backslashW[] = {'\\',0}; 211 WCHAR buffer[MAX_PATH], buffer2[MAX_PATH]; 212 IShellFolder *desktop; 213 ITEMIDLIST *pidl; 214 HRESULT hr; 215 BOOL bRes; 216 int i; 217 218 hr = SHGetDesktopFolder(&desktop); 219 ok(hr == S_OK, "Expected SHGetDesktopFolder to return S_OK, got 0x%08x\n", hr); 220 221 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, NULL, NULL, &pidl, NULL); 222 ok(hr == E_INVALIDARG, "got %#x\n", hr); 223 224 for (i = 0; i < ARRAY_SIZE(parse_tests); i++) 225 { 226 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, parse_tests[i].path, NULL, &pidl, NULL); 227 todo_wine_if(parse_tests[i].todo) 228 ok(hr == parse_tests[i].hr, "%s: expected %#x, got %#x\n", 229 wine_dbgstr_w(parse_tests[i].path), parse_tests[i].hr, hr); 230 if (SUCCEEDED(hr)) 231 CoTaskMemFree(pidl); 232 } 233 234 /* I thought that perhaps the DesktopFolder's ParseDisplayName would recognize the 235 * path corresponding to CSIDL_PERSONAL and return a CLSID_MyDocuments PIDL. Turns 236 * out it doesn't. The magic seems to happen in the file dialogs, then. */ 237 238 bRes = SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, FALSE); 239 ok(bRes, "SHGetSpecialFolderPath(CSIDL_PERSONAL) failed! %u\n", GetLastError()); 240 241 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, buffer, NULL, &pidl, 0); 242 ok(hr == S_OK, "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr); 243 244 ok(ILFindLastID(pidl)->mkid.abID[0] == 0x31, 245 "Last pidl should be of type PT_FOLDER, but is: %02x\n", 246 ILFindLastID(pidl)->mkid.abID[0]); 247 CoTaskMemFree(pidl); 248 249 /* Relative paths are interpreted relative to the desktop. */ 250 GetTempPathW(ARRAY_SIZE(buffer), buffer); 251 GetLongPathNameW(buffer, buffer, ARRAY_SIZE(buffer)); 252 SetCurrentDirectoryW(buffer); 253 CreateDirectoryW(testdirW, NULL); 254 255 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, testdirW, NULL, &pidl, NULL); 256 ok(hr == 0x80070002, "got %#x\n", hr); 257 258 RemoveDirectoryW(testdirW); 259 260 hr = SHGetSpecialFolderPathW(NULL, buffer, CSIDL_DESKTOP, FALSE); 261 ok(hr == S_FALSE, "got %#x\n", hr); 262 SetCurrentDirectoryW(buffer); 263 CreateDirectoryW(testdirW, NULL); 264 265 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, testdirW, NULL, &pidl, NULL); 266 ok(hr == S_OK, "got %#x\n", hr); 267 268 ok(SHGetPathFromIDListW(pidl, buffer2), "SHGetPathFromIDList failed\n"); 269 lstrcatW(buffer, backslashW); 270 lstrcatW(buffer, testdirW); 271 ok(!lstrcmpW(buffer, buffer2), "expected %s, got %s\n", wine_dbgstr_w(buffer), wine_dbgstr_w(buffer2)); 272 273 RemoveDirectoryW(testdirW); 274 CoTaskMemFree(pidl); 275 276 IShellFolder_Release(desktop); 277 } 278 279 /* creates a file with the specified name for tests */ 280 static void CreateTestFile(const CHAR *name) 281 { 282 HANDLE file; 283 DWORD written; 284 285 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 286 if (file != INVALID_HANDLE_VALUE) 287 { 288 WriteFile(file, name, strlen(name), &written, NULL); 289 WriteFile(file, "\n", strlen("\n"), &written, NULL); 290 CloseHandle(file); 291 } 292 } 293 294 295 /* initializes the tests */ 296 static void CreateFilesFolders(void) 297 { 298 CreateDirectoryA(".\\testdir", NULL); 299 CreateDirectoryA(".\\testdir\\test.txt", NULL); 300 CreateTestFile (".\\testdir\\test1.txt "); 301 CreateTestFile (".\\testdir\\test2.txt "); 302 CreateTestFile (".\\testdir\\test3.txt "); 303 CreateDirectoryA(".\\testdir\\testdir2 ", NULL); 304 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL); 305 } 306 307 /* cleans after tests */ 308 static void Cleanup(void) 309 { 310 DeleteFileA(".\\testdir\\test1.txt"); 311 DeleteFileA(".\\testdir\\test2.txt"); 312 DeleteFileA(".\\testdir\\test3.txt"); 313 RemoveDirectoryA(".\\testdir\\test.txt"); 314 RemoveDirectoryA(".\\testdir\\testdir2\\subdir"); 315 RemoveDirectoryA(".\\testdir\\testdir2"); 316 RemoveDirectoryA(".\\testdir"); 317 } 318 319 320 /* perform test */ 321 static void test_EnumObjects(IShellFolder *iFolder) 322 { 323 IEnumIDList *iEnumList; 324 LPITEMIDLIST newPIDL, idlArr[10]; 325 ULONG NumPIDLs; 326 int i=0, j; 327 HRESULT hr; 328 329 static const WORD iResults [5][5] = 330 { 331 { 0,-1,-1,-1,-1}, 332 { 1, 0,-1,-1,-1}, 333 { 1, 1, 0,-1,-1}, 334 { 1, 1, 1, 0,-1}, 335 { 1, 1, 1, 1, 0} 336 }; 337 338 #define SFGAO_testfor SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CAPABILITYMASK 339 /* Don't test for SFGAO_HASSUBFOLDER since we return real state and native cached */ 340 static const ULONG attrs[5] = 341 { 342 SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR, 343 SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR, 344 SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM, 345 SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM, 346 SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM, 347 }; 348 static const ULONG full_attrs[5] = 349 { 350 SFGAO_CAPABILITYMASK | SFGAO_STORAGE | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR, 351 SFGAO_CAPABILITYMASK | SFGAO_STORAGE | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR, 352 SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM, 353 SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM, 354 SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM, 355 }; 356 357 hr = IShellFolder_EnumObjects(iFolder, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &iEnumList); 358 ok(hr == S_OK, "EnumObjects failed %08x\n", hr); 359 360 /* This is to show that, contrary to what is said on MSDN, on IEnumIDList::Next, 361 * the filesystem shellfolders return S_OK even if less than 'celt' items are 362 * returned (in contrast to S_FALSE). We have to do it in a loop since WinXP 363 * only ever returns a single entry per call. */ 364 while (IEnumIDList_Next(iEnumList, 10-i, &idlArr[i], &NumPIDLs) == S_OK) 365 i += NumPIDLs; 366 ok (i == 5, "i: %d\n", i); 367 368 hr = IEnumIDList_Release(iEnumList); 369 ok(hr == S_OK, "IEnumIDList_Release failed %08x\n", hr); 370 371 /* Sort them first in case of wrong order from system */ 372 for (i=0;i<5;i++) for (j=0;j<5;j++) 373 if ((SHORT)IShellFolder_CompareIDs(iFolder, 0, idlArr[i], idlArr[j]) < 0) 374 { 375 newPIDL = idlArr[i]; 376 idlArr[i] = idlArr[j]; 377 idlArr[j] = newPIDL; 378 } 379 380 for (i=0;i<5;i++) for (j=0;j<5;j++) 381 { 382 hr = IShellFolder_CompareIDs(iFolder, 0, idlArr[i], idlArr[j]); 383 ok(hr == iResults[i][j], "Got %x expected [%d]-[%d]=%x\n", hr, i, j, iResults[i][j]); 384 } 385 386 387 for (i = 0; i < 5; i++) 388 { 389 SFGAOF flags; 390 #define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY 391 /* Native returns all flags no matter what we ask for */ 392 flags = SFGAO_CANCOPY; 393 hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags); 394 flags &= SFGAO_testfor; 395 ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr); 396 ok(flags == (attrs[i]) || 397 flags == ((attrs[i] & ~SFGAO_CAPABILITYMASK) | SFGAO_VISTA), /* Vista and higher */ 398 "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]); 399 400 flags = SFGAO_testfor; 401 hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags); 402 flags &= SFGAO_testfor; 403 ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr); 404 ok(flags == attrs[i], "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]); 405 406 flags = ~0u; 407 hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags); 408 ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr); 409 ok((flags & ~(SFGAO_HASSUBFOLDER|SFGAO_COMPRESSED)) == full_attrs[i], "%d: got %08x expected %08x\n", i, flags, full_attrs[i]); 410 } 411 412 for (i=0;i<5;i++) 413 IMalloc_Free(ppM, idlArr[i]); 414 } 415 416 static void test_BindToObject(void) 417 { 418 HRESULT hr; 419 UINT cChars; 420 IShellFolder *psfDesktop, *psfChild, *psfMyComputer, *psfSystemDir; 421 SHITEMID emptyitem = { 0, { 0 } }; 422 LPITEMIDLIST pidlMyComputer, pidlSystemDir, pidl, pidlEmpty = (LPITEMIDLIST)&emptyitem; 423 WCHAR wszSystemDir[MAX_PATH]; 424 char szSystemDir[MAX_PATH]; 425 char buf[MAX_PATH]; 426 WCHAR path[MAX_PATH]; 427 CHAR pathA[MAX_PATH]; 428 HANDLE hfile; 429 WCHAR wszMyComputer[] = { 430 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-', 431 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 }; 432 static const CHAR filename_html[] = "winetest.html"; 433 static const CHAR filename_txt[] = "winetest.txt"; 434 static const CHAR filename_foo[] = "winetest.foo"; 435 436 /* The following tests shows that BindToObject should fail with E_INVALIDARG if called 437 * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder 438 */ 439 hr = SHGetDesktopFolder(&psfDesktop); 440 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08x\n", hr); 441 if (hr != S_OK) return; 442 443 hr = IShellFolder_BindToObject(psfDesktop, pidlEmpty, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); 444 ok (hr == E_INVALIDARG, "Desktop's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr); 445 446 hr = IShellFolder_BindToObject(psfDesktop, NULL, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); 447 ok (hr == E_INVALIDARG, "Desktop's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr); 448 449 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL); 450 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr); 451 if (hr != S_OK) { 452 IShellFolder_Release(psfDesktop); 453 return; 454 } 455 456 hr = IShellFolder_BindToObject(psfDesktop, pidlMyComputer, NULL, &IID_IShellFolder, (LPVOID*)&psfMyComputer); 457 ok (hr == S_OK, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr); 458 IShellFolder_Release(psfDesktop); 459 IMalloc_Free(ppM, pidlMyComputer); 460 if (hr != S_OK) return; 461 462 hr = IShellFolder_BindToObject(psfMyComputer, pidlEmpty, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); 463 ok (hr == E_INVALIDARG, "MyComputers's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr); 464 465 hr = IShellFolder_BindToObject(psfMyComputer, NULL, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); 466 ok (hr == E_INVALIDARG, "MyComputers's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr); 467 468 cChars = GetSystemDirectoryA(szSystemDir, MAX_PATH); 469 ok (cChars > 0 && cChars < MAX_PATH, "GetSystemDirectoryA failed! LastError: %u\n", GetLastError()); 470 if (cChars == 0 || cChars >= MAX_PATH) { 471 IShellFolder_Release(psfMyComputer); 472 return; 473 } 474 MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wszSystemDir, MAX_PATH); 475 476 hr = IShellFolder_ParseDisplayName(psfMyComputer, NULL, NULL, wszSystemDir, NULL, &pidlSystemDir, NULL); 477 ok (hr == S_OK, "MyComputers's ParseDisplayName failed to parse the SystemDirectory! hr = %08x\n", hr); 478 if (hr != S_OK) { 479 IShellFolder_Release(psfMyComputer); 480 return; 481 } 482 483 hr = IShellFolder_BindToObject(psfMyComputer, pidlSystemDir, NULL, &IID_IShellFolder, (LPVOID*)&psfSystemDir); 484 ok (hr == S_OK, "MyComputer failed to bind to a FileSystem ShellFolder! hr = %08x\n", hr); 485 IShellFolder_Release(psfMyComputer); 486 IMalloc_Free(ppM, pidlSystemDir); 487 if (hr != S_OK) return; 488 489 hr = IShellFolder_BindToObject(psfSystemDir, pidlEmpty, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); 490 ok (hr == E_INVALIDARG, 491 "FileSystem ShellFolder's BindToObject should fail, when called with empty pidl! hr = %08x\n", hr); 492 493 hr = IShellFolder_BindToObject(psfSystemDir, NULL, NULL, &IID_IShellFolder, (LPVOID*)&psfChild); 494 ok (hr == E_INVALIDARG, 495 "FileSystem ShellFolder's BindToObject should fail, when called with NULL pidl! hr = %08x\n", hr); 496 497 IShellFolder_Release(psfSystemDir); 498 499 cChars = GetCurrentDirectoryA(MAX_PATH, buf); 500 if(!cChars) 501 { 502 skip("Failed to get current directory, skipping tests.\n"); 503 return; 504 } 505 if(buf[cChars-1] != '\\') lstrcatA(buf, "\\"); 506 507 SHGetDesktopFolder(&psfDesktop); 508 509 /* Attempt BindToObject on files. */ 510 511 /* .html */ 512 lstrcpyA(pathA, buf); 513 lstrcatA(pathA, filename_html); 514 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 515 if(hfile != INVALID_HANDLE_VALUE) 516 { 517 CloseHandle(hfile); 518 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH); 519 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL); 520 ok(hr == S_OK, "Got 0x%08x\n", hr); 521 if(SUCCEEDED(hr)) 522 { 523 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild); 524 ok(hr == S_OK || 525 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */ 526 "Got 0x%08x\n", hr); 527 if(SUCCEEDED(hr)) 528 { 529 IPersist *pp; 530 hr = IShellFolder_QueryInterface(psfChild, &IID_IPersist, (void**)&pp); 531 ok(hr == S_OK, "Got 0x%08x\n", hr); 532 if(SUCCEEDED(hr)) 533 { 534 CLSID id; 535 hr = IPersist_GetClassID(pp, &id); 536 ok(hr == S_OK, "Got 0x%08x\n", hr); 537 ok(IsEqualIID(&id, &CLSID_ShellDocObjView), "Unexpected classid %s\n", wine_dbgstr_guid(&id)); 538 IPersist_Release(pp); 539 } 540 541 IShellFolder_Release(psfChild); 542 } 543 ILFree(pidl); 544 } 545 DeleteFileA(pathA); 546 } 547 else 548 win_skip("Failed to create .html testfile.\n"); 549 550 /* .txt */ 551 lstrcpyA(pathA, buf); 552 lstrcatA(pathA, filename_txt); 553 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 554 if(hfile != INVALID_HANDLE_VALUE) 555 { 556 CloseHandle(hfile); 557 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH); 558 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL); 559 ok(hr == S_OK, "Got 0x%08x\n", hr); 560 if(SUCCEEDED(hr)) 561 { 562 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild); 563 ok(hr == E_FAIL || /* Vista+ */ 564 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */ 565 "Got 0x%08x\n", hr); 566 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild); 567 ILFree(pidl); 568 } 569 DeleteFileA(pathA); 570 } 571 else 572 win_skip("Failed to create .txt testfile.\n"); 573 574 /* .foo */ 575 lstrcpyA(pathA, buf); 576 lstrcatA(pathA, filename_foo); 577 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 578 if(hfile != INVALID_HANDLE_VALUE) 579 { 580 CloseHandle(hfile); 581 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH); 582 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL); 583 ok(hr == S_OK, "Got 0x%08x\n", hr); 584 if(SUCCEEDED(hr)) 585 { 586 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild); 587 ok(hr == E_FAIL || /* Vista+ */ 588 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */ 589 "Got 0x%08x\n", hr); 590 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild); 591 ILFree(pidl); 592 } 593 DeleteFileA(pathA); 594 } 595 else 596 win_skip("Failed to create .foo testfile.\n"); 597 598 /* And on the desktop */ 599 SHGetSpecialFolderPathA(NULL, pathA, CSIDL_DESKTOP, FALSE); 600 lstrcatA(pathA, "\\"); 601 lstrcatA(pathA, filename_html); 602 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 603 604 CloseHandle(hfile); 605 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH); 606 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL); 607 ok(hr == S_OK, "Got 0x%08x\n", hr); 608 609 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void **)&psfChild); 610 ok(hr == S_OK || 611 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */ 612 "Got 0x%08x\n", hr); 613 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild); 614 ILFree(pidl); 615 if(!DeleteFileA(pathA)) 616 trace("Failed to delete: %d\n", GetLastError()); 617 618 SHGetSpecialFolderPathA(NULL, pathA, CSIDL_DESKTOP, FALSE); 619 lstrcatA(pathA, "\\"); 620 lstrcatA(pathA, filename_foo); 621 hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 622 623 CloseHandle(hfile); 624 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH); 625 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL); 626 ok(hr == S_OK, "Got 0x%08x\n", hr); 627 628 hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void **)&psfChild); 629 ok(hr == E_FAIL || /* Vista+ */ 630 hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), /* XP, W2K3 */ 631 "Got 0x%08x\n", hr); 632 if(SUCCEEDED(hr)) IShellFolder_Release(psfChild); 633 ILFree(pidl); 634 DeleteFileA(pathA); 635 636 IShellFolder_Release(psfDesktop); 637 } 638 639 static void test_GetDisplayName(void) 640 { 641 BOOL result; 642 HRESULT hr; 643 HANDLE hTestFile; 644 WCHAR wszTestFile[MAX_PATH], wszTestFile2[MAX_PATH]; 645 char szTestFile[MAX_PATH], szTestDir[MAX_PATH]; 646 DWORD attr; 647 STRRET strret; 648 LPSHELLFOLDER psfDesktop, psfPersonal; 649 IUnknown *psfFile; 650 SHITEMID emptyitem = { 0, { 0 } }; 651 LPITEMIDLIST pidlTestFile, pidlEmpty = (LPITEMIDLIST)&emptyitem; 652 LPCITEMIDLIST pidlLast; 653 static const CHAR szFileName[] = "winetest.foo"; 654 static const WCHAR wszFileName[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 }; 655 static const WCHAR wszDirName[] = { 'w','i','n','e','t','e','s','t',0 }; 656 657 /* It's ok to use this fixed path. Call will fail anyway. */ 658 WCHAR wszAbsoluteFilename[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 }; 659 LPITEMIDLIST pidlNew; 660 661 /* I'm trying to figure if there is a functional difference between calling 662 * SHGetPathFromIDListW and calling GetDisplayNameOf(SHGDN_FORPARSING) after 663 * binding to the shellfolder. One thing I thought of was that perhaps 664 * SHGetPathFromIDListW would be able to get the path to a file, which does 665 * not exist anymore, while the other method wouldn't. It turns out there's 666 * no functional difference in this respect. 667 */ 668 669 /* First creating a directory in MyDocuments and a file in this directory. */ 670 result = SHGetSpecialFolderPathA(NULL, szTestDir, CSIDL_PERSONAL, FALSE); 671 ok(result, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError()); 672 if (!result) return; 673 674 /* Use ANSI file functions so this works on Windows 9x */ 675 lstrcatA(szTestDir, "\\winetest"); 676 CreateDirectoryA(szTestDir, NULL); 677 attr=GetFileAttributesA(szTestDir); 678 if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY)) 679 { 680 ok(0, "unable to create the '%s' directory\n", szTestDir); 681 return; 682 } 683 684 lstrcpyA(szTestFile, szTestDir); 685 lstrcatA(szTestFile, "\\"); 686 lstrcatA(szTestFile, szFileName); 687 hTestFile = CreateFileA(szTestFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 688 ok((hTestFile != INVALID_HANDLE_VALUE), "CreateFileA failed! Last error: %u\n", GetLastError()); 689 if (hTestFile == INVALID_HANDLE_VALUE) return; 690 CloseHandle(hTestFile); 691 692 /* Getting an itemidlist for the file. */ 693 hr = SHGetDesktopFolder(&psfDesktop); 694 ok(hr == S_OK, "SHGetDesktopFolder failed! hr = %08x\n", hr); 695 if (hr != S_OK) return; 696 697 MultiByteToWideChar(CP_ACP, 0, szTestFile, -1, wszTestFile, MAX_PATH); 698 699 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszTestFile, NULL, &pidlTestFile, NULL); 700 ok(hr == S_OK, "Desktop->ParseDisplayName failed! hr = %08x\n", hr); 701 if (hr != S_OK) { 702 IShellFolder_Release(psfDesktop); 703 return; 704 } 705 706 pidlLast = ILFindLastID(pidlTestFile); 707 ok(pidlLast->mkid.cb >= 76, "Expected pidl length of at least 76, got %d.\n", pidlLast->mkid.cb); 708 if (pidlLast->mkid.cb >= 28) { 709 ok(!lstrcmpA((CHAR*)&pidlLast->mkid.abID[12], szFileName), 710 "Filename should be stored as ansi-string at this position!\n"); 711 } 712 /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */ 713 if (pidlLast->mkid.cb >= 76) { 714 ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName) || 715 (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)) || /* Vista */ 716 (pidlLast->mkid.cb >= 98 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[68], wszFileName)) || /* Win7 */ 717 (pidlLast->mkid.cb >= 102 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[72], wszFileName)), /* Win8 */ 718 "Filename should be stored as wchar-string at this position!\n"); 719 } 720 721 /* It seems as if we cannot bind to regular files on windows, but only directories. 722 */ 723 hr = IShellFolder_BindToObject(psfDesktop, pidlTestFile, NULL, &IID_IUnknown, (VOID**)&psfFile); 724 ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || 725 hr == E_NOTIMPL, /* Vista */ 726 "hr = %08x\n", hr); 727 if (hr == S_OK) { 728 IUnknown_Release(psfFile); 729 } 730 731 /* Some tests for IShellFolder::SetNameOf */ 732 hr = SHBindToParent(pidlTestFile, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); 733 ok(hr == S_OK, "SHBindToParent failed! hr = %08x\n", hr); 734 735 /* The pidl returned through the last parameter of SetNameOf is a simple one. */ 736 hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlLast, wszDirName, SHGDN_NORMAL, &pidlNew); 737 ok (hr == S_OK, "SetNameOf failed! hr = %08x\n", hr); 738 739 ok (((ITEMIDLIST *)((BYTE *)pidlNew + pidlNew->mkid.cb))->mkid.cb == 0, 740 "pidl returned from SetNameOf should be simple!\n"); 741 742 /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf 743 * is implemented on top of SHFileOperation in WinXP. */ 744 hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename, SHGDN_FORPARSING, NULL); 745 ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08x\n", hr); 746 747 /* Rename the file back to its original name. SetNameOf ignores the fact, that the 748 * SHGDN flags specify an absolute path. */ 749 hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL); 750 ok (hr == S_OK, "SetNameOf failed! hr = %08x\n", hr); 751 752 ILFree(pidlNew); 753 IShellFolder_Release(psfPersonal); 754 755 /* Deleting the file and the directory */ 756 DeleteFileA(szTestFile); 757 RemoveDirectoryA(szTestDir); 758 759 /* SHGetPathFromIDListW still works, although the file is not present anymore. */ 760 result = SHGetPathFromIDListW(pidlTestFile, wszTestFile2); 761 ok (result, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError()); 762 ok (!lstrcmpiW(wszTestFile, wszTestFile2), "SHGetPathFromIDListW returns incorrect path!\n"); 763 764 /* SHBindToParent fails, if called with a NULL PIDL. */ 765 hr = SHBindToParent(NULL, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); 766 ok (hr == E_INVALIDARG || broken(hr == E_OUTOFMEMORY) /* XP */, 767 "SHBindToParent(NULL) should fail! hr = %08x\n", hr); 768 769 /* But it succeeds with an empty PIDL. */ 770 hr = SHBindToParent(pidlEmpty, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); 771 ok (hr == S_OK, "SHBindToParent(empty PIDL) should succeed! hr = %08x\n", hr); 772 ok (pidlLast == pidlEmpty, "The last element of an empty PIDL should be the PIDL itself!\n"); 773 if (hr == S_OK) 774 IShellFolder_Release(psfPersonal); 775 776 /* Binding to the folder and querying the display name of the file also works. */ 777 hr = SHBindToParent(pidlTestFile, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); 778 ok (hr == S_OK, "SHBindToParent failed! hr = %08x\n", hr); 779 if (hr != S_OK) { 780 IShellFolder_Release(psfDesktop); 781 return; 782 } 783 784 /* This test shows that Windows doesn't allocate a new pidlLast, but returns a pointer into 785 * pidlTestFile (In accordance with MSDN). */ 786 ok (ILFindLastID(pidlTestFile) == pidlLast, 787 "SHBindToParent doesn't return the last id of the pidl param!\n"); 788 789 hr = IShellFolder_GetDisplayNameOf(psfPersonal, pidlLast, SHGDN_FORPARSING, &strret); 790 ok (hr == S_OK, "Personal->GetDisplayNameOf failed! hr = %08x\n", hr); 791 if (hr != S_OK) { 792 IShellFolder_Release(psfDesktop); 793 IShellFolder_Release(psfPersonal); 794 return; 795 } 796 797 hr = StrRetToBufW(&strret, pidlLast, wszTestFile2, MAX_PATH); 798 ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr); 799 ok (!lstrcmpiW(wszTestFile, wszTestFile2), "GetDisplayNameOf returns incorrect path!\n"); 800 801 ILFree(pidlTestFile); 802 IShellFolder_Release(psfDesktop); 803 IShellFolder_Release(psfPersonal); 804 } 805 806 static void test_CallForAttributes(void) 807 { 808 HKEY hKey; 809 LONG lResult; 810 HRESULT hr; 811 DWORD dwSize; 812 LPSHELLFOLDER psfDesktop; 813 LPITEMIDLIST pidlMyDocuments; 814 DWORD dwAttributes, dwCallForAttributes, dwOrigAttributes, dwOrigCallForAttributes; 815 static const WCHAR wszAttributes[] = { 'A','t','t','r','i','b','u','t','e','s',0 }; 816 static const WCHAR wszCallForAttributes[] = { 817 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 }; 818 static const WCHAR wszMyDocumentsKey[] = { 819 'C','L','S','I','D','\\','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-', 820 '1','1','D','0','-','9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}', 821 '\\','S','h','e','l','l','F','o','l','d','e','r',0 }; 822 WCHAR wszMyDocuments[] = { 823 ':',':','{','4','5','0','D','8','F','B','A','-','A','D','2','5','-','1','1','D','0','-', 824 '9','8','A','8','-','0','8','0','0','3','6','1','B','1','1','0','3','}',0 }; 825 826 /* For the root of a namespace extension, the attributes are not queried by binding 827 * to the object and calling GetAttributesOf. Instead, the attributes are read from 828 * the registry value HKCR/CLSID/{...}/ShellFolder/Attributes. This is documented on MSDN. 829 * 830 * The MyDocuments shellfolder on WinXP has a HKCR/CLSID/{...}/ShellFolder/CallForAttributes 831 * value. It seems that if the folder is queried for one of the flags set in CallForAttributes, 832 * the shell does bind to the folder object and calls GetAttributesOf. This is not documented 833 * on MSDN. This test is meant to document the observed behaviour on WinXP SP2. 834 */ 835 hr = SHGetDesktopFolder(&psfDesktop); 836 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08x\n", hr); 837 if (hr != S_OK) return; 838 839 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyDocuments, NULL, 840 &pidlMyDocuments, NULL); 841 ok (hr == S_OK, 842 "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr); 843 if (hr != S_OK) { 844 IShellFolder_Release(psfDesktop); 845 return; 846 } 847 848 dwAttributes = 0xffffffff; 849 hr = IShellFolder_GetAttributesOf(psfDesktop, 1, 850 (LPCITEMIDLIST*)&pidlMyDocuments, &dwAttributes); 851 ok (hr == S_OK, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr); 852 853 /* We need the following setup (as observed on WinXP SP2), for the tests to make sense. */ 854 ok (dwAttributes & SFGAO_FILESYSTEM, "SFGAO_FILESYSTEM attribute is not set for MyDocuments!\n"); 855 ok (!(dwAttributes & SFGAO_ISSLOW), "SFGAO_ISSLOW attribute is set for MyDocuments!\n"); 856 ok (!(dwAttributes & SFGAO_GHOSTED), "SFGAO_GHOSTED attribute is set for MyDocuments!\n"); 857 858 /* We don't have the MyDocuments shellfolder in wine yet, and thus we don't have the registry 859 * key. So the test will return at this point, if run on wine. 860 */ 861 lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszMyDocumentsKey, 0, KEY_WRITE|KEY_READ, &hKey); 862 ok (lResult == ERROR_SUCCESS || 863 lResult == ERROR_ACCESS_DENIED, 864 "RegOpenKeyEx failed! result: %08x\n", lResult); 865 if (lResult != ERROR_SUCCESS) { 866 if (lResult == ERROR_ACCESS_DENIED) 867 skip("Not enough rights to open the registry key\n"); 868 IMalloc_Free(ppM, pidlMyDocuments); 869 IShellFolder_Release(psfDesktop); 870 return; 871 } 872 873 /* Query MyDocuments' Attributes value, to be able to restore it later. */ 874 dwSize = sizeof(DWORD); 875 lResult = RegQueryValueExW(hKey, wszAttributes, NULL, NULL, (LPBYTE)&dwOrigAttributes, &dwSize); 876 ok (lResult == ERROR_SUCCESS, "RegQueryValueEx failed! result: %08x\n", lResult); 877 if (lResult != ERROR_SUCCESS) { 878 RegCloseKey(hKey); 879 IMalloc_Free(ppM, pidlMyDocuments); 880 IShellFolder_Release(psfDesktop); 881 return; 882 } 883 884 /* Query MyDocuments' CallForAttributes value, to be able to restore it later. */ 885 dwSize = sizeof(DWORD); 886 lResult = RegQueryValueExW(hKey, wszCallForAttributes, NULL, NULL, 887 (LPBYTE)&dwOrigCallForAttributes, &dwSize); 888 ok (lResult == ERROR_SUCCESS, "RegQueryValueEx failed! result: %08x\n", lResult); 889 if (lResult != ERROR_SUCCESS) { 890 RegCloseKey(hKey); 891 IMalloc_Free(ppM, pidlMyDocuments); 892 IShellFolder_Release(psfDesktop); 893 return; 894 } 895 896 /* Define via the Attributes value that MyDocuments attributes are SFGAO_ISSLOW and 897 * SFGAO_GHOSTED and that MyDocuments should be called for the SFGAO_ISSLOW and 898 * SFGAO_FILESYSTEM attributes. */ 899 dwAttributes = SFGAO_ISSLOW|SFGAO_GHOSTED; 900 RegSetValueExW(hKey, wszAttributes, 0, REG_DWORD, (LPBYTE)&dwAttributes, sizeof(DWORD)); 901 dwCallForAttributes = SFGAO_ISSLOW|SFGAO_FILESYSTEM; 902 RegSetValueExW(hKey, wszCallForAttributes, 0, REG_DWORD, 903 (LPBYTE)&dwCallForAttributes, sizeof(DWORD)); 904 905 /* Although it is not set in CallForAttributes, the SFGAO_GHOSTED flag is reset by 906 * GetAttributesOf. It seems that once there is a single attribute queried, for which 907 * CallForAttributes is set, all flags are taken from the GetAttributesOf call and 908 * the flags in Attributes are ignored. 909 */ 910 dwAttributes = SFGAO_ISSLOW|SFGAO_GHOSTED|SFGAO_FILESYSTEM; 911 hr = IShellFolder_GetAttributesOf(psfDesktop, 1, 912 (LPCITEMIDLIST*)&pidlMyDocuments, &dwAttributes); 913 ok (hr == S_OK, "Desktop->GetAttributesOf(MyDocuments) failed! hr = %08x\n", hr); 914 if (hr == S_OK) 915 ok (dwAttributes == SFGAO_FILESYSTEM, 916 "Desktop->GetAttributes(MyDocuments) returned unexpected attributes: %08x\n", 917 dwAttributes); 918 919 /* Restore MyDocuments' original Attributes and CallForAttributes registry values */ 920 RegSetValueExW(hKey, wszAttributes, 0, REG_DWORD, (LPBYTE)&dwOrigAttributes, sizeof(DWORD)); 921 RegSetValueExW(hKey, wszCallForAttributes, 0, REG_DWORD, 922 (LPBYTE)&dwOrigCallForAttributes, sizeof(DWORD)); 923 RegCloseKey(hKey); 924 IMalloc_Free(ppM, pidlMyDocuments); 925 IShellFolder_Release(psfDesktop); 926 } 927 928 static void test_GetAttributesOf(void) 929 { 930 HRESULT hr; 931 LPSHELLFOLDER psfDesktop, psfMyComputer; 932 SHITEMID emptyitem = { 0, { 0 } }; 933 LPCITEMIDLIST pidlEmpty = (LPCITEMIDLIST)&emptyitem; 934 LPITEMIDLIST pidlMyComputer; 935 DWORD dwFlags; 936 static const DWORD desktopFlags = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | 937 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER; 938 static const DWORD myComputerFlags = SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | 939 SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER; 940 WCHAR wszMyComputer[] = { 941 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-', 942 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 }; 943 char cCurrDirA [MAX_PATH] = {0}; 944 WCHAR cCurrDirW [MAX_PATH]; 945 static WCHAR cTestDirW[] = {'t','e','s','t','d','i','r',0}; 946 IShellFolder *IDesktopFolder, *testIShellFolder; 947 ITEMIDLIST *newPIDL; 948 int len; 949 950 hr = SHGetDesktopFolder(&psfDesktop); 951 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08x\n", hr); 952 if (hr != S_OK) return; 953 954 /* The Desktop attributes can be queried with a single empty itemidlist, .. */ 955 dwFlags = 0xffffffff; 956 hr = IShellFolder_GetAttributesOf(psfDesktop, 1, &pidlEmpty, &dwFlags); 957 ok (hr == S_OK, "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr); 958 ok (dwFlags == desktopFlags, "Wrong Desktop attributes: %08x\n", dwFlags); 959 960 /* .. or with no itemidlist at all. */ 961 dwFlags = 0xffffffff; 962 hr = IShellFolder_GetAttributesOf(psfDesktop, 0, NULL, &dwFlags); 963 ok (hr == S_OK, "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr); 964 ok (dwFlags == desktopFlags, "Wrong Desktop attributes: %08x\n", dwFlags); 965 966 /* Testing the attributes of the MyComputer shellfolder */ 967 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL); 968 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr); 969 if (hr != S_OK) { 970 IShellFolder_Release(psfDesktop); 971 return; 972 } 973 974 /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop 975 * folder object. It doesn't do this, if MyComputer is queried directly (see below). 976 */ 977 dwFlags = 0xffffffff; 978 hr = IShellFolder_GetAttributesOf(psfDesktop, 1, (LPCITEMIDLIST*)&pidlMyComputer, &dwFlags); 979 ok (hr == S_OK, "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr); 980 todo_wine 981 ok (dwFlags == (myComputerFlags | SFGAO_CANLINK), "Wrong MyComputer attributes: %08x\n", dwFlags); 982 983 hr = IShellFolder_BindToObject(psfDesktop, pidlMyComputer, NULL, &IID_IShellFolder, (LPVOID*)&psfMyComputer); 984 ok (hr == S_OK, "Desktop failed to bind to MyComputer object! hr = %08x\n", hr); 985 IShellFolder_Release(psfDesktop); 986 IMalloc_Free(ppM, pidlMyComputer); 987 if (hr != S_OK) return; 988 989 hr = IShellFolder_GetAttributesOf(psfMyComputer, 1, &pidlEmpty, &dwFlags); 990 todo_wine 991 ok (hr == E_INVALIDARG, "MyComputer->GetAttributesOf(empty pidl) should fail! hr = %08x\n", hr); 992 993 dwFlags = 0xffffffff; 994 hr = IShellFolder_GetAttributesOf(psfMyComputer, 0, NULL, &dwFlags); 995 ok (hr == S_OK, "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr); 996 todo_wine 997 ok (dwFlags == myComputerFlags, "Wrong MyComputer attributes: %08x\n", dwFlags); 998 999 IShellFolder_Release(psfMyComputer); 1000 1001 GetCurrentDirectoryA(MAX_PATH, cCurrDirA); 1002 len = lstrlenA(cCurrDirA); 1003 1004 if (len == 0) { 1005 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n"); 1006 return; 1007 } 1008 if (len > 3 && cCurrDirA[len-1] == '\\') 1009 cCurrDirA[len-1] = 0; 1010 1011 /* create test directory */ 1012 CreateFilesFolders(); 1013 1014 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH); 1015 1016 hr = SHGetDesktopFolder(&IDesktopFolder); 1017 ok(hr == S_OK, "SHGetDesktopfolder failed %08x\n", hr); 1018 1019 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0); 1020 ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr); 1021 1022 hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder); 1023 ok(hr == S_OK, "BindToObject failed %08x\n", hr); 1024 1025 IMalloc_Free(ppM, newPIDL); 1026 1027 /* get relative PIDL */ 1028 hr = IShellFolder_ParseDisplayName(testIShellFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0); 1029 ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr); 1030 1031 /* test the shell attributes of the test directory using the relative PIDL */ 1032 dwFlags = SFGAO_FOLDER; 1033 hr = IShellFolder_GetAttributesOf(testIShellFolder, 1, (LPCITEMIDLIST*)&newPIDL, &dwFlags); 1034 ok (hr == S_OK, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr); 1035 ok ((dwFlags&SFGAO_FOLDER), "Wrong directory attribute for relative PIDL: %08x\n", dwFlags); 1036 1037 /* free memory */ 1038 IMalloc_Free(ppM, newPIDL); 1039 1040 /* append testdirectory name to path */ 1041 if (cCurrDirA[len-1] == '\\') 1042 cCurrDirA[len-1] = 0; 1043 lstrcatA(cCurrDirA, "\\testdir"); 1044 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH); 1045 1046 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0); 1047 ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr); 1048 1049 /* test the shell attributes of the test directory using the absolute PIDL */ 1050 dwFlags = SFGAO_FOLDER; 1051 hr = IShellFolder_GetAttributesOf(IDesktopFolder, 1, (LPCITEMIDLIST*)&newPIDL, &dwFlags); 1052 ok (hr == S_OK, "Desktop->GetAttributesOf() failed! hr = %08x\n", hr); 1053 ok ((dwFlags&SFGAO_FOLDER), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags); 1054 1055 /* free memory */ 1056 IMalloc_Free(ppM, newPIDL); 1057 1058 IShellFolder_Release(testIShellFolder); 1059 1060 Cleanup(); 1061 1062 IShellFolder_Release(IDesktopFolder); 1063 } 1064 1065 static void test_SHGetPathFromIDList(void) 1066 { 1067 SHITEMID emptyitem = { 0, { 0 } }; 1068 LPCITEMIDLIST pidlEmpty = (LPCITEMIDLIST)&emptyitem; 1069 LPITEMIDLIST pidlMyComputer; 1070 WCHAR wszPath[MAX_PATH], wszDesktop[MAX_PATH]; 1071 BOOL result; 1072 HRESULT hr; 1073 LPSHELLFOLDER psfDesktop; 1074 WCHAR wszMyComputer[] = { 1075 ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-', 1076 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 }; 1077 WCHAR wszFileName[MAX_PATH]; 1078 LPITEMIDLIST pidlTestFile; 1079 HANDLE hTestFile; 1080 STRRET strret; 1081 static WCHAR wszTestFile[] = { 1082 'w','i','n','e','t','e','s','t','.','f','o','o',0 }; 1083 LPITEMIDLIST pidlPrograms; 1084 1085 /* Calling SHGetPathFromIDListW with no pidl should return the empty string */ 1086 wszPath[0] = 'a'; 1087 wszPath[1] = '\0'; 1088 result = SHGetPathFromIDListW(NULL, wszPath); 1089 ok(!result, "Expected failure\n"); 1090 ok(!wszPath[0], "Expected empty string\n"); 1091 1092 /* Calling SHGetPathFromIDListW with an empty pidl should return the desktop folder's path. */ 1093 result = SHGetSpecialFolderPathW(NULL, wszDesktop, CSIDL_DESKTOP, FALSE); 1094 ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError()); 1095 if (!result) return; 1096 1097 result = SHGetPathFromIDListW(pidlEmpty, wszPath); 1098 ok(result, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError()); 1099 if (!result) return; 1100 ok(!lstrcmpiW(wszDesktop, wszPath), "SHGetPathFromIDListW didn't return desktop path for empty pidl!\n"); 1101 1102 /* MyComputer does not map to a filesystem path. SHGetPathFromIDListW should fail. */ 1103 hr = SHGetDesktopFolder(&psfDesktop); 1104 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08x\n", hr); 1105 if (hr != S_OK) return; 1106 1107 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL); 1108 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08x\n", hr); 1109 if (hr != S_OK) { 1110 IShellFolder_Release(psfDesktop); 1111 return; 1112 } 1113 1114 SetLastError(0xdeadbeef); 1115 wszPath[0] = 'a'; 1116 wszPath[1] = '\0'; 1117 result = SHGetPathFromIDListW(pidlMyComputer, wszPath); 1118 ok (!result, "SHGetPathFromIDListW succeeded where it shouldn't!\n"); 1119 ok (GetLastError()==0xdeadbeef || 1120 GetLastError()==ERROR_SUCCESS, /* Vista and higher */ 1121 "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError()); 1122 ok (!wszPath[0], "Expected empty path\n"); 1123 if (result) { 1124 IShellFolder_Release(psfDesktop); 1125 return; 1126 } 1127 1128 IMalloc_Free(ppM, pidlMyComputer); 1129 1130 result = SHGetSpecialFolderPathW(NULL, wszFileName, CSIDL_DESKTOPDIRECTORY, FALSE); 1131 ok(result, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError()); 1132 if (!result) { 1133 IShellFolder_Release(psfDesktop); 1134 return; 1135 } 1136 myPathAddBackslashW(wszFileName); 1137 lstrcatW(wszFileName, wszTestFile); 1138 hTestFile = CreateFileW(wszFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); 1139 ok(hTestFile != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: %u\n", GetLastError()); 1140 if (hTestFile == INVALID_HANDLE_VALUE) { 1141 IShellFolder_Release(psfDesktop); 1142 return; 1143 } 1144 CloseHandle(hTestFile); 1145 1146 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszTestFile, NULL, &pidlTestFile, NULL); 1147 ok (hr == S_OK, "Desktop's ParseDisplayName failed to parse filename hr = %08x\n", hr); 1148 if (hr != S_OK) { 1149 IShellFolder_Release(psfDesktop); 1150 DeleteFileW(wszFileName); 1151 IMalloc_Free(ppM, pidlTestFile); 1152 return; 1153 } 1154 1155 /* This test is to show that the Desktop shellfolder prepends the CSIDL_DESKTOPDIRECTORY 1156 * path for files placed on the desktop, if called with SHGDN_FORPARSING. */ 1157 hr = IShellFolder_GetDisplayNameOf(psfDesktop, pidlTestFile, SHGDN_FORPARSING, &strret); 1158 ok (hr == S_OK, "Desktop's GetDisplayNamfOf failed! hr = %08x\n", hr); 1159 IShellFolder_Release(psfDesktop); 1160 DeleteFileW(wszFileName); 1161 if (hr != S_OK) { 1162 IMalloc_Free(ppM, pidlTestFile); 1163 return; 1164 } 1165 StrRetToBufW(&strret, pidlTestFile, wszPath, MAX_PATH); 1166 ok(0 == lstrcmpW(wszFileName, wszPath), 1167 "Desktop->GetDisplayNameOf(pidlTestFile, SHGDN_FORPARSING) " 1168 "returned incorrect path for file placed on desktop\n"); 1169 1170 result = SHGetPathFromIDListW(pidlTestFile, wszPath); 1171 ok(result, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError()); 1172 ok(0 == lstrcmpW(wszFileName, wszPath), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n"); 1173 1174 if (pSHGetPathFromIDListEx) 1175 { 1176 result = pSHGetPathFromIDListEx(pidlEmpty, wszPath, MAX_PATH, SFGAO_FILESYSTEM); 1177 ok(result, "SHGetPathFromIDListEx failed: %u\n", GetLastError()); 1178 ok(!lstrcmpiW(wszDesktop, wszPath), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n", 1179 wine_dbgstr_w(wszPath), wine_dbgstr_w(wszDesktop)); 1180 1181 result = pSHGetPathFromIDListEx(pidlTestFile, wszPath, MAX_PATH, SFGAO_FILESYSTEM); 1182 ok(result, "SHGetPathFromIDListEx failed: %u\n", GetLastError()); 1183 ok(!lstrcmpiW(wszFileName, wszPath), "Unexpected SHGetPathFromIDListEx result %s, expected %s\n", 1184 wine_dbgstr_w(wszPath), wine_dbgstr_w(wszFileName)); 1185 1186 SetLastError(0xdeadbeef); 1187 memset(wszPath, 0x55, sizeof(wszPath)); 1188 result = pSHGetPathFromIDListEx(pidlTestFile, wszPath, 5, SFGAO_FILESYSTEM); 1189 ok(!result, "SHGetPathFromIDListEx returned: %x(%u)\n", result, GetLastError()); 1190 1191 SetLastError(0xdeadbeef); 1192 memset(wszPath, 0x55, sizeof(wszPath)); 1193 result = pSHGetPathFromIDListEx(pidlEmpty, wszPath, 5, SFGAO_FILESYSTEM); 1194 ok(!result, "SHGetPathFromIDListEx returned: %x(%u)\n", result, GetLastError()); 1195 } 1196 else 1197 win_skip("SHGetPathFromIDListEx not available\n"); 1198 1199 IMalloc_Free(ppM, pidlTestFile); 1200 1201 /* Test if we can get the path from the start menu "program files" PIDL. */ 1202 hr = SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES, &pidlPrograms); 1203 ok(hr == S_OK, "SHGetFolderLocation failed: 0x%08x\n", hr); 1204 1205 SetLastError(0xdeadbeef); 1206 result = SHGetPathFromIDListW(pidlPrograms, wszPath); 1207 IMalloc_Free(ppM, pidlPrograms); 1208 ok(result, "SHGetPathFromIDListW failed\n"); 1209 } 1210 1211 static void test_EnumObjects_and_CompareIDs(void) 1212 { 1213 ITEMIDLIST *newPIDL; 1214 IShellFolder *IDesktopFolder, *testIShellFolder; 1215 char cCurrDirA [MAX_PATH] = {0}; 1216 static const CHAR cTestDirA[] = "\\testdir"; 1217 WCHAR cTestDirW[MAX_PATH]; 1218 int len; 1219 HRESULT hr; 1220 1221 GetCurrentDirectoryA(MAX_PATH, cCurrDirA); 1222 len = lstrlenA(cCurrDirA); 1223 1224 if(len == 0) { 1225 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n"); 1226 return; 1227 } 1228 if(cCurrDirA[len-1] == '\\') 1229 cCurrDirA[len-1] = 0; 1230 1231 lstrcatA(cCurrDirA, cTestDirA); 1232 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cTestDirW, MAX_PATH); 1233 1234 hr = SHGetDesktopFolder(&IDesktopFolder); 1235 ok(hr == S_OK, "SHGetDesktopfolder failed %08x\n", hr); 1236 1237 CreateFilesFolders(); 1238 1239 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0); 1240 ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr); 1241 1242 hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder); 1243 ok(hr == S_OK, "BindToObject failed %08x\n", hr); 1244 1245 test_EnumObjects(testIShellFolder); 1246 1247 IShellFolder_Release(testIShellFolder); 1248 1249 Cleanup(); 1250 1251 IMalloc_Free(ppM, newPIDL); 1252 1253 IShellFolder_Release(IDesktopFolder); 1254 } 1255 1256 /* A simple implementation of an IPropertyBag, which returns fixed values for 1257 * 'Target' and 'Attributes' properties. 1258 */ 1259 static HRESULT WINAPI InitPropertyBag_IPropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, 1260 void **ppvObject) 1261 { 1262 if (!ppvObject) 1263 return E_INVALIDARG; 1264 1265 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPropertyBag, riid)) { 1266 *ppvObject = iface; 1267 } else { 1268 ok (FALSE, "InitPropertyBag asked for unknown interface!\n"); 1269 return E_NOINTERFACE; 1270 } 1271 1272 IPropertyBag_AddRef(iface); 1273 return S_OK; 1274 } 1275 1276 static ULONG WINAPI InitPropertyBag_IPropertyBag_AddRef(IPropertyBag *iface) { 1277 return 2; 1278 } 1279 1280 static ULONG WINAPI InitPropertyBag_IPropertyBag_Release(IPropertyBag *iface) { 1281 return 1; 1282 } 1283 1284 static HRESULT WINAPI InitPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName, 1285 VARIANT *pVar, IErrorLog *pErrorLog) 1286 { 1287 static const WCHAR wszTargetSpecialFolder[] = { 1288 'T','a','r','g','e','t','S','p','e','c','i','a','l','F','o','l','d','e','r',0 }; 1289 static const WCHAR wszTarget[] = { 1290 'T','a','r','g','e','t',0 }; 1291 static const WCHAR wszAttributes[] = { 1292 'A','t','t','r','i','b','u','t','e','s',0 }; 1293 static const WCHAR wszResolveLinkFlags[] = { 1294 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 }; 1295 static const WCHAR wszTargetKnownFolder[] = { 1296 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 }; 1297 static const WCHAR wszCLSID[] = { 1298 'C','L','S','I','D',0 }; 1299 1300 if (!lstrcmpW(pszPropName, wszTargetSpecialFolder)) { 1301 ok(V_VT(pVar) == VT_I4, "Wrong variant type for 'TargetSpecialFolder' property!\n"); 1302 return E_INVALIDARG; 1303 } 1304 1305 if (!lstrcmpW(pszPropName, wszResolveLinkFlags)) 1306 { 1307 ok(V_VT(pVar) == VT_UI4, "Wrong variant type for 'ResolveLinkFlags' property!\n"); 1308 return E_INVALIDARG; 1309 } 1310 1311 if (!lstrcmpW(pszPropName, wszTarget)) { 1312 WCHAR wszPath[MAX_PATH]; 1313 BOOL result; 1314 1315 ok(V_VT(pVar) == VT_BSTR, "Wrong variant type for 'Target' property!\n"); 1316 if (V_VT(pVar) != VT_BSTR) return E_INVALIDARG; 1317 1318 result = SHGetSpecialFolderPathW(NULL, wszPath, CSIDL_DESKTOPDIRECTORY, FALSE); 1319 ok(result, "SHGetSpecialFolderPathW(DESKTOPDIRECTORY) failed! %u\n", GetLastError()); 1320 if (!result) return E_INVALIDARG; 1321 1322 V_BSTR(pVar) = SysAllocString(wszPath); 1323 return S_OK; 1324 } 1325 1326 if (!lstrcmpW(pszPropName, wszAttributes)) { 1327 ok(V_VT(pVar) == VT_UI4, "Wrong variant type for 'Attributes' property!\n"); 1328 if (V_VT(pVar) != VT_UI4) return E_INVALIDARG; 1329 V_UI4(pVar) = SFGAO_FOLDER|SFGAO_HASSUBFOLDER|SFGAO_FILESYSANCESTOR| 1330 SFGAO_CANRENAME|SFGAO_FILESYSTEM; 1331 return S_OK; 1332 } 1333 1334 if (!lstrcmpW(pszPropName, wszTargetKnownFolder)) { 1335 ok(V_VT(pVar) == VT_BSTR, "Wrong variant type for 'TargetKnownFolder' property!\n"); 1336 /* TODO */ 1337 return E_INVALIDARG; 1338 } 1339 1340 if (!lstrcmpW(pszPropName, wszCLSID)) { 1341 ok(V_VT(pVar) == VT_EMPTY, "Wrong variant type for 'CLSID' property!\n"); 1342 /* TODO */ 1343 return E_INVALIDARG; 1344 } 1345 1346 ok(FALSE, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName), V_VT(pVar)); 1347 return E_INVALIDARG; 1348 } 1349 1350 static HRESULT WINAPI InitPropertyBag_IPropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName, 1351 VARIANT *pVar) 1352 { 1353 ok(FALSE, "Unexpected call to IPropertyBag_Write\n"); 1354 return E_NOTIMPL; 1355 } 1356 1357 static const IPropertyBagVtbl InitPropertyBag_IPropertyBagVtbl = { 1358 InitPropertyBag_IPropertyBag_QueryInterface, 1359 InitPropertyBag_IPropertyBag_AddRef, 1360 InitPropertyBag_IPropertyBag_Release, 1361 InitPropertyBag_IPropertyBag_Read, 1362 InitPropertyBag_IPropertyBag_Write 1363 }; 1364 1365 static struct IPropertyBag InitPropertyBag = { 1366 &InitPropertyBag_IPropertyBagVtbl 1367 }; 1368 1369 static void test_FolderShortcut(void) { 1370 IPersistPropertyBag *pPersistPropertyBag; 1371 IShellFolder *pShellFolder, *pDesktopFolder; 1372 IPersistFolder3 *pPersistFolder3; 1373 HRESULT hr; 1374 STRRET strret; 1375 WCHAR wszDesktopPath[MAX_PATH], wszBuffer[MAX_PATH]; 1376 BOOL result; 1377 CLSID clsid; 1378 LPITEMIDLIST pidlCurrentFolder, pidlWineTestFolder, pidlSubFolder; 1379 HKEY hShellExtKey; 1380 WCHAR wszWineTestFolder[] = { 1381 ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-', 1382 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 }; 1383 WCHAR wszShellExtKey[] = { 'S','o','f','t','w','a','r','e','\\', 1384 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 1385 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 1386 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\', 1387 'N','a','m','e','S','p','a','c','e','\\', 1388 '{','9','b','3','5','2','e','b','f','-','2','7','6','5','-','4','5','c','1','-', 1389 'b','4','c','6','-','8','5','c','c','7','f','7','a','b','c','6','4','}',0 }; 1390 1391 WCHAR wszSomeSubFolder[] = { 'S','u','b','F','o','l','d','e','r', 0}; 1392 static const GUID CLSID_UnixDosFolder = 1393 {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}}; 1394 1395 /* These tests basically show, that CLSID_FolderShortcuts are initialized 1396 * via their IPersistPropertyBag interface. And that the target folder 1397 * is taken from the IPropertyBag's 'Target' property. 1398 */ 1399 hr = CoCreateInstance(&CLSID_FolderShortcut, NULL, CLSCTX_INPROC_SERVER, 1400 &IID_IPersistPropertyBag, (LPVOID*)&pPersistPropertyBag); 1401 if (hr == REGDB_E_CLASSNOTREG) { 1402 win_skip("CLSID_FolderShortcut is not implemented\n"); 1403 return; 1404 } 1405 ok (hr == S_OK, "CoCreateInstance failed! hr = 0x%08x\n", hr); 1406 if (hr != S_OK) return; 1407 1408 hr = IPersistPropertyBag_Load(pPersistPropertyBag, &InitPropertyBag, NULL); 1409 ok(hr == S_OK, "IPersistPropertyBag_Load failed! hr = %08x\n", hr); 1410 if (hr != S_OK) { 1411 IPersistPropertyBag_Release(pPersistPropertyBag); 1412 return; 1413 } 1414 1415 hr = IPersistPropertyBag_QueryInterface(pPersistPropertyBag, &IID_IShellFolder, 1416 (LPVOID*)&pShellFolder); 1417 IPersistPropertyBag_Release(pPersistPropertyBag); 1418 ok(hr == S_OK, "IPersistPropertyBag_QueryInterface(IShellFolder) failed! hr = %08x\n", hr); 1419 if (hr != S_OK) return; 1420 1421 hr = IShellFolder_GetDisplayNameOf(pShellFolder, NULL, SHGDN_FORPARSING, &strret); 1422 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* win10 */, 1423 "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr); 1424 if (hr != S_OK) { 1425 IShellFolder_Release(pShellFolder); 1426 return; 1427 } 1428 1429 result = SHGetSpecialFolderPathW(NULL, wszDesktopPath, CSIDL_DESKTOPDIRECTORY, FALSE); 1430 ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError()); 1431 if (!result) return; 1432 1433 StrRetToBufW(&strret, NULL, wszBuffer, MAX_PATH); 1434 ok(!lstrcmpiW(wszDesktopPath, wszBuffer), "FolderShortcut returned incorrect folder!\n"); 1435 1436 hr = IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder3, (LPVOID*)&pPersistFolder3); 1437 IShellFolder_Release(pShellFolder); 1438 ok(hr == S_OK, "IShellFolder_QueryInterface(IID_IPersistFolder3 failed! hr = 0x%08x\n", hr); 1439 if (hr != S_OK) return; 1440 1441 hr = IPersistFolder3_GetClassID(pPersistFolder3, &clsid); 1442 ok(hr == S_OK, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr); 1443 ok(IsEqualCLSID(&clsid, &CLSID_FolderShortcut), "Unexpected CLSID!\n"); 1444 1445 hr = IPersistFolder3_GetCurFolder(pPersistFolder3, &pidlCurrentFolder); 1446 todo_wine ok(hr == S_FALSE, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr); 1447 ok(!pidlCurrentFolder, "IPersistFolder3_GetCurFolder should return a NULL pidl!\n"); 1448 1449 /* For FolderShortcut objects, the Initialize method initialized the folder's position in the 1450 * shell namespace. The target folder, read from the property bag above, remains untouched. 1451 * The following tests show this: The itemidlist for some imaginary shellfolder object 1452 * is created and the FolderShortcut is initialized with it. GetCurFolder now returns this 1453 * itemidlist, but GetDisplayNameOf still returns the path from above. 1454 */ 1455 hr = SHGetDesktopFolder(&pDesktopFolder); 1456 ok (hr == S_OK, "SHGetDesktopFolder failed! hr = %08x\n", hr); 1457 if (hr != S_OK) return; 1458 1459 /* Temporarily register WineTestFolder as a shell namespace extension at the Desktop. 1460 * Otherwise ParseDisplayName fails on WinXP with E_INVALIDARG */ 1461 RegCreateKeyW(HKEY_CURRENT_USER, wszShellExtKey, &hShellExtKey); 1462 RegCloseKey(hShellExtKey); 1463 hr = IShellFolder_ParseDisplayName(pDesktopFolder, NULL, NULL, wszWineTestFolder, NULL, 1464 &pidlWineTestFolder, NULL); 1465 RegDeleteKeyW(HKEY_CURRENT_USER, wszShellExtKey); 1466 IShellFolder_Release(pDesktopFolder); 1467 ok (hr == S_OK, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr); 1468 if (hr != S_OK) return; 1469 1470 hr = IPersistFolder3_Initialize(pPersistFolder3, pidlWineTestFolder); 1471 ok (hr == S_OK, "IPersistFolder3::Initialize failed! hr = %08x\n", hr); 1472 if (hr != S_OK) { 1473 IPersistFolder3_Release(pPersistFolder3); 1474 ILFree(pidlWineTestFolder); 1475 return; 1476 } 1477 1478 hr = IPersistFolder3_GetCurFolder(pPersistFolder3, &pidlCurrentFolder); 1479 ok(hr == S_OK, "IPersistFolder3_GetCurFolder failed! hr=0x%08x\n", hr); 1480 ok(ILIsEqual(pidlCurrentFolder, pidlWineTestFolder), 1481 "IPersistFolder3_GetCurFolder should return pidlWineTestFolder!\n"); 1482 ILFree(pidlCurrentFolder); 1483 ILFree(pidlWineTestFolder); 1484 1485 hr = IPersistFolder3_QueryInterface(pPersistFolder3, &IID_IShellFolder, (LPVOID*)&pShellFolder); 1486 IPersistFolder3_Release(pPersistFolder3); 1487 ok(hr == S_OK, "IPersistFolder3_QueryInterface(IShellFolder) failed! hr = %08x\n", hr); 1488 if (hr != S_OK) return; 1489 1490 hr = IShellFolder_GetDisplayNameOf(pShellFolder, NULL, SHGDN_FORPARSING, &strret); 1491 ok(hr == S_OK, "IShellFolder_GetDisplayNameOf(NULL) failed! hr = %08x\n", hr); 1492 if (hr != S_OK) { 1493 IShellFolder_Release(pShellFolder); 1494 return; 1495 } 1496 1497 StrRetToBufW(&strret, NULL, wszBuffer, MAX_PATH); 1498 ok(!lstrcmpiW(wszDesktopPath, wszBuffer), "FolderShortcut returned incorrect folder!\n"); 1499 1500 /* Next few lines are meant to show that children of FolderShortcuts are not FolderShortcuts, 1501 * but ShellFSFolders. */ 1502 myPathAddBackslashW(wszDesktopPath); 1503 lstrcatW(wszDesktopPath, wszSomeSubFolder); 1504 if (!CreateDirectoryW(wszDesktopPath, NULL)) { 1505 IShellFolder_Release(pShellFolder); 1506 return; 1507 } 1508 1509 hr = IShellFolder_ParseDisplayName(pShellFolder, NULL, NULL, wszSomeSubFolder, NULL, 1510 &pidlSubFolder, NULL); 1511 RemoveDirectoryW(wszDesktopPath); 1512 ok (hr == S_OK, "IShellFolder::ParseDisplayName failed! hr = %08x\n", hr); 1513 if (hr != S_OK) { 1514 IShellFolder_Release(pShellFolder); 1515 return; 1516 } 1517 1518 hr = IShellFolder_BindToObject(pShellFolder, pidlSubFolder, NULL, &IID_IPersistFolder3, 1519 (LPVOID*)&pPersistFolder3); 1520 IShellFolder_Release(pShellFolder); 1521 ILFree(pidlSubFolder); 1522 ok (hr == S_OK, "IShellFolder::BindToObject failed! hr = %08x\n", hr); 1523 if (hr != S_OK) 1524 return; 1525 1526 /* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint 1527 * a little bit and also allow CLSID_UnixDosFolder. */ 1528 hr = IPersistFolder3_GetClassID(pPersistFolder3, &clsid); 1529 ok(hr == S_OK, "IPersistFolder3_GetClassID failed! hr=0x%08x\n", hr); 1530 ok(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder) || IsEqualCLSID(&clsid, &CLSID_UnixDosFolder), 1531 "IPersistFolder3::GetClassID returned unexpected CLSID!\n"); 1532 1533 IPersistFolder3_Release(pPersistFolder3); 1534 } 1535 1536 #include "pshpack1.h" 1537 struct FileStructA { 1538 BYTE type; 1539 BYTE dummy; 1540 DWORD dwFileSize; 1541 WORD uFileDate; /* In our current implementation this is */ 1542 WORD uFileTime; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastWriteTime) */ 1543 WORD uFileAttribs; 1544 CHAR szName[1]; 1545 }; 1546 1547 struct FileStructW { 1548 WORD cbLen; /* Length of this element. */ 1549 BYTE abFooBar1[6]; /* Beyond any recognition. */ 1550 WORD uDate; /* FileTimeToDosDate(WIN32_FIND_DATA->ftCreationTime)? */ 1551 WORD uTime; /* (this is currently speculation) */ 1552 WORD uDate2; /* FileTimeToDosDate(WIN32_FIND_DATA->ftLastAccessTime)? */ 1553 WORD uTime2; /* (this is currently speculation) */ 1554 BYTE abFooBar2[4]; /* Beyond any recognition. */ 1555 WCHAR wszName[1]; /* The long filename in unicode. */ 1556 /* Just for documentation: Right after the unicode string: */ 1557 WORD cbOffset; /* FileStructW's offset from the beginning of the SHITMEID. 1558 * SHITEMID->cb == uOffset + cbLen */ 1559 }; 1560 #include "poppack.h" 1561 1562 static void test_ITEMIDLIST_format(void) { 1563 WCHAR wszPersonal[MAX_PATH]; 1564 LPSHELLFOLDER psfDesktop, psfPersonal; 1565 LPITEMIDLIST pidlPersonal, pidlFile; 1566 HANDLE hFile; 1567 HRESULT hr; 1568 BOOL bResult; 1569 WCHAR wszFile[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 }, 1570 { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } }; 1571 int i; 1572 1573 bResult = SHGetSpecialFolderPathW(NULL, wszPersonal, CSIDL_PERSONAL, FALSE); 1574 ok(bResult, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError()); 1575 if (!bResult) return; 1576 1577 SetLastError(0xdeadbeef); 1578 bResult = SetCurrentDirectoryW(wszPersonal); 1579 if (!bResult && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { 1580 win_skip("Most W-calls are not implemented\n"); 1581 return; 1582 } 1583 ok(bResult, "SetCurrentDirectory failed! Last error: %u\n", GetLastError()); 1584 if (!bResult) return; 1585 1586 hr = SHGetDesktopFolder(&psfDesktop); 1587 ok(hr == S_OK, "SHGetDesktopFolder failed! hr: %08x\n", hr); 1588 if (hr != S_OK) return; 1589 1590 hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszPersonal, NULL, &pidlPersonal, NULL); 1591 ok(hr == S_OK, "psfDesktop->ParseDisplayName failed! hr = %08x\n", hr); 1592 if (hr != S_OK) { 1593 IShellFolder_Release(psfDesktop); 1594 return; 1595 } 1596 1597 hr = IShellFolder_BindToObject(psfDesktop, pidlPersonal, NULL, &IID_IShellFolder, 1598 (LPVOID*)&psfPersonal); 1599 IShellFolder_Release(psfDesktop); 1600 ILFree(pidlPersonal); 1601 ok(hr == S_OK, "psfDesktop->BindToObject failed! hr = %08x\n", hr); 1602 if (hr != S_OK) return; 1603 1604 for (i=0; i<3; i++) { 1605 CHAR szFile[MAX_PATH]; 1606 struct FileStructA *pFileStructA; 1607 WORD cbOffset; 1608 1609 WideCharToMultiByte(CP_ACP, 0, wszFile[i], -1, szFile, MAX_PATH, NULL, NULL); 1610 1611 hFile = CreateFileW(wszFile[i], GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_WRITE_THROUGH, NULL); 1612 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed! (%u)\n", GetLastError()); 1613 if (hFile == INVALID_HANDLE_VALUE) { 1614 IShellFolder_Release(psfPersonal); 1615 return; 1616 } 1617 CloseHandle(hFile); 1618 1619 hr = IShellFolder_ParseDisplayName(psfPersonal, NULL, NULL, wszFile[i], NULL, &pidlFile, NULL); 1620 DeleteFileW(wszFile[i]); 1621 ok(hr == S_OK, "psfPersonal->ParseDisplayName failed! hr: %08x\n", hr); 1622 if (hr != S_OK) { 1623 IShellFolder_Release(psfPersonal); 1624 return; 1625 } 1626 1627 pFileStructA = (struct FileStructA *)pidlFile->mkid.abID; 1628 ok(pFileStructA->type == 0x32, "PIDLTYPE should be 0x32!\n"); 1629 ok(pFileStructA->dummy == 0x00, "Dummy Byte should be 0x00!\n"); 1630 ok(pFileStructA->dwFileSize == 0, "Filesize should be zero!\n"); 1631 1632 if (i < 2) /* First two file names are already in valid 8.3 format */ 1633 ok(!strcmp(szFile, (CHAR*)&pidlFile->mkid.abID[12]), "Wrong file name!\n"); 1634 else 1635 /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably 1636 * can't implement this correctly, since unix filesystems don't support 1637 * this nasty short/long filename stuff. So we'll probably stay with our 1638 * current habit of storing the long filename here, which seems to work 1639 * just fine. */ 1640 todo_wine 1641 ok(pidlFile->mkid.abID[18] == '~', "Should be derived 8.3 name!\n"); 1642 1643 if (i == 0) /* First file name has an even number of chars. No need for alignment. */ 1644 ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] != '\0', 1645 "Alignment byte, where there shouldn't be!\n"); 1646 1647 if (i == 1) /* Second file name has an uneven number of chars => alignment byte */ 1648 ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] == '\0', 1649 "There should be an alignment byte, but isn't!\n"); 1650 1651 /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */ 1652 cbOffset = *(WORD*)(((LPBYTE)pidlFile)+pidlFile->mkid.cb-sizeof(WORD)); 1653 ok ((cbOffset >= sizeof(struct FileStructA) && 1654 cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW)), 1655 "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset); 1656 1657 if (cbOffset >= sizeof(struct FileStructA) && 1658 cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW)) 1659 { 1660 struct FileStructW *pFileStructW = (struct FileStructW *)(((LPBYTE)pidlFile)+cbOffset); 1661 WCHAR *name = pFileStructW->wszName; 1662 1663 ok(pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen, 1664 "FileStructW's offset and length should add up to the PIDL's length!\n"); 1665 1666 if (pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen) { 1667 /* Since we just created the file, time of creation, 1668 * time of last access and time of last write access just be the same. 1669 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly 1670 * after the first run. I do remember something with NTFS keeping the creation time 1671 * if a file is deleted and then created again within a couple of seconds or so. 1672 * Might be the reason. */ 1673 ok (pFileStructA->uFileDate == pFileStructW->uDate && 1674 pFileStructA->uFileTime == pFileStructW->uTime, 1675 "Last write time should match creation time!\n"); 1676 1677 /* On FAT filesystems the last access time is midnight 1678 local time, so the values of uDate2 and uTime2 will 1679 depend on the local timezone. If the times are exactly 1680 equal then the dates should be identical for both FAT 1681 and NTFS as no timezone is more than 1 day away from UTC. 1682 */ 1683 if (pFileStructA->uFileTime == pFileStructW->uTime2) 1684 { 1685 ok (pFileStructA->uFileDate == pFileStructW->uDate2, 1686 "Last write date and time should match last access date and time!\n"); 1687 } 1688 else 1689 { 1690 /* Filesystem may be FAT. Check date within 1 day 1691 and seconds are zero. */ 1692 trace ("Filesystem may be FAT. Performing less strict atime test.\n"); 1693 ok ((pFileStructW->uTime2 & 0x1F) == 0, 1694 "Last access time on FAT filesystems should have zero seconds.\n"); 1695 /* TODO: Perform check for date being within one day.*/ 1696 } 1697 1698 ok (!lstrcmpW(wszFile[i], name) || 1699 !lstrcmpW(wszFile[i], name + 9) || /* Vista */ 1700 !lstrcmpW(wszFile[i], name + 11) || /* Win7 */ 1701 !lstrcmpW(wszFile[i], name + 13), /* Win8 */ 1702 "The filename should be stored in unicode at this position!\n"); 1703 } 1704 } 1705 1706 ILFree(pidlFile); 1707 } 1708 1709 IShellFolder_Release(psfPersonal); 1710 } 1711 1712 static void test_SHGetFolderPathA(void) 1713 { 1714 static const BOOL is_win64 = sizeof(void *) > sizeof(int); 1715 BOOL is_wow64; 1716 char path[MAX_PATH]; 1717 char path_x86[MAX_PATH]; 1718 char path_key[MAX_PATH]; 1719 HRESULT hr; 1720 HKEY key; 1721 1722 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE; 1723 1724 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES, 0, SHGFP_TYPE_CURRENT, path ); 1725 ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr ); 1726 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86, 0, SHGFP_TYPE_CURRENT, path_x86 ); 1727 if (hr == E_FAIL) 1728 { 1729 win_skip( "Program Files (x86) not supported\n" ); 1730 return; 1731 } 1732 ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr ); 1733 if (is_win64) 1734 { 1735 ok( lstrcmpiA( path, path_x86 ), "paths are identical '%s'\n", path ); 1736 ok( strstr( path, "x86" ) == NULL, "64-bit path '%s' contains x86\n", path ); 1737 ok( strstr( path_x86, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path_x86 ); 1738 } 1739 else 1740 { 1741 ok( !lstrcmpiA( path, path_x86 ), "paths differ '%s' != '%s'\n", path, path_x86 ); 1742 if (is_wow64) 1743 ok( strstr( path, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path ); 1744 else 1745 ok( strstr( path, "x86" ) == NULL, "32-bit path '%s' contains x86\n", path ); 1746 } 1747 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &key )) 1748 { 1749 DWORD type, count = sizeof(path_x86); 1750 if (!RegQueryValueExA( key, "ProgramFilesDir (x86)", NULL, &type, (BYTE *)path_key, &count )) 1751 { 1752 ok( is_win64 || is_wow64, "ProgramFilesDir (x86) exists on 32-bit setup\n" ); 1753 ok( !lstrcmpiA( path_key, path_x86 ), "paths differ '%s' != '%s'\n", path_key, path_x86 ); 1754 } 1755 else ok( !is_win64 && !is_wow64, "ProgramFilesDir (x86) should exist on 64-bit setup\n" ); 1756 RegCloseKey( key ); 1757 } 1758 1759 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON, 0, SHGFP_TYPE_CURRENT, path ); 1760 ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr ); 1761 hr = SHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86, 0, SHGFP_TYPE_CURRENT, path_x86 ); 1762 if (hr == E_FAIL) 1763 { 1764 win_skip( "Common Files (x86) not supported\n" ); 1765 return; 1766 } 1767 ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr ); 1768 if (is_win64) 1769 { 1770 ok( lstrcmpiA( path, path_x86 ), "paths are identical '%s'\n", path ); 1771 ok( strstr( path, "x86" ) == NULL, "64-bit path '%s' contains x86\n", path ); 1772 ok( strstr( path_x86, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path_x86 ); 1773 } 1774 else 1775 { 1776 ok( !lstrcmpiA( path, path_x86 ), "paths differ '%s' != '%s'\n", path, path_x86 ); 1777 if (is_wow64) 1778 ok( strstr( path, "x86" ) != NULL, "32-bit path '%s' doesn't contain x86\n", path ); 1779 else 1780 ok( strstr( path, "x86" ) == NULL, "32-bit path '%s' contains x86\n", path ); 1781 } 1782 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &key )) 1783 { 1784 DWORD type, count = sizeof(path_x86); 1785 if (!RegQueryValueExA( key, "CommonFilesDir (x86)", NULL, &type, (BYTE *)path_key, &count )) 1786 { 1787 ok( is_win64 || is_wow64, "CommonFilesDir (x86) exists on 32-bit setup\n" ); 1788 ok( !lstrcmpiA( path_key, path_x86 ), "paths differ '%s' != '%s'\n", path_key, path_x86 ); 1789 } 1790 else ok( !is_win64 && !is_wow64, "CommonFilesDir (x86) should exist on 64-bit setup\n" ); 1791 } 1792 } 1793 1794 static void test_SHGetFolderPathAndSubDirA(void) 1795 { 1796 HRESULT ret; 1797 BOOL delret; 1798 DWORD dwret; 1799 int i; 1800 static const char wine[] = "wine"; 1801 static const char winetemp[] = "wine\\temp"; 1802 static char appdata[MAX_PATH]; 1803 static char testpath[MAX_PATH]; 1804 static char toolongpath[MAX_PATH+1]; 1805 1806 if(FAILED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdata))) 1807 { 1808 win_skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n"); 1809 return; 1810 } 1811 1812 sprintf(testpath, "%s\\%s", appdata, winetemp); 1813 delret = RemoveDirectoryA(testpath); 1814 if(!delret && (ERROR_PATH_NOT_FOUND != GetLastError()) ) { 1815 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath, GetLastError()); 1816 return; 1817 } 1818 1819 sprintf(testpath, "%s\\%s", appdata, wine); 1820 delret = RemoveDirectoryA(testpath); 1821 if(!delret && (ERROR_PATH_NOT_FOUND != GetLastError()) && (ERROR_FILE_NOT_FOUND != GetLastError())) { 1822 win_skip("RemoveDirectoryA(%s) failed with error %u\n", testpath, GetLastError()); 1823 return; 1824 } 1825 1826 /* test invalid second parameter */ 1827 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | 0xff, NULL, SHGFP_TYPE_CURRENT, wine, testpath); 1828 ok(E_INVALIDARG == ret, "expected E_INVALIDARG, got %x\n", ret); 1829 1830 /* test fourth parameter */ 1831 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, 2, winetemp, testpath); 1832 switch(ret) { 1833 case S_OK: /* winvista */ 1834 ok(!strncmp(appdata, testpath, strlen(appdata)), 1835 "expected %s to start with %s\n", testpath, appdata); 1836 ok(!lstrcmpA(&testpath[1 + strlen(appdata)], winetemp), 1837 "expected %s to end with %s\n", testpath, winetemp); 1838 break; 1839 case E_INVALIDARG: /* winxp, win2k3 */ 1840 break; 1841 default: 1842 ok(0, "expected S_OK or E_INVALIDARG, got %x\n", ret); 1843 } 1844 1845 /* test fifth parameter */ 1846 testpath[0] = '\0'; 1847 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, NULL, testpath); 1848 ok(S_OK == ret, "expected S_OK, got %x\n", ret); 1849 ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath); 1850 1851 testpath[0] = '\0'; 1852 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, "", testpath); 1853 ok(S_OK == ret, "expected S_OK, got %x\n", ret); 1854 ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath); 1855 1856 testpath[0] = '\0'; 1857 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, "\\", testpath); 1858 ok(S_OK == ret, "expected S_OK, got %x\n", ret); 1859 ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath); 1860 1861 for(i=0; i< MAX_PATH; i++) 1862 toolongpath[i] = '0' + i % 10; 1863 toolongpath[MAX_PATH] = '\0'; 1864 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, toolongpath, testpath); 1865 ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) == ret, 1866 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), ret); 1867 1868 testpath[0] = '\0'; 1869 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wine, NULL); 1870 ok((S_OK == ret) || (E_INVALIDARG == ret), "expected S_OK or E_INVALIDARG, got %x\n", ret); 1871 1872 /* test a not existing path */ 1873 testpath[0] = '\0'; 1874 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, winetemp, testpath); 1875 ok(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == ret, 1876 "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), ret); 1877 1878 /* create a directory inside a not existing directory */ 1879 testpath[0] = '\0'; 1880 ret = SHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_CREATE | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, winetemp, testpath); 1881 ok(S_OK == ret, "expected S_OK, got %x\n", ret); 1882 ok(!strncmp(appdata, testpath, strlen(appdata)), 1883 "expected %s to start with %s\n", testpath, appdata); 1884 ok(!lstrcmpA(&testpath[1 + strlen(appdata)], winetemp), 1885 "expected %s to end with %s\n", testpath, winetemp); 1886 dwret = GetFileAttributesA(testpath); 1887 ok(FILE_ATTRIBUTE_DIRECTORY | dwret, "expected %x to contain FILE_ATTRIBUTE_DIRECTORY\n", dwret); 1888 1889 /* cleanup */ 1890 sprintf(testpath, "%s\\%s", appdata, winetemp); 1891 RemoveDirectoryA(testpath); 1892 sprintf(testpath, "%s\\%s", appdata, wine); 1893 RemoveDirectoryA(testpath); 1894 } 1895 1896 static void test_LocalizedNames(void) 1897 { 1898 static char cCurrDirA[MAX_PATH]; 1899 WCHAR cCurrDirW[MAX_PATH], tempbufW[25]; 1900 IShellFolder *IDesktopFolder, *testIShellFolder; 1901 ITEMIDLIST *newPIDL; 1902 int len; 1903 HRESULT hr; 1904 static char resourcefile[MAX_PATH]; 1905 DWORD res; 1906 HANDLE file; 1907 STRRET strret; 1908 BOOL ret; 1909 1910 static const char desktopini_contents1[] = 1911 "[.ShellClassInfo]\r\n" 1912 "LocalizedResourceName=@"; 1913 static const char desktopini_contents2[] = 1914 ",-1\r\n"; 1915 static WCHAR foldernameW[] = {'t','e','s','t','f','o','l','d','e','r',0}; 1916 static const WCHAR folderdisplayW[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0}; 1917 1918 /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */ 1919 CreateDirectoryA(".\\testfolder", NULL); 1920 1921 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM); 1922 1923 GetModuleFileNameA(NULL, resourcefile, MAX_PATH); 1924 1925 file = CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE, 0, NULL, 1926 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1927 ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed %i\n", GetLastError()); 1928 ret = WriteFile(file, desktopini_contents1, strlen(desktopini_contents1), &res, NULL) && 1929 WriteFile(file, resourcefile, strlen(resourcefile), &res, NULL) && 1930 WriteFile(file, desktopini_contents2, strlen(desktopini_contents2), &res, NULL); 1931 ok(ret, "WriteFile failed %i\n", GetLastError()); 1932 CloseHandle(file); 1933 1934 /* get IShellFolder for parent */ 1935 GetCurrentDirectoryA(MAX_PATH, cCurrDirA); 1936 len = lstrlenA(cCurrDirA); 1937 1938 if (len == 0) { 1939 win_skip("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n"); 1940 goto cleanup; 1941 } 1942 if(cCurrDirA[len-1] == '\\') 1943 cCurrDirA[len-1] = 0; 1944 1945 MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH); 1946 1947 hr = SHGetDesktopFolder(&IDesktopFolder); 1948 ok(hr == S_OK, "SHGetDesktopfolder failed %08x\n", hr); 1949 1950 hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0); 1951 ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr); 1952 1953 hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder); 1954 ok(hr == S_OK, "BindToObject failed %08x\n", hr); 1955 1956 IMalloc_Free(ppM, newPIDL); 1957 1958 /* windows reads the display name from the resource */ 1959 hr = IShellFolder_ParseDisplayName(testIShellFolder, NULL, NULL, foldernameW, NULL, &newPIDL, 0); 1960 ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr); 1961 1962 hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER, &strret); 1963 ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr); 1964 1965 hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW)); 1966 ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr); 1967 todo_wine 1968 ok (!lstrcmpiW(tempbufW, folderdisplayW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW)); 1969 1970 /* editing name is also read from the resource */ 1971 hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FOREDITING, &strret); 1972 ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr); 1973 1974 hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW)); 1975 ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr); 1976 todo_wine 1977 ok (!lstrcmpiW(tempbufW, folderdisplayW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW)); 1978 1979 /* parsing name is unchanged */ 1980 hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FORPARSING, &strret); 1981 ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr); 1982 1983 hr = StrRetToBufW(&strret, newPIDL, tempbufW, ARRAY_SIZE(tempbufW)); 1984 ok (hr == S_OK, "StrRetToBufW failed! hr = %08x\n", hr); 1985 ok (!lstrcmpiW(tempbufW, foldernameW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW)); 1986 1987 IShellFolder_Release(IDesktopFolder); 1988 IShellFolder_Release(testIShellFolder); 1989 1990 IMalloc_Free(ppM, newPIDL); 1991 1992 cleanup: 1993 DeleteFileA(".\\testfolder\\desktop.ini"); 1994 SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM); 1995 RemoveDirectoryA(".\\testfolder"); 1996 } 1997 1998 static void test_SHCreateShellItem(void) 1999 { 2000 IShellItem *shellitem, *shellitem2; 2001 IPersistIDList *persistidl; 2002 LPITEMIDLIST pidl_cwd=NULL, pidl_testfile, pidl_abstestfile, pidl_test, pidl_desktop; 2003 HRESULT ret; 2004 char curdirA[MAX_PATH]; 2005 WCHAR curdirW[MAX_PATH]; 2006 WCHAR fnbufW[MAX_PATH]; 2007 IShellFolder *desktopfolder=NULL, *currentfolder=NULL; 2008 static WCHAR testfileW[] = {'t','e','s','t','f','i','l','e',0}; 2009 2010 GetCurrentDirectoryA(MAX_PATH, curdirA); 2011 2012 if (!pSHCreateShellItem) 2013 { 2014 win_skip("SHCreateShellItem isn't available\n"); 2015 return; 2016 } 2017 2018 if (!curdirA[0]) 2019 { 2020 win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n"); 2021 return; 2022 } 2023 2024 ret = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop); 2025 ok(ret == S_OK, "Got 0x%08x\n", ret); 2026 2027 MultiByteToWideChar(CP_ACP, 0, curdirA, -1, curdirW, MAX_PATH); 2028 2029 ret = SHGetDesktopFolder(&desktopfolder); 2030 ok(SUCCEEDED(ret), "SHGetShellFolder returned %x\n", ret); 2031 2032 ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, curdirW, NULL, &pidl_cwd, NULL); 2033 ok(SUCCEEDED(ret), "ParseDisplayName returned %x\n", ret); 2034 2035 ret = IShellFolder_BindToObject(desktopfolder, pidl_cwd, NULL, &IID_IShellFolder, (void**)¤tfolder); 2036 ok(SUCCEEDED(ret), "BindToObject returned %x\n", ret); 2037 2038 CreateTestFile(".\\testfile"); 2039 2040 ret = IShellFolder_ParseDisplayName(currentfolder, NULL, NULL, testfileW, NULL, &pidl_testfile, NULL); 2041 ok(SUCCEEDED(ret), "ParseDisplayName returned %x\n", ret); 2042 2043 pidl_abstestfile = ILCombine(pidl_cwd, pidl_testfile); 2044 2045 shellitem = (void*)0xdeadbeef; 2046 ret = pSHCreateShellItem(NULL, NULL, NULL, &shellitem); 2047 ok(ret == E_INVALIDARG, "SHCreateShellItem returned %x\n", ret); 2048 ok(shellitem == 0, "Got %p\n", shellitem); 2049 2050 if (0) /* crashes on Windows XP */ 2051 { 2052 pSHCreateShellItem(NULL, NULL, pidl_cwd, NULL); 2053 pSHCreateShellItem(pidl_cwd, NULL, NULL, &shellitem); 2054 pSHCreateShellItem(NULL, currentfolder, NULL, &shellitem); 2055 pSHCreateShellItem(pidl_cwd, currentfolder, NULL, &shellitem); 2056 } 2057 2058 ret = pSHCreateShellItem(NULL, NULL, pidl_cwd, &shellitem); 2059 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2060 if (SUCCEEDED(ret)) 2061 { 2062 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2063 ok(SUCCEEDED(ret), "QueryInterface returned %x\n", ret); 2064 if (SUCCEEDED(ret)) 2065 { 2066 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2067 ok(SUCCEEDED(ret), "GetIDList returned %x\n", ret); 2068 if (SUCCEEDED(ret)) 2069 { 2070 ok(ILIsEqual(pidl_cwd, pidl_test), "id lists are not equal\n"); 2071 ILFree(pidl_test); 2072 } 2073 IPersistIDList_Release(persistidl); 2074 } 2075 IShellItem_Release(shellitem); 2076 } 2077 2078 ret = pSHCreateShellItem(pidl_cwd, NULL, pidl_testfile, &shellitem); 2079 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2080 if (SUCCEEDED(ret)) 2081 { 2082 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2083 ok(SUCCEEDED(ret), "QueryInterface returned %x\n", ret); 2084 if (SUCCEEDED(ret)) 2085 { 2086 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2087 ok(SUCCEEDED(ret), "GetIDList returned %x\n", ret); 2088 if (SUCCEEDED(ret)) 2089 { 2090 ok(ILIsEqual(pidl_abstestfile, pidl_test), "id lists are not equal\n"); 2091 ILFree(pidl_test); 2092 } 2093 IPersistIDList_Release(persistidl); 2094 } 2095 2096 ret = IShellItem_GetParent(shellitem, &shellitem2); 2097 ok(SUCCEEDED(ret), "GetParent returned %x\n", ret); 2098 if (SUCCEEDED(ret)) 2099 { 2100 ret = IShellItem_QueryInterface(shellitem2, &IID_IPersistIDList, (void**)&persistidl); 2101 ok(SUCCEEDED(ret), "QueryInterface returned %x\n", ret); 2102 if (SUCCEEDED(ret)) 2103 { 2104 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2105 ok(SUCCEEDED(ret), "GetIDList returned %x\n", ret); 2106 if (SUCCEEDED(ret)) 2107 { 2108 ok(ILIsEqual(pidl_cwd, pidl_test), "id lists are not equal\n"); 2109 ILFree(pidl_test); 2110 } 2111 IPersistIDList_Release(persistidl); 2112 } 2113 IShellItem_Release(shellitem2); 2114 } 2115 2116 IShellItem_Release(shellitem); 2117 } 2118 2119 ret = pSHCreateShellItem(NULL, currentfolder, pidl_testfile, &shellitem); 2120 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2121 if (SUCCEEDED(ret)) 2122 { 2123 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2124 ok(SUCCEEDED(ret), "QueryInterface returned %x\n", ret); 2125 if (SUCCEEDED(ret)) 2126 { 2127 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2128 ok(SUCCEEDED(ret), "GetIDList returned %x\n", ret); 2129 if (SUCCEEDED(ret)) 2130 { 2131 ok(ILIsEqual(pidl_abstestfile, pidl_test), "id lists are not equal\n"); 2132 ILFree(pidl_test); 2133 } 2134 IPersistIDList_Release(persistidl); 2135 } 2136 IShellItem_Release(shellitem); 2137 } 2138 2139 /* if a parent pidl and shellfolder are specified, the shellfolder is ignored */ 2140 ret = pSHCreateShellItem(pidl_cwd, desktopfolder, pidl_testfile, &shellitem); 2141 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2142 if (SUCCEEDED(ret)) 2143 { 2144 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2145 ok(SUCCEEDED(ret), "QueryInterface returned %x\n", ret); 2146 if (SUCCEEDED(ret)) 2147 { 2148 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2149 ok(SUCCEEDED(ret), "GetIDList returned %x\n", ret); 2150 if (SUCCEEDED(ret)) 2151 { 2152 ok(ILIsEqual(pidl_abstestfile, pidl_test), "id lists are not equal\n"); 2153 ILFree(pidl_test); 2154 } 2155 IPersistIDList_Release(persistidl); 2156 } 2157 IShellItem_Release(shellitem); 2158 } 2159 2160 ret = pSHCreateShellItem(NULL, desktopfolder, pidl_testfile, &shellitem); 2161 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2162 if (SUCCEEDED(ret)) 2163 { 2164 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2165 ok(SUCCEEDED(ret), "QueryInterface returned %x\n", ret); 2166 if (SUCCEEDED(ret)) 2167 { 2168 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2169 ok(SUCCEEDED(ret), "GetIDList returned %x\n", ret); 2170 if (SUCCEEDED(ret)) 2171 { 2172 ok(ILIsEqual(pidl_testfile, pidl_test), "id lists are not equal\n"); 2173 ILFree(pidl_test); 2174 } 2175 IPersistIDList_Release(persistidl); 2176 } 2177 2178 IShellItem_Release(shellitem); 2179 } 2180 2181 ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem); 2182 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2183 if (SUCCEEDED(ret)) 2184 { 2185 ret = IShellItem_GetParent(shellitem, &shellitem2); 2186 ok(FAILED(ret), "Got 0x%08x\n", ret); 2187 if(SUCCEEDED(ret)) IShellItem_Release(shellitem2); 2188 IShellItem_Release(shellitem); 2189 } 2190 2191 /* SHCreateItemFromParsingName */ 2192 if(pSHCreateItemFromParsingName) 2193 { 2194 if(0) 2195 { 2196 /* Crashes under windows 7 */ 2197 pSHCreateItemFromParsingName(NULL, NULL, &IID_IShellItem, NULL); 2198 } 2199 2200 shellitem = (void*)0xdeadbeef; 2201 ret = pSHCreateItemFromParsingName(NULL, NULL, &IID_IShellItem, (void**)&shellitem); 2202 ok(ret == E_INVALIDARG, "SHCreateItemFromParsingName returned %x\n", ret); 2203 ok(shellitem == NULL, "shellitem was %p.\n", shellitem); 2204 2205 ret = pSHCreateItemFromParsingName(testfileW, NULL, &IID_IShellItem, (void**)&shellitem); 2206 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 2207 "SHCreateItemFromParsingName returned %x\n", ret); 2208 if(SUCCEEDED(ret)) IShellItem_Release(shellitem); 2209 2210 lstrcpyW(fnbufW, curdirW); 2211 myPathAddBackslashW(fnbufW); 2212 lstrcatW(fnbufW, testfileW); 2213 2214 ret = pSHCreateItemFromParsingName(fnbufW, NULL, &IID_IShellItem, (void**)&shellitem); 2215 ok(ret == S_OK, "SHCreateItemFromParsingName returned %x\n", ret); 2216 if(SUCCEEDED(ret)) 2217 { 2218 LPWSTR tmp_fname; 2219 ret = IShellItem_GetDisplayName(shellitem, SIGDN_FILESYSPATH, &tmp_fname); 2220 ok(ret == S_OK, "GetDisplayName returned %x\n", ret); 2221 if(SUCCEEDED(ret)) 2222 { 2223 ok(!lstrcmpW(fnbufW, tmp_fname), "strings not equal\n"); 2224 CoTaskMemFree(tmp_fname); 2225 } 2226 IShellItem_Release(shellitem); 2227 } 2228 } 2229 else 2230 win_skip("No SHCreateItemFromParsingName\n"); 2231 2232 2233 /* SHCreateItemFromIDList */ 2234 if(pSHCreateItemFromIDList) 2235 { 2236 if(0) 2237 { 2238 /* Crashes under win7 */ 2239 pSHCreateItemFromIDList(NULL, &IID_IShellItem, NULL); 2240 } 2241 2242 ret = pSHCreateItemFromIDList(NULL, &IID_IShellItem, (void**)&shellitem); 2243 ok(ret == E_INVALIDARG, "SHCreateItemFromIDList returned %x\n", ret); 2244 2245 ret = pSHCreateItemFromIDList(pidl_cwd, &IID_IShellItem, (void**)&shellitem); 2246 ok(ret == S_OK, "SHCreateItemFromIDList returned %x\n", ret); 2247 if (SUCCEEDED(ret)) 2248 { 2249 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2250 ok(ret == S_OK, "QueryInterface returned %x\n", ret); 2251 if (SUCCEEDED(ret)) 2252 { 2253 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2254 ok(ret == S_OK, "GetIDList returned %x\n", ret); 2255 if (SUCCEEDED(ret)) 2256 { 2257 ok(ILIsEqual(pidl_cwd, pidl_test), "id lists are not equal\n"); 2258 ILFree(pidl_test); 2259 } 2260 IPersistIDList_Release(persistidl); 2261 } 2262 IShellItem_Release(shellitem); 2263 } 2264 2265 ret = pSHCreateItemFromIDList(pidl_testfile, &IID_IShellItem, (void**)&shellitem); 2266 ok(ret == S_OK, "SHCreateItemFromIDList returned %x\n", ret); 2267 if (SUCCEEDED(ret)) 2268 { 2269 ret = IShellItem_QueryInterface(shellitem, &IID_IPersistIDList, (void**)&persistidl); 2270 ok(ret == S_OK, "QueryInterface returned %x\n", ret); 2271 if (SUCCEEDED(ret)) 2272 { 2273 ret = IPersistIDList_GetIDList(persistidl, &pidl_test); 2274 ok(ret == S_OK, "GetIDList returned %x\n", ret); 2275 if (SUCCEEDED(ret)) 2276 { 2277 ok(ILIsEqual(pidl_testfile, pidl_test), "id lists are not equal\n"); 2278 ILFree(pidl_test); 2279 } 2280 IPersistIDList_Release(persistidl); 2281 } 2282 IShellItem_Release(shellitem); 2283 } 2284 } 2285 else 2286 win_skip("No SHCreateItemFromIDList\n"); 2287 2288 /* SHCreateItemFromRelativeName */ 2289 if(pSHCreateItemFromRelativeName && pSHGetKnownFolderPath) 2290 { 2291 IShellItem *shellitem_desktop = NULL; 2292 WCHAR *desktop_path, *displayname; 2293 WCHAR testfile_path[MAX_PATH] = {0}; 2294 HANDLE file; 2295 LPITEMIDLIST pidl_desktop_testfile = NULL; 2296 int order; 2297 2298 ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem_desktop); 2299 ok(ret == S_OK, "SHCreateShellItem failed: 0x%08x.\n", ret); 2300 2301 shellitem = (void*)0xdeadbeef; 2302 ret = pSHCreateItemFromRelativeName(shellitem_desktop, NULL, NULL, &IID_IShellItem, 2303 (void**)&shellitem); 2304 ok(ret == E_INVALIDARG, "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n", 2305 E_INVALIDARG, ret); 2306 ok(shellitem == NULL, "shellitem was %p.\n", shellitem); 2307 2308 /* Test with a non-existent file */ 2309 shellitem = (void*)0xdeadbeef; 2310 ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem, 2311 (void**)&shellitem); 2312 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 2313 "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n", 2314 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), ret); 2315 ok(shellitem == NULL, "shellitem was %p.\n", shellitem); 2316 2317 /* Create a file for testing in desktop folder */ 2318 pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &desktop_path); 2319 lstrcatW(testfile_path, desktop_path); 2320 myPathAddBackslashW(testfile_path); 2321 lstrcatW(testfile_path, testfileW); 2322 file = CreateFileW(testfile_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); 2323 ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError()); 2324 CloseHandle(file); 2325 2326 shellitem = (void*)0xdeadbeef; 2327 ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem, 2328 (void**)&shellitem); 2329 ok(ret == S_OK, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret); 2330 ok(shellitem != NULL, "shellitem was %p.\n", shellitem); 2331 if(SUCCEEDED(ret)) 2332 { 2333 ret = IShellItem_GetDisplayName(shellitem, 0, &displayname); 2334 ok(ret == S_OK, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret); 2335 ok(!lstrcmpW(displayname, testfileW), "got wrong display name: %s.\n", wine_dbgstr_w(displayname)); 2336 CoTaskMemFree(displayname); 2337 2338 shellitem2 = (void*)0xdeadbeef; 2339 ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem, 2340 (void**)&shellitem2); 2341 ok(ret == S_OK, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret); 2342 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); 2343 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08x.\n", ret); 2344 ok(!order, "order got wrong value: %d.\n", order); 2345 IShellItem_Release(shellitem2); 2346 2347 shellitem2 = (void*)0xdeadbeef; 2348 ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, testfileW, NULL, 2349 &pidl_desktop_testfile, NULL); 2350 ok(ret == S_OK, "ParseDisplayName failed 0x%08x.\n", ret); 2351 ret = pSHCreateItemFromIDList(pidl_desktop_testfile, &IID_IShellItem, (void**)&shellitem2); 2352 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); 2353 ok(ret == S_OK, "IShellItem_Compare fail: 0x%08x.\n", ret); 2354 ok(!order, "order got wrong value: %d.\n", order); 2355 ILFree(pidl_desktop_testfile); 2356 IShellItem_Release(shellitem2); 2357 2358 IShellItem_Release(shellitem); 2359 } 2360 2361 DeleteFileW(testfile_path); 2362 CoTaskMemFree(desktop_path); 2363 IShellItem_Release(shellitem_desktop); 2364 } 2365 else 2366 win_skip("No SHCreateItemFromRelativeName or SHGetKnownFolderPath\n"); 2367 2368 /* SHCreateItemInKnownFolder */ 2369 if(pSHCreateItemInKnownFolder && pSHGetKnownFolderPath) 2370 { 2371 WCHAR *desktop_path; 2372 WCHAR testfile_path[MAX_PATH] = {0}; 2373 HANDLE file; 2374 WCHAR *displayname = NULL; 2375 int order; 2376 LPITEMIDLIST pidl_desktop_testfile = NULL; 2377 2378 shellitem = (void*)0xdeadbeef; 2379 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, NULL, &IID_IShellItem, 2380 (void**)&shellitem); 2381 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret); 2382 ok(shellitem != NULL, "shellitem was %p.\n", shellitem); 2383 if(SUCCEEDED(ret)) 2384 { 2385 shellitem2 = (void*)0xdeadbeef; 2386 ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem2); 2387 ok(SUCCEEDED(ret), "SHCreateShellItem returned %x\n", ret); 2388 if(SUCCEEDED(ret)) 2389 { 2390 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); 2391 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08x.\n", ret); 2392 ok(!order, "order got wrong value: %d.\n", order); 2393 IShellItem_Release(shellitem2); 2394 } 2395 IShellItem_Release(shellitem); 2396 } 2397 2398 /* Test with a non-existent file */ 2399 shellitem = (void*)0xdeadbeef; 2400 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, testfileW, &IID_IShellItem, 2401 (void**)&shellitem); 2402 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 2403 "Expected 0x%08x but SHCreateItemInKnownFolder return: 0x%08x.\n", 2404 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), ret); 2405 ok(shellitem == NULL, "shellitem was %p.\n", shellitem); 2406 2407 pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &desktop_path); 2408 lstrcatW(testfile_path, desktop_path); 2409 myPathAddBackslashW(testfile_path); 2410 lstrcatW(testfile_path, testfileW); 2411 file = CreateFileW(testfile_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); 2412 ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError()); 2413 CloseHandle(file); 2414 2415 shellitem = (void*)0xdeadbeef; 2416 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, testfileW, &IID_IShellItem, 2417 (void**)&shellitem); 2418 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret); 2419 ok(shellitem != NULL, "shellitem was %p.\n", shellitem); 2420 if(SUCCEEDED(ret)) 2421 { 2422 ret = IShellItem_GetDisplayName(shellitem, 0, &displayname); 2423 ok(ret == S_OK, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret); 2424 ok(!lstrcmpW(displayname, testfileW), "got wrong display name: %s.\n", 2425 wine_dbgstr_w(displayname)); 2426 CoTaskMemFree(displayname); 2427 2428 shellitem2 = (void*)0xdeadbeef; 2429 ret = pSHCreateItemInKnownFolder(&FOLDERID_Desktop, 0, testfileW, &IID_IShellItem, 2430 (void**)&shellitem2); 2431 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret); 2432 ok(shellitem2 != NULL, "shellitem was %p.\n", shellitem); 2433 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); 2434 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08x.\n", ret); 2435 ok(!order, "order got wrong value: %d.\n", order); 2436 IShellItem_Release(shellitem2); 2437 2438 shellitem2 = (void*)0xdeadbeef; 2439 ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, testfileW, NULL, 2440 &pidl_desktop_testfile, NULL); 2441 ok(SUCCEEDED(ret), "ParseDisplayName returned %x.\n", ret); 2442 ret = pSHCreateItemFromIDList(pidl_desktop_testfile, &IID_IShellItem, (void**)&shellitem2); 2443 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); 2444 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08x.\n", ret); 2445 ok(!order, "order got wrong value: %d.\n", order); 2446 ILFree(pidl_desktop_testfile); 2447 IShellItem_Release(shellitem2); 2448 2449 IShellItem_Release(shellitem); 2450 } 2451 2452 shellitem = (void*)0xdeadbeef; 2453 ret = pSHCreateItemInKnownFolder(&FOLDERID_Documents, 0, NULL, &IID_IShellItem, 2454 (void**)&shellitem); 2455 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret); 2456 ok(shellitem != NULL, "shellitem was %p.\n", shellitem); 2457 if(SUCCEEDED(ret)) 2458 { 2459 shellitem2 = (void*)0xdeadbeef; 2460 ret = pSHCreateItemInKnownFolder(&FOLDERID_Documents, 0, NULL, &IID_IShellItem, 2461 (void**)&shellitem2); 2462 ok(ret == S_OK, "SHCreateItemInKnownFolder failed: 0x%08x.\n", ret); 2463 ok(shellitem2 != NULL, "shellitem was %p.\n", shellitem); 2464 ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); 2465 ok(ret == S_OK, "IShellItem_Compare failed: 0x%08x.\n", ret); 2466 ok(!order, "order got wrong value: %d.\n", order); 2467 IShellItem_Release(shellitem2); 2468 2469 IShellItem_Release(shellitem); 2470 } 2471 DeleteFileW(testfile_path); 2472 CoTaskMemFree(desktop_path); 2473 } 2474 else 2475 win_skip("No SHCreateItemInKnownFolder or SHGetKnownFolderPath\n"); 2476 2477 DeleteFileA(".\\testfile"); 2478 ILFree(pidl_abstestfile); 2479 ILFree(pidl_testfile); 2480 ILFree(pidl_desktop); 2481 ILFree(pidl_cwd); 2482 IShellFolder_Release(currentfolder); 2483 IShellFolder_Release(desktopfolder); 2484 } 2485 2486 static void test_SHGetNameFromIDList(void) 2487 { 2488 IShellItem *shellitem; 2489 LPITEMIDLIST pidl; 2490 LPWSTR name_string; 2491 HRESULT hres; 2492 UINT i; 2493 static const DWORD flags[] = { 2494 SIGDN_NORMALDISPLAY, SIGDN_PARENTRELATIVEPARSING, 2495 SIGDN_DESKTOPABSOLUTEPARSING,SIGDN_PARENTRELATIVEEDITING, 2496 SIGDN_DESKTOPABSOLUTEEDITING, /*SIGDN_FILESYSPATH, SIGDN_URL, */ 2497 SIGDN_PARENTRELATIVEFORADDRESSBAR,SIGDN_PARENTRELATIVE, -1234}; 2498 2499 if(!pSHGetNameFromIDList) 2500 { 2501 win_skip("SHGetNameFromIDList missing.\n"); 2502 return; 2503 } 2504 2505 /* This should be available on any platform that passed the above test. */ 2506 ok(pSHCreateShellItem != NULL, "SHCreateShellItem missing.\n"); 2507 2508 if(0) 2509 { 2510 /* Crashes under win7 */ 2511 pSHGetNameFromIDList(NULL, 0, NULL); 2512 } 2513 2514 hres = pSHGetNameFromIDList(NULL, 0, &name_string); 2515 ok(hres == E_INVALIDARG, "Got 0x%08x\n", hres); 2516 2517 /* Test the desktop */ 2518 hres = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl); 2519 ok(hres == S_OK, "Got 0x%08x\n", hres); 2520 hres = pSHCreateShellItem(NULL, NULL, pidl, &shellitem); 2521 ok(hres == S_OK, "Got 0x%08x\n", hres); 2522 if(SUCCEEDED(hres)) 2523 { 2524 WCHAR *nameSI, *nameSH; 2525 WCHAR buf[MAX_PATH]; 2526 HRESULT hrSI, hrSH, hrSF; 2527 STRRET strret; 2528 IShellFolder *psf; 2529 BOOL res; 2530 2531 SHGetDesktopFolder(&psf); 2532 for(i = 0; flags[i] != -1234; i++) 2533 { 2534 hrSI = IShellItem_GetDisplayName(shellitem, flags[i], &nameSI); 2535 ok(hrSI == S_OK, "Got 0x%08x\n", hrSI); 2536 hrSH = pSHGetNameFromIDList(pidl, flags[i], &nameSH); 2537 ok(hrSH == S_OK, "Got 0x%08x\n", hrSH); 2538 hrSF = IShellFolder_GetDisplayNameOf(psf, pidl, flags[i] & 0xffff, &strret); 2539 ok(hrSF == S_OK, "Got 0x%08x\n", hrSF); 2540 2541 if(SUCCEEDED(hrSI) && SUCCEEDED(hrSH)) 2542 ok(!lstrcmpW(nameSI, nameSH), "Strings differ.\n"); 2543 2544 if(SUCCEEDED(hrSF)) 2545 { 2546 StrRetToBufW(&strret, NULL, buf, MAX_PATH); 2547 if(SUCCEEDED(hrSI)) 2548 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n"); 2549 if(SUCCEEDED(hrSF)) 2550 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n"); 2551 } 2552 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI); 2553 if(SUCCEEDED(hrSH)) CoTaskMemFree(nameSH); 2554 } 2555 IShellFolder_Release(psf); 2556 2557 hrSI = pSHGetNameFromIDList(pidl, SIGDN_FILESYSPATH, &nameSI); 2558 ok(hrSI == S_OK, "Got 0x%08x\n", hrSI); 2559 res = SHGetPathFromIDListW(pidl, buf); 2560 ok(res == TRUE, "Got %d\n", res); 2561 if(SUCCEEDED(hrSI) && res) 2562 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n"); 2563 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI); 2564 2565 hres = pSHGetNameFromIDList(pidl, SIGDN_URL, &name_string); 2566 todo_wine ok(hres == S_OK, "Got 0x%08x\n", hres); 2567 if(SUCCEEDED(hres)) CoTaskMemFree(name_string); 2568 2569 IShellItem_Release(shellitem); 2570 } 2571 ILFree(pidl); 2572 2573 /* Test the control panel */ 2574 hres = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidl); 2575 ok(hres == S_OK, "Got 0x%08x\n", hres); 2576 hres = pSHCreateShellItem(NULL, NULL, pidl, &shellitem); 2577 ok(hres == S_OK, "Got 0x%08x\n", hres); 2578 if(SUCCEEDED(hres)) 2579 { 2580 WCHAR *nameSI, *nameSH; 2581 WCHAR buf[MAX_PATH]; 2582 HRESULT hrSI, hrSH, hrSF; 2583 STRRET strret; 2584 IShellFolder *psf; 2585 BOOL res; 2586 2587 SHGetDesktopFolder(&psf); 2588 for(i = 0; flags[i] != -1234; i++) 2589 { 2590 hrSI = IShellItem_GetDisplayName(shellitem, flags[i], &nameSI); 2591 ok(hrSI == S_OK, "Got 0x%08x\n", hrSI); 2592 hrSH = pSHGetNameFromIDList(pidl, flags[i], &nameSH); 2593 ok(hrSH == S_OK, "Got 0x%08x\n", hrSH); 2594 hrSF = IShellFolder_GetDisplayNameOf(psf, pidl, flags[i] & 0xffff, &strret); 2595 ok(hrSF == S_OK, "Got 0x%08x\n", hrSF); 2596 2597 if(SUCCEEDED(hrSI) && SUCCEEDED(hrSH)) 2598 ok(!lstrcmpW(nameSI, nameSH), "Strings differ.\n"); 2599 2600 if(SUCCEEDED(hrSF)) 2601 { 2602 StrRetToBufW(&strret, NULL, buf, MAX_PATH); 2603 if(SUCCEEDED(hrSI)) 2604 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n"); 2605 if(SUCCEEDED(hrSF)) 2606 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n"); 2607 } 2608 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI); 2609 if(SUCCEEDED(hrSH)) CoTaskMemFree(nameSH); 2610 } 2611 IShellFolder_Release(psf); 2612 2613 hrSI = pSHGetNameFromIDList(pidl, SIGDN_FILESYSPATH, &nameSI); 2614 ok(hrSI == E_INVALIDARG, "Got 0x%08x\n", hrSI); 2615 res = SHGetPathFromIDListW(pidl, buf); 2616 ok(res == FALSE, "Got %d\n", res); 2617 if(SUCCEEDED(hrSI) && res) 2618 ok(!lstrcmpW(nameSI, buf), "Strings differ.\n"); 2619 if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI); 2620 2621 hres = pSHGetNameFromIDList(pidl, SIGDN_URL, &name_string); 2622 todo_wine ok(hres == E_NOTIMPL /* Win7 */ || hres == S_OK /* Vista */, 2623 "Got 0x%08x\n", hres); 2624 if(SUCCEEDED(hres)) CoTaskMemFree(name_string); 2625 2626 IShellItem_Release(shellitem); 2627 } 2628 ILFree(pidl); 2629 } 2630 2631 static void test_SHGetItemFromDataObject(void) 2632 { 2633 IShellFolder *psfdesktop; 2634 IShellItem *psi; 2635 IShellView *psv; 2636 HRESULT hres; 2637 2638 if(!pSHGetItemFromDataObject) 2639 { 2640 win_skip("No SHGetItemFromDataObject.\n"); 2641 return; 2642 } 2643 2644 if(0) 2645 { 2646 /* Crashes under win7 */ 2647 pSHGetItemFromDataObject(NULL, 0, &IID_IShellItem, NULL); 2648 } 2649 2650 hres = pSHGetItemFromDataObject(NULL, 0, &IID_IShellItem, (void**)&psv); 2651 ok(hres == E_INVALIDARG, "got 0x%08x\n", hres); 2652 2653 SHGetDesktopFolder(&psfdesktop); 2654 2655 hres = IShellFolder_CreateViewObject(psfdesktop, NULL, &IID_IShellView, (void**)&psv); 2656 ok(hres == S_OK, "got 0x%08x\n", hres); 2657 if(SUCCEEDED(hres)) 2658 { 2659 IEnumIDList *peidl; 2660 IDataObject *pdo; 2661 SHCONTF enum_flags; 2662 2663 enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN; 2664 hres = IShellFolder_EnumObjects(psfdesktop, NULL, enum_flags, &peidl); 2665 ok(hres == S_OK, "got 0x%08x\n", hres); 2666 if(SUCCEEDED(hres)) 2667 { 2668 LPITEMIDLIST apidl[5]; 2669 UINT count = 0, i; 2670 2671 for(count = 0; count < 5; count++) 2672 if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK) 2673 break; 2674 2675 if(count) 2676 { 2677 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, 1, (LPCITEMIDLIST*)apidl, 2678 &IID_IDataObject, NULL, (void**)&pdo); 2679 ok(hres == S_OK, "got 0x%08x\n", hres); 2680 if(SUCCEEDED(hres)) 2681 { 2682 hres = pSHGetItemFromDataObject(pdo, DOGIF_DEFAULT, &IID_IShellItem, (void**)&psi); 2683 ok(hres == S_OK, "got 0x%08x\n", hres); 2684 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2685 hres = pSHGetItemFromDataObject(pdo, DOGIF_TRAVERSE_LINK, &IID_IShellItem, (void**)&psi); 2686 ok(hres == S_OK, "got 0x%08x\n", hres); 2687 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2688 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_HDROP, &IID_IShellItem, (void**)&psi); 2689 ok(hres == S_OK, "got 0x%08x\n", hres); 2690 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2691 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_URL, &IID_IShellItem, (void**)&psi); 2692 ok(hres == S_OK, "got 0x%08x\n", hres); 2693 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2694 hres = pSHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE, &IID_IShellItem, (void**)&psi); 2695 ok(hres == S_OK, "got 0x%08x\n", hres); 2696 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2697 2698 IDataObject_Release(pdo); 2699 } 2700 } 2701 else 2702 skip("No file(s) found - skipping single-file test.\n"); 2703 2704 if(count > 1) 2705 { 2706 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, count, (LPCITEMIDLIST*)apidl, 2707 &IID_IDataObject, NULL, (void**)&pdo); 2708 ok(hres == S_OK, "got 0x%08x\n", hres); 2709 if(SUCCEEDED(hres)) 2710 { 2711 hres = pSHGetItemFromDataObject(pdo, DOGIF_DEFAULT, &IID_IShellItem, (void**)&psi); 2712 ok(hres == S_OK, "got 0x%08x\n", hres); 2713 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2714 hres = pSHGetItemFromDataObject(pdo, DOGIF_TRAVERSE_LINK, &IID_IShellItem, (void**)&psi); 2715 ok(hres == S_OK, "got 0x%08x\n", hres); 2716 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2717 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_HDROP, &IID_IShellItem, (void**)&psi); 2718 ok(hres == S_OK, "got 0x%08x\n", hres); 2719 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2720 hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_URL, &IID_IShellItem, (void**)&psi); 2721 ok(hres == S_OK, "got 0x%08x\n", hres); 2722 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2723 hres = pSHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE, &IID_IShellItem, (void**)&psi); 2724 ok(hres == E_FAIL, "got 0x%08x\n", hres); 2725 if(SUCCEEDED(hres)) IShellItem_Release(psi); 2726 IDataObject_Release(pdo); 2727 } 2728 } 2729 else 2730 skip("zero or one file found - skipping multi-file test.\n"); 2731 2732 for(i = 0; i < count; i++) 2733 ILFree(apidl[i]); 2734 2735 IEnumIDList_Release(peidl); 2736 } 2737 2738 IShellView_Release(psv); 2739 } 2740 2741 IShellFolder_Release(psfdesktop); 2742 } 2743 2744 static void test_ShellItemCompare(void) 2745 { 2746 IShellItem *psi[9]; /* a\a, a\b, a\c, b\a, .. */ 2747 IShellItem *psi_a = NULL, *psi_b = NULL, *psi_c = NULL; 2748 IShellFolder *psf_desktop, *psf_current; 2749 LPITEMIDLIST pidl_cwd; 2750 WCHAR curdirW[MAX_PATH]; 2751 BOOL failed; 2752 HRESULT hr; 2753 static const WCHAR filesW[][9] = { 2754 {'a','\\','a',0}, {'a','\\','b',0}, {'a','\\','c',0}, 2755 {'b','\\','a',0}, {'b','\\','b',0}, {'b','\\','c',0}, 2756 {'c','\\','a',0}, {'c','\\','b',0}, {'c','\\','c',0} }; 2757 int order; 2758 UINT i; 2759 2760 if(!pSHCreateShellItem) 2761 { 2762 win_skip("SHCreateShellItem missing.\n"); 2763 return; 2764 } 2765 2766 GetCurrentDirectoryW(MAX_PATH, curdirW); 2767 if (!curdirW[0]) 2768 { 2769 skip("Failed to get current directory, skipping.\n"); 2770 return; 2771 } 2772 2773 CreateDirectoryA(".\\a", NULL); 2774 CreateDirectoryA(".\\b", NULL); 2775 CreateDirectoryA(".\\c", NULL); 2776 CreateTestFile(".\\a\\a"); 2777 CreateTestFile(".\\a\\b"); 2778 CreateTestFile(".\\a\\c"); 2779 CreateTestFile(".\\b\\a"); 2780 CreateTestFile(".\\b\\b"); 2781 CreateTestFile(".\\b\\c"); 2782 CreateTestFile(".\\c\\a"); 2783 CreateTestFile(".\\c\\b"); 2784 CreateTestFile(".\\c\\c"); 2785 2786 SHGetDesktopFolder(&psf_desktop); 2787 hr = IShellFolder_ParseDisplayName(psf_desktop, NULL, NULL, curdirW, NULL, &pidl_cwd, NULL); 2788 ok(SUCCEEDED(hr), "ParseDisplayName returned %x\n", hr); 2789 hr = IShellFolder_BindToObject(psf_desktop, pidl_cwd, NULL, &IID_IShellFolder, (void**)&psf_current); 2790 ok(SUCCEEDED(hr), "BindToObject returned %x\n", hr); 2791 IShellFolder_Release(psf_desktop); 2792 ILFree(pidl_cwd); 2793 2794 /* Generate ShellItems for the files */ 2795 memset(&psi, 0, sizeof(psi)); 2796 failed = FALSE; 2797 for(i = 0; i < 9; i++) 2798 { 2799 LPITEMIDLIST pidl_testfile = NULL; 2800 2801 hr = IShellFolder_ParseDisplayName(psf_current, NULL, NULL, (LPWSTR)filesW[i], 2802 NULL, &pidl_testfile, NULL); 2803 ok(SUCCEEDED(hr), "ParseDisplayName returned %x\n", hr); 2804 if(SUCCEEDED(hr)) 2805 { 2806 hr = pSHCreateShellItem(NULL, NULL, pidl_testfile, &psi[i]); 2807 ok(hr == S_OK, "Got 0x%08x\n", hr); 2808 ILFree(pidl_testfile); 2809 } 2810 if(FAILED(hr)) failed = TRUE; 2811 } 2812 if(failed) 2813 { 2814 skip("Failed to create all shellitems.\n"); 2815 goto cleanup; 2816 } 2817 2818 /* Generate ShellItems for the folders */ 2819 hr = IShellItem_GetParent(psi[0], &psi_a); 2820 ok(hr == S_OK, "Got 0x%08x\n", hr); 2821 if(FAILED(hr)) failed = TRUE; 2822 hr = IShellItem_GetParent(psi[3], &psi_b); 2823 ok(hr == S_OK, "Got 0x%08x\n", hr); 2824 if(FAILED(hr)) failed = TRUE; 2825 hr = IShellItem_GetParent(psi[6], &psi_c); 2826 ok(hr == S_OK, "Got 0x%08x\n", hr); 2827 if(FAILED(hr)) failed = TRUE; 2828 2829 if(failed) 2830 { 2831 skip("Failed to create shellitems.\n"); 2832 goto cleanup; 2833 } 2834 2835 if(0) 2836 { 2837 /* Crashes on native (win7, winxp) */ 2838 IShellItem_Compare(psi_a, NULL, 0, NULL); 2839 IShellItem_Compare(psi_a, psi_b, 0, NULL); 2840 IShellItem_Compare(psi_a, NULL, 0, &order); 2841 } 2842 2843 /* Basics */ 2844 for(i = 0; i < 9; i++) 2845 { 2846 hr = IShellItem_Compare(psi[i], psi[i], SICHINT_DISPLAY, &order); 2847 ok(hr == S_OK, "Got 0x%08x\n", hr); 2848 ok(order == 0, "Got order %d\n", order); 2849 hr = IShellItem_Compare(psi[i], psi[i], SICHINT_CANONICAL, &order); 2850 ok(hr == S_OK, "Got 0x%08x\n", hr); 2851 ok(order == 0, "Got order %d\n", order); 2852 hr = IShellItem_Compare(psi[i], psi[i], SICHINT_ALLFIELDS, &order); 2853 ok(hr == S_OK, "Got 0x%08x\n", hr); 2854 ok(order == 0, "Got order %d\n", order); 2855 } 2856 2857 /* Order */ 2858 /* a\b:a\a , a\b:a\c, a\b:a\b */ 2859 hr = IShellItem_Compare(psi[1], psi[0], SICHINT_DISPLAY, &order); 2860 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2861 ok(order == 1, "Got order %d\n", order); 2862 hr = IShellItem_Compare(psi[1], psi[2], SICHINT_DISPLAY, &order); 2863 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2864 ok(order == -1, "Got order %d\n", order); 2865 hr = IShellItem_Compare(psi[1], psi[1], SICHINT_DISPLAY, &order); 2866 ok(hr == S_OK, "Got 0x%08x\n", hr); 2867 ok(order == 0, "Got order %d\n", order); 2868 2869 /* b\b:a\b, b\b:c\b, b\b:c\b */ 2870 hr = IShellItem_Compare(psi[4], psi[1], SICHINT_DISPLAY, &order); 2871 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2872 ok(order == 1, "Got order %d\n", order); 2873 hr = IShellItem_Compare(psi[4], psi[7], SICHINT_DISPLAY, &order); 2874 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2875 ok(order == -1, "Got order %d\n", order); 2876 hr = IShellItem_Compare(psi[4], psi[4], SICHINT_DISPLAY, &order); 2877 ok(hr == S_OK, "Got 0x%08x\n", hr); 2878 ok(order == 0, "Got order %d\n", order); 2879 2880 /* b:a\a, b:a\c, b:a\b */ 2881 hr = IShellItem_Compare(psi_b, psi[0], SICHINT_DISPLAY, &order); 2882 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2883 todo_wine ok(order == 1, "Got order %d\n", order); 2884 hr = IShellItem_Compare(psi_b, psi[2], SICHINT_DISPLAY, &order); 2885 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2886 todo_wine ok(order == 1, "Got order %d\n", order); 2887 hr = IShellItem_Compare(psi_b, psi[1], SICHINT_DISPLAY, &order); 2888 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2889 todo_wine ok(order == 1, "Got order %d\n", order); 2890 2891 /* b:c\a, b:c\c, b:c\b */ 2892 hr = IShellItem_Compare(psi_b, psi[6], 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_b, psi[8], SICHINT_DISPLAY, &order); 2896 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2897 ok(order == -1, "Got order %d\n", order); 2898 hr = IShellItem_Compare(psi_b, psi[7], SICHINT_DISPLAY, &order); 2899 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2900 ok(order == -1, "Got order %d\n", order); 2901 2902 /* a\b:a\a , a\b:a\c, a\b:a\b */ 2903 hr = IShellItem_Compare(psi[1], psi[0], SICHINT_CANONICAL, &order); 2904 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2905 ok(order == 1, "Got order %d\n", order); 2906 hr = IShellItem_Compare(psi[1], psi[2], SICHINT_CANONICAL, &order); 2907 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2908 ok(order == -1, "Got order %d\n", order); 2909 hr = IShellItem_Compare(psi[1], psi[1], SICHINT_CANONICAL, &order); 2910 ok(hr == S_OK, "Got 0x%08x\n", hr); 2911 ok(order == 0, "Got order %d\n", order); 2912 2913 /* b\b:a\b, b\b:c\b, b\b:c\b */ 2914 hr = IShellItem_Compare(psi[4], psi[1], SICHINT_CANONICAL, &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[4], psi[7], SICHINT_CANONICAL, &order); 2918 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2919 ok(order == -1, "Got order %d\n", order); 2920 hr = IShellItem_Compare(psi[4], psi[4], SICHINT_CANONICAL, &order); 2921 ok(hr == S_OK, "Got 0x%08x\n", hr); 2922 ok(order == 0, "Got order %d\n", order); 2923 2924 /* b:a\a, b:a\c, b:a\b */ 2925 hr = IShellItem_Compare(psi_b, psi[0], SICHINT_CANONICAL, &order); 2926 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2927 todo_wine ok(order == 1, "Got order %d\n", order); 2928 hr = IShellItem_Compare(psi_b, psi[2], SICHINT_CANONICAL, &order); 2929 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2930 todo_wine ok(order == 1, "Got order %d\n", order); 2931 hr = IShellItem_Compare(psi_b, psi[1], SICHINT_CANONICAL, &order); 2932 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2933 todo_wine ok(order == 1, "Got order %d\n", order); 2934 2935 /* b:c\a, b:c\c, b:c\b */ 2936 hr = IShellItem_Compare(psi_b, psi[6], 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_b, psi[8], SICHINT_CANONICAL, &order); 2940 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2941 ok(order == -1, "Got order %d\n", order); 2942 hr = IShellItem_Compare(psi_b, psi[7], SICHINT_CANONICAL, &order); 2943 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 2944 ok(order == -1, "Got order %d\n", order); 2945 2946 cleanup: 2947 IShellFolder_Release(psf_current); 2948 2949 DeleteFileA(".\\a\\a"); 2950 DeleteFileA(".\\a\\b"); 2951 DeleteFileA(".\\a\\c"); 2952 DeleteFileA(".\\b\\a"); 2953 DeleteFileA(".\\b\\b"); 2954 DeleteFileA(".\\b\\c"); 2955 DeleteFileA(".\\c\\a"); 2956 DeleteFileA(".\\c\\b"); 2957 DeleteFileA(".\\c\\c"); 2958 RemoveDirectoryA(".\\a"); 2959 RemoveDirectoryA(".\\b"); 2960 RemoveDirectoryA(".\\c"); 2961 2962 if(psi_a) IShellItem_Release(psi_a); 2963 if(psi_b) IShellItem_Release(psi_b); 2964 if(psi_c) IShellItem_Release(psi_c); 2965 2966 for(i = 0; i < 9; i++) 2967 if(psi[i]) IShellItem_Release(psi[i]); 2968 } 2969 2970 /**************************************************************/ 2971 /* IUnknown implementation for counting QueryInterface calls. */ 2972 typedef struct { 2973 IUnknown IUnknown_iface; 2974 struct if_count { 2975 REFIID id; 2976 LONG count; 2977 } *ifaces; 2978 LONG unknown; 2979 } IUnknownImpl; 2980 2981 static inline IUnknownImpl *impl_from_IUnknown(IUnknown *iface) 2982 { 2983 return CONTAINING_RECORD(iface, IUnknownImpl, IUnknown_iface); 2984 } 2985 2986 static HRESULT WINAPI unk_fnQueryInterface(IUnknown *iunk, REFIID riid, void** punk) 2987 { 2988 IUnknownImpl *This = impl_from_IUnknown(iunk); 2989 UINT i; 2990 BOOL found = FALSE; 2991 for(i = 0; This->ifaces[i].id != NULL; i++) 2992 { 2993 if(IsEqualIID(This->ifaces[i].id, riid)) 2994 { 2995 This->ifaces[i].count++; 2996 found = TRUE; 2997 break; 2998 } 2999 } 3000 if(!found) 3001 This->unknown++; 3002 return E_NOINTERFACE; 3003 } 3004 3005 static ULONG WINAPI unk_fnAddRef(IUnknown *iunk) 3006 { 3007 return 2; 3008 } 3009 3010 static ULONG WINAPI unk_fnRelease(IUnknown *iunk) 3011 { 3012 return 1; 3013 } 3014 3015 static const IUnknownVtbl vt_IUnknown = { 3016 unk_fnQueryInterface, 3017 unk_fnAddRef, 3018 unk_fnRelease 3019 }; 3020 3021 static void test_SHGetIDListFromObject(void) 3022 { 3023 IUnknownImpl *punkimpl; 3024 IShellFolder *psfdesktop; 3025 IShellView *psv; 3026 LPITEMIDLIST pidl, pidl_desktop; 3027 HRESULT hres; 3028 UINT i; 3029 struct if_count ifaces[] = 3030 { {&IID_IPersistIDList, 0}, 3031 {&IID_IPersistFolder2, 0}, 3032 {&IID_IDataObject, 0}, 3033 {&IID_IParentAndItem, 0}, 3034 {&IID_IFolderView, 0}, 3035 {NULL, 0} }; 3036 3037 if(!pSHGetIDListFromObject) 3038 { 3039 win_skip("SHGetIDListFromObject missing.\n"); 3040 return; 3041 } 3042 3043 if(0) 3044 { 3045 /* Crashes native */ 3046 pSHGetIDListFromObject(NULL, NULL); 3047 pSHGetIDListFromObject((void*)0xDEADBEEF, NULL); 3048 } 3049 3050 hres = pSHGetIDListFromObject(NULL, &pidl); 3051 ok(hres == E_NOINTERFACE, "Got %x\n", hres); 3052 3053 punkimpl = heap_alloc(sizeof(*punkimpl)); 3054 punkimpl->IUnknown_iface.lpVtbl = &vt_IUnknown; 3055 punkimpl->ifaces = ifaces; 3056 punkimpl->unknown = 0; 3057 3058 hres = pSHGetIDListFromObject(&punkimpl->IUnknown_iface, &pidl); 3059 ok(hres == E_NOINTERFACE, "Got %x\n", hres); 3060 ok(ifaces[0].count, "interface not requested.\n"); 3061 ok(ifaces[1].count, "interface not requested.\n"); 3062 ok(ifaces[2].count, "interface not requested.\n"); 3063 todo_wine 3064 ok(ifaces[3].count || broken(!ifaces[3].count /*vista*/), 3065 "interface not requested.\n"); 3066 ok(ifaces[4].count || broken(!ifaces[4].count /*vista*/), 3067 "interface not requested.\n"); 3068 3069 ok(!punkimpl->unknown, "Got %d unknown.\n", punkimpl->unknown); 3070 heap_free(punkimpl); 3071 3072 pidl_desktop = NULL; 3073 SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop); 3074 ok(pidl_desktop != NULL, "Failed to get desktop pidl.\n"); 3075 3076 SHGetDesktopFolder(&psfdesktop); 3077 3078 /* Test IShellItem */ 3079 if(pSHCreateShellItem) 3080 { 3081 IShellItem *shellitem; 3082 hres = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem); 3083 ok(hres == S_OK, "got 0x%08x\n", hres); 3084 if(SUCCEEDED(hres)) 3085 { 3086 hres = pSHGetIDListFromObject((IUnknown*)shellitem, &pidl); 3087 ok(hres == S_OK, "got 0x%08x\n", hres); 3088 if(SUCCEEDED(hres)) 3089 { 3090 ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n"); 3091 ILFree(pidl); 3092 } 3093 IShellItem_Release(shellitem); 3094 } 3095 } 3096 else 3097 skip("no SHCreateShellItem.\n"); 3098 3099 /* Test IShellFolder */ 3100 hres = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl); 3101 ok(hres == S_OK, "got 0x%08x\n", hres); 3102 if(SUCCEEDED(hres)) 3103 { 3104 ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n"); 3105 ILFree(pidl); 3106 } 3107 3108 hres = IShellFolder_CreateViewObject(psfdesktop, NULL, &IID_IShellView, (void**)&psv); 3109 ok(hres == S_OK, "got 0x%08x\n", hres); 3110 if(SUCCEEDED(hres)) 3111 { 3112 IEnumIDList *peidl; 3113 IDataObject *pdo; 3114 SHCONTF enum_flags; 3115 3116 /* Test IFolderView */ 3117 hres = pSHGetIDListFromObject((IUnknown*)psv, &pidl); 3118 ok(hres == S_OK, "got 0x%08x\n", hres); 3119 if(SUCCEEDED(hres)) 3120 { 3121 ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n"); 3122 ILFree(pidl); 3123 } 3124 3125 /* Test IDataObject */ 3126 enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN; 3127 hres = IShellFolder_EnumObjects(psfdesktop, NULL, enum_flags, &peidl); 3128 ok(hres == S_OK, "got 0x%08x\n", hres); 3129 if(SUCCEEDED(hres)) 3130 { 3131 LPITEMIDLIST apidl[5]; 3132 UINT count = 0; 3133 for(count = 0; count < 5; count++) 3134 if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK) 3135 break; 3136 3137 if(count) 3138 { 3139 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, 1, (LPCITEMIDLIST*)apidl, 3140 &IID_IDataObject, NULL, (void**)&pdo); 3141 ok(hres == S_OK, "got 0x%08x\n", hres); 3142 if(SUCCEEDED(hres)) 3143 { 3144 pidl = (void*)0xDEADBEEF; 3145 hres = pSHGetIDListFromObject((IUnknown*)pdo, &pidl); 3146 ok(hres == S_OK, "got 0x%08x\n", hres); 3147 ok(pidl != NULL, "pidl is NULL.\n"); 3148 ok(ILIsEqual(pidl, apidl[0]), "pidl not equal.\n"); 3149 ILFree(pidl); 3150 3151 IDataObject_Release(pdo); 3152 } 3153 } 3154 else 3155 skip("No files found - skipping single-file test.\n"); 3156 3157 if(count > 1) 3158 { 3159 hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, count, (LPCITEMIDLIST*)apidl, 3160 &IID_IDataObject, NULL, (void**)&pdo); 3161 ok(hres == S_OK, "got 0x%08x\n", hres); 3162 if(SUCCEEDED(hres)) 3163 { 3164 pidl = (void*)0xDEADBEEF; 3165 hres = pSHGetIDListFromObject((IUnknown*)pdo, &pidl); 3166 ok(hres == E_NOINTERFACE || hres == E_FAIL /*Vista*/, 3167 "got 0x%08x\n", hres); 3168 ok(pidl == NULL, "pidl is not NULL.\n"); 3169 3170 IDataObject_Release(pdo); 3171 } 3172 } 3173 else 3174 skip("zero or one file found - skipping multi-file test.\n"); 3175 3176 for(i = 0; i < count; i++) 3177 ILFree(apidl[i]); 3178 3179 IEnumIDList_Release(peidl); 3180 } 3181 3182 IShellView_Release(psv); 3183 } 3184 3185 IShellFolder_Release(psfdesktop); 3186 ILFree(pidl_desktop); 3187 } 3188 3189 static void test_SHGetItemFromObject(void) 3190 { 3191 IUnknownImpl *punkimpl; 3192 IShellFolder *psfdesktop; 3193 LPITEMIDLIST pidl; 3194 IShellItem *psi; 3195 IUnknown *punk; 3196 HRESULT hres; 3197 struct if_count ifaces[] = 3198 { {&IID_IPersistIDList, 0}, 3199 {&IID_IPersistFolder2, 0}, 3200 {&IID_IDataObject, 0}, 3201 {&IID_IParentAndItem, 0}, 3202 {&IID_IFolderView, 0}, 3203 {NULL, 0} }; 3204 3205 if(!pSHGetItemFromObject) 3206 { 3207 skip("No SHGetItemFromObject.\n"); 3208 return; 3209 } 3210 3211 SHGetDesktopFolder(&psfdesktop); 3212 3213 if(0) 3214 { 3215 /* Crashes with Windows 7 */ 3216 pSHGetItemFromObject((IUnknown*)psfdesktop, &IID_IUnknown, NULL); 3217 pSHGetItemFromObject(NULL, &IID_IUnknown, NULL); 3218 pSHGetItemFromObject((IUnknown*)psfdesktop, NULL, (void**)&punk); 3219 } 3220 3221 hres = pSHGetItemFromObject(NULL, &IID_IUnknown, (void**)&punk); 3222 ok(hres == E_NOINTERFACE, "Got 0x%08x\n", hres); 3223 3224 punkimpl = heap_alloc(sizeof(*punkimpl)); 3225 punkimpl->IUnknown_iface.lpVtbl = &vt_IUnknown; 3226 punkimpl->ifaces = ifaces; 3227 punkimpl->unknown = 0; 3228 3229 /* The same as SHGetIDListFromObject */ 3230 hres = pSHGetIDListFromObject(&punkimpl->IUnknown_iface, &pidl); 3231 ok(hres == E_NOINTERFACE, "Got %x\n", hres); 3232 ok(ifaces[0].count, "interface not requested.\n"); 3233 ok(ifaces[1].count, "interface not requested.\n"); 3234 ok(ifaces[2].count, "interface not requested.\n"); 3235 todo_wine 3236 ok(ifaces[3].count || broken(!ifaces[3].count /*vista*/), 3237 "interface not requested.\n"); 3238 ok(ifaces[4].count || broken(!ifaces[4].count /*vista*/), 3239 "interface not requested.\n"); 3240 3241 ok(!punkimpl->unknown, "Got %d unknown.\n", punkimpl->unknown); 3242 heap_free(punkimpl); 3243 3244 /* Test IShellItem */ 3245 hres = pSHGetItemFromObject((IUnknown*)psfdesktop, &IID_IShellItem, (void**)&psi); 3246 ok(hres == S_OK, "Got 0x%08x\n", hres); 3247 if(SUCCEEDED(hres)) 3248 { 3249 IShellItem *psi2; 3250 hres = pSHGetItemFromObject((IUnknown*)psi, &IID_IShellItem, (void**)&psi2); 3251 ok(hres == S_OK, "Got 0x%08x\n", hres); 3252 if(SUCCEEDED(hres)) 3253 { 3254 todo_wine 3255 ok(psi == psi2, "Different instances (%p != %p).\n", psi, psi2); 3256 IShellItem_Release(psi2); 3257 } 3258 IShellItem_Release(psi); 3259 } 3260 3261 IShellFolder_Release(psfdesktop); 3262 } 3263 3264 static void test_SHCreateShellItemArray(void) 3265 { 3266 IShellFolder *pdesktopsf, *psf; 3267 IShellItemArray *psia; 3268 IEnumIDList *peidl; 3269 HRESULT hr; 3270 WCHAR cTestDirW[MAX_PATH]; 3271 LPITEMIDLIST pidl_testdir, pidl; 3272 static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0}; 3273 3274 if(!pSHCreateShellItemArray) { 3275 skip("No pSHCreateShellItemArray!\n"); 3276 return; 3277 } 3278 3279 if(0) 3280 { 3281 /* Crashes under native */ 3282 pSHCreateShellItemArray(NULL, NULL, 0, NULL, NULL); 3283 pSHCreateShellItemArray(NULL, NULL, 1, NULL, NULL); 3284 pSHCreateShellItemArray(NULL, pdesktopsf, 0, NULL, NULL); 3285 pSHCreateShellItemArray(pidl, NULL, 0, NULL, NULL); 3286 } 3287 3288 hr = pSHCreateShellItemArray(NULL, NULL, 0, NULL, &psia); 3289 ok(hr == E_POINTER, "got 0x%08x\n", hr); 3290 3291 SHGetDesktopFolder(&pdesktopsf); 3292 hr = pSHCreateShellItemArray(NULL, pdesktopsf, 0, NULL, &psia); 3293 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3294 3295 hr = pSHCreateShellItemArray(NULL, pdesktopsf, 1, NULL, &psia); 3296 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3297 3298 SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl); 3299 hr = pSHCreateShellItemArray(pidl, NULL, 0, NULL, &psia); 3300 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3301 ILFree(pidl); 3302 3303 GetCurrentDirectoryW(MAX_PATH, cTestDirW); 3304 myPathAddBackslashW(cTestDirW); 3305 lstrcatW(cTestDirW, testdirW); 3306 3307 CreateFilesFolders(); 3308 3309 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, cTestDirW, NULL, &pidl_testdir, 0); 3310 ok(hr == S_OK, "got 0x%08x\n", hr); 3311 if(SUCCEEDED(hr)) 3312 { 3313 hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder, 3314 (void**)&psf); 3315 ok(hr == S_OK, "Got 0x%08x\n", hr); 3316 } 3317 IShellFolder_Release(pdesktopsf); 3318 3319 if(FAILED(hr)) 3320 { 3321 skip("Failed to set up environment for SHCreateShellItemArray tests.\n"); 3322 ILFree(pidl_testdir); 3323 Cleanup(); 3324 return; 3325 } 3326 3327 hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl); 3328 ok(hr == S_OK, "Got %08x\n", hr); 3329 if(SUCCEEDED(hr)) 3330 { 3331 LPITEMIDLIST apidl[5]; 3332 UINT done, numitems, i; 3333 3334 for(done = 0; done < 5; done++) 3335 if(IEnumIDList_Next(peidl, 1, &apidl[done], NULL) != S_OK) 3336 break; 3337 ok(done == 5, "Got %d pidls\n", done); 3338 IEnumIDList_Release(peidl); 3339 3340 /* Create a ShellItemArray */ 3341 hr = pSHCreateShellItemArray(NULL, psf, done, (LPCITEMIDLIST*)apidl, &psia); 3342 ok(hr == S_OK, "Got 0x%08x\n", hr); 3343 if(SUCCEEDED(hr)) 3344 { 3345 IShellItem *psi; 3346 3347 if(0) 3348 { 3349 /* Crashes in Windows 7 */ 3350 IShellItemArray_GetCount(psia, NULL); 3351 } 3352 3353 IShellItemArray_GetCount(psia, &numitems); 3354 ok(numitems == done, "Got %d, expected %d\n", numitems, done); 3355 3356 hr = IShellItemArray_GetItemAt(psia, numitems, &psi); 3357 ok(hr == E_FAIL, "Got 0x%08x\n", hr); 3358 3359 /* Compare all the items */ 3360 for(i = 0; i < numitems; i++) 3361 { 3362 LPITEMIDLIST pidl_abs; 3363 pidl_abs = ILCombine(pidl_testdir, apidl[i]); 3364 3365 hr = IShellItemArray_GetItemAt(psia, i, &psi); 3366 ok(hr == S_OK, "(%d) Failed with 0x%08x\n", i, hr); 3367 if(SUCCEEDED(hr)) 3368 { 3369 hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl); 3370 ok(hr == S_OK, "Got 0x%08x\n", hr); 3371 if(SUCCEEDED(hr)) 3372 { 3373 ok(ILIsEqual(pidl_abs, pidl), "Pidl not equal.\n"); 3374 ILFree(pidl); 3375 } 3376 IShellItem_Release(psi); 3377 } 3378 ILFree(pidl_abs); 3379 } 3380 for(i = 0; i < done; i++) 3381 ILFree(apidl[i]); 3382 IShellItemArray_Release(psia); 3383 } 3384 } 3385 3386 /* SHCreateShellItemArrayFromShellItem */ 3387 if(pSHCreateShellItemArrayFromShellItem) 3388 { 3389 IShellItem *psi; 3390 3391 if(0) 3392 { 3393 /* Crashes under Windows 7 */ 3394 pSHCreateShellItemArrayFromShellItem(NULL, &IID_IShellItemArray, NULL); 3395 pSHCreateShellItemArrayFromShellItem(NULL, &IID_IShellItemArray, (void**)&psia); 3396 pSHCreateShellItemArrayFromShellItem(psi, &IID_IShellItemArray, NULL); 3397 } 3398 3399 hr = pSHCreateItemFromIDList(pidl_testdir, &IID_IShellItem, (void**)&psi); 3400 ok(hr == S_OK, "Got 0x%08x\n", hr); 3401 if(SUCCEEDED(hr)) 3402 { 3403 hr = pSHCreateShellItemArrayFromShellItem(psi, &IID_IShellItemArray, (void**)&psia); 3404 ok(hr == S_OK, "Got 0x%08x\n", hr); 3405 if(SUCCEEDED(hr)) 3406 { 3407 IShellItem *psi2; 3408 UINT count; 3409 hr = IShellItemArray_GetCount(psia, &count); 3410 ok(hr == S_OK, "Got 0x%08x\n", hr); 3411 ok(count == 1, "Got count %d\n", count); 3412 hr = IShellItemArray_GetItemAt(psia, 0, &psi2); 3413 ok(hr == S_OK, "Got 0x%08x\n", hr); 3414 todo_wine 3415 ok(psi != psi2, "ShellItems are of the same instance.\n"); 3416 if(SUCCEEDED(hr)) 3417 { 3418 LPITEMIDLIST pidl1, pidl2; 3419 hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl1); 3420 ok(hr == S_OK, "Got 0x%08x\n", hr); 3421 ok(pidl1 != NULL, "pidl1 was null.\n"); 3422 hr = pSHGetIDListFromObject((IUnknown*)psi2, &pidl2); 3423 ok(hr == S_OK, "Got 0x%08x\n", hr); 3424 ok(pidl2 != NULL, "pidl2 was null.\n"); 3425 ok(ILIsEqual(pidl1, pidl2), "pidls not equal.\n"); 3426 ILFree(pidl1); 3427 ILFree(pidl2); 3428 IShellItem_Release(psi2); 3429 } 3430 hr = IShellItemArray_GetItemAt(psia, 1, &psi2); 3431 ok(hr == E_FAIL, "Got 0x%08x\n", hr); 3432 IShellItemArray_Release(psia); 3433 } 3434 IShellItem_Release(psi); 3435 } 3436 } 3437 else 3438 skip("No SHCreateShellItemArrayFromShellItem.\n"); 3439 3440 if(pSHCreateShellItemArrayFromDataObject) 3441 { 3442 IShellView *psv; 3443 3444 if(0) 3445 { 3446 /* Crashes under Windows 7 */ 3447 pSHCreateShellItemArrayFromDataObject(NULL, &IID_IShellItemArray, NULL); 3448 } 3449 hr = pSHCreateShellItemArrayFromDataObject(NULL, &IID_IShellItemArray, (void**)&psia); 3450 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 3451 3452 hr = IShellFolder_CreateViewObject(psf, NULL, &IID_IShellView, (void**)&psv); 3453 ok(hr == S_OK, "got 0x%08x\n", hr); 3454 if(SUCCEEDED(hr)) 3455 { 3456 IEnumIDList *peidl; 3457 IDataObject *pdo; 3458 SHCONTF enum_flags; 3459 3460 enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN; 3461 hr = IShellFolder_EnumObjects(psf, NULL, enum_flags, &peidl); 3462 ok(hr == S_OK, "got 0x%08x\n", hr); 3463 if(SUCCEEDED(hr)) 3464 { 3465 LPITEMIDLIST apidl[5]; 3466 UINT count, i; 3467 3468 for(count = 0; count < 5; count++) 3469 if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK) 3470 break; 3471 ok(count == 5, "Got %d\n", count); 3472 3473 if(count) 3474 { 3475 hr = IShellFolder_GetUIObjectOf(psf, NULL, count, (LPCITEMIDLIST*)apidl, 3476 &IID_IDataObject, NULL, (void**)&pdo); 3477 ok(hr == S_OK, "Got 0x%08x\n", hr); 3478 if(SUCCEEDED(hr)) 3479 { 3480 hr = pSHCreateShellItemArrayFromDataObject(pdo, &IID_IShellItemArray, 3481 (void**)&psia); 3482 ok(hr == S_OK, "Got 0x%08x\n", hr); 3483 if(SUCCEEDED(hr)) 3484 { 3485 UINT count_sia, i; 3486 hr = IShellItemArray_GetCount(psia, &count_sia); 3487 ok(hr == S_OK, "Got 0x%08x\n", hr); 3488 ok(count_sia == count, "Counts differ (%d, %d)\n", count, count_sia); 3489 for(i = 0; i < count_sia; i++) 3490 { 3491 LPITEMIDLIST pidl_abs = ILCombine(pidl_testdir, apidl[i]); 3492 IShellItem *psi; 3493 hr = IShellItemArray_GetItemAt(psia, i, &psi); 3494 ok(hr == S_OK, "Got 0x%08x\n", hr); 3495 if(SUCCEEDED(hr)) 3496 { 3497 LPITEMIDLIST pidl; 3498 hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl); 3499 ok(hr == S_OK, "Got 0x%08x\n", hr); 3500 ok(pidl != NULL, "pidl as NULL.\n"); 3501 ok(ILIsEqual(pidl, pidl_abs), "pidls differ.\n"); 3502 ILFree(pidl); 3503 IShellItem_Release(psi); 3504 } 3505 ILFree(pidl_abs); 3506 } 3507 3508 IShellItemArray_Release(psia); 3509 } 3510 3511 IDataObject_Release(pdo); 3512 } 3513 for(i = 0; i < count; i++) 3514 ILFree(apidl[i]); 3515 } 3516 else 3517 skip("No files found - skipping test.\n"); 3518 3519 IEnumIDList_Release(peidl); 3520 } 3521 IShellView_Release(psv); 3522 } 3523 } 3524 else 3525 skip("No SHCreateShellItemArrayFromDataObject.\n"); 3526 3527 if(pSHCreateShellItemArrayFromIDLists) 3528 { 3529 WCHAR test1W[] = {'t','e','s','t','1','.','t','x','t',0}; 3530 WCHAR test1pathW[MAX_PATH]; 3531 LPITEMIDLIST pidltest1; 3532 LPCITEMIDLIST pidl_array[2]; 3533 3534 if(0) 3535 { 3536 /* Crashes */ 3537 hr = pSHCreateShellItemArrayFromIDLists(0, NULL, NULL); 3538 } 3539 3540 psia = (void*)0xdeadbeef; 3541 hr = pSHCreateShellItemArrayFromIDLists(0, NULL, &psia); 3542 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 3543 ok(psia == NULL, "Got %p\n", psia); 3544 3545 psia = (void*)0xdeadbeef; 3546 hr = pSHCreateShellItemArrayFromIDLists(0, pidl_array, &psia); 3547 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 3548 ok(psia == NULL, "Got %p\n", psia); 3549 3550 psia = (void*)0xdeadbeef; 3551 pidl_array[0] = NULL; 3552 hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia); 3553 todo_wine ok(hr == E_OUTOFMEMORY, "Got 0x%08x\n", hr); 3554 ok(psia == NULL, "Got %p\n", psia); 3555 3556 psia = (void*)0xdeadbeef; 3557 pidl_array[0] = pidl_testdir; 3558 pidl_array[1] = NULL; 3559 hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia); 3560 todo_wine ok(hr == S_OK || broken(hr == E_INVALIDARG) /* Vista */, "Got 0x%08x\n", hr); 3561 todo_wine ok(psia != NULL || broken(psia == NULL) /* Vista */, "Got %p\n", psia); 3562 if(SUCCEEDED(hr)) 3563 { 3564 IShellItem *psi; 3565 UINT count = 0; 3566 3567 hr = IShellItemArray_GetCount(psia, &count); 3568 ok(hr == S_OK, "Got 0x%08x\n", hr); 3569 ok(count == 2, "Got %d\n", count); 3570 3571 hr = IShellItemArray_GetItemAt(psia, 0, &psi); 3572 ok(hr == S_OK, "Got 0x%08x\n", hr); 3573 if(SUCCEEDED(hr)) 3574 { 3575 LPWSTR path; 3576 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); 3577 ok(hr == S_OK, "Got 0x%08x\n", hr); 3578 ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path)); 3579 if(SUCCEEDED(hr)) 3580 CoTaskMemFree(path); 3581 3582 IShellItem_Release(psi); 3583 } 3584 3585 hr = IShellItemArray_GetItemAt(psia, 1, &psi); 3586 ok(hr == S_OK, "Got 0x%08x\n", hr); 3587 if(SUCCEEDED(hr)) 3588 { 3589 LPWSTR path; 3590 WCHAR desktoppath[MAX_PATH]; 3591 BOOL result; 3592 3593 result = SHGetSpecialFolderPathW(NULL, desktoppath, CSIDL_DESKTOPDIRECTORY, FALSE); 3594 ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError()); 3595 3596 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); 3597 ok(hr == S_OK, "Got 0x%08x\n", hr); 3598 ok(!lstrcmpW(path, desktoppath), "Got %s\n", wine_dbgstr_w(path)); 3599 if(SUCCEEDED(hr)) 3600 CoTaskMemFree(path); 3601 3602 IShellItem_Release(psi); 3603 } 3604 3605 3606 IShellItemArray_Release(psia); 3607 } 3608 3609 3610 /* Single pidl */ 3611 psia = (void*)0xdeadbeef; 3612 pidl_array[0] = pidl_testdir; 3613 hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia); 3614 ok(hr == S_OK, "Got 0x%08x\n", hr); 3615 if(SUCCEEDED(hr)) 3616 { 3617 IShellItem *psi; 3618 UINT count = 0; 3619 3620 hr = IShellItemArray_GetCount(psia, &count); 3621 ok(hr == S_OK, "Got 0x%08x\n", hr); 3622 ok(count == 1, "Got %d\n", count); 3623 3624 hr = IShellItemArray_GetItemAt(psia, 0, &psi); 3625 ok(hr == S_OK, "Got 0x%08x\n", hr); 3626 if(SUCCEEDED(hr)) 3627 { 3628 LPWSTR path; 3629 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); 3630 ok(hr == S_OK, "Got 0x%08x\n", hr); 3631 ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path)); 3632 if(SUCCEEDED(hr)) 3633 CoTaskMemFree(path); 3634 3635 IShellItem_Release(psi); 3636 } 3637 3638 IShellItemArray_Release(psia); 3639 } 3640 3641 3642 lstrcpyW(test1pathW, cTestDirW); 3643 myPathAddBackslashW(test1pathW); 3644 lstrcatW(test1pathW, test1W); 3645 3646 SHGetDesktopFolder(&pdesktopsf); 3647 3648 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, test1pathW, NULL, &pidltest1, NULL); 3649 ok(hr == S_OK, "Got 0x%08x\n", hr); 3650 if(SUCCEEDED(hr)) 3651 { 3652 psia = (void*)0xdeadbeef; 3653 pidl_array[0] = pidl_testdir; 3654 pidl_array[1] = pidltest1; 3655 hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia); 3656 ok(hr == S_OK, "Got 0x%08x\n", hr); 3657 if(SUCCEEDED(hr)) 3658 { 3659 IShellItem *psi; 3660 UINT count = 0; 3661 3662 hr = IShellItemArray_GetCount(psia, &count); 3663 ok(hr == S_OK, "Got 0x%08x\n", hr); 3664 ok(count == 2, "Got %d\n", count); 3665 3666 hr = IShellItemArray_GetItemAt(psia, 0, &psi); 3667 ok(hr == S_OK, "Got 0x%08x\n", hr); 3668 if(SUCCEEDED(hr)) 3669 { 3670 LPWSTR path; 3671 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); 3672 ok(hr == S_OK, "Got 0x%08x\n", hr); 3673 ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path)); 3674 if(SUCCEEDED(hr)) 3675 CoTaskMemFree(path); 3676 3677 IShellItem_Release(psi); 3678 } 3679 3680 hr = IShellItemArray_GetItemAt(psia, 1, &psi); 3681 ok(hr == S_OK, "Got 0x%08x\n", hr); 3682 if(SUCCEEDED(hr)) 3683 { 3684 LPWSTR path; 3685 hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); 3686 ok(hr == S_OK, "Got 0x%08x\n", hr); 3687 ok(!lstrcmpW(path, test1pathW), "Got %s\n", wine_dbgstr_w(path)); 3688 if(SUCCEEDED(hr)) 3689 CoTaskMemFree(path); 3690 3691 IShellItem_Release(psi); 3692 } 3693 3694 3695 IShellItemArray_Release(psia); 3696 } 3697 3698 ILFree(pidltest1); 3699 } 3700 3701 IShellFolder_Release(pdesktopsf); 3702 } 3703 else 3704 skip("No SHCreateShellItemArrayFromIDLists.\n"); 3705 3706 IShellFolder_Release(psf); 3707 ILFree(pidl_testdir); 3708 Cleanup(); 3709 } 3710 3711 static void test_ShellItemArrayEnumItems(void) 3712 { 3713 IShellFolder *pdesktopsf, *psf; 3714 IEnumIDList *peidl; 3715 WCHAR cTestDirW[MAX_PATH]; 3716 HRESULT hr; 3717 LPITEMIDLIST pidl_testdir; 3718 static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0}; 3719 3720 if(!pSHCreateShellItemArray) 3721 { 3722 win_skip("No SHCreateShellItemArray, skipping test...\n"); 3723 return; 3724 } 3725 3726 CreateFilesFolders(); 3727 3728 SHGetDesktopFolder(&pdesktopsf); 3729 3730 GetCurrentDirectoryW(MAX_PATH, cTestDirW); 3731 myPathAddBackslashW(cTestDirW); 3732 lstrcatW(cTestDirW, testdirW); 3733 3734 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, cTestDirW, NULL, &pidl_testdir, 0); 3735 ok(hr == S_OK, "got 0x%08x\n", hr); 3736 if(SUCCEEDED(hr)) 3737 { 3738 hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder, 3739 (void**)&psf); 3740 ok(hr == S_OK, "Got 0x%08x\n", hr); 3741 ILFree(pidl_testdir); 3742 } 3743 IShellFolder_Release(pdesktopsf); 3744 if (FAILED(hr)) return; 3745 3746 hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl); 3747 ok(hr == S_OK, "Got %08x\n", hr); 3748 if(SUCCEEDED(hr)) 3749 { 3750 IShellItemArray *psia; 3751 LPITEMIDLIST apidl[5]; 3752 UINT done, numitems, i; 3753 3754 for(done = 0; done < 5; done++) 3755 if(IEnumIDList_Next(peidl, 1, &apidl[done], NULL) != S_OK) 3756 break; 3757 ok(done == 5, "Got %d pidls\n", done); 3758 IEnumIDList_Release(peidl); 3759 3760 /* Create a ShellItemArray */ 3761 hr = pSHCreateShellItemArray(NULL, psf, done, (LPCITEMIDLIST*)apidl, &psia); 3762 ok(hr == S_OK, "Got 0x%08x\n", hr); 3763 if(SUCCEEDED(hr)) 3764 { 3765 IEnumShellItems *iesi; 3766 IShellItem *my_array[10]; 3767 ULONG fetched; 3768 3769 IShellItemArray_GetCount(psia, &numitems); 3770 ok(numitems == done, "Got %d, expected %d\n", numitems, done); 3771 3772 iesi = NULL; 3773 hr = IShellItemArray_EnumItems(psia, &iesi); 3774 ok(hr == S_OK, "Got 0x%08x\n", hr); 3775 ok(iesi != NULL, "Got NULL\n"); 3776 if(SUCCEEDED(hr)) 3777 { 3778 IEnumShellItems *iesi2; 3779 3780 /* This should fail according to the documentation and Win7+ */ 3781 for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef; 3782 hr = IEnumShellItems_Next(iesi, 2, my_array, NULL); 3783 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr); 3784 for(i = 0; i < 2; i++) 3785 { 3786 ok(my_array[i] == (void*)0xdeadbeef || 3787 broken(my_array[i] != (void*)0xdeadbeef && my_array[i] != NULL), /* Vista */ 3788 "Got %p (%d)\n", my_array[i], i); 3789 3790 if(my_array[i] != (void*)0xdeadbeef) 3791 IShellItem_Release(my_array[i]); 3792 } 3793 ok(my_array[2] == (void*)0xdeadbeef, "Got %p\n", my_array[2]); 3794 3795 IEnumShellItems_Reset(iesi); 3796 for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef; 3797 hr = IEnumShellItems_Next(iesi, 1, my_array, NULL); 3798 ok(hr == S_OK, "Got 0x%08x\n", hr); 3799 ok(my_array[0] != NULL && my_array[0] != (void*)0xdeadbeef, "Got %p\n", my_array[0]); 3800 if(my_array[0] != NULL && my_array[0] != (void*)0xdeadbeef) 3801 IShellItem_Release(my_array[0]); 3802 ok(my_array[1] == (void*)0xdeadbeef, "Got %p\n", my_array[1]); 3803 3804 IEnumShellItems_Reset(iesi); 3805 fetched = 0; 3806 for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef; 3807 hr = IEnumShellItems_Next(iesi, numitems, my_array, &fetched); 3808 ok(hr == S_OK, "Got 0x%08x\n", hr); 3809 ok(fetched == numitems, "Got %d\n", fetched); 3810 for(i = 0;i < numitems; i++) 3811 { 3812 ok(my_array[i] != NULL && my_array[i] != (void*)0xdeadbeef, 3813 "Got %p at %d\n", my_array[i], i); 3814 3815 if(my_array[i] != NULL && my_array[i] != (void*)0xdeadbeef) 3816 IShellItem_Release(my_array[i]); 3817 } 3818 ok(my_array[i] == (void*)0xdeadbeef, "Got %p\n", my_array[i]); 3819 3820 /* Compare all the items */ 3821 IEnumShellItems_Reset(iesi); 3822 for(i = 0; i < numitems; i++) 3823 { 3824 IShellItem *psi; 3825 int order; 3826 3827 hr = IShellItemArray_GetItemAt(psia, i, &psi); 3828 ok(hr == S_OK, "Got 0x%08x\n", hr); 3829 hr = IEnumShellItems_Next(iesi, 1, my_array, &fetched); 3830 ok(hr == S_OK, "Got 0x%08x\n", hr); 3831 ok(fetched == 1, "Got %d\n", fetched); 3832 3833 hr = IShellItem_Compare(psi, my_array[0], 0, &order); 3834 ok(hr == S_OK, "Got 0x%08x\n", hr); 3835 ok(order == 0, "Got %d\n", order); 3836 3837 IShellItem_Release(psi); 3838 IShellItem_Release(my_array[0]); 3839 } 3840 3841 my_array[0] = (void*)0xdeadbeef; 3842 hr = IEnumShellItems_Next(iesi, 1, my_array, &fetched); 3843 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 3844 ok(fetched == 0, "Got %d\n", fetched); 3845 ok(my_array[0] == (void*)0xdeadbeef, "Got %p\n", my_array[0]); 3846 3847 /* Cloning not implemented anywhere */ 3848 iesi2 = (void*)0xdeadbeef; 3849 hr = IEnumShellItems_Clone(iesi, &iesi2); 3850 ok(hr == E_NOTIMPL, "Got 0x%08x\n", hr); 3851 ok(iesi2 == NULL || broken(iesi2 == (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2); 3852 3853 IEnumShellItems_Release(iesi); 3854 } 3855 3856 IShellItemArray_Release(psia); 3857 } 3858 3859 for(i = 0; i < done; i++) 3860 ILFree(apidl[i]); 3861 } 3862 3863 IShellFolder_Release(psf); 3864 } 3865 3866 3867 static void test_ShellItemBindToHandler(void) 3868 { 3869 IShellItem *psi; 3870 LPITEMIDLIST pidl_desktop; 3871 HRESULT hr; 3872 3873 if(!pSHCreateShellItem) 3874 { 3875 skip("SHCreateShellItem missing.\n"); 3876 return; 3877 } 3878 3879 hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop); 3880 ok(hr == S_OK, "Got 0x%08x\n", hr); 3881 if(SUCCEEDED(hr)) 3882 { 3883 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psi); 3884 ok(hr == S_OK, "Got 0x%08x\n", hr); 3885 } 3886 if(SUCCEEDED(hr)) 3887 { 3888 IPersistFolder2 *ppf2; 3889 IUnknown *punk; 3890 3891 if(0) 3892 { 3893 /* Crashes under Windows 7 */ 3894 IShellItem_BindToHandler(psi, NULL, NULL, NULL, NULL); 3895 IShellItem_BindToHandler(psi, NULL, &IID_IUnknown, &IID_IUnknown, NULL); 3896 } 3897 hr = IShellItem_BindToHandler(psi, NULL, &IID_IUnknown, &IID_IUnknown, (void**)&punk); 3898 ok(hr == MK_E_NOOBJECT, "Got 0x%08x\n", hr); 3899 3900 /* BHID_SFObject */ 3901 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IShellFolder, (void**)&punk); 3902 ok(hr == S_OK, "Got 0x%08x\n", hr); 3903 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3904 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IPersistFolder2, (void**)&ppf2); 3905 ok(hr == S_OK, "Got 0x%08x\n", hr); 3906 if(SUCCEEDED(hr)) 3907 { 3908 LPITEMIDLIST pidl_tmp; 3909 hr = IPersistFolder2_GetCurFolder(ppf2, &pidl_tmp); 3910 ok(hr == S_OK, "Got 0x%08x\n", hr); 3911 if(SUCCEEDED(hr)) 3912 { 3913 ok(ILIsEqual(pidl_desktop, pidl_tmp), "Pidl not equal (%p, %p)\n", pidl_desktop, pidl_tmp); 3914 ILFree(pidl_tmp); 3915 } 3916 IPersistFolder2_Release(ppf2); 3917 } 3918 3919 /* BHID_SFUIObject */ 3920 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFUIObject, &IID_IDataObject, (void**)&punk); 3921 ok(hr == S_OK || broken(hr == E_NOINTERFACE /* XP */), "Got 0x%08x\n", hr); 3922 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3923 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFUIObject, &IID_IContextMenu, (void**)&punk); 3924 ok(hr == S_OK || broken(hr == E_NOINTERFACE /* XP */), "Got 0x%08x\n", hr); 3925 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3926 3927 /* BHID_DataObject */ 3928 hr = IShellItem_BindToHandler(psi, NULL, &BHID_DataObject, &IID_IDataObject, (void**)&punk); 3929 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 3930 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3931 3932 todo_wine 3933 { 3934 /* BHID_SFViewObject */ 3935 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFViewObject, &IID_IShellView, (void**)&punk); 3936 ok(hr == S_OK, "Got 0x%08x\n", hr); 3937 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3938 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFViewObject, &IID_IShellFolderView, (void**)&punk); 3939 ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr); 3940 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3941 3942 /* BHID_Storage */ 3943 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Storage, &IID_IStream, (void**)&punk); 3944 ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr); 3945 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3946 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Storage, &IID_IUnknown, (void**)&punk); 3947 ok(hr == S_OK, "Got 0x%08x\n", hr); 3948 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3949 3950 /* BHID_Stream */ 3951 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Stream, &IID_IStream, (void**)&punk); 3952 ok(hr == E_NOINTERFACE, "Got 0x%08x\n", hr); 3953 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3954 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Stream, &IID_IUnknown, (void**)&punk); 3955 ok(hr == S_OK, "Got 0x%08x\n", hr); 3956 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3957 3958 /* BHID_StorageEnum */ 3959 hr = IShellItem_BindToHandler(psi, NULL, &BHID_StorageEnum, &IID_IEnumShellItems, (void**)&punk); 3960 ok(hr == S_OK, "Got 0x%08x\n", hr); 3961 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3962 3963 /* BHID_Transfer 3964 ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is 3965 supported starting from Win8. */ 3966 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_ITransferSource, (void**)&punk); 3967 ok(hr == S_OK || broken(FAILED(hr)) /* pre-Vista */, "Got 0x%08x\n", hr); 3968 if(SUCCEEDED(hr)) 3969 { 3970 IUnknown_Release(punk); 3971 3972 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_ITransferDestination, (void**)&punk); 3973 ok(hr == S_OK, "Got 0x%08x\n", hr); 3974 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3975 3976 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_IUnknown, (void**)&punk); 3977 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* pre-Win8 */, "Got 0x%08x\n", hr); 3978 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3979 } 3980 3981 /* BHID_EnumItems */ 3982 hr = IShellItem_BindToHandler(psi, NULL, &BHID_EnumItems, &IID_IEnumShellItems, (void**)&punk); 3983 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 3984 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3985 3986 /* BHID_Filter */ 3987 hr = IShellItem_BindToHandler(psi, NULL, &BHID_Filter, &IID_IUnknown, (void**)&punk); 3988 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 3989 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3990 3991 /* BHID_LinkTargetItem */ 3992 hr = IShellItem_BindToHandler(psi, NULL, &BHID_LinkTargetItem, &IID_IShellItem, (void**)&punk); 3993 ok(hr == E_NOINTERFACE || broken(hr == E_INVALIDARG /* XP */), "Got 0x%08x\n", hr); 3994 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3995 hr = IShellItem_BindToHandler(psi, NULL, &BHID_LinkTargetItem, &IID_IUnknown, (void**)&punk); 3996 ok(hr == E_NOINTERFACE || broken(hr == E_INVALIDARG /* XP */), "Got 0x%08x\n", hr); 3997 if(SUCCEEDED(hr)) IUnknown_Release(punk); 3998 3999 /* BHID_PropertyStore */ 4000 hr = IShellItem_BindToHandler(psi, NULL, &BHID_PropertyStore, &IID_IPropertyStore, (void**)&punk); 4001 ok(hr == E_NOINTERFACE || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 4002 if(SUCCEEDED(hr)) IUnknown_Release(punk); 4003 hr = IShellItem_BindToHandler(psi, NULL, &BHID_PropertyStore, &IID_IPropertyStoreFactory, (void**)&punk); 4004 ok(hr == E_NOINTERFACE || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 4005 if(SUCCEEDED(hr)) IUnknown_Release(punk); 4006 4007 /* BHID_ThumbnailHandler */ 4008 hr = IShellItem_BindToHandler(psi, NULL, &BHID_ThumbnailHandler, &IID_IUnknown, (void**)&punk); 4009 ok(hr == E_INVALIDARG || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 4010 if(SUCCEEDED(hr)) IUnknown_Release(punk); 4011 4012 /* BHID_AssociationArray */ 4013 hr = IShellItem_BindToHandler(psi, NULL, &BHID_AssociationArray, &IID_IQueryAssociations, (void**)&punk); 4014 ok(hr == S_OK || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 4015 if(SUCCEEDED(hr)) IUnknown_Release(punk); 4016 4017 /* BHID_EnumAssocHandlers */ 4018 hr = IShellItem_BindToHandler(psi, NULL, &BHID_EnumAssocHandlers, &IID_IUnknown, (void**)&punk); 4019 ok(hr == E_NOINTERFACE || broken(hr == MK_E_NOOBJECT /* XP */), "Got 0x%08x\n", hr); 4020 if(SUCCEEDED(hr)) IUnknown_Release(punk); 4021 } 4022 4023 IShellItem_Release(psi); 4024 } 4025 else 4026 skip("Failed to create ShellItem.\n"); 4027 4028 ILFree(pidl_desktop); 4029 } 4030 4031 static void test_ShellItemGetAttributes(void) 4032 { 4033 IShellItem *psi, *psi_folder1, *psi_file1; 4034 IShellFolder *pdesktopsf; 4035 LPITEMIDLIST pidl_desktop, pidl; 4036 SFGAOF sfgao; 4037 HRESULT hr; 4038 WCHAR curdirW[MAX_PATH]; 4039 WCHAR buf[MAX_PATH]; 4040 static const WCHAR testdir1W[] = {'t','e','s','t','d','i','r',0}; 4041 static const WCHAR testfile1W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0}; 4042 4043 if(!pSHCreateShellItem) 4044 { 4045 skip("SHCreateShellItem missing.\n"); 4046 return; 4047 } 4048 4049 hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop); 4050 ok(hr == S_OK, "Got 0x%08x\n", hr); 4051 if(SUCCEEDED(hr)) 4052 { 4053 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psi); 4054 ok(hr == S_OK, "Got 0x%08x\n", hr); 4055 ILFree(pidl_desktop); 4056 } 4057 if(FAILED(hr)) 4058 { 4059 skip("Skipping tests.\n"); 4060 return; 4061 } 4062 4063 if(0) 4064 { 4065 /* Crashes on native (Win 7) */ 4066 IShellItem_GetAttributes(psi, 0, NULL); 4067 } 4068 4069 /* Test GetAttributes on the desktop folder. */ 4070 sfgao = 0xdeadbeef; 4071 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER, &sfgao); 4072 ok(hr == S_OK || broken(hr == E_FAIL) /* <Vista */, "Got 0x%08x\n", hr); 4073 ok(sfgao == SFGAO_FOLDER || broken(sfgao == 0) /* <Vista */, "Got 0x%08x\n", sfgao); 4074 4075 IShellItem_Release(psi); 4076 4077 CreateFilesFolders(); 4078 4079 SHGetDesktopFolder(&pdesktopsf); 4080 4081 GetCurrentDirectoryW(MAX_PATH, curdirW); 4082 myPathAddBackslashW(curdirW); 4083 4084 lstrcpyW(buf, curdirW); 4085 lstrcatW(buf, testdir1W); 4086 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, &pidl, NULL); 4087 ok(hr == S_OK, "got 0x%08x\n", hr); 4088 hr = pSHCreateShellItem(NULL, NULL, pidl, &psi_folder1); 4089 ok(hr == S_OK, "Got 0x%08x\n", sfgao); 4090 ILFree(pidl); 4091 4092 lstrcpyW(buf, curdirW); 4093 lstrcatW(buf, testfile1W); 4094 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, &pidl, NULL); 4095 ok(hr == S_OK, "got 0x%08x\n", hr); 4096 hr = pSHCreateShellItem(NULL, NULL, pidl, &psi_file1); 4097 ok(hr == S_OK, "Got 0x%08x\n", sfgao); 4098 ILFree(pidl); 4099 4100 IShellFolder_Release(pdesktopsf); 4101 4102 sfgao = 0xdeadbeef; 4103 hr = IShellItem_GetAttributes(psi_folder1, 0, &sfgao); 4104 ok(hr == S_OK, "Got 0x%08x\n", hr); 4105 ok(sfgao == 0, "Got 0x%08x\n", sfgao); 4106 4107 sfgao = 0xdeadbeef; 4108 hr = IShellItem_GetAttributes(psi_folder1, SFGAO_FOLDER, &sfgao); 4109 ok(hr == S_OK, "Got 0x%08x\n", hr); 4110 ok(sfgao == SFGAO_FOLDER, "Got 0x%08x\n", sfgao); 4111 4112 sfgao = 0xdeadbeef; 4113 hr = IShellItem_GetAttributes(psi_file1, SFGAO_FOLDER, &sfgao); 4114 ok(hr == S_FALSE, "Got 0x%08x\n", hr); 4115 ok(sfgao == 0, "Got 0x%08x\n", sfgao); 4116 4117 IShellItem_Release(psi_folder1); 4118 IShellItem_Release(psi_file1); 4119 4120 Cleanup(); 4121 } 4122 4123 static void test_ShellItemArrayGetAttributes(void) 4124 { 4125 IShellItemArray *psia_files, *psia_folders1, *psia_folders2, *psia_all; 4126 IShellFolder *pdesktopsf; 4127 LPCITEMIDLIST pidl_array[5]; 4128 SFGAOF attr; 4129 HRESULT hr; 4130 WCHAR curdirW[MAX_PATH]; 4131 WCHAR buf[MAX_PATH]; 4132 UINT i; 4133 static const WCHAR testdir1W[] = {'t','e','s','t','d','i','r',0}; 4134 static const WCHAR testdir2W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0}; 4135 static const WCHAR testdir3W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0}; 4136 static const WCHAR testfile1W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0}; 4137 static const WCHAR testfile2W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0}; 4138 static const WCHAR *testfilesW[5] = { testdir1W, testdir2W, testdir3W, testfile1W, testfile2W }; 4139 4140 if(!pSHCreateShellItemArrayFromShellItem) 4141 { 4142 win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n"); 4143 return; 4144 } 4145 4146 CreateFilesFolders(); 4147 CreateDirectoryA(".\\testdir\\testdir3", NULL); 4148 4149 SHGetDesktopFolder(&pdesktopsf); 4150 4151 GetCurrentDirectoryW(MAX_PATH, curdirW); 4152 myPathAddBackslashW(curdirW); 4153 4154 for(i = 0; i < 5; i++) 4155 { 4156 lstrcpyW(buf, curdirW); 4157 lstrcatW(buf, testfilesW[i]); 4158 hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, (LPITEMIDLIST*)&pidl_array[i], NULL); 4159 ok(hr == S_OK, "got 0x%08x\n", hr); 4160 } 4161 IShellFolder_Release(pdesktopsf); 4162 4163 hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia_folders1); 4164 ok(hr == S_OK, "got 0x%08x\n", hr); 4165 hr = pSHCreateShellItemArrayFromIDLists(2, &pidl_array[1], &psia_folders2); 4166 ok(hr == S_OK, "got 0x%08x\n", hr); 4167 hr = pSHCreateShellItemArrayFromIDLists(2, &pidl_array[3], &psia_files); 4168 ok(hr == S_OK, "got 0x%08x\n", hr); 4169 hr = pSHCreateShellItemArrayFromIDLists(4, &pidl_array[1], &psia_all); /* All except the first */ 4170 ok(hr == S_OK, "got 0x%08x\n", hr); 4171 4172 for(i = 0; i < 5; i++) 4173 ILFree((LPITEMIDLIST)pidl_array[i]); 4174 4175 /* [testfolder/, testfolder/testfolder2] seems to break in Vista */ 4176 attr = 0xdeadbeef; 4177 hr = IShellItemArray_GetAttributes(psia_folders1, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr); 4178 ok(hr == S_OK || broken(hr == E_UNEXPECTED) /* Vista */, "Got 0x%08x\n", hr); 4179 ok(attr == SFGAO_FOLDER || broken(attr == 0) /* Vista */, "Got 0x%08x\n", attr); 4180 attr = 0xdeadbeef; 4181 hr = IShellItemArray_GetAttributes(psia_folders1, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr); 4182 ok(hr == S_OK || broken(hr == E_UNEXPECTED) /* Vista */, "Got 0x%08x\n", hr); 4183 ok(attr == SFGAO_FOLDER || broken(attr == 0) /* Vista */, "Got 0x%08x\n", attr); 4184 4185 /* [testfolder/testfolder2, testfolder/testfolder3] works */ 4186 attr = 0xdeadbeef; 4187 hr = IShellItemArray_GetAttributes(psia_folders2, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr); 4188 ok(hr == S_OK, "Got 0x%08x\n", hr); 4189 ok(attr == SFGAO_FOLDER, "Got 0x%08x\n", attr); 4190 attr = 0xdeadbeef; 4191 hr = IShellItemArray_GetAttributes(psia_files, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr); 4192 ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr); 4193 ok(attr == 0, "Got 0x%08x\n", attr); 4194 attr = 0xdeadbeef; 4195 hr = IShellItemArray_GetAttributes(psia_all, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr); 4196 ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr); 4197 ok(attr == 0, "Got 0x%08x\n", attr); 4198 attr = 0xdeadbeef; 4199 hr = IShellItemArray_GetAttributes(psia_folders2, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr); 4200 ok(hr == S_OK, "Got 0x%08x\n", hr); 4201 ok(attr == SFGAO_FOLDER, "Got 0x%08x\n", attr); 4202 attr = 0xdeadbeef; 4203 hr = IShellItemArray_GetAttributes(psia_files, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr); 4204 ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr); 4205 ok(attr == 0, "Got 0x%08x\n", attr); 4206 attr = 0xdeadbeef; 4207 hr = IShellItemArray_GetAttributes(psia_all, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr); 4208 ok(hr == S_OK, "Got 0x%08x\n", hr); 4209 ok(attr == SFGAO_FOLDER, "Got 0x%08x\n", attr); 4210 4211 IShellItemArray_Release(psia_folders1); 4212 IShellItemArray_Release(psia_folders2); 4213 IShellItemArray_Release(psia_files); 4214 IShellItemArray_Release(psia_all); 4215 4216 RemoveDirectoryA(".\\testdir\\testdir3"); 4217 Cleanup(); 4218 } 4219 4220 static WCHAR *get_empty_cddrive(void) 4221 { 4222 static WCHAR cdrom_drive[] = {'A',':','\\',0}; 4223 DWORD drives = GetLogicalDrives(); 4224 4225 cdrom_drive[0] = 'A'; 4226 while (drives) 4227 { 4228 if ((drives & 1) && 4229 GetDriveTypeW(cdrom_drive) == DRIVE_CDROM && 4230 GetFileAttributesW(cdrom_drive) == INVALID_FILE_ATTRIBUTES) 4231 { 4232 return cdrom_drive; 4233 } 4234 4235 drives = drives >> 1; 4236 cdrom_drive[0]++; 4237 } 4238 return NULL; 4239 } 4240 4241 static void test_SHParseDisplayName(void) 4242 { 4243 LPITEMIDLIST pidl1, pidl2; 4244 IShellFolder *desktop; 4245 WCHAR dirW[MAX_PATH]; 4246 WCHAR nameW[10]; 4247 WCHAR *cdrom; 4248 HRESULT hr; 4249 BOOL ret, is_wow64; 4250 4251 if (0) 4252 { 4253 /* crashes on native */ 4254 SHParseDisplayName(NULL, NULL, NULL, 0, NULL); 4255 nameW[0] = 0; 4256 SHParseDisplayName(nameW, NULL, NULL, 0, NULL); 4257 } 4258 4259 pidl1 = (LPITEMIDLIST)0xdeadbeef; 4260 hr = SHParseDisplayName(NULL, NULL, &pidl1, 0, NULL); 4261 ok(broken(hr == E_OUTOFMEMORY) /* < Vista */ || 4262 hr == E_INVALIDARG, "failed %08x\n", hr); 4263 ok(pidl1 == 0, "expected null ptr, got %p\n", pidl1); 4264 4265 /* dummy name */ 4266 nameW[0] = 0; 4267 hr = SHParseDisplayName(nameW, NULL, &pidl1, 0, NULL); 4268 ok(hr == S_OK, "failed %08x\n", hr); 4269 hr = SHGetDesktopFolder(&desktop); 4270 ok(hr == S_OK, "failed %08x\n", hr); 4271 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, nameW, NULL, &pidl2, NULL); 4272 ok(hr == S_OK, "failed %08x\n", hr); 4273 ret = ILIsEqual(pidl1, pidl2); 4274 ok(ret == TRUE, "expected equal idls\n"); 4275 ILFree(pidl1); 4276 ILFree(pidl2); 4277 4278 /* with path */ 4279 GetWindowsDirectoryW( dirW, MAX_PATH ); 4280 4281 hr = SHParseDisplayName(dirW, NULL, &pidl1, 0, NULL); 4282 ok(hr == S_OK, "failed %08x\n", hr); 4283 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, dirW, NULL, &pidl2, NULL); 4284 ok(hr == S_OK, "failed %08x\n", hr); 4285 4286 ret = ILIsEqual(pidl1, pidl2); 4287 ok(ret == TRUE, "expected equal idls\n"); 4288 ILFree(pidl1); 4289 ILFree(pidl2); 4290 4291 /* system32 is not redirected to syswow64 on WOW64 */ 4292 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE; 4293 if (is_wow64) 4294 { 4295 UINT len; 4296 *dirW = 0; 4297 len = GetSystemDirectoryW(dirW, MAX_PATH); 4298 ok(len > 0, "GetSystemDirectoryW failed: %u\n", GetLastError()); 4299 hr = SHParseDisplayName(dirW, NULL, &pidl1, 0, NULL); 4300 ok(hr == S_OK, "failed %08x\n", hr); 4301 *dirW = 0; 4302 len = GetSystemWow64DirectoryW(dirW, MAX_PATH); 4303 ok(len > 0, "GetSystemWow64DirectoryW failed: %u\n", GetLastError()); 4304 hr = SHParseDisplayName(dirW, NULL, &pidl2, 0, NULL); 4305 ok(hr == S_OK, "failed %08x\n", hr); 4306 ret = ILIsEqual(pidl1, pidl2); 4307 ok(ret == FALSE, "expected different idls\n"); 4308 ILFree(pidl1); 4309 ILFree(pidl2); 4310 } 4311 4312 IShellFolder_Release(desktop); 4313 4314 cdrom = get_empty_cddrive(); 4315 if (!cdrom) 4316 skip("No empty cdrom drive found, skipping test\n"); 4317 else 4318 { 4319 hr = SHParseDisplayName(cdrom, NULL, &pidl1, 0, NULL); 4320 ok(hr == S_OK, "failed %08x\n", hr); 4321 if (SUCCEEDED(hr)) ILFree(pidl1); 4322 } 4323 } 4324 4325 static void test_desktop_IPersist(void) 4326 { 4327 IShellFolder *desktop; 4328 IPersist *persist; 4329 IPersistFolder2 *ppf2; 4330 CLSID clsid; 4331 HRESULT hr; 4332 4333 hr = SHGetDesktopFolder(&desktop); 4334 ok(hr == S_OK, "failed %08x\n", hr); 4335 4336 hr = IShellFolder_QueryInterface(desktop, &IID_IPersist, (void**)&persist); 4337 ok(hr == S_OK, "failed %08x\n", hr); 4338 4339 if (hr == S_OK) 4340 { 4341 if (0) 4342 { 4343 /* crashes on native */ 4344 IPersist_GetClassID(persist, NULL); 4345 } 4346 memset(&clsid, 0, sizeof(clsid)); 4347 hr = IPersist_GetClassID(persist, &clsid); 4348 ok(hr == S_OK, "failed %08x\n", hr); 4349 ok(IsEqualIID(&CLSID_ShellDesktop, &clsid), "Expected CLSID_ShellDesktop\n"); 4350 IPersist_Release(persist); 4351 } 4352 4353 hr = IShellFolder_QueryInterface(desktop, &IID_IPersistFolder2, (void**)&ppf2); 4354 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* pre-Vista */, "failed %08x\n", hr); 4355 if(SUCCEEDED(hr)) 4356 { 4357 IPersistFolder *ppf; 4358 LPITEMIDLIST pidl; 4359 hr = IShellFolder_QueryInterface(desktop, &IID_IPersistFolder, (void**)&ppf); 4360 ok(hr == S_OK, "IID_IPersistFolder2 without IID_IPersistFolder.\n"); 4361 if(SUCCEEDED(hr)) 4362 IPersistFolder_Release(ppf); 4363 4364 todo_wine { 4365 hr = IPersistFolder2_Initialize(ppf2, NULL); 4366 ok(hr == S_OK, "got %08x\n", hr); 4367 } 4368 4369 pidl = NULL; 4370 hr = IPersistFolder2_GetCurFolder(ppf2, &pidl); 4371 ok(hr == S_OK, "got %08x\n", hr); 4372 ok(pidl != NULL, "pidl was NULL.\n"); 4373 if(SUCCEEDED(hr)) ILFree(pidl); 4374 4375 IPersistFolder2_Release(ppf2); 4376 } 4377 4378 IShellFolder_Release(desktop); 4379 } 4380 4381 static void test_contextmenu_qi(IContextMenu *menu, BOOL todo) 4382 { 4383 IUnknown *unk; 4384 HRESULT hr; 4385 4386 hr = IContextMenu_QueryInterface(menu, &IID_IShellExtInit, (void **)&unk); 4387 todo_wine_if(todo) 4388 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#x.\n", hr); 4389 if (hr == S_OK) 4390 IUnknown_Release(unk); 4391 4392 hr = IContextMenu_QueryInterface(menu, &IID_IObjectWithSite, (void **)&unk); 4393 todo_wine_if(todo) 4394 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#x.\n", hr); 4395 if (hr == S_OK) 4396 IUnknown_Release(unk); 4397 } 4398 4399 static void test_contextmenu(IContextMenu *menu, BOOL background) 4400 { 4401 HMENU hmenu = CreatePopupMenu(); 4402 const int id_upper_limit = 32767; 4403 const int baseItem = 0x40; 4404 INT max_id, max_id_check; 4405 UINT count, i; 4406 HRESULT hr; 4407 4408 test_contextmenu_qi(menu, FALSE); 4409 4410 hr = IContextMenu_QueryContextMenu(menu, hmenu, 0, baseItem, id_upper_limit, CMF_NORMAL); 4411 ok(SUCCEEDED(hr), "Failed to query the menu, hr %#x.\n", hr); 4412 4413 max_id = HRESULT_CODE(hr) - 1; /* returns max_id + 1 */ 4414 ok(max_id <= id_upper_limit, "Got %d\n", max_id); 4415 count = GetMenuItemCount(hmenu); 4416 ok(count, "Got %d\n", count); 4417 4418 max_id_check = 0; 4419 for (i = 0; i < count; i++) 4420 { 4421 MENUITEMINFOA mii; 4422 INT res; 4423 char buf[255], buf2[255]; 4424 ZeroMemory(&mii, sizeof(MENUITEMINFOA)); 4425 mii.cbSize = sizeof(MENUITEMINFOA); 4426 mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING; 4427 mii.dwTypeData = buf2; 4428 mii.cch = sizeof(buf2); 4429 4430 res = GetMenuItemInfoA(hmenu, i, TRUE, &mii); 4431 ok(res, "Failed to get menu item info, error %d.\n", GetLastError()); 4432 4433 ok((mii.wID <= id_upper_limit) || (mii.fType & MFT_SEPARATOR), 4434 "Got non-separator ID out of range: %d (type: %x)\n", mii.wID, mii.fType); 4435 if (!(mii.fType & MFT_SEPARATOR)) 4436 { 4437 max_id_check = (mii.wID > max_id_check) ? mii.wID : max_id_check; 4438 hr = IContextMenu_GetCommandString(menu, mii.wID - baseItem, GCS_VERBA, 0, buf, sizeof(buf)); 4439 todo_wine_if(background) 4440 ok(SUCCEEDED(hr) || hr == E_NOTIMPL, "for id 0x%x got 0x%08x (menustr: %s)\n", mii.wID - baseItem, hr, mii.dwTypeData); 4441 if (SUCCEEDED(hr)) 4442 trace("for id 0x%x got string %s (menu string: %s)\n", mii.wID - baseItem, buf, mii.dwTypeData); 4443 else if (hr == E_NOTIMPL) 4444 trace("for id 0x%x got E_NOTIMPL (menu string: %s)\n", mii.wID - baseItem, mii.dwTypeData); 4445 } 4446 } 4447 max_id_check -= baseItem; 4448 ok((max_id_check == max_id) || 4449 (max_id_check == max_id-1) || /* Win 7 */ 4450 (max_id_check == max_id-2) || /* Win 8 */ 4451 (max_id_check == max_id-3), 4452 "Not equal (or near equal), got %d and %d\n", max_id_check, max_id); 4453 4454 if (count) 4455 { 4456 CMINVOKECOMMANDINFO cmi; 4457 4458 memset(&cmi, 0, sizeof(CMINVOKECOMMANDINFO)); 4459 cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); 4460 4461 /* Attempt to execute a nonexistent command */ 4462 cmi.lpVerb = MAKEINTRESOURCEA(9999); 4463 hr = IContextMenu_InvokeCommand(menu, &cmi); 4464 todo_wine_if(background) 4465 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 4466 4467 cmi.lpVerb = "foobar_wine_test"; 4468 hr = IContextMenu_InvokeCommand(menu, &cmi); 4469 todo_wine_if(background) 4470 ok((hr == E_INVALIDARG) || (hr == E_FAIL /* Win7 */) || 4471 (hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION) /* Vista */), 4472 "Unexpected hr %#x.\n", hr); 4473 } 4474 4475 DestroyMenu(hmenu); 4476 } 4477 4478 static void test_GetUIObject(void) 4479 { 4480 IShellFolder *psf_desktop; 4481 IContextMenu *pcm; 4482 LPITEMIDLIST pidl; 4483 HRESULT hr; 4484 WCHAR path[MAX_PATH]; 4485 const WCHAR filename[] = 4486 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0}; 4487 LPCITEMIDLIST pidl_child; 4488 IShellFolder *psf; 4489 4490 GetCurrentDirectoryW(MAX_PATH, path); 4491 if (!path[0]) 4492 { 4493 skip("GetCurrentDirectoryW returned an empty string.\n"); 4494 return; 4495 } 4496 lstrcatW(path, filename); 4497 SHGetDesktopFolder(&psf_desktop); 4498 4499 CreateFilesFolders(); 4500 4501 hr = IShellFolder_ParseDisplayName(psf_desktop, NULL, NULL, path, NULL, &pidl, 0); 4502 ok(hr == S_OK, "Got 0x%08x\n", hr); 4503 4504 hr = SHBindToParent(pidl, &IID_IShellFolder, (void **)&psf, &pidl_child); 4505 ok(hr == S_OK, "Failed to bind to folder, hr %#x.\n", hr); 4506 4507 /* Item menu */ 4508 hr = IShellFolder_GetUIObjectOf(psf, NULL, 1, &pidl_child, &IID_IContextMenu, NULL, (void **)&pcm); 4509 ok(hr == S_OK, "GetUIObjectOf() failed, hr %#x.\n", hr); 4510 test_contextmenu(pcm, FALSE); 4511 IContextMenu_Release(pcm); 4512 4513 /* Background menu */ 4514 hr = IShellFolder_GetUIObjectOf(psf_desktop, NULL, 0, NULL, &IID_IContextMenu, NULL, (void **)&pcm); 4515 ok(hr == S_OK, "GetUIObjectOf() failed, hr %#x.\n", hr); 4516 test_contextmenu(pcm, TRUE); 4517 IContextMenu_Release(pcm); 4518 4519 IShellFolder_Release(psf); 4520 ILFree(pidl); 4521 4522 IShellFolder_Release(psf_desktop); 4523 Cleanup(); 4524 } 4525 4526 #define verify_pidl(i,p) r_verify_pidl(__LINE__, i, p) 4527 static void r_verify_pidl(unsigned l, LPCITEMIDLIST pidl, const WCHAR *path) 4528 { 4529 LPCITEMIDLIST child; 4530 IShellFolder *parent; 4531 STRRET filename; 4532 HRESULT hr; 4533 4534 if(path){ 4535 if(!pidl){ 4536 ok_(__FILE__,l)(0, "didn't get expected path (%s), instead: NULL\n", wine_dbgstr_w(path)); 4537 return; 4538 } 4539 4540 hr = SHBindToParent(pidl, &IID_IShellFolder, (void **)&parent, &child); 4541 ok_(__FILE__,l)(hr == S_OK, "SHBindToParent failed: 0x%08x\n", hr); 4542 if(FAILED(hr)) 4543 return; 4544 4545 hr = IShellFolder_GetDisplayNameOf(parent, child, SHGDN_FORPARSING, &filename); 4546 ok_(__FILE__,l)(hr == S_OK, "GetDisplayNameOf failed: 0x%08x\n", hr); 4547 if(FAILED(hr)){ 4548 IShellFolder_Release(parent); 4549 return; 4550 } 4551 4552 ok_(__FILE__,l)(filename.uType == STRRET_WSTR || filename.uType == STRRET_CSTR, 4553 "Got unexpected string type: %d\n", filename.uType); 4554 if(filename.uType == STRRET_WSTR){ 4555 ok_(__FILE__,l)(lstrcmpW(path, U(filename).pOleStr) == 0, 4556 "didn't get expected path (%s), instead: %s\n", 4557 wine_dbgstr_w(path), wine_dbgstr_w(U(filename).pOleStr)); 4558 SHFree(U(filename).pOleStr); 4559 }else if(filename.uType == STRRET_CSTR){ 4560 ok_(__FILE__,l)(strcmp_wa(path, U(filename).cStr) == 0, 4561 "didn't get expected path (%s), instead: %s\n", 4562 wine_dbgstr_w(path), U(filename).cStr); 4563 } 4564 4565 IShellFolder_Release(parent); 4566 }else 4567 ok_(__FILE__,l)(pidl == NULL, "Expected PIDL to be NULL\n"); 4568 } 4569 4570 static void test_SHSimpleIDListFromPath(void) 4571 { 4572 const WCHAR adirW[] = {'C',':','\\','s','i','d','l','f','p','d','i','r',0}; 4573 const CHAR adirA[] = "C:\\sidlfpdir"; 4574 BOOL br, is_unicode = !(GetVersion() & 0x80000000); 4575 4576 LPITEMIDLIST pidl = NULL; 4577 4578 br = CreateDirectoryA(adirA, NULL); 4579 ok(br == TRUE, "CreateDirectory failed: %d\n", GetLastError()); 4580 4581 if(is_unicode) 4582 pidl = SHSimpleIDListFromPath(adirW); 4583 else 4584 pidl = SHSimpleIDListFromPath((const WCHAR *)adirA); 4585 verify_pidl(pidl, adirW); 4586 ILFree(pidl); 4587 4588 br = RemoveDirectoryA(adirA); 4589 ok(br == TRUE, "RemoveDirectory failed: %d\n", GetLastError()); 4590 4591 if(is_unicode) 4592 pidl = SHSimpleIDListFromPath(adirW); 4593 else 4594 pidl = SHSimpleIDListFromPath((const WCHAR *)adirA); 4595 verify_pidl(pidl, adirW); 4596 ILFree(pidl); 4597 } 4598 4599 /* IFileSystemBindData impl */ 4600 static HRESULT WINAPI fsbd_QueryInterface(IFileSystemBindData *fsbd, 4601 REFIID riid, void **ppv) 4602 { 4603 if(IsEqualIID(riid, &IID_IFileSystemBindData) || 4604 IsEqualIID(riid, &IID_IUnknown)){ 4605 *ppv = fsbd; 4606 return S_OK; 4607 } 4608 return E_NOINTERFACE; 4609 } 4610 4611 static ULONG WINAPI fsbd_AddRef(IFileSystemBindData *fsbd) 4612 { 4613 return 2; 4614 } 4615 4616 static ULONG WINAPI fsbd_Release(IFileSystemBindData *fsbd) 4617 { 4618 return 1; 4619 } 4620 4621 static HRESULT WINAPI fsbd_SetFindData(IFileSystemBindData *fsbd, 4622 const WIN32_FIND_DATAW *pfd) 4623 { 4624 ok(0, "SetFindData called\n"); 4625 return E_NOTIMPL; 4626 } 4627 4628 static HRESULT WINAPI fsbd_GetFindData_nul(IFileSystemBindData *fsbd, 4629 WIN32_FIND_DATAW *pfd) 4630 { 4631 memset(pfd, 0, sizeof(WIN32_FIND_DATAW)); 4632 return S_OK; 4633 } 4634 4635 static HRESULT WINAPI fsbd_GetFindData_junk(IFileSystemBindData *fsbd, 4636 WIN32_FIND_DATAW *pfd) 4637 { 4638 memset(pfd, 0xef, sizeof(WIN32_FIND_DATAW)); 4639 return S_OK; 4640 } 4641 4642 static HRESULT WINAPI fsbd_GetFindData_invalid(IFileSystemBindData *fsbd, 4643 WIN32_FIND_DATAW *pfd) 4644 { 4645 memset(pfd, 0, sizeof(WIN32_FIND_DATAW)); 4646 *pfd->cFileName = 'a'; 4647 *pfd->cAlternateFileName = 'a'; 4648 return S_OK; 4649 } 4650 4651 static HRESULT WINAPI fsbd_GetFindData_valid(IFileSystemBindData *fsbd, 4652 WIN32_FIND_DATAW *pfd) 4653 { 4654 static const WCHAR adirW[] = {'C',':','\\','f','s','b','d','d','i','r',0}; 4655 HANDLE handle = FindFirstFileW(adirW, pfd); 4656 FindClose(handle); 4657 return S_OK; 4658 } 4659 4660 static HRESULT WINAPI fsbd_GetFindData_fail(IFileSystemBindData *fsbd, 4661 WIN32_FIND_DATAW *pfd) 4662 { 4663 return E_FAIL; 4664 } 4665 4666 static IFileSystemBindDataVtbl fsbdVtbl = { 4667 fsbd_QueryInterface, 4668 fsbd_AddRef, 4669 fsbd_Release, 4670 fsbd_SetFindData, 4671 NULL 4672 }; 4673 4674 static IFileSystemBindData fsbd = { &fsbdVtbl }; 4675 4676 static void test_ParseDisplayNamePBC(void) 4677 { 4678 WCHAR wFileSystemBindData[] = 4679 {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d',' ','D','a','t','a',0}; 4680 WCHAR adirW[] = {'C',':','\\','f','s','b','d','d','i','r',0}; 4681 WCHAR afileW[] = {'C',':','\\','f','s','b','d','d','i','r','\\','f','i','l','e','.','t','x','t',0}; 4682 WCHAR afile2W[] = {'C',':','\\','f','s','b','d','d','i','r','\\','s','\\','f','i','l','e','.','t','x','t',0}; 4683 const HRESULT exp_err = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4684 4685 IShellFolder *psf; 4686 IBindCtx *pbc; 4687 HRESULT hres; 4688 ITEMIDLIST *pidl; 4689 4690 /* Check if we support WCHAR functions */ 4691 SetLastError(0xdeadbeef); 4692 lstrcmpiW(adirW, adirW); 4693 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED){ 4694 win_skip("Most W-calls are not implemented\n"); 4695 return; 4696 } 4697 4698 hres = SHGetDesktopFolder(&psf); 4699 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres); 4700 if(FAILED(hres)){ 4701 win_skip("Failed to get IShellFolder, can't run tests\n"); 4702 return; 4703 } 4704 4705 /* fails on unknown dir with no IBindCtx */ 4706 hres = IShellFolder_ParseDisplayName(psf, NULL, NULL, adirW, NULL, &pidl, NULL); 4707 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08x\n", hres); 4708 hres = IShellFolder_ParseDisplayName(psf, NULL, NULL, afileW, NULL, &pidl, NULL); 4709 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08x\n", hres); 4710 hres = IShellFolder_ParseDisplayName(psf, NULL, NULL, afile2W, NULL, &pidl, NULL); 4711 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08x\n", hres); 4712 4713 /* fails on unknown dir with IBindCtx with no IFileSystemBindData */ 4714 hres = CreateBindCtx(0, &pbc); 4715 ok(hres == S_OK, "CreateBindCtx failed: 0x%08x\n", hres); 4716 4717 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL); 4718 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08x\n", hres); 4719 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL); 4720 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08x\n", hres); 4721 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL); 4722 ok(hres == exp_err, "ParseDisplayName failed with wrong error: 0x%08x\n", hres); 4723 4724 /* unknown dir with IBindCtx with IFileSystemBindData */ 4725 hres = IBindCtx_RegisterObjectParam(pbc, wFileSystemBindData, (IUnknown*)&fsbd); 4726 ok(hres == S_OK, "RegisterObjectParam failed: 0x%08x\n", hres); 4727 4728 /* return E_FAIL from GetFindData */ 4729 pidl = (ITEMIDLIST*)0xdeadbeef; 4730 fsbdVtbl.GetFindData = fsbd_GetFindData_fail; 4731 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL); 4732 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4733 if(SUCCEEDED(hres)){ 4734 verify_pidl(pidl, adirW); 4735 ILFree(pidl); 4736 } 4737 4738 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL); 4739 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4740 if(SUCCEEDED(hres)){ 4741 verify_pidl(pidl, afileW); 4742 ILFree(pidl); 4743 } 4744 4745 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL); 4746 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4747 if(SUCCEEDED(hres)){ 4748 verify_pidl(pidl, afile2W); 4749 ILFree(pidl); 4750 } 4751 4752 /* set FIND_DATA struct to NULLs */ 4753 pidl = (ITEMIDLIST*)0xdeadbeef; 4754 fsbdVtbl.GetFindData = fsbd_GetFindData_nul; 4755 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL); 4756 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4757 if(SUCCEEDED(hres)){ 4758 verify_pidl(pidl, adirW); 4759 ILFree(pidl); 4760 } 4761 4762 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL); 4763 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4764 if(SUCCEEDED(hres)){ 4765 verify_pidl(pidl, afileW); 4766 ILFree(pidl); 4767 } 4768 4769 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL); 4770 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4771 if(SUCCEEDED(hres)){ 4772 verify_pidl(pidl, afile2W); 4773 ILFree(pidl); 4774 } 4775 4776 /* set FIND_DATA struct to junk */ 4777 pidl = (ITEMIDLIST*)0xdeadbeef; 4778 fsbdVtbl.GetFindData = fsbd_GetFindData_junk; 4779 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL); 4780 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4781 if(SUCCEEDED(hres)){ 4782 verify_pidl(pidl, adirW); 4783 ILFree(pidl); 4784 } 4785 4786 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL); 4787 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4788 if(SUCCEEDED(hres)){ 4789 verify_pidl(pidl, afileW); 4790 ILFree(pidl); 4791 } 4792 4793 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL); 4794 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4795 if(SUCCEEDED(hres)){ 4796 verify_pidl(pidl, afile2W); 4797 ILFree(pidl); 4798 } 4799 4800 /* set FIND_DATA struct to invalid data */ 4801 pidl = (ITEMIDLIST*)0xdeadbeef; 4802 fsbdVtbl.GetFindData = fsbd_GetFindData_invalid; 4803 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL); 4804 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4805 if(SUCCEEDED(hres)){ 4806 verify_pidl(pidl, adirW); 4807 ILFree(pidl); 4808 } 4809 4810 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL); 4811 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4812 if(SUCCEEDED(hres)){ 4813 verify_pidl(pidl, afileW); 4814 ILFree(pidl); 4815 } 4816 4817 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL); 4818 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4819 if(SUCCEEDED(hres)){ 4820 verify_pidl(pidl, afile2W); 4821 ILFree(pidl); 4822 } 4823 4824 /* set FIND_DATA struct to valid data */ 4825 pidl = (ITEMIDLIST*)0xdeadbeef; 4826 fsbdVtbl.GetFindData = fsbd_GetFindData_valid; 4827 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, adirW, NULL, &pidl, NULL); 4828 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4829 if(SUCCEEDED(hres)){ 4830 verify_pidl(pidl, adirW); 4831 ILFree(pidl); 4832 } 4833 4834 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afileW, NULL, &pidl, NULL); 4835 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4836 if(SUCCEEDED(hres)){ 4837 verify_pidl(pidl, afileW); 4838 ILFree(pidl); 4839 } 4840 4841 hres = IShellFolder_ParseDisplayName(psf, NULL, pbc, afile2W, NULL, &pidl, NULL); 4842 ok(hres == S_OK, "ParseDisplayName failed: 0x%08x\n", hres); 4843 if(SUCCEEDED(hres)){ 4844 verify_pidl(pidl, afile2W); 4845 ILFree(pidl); 4846 } 4847 4848 IBindCtx_Release(pbc); 4849 IShellFolder_Release(psf); 4850 } 4851 4852 static const CHAR testwindow_class[] = "testwindow"; 4853 #define WM_USER_NOTIFY (WM_APP+1) 4854 4855 struct ChNotifyTest { 4856 const char id[256]; 4857 const UINT notify_count; 4858 UINT missing_events; 4859 UINT signal; 4860 const char path_1[256]; 4861 const char path_2[256]; 4862 } chnotify_tests[] = { 4863 {"MKDIR", 1, 0, SHCNE_MKDIR, "C:\\shell32_cn_test\\test", ""}, 4864 {"CREATE", 1, 0, SHCNE_CREATE, "C:\\shell32_cn_test\\test\\file.txt", ""}, 4865 {"RMDIR", 1, 0, SHCNE_RMDIR, "C:\\shell32_cn_test\\test", ""}, 4866 }; 4867 4868 struct ChNotifyTest *exp_data; 4869 BOOL test_new_delivery_flag; 4870 4871 static LRESULT CALLBACK testwindow_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4872 { 4873 LONG signal = (LONG)lparam; 4874 4875 switch(msg){ 4876 case WM_USER_NOTIFY: 4877 if(exp_data->missing_events > 0) { 4878 WCHAR *path1, *path2; 4879 LPITEMIDLIST *pidls = (LPITEMIDLIST*)wparam; 4880 HANDLE hLock = NULL; 4881 4882 if(test_new_delivery_flag) { 4883 hLock = SHChangeNotification_Lock((HANDLE)wparam, lparam, &pidls, &signal); 4884 ok(hLock != NULL, "SHChangeNotification_Lock returned NULL\n"); 4885 } 4886 4887 ok(exp_data->signal == signal, 4888 "%s: expected notification type %x, got: %x\n", 4889 exp_data->id, exp_data->signal, signal); 4890 4891 trace("verifying pidls for: %s\n", exp_data->id); 4892 path1 = make_wstr(exp_data->path_1); 4893 path2 = make_wstr(exp_data->path_2); 4894 verify_pidl(pidls[0], path1); 4895 verify_pidl(pidls[1], path2); 4896 heap_free(path1); 4897 heap_free(path2); 4898 4899 exp_data->missing_events--; 4900 4901 if(test_new_delivery_flag) 4902 SHChangeNotification_Unlock(hLock); 4903 }else 4904 ok(0, "Didn't expect a WM_USER_NOTIFY message (event: %x)\n", signal); 4905 return 0; 4906 } 4907 return DefWindowProcA(hwnd, msg, wparam, lparam); 4908 } 4909 4910 static void register_testwindow_class(void) 4911 { 4912 WNDCLASSEXA cls; 4913 ATOM ret; 4914 4915 ZeroMemory(&cls, sizeof(cls)); 4916 cls.cbSize = sizeof(cls); 4917 cls.style = 0; 4918 cls.lpfnWndProc = testwindow_wndproc; 4919 cls.hInstance = GetModuleHandleA(NULL); 4920 cls.lpszClassName = testwindow_class; 4921 4922 SetLastError(0); 4923 ret = RegisterClassExA(&cls); 4924 ok(ret != 0, "RegisterClassExA failed: %d\n", GetLastError()); 4925 } 4926 4927 /* SHCNF_FLUSH doesn't seem to work as advertised for SHCNF_PATHA, so we 4928 * have to poll repeatedly for the message to appear */ 4929 static void do_events(void) 4930 { 4931 int c = 0; 4932 while (exp_data->missing_events && (c++ < 10)){ 4933 MSG msg; 4934 while(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)){ 4935 TranslateMessage(&msg); 4936 DispatchMessageA(&msg); 4937 } 4938 if(exp_data->missing_events) 4939 Sleep(500); 4940 } 4941 trace("%s: took %d tries\n", exp_data->id, c); 4942 } 4943 4944 static void test_SHChangeNotify(BOOL test_new_delivery) 4945 { 4946 HWND wnd; 4947 ULONG notifyID, i; 4948 HRESULT hr; 4949 BOOL br, has_unicode; 4950 SHChangeNotifyEntry entries[1]; 4951 const CHAR root_dirA[] = "C:\\shell32_cn_test"; 4952 const WCHAR root_dirW[] = {'C',':','\\','s','h','e','l','l','3','2','_','c','n','_','t','e','s','t',0}; 4953 4954 trace("SHChangeNotify tests (%x)\n", test_new_delivery); 4955 4956 CreateDirectoryW(NULL, NULL); 4957 has_unicode = !(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED); 4958 4959 test_new_delivery_flag = test_new_delivery; 4960 if(!test_new_delivery) 4961 register_testwindow_class(); 4962 4963 wnd = CreateWindowExA(0, testwindow_class, testwindow_class, 0, 4964 CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, 4965 NULL, NULL, GetModuleHandleA(NULL), 0); 4966 ok(wnd != NULL, "Failed to make a window\n"); 4967 4968 br = CreateDirectoryA(root_dirA, NULL); 4969 ok(br == TRUE, "CreateDirectory failed: %d\n", GetLastError()); 4970 4971 entries[0].pidl = NULL; 4972 if(has_unicode) 4973 hr = SHILCreateFromPath(root_dirW, (LPITEMIDLIST*)&entries[0].pidl, 0); 4974 else 4975 hr = SHILCreateFromPath((const void *)root_dirA, (LPITEMIDLIST*)&entries[0].pidl, 0); 4976 ok(hr == S_OK, "SHILCreateFromPath failed: 0x%08x\n", hr); 4977 entries[0].fRecursive = TRUE; 4978 4979 notifyID = SHChangeNotifyRegister(wnd, !test_new_delivery ? SHCNRF_ShellLevel : SHCNRF_ShellLevel|SHCNRF_NewDelivery, 4980 SHCNE_ALLEVENTS, WM_USER_NOTIFY, 1, entries); 4981 ok(notifyID != 0, "Failed to register a window for change notifications\n"); 4982 4983 for (i = 0; i < ARRAY_SIZE(chnotify_tests); ++i) 4984 { 4985 exp_data = chnotify_tests + i; 4986 4987 exp_data->missing_events = exp_data->notify_count; 4988 SHChangeNotify(exp_data->signal, SHCNF_PATHA | SHCNF_FLUSH, 4989 exp_data->path_1[0] ? exp_data->path_1 : NULL, 4990 exp_data->path_2[0] ? exp_data->path_2 : NULL); 4991 do_events(); 4992 ok(exp_data->missing_events == 0, "%s: Expected wndproc to be called\n", exp_data->id); 4993 4994 if(has_unicode){ 4995 WCHAR *path1, *path2; 4996 4997 path1 = make_wstr(exp_data->path_1); 4998 path2 = make_wstr(exp_data->path_2); 4999 5000 exp_data->missing_events = exp_data->notify_count; 5001 SHChangeNotify(exp_data->signal, SHCNF_PATHW | SHCNF_FLUSH, path1, path2); 5002 do_events(); 5003 ok(exp_data->missing_events == 0, "%s: Expected wndproc to be called\n", exp_data->id); 5004 5005 heap_free(path1); 5006 heap_free(path2); 5007 } 5008 } 5009 5010 SHChangeNotifyDeregister(notifyID); 5011 DestroyWindow(wnd); 5012 5013 ILFree((LPITEMIDLIST)entries[0].pidl); 5014 br = RemoveDirectoryA(root_dirA); 5015 ok(br == TRUE, "RemoveDirectory failed: %d\n", GetLastError()); 5016 } 5017 5018 static void test_SHCreateDefaultContextMenu(void) 5019 { 5020 HKEY keys[16]; 5021 WCHAR path[MAX_PATH]; 5022 IShellFolder *desktop,*folder; 5023 IPersistFolder2 *persist; 5024 IContextMenu *cmenu; 5025 LONG status; 5026 LPITEMIDLIST pidlFolder, pidl_child, pidl; 5027 DEFCONTEXTMENU cminfo; 5028 HRESULT hr; 5029 UINT i; 5030 const WCHAR filename[] = 5031 {'\\','t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0}; 5032 if(!pSHCreateDefaultContextMenu) 5033 { 5034 win_skip("SHCreateDefaultContextMenu missing.\n"); 5035 return; 5036 } 5037 5038 GetCurrentDirectoryW(MAX_PATH, path); 5039 if (!path[0]) 5040 { 5041 skip("GetCurrentDirectoryW returned an empty string.\n"); 5042 return; 5043 } 5044 lstrcatW(path, filename); 5045 SHGetDesktopFolder(&desktop); 5046 5047 CreateFilesFolders(); 5048 5049 hr = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &pidl, 0); 5050 ok(hr == S_OK, "Got 0x%08x\n", hr); 5051 if(SUCCEEDED(hr)) 5052 { 5053 hr = SHBindToParent(pidl, &IID_IShellFolder, (void **)&folder, (const ITEMIDLIST **)&pidl_child); 5054 ok(hr == S_OK, "Got 0x%08x\n", hr); 5055 5056 IShellFolder_QueryInterface(folder,&IID_IPersistFolder2,(void**)&persist); 5057 IPersistFolder2_GetCurFolder(persist,&pidlFolder); 5058 IPersistFolder2_Release(persist); 5059 if(SUCCEEDED(hr)) 5060 { 5061 cminfo.hwnd=NULL; 5062 cminfo.pcmcb=NULL; 5063 cminfo.psf=folder; 5064 cminfo.pidlFolder=NULL; 5065 cminfo.apidl=(LPCITEMIDLIST*)&pidl_child; 5066 cminfo.cidl=1; 5067 cminfo.aKeys=NULL; 5068 cminfo.cKeys=0; 5069 cminfo.punkAssociationInfo=NULL; 5070 5071 hr = pSHCreateDefaultContextMenu(&cminfo,&IID_IContextMenu,(void**)&cmenu); 5072 ok(hr==S_OK,"Got 0x%08x\n", hr); 5073 test_contextmenu_qi(cmenu, TRUE); 5074 IContextMenu_Release(cmenu); 5075 5076 cminfo.pidlFolder=pidlFolder; 5077 hr = pSHCreateDefaultContextMenu(&cminfo,&IID_IContextMenu,(void**)&cmenu); 5078 ok(hr==S_OK,"Got 0x%08x\n", hr); 5079 test_contextmenu_qi(cmenu, TRUE); 5080 IContextMenu_Release(cmenu); 5081 5082 status = RegOpenKeyExA(HKEY_CLASSES_ROOT,"*",0,KEY_READ,keys); 5083 if(status==ERROR_SUCCESS){ 5084 for(i=1;i<16;i++) 5085 keys[i]=keys[0]; 5086 cminfo.aKeys=keys; 5087 cminfo.cKeys=16; 5088 hr = pSHCreateDefaultContextMenu(&cminfo,&IID_IContextMenu,(void**)&cmenu); 5089 RegCloseKey(keys[0]); 5090 ok(hr==S_OK,"Got 0x%08x\n", hr); 5091 IContextMenu_Release(cmenu); 5092 } 5093 } 5094 ILFree(pidlFolder); 5095 IShellFolder_Release(folder); 5096 } 5097 IShellFolder_Release(desktop); 5098 ILFree(pidl); 5099 Cleanup(); 5100 } 5101 5102 static void test_DataObject(void) 5103 { 5104 IShellFolder *desktop; 5105 IDataObject *data_obj; 5106 HRESULT hres; 5107 IEnumIDList *peidl; 5108 LPITEMIDLIST apidl; 5109 FORMATETC fmt; 5110 DWORD cf_shellidlist; 5111 STGMEDIUM medium; 5112 5113 SHGetDesktopFolder(&desktop); 5114 5115 hres = IShellFolder_EnumObjects(desktop, NULL, 5116 SHCONTF_NONFOLDERS|SHCONTF_FOLDERS|SHCONTF_INCLUDEHIDDEN, &peidl); 5117 ok(hres == S_OK, "got %x\n", hres); 5118 5119 if(IEnumIDList_Next(peidl, 1, &apidl, NULL) != S_OK) { 5120 skip("no files on desktop - skipping GetDataObject tests\n"); 5121 IEnumIDList_Release(peidl); 5122 IShellFolder_Release(desktop); 5123 return; 5124 } 5125 IEnumIDList_Release(peidl); 5126 5127 hres = IShellFolder_GetUIObjectOf(desktop, NULL, 1, (LPCITEMIDLIST*)&apidl, 5128 &IID_IDataObject, NULL, (void**)&data_obj); 5129 ok(hres == S_OK, "got %x\n", hres); 5130 ILFree(apidl); 5131 IShellFolder_Release(desktop); 5132 5133 cf_shellidlist = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); 5134 fmt.cfFormat = cf_shellidlist; 5135 fmt.ptd = NULL; 5136 fmt.dwAspect = DVASPECT_CONTENT; 5137 fmt.lindex = -1; 5138 fmt.tymed = TYMED_HGLOBAL; 5139 hres = IDataObject_QueryGetData(data_obj, &fmt); 5140 ok(hres == S_OK, "got %x\n", hres); 5141 5142 fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM; 5143 hres = IDataObject_QueryGetData(data_obj, &fmt); 5144 ok(hres == S_OK, "got %x\n", hres); 5145 5146 fmt.tymed = TYMED_ISTREAM; 5147 hres = IDataObject_QueryGetData(data_obj, &fmt); 5148 todo_wine ok(hres == S_FALSE, "got %x\n", hres); 5149 5150 fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM; 5151 hres = IDataObject_GetData(data_obj, &fmt, &medium); 5152 ok(hres == S_OK, "got %x\n", hres); 5153 ok(medium.tymed == TYMED_HGLOBAL, "medium.tymed = %x\n", medium.tymed); 5154 ReleaseStgMedium(&medium); 5155 5156 IDataObject_Release(data_obj); 5157 } 5158 5159 static void test_GetDefaultColumn(void) 5160 { 5161 static const CLSID *folders[] = 5162 { 5163 &CLSID_MyComputer, 5164 &CLSID_MyDocuments, 5165 &CLSID_ControlPanel, 5166 &CLSID_NetworkPlaces, 5167 &CLSID_Printers, 5168 &CLSID_RecycleBin, 5169 &CLSID_ShellDesktop, 5170 }; 5171 HRESULT hr; 5172 int i; 5173 5174 CoInitialize(NULL); 5175 5176 for (i = 0; i < ARRAY_SIZE(folders); i++) 5177 { 5178 IShellFolder2 *folder; 5179 ULONG sort, display; 5180 5181 hr = CoCreateInstance(folders[i], NULL, CLSCTX_INPROC_SERVER, &IID_IShellFolder2, (void **)&folder); 5182 if (hr != S_OK) 5183 { 5184 win_skip("Failed to create folder %s, hr %#x.\n", wine_dbgstr_guid(folders[i]), hr); 5185 continue; 5186 } 5187 5188 hr = IShellFolder2_GetDefaultColumn(folder, 0, NULL, NULL); 5189 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); 5190 5191 sort = display = 123; 5192 hr = IShellFolder2_GetDefaultColumn(folder, 0, &sort, &display); 5193 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); 5194 ok(sort == 123 && display == 123, "Unexpected default column.\n"); 5195 5196 display = 123; 5197 hr = IShellFolder2_GetDefaultColumn(folder, 0, NULL, &display); 5198 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); 5199 ok(display == 123, "Unexpected default column.\n"); 5200 5201 sort = 123; 5202 hr = IShellFolder2_GetDefaultColumn(folder, 0, &sort, NULL); 5203 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); 5204 ok(sort == 123, "Unexpected default column.\n"); 5205 5206 IShellFolder2_Release(folder); 5207 } 5208 5209 CoUninitialize(); 5210 } 5211 5212 static void test_GetDefaultSearchGUID(void) 5213 { 5214 static const CLSID *folders[] = 5215 { 5216 &CLSID_MyComputer, 5217 &CLSID_MyDocuments, 5218 &CLSID_ControlPanel, 5219 &CLSID_NetworkPlaces, 5220 &CLSID_Printers, 5221 &CLSID_RecycleBin, 5222 &CLSID_ShellDesktop, 5223 }; 5224 HRESULT hr; 5225 int i; 5226 5227 CoInitialize(NULL); 5228 5229 for (i = 0; i < ARRAY_SIZE(folders); i++) 5230 { 5231 IShellFolder2 *folder; 5232 GUID guid; 5233 5234 hr = CoCreateInstance(folders[i], NULL, CLSCTX_INPROC_SERVER, &IID_IShellFolder2, (void **)&folder); 5235 if (hr != S_OK) 5236 { 5237 win_skip("Failed to create folder %s, hr %#x.\n", wine_dbgstr_guid(folders[i]), hr); 5238 continue; 5239 } 5240 5241 if (0) 5242 { 5243 /* crashes on XP */ 5244 hr = IShellFolder2_GetDefaultSearchGUID(folder, NULL); 5245 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); 5246 } 5247 5248 memcpy(&guid, &CLSID_MyComputer, sizeof(guid)); 5249 hr = IShellFolder2_GetDefaultSearchGUID(folder, &guid); 5250 ok(hr == E_NOTIMPL || broken(hr == S_OK) /* Method was last supported on XP */, "Unexpected hr %#x.\n", hr); 5251 if (hr == E_NOTIMPL) 5252 ok(IsEqualGUID(&guid, &CLSID_MyComputer), "Unexpected guid %s.\n", wine_dbgstr_guid(&guid)); 5253 5254 IShellFolder2_Release(folder); 5255 } 5256 5257 CoUninitialize(); 5258 } 5259 5260 static void test_SHLimitInputEdit(void) 5261 { 5262 IShellFolder *desktop; 5263 HRESULT hr; 5264 HWND hwnd; 5265 5266 hr = SHGetDesktopFolder(&desktop); 5267 ok(hr == S_OK, "Failed to get desktop folder, hr %#x.\n", hr); 5268 5269 hr = SHLimitInputEdit(NULL, desktop); 5270 todo_wine 5271 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); 5272 5273 hwnd = CreateWindowA("EDIT", NULL, WS_VISIBLE, 0, 0, 100, 30, NULL, NULL, NULL, NULL); 5274 ok(hwnd != NULL, "Failed to create Edit control.\n"); 5275 5276 hr = SHLimitInputEdit(hwnd, desktop); 5277 todo_wine 5278 ok(hr == S_OK, "Failed to set input limits, hr %#x.\n", hr); 5279 5280 hr = SHLimitInputEdit(hwnd, desktop); 5281 todo_wine 5282 ok(hr == S_OK, "Failed to set input limits, hr %#x.\n", hr); 5283 5284 DestroyWindow(hwnd); 5285 IShellFolder_Release(desktop); 5286 } 5287 5288 static void test_SHGetSetFolderCustomSettings(void) 5289 { 5290 HRESULT hr; 5291 SHFOLDERCUSTOMSETTINGS fcs; 5292 WCHAR pathW[MAX_PATH]; 5293 WCHAR bufferW[MAX_PATH]; 5294 WCHAR iconpathW[MAX_PATH]; 5295 static const WCHAR somedirW[] = {'s','o','m','e','_','d','i','r',0}; 5296 static const WCHAR iconW[] = {'\\','s','o','m','e','_','i','c','o','n','.','i','c','o',0}; 5297 static const WCHAR desktop_iniW[] = {'\\','D','e','s','k','t','o','p','.','i','n','i',0}; 5298 5299 if (!pSHGetSetFolderCustomSettings) 5300 { 5301 win_skip("SHGetSetFolderCustomSetting not exported by name (only by ordinal) for version XP/win2003\n"); 5302 return; 5303 } 5304 5305 GetTempPathW(MAX_PATH, pathW); 5306 lstrcatW(pathW, somedirW); 5307 CreateDirectoryW(pathW, NULL); 5308 5309 lstrcpyW(iconpathW, pathW); 5310 lstrcatW(iconpathW, iconW); 5311 5312 memset(&fcs, 0, sizeof(fcs)); 5313 fcs.dwSize = sizeof(fcs); 5314 fcs.dwMask = FCSM_ICONFILE; 5315 fcs.pszIconFile = iconpathW; 5316 5317 hr = pSHGetSetFolderCustomSettings(&fcs, pathW, FCS_FORCEWRITE); /*creates and writes to a Desktop.ini*/ 5318 ok(hr == S_OK, "Expected S_OK, got %#x\n", hr); 5319 5320 memset(&fcs, 0, sizeof(fcs)); 5321 fcs.dwSize = sizeof(fcs); 5322 fcs.dwMask = FCSM_ICONFILE; 5323 fcs.cchIconFile = MAX_PATH; 5324 fcs.pszIconFile = bufferW; 5325 bufferW[0] = 0; 5326 5327 hr = pSHGetSetFolderCustomSettings(&fcs, pathW, FCS_READ); 5328 todo_wine ok(hr == S_OK, "Expected S_OK, got %#x\n", hr); 5329 todo_wine ok(!lstrcmpiW(iconpathW, fcs.pszIconFile), "Expected %s, got %s\n", wine_dbgstr_w(iconpathW), wine_dbgstr_w(fcs.pszIconFile)); 5330 5331 hr = pSHGetSetFolderCustomSettings(&fcs, NULL, FCS_READ); 5332 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 5333 5334 lstrcpyW(bufferW, pathW); 5335 lstrcatW(bufferW, desktop_iniW); 5336 DeleteFileW(bufferW); 5337 RemoveDirectoryW(pathW); 5338 } 5339 5340 START_TEST(shlfolder) 5341 { 5342 init_function_pointers(); 5343 /* if OleInitialize doesn't get called, ParseDisplayName returns 5344 CO_E_NOTINITIALIZED for malformed directory names */ 5345 OleInitialize(NULL); 5346 5347 test_ParseDisplayName(); 5348 test_SHParseDisplayName(); 5349 test_BindToObject(); 5350 test_EnumObjects_and_CompareIDs(); 5351 test_GetDisplayName(); 5352 test_GetAttributesOf(); 5353 test_SHGetPathFromIDList(); 5354 test_CallForAttributes(); 5355 test_FolderShortcut(); 5356 test_ITEMIDLIST_format(); 5357 test_SHGetFolderPathA(); 5358 test_SHGetFolderPathAndSubDirA(); 5359 test_LocalizedNames(); 5360 test_SHCreateShellItem(); 5361 test_SHCreateShellItemArray(); 5362 test_ShellItemArrayEnumItems(); 5363 test_desktop_IPersist(); 5364 test_GetUIObject(); 5365 test_SHSimpleIDListFromPath(); 5366 test_ParseDisplayNamePBC(); 5367 test_SHGetNameFromIDList(); 5368 test_SHGetItemFromDataObject(); 5369 test_SHGetIDListFromObject(); 5370 test_SHGetItemFromObject(); 5371 test_ShellItemCompare(); 5372 test_SHChangeNotify(FALSE); 5373 test_SHChangeNotify(TRUE); 5374 test_ShellItemBindToHandler(); 5375 test_ShellItemGetAttributes(); 5376 test_ShellItemArrayGetAttributes(); 5377 test_SHCreateDefaultContextMenu(); 5378 test_DataObject(); 5379 test_GetDefaultColumn(); 5380 test_GetDefaultSearchGUID(); 5381 test_SHLimitInputEdit(); 5382 test_SHGetSetFolderCustomSettings(); 5383 5384 OleUninitialize(); 5385 } 5386