1 /* 2 * 3 * Copyright 2012 Alistair Leslie-Hughes 4 * Copyright 2014 Dmitry Timoshkov 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 #define COBJMACROS 22 #include <stdio.h> 23 #include <limits.h> 24 25 #include "windows.h" 26 #include "ole2.h" 27 #include "olectl.h" 28 #include "oleauto.h" 29 #include "dispex.h" 30 31 #include "wine/test.h" 32 33 #include "initguid.h" 34 #include "scrrun.h" 35 36 static IFileSystem3 *fs3; 37 38 /* w2k and 2k3 error code. */ 39 #define E_VAR_NOT_SET 0x800a005b 40 41 static inline ULONG get_refcount(IUnknown *iface) 42 { 43 IUnknown_AddRef(iface); 44 return IUnknown_Release(iface); 45 } 46 47 static const WCHAR crlfW[] = {'\r','\n',0}; 48 static const char utf16bom[] = {0xff,0xfe,0}; 49 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; 50 51 #define GET_REFCOUNT(iface) \ 52 get_refcount((IUnknown*)iface) 53 54 static inline void get_temp_path(const WCHAR *prefix, WCHAR *path) 55 { 56 WCHAR buffW[MAX_PATH]; 57 58 GetTempPathW(MAX_PATH, buffW); 59 GetTempFileNameW(buffW, prefix, 0, path); 60 DeleteFileW(path); 61 } 62 63 static IDrive *get_fixed_drive(void) 64 { 65 IDriveCollection *drives; 66 IEnumVARIANT *iter; 67 IDrive *drive; 68 HRESULT hr; 69 70 hr = IFileSystem3_get_Drives(fs3, &drives); 71 ok(hr == S_OK, "got 0x%08x\n", hr); 72 73 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&iter); 74 ok(hr == S_OK, "got 0x%08x\n", hr); 75 IDriveCollection_Release(drives); 76 77 while (1) { 78 DriveTypeConst type; 79 VARIANT var; 80 81 hr = IEnumVARIANT_Next(iter, 1, &var, NULL); 82 if (hr == S_FALSE) { 83 drive = NULL; 84 break; 85 } 86 ok(hr == S_OK, "got 0x%08x\n", hr); 87 88 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDrive, (void**)&drive); 89 ok(hr == S_OK, "got 0x%08x\n", hr); 90 VariantClear(&var); 91 92 hr = IDrive_get_DriveType(drive, &type); 93 ok(hr == S_OK, "got 0x%08x\n", hr); 94 if (type == Fixed) 95 break; 96 97 IDrive_Release(drive); 98 } 99 100 IEnumVARIANT_Release(iter); 101 return drive; 102 } 103 104 #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__) 105 static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line) 106 { 107 IProvideClassInfo *classinfo; 108 TYPEATTR *attr; 109 ITypeInfo *ti; 110 IUnknown *unk; 111 HRESULT hr; 112 113 hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo); 114 ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr); 115 116 hr = IProvideClassInfo_GetClassInfo(classinfo, &ti); 117 ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr); 118 119 hr = ITypeInfo_GetTypeAttr(ti, &attr); 120 ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr); 121 122 ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid), 123 wine_dbgstr_guid(guid)); 124 125 hr = IProvideClassInfo_QueryInterface(classinfo, &IID_IUnknown, (void **)&unk); 126 ok(hr == S_OK, "Failed to QI for IUnknown.\n"); 127 ok(unk == (IUnknown *)disp, "Got unk %p, original %p.\n", unk, disp); 128 IUnknown_Release(unk); 129 130 IProvideClassInfo_Release(classinfo); 131 ITypeInfo_ReleaseTypeAttr(ti, attr); 132 ITypeInfo_Release(ti); 133 } 134 135 static void test_interfaces(void) 136 { 137 static const WCHAR nonexistent_dirW[] = { 138 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', 0}; 139 static const WCHAR pathW[] = {'p','a','t','h',0}; 140 static const WCHAR file_kernel32W[] = { 141 '\\', 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0}; 142 HRESULT hr; 143 IDispatch *disp; 144 IDispatchEx *dispex; 145 IObjectWithSite *site; 146 VARIANT_BOOL b; 147 BSTR path; 148 WCHAR windows_path[MAX_PATH]; 149 WCHAR file_path[MAX_PATH]; 150 151 IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp); 152 153 GetSystemDirectoryW(windows_path, MAX_PATH); 154 lstrcpyW(file_path, windows_path); 155 lstrcatW(file_path, file_kernel32W); 156 157 test_provideclassinfo(disp, &CLSID_FileSystemObject); 158 159 hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site); 160 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE); 161 162 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); 163 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE); 164 165 b = VARIANT_TRUE; 166 hr = IFileSystem3_FileExists(fs3, NULL, &b); 167 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 168 ok(b == VARIANT_FALSE, "got %x\n", b); 169 170 hr = IFileSystem3_FileExists(fs3, NULL, NULL); 171 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER); 172 173 path = SysAllocString(pathW); 174 b = VARIANT_TRUE; 175 hr = IFileSystem3_FileExists(fs3, path, &b); 176 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 177 ok(b == VARIANT_FALSE, "got %x\n", b); 178 SysFreeString(path); 179 180 path = SysAllocString(file_path); 181 b = VARIANT_FALSE; 182 hr = IFileSystem3_FileExists(fs3, path, &b); 183 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 184 ok(b == VARIANT_TRUE, "got %x\n", b); 185 SysFreeString(path); 186 187 path = SysAllocString(windows_path); 188 b = VARIANT_TRUE; 189 hr = IFileSystem3_FileExists(fs3, path, &b); 190 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 191 ok(b == VARIANT_FALSE, "got %x\n", b); 192 SysFreeString(path); 193 194 /* Folder Exists */ 195 hr = IFileSystem3_FolderExists(fs3, NULL, NULL); 196 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER); 197 198 path = SysAllocString(windows_path); 199 hr = IFileSystem3_FolderExists(fs3, path, &b); 200 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 201 ok(b == VARIANT_TRUE, "Folder doesn't exists\n"); 202 SysFreeString(path); 203 204 path = SysAllocString(nonexistent_dirW); 205 hr = IFileSystem3_FolderExists(fs3, path, &b); 206 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 207 ok(b == VARIANT_FALSE, "Folder exists\n"); 208 SysFreeString(path); 209 210 path = SysAllocString(file_path); 211 hr = IFileSystem3_FolderExists(fs3, path, &b); 212 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 213 ok(b == VARIANT_FALSE, "Folder exists\n"); 214 SysFreeString(path); 215 216 IDispatch_Release(disp); 217 } 218 219 static void test_createfolder(void) 220 { 221 WCHAR buffW[MAX_PATH]; 222 HRESULT hr; 223 BSTR path; 224 IFolder *folder; 225 BOOL ret; 226 227 get_temp_path(NULL, buffW); 228 ret = CreateDirectoryW(buffW, NULL); 229 ok(ret, "got %d, %d\n", ret, GetLastError()); 230 231 /* create existing directory */ 232 path = SysAllocString(buffW); 233 folder = (void*)0xdeabeef; 234 hr = IFileSystem3_CreateFolder(fs3, path, &folder); 235 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr); 236 ok(folder == NULL, "got %p\n", folder); 237 SysFreeString(path); 238 RemoveDirectoryW(buffW); 239 } 240 241 static void test_textstream(void) 242 { 243 ITextStream *stream; 244 VARIANT_BOOL b; 245 DWORD written; 246 HANDLE file; 247 HRESULT hr; 248 BSTR name, data; 249 BOOL ret; 250 251 file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 252 CloseHandle(file); 253 254 name = SysAllocString(testfileW); 255 b = VARIANT_FALSE; 256 hr = IFileSystem3_FileExists(fs3, name, &b); 257 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); 258 ok(b == VARIANT_TRUE, "got %x\n", b); 259 260 /* different mode combinations */ 261 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream); 262 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 263 264 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream); 265 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 266 267 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream); 268 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 269 270 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream); 271 ok(hr == S_OK, "got 0x%08x\n", hr); 272 hr = ITextStream_Read(stream, 1, &data); 273 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 274 ITextStream_Release(stream); 275 276 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream); 277 ok(hr == S_OK, "got 0x%08x\n", hr); 278 hr = ITextStream_Read(stream, 1, &data); 279 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 280 ITextStream_Release(stream); 281 282 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream); 283 ok(hr == S_OK, "got 0x%08x\n", hr); 284 285 /* try to write when open for reading */ 286 hr = ITextStream_WriteLine(stream, name); 287 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 288 289 hr = ITextStream_Write(stream, name); 290 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 291 292 hr = ITextStream_get_AtEndOfStream(stream, NULL); 293 ok(hr == E_POINTER, "got 0x%08x\n", hr); 294 295 b = 10; 296 hr = ITextStream_get_AtEndOfStream(stream, &b); 297 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr); 298 ok(b == VARIANT_TRUE, "got 0x%x\n", b); 299 300 ITextStream_Release(stream); 301 302 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream); 303 ok(hr == S_OK, "got 0x%08x\n", hr); 304 305 b = 10; 306 hr = ITextStream_get_AtEndOfStream(stream, &b); 307 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 308 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b); 309 310 b = 10; 311 hr = ITextStream_get_AtEndOfLine(stream, &b); 312 todo_wine { 313 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 314 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b); 315 } 316 hr = ITextStream_Read(stream, 1, &data); 317 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 318 319 hr = ITextStream_ReadLine(stream, &data); 320 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 321 322 hr = ITextStream_ReadAll(stream, &data); 323 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 324 325 ITextStream_Release(stream); 326 327 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream); 328 ok(hr == S_OK, "got 0x%08x\n", hr); 329 330 b = 10; 331 hr = ITextStream_get_AtEndOfStream(stream, &b); 332 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 333 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b); 334 335 b = 10; 336 hr = ITextStream_get_AtEndOfLine(stream, &b); 337 todo_wine { 338 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 339 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b); 340 } 341 hr = ITextStream_Read(stream, 1, &data); 342 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 343 344 hr = ITextStream_ReadLine(stream, &data); 345 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 346 347 hr = ITextStream_ReadAll(stream, &data); 348 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 349 350 ITextStream_Release(stream); 351 352 /* now with non-empty file */ 353 file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 354 ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL); 355 ok(ret && written == sizeof(testfileW), "got %d\n", ret); 356 CloseHandle(file); 357 358 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream); 359 ok(hr == S_OK, "got 0x%08x\n", hr); 360 b = 10; 361 hr = ITextStream_get_AtEndOfStream(stream, &b); 362 ok(hr == S_OK, "got 0x%08x\n", hr); 363 ok(b == VARIANT_FALSE, "got 0x%x\n", b); 364 ITextStream_Release(stream); 365 366 SysFreeString(name); 367 DeleteFileW(testfileW); 368 } 369 370 static void test_GetFileVersion(void) 371 { 372 static const WCHAR k32W[] = {'\\','k','e','r','n','e','l','3','2','.','d','l','l',0}; 373 static const WCHAR k33W[] = {'\\','k','e','r','n','e','l','3','3','.','d','l','l',0}; 374 WCHAR pathW[MAX_PATH], filenameW[MAX_PATH]; 375 BSTR path, version; 376 HRESULT hr; 377 378 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW)); 379 380 lstrcpyW(filenameW, pathW); 381 lstrcatW(filenameW, k32W); 382 383 path = SysAllocString(filenameW); 384 hr = IFileSystem3_GetFileVersion(fs3, path, &version); 385 ok(hr == S_OK, "got 0x%08x\n", hr); 386 ok(*version != 0, "got %s\n", wine_dbgstr_w(version)); 387 SysFreeString(version); 388 SysFreeString(path); 389 390 lstrcpyW(filenameW, pathW); 391 lstrcatW(filenameW, k33W); 392 393 path = SysAllocString(filenameW); 394 version = (void*)0xdeadbeef; 395 hr = IFileSystem3_GetFileVersion(fs3, path, &version); 396 ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 397 if (hr == S_OK) 398 { 399 ok(*version == 0, "got %s\n", wine_dbgstr_w(version)); 400 SysFreeString(version); 401 } 402 else 403 ok(version == (void*)0xdeadbeef, "got %p\n", version); 404 SysFreeString(path); 405 } 406 407 static void test_GetParentFolderName(void) 408 { 409 static const WCHAR path1[] = {'a',0}; 410 static const WCHAR path2[] = {'a','/','a','/','a',0}; 411 static const WCHAR path3[] = {'a','\\','a','\\','a',0}; 412 static const WCHAR path4[] = {'a','/','a','/','/','\\','\\',0}; 413 static const WCHAR path5[] = {'c',':','\\','\\','a',0}; 414 static const WCHAR path6[] = {'a','c',':','\\','a',0}; 415 static const WCHAR result2[] = {'a','/','a',0}; 416 static const WCHAR result3[] = {'a','\\','a',0}; 417 static const WCHAR result4[] = {'a',0}; 418 static const WCHAR result5[] = {'c',':','\\',0}; 419 static const WCHAR result6[] = {'a','c',':',0}; 420 421 static const struct { 422 const WCHAR *path; 423 const WCHAR *result; 424 } tests[] = { 425 {NULL, NULL}, 426 {path1, NULL}, 427 {path2, result2}, 428 {path3, result3}, 429 {path4, result4}, 430 {path5, result5}, 431 {path6, result6} 432 }; 433 434 BSTR path, result; 435 HRESULT hr; 436 int i; 437 438 hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL); 439 ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr); 440 441 for(i=0; i < ARRAY_SIZE(tests); i++) { 442 result = (BSTR)0xdeadbeef; 443 path = tests[i].path ? SysAllocString(tests[i].path) : NULL; 444 hr = IFileSystem3_GetParentFolderName(fs3, path, &result); 445 ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr); 446 if(!tests[i].result) 447 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result)); 448 else 449 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result)); 450 SysFreeString(path); 451 SysFreeString(result); 452 } 453 } 454 455 static void test_GetFileName(void) 456 { 457 static const WCHAR path1[] = {'a',0}; 458 static const WCHAR path2[] = {'a','/','a','.','b',0}; 459 static const WCHAR path3[] = {'a','\\',0}; 460 static const WCHAR path4[] = {'c',':',0}; 461 static const WCHAR path5[] = {'/','\\',0}; 462 static const WCHAR result2[] = {'a','.','b',0}; 463 static const WCHAR result3[] = {'a',0}; 464 465 static const struct { 466 const WCHAR *path; 467 const WCHAR *result; 468 } tests[] = { 469 {NULL, NULL}, 470 {path1, path1}, 471 {path2, result2}, 472 {path3, result3}, 473 {path4, NULL}, 474 {path5, NULL} 475 }; 476 477 BSTR path, result; 478 HRESULT hr; 479 int i; 480 481 hr = IFileSystem3_GetFileName(fs3, NULL, NULL); 482 ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr); 483 484 for(i=0; i < ARRAY_SIZE(tests); i++) { 485 result = (BSTR)0xdeadbeef; 486 path = tests[i].path ? SysAllocString(tests[i].path) : NULL; 487 hr = IFileSystem3_GetFileName(fs3, path, &result); 488 ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr); 489 if(!tests[i].result) 490 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result)); 491 else 492 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result)); 493 SysFreeString(path); 494 SysFreeString(result); 495 } 496 } 497 498 static void test_GetBaseName(void) 499 { 500 static const WCHAR path1[] = {'a',0}; 501 static const WCHAR path2[] = {'a','/','a','.','b','.','c',0}; 502 static const WCHAR path3[] = {'a','.','b','\\',0}; 503 static const WCHAR path4[] = {'c',':',0}; 504 static const WCHAR path5[] = {'/','\\',0}; 505 static const WCHAR path6[] = {'.','a',0}; 506 static const WCHAR result1[] = {'a',0}; 507 static const WCHAR result2[] = {'a','.','b',0}; 508 static const WCHAR result6[] = {0}; 509 510 static const struct { 511 const WCHAR *path; 512 const WCHAR *result; 513 } tests[] = { 514 {NULL, NULL}, 515 {path1, result1}, 516 {path2, result2}, 517 {path3, result1}, 518 {path4, NULL}, 519 {path5, NULL}, 520 {path6, result6} 521 }; 522 523 BSTR path, result; 524 HRESULT hr; 525 int i; 526 527 hr = IFileSystem3_GetBaseName(fs3, NULL, NULL); 528 ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr); 529 530 for(i=0; i < ARRAY_SIZE(tests); i++) { 531 result = (BSTR)0xdeadbeef; 532 path = tests[i].path ? SysAllocString(tests[i].path) : NULL; 533 hr = IFileSystem3_GetBaseName(fs3, path, &result); 534 ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr); 535 if(!tests[i].result) 536 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result)); 537 else 538 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result)); 539 SysFreeString(path); 540 SysFreeString(result); 541 } 542 } 543 544 static void test_GetAbsolutePathName(void) 545 { 546 static const WCHAR dir1[] = {'t','e','s','t','_','d','i','r','1',0}; 547 static const WCHAR dir2[] = {'t','e','s','t','_','d','i','r','2',0}; 548 static const WCHAR dir_match1[] = {'t','e','s','t','_','d','i','r','*',0}; 549 static const WCHAR dir_match2[] = {'t','e','s','t','_','d','i','*',0}; 550 static const WCHAR cur_dir[] = {'.',0}; 551 552 WIN32_FIND_DATAW fdata; 553 HANDLE find; 554 WCHAR buf[MAX_PATH], buf2[MAX_PATH]; 555 BSTR path, result; 556 HRESULT hr; 557 558 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL); 559 ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr); 560 561 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result); 562 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); 563 GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL); 564 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf)); 565 SysFreeString(result); 566 567 find = FindFirstFileW(dir_match2, &fdata); 568 if(find != INVALID_HANDLE_VALUE) { 569 skip("GetAbsolutePathName tests\n"); 570 FindClose(find); 571 return; 572 } 573 574 path = SysAllocString(dir_match1); 575 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); 576 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); 577 GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL); 578 ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2)); 579 SysFreeString(result); 580 581 ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1)); 582 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); 583 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); 584 GetFullPathNameW(dir1, MAX_PATH, buf, NULL); 585 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n", 586 wine_dbgstr_w(result), wine_dbgstr_w(buf)); 587 SysFreeString(result); 588 589 ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2)); 590 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); 591 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); 592 if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) { 593 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n", 594 wine_dbgstr_w(result), wine_dbgstr_w(buf)); 595 }else { 596 GetFullPathNameW(dir2, MAX_PATH, buf, NULL); 597 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", 598 wine_dbgstr_w(result), wine_dbgstr_w(buf)); 599 } 600 SysFreeString(result); 601 602 SysFreeString(path); 603 path = SysAllocString(dir_match2); 604 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); 605 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); 606 GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL); 607 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf)); 608 SysFreeString(result); 609 SysFreeString(path); 610 611 RemoveDirectoryW(dir1); 612 RemoveDirectoryW(dir2); 613 } 614 615 static void test_GetFile(void) 616 { 617 static const WCHAR slW[] = {'\\',0}; 618 BSTR path, str; 619 WCHAR pathW[MAX_PATH]; 620 FileAttribute fa; 621 VARIANT size; 622 DWORD gfa, new_gfa; 623 IFile *file; 624 HRESULT hr; 625 HANDLE hf; 626 BOOL ret; 627 DATE date; 628 629 get_temp_path(NULL, pathW); 630 631 path = SysAllocString(pathW); 632 hr = IFileSystem3_GetFile(fs3, path, NULL); 633 ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr); 634 hr = IFileSystem3_GetFile(fs3, NULL, &file); 635 ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr); 636 637 file = (IFile*)0xdeadbeef; 638 hr = IFileSystem3_GetFile(fs3, path, &file); 639 ok(!file, "file != NULL\n"); 640 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); 641 642 hf = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL); 643 if(hf == INVALID_HANDLE_VALUE) { 644 skip("Can't create temporary file\n"); 645 SysFreeString(path); 646 return; 647 } 648 CloseHandle(hf); 649 650 hr = IFileSystem3_GetFile(fs3, path, &file); 651 ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr); 652 653 hr = IFile_get_DateLastModified(file, NULL); 654 ok(hr == E_POINTER, "got 0x%08x\n", hr); 655 656 date = 0.0; 657 hr = IFile_get_DateLastModified(file, &date); 658 ok(hr == S_OK, "got 0x%08x\n", hr); 659 ok(date > 0.0, "got %f\n", date); 660 661 hr = IFile_get_Path(file, NULL); 662 ok(hr == E_POINTER, "got 0x%08x\n", hr); 663 664 hr = IFile_get_Path(file, &str); 665 ok(hr == S_OK, "got 0x%08x\n", hr); 666 ok(!lstrcmpiW(str, pathW), "got %s\n", wine_dbgstr_w(str)); 667 SysFreeString(str); 668 669 #define FILE_ATTR_MASK (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \ 670 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | \ 671 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED) 672 673 hr = IFile_get_Attributes(file, &fa); 674 gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK; 675 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr); 676 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa); 677 678 hr = IFile_put_Attributes(file, gfa | FILE_ATTRIBUTE_READONLY); 679 ok(hr == S_OK, "put_Attributes failed: %08x\n", hr); 680 new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK; 681 ok(new_gfa == (gfa|FILE_ATTRIBUTE_READONLY), "new_gfa = %x, expected %x\n", new_gfa, gfa|FILE_ATTRIBUTE_READONLY); 682 683 hr = IFile_get_Attributes(file, &fa); 684 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr); 685 ok(fa == new_gfa, "fa = %x, expected %x\n", fa, new_gfa); 686 687 hr = IFile_put_Attributes(file, gfa); 688 ok(hr == S_OK, "put_Attributes failed: %08x\n", hr); 689 new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK; 690 ok(new_gfa == gfa, "new_gfa = %x, expected %x\n", new_gfa, gfa); 691 692 hr = IFile_get_Attributes(file, &fa); 693 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr); 694 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa); 695 696 hr = IFile_get_Size(file, &size); 697 ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr); 698 ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size)); 699 ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size)); 700 IFile_Release(file); 701 702 hr = IFileSystem3_DeleteFile(fs3, path, FALSE); 703 ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK), 704 "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr); 705 if(hr != S_OK) { 706 hr = IFileSystem3_DeleteFile(fs3, path, TRUE); 707 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr); 708 } 709 hr = IFileSystem3_DeleteFile(fs3, path, TRUE); 710 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); 711 712 SysFreeString(path); 713 714 /* try with directory */ 715 lstrcatW(pathW, slW); 716 ret = CreateDirectoryW(pathW, NULL); 717 ok(ret, "got %d, error %d\n", ret, GetLastError()); 718 719 path = SysAllocString(pathW); 720 hr = IFileSystem3_GetFile(fs3, path, &file); 721 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected S_OK\n", hr); 722 SysFreeString(path); 723 724 RemoveDirectoryW(pathW); 725 } 726 727 static inline BOOL create_file(const WCHAR *name) 728 { 729 HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); 730 CloseHandle(f); 731 return f != INVALID_HANDLE_VALUE; 732 } 733 734 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret) 735 { 736 DWORD len = lstrlenW(folder); 737 memmove(ret, folder, len*sizeof(WCHAR)); 738 ret[len] = '\\'; 739 memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR)); 740 } 741 742 static void test_CopyFolder(void) 743 { 744 static const WCHAR filesystem3_dir[] = {'f','i','l','e','s','y','s','t','e','m','3','_','t','e','s','t',0}; 745 static const WCHAR s1[] = {'s','r','c','1',0}; 746 static const WCHAR s[] = {'s','r','c','*',0}; 747 static const WCHAR d[] = {'d','s','t',0}; 748 static const WCHAR empty[] = {0}; 749 750 WCHAR tmp[MAX_PATH]; 751 BSTR bsrc, bdst; 752 HRESULT hr; 753 754 if(!CreateDirectoryW(filesystem3_dir, NULL)) { 755 skip("can't create temporary directory\n"); 756 return; 757 } 758 759 create_path(filesystem3_dir, s1, tmp); 760 bsrc = SysAllocString(tmp); 761 create_path(filesystem3_dir, d, tmp); 762 bdst = SysAllocString(tmp); 763 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE); 764 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); 765 766 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 767 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr); 768 769 ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc)); 770 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE); 771 ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr); 772 773 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 774 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr); 775 776 hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE); 777 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr); 778 779 ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc)); 780 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE); 781 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); 782 783 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 784 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr); 785 786 hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE); 787 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr); 788 789 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 790 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); 791 792 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 793 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); 794 create_path(tmp, s1, tmp); 795 ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES, 796 "%s file exists\n", wine_dbgstr_w(tmp)); 797 798 create_path(filesystem3_dir, d, tmp); 799 create_path(tmp, empty, tmp); 800 SysFreeString(bdst); 801 bdst = SysAllocString(tmp); 802 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 803 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); 804 create_path(tmp, s1, tmp); 805 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES, 806 "%s directory doesn't exist\n", wine_dbgstr_w(tmp)); 807 ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp)); 808 create_path(filesystem3_dir, d, tmp); 809 SysFreeString(bdst); 810 bdst = SysAllocString(tmp); 811 812 813 create_path(filesystem3_dir, s, tmp); 814 SysFreeString(bsrc); 815 bsrc = SysAllocString(tmp); 816 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 817 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); 818 create_path(filesystem3_dir, d, tmp); 819 create_path(tmp, s1, tmp); 820 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES, 821 "%s directory doesn't exist\n", wine_dbgstr_w(tmp)); 822 823 hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE); 824 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr); 825 826 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 827 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr); 828 829 create_path(filesystem3_dir, s1, tmp); 830 SysFreeString(bsrc); 831 bsrc = SysAllocString(tmp); 832 create_path(tmp, s1, tmp); 833 ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp)); 834 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE); 835 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); 836 837 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE); 838 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr); 839 840 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); 841 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); 842 SysFreeString(bsrc); 843 SysFreeString(bdst); 844 845 bsrc = SysAllocString(filesystem3_dir); 846 hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE); 847 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr); 848 SysFreeString(bsrc); 849 } 850 851 static BSTR bstr_from_str(const char *str) 852 { 853 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 854 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */ 855 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); 856 return ret; 857 } 858 859 struct buildpath_test 860 { 861 const char *path; 862 const char *name; 863 const char *result; 864 }; 865 866 static struct buildpath_test buildpath_data[] = 867 { 868 { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" }, 869 { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" }, 870 { "C:\\path", "name.tmp", "C:\\path\\name.tmp" }, 871 { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" }, 872 { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" }, 873 { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" }, 874 { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" }, 875 { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" }, 876 { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" }, 877 { "C:", "name.tmp", "C:name.tmp" }, 878 { "C:", "\\\\name.tmp", "C:\\\\name.tmp" }, 879 { NULL } 880 }; 881 882 static void test_BuildPath(void) 883 { 884 struct buildpath_test *ptr = buildpath_data; 885 BSTR ret, path; 886 HRESULT hr; 887 int i = 0; 888 889 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL); 890 ok(hr == E_POINTER, "got 0x%08x\n", hr); 891 892 ret = (BSTR)0xdeadbeef; 893 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret); 894 ok(hr == S_OK, "got 0x%08x\n", hr); 895 ok(*ret == 0, "got %p\n", ret); 896 SysFreeString(ret); 897 898 ret = (BSTR)0xdeadbeef; 899 path = bstr_from_str("path"); 900 hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret); 901 ok(hr == S_OK, "got 0x%08x\n", hr); 902 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret)); 903 SysFreeString(ret); 904 SysFreeString(path); 905 906 ret = (BSTR)0xdeadbeef; 907 path = bstr_from_str("path"); 908 hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret); 909 ok(hr == S_OK, "got 0x%08x\n", hr); 910 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret)); 911 SysFreeString(ret); 912 SysFreeString(path); 913 914 while (ptr->path) 915 { 916 BSTR name, result; 917 918 ret = NULL; 919 path = bstr_from_str(ptr->path); 920 name = bstr_from_str(ptr->name); 921 result = bstr_from_str(ptr->result); 922 hr = IFileSystem3_BuildPath(fs3, path, name, &ret); 923 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); 924 if (hr == S_OK) 925 { 926 ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret), 927 wine_dbgstr_w(result)); 928 SysFreeString(ret); 929 } 930 SysFreeString(path); 931 SysFreeString(name); 932 SysFreeString(result); 933 934 i++; 935 ptr++; 936 } 937 } 938 939 static void test_GetFolder(void) 940 { 941 static const WCHAR dummyW[] = {'d','u','m','m','y',0}; 942 WCHAR buffW[MAX_PATH]; 943 IFolder *folder; 944 HRESULT hr; 945 BSTR str; 946 947 folder = (void*)0xdeadbeef; 948 hr = IFileSystem3_GetFolder(fs3, NULL, &folder); 949 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 950 ok(folder == NULL, "got %p\n", folder); 951 952 hr = IFileSystem3_GetFolder(fs3, NULL, NULL); 953 ok(hr == E_POINTER, "got 0x%08x\n", hr); 954 955 /* something that doesn't exist */ 956 str = SysAllocString(dummyW); 957 958 hr = IFileSystem3_GetFolder(fs3, str, NULL); 959 ok(hr == E_POINTER, "got 0x%08x\n", hr); 960 961 folder = (void*)0xdeadbeef; 962 hr = IFileSystem3_GetFolder(fs3, str, &folder); 963 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr); 964 ok(folder == NULL, "got %p\n", folder); 965 SysFreeString(str); 966 967 GetWindowsDirectoryW(buffW, MAX_PATH); 968 str = SysAllocString(buffW); 969 hr = IFileSystem3_GetFolder(fs3, str, &folder); 970 ok(hr == S_OK, "got 0x%08x\n", hr); 971 SysFreeString(str); 972 test_provideclassinfo(folder, &CLSID_Folder); 973 IFolder_Release(folder); 974 } 975 976 static void _test_clone(IEnumVARIANT *enumvar, BOOL position_inherited, LONG count, int line) 977 { 978 HRESULT hr; 979 IEnumVARIANT *clone; 980 ULONG fetched; 981 VARIANT var, var2; 982 983 hr = IEnumVARIANT_Reset(enumvar); 984 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr); 985 986 VariantInit(&var); 987 fetched = -1; 988 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); 989 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr); 990 ok(fetched == 1, "%d: got %d\n", line, fetched); 991 992 /* clone enumerator */ 993 hr = IEnumVARIANT_Clone(enumvar, &clone); 994 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr); 995 ok(clone != enumvar, "%d: got %p, %p\n", line, enumvar, clone); 996 997 /* check if clone inherits position */ 998 VariantInit(&var2); 999 fetched = -1; 1000 hr = IEnumVARIANT_Next(clone, 1, &var2, &fetched); 1001 if (position_inherited && count == 1) 1002 { 1003 ok(hr == S_FALSE, "%d: got 0x%08x\n", line, hr); 1004 ok(fetched == 0, "%d: got %d\n", line, fetched); 1005 } 1006 else 1007 { 1008 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr); 1009 ok(fetched == 1, "%d: got %d\n", line, fetched); 1010 if (!position_inherited) 1011 todo_wine ok(V_DISPATCH(&var) == V_DISPATCH(&var2), "%d: values don't match\n", line); 1012 else 1013 { 1014 fetched = -1; 1015 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); 1016 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr); 1017 ok(fetched == 1, "%d: got %d\n", line, fetched); 1018 todo_wine ok(V_DISPATCH(&var) == V_DISPATCH(&var2), "%d: values don't match\n", line); 1019 } 1020 } 1021 1022 VariantClear(&var2); 1023 VariantClear(&var); 1024 IEnumVARIANT_Release(clone); 1025 1026 hr = IEnumVARIANT_Reset(enumvar); 1027 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr); 1028 } 1029 #define test_clone(a, b, c) _test_clone(a, b, c, __LINE__) 1030 1031 /* Please keep the tests for IFolderCollection and IFileCollection in sync */ 1032 static void test_FolderCollection(void) 1033 { 1034 static const WCHAR fooW[] = {'f','o','o',0}; 1035 static const WCHAR aW[] = {'\\','a',0}; 1036 static const WCHAR bW[] = {'\\','b',0}; 1037 static const WCHAR cW[] = {'\\','c',0}; 1038 IFolderCollection *folders; 1039 WCHAR buffW[MAX_PATH], pathW[MAX_PATH]; 1040 IEnumVARIANT *enumvar; 1041 LONG count, ref, ref2, i; 1042 IUnknown *unk, *unk2; 1043 IFolder *folder; 1044 ULONG fetched; 1045 VARIANT var, var2[2]; 1046 HRESULT hr; 1047 BSTR str; 1048 int found_a = 0, found_b = 0, found_c = 0; 1049 1050 get_temp_path(fooW, buffW); 1051 CreateDirectoryW(buffW, NULL); 1052 1053 str = SysAllocString(buffW); 1054 hr = IFileSystem3_GetFolder(fs3, str, &folder); 1055 ok(hr == S_OK, "got 0x%08x\n", hr); 1056 SysFreeString(str); 1057 1058 hr = IFolder_get_SubFolders(folder, NULL); 1059 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1060 1061 hr = IFolder_get_Path(folder, NULL); 1062 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1063 1064 hr = IFolder_get_Path(folder, &str); 1065 ok(hr == S_OK, "got 0x%08x\n", hr); 1066 ok(!lstrcmpiW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW)); 1067 SysFreeString(str); 1068 1069 lstrcpyW(pathW, buffW); 1070 lstrcatW(pathW, aW); 1071 CreateDirectoryW(pathW, NULL); 1072 1073 lstrcpyW(pathW, buffW); 1074 lstrcatW(pathW, bW); 1075 CreateDirectoryW(pathW, NULL); 1076 1077 hr = IFolder_get_SubFolders(folder, &folders); 1078 ok(hr == S_OK, "got 0x%08x\n", hr); 1079 test_provideclassinfo(folders, &CLSID_Folders); 1080 IFolder_Release(folder); 1081 1082 count = 0; 1083 hr = IFolderCollection_get_Count(folders, &count); 1084 ok(hr == S_OK, "got 0x%08x\n", hr); 1085 ok(count == 2, "got %d\n", count); 1086 1087 lstrcpyW(pathW, buffW); 1088 lstrcatW(pathW, cW); 1089 CreateDirectoryW(pathW, NULL); 1090 1091 /* every time property is requested it scans directory */ 1092 count = 0; 1093 hr = IFolderCollection_get_Count(folders, &count); 1094 ok(hr == S_OK, "got 0x%08x\n", hr); 1095 ok(count == 3, "got %d\n", count); 1096 1097 hr = IFolderCollection_get__NewEnum(folders, NULL); 1098 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1099 1100 hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk); 1101 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 1102 1103 /* NewEnum creates new instance each time it's called */ 1104 ref = GET_REFCOUNT(folders); 1105 1106 unk = NULL; 1107 hr = IFolderCollection_get__NewEnum(folders, &unk); 1108 ok(hr == S_OK, "got 0x%08x\n", hr); 1109 1110 ref2 = GET_REFCOUNT(folders); 1111 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref); 1112 1113 unk2 = NULL; 1114 hr = IFolderCollection_get__NewEnum(folders, &unk2); 1115 ok(hr == S_OK, "got 0x%08x\n", hr); 1116 ok(unk != unk2, "got %p, %p\n", unk2, unk); 1117 IUnknown_Release(unk2); 1118 1119 /* now get IEnumVARIANT */ 1120 ref = GET_REFCOUNT(folders); 1121 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar); 1122 ok(hr == S_OK, "got 0x%08x\n", hr); 1123 ref2 = GET_REFCOUNT(folders); 1124 ok(ref2 == ref, "got %d, %d\n", ref2, ref); 1125 1126 test_clone(enumvar, FALSE, count); 1127 1128 for (i = 0; i < 3; i++) 1129 { 1130 VariantInit(&var); 1131 fetched = 0; 1132 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); 1133 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); 1134 ok(fetched == 1, "%d: got %d\n", i, fetched); 1135 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var)); 1136 1137 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder); 1138 ok(hr == S_OK, "got 0x%08x\n", hr); 1139 1140 str = NULL; 1141 hr = IFolder_get_Name(folder, &str); 1142 ok(hr == S_OK, "got 0x%08x\n", hr); 1143 if (!lstrcmpW(str, aW + 1)) 1144 found_a++; 1145 else if (!lstrcmpW(str, bW + 1)) 1146 found_b++; 1147 else if (!lstrcmpW(str, cW + 1)) 1148 found_c++; 1149 else 1150 ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str)); 1151 SysFreeString(str); 1152 1153 IFolder_Release(folder); 1154 VariantClear(&var); 1155 } 1156 1157 ok(found_a == 1 && found_b == 1 && found_c == 1, 1158 "each folder should be found 1 time instead of %d/%d/%d\n", 1159 found_a, found_b, found_c); 1160 1161 VariantInit(&var); 1162 fetched = -1; 1163 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); 1164 ok(hr == S_FALSE, "got 0x%08x\n", hr); 1165 ok(fetched == 0, "got %d\n", fetched); 1166 1167 hr = IEnumVARIANT_Reset(enumvar); 1168 ok(hr == S_OK, "got 0x%08x\n", hr); 1169 hr = IEnumVARIANT_Skip(enumvar, 2); 1170 ok(hr == S_OK, "got 0x%08x\n", hr); 1171 hr = IEnumVARIANT_Skip(enumvar, 0); 1172 ok(hr == S_OK, "got 0x%08x\n", hr); 1173 1174 VariantInit(&var2[0]); 1175 VariantInit(&var2[1]); 1176 fetched = -1; 1177 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched); 1178 ok(hr == S_OK, "got 0x%08x\n", hr); 1179 ok(fetched == 0, "got %d\n", fetched); 1180 fetched = -1; 1181 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched); 1182 ok(hr == S_FALSE, "got 0x%08x\n", hr); 1183 ok(fetched == 1, "got %d\n", fetched); 1184 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0])); 1185 VariantClear(&var2[0]); 1186 VariantClear(&var2[1]); 1187 1188 IEnumVARIANT_Release(enumvar); 1189 IUnknown_Release(unk); 1190 1191 lstrcpyW(pathW, buffW); 1192 lstrcatW(pathW, aW); 1193 RemoveDirectoryW(pathW); 1194 lstrcpyW(pathW, buffW); 1195 lstrcatW(pathW, bW); 1196 RemoveDirectoryW(pathW); 1197 lstrcpyW(pathW, buffW); 1198 lstrcatW(pathW, cW); 1199 RemoveDirectoryW(pathW); 1200 RemoveDirectoryW(buffW); 1201 1202 IFolderCollection_Release(folders); 1203 } 1204 1205 /* Please keep the tests for IFolderCollection and IFileCollection in sync */ 1206 static void test_FileCollection(void) 1207 { 1208 static const WCHAR fooW[] = {'\\','f','o','o',0}; 1209 static const WCHAR aW[] = {'\\','a',0}; 1210 static const WCHAR bW[] = {'\\','b',0}; 1211 static const WCHAR cW[] = {'\\','c',0}; 1212 WCHAR buffW[MAX_PATH], pathW[MAX_PATH]; 1213 IFolder *folder; 1214 IFileCollection *files; 1215 IFile *file; 1216 IEnumVARIANT *enumvar; 1217 LONG count, ref, ref2, i; 1218 IUnknown *unk, *unk2; 1219 ULONG fetched; 1220 VARIANT var, var2[2]; 1221 HRESULT hr; 1222 BSTR str; 1223 HANDLE file_a, file_b, file_c; 1224 int found_a = 0, found_b = 0, found_c = 0; 1225 1226 get_temp_path(fooW, buffW); 1227 CreateDirectoryW(buffW, NULL); 1228 1229 str = SysAllocString(buffW); 1230 hr = IFileSystem3_GetFolder(fs3, str, &folder); 1231 ok(hr == S_OK, "got 0x%08x\n", hr); 1232 SysFreeString(str); 1233 1234 hr = IFolder_get_Files(folder, NULL); 1235 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1236 1237 lstrcpyW(pathW, buffW); 1238 lstrcatW(pathW, aW); 1239 file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1240 FILE_FLAG_DELETE_ON_CLOSE, 0); 1241 lstrcpyW(pathW, buffW); 1242 lstrcatW(pathW, bW); 1243 file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1244 FILE_FLAG_DELETE_ON_CLOSE, 0); 1245 1246 hr = IFolder_get_Files(folder, &files); 1247 ok(hr == S_OK, "got 0x%08x\n", hr); 1248 test_provideclassinfo(files, &CLSID_Files); 1249 IFolder_Release(folder); 1250 1251 count = 0; 1252 hr = IFileCollection_get_Count(files, &count); 1253 ok(hr == S_OK, "got 0x%08x\n", hr); 1254 ok(count == 2, "got %d\n", count); 1255 1256 lstrcpyW(pathW, buffW); 1257 lstrcatW(pathW, cW); 1258 file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1259 FILE_FLAG_DELETE_ON_CLOSE, 0); 1260 1261 /* every time property is requested it scans directory */ 1262 count = 0; 1263 hr = IFileCollection_get_Count(files, &count); 1264 ok(hr == S_OK, "got 0x%08x\n", hr); 1265 ok(count == 3, "got %d\n", count); 1266 1267 hr = IFileCollection_get__NewEnum(files, NULL); 1268 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1269 1270 hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk); 1271 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 1272 1273 /* NewEnum creates new instance each time it's called */ 1274 ref = GET_REFCOUNT(files); 1275 1276 unk = NULL; 1277 hr = IFileCollection_get__NewEnum(files, &unk); 1278 ok(hr == S_OK, "got 0x%08x\n", hr); 1279 1280 ref2 = GET_REFCOUNT(files); 1281 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref); 1282 1283 unk2 = NULL; 1284 hr = IFileCollection_get__NewEnum(files, &unk2); 1285 ok(hr == S_OK, "got 0x%08x\n", hr); 1286 ok(unk != unk2, "got %p, %p\n", unk2, unk); 1287 IUnknown_Release(unk2); 1288 1289 /* now get IEnumVARIANT */ 1290 ref = GET_REFCOUNT(files); 1291 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar); 1292 ok(hr == S_OK, "got 0x%08x\n", hr); 1293 ref2 = GET_REFCOUNT(files); 1294 ok(ref2 == ref, "got %d, %d\n", ref2, ref); 1295 1296 test_clone(enumvar, FALSE, count); 1297 1298 for (i = 0; i < 3; i++) 1299 { 1300 VariantInit(&var); 1301 fetched = 0; 1302 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); 1303 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); 1304 ok(fetched == 1, "%d: got %d\n", i, fetched); 1305 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var)); 1306 1307 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file); 1308 ok(hr == S_OK, "got 0x%08x\n", hr); 1309 test_provideclassinfo(file, &CLSID_File); 1310 1311 str = NULL; 1312 hr = IFile_get_Name(file, &str); 1313 ok(hr == S_OK, "got 0x%08x\n", hr); 1314 if (!lstrcmpW(str, aW + 1)) 1315 found_a++; 1316 else if (!lstrcmpW(str, bW + 1)) 1317 found_b++; 1318 else if (!lstrcmpW(str, cW + 1)) 1319 found_c++; 1320 else 1321 ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str)); 1322 SysFreeString(str); 1323 1324 IFile_Release(file); 1325 VariantClear(&var); 1326 } 1327 1328 ok(found_a == 1 && found_b == 1 && found_c == 1, 1329 "each file should be found 1 time instead of %d/%d/%d\n", 1330 found_a, found_b, found_c); 1331 1332 VariantInit(&var); 1333 fetched = -1; 1334 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); 1335 ok(hr == S_FALSE, "got 0x%08x\n", hr); 1336 ok(fetched == 0, "got %d\n", fetched); 1337 1338 hr = IEnumVARIANT_Reset(enumvar); 1339 ok(hr == S_OK, "got 0x%08x\n", hr); 1340 hr = IEnumVARIANT_Skip(enumvar, 2); 1341 ok(hr == S_OK, "got 0x%08x\n", hr); 1342 hr = IEnumVARIANT_Skip(enumvar, 0); 1343 ok(hr == S_OK, "got 0x%08x\n", hr); 1344 1345 VariantInit(&var2[0]); 1346 VariantInit(&var2[1]); 1347 fetched = -1; 1348 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched); 1349 ok(hr == S_OK, "got 0x%08x\n", hr); 1350 ok(fetched == 0, "got %d\n", fetched); 1351 fetched = -1; 1352 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched); 1353 ok(hr == S_FALSE, "got 0x%08x\n", hr); 1354 ok(fetched == 1, "got %d\n", fetched); 1355 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0])); 1356 VariantClear(&var2[0]); 1357 VariantClear(&var2[1]); 1358 1359 IEnumVARIANT_Release(enumvar); 1360 IUnknown_Release(unk); 1361 1362 CloseHandle(file_a); 1363 CloseHandle(file_b); 1364 CloseHandle(file_c); 1365 RemoveDirectoryW(buffW); 1366 1367 IFileCollection_Release(files); 1368 } 1369 1370 static void test_DriveCollection(void) 1371 { 1372 IDriveCollection *drives; 1373 IEnumVARIANT *enumvar; 1374 ULONG fetched; 1375 VARIANT var; 1376 HRESULT hr; 1377 LONG count; 1378 1379 hr = IFileSystem3_get_Drives(fs3, &drives); 1380 ok(hr == S_OK, "got 0x%08x\n", hr); 1381 1382 test_provideclassinfo(drives, &CLSID_Drives); 1383 1384 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar); 1385 ok(hr == S_OK, "got 0x%08x\n", hr); 1386 1387 hr = IDriveCollection_get_Count(drives, NULL); 1388 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1389 1390 count = 0; 1391 hr = IDriveCollection_get_Count(drives, &count); 1392 ok(hr == S_OK, "got 0x%08x\n", hr); 1393 ok(count > 0, "got %d\n", count); 1394 1395 V_VT(&var) = VT_EMPTY; 1396 fetched = -1; 1397 hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched); 1398 ok(hr == S_OK, "got 0x%08x\n", hr); 1399 ok(fetched == 0, "got %d\n", fetched); 1400 1401 hr = IEnumVARIANT_Skip(enumvar, 0); 1402 ok(hr == S_OK, "got 0x%08x\n", hr); 1403 1404 hr = IEnumVARIANT_Skip(enumvar, count); 1405 ok(hr == S_OK, "got 0x%08x\n", hr); 1406 1407 hr = IEnumVARIANT_Skip(enumvar, 1); 1408 ok(hr == S_FALSE, "got 0x%08x\n", hr); 1409 1410 test_clone(enumvar, TRUE, count); 1411 1412 while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) { 1413 IDrive *drive = (IDrive*)V_DISPATCH(&var); 1414 DriveTypeConst type; 1415 BSTR str; 1416 1417 hr = IDrive_get_DriveType(drive, &type); 1418 ok(hr == S_OK, "got 0x%08x\n", hr); 1419 1420 hr = IDrive_get_DriveLetter(drive, NULL); 1421 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1422 1423 hr = IDrive_get_DriveLetter(drive, &str); 1424 ok(hr == S_OK, "got 0x%08x\n", hr); 1425 ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str)); 1426 SysFreeString(str); 1427 1428 hr = IDrive_get_IsReady(drive, NULL); 1429 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1430 1431 hr = IDrive_get_TotalSize(drive, NULL); 1432 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1433 1434 hr = IDrive_get_AvailableSpace(drive, NULL); 1435 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1436 1437 hr = IDrive_get_FreeSpace(drive, NULL); 1438 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1439 1440 if (type == Fixed) { 1441 VARIANT_BOOL ready = VARIANT_FALSE; 1442 VARIANT size; 1443 1444 hr = IDrive_get_IsReady(drive, &ready); 1445 ok(hr == S_OK, "got 0x%08x\n", hr); 1446 ok(ready == VARIANT_TRUE, "got %x\n", ready); 1447 1448 if (ready != VARIANT_TRUE) { 1449 hr = IDrive_get_DriveLetter(drive, &str); 1450 ok(hr == S_OK, "got 0x%08x\n", hr); 1451 1452 skip("Drive %s is not ready, skipping some tests\n", wine_dbgstr_w(str)); 1453 1454 VariantClear(&var); 1455 SysFreeString(str); 1456 continue; 1457 } 1458 1459 V_VT(&size) = VT_EMPTY; 1460 hr = IDrive_get_TotalSize(drive, &size); 1461 ok(hr == S_OK, "got 0x%08x\n", hr); 1462 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size)); 1463 if (V_VT(&size) == VT_R8) 1464 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size)); 1465 else 1466 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size)); 1467 1468 V_VT(&size) = VT_EMPTY; 1469 hr = IDrive_get_AvailableSpace(drive, &size); 1470 ok(hr == S_OK, "got 0x%08x\n", hr); 1471 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size)); 1472 if (V_VT(&size) == VT_R8) 1473 ok(V_R8(&size) > (double)INT_MAX, "got %f\n", V_R8(&size)); 1474 else 1475 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size)); 1476 1477 V_VT(&size) = VT_EMPTY; 1478 hr = IDrive_get_FreeSpace(drive, &size); 1479 ok(hr == S_OK, "got 0x%08x\n", hr); 1480 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size)); 1481 if (V_VT(&size) == VT_R8) 1482 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size)); 1483 else 1484 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size)); 1485 } 1486 VariantClear(&var); 1487 } 1488 1489 IEnumVARIANT_Release(enumvar); 1490 IDriveCollection_Release(drives); 1491 } 1492 1493 static void get_temp_filepath(const WCHAR *filename, WCHAR *path, WCHAR *dir) 1494 { 1495 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; 1496 1497 GetTempPathW(MAX_PATH, path); 1498 lstrcatW(path, scrrunW); 1499 lstrcpyW(dir, path); 1500 lstrcatW(path, filename); 1501 } 1502 1503 static void test_CreateTextFile(void) 1504 { 1505 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10]; 1506 ITextStream *stream; 1507 BSTR nameW, str; 1508 HANDLE file; 1509 HRESULT hr; 1510 BOOL ret; 1511 1512 get_temp_filepath(testfileW, pathW, dirW); 1513 1514 /* dir doesn't exist */ 1515 nameW = SysAllocString(pathW); 1516 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); 1517 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr); 1518 1519 ret = CreateDirectoryW(dirW, NULL); 1520 ok(ret, "got %d, %d\n", ret, GetLastError()); 1521 1522 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); 1523 ok(hr == S_OK, "got 0x%08x\n", hr); 1524 1525 test_provideclassinfo(stream, &CLSID_TextStream); 1526 1527 hr = ITextStream_Read(stream, 1, &str); 1528 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 1529 1530 hr = ITextStream_Close(stream); 1531 ok(hr == S_OK, "got 0x%08x\n", hr); 1532 1533 hr = ITextStream_Read(stream, 1, &str); 1534 ok(hr == CTL_E_BADFILEMODE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr); 1535 1536 hr = ITextStream_Close(stream); 1537 ok(hr == S_FALSE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr); 1538 1539 ITextStream_Release(stream); 1540 1541 /* check it's created */ 1542 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1543 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file); 1544 CloseHandle(file); 1545 1546 /* try to create again with no-overwrite mode */ 1547 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); 1548 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr); 1549 1550 /* now overwrite */ 1551 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); 1552 ok(hr == S_OK, "got 0x%08x\n", hr); 1553 ITextStream_Release(stream); 1554 1555 /* overwrite in Unicode mode, check for BOM */ 1556 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream); 1557 ok(hr == S_OK, "got 0x%08x\n", hr); 1558 ITextStream_Release(stream); 1559 1560 /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode 1561 treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */ 1562 buffW[0] = 0; 1563 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW)); 1564 1565 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); 1566 ok(hr == S_OK, "got 0x%08x\n", hr); 1567 hr = ITextStream_ReadAll(stream, &str); 1568 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); 1569 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW)); 1570 SysFreeString(str); 1571 ITextStream_Release(stream); 1572 1573 DeleteFileW(nameW); 1574 RemoveDirectoryW(dirW); 1575 SysFreeString(nameW); 1576 } 1577 1578 static void test_WriteLine(void) 1579 { 1580 WCHAR pathW[MAX_PATH], dirW[MAX_PATH]; 1581 WCHAR buffW[MAX_PATH], buff2W[MAX_PATH]; 1582 char buffA[MAX_PATH]; 1583 ITextStream *stream; 1584 DWORD r, len; 1585 HANDLE file; 1586 BSTR nameW; 1587 HRESULT hr; 1588 BOOL ret; 1589 1590 get_temp_filepath(testfileW, pathW, dirW); 1591 1592 ret = CreateDirectoryW(dirW, NULL); 1593 ok(ret, "got %d, %d\n", ret, GetLastError()); 1594 1595 /* create as ASCII file first */ 1596 nameW = SysAllocString(pathW); 1597 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); 1598 ok(hr == S_OK, "got 0x%08x\n", hr); 1599 1600 hr = ITextStream_WriteLine(stream, nameW); 1601 ok(hr == S_OK, "got 0x%08x\n", hr); 1602 ITextStream_Release(stream); 1603 1604 /* check contents */ 1605 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1606 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file); 1607 r = 0; 1608 ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL); 1609 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError()); 1610 1611 len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, ARRAY_SIZE(buffW)); 1612 buffW[len] = 0; 1613 lstrcpyW(buff2W, nameW); 1614 lstrcatW(buff2W, crlfW); 1615 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W)); 1616 CloseHandle(file); 1617 DeleteFileW(nameW); 1618 1619 /* same for unicode file */ 1620 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream); 1621 ok(hr == S_OK, "got 0x%08x\n", hr); 1622 1623 hr = ITextStream_WriteLine(stream, nameW); 1624 ok(hr == S_OK, "got 0x%08x\n", hr); 1625 ITextStream_Release(stream); 1626 1627 /* check contents */ 1628 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1629 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file); 1630 r = 0; 1631 ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL); 1632 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError()); 1633 buffW[r/sizeof(WCHAR)] = 0; 1634 1635 buff2W[0] = 0xfeff; 1636 buff2W[1] = 0; 1637 lstrcatW(buff2W, nameW); 1638 lstrcatW(buff2W, crlfW); 1639 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W)); 1640 CloseHandle(file); 1641 DeleteFileW(nameW); 1642 1643 RemoveDirectoryW(dirW); 1644 SysFreeString(nameW); 1645 } 1646 1647 static void test_ReadAll(void) 1648 { 1649 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0}; 1650 static const WCHAR aW[] = {'A',0}; 1651 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500]; 1652 ITextStream *stream; 1653 BSTR nameW; 1654 HRESULT hr; 1655 BOOL ret; 1656 BSTR str; 1657 1658 get_temp_filepath(testfileW, pathW, dirW); 1659 1660 ret = CreateDirectoryW(dirW, NULL); 1661 ok(ret, "got %d, %d\n", ret, GetLastError()); 1662 1663 /* Unicode file -> read with ascii stream */ 1664 nameW = SysAllocString(pathW); 1665 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream); 1666 ok(hr == S_OK, "got 0x%08x\n", hr); 1667 1668 hr = ITextStream_WriteLine(stream, nameW); 1669 ok(hr == S_OK, "got 0x%08x\n", hr); 1670 1671 str = SysAllocString(secondlineW); 1672 hr = ITextStream_WriteLine(stream, str); 1673 ok(hr == S_OK, "got 0x%08x\n", hr); 1674 SysFreeString(str); 1675 1676 hr = ITextStream_ReadAll(stream, NULL); 1677 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1678 1679 str = (void*)0xdeadbeef; 1680 hr = ITextStream_ReadAll(stream, &str); 1681 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 1682 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); 1683 1684 ITextStream_Release(stream); 1685 1686 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); 1687 ok(hr == S_OK, "got 0x%08x\n", hr); 1688 1689 hr = ITextStream_ReadAll(stream, NULL); 1690 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1691 1692 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */ 1693 str = NULL; 1694 hr = ITextStream_ReadAll(stream, &str); 1695 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); 1696 buffW[0] = 0; 1697 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW)); 1698 ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str)); 1699 SysFreeString(str); 1700 ITextStream_Release(stream); 1701 1702 /* Unicode file -> read with unicode stream */ 1703 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 1704 ok(hr == S_OK, "got 0x%08x\n", hr); 1705 1706 lstrcpyW(buffW, nameW); 1707 lstrcatW(buffW, crlfW); 1708 lstrcatW(buffW, secondlineW); 1709 lstrcatW(buffW, crlfW); 1710 str = NULL; 1711 hr = ITextStream_ReadAll(stream, &str); 1712 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); 1713 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); 1714 SysFreeString(str); 1715 1716 /* ReadAll one more time */ 1717 str = (void*)0xdeadbeef; 1718 hr = ITextStream_ReadAll(stream, &str); 1719 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); 1720 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); 1721 1722 /* ReadLine fails the same way */ 1723 str = (void*)0xdeadbeef; 1724 hr = ITextStream_ReadLine(stream, &str); 1725 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); 1726 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); 1727 ITextStream_Release(stream); 1728 1729 /* Open again and skip first line before ReadAll */ 1730 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 1731 ok(hr == S_OK, "got 0x%08x\n", hr); 1732 1733 str = NULL; 1734 hr = ITextStream_ReadLine(stream, &str); 1735 todo_wine { 1736 ok(hr == S_OK, "got 0x%08x\n", hr); 1737 ok(str != NULL, "got %p\n", str); 1738 } 1739 SysFreeString(str); 1740 1741 lstrcpyW(buffW, secondlineW); 1742 lstrcatW(buffW, crlfW); 1743 str = NULL; 1744 hr = ITextStream_ReadAll(stream, &str); 1745 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); 1746 todo_wine 1747 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); 1748 SysFreeString(str); 1749 ITextStream_Release(stream); 1750 1751 /* ASCII file, read with Unicode stream */ 1752 /* 1. one byte content, not enough for Unicode read */ 1753 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); 1754 ok(hr == S_OK, "got 0x%08x\n", hr); 1755 str = SysAllocString(aW); 1756 hr = ITextStream_Write(stream, str); 1757 ok(hr == S_OK, "got 0x%08x\n", hr); 1758 SysFreeString(str); 1759 ITextStream_Release(stream); 1760 1761 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 1762 ok(hr == S_OK, "got 0x%08x\n", hr); 1763 1764 str = (void*)0xdeadbeef; 1765 hr = ITextStream_ReadAll(stream, &str); 1766 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); 1767 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); 1768 1769 ITextStream_Release(stream); 1770 1771 DeleteFileW(nameW); 1772 RemoveDirectoryW(dirW); 1773 SysFreeString(nameW); 1774 } 1775 1776 static void test_Read(void) 1777 { 1778 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0}; 1779 static const WCHAR aW[] = {'A',0}; 1780 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500]; 1781 ITextStream *stream; 1782 BSTR nameW; 1783 HRESULT hr; 1784 BOOL ret; 1785 BSTR str; 1786 1787 get_temp_filepath(testfileW, pathW, dirW); 1788 1789 ret = CreateDirectoryW(dirW, NULL); 1790 ok(ret, "got %d, %d\n", ret, GetLastError()); 1791 1792 /* Unicode file -> read with ascii stream */ 1793 nameW = SysAllocString(pathW); 1794 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream); 1795 ok(hr == S_OK, "got 0x%08x\n", hr); 1796 1797 hr = ITextStream_WriteLine(stream, nameW); 1798 ok(hr == S_OK, "got 0x%08x\n", hr); 1799 1800 str = SysAllocString(secondlineW); 1801 hr = ITextStream_WriteLine(stream, str); 1802 ok(hr == S_OK, "got 0x%08x\n", hr); 1803 SysFreeString(str); 1804 1805 hr = ITextStream_Read(stream, 0, NULL); 1806 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1807 1808 hr = ITextStream_Read(stream, 1, NULL); 1809 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1810 1811 hr = ITextStream_Read(stream, -1, NULL); 1812 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1813 1814 str = (void*)0xdeadbeef; 1815 hr = ITextStream_Read(stream, 1, &str); 1816 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); 1817 ok(str == NULL, "got %p\n", str); 1818 1819 ITextStream_Release(stream); 1820 1821 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); 1822 ok(hr == S_OK, "got 0x%08x\n", hr); 1823 1824 hr = ITextStream_Read(stream, 1, NULL); 1825 ok(hr == E_POINTER, "got 0x%08x\n", hr); 1826 1827 str = (void*)0xdeadbeef; 1828 hr = ITextStream_Read(stream, -1, &str); 1829 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 1830 ok(str == NULL, "got %p\n", str); 1831 1832 str = (void*)0xdeadbeef; 1833 hr = ITextStream_Read(stream, 0, &str); 1834 ok(hr == S_OK, "got 0x%08x\n", hr); 1835 ok(str == NULL, "got %p\n", str); 1836 1837 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */ 1838 str = NULL; 1839 hr = ITextStream_Read(stream, 2, &str); 1840 ok(hr == S_OK, "got 0x%08x\n", hr); 1841 1842 buffW[0] = 0; 1843 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW)); 1844 1845 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW)); 1846 ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str)); 1847 SysFreeString(str); 1848 ITextStream_Release(stream); 1849 1850 /* Unicode file -> read with unicode stream */ 1851 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 1852 ok(hr == S_OK, "got 0x%08x\n", hr); 1853 1854 lstrcpyW(buffW, nameW); 1855 lstrcatW(buffW, crlfW); 1856 lstrcatW(buffW, secondlineW); 1857 lstrcatW(buffW, crlfW); 1858 str = NULL; 1859 hr = ITextStream_Read(stream, 500, &str); 1860 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); 1861 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); 1862 SysFreeString(str); 1863 1864 /* ReadAll one more time */ 1865 str = (void*)0xdeadbeef; 1866 hr = ITextStream_Read(stream, 10, &str); 1867 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); 1868 ok(str == NULL, "got %p\n", str); 1869 1870 /* ReadLine fails the same way */ 1871 str = (void*)0xdeadbeef; 1872 hr = ITextStream_ReadLine(stream, &str); 1873 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); 1874 ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str); 1875 ITextStream_Release(stream); 1876 1877 /* Open again and skip first line before ReadAll */ 1878 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 1879 ok(hr == S_OK, "got 0x%08x\n", hr); 1880 1881 str = NULL; 1882 hr = ITextStream_ReadLine(stream, &str); 1883 todo_wine { 1884 ok(hr == S_OK, "got 0x%08x\n", hr); 1885 ok(str != NULL, "got %p\n", str); 1886 } 1887 SysFreeString(str); 1888 1889 lstrcpyW(buffW, secondlineW); 1890 lstrcatW(buffW, crlfW); 1891 str = NULL; 1892 hr = ITextStream_Read(stream, 100, &str); 1893 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); 1894 todo_wine 1895 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); 1896 SysFreeString(str); 1897 ITextStream_Release(stream); 1898 1899 /* default read will use Unicode */ 1900 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateUseDefault, &stream); 1901 ok(hr == S_OK, "got 0x%08x\n", hr); 1902 1903 lstrcpyW(buffW, nameW); 1904 lstrcatW(buffW, crlfW); 1905 lstrcatW(buffW, secondlineW); 1906 lstrcatW(buffW, crlfW); 1907 str = NULL; 1908 hr = ITextStream_Read(stream, 500, &str); 1909 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr); 1910 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); 1911 SysFreeString(str); 1912 1913 ITextStream_Release(stream); 1914 1915 /* default append will use Unicode */ 1916 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForAppending, VARIANT_FALSE, TristateUseDefault, &stream); 1917 ok(hr == S_OK, "got 0x%08x\n", hr); 1918 1919 str = SysAllocString(L"123"); 1920 hr = ITextStream_Write(stream, str); 1921 ok(hr == S_OK, "got %08x\n", hr); 1922 SysFreeString(str); 1923 1924 ITextStream_Release(stream); 1925 1926 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 1927 ok(hr == S_OK, "got 0x%08x\n", hr); 1928 1929 lstrcatW(buffW, L"123"); 1930 str = NULL; 1931 hr = ITextStream_Read(stream, 500, &str); 1932 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr); 1933 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); 1934 SysFreeString(str); 1935 1936 ITextStream_Release(stream); 1937 1938 /* default write will use ASCII */ 1939 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForWriting, VARIANT_FALSE, TristateUseDefault, &stream); 1940 ok(hr == S_OK, "got 0x%08x\n", hr); 1941 1942 str = SysAllocString(L"123"); 1943 hr = ITextStream_Write(stream, str); 1944 ok(hr == S_OK, "got %08x\n", hr); 1945 SysFreeString(str); 1946 1947 ITextStream_Release(stream); 1948 1949 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); 1950 ok(hr == S_OK, "got 0x%08x\n", hr); 1951 1952 str = (void*)0xdeadbeef; 1953 hr = ITextStream_Read(stream, 500, &str); 1954 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr); 1955 ok(!wcscmp(str, L"123"), "got %s\n", wine_dbgstr_w(str)); 1956 1957 ITextStream_Release(stream); 1958 /* ASCII file, read with default stream */ 1959 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); 1960 ok(hr == S_OK, "got 0x%08x\n", hr); 1961 str = SysAllocString(L"test"); 1962 hr = ITextStream_Write(stream, str); 1963 ok(hr == S_OK, "got 0x%08x\n", hr); 1964 SysFreeString(str); 1965 ITextStream_Release(stream); 1966 1967 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateUseDefault, &stream); 1968 ok(hr == S_OK, "got 0x%08x\n", hr); 1969 1970 str = (void*)0xdeadbeef; 1971 hr = ITextStream_Read(stream, 500, &str); 1972 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr); 1973 ok(!wcscmp(str, L"test"), "got %s\n", wine_dbgstr_w(str)); 1974 1975 ITextStream_Release(stream); 1976 1977 /* default append will use Unicode */ 1978 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForAppending, VARIANT_FALSE, TristateUseDefault, &stream); 1979 ok(hr == S_OK, "got 0x%08x\n", hr); 1980 1981 str = SysAllocString(L"123"); 1982 hr = ITextStream_Write(stream, str); 1983 ok(hr == S_OK, "got %08x\n", hr); 1984 SysFreeString(str); 1985 1986 ITextStream_Release(stream); 1987 1988 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); 1989 ok(hr == S_OK, "got 0x%08x\n", hr); 1990 1991 str = NULL; 1992 hr = ITextStream_Read(stream, 500, &str); 1993 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr); 1994 ok(!lstrcmpW(L"test123", str), "got %s\n", wine_dbgstr_w(str)); 1995 SysFreeString(str); 1996 1997 ITextStream_Release(stream); 1998 1999 /* default write will use ASCII as well */ 2000 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForWriting, VARIANT_FALSE, TristateUseDefault, &stream); 2001 ok(hr == S_OK, "got 0x%08x\n", hr); 2002 2003 str = SysAllocString(L"test string"); 2004 hr = ITextStream_Write(stream, str); 2005 ok(hr == S_OK, "got %08x\n", hr); 2006 SysFreeString(str); 2007 2008 ITextStream_Release(stream); 2009 2010 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); 2011 ok(hr == S_OK, "got 0x%08x\n", hr); 2012 2013 str = (void*)0xdeadbeef; 2014 hr = ITextStream_Read(stream, 500, &str); 2015 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr); 2016 ok(!wcscmp(str, L"test string"), "got %s\n", wine_dbgstr_w(str)); 2017 2018 ITextStream_Release(stream); 2019 2020 /* ASCII file, read with Unicode stream */ 2021 /* 1. one byte content, not enough for Unicode read */ 2022 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); 2023 ok(hr == S_OK, "got 0x%08x\n", hr); 2024 str = SysAllocString(aW); 2025 hr = ITextStream_Write(stream, str); 2026 ok(hr == S_OK, "got 0x%08x\n", hr); 2027 SysFreeString(str); 2028 ITextStream_Release(stream); 2029 2030 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); 2031 ok(hr == S_OK, "got 0x%08x\n", hr); 2032 2033 str = (void*)0xdeadbeef; 2034 hr = ITextStream_Read(stream, 500, &str); 2035 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); 2036 ok(str == NULL, "got %p\n", str); 2037 2038 ITextStream_Release(stream); 2039 2040 DeleteFileW(nameW); 2041 RemoveDirectoryW(dirW); 2042 SysFreeString(nameW); 2043 } 2044 2045 struct driveexists_test { 2046 const WCHAR drivespec[10]; 2047 const INT drivetype; 2048 const VARIANT_BOOL expected_ret; 2049 }; 2050 2051 /* If 'drivetype' != -1, the first character of 'drivespec' will be replaced 2052 * with the drive letter of a drive of this type. If such a drive does not exist, 2053 * the test will be skipped. */ 2054 static const struct driveexists_test driveexiststestdata[] = { 2055 { {'N',':','\\',0}, DRIVE_NO_ROOT_DIR, VARIANT_FALSE }, 2056 { {'R',':','\\',0}, DRIVE_REMOVABLE, VARIANT_TRUE }, 2057 { {'F',':','\\',0}, DRIVE_FIXED, VARIANT_TRUE }, 2058 { {'F',':',0}, DRIVE_FIXED, VARIANT_TRUE }, 2059 { {'F','?',0}, DRIVE_FIXED, VARIANT_FALSE }, 2060 { {'F',0}, DRIVE_FIXED, VARIANT_TRUE }, 2061 { {'?',0}, -1, VARIANT_FALSE }, 2062 { { 0 } } 2063 }; 2064 2065 static void test_DriveExists(void) 2066 { 2067 const struct driveexists_test *ptr = driveexiststestdata; 2068 HRESULT hr; 2069 VARIANT_BOOL ret; 2070 BSTR drivespec; 2071 WCHAR root[] = {'?',':','\\',0}; 2072 2073 hr = IFileSystem3_DriveExists(fs3, NULL, NULL); 2074 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2075 2076 ret = VARIANT_TRUE; 2077 hr = IFileSystem3_DriveExists(fs3, NULL, &ret); 2078 ok(hr == S_OK, "got 0x%08x\n", hr); 2079 ok(ret == VARIANT_FALSE, "got %x\n", ret); 2080 2081 drivespec = SysAllocString(root); 2082 hr = IFileSystem3_DriveExists(fs3, drivespec, NULL); 2083 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2084 SysFreeString(drivespec); 2085 2086 for (; *ptr->drivespec; ptr++) { 2087 drivespec = SysAllocString(ptr->drivespec); 2088 if (ptr->drivetype != -1) { 2089 for (root[0] = 'A'; root[0] <= 'Z'; root[0]++) 2090 if (GetDriveTypeW(root) == ptr->drivetype) 2091 break; 2092 if (root[0] > 'Z') { 2093 skip("No drive with type 0x%x found, skipping test %s.\n", 2094 ptr->drivetype, wine_dbgstr_w(ptr->drivespec)); 2095 SysFreeString(drivespec); 2096 continue; 2097 } 2098 2099 /* Test both upper and lower case drive letters. */ 2100 drivespec[0] = root[0]; 2101 ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE; 2102 hr = IFileSystem3_DriveExists(fs3, drivespec, &ret); 2103 ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n", 2104 hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); 2105 ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n", 2106 ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); 2107 2108 drivespec[0] = tolower(root[0]); 2109 } 2110 2111 ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE; 2112 hr = IFileSystem3_DriveExists(fs3, drivespec, &ret); 2113 ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n", 2114 hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); 2115 ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n", 2116 ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); 2117 2118 SysFreeString(drivespec); 2119 } 2120 } 2121 2122 struct getdrivename_test { 2123 const WCHAR path[10]; 2124 const WCHAR drive[5]; 2125 }; 2126 2127 static const struct getdrivename_test getdrivenametestdata[] = { 2128 { {'C',':','\\','1','.','t','s','t',0}, {'C',':',0} }, 2129 { {'O',':','\\','1','.','t','s','t',0}, {'O',':',0} }, 2130 { {'O',':',0}, {'O',':',0} }, 2131 { {'o',':',0}, {'o',':',0} }, 2132 { {'O','O',':',0} }, 2133 { {':',0} }, 2134 { {'O',0} }, 2135 { { 0 } } 2136 }; 2137 2138 static void test_GetDriveName(void) 2139 { 2140 const struct getdrivename_test *ptr = getdrivenametestdata; 2141 HRESULT hr; 2142 BSTR name; 2143 2144 hr = IFileSystem3_GetDriveName(fs3, NULL, NULL); 2145 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2146 2147 name = (void*)0xdeadbeef; 2148 hr = IFileSystem3_GetDriveName(fs3, NULL, &name); 2149 ok(hr == S_OK, "got 0x%08x\n", hr); 2150 ok(name == NULL, "got %p\n", name); 2151 2152 while (*ptr->path) { 2153 BSTR path = SysAllocString(ptr->path); 2154 name = (void*)0xdeadbeef; 2155 hr = IFileSystem3_GetDriveName(fs3, path, &name); 2156 ok(hr == S_OK, "got 0x%08x\n", hr); 2157 if (name) 2158 ok(!lstrcmpW(ptr->drive, name), "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive)); 2159 else 2160 ok(!*ptr->drive, "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive)); 2161 SysFreeString(path); 2162 SysFreeString(name); 2163 ptr++; 2164 } 2165 } 2166 2167 struct getdrive_test { 2168 const WCHAR drivespec[12]; 2169 HRESULT res; 2170 const WCHAR driveletter[2]; 2171 }; 2172 2173 static void test_GetDrive(void) 2174 { 2175 HRESULT hr; 2176 IDrive *drive_fixed, *drive; 2177 BSTR dl_fixed, drivespec; 2178 WCHAR root[] = {'?',':','\\',0}; 2179 2180 drive = (void*)0xdeadbeef; 2181 hr = IFileSystem3_GetDrive(fs3, NULL, NULL); 2182 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2183 ok(drive == (void*)0xdeadbeef, "got %p\n", drive); 2184 2185 for (root[0] = 'A'; root[0] <= 'Z'; root[0]++) 2186 if (GetDriveTypeW(root) == DRIVE_NO_ROOT_DIR) 2187 break; 2188 2189 if (root[0] > 'Z') 2190 skip("All drive letters are occupied, skipping test for nonexisting drive.\n"); 2191 else { 2192 drivespec = SysAllocString(root); 2193 drive = (void*)0xdeadbeef; 2194 hr = IFileSystem3_GetDrive(fs3, drivespec, &drive); 2195 ok(hr == CTL_E_DEVICEUNAVAILABLE, "got 0x%08x\n", hr); 2196 ok(drive == NULL, "got %p\n", drive); 2197 SysFreeString(drivespec); 2198 } 2199 2200 drive_fixed = get_fixed_drive(); 2201 if (!drive_fixed) { 2202 skip("No fixed drive found, skipping test.\n"); 2203 return; 2204 } 2205 2206 hr = IDrive_get_DriveLetter(drive_fixed, &dl_fixed); 2207 ok(hr == S_OK, "got 0x%08x\n", hr); 2208 2209 if (FAILED(hr)) 2210 skip("Could not retrieve drive letter of fixed drive, skipping test.\n"); 2211 else { 2212 WCHAR dl_upper = toupper(dl_fixed[0]); 2213 WCHAR dl_lower = tolower(dl_fixed[0]); 2214 struct getdrive_test testdata[] = { 2215 { {dl_upper,0}, S_OK, {dl_upper,0} }, 2216 { {dl_upper,':',0}, S_OK, {dl_upper,0} }, 2217 { {dl_upper,':','\\',0}, S_OK, {dl_upper,0} }, 2218 { {dl_lower,':','\\',0}, S_OK, {dl_upper,0} }, 2219 { {dl_upper,'\\',0}, E_INVALIDARG, { 0 } }, 2220 { {dl_lower,'\\',0}, E_INVALIDARG, { 0 } }, 2221 { {'$',':','\\',0}, E_INVALIDARG, { 0 } }, 2222 { {'\\','h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } }, 2223 { {'h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } }, 2224 { { 0 } }, 2225 }; 2226 struct getdrive_test *ptr = &testdata[0]; 2227 2228 for (; *ptr->drivespec; ptr++) { 2229 drivespec = SysAllocString(ptr->drivespec); 2230 drive = (void*)0xdeadbeef; 2231 hr = IFileSystem3_GetDrive(fs3, drivespec, &drive); 2232 ok(hr == ptr->res, "got 0x%08x, expected 0x%08x for drive spec %s\n", 2233 hr, ptr->res, wine_dbgstr_w(ptr->drivespec)); 2234 ok(!lstrcmpW(ptr->drivespec, drivespec), "GetDrive modified its DriveSpec argument\n"); 2235 SysFreeString(drivespec); 2236 2237 if (*ptr->driveletter) { 2238 BSTR driveletter; 2239 hr = IDrive_get_DriveLetter(drive, &driveletter); 2240 ok(hr == S_OK, "got 0x%08x for drive spec %s\n", hr, wine_dbgstr_w(ptr->drivespec)); 2241 if (SUCCEEDED(hr)) { 2242 ok(!lstrcmpW(ptr->driveletter, driveletter), "got %s, expected %s for drive spec %s\n", 2243 wine_dbgstr_w(driveletter), wine_dbgstr_w(ptr->driveletter), 2244 wine_dbgstr_w(ptr->drivespec)); 2245 SysFreeString(driveletter); 2246 } 2247 test_provideclassinfo(drive, &CLSID_Drive); 2248 IDrive_Release(drive); 2249 } else 2250 ok(drive == NULL, "got %p for drive spec %s\n", drive, wine_dbgstr_w(ptr->drivespec)); 2251 } 2252 SysFreeString(dl_fixed); 2253 } 2254 } 2255 2256 static void test_SerialNumber(void) 2257 { 2258 IDrive *drive; 2259 LONG serial; 2260 HRESULT hr; 2261 BSTR name; 2262 2263 drive = get_fixed_drive(); 2264 if (!drive) { 2265 skip("No fixed drive found, skipping test.\n"); 2266 return; 2267 } 2268 2269 hr = IDrive_get_SerialNumber(drive, NULL); 2270 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2271 2272 serial = 0xdeadbeef; 2273 hr = IDrive_get_SerialNumber(drive, &serial); 2274 ok(hr == S_OK, "got 0x%08x\n", hr); 2275 ok(serial != 0xdeadbeef, "got %x\n", serial); 2276 2277 hr = IDrive_get_FileSystem(drive, NULL); 2278 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2279 2280 name = NULL; 2281 hr = IDrive_get_FileSystem(drive, &name); 2282 ok(hr == S_OK, "got 0x%08x\n", hr); 2283 ok(name != NULL, "got %p\n", name); 2284 SysFreeString(name); 2285 2286 hr = IDrive_get_VolumeName(drive, NULL); 2287 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2288 2289 name = NULL; 2290 hr = IDrive_get_VolumeName(drive, &name); 2291 ok(hr == S_OK, "got 0x%08x\n", hr); 2292 ok(name != NULL, "got %p\n", name); 2293 SysFreeString(name); 2294 2295 IDrive_Release(drive); 2296 } 2297 2298 static const struct extension_test { 2299 WCHAR path[20]; 2300 WCHAR ext[10]; 2301 } extension_tests[] = { 2302 { {'n','o','e','x','t',0}, {0} }, 2303 { {'n','.','o','.','e','x','t',0}, {'e','x','t',0} }, 2304 { {'n','.','o','.','e','X','t',0}, {'e','X','t',0} }, 2305 { { 0 } } 2306 }; 2307 2308 static void test_GetExtensionName(void) 2309 { 2310 BSTR path, ext; 2311 HRESULT hr; 2312 int i; 2313 2314 for (i = 0; i < ARRAY_SIZE(extension_tests); i++) { 2315 2316 path = SysAllocString(extension_tests[i].path); 2317 ext = NULL; 2318 hr = IFileSystem3_GetExtensionName(fs3, path, &ext); 2319 ok(hr == S_OK, "got 0x%08x\n", hr); 2320 if (*extension_tests[i].ext) 2321 ok(!lstrcmpW(ext, extension_tests[i].ext), "%d: path %s, got %s, expected %s\n", i, 2322 wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext)); 2323 else 2324 ok(ext == NULL, "%d: path %s, got %s, expected %s\n", i, 2325 wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext)); 2326 2327 SysFreeString(path); 2328 SysFreeString(ext); 2329 } 2330 } 2331 2332 static void test_GetSpecialFolder(void) 2333 { 2334 WCHAR pathW[MAX_PATH]; 2335 IFolder *folder; 2336 HRESULT hr; 2337 DWORD ret; 2338 BSTR path; 2339 2340 hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, NULL); 2341 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2342 2343 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, NULL); 2344 ok(hr == E_POINTER, "got 0x%08x\n", hr); 2345 2346 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, &folder); 2347 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 2348 2349 hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, &folder); 2350 ok(hr == S_OK, "got 0x%08x\n", hr); 2351 hr = IFolder_get_Path(folder, &path); 2352 ok(hr == S_OK, "got 0x%08x\n", hr); 2353 GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW)); 2354 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW)); 2355 SysFreeString(path); 2356 IFolder_Release(folder); 2357 2358 hr = IFileSystem3_GetSpecialFolder(fs3, SystemFolder, &folder); 2359 ok(hr == S_OK, "got 0x%08x\n", hr); 2360 hr = IFolder_get_Path(folder, &path); 2361 ok(hr == S_OK, "got 0x%08x\n", hr); 2362 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW)); 2363 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW)); 2364 SysFreeString(path); 2365 IFolder_Release(folder); 2366 2367 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder, &folder); 2368 ok(hr == S_OK, "got 0x%08x\n", hr); 2369 hr = IFolder_get_Path(folder, &path); 2370 ok(hr == S_OK, "got 0x%08x\n", hr); 2371 ret = GetTempPathW(ARRAY_SIZE(pathW), pathW); 2372 if (ret && pathW[ret-1] == '\\') 2373 pathW[ret-1] = 0; 2374 2375 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW)); 2376 SysFreeString(path); 2377 IFolder_Release(folder); 2378 } 2379 2380 START_TEST(filesystem) 2381 { 2382 HRESULT hr; 2383 2384 CoInitialize(NULL); 2385 2386 hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 2387 &IID_IFileSystem3, (void**)&fs3); 2388 if(FAILED(hr)) { 2389 win_skip("Could not create FileSystem object: %08x\n", hr); 2390 return; 2391 } 2392 2393 test_interfaces(); 2394 test_createfolder(); 2395 test_textstream(); 2396 test_GetFileVersion(); 2397 test_GetParentFolderName(); 2398 test_GetFileName(); 2399 test_GetBaseName(); 2400 test_GetAbsolutePathName(); 2401 test_GetFile(); 2402 test_CopyFolder(); 2403 test_BuildPath(); 2404 test_GetFolder(); 2405 test_FolderCollection(); 2406 test_FileCollection(); 2407 test_DriveCollection(); 2408 test_CreateTextFile(); 2409 test_WriteLine(); 2410 test_ReadAll(); 2411 test_Read(); 2412 test_DriveExists(); 2413 test_GetDriveName(); 2414 test_GetDrive(); 2415 test_SerialNumber(); 2416 test_GetExtensionName(); 2417 test_GetSpecialFolder(); 2418 2419 IFileSystem3_Release(fs3); 2420 2421 CoUninitialize(); 2422 } 2423