| /* | |
| * | |
| * Copyright 2012 Alistair Leslie-Hughes | |
| * Copyright 2014 Dmitry Timoshkov | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #define COBJMACROS | |
| #include <stdio.h> | |
| #include <limits.h> | |
| #include "windows.h" | |
| #include "ole2.h" | |
| #include "olectl.h" | |
| #include "oleauto.h" | |
| #include "dispex.h" | |
| #include "wine/test.h" | |
| #include "initguid.h" | |
| #include "scrrun.h" | |
| static IFileSystem3 *fs3; | |
| /* w2k and 2k3 error code. */ | |
| #define E_VAR_NOT_SET 0x800a005b | |
| static inline ULONG get_refcount(IUnknown *iface) | |
| { | |
| IUnknown_AddRef(iface); | |
| return IUnknown_Release(iface); | |
| } | |
| static const WCHAR crlfW[] = {'\r','\n',0}; | |
| static const char utf16bom[] = {0xff,0xfe,0}; | |
| #define GET_REFCOUNT(iface) \ | |
| get_refcount((IUnknown*)iface) | |
| static inline void get_temp_path(const WCHAR *prefix, WCHAR *path) | |
| { | |
| WCHAR buffW[MAX_PATH]; | |
| GetTempPathW(MAX_PATH, buffW); | |
| GetTempFileNameW(buffW, prefix, 0, path); | |
| DeleteFileW(path); | |
| } | |
| static IDrive *get_fixed_drive(void) | |
| { | |
| IDriveCollection *drives; | |
| IEnumVARIANT *iter; | |
| IDrive *drive; | |
| HRESULT hr; | |
| hr = IFileSystem3_get_Drives(fs3, &drives); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&iter); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| IDriveCollection_Release(drives); | |
| while (1) { | |
| DriveTypeConst type; | |
| VARIANT var; | |
| hr = IEnumVARIANT_Next(iter, 1, &var, NULL); | |
| if (hr == S_FALSE) { | |
| drive = NULL; | |
| break; | |
| } | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDrive, (void**)&drive); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantClear(&var); | |
| hr = IDrive_get_DriveType(drive, &type); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (type == Fixed) | |
| break; | |
| IDrive_Release(drive); | |
| } | |
| IEnumVARIANT_Release(iter); | |
| return drive; | |
| } | |
| #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__) | |
| static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line) | |
| { | |
| IProvideClassInfo *classinfo; | |
| TYPEATTR *attr; | |
| ITypeInfo *ti; | |
| IUnknown *unk; | |
| HRESULT hr; | |
| hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo); | |
| ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr); | |
| hr = IProvideClassInfo_GetClassInfo(classinfo, &ti); | |
| ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr); | |
| hr = ITypeInfo_GetTypeAttr(ti, &attr); | |
| ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr); | |
| ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid), | |
| wine_dbgstr_guid(guid)); | |
| hr = IProvideClassInfo_QueryInterface(classinfo, &IID_IUnknown, (void **)&unk); | |
| ok(hr == S_OK, "Failed to QI for IUnknown.\n"); | |
| ok(unk == (IUnknown *)disp, "Got unk %p, original %p.\n", unk, disp); | |
| IUnknown_Release(unk); | |
| IProvideClassInfo_Release(classinfo); | |
| ITypeInfo_ReleaseTypeAttr(ti, attr); | |
| ITypeInfo_Release(ti); | |
| } | |
| static void test_interfaces(void) | |
| { | |
| static const WCHAR nonexistent_dirW[] = { | |
| 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', 0}; | |
| static const WCHAR pathW[] = {'p','a','t','h',0}; | |
| static const WCHAR file_kernel32W[] = { | |
| '\\', 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0}; | |
| HRESULT hr; | |
| IDispatch *disp; | |
| IDispatchEx *dispex; | |
| IObjectWithSite *site; | |
| VARIANT_BOOL b; | |
| BSTR path; | |
| WCHAR windows_path[MAX_PATH]; | |
| WCHAR file_path[MAX_PATH]; | |
| IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp); | |
| GetSystemDirectoryW(windows_path, MAX_PATH); | |
| lstrcpyW(file_path, windows_path); | |
| lstrcatW(file_path, file_kernel32W); | |
| test_provideclassinfo(disp, &CLSID_FileSystemObject); | |
| hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site); | |
| ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE); | |
| hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); | |
| ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE); | |
| b = VARIANT_TRUE; | |
| hr = IFileSystem3_FileExists(fs3, NULL, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_FALSE, "got %x\n", b); | |
| hr = IFileSystem3_FileExists(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER); | |
| path = SysAllocString(pathW); | |
| b = VARIANT_TRUE; | |
| hr = IFileSystem3_FileExists(fs3, path, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_FALSE, "got %x\n", b); | |
| SysFreeString(path); | |
| path = SysAllocString(file_path); | |
| b = VARIANT_FALSE; | |
| hr = IFileSystem3_FileExists(fs3, path, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_TRUE, "got %x\n", b); | |
| SysFreeString(path); | |
| path = SysAllocString(windows_path); | |
| b = VARIANT_TRUE; | |
| hr = IFileSystem3_FileExists(fs3, path, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_FALSE, "got %x\n", b); | |
| SysFreeString(path); | |
| /* Folder Exists */ | |
| hr = IFileSystem3_FolderExists(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER); | |
| path = SysAllocString(windows_path); | |
| hr = IFileSystem3_FolderExists(fs3, path, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_TRUE, "Folder doesn't exists\n"); | |
| SysFreeString(path); | |
| path = SysAllocString(nonexistent_dirW); | |
| hr = IFileSystem3_FolderExists(fs3, path, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_FALSE, "Folder exists\n"); | |
| SysFreeString(path); | |
| path = SysAllocString(file_path); | |
| hr = IFileSystem3_FolderExists(fs3, path, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_FALSE, "Folder exists\n"); | |
| SysFreeString(path); | |
| IDispatch_Release(disp); | |
| } | |
| static void test_createfolder(void) | |
| { | |
| WCHAR buffW[MAX_PATH]; | |
| HRESULT hr; | |
| BSTR path; | |
| IFolder *folder; | |
| BOOL ret; | |
| get_temp_path(NULL, buffW); | |
| ret = CreateDirectoryW(buffW, NULL); | |
| ok(ret, "got %d, %d\n", ret, GetLastError()); | |
| /* create existing directory */ | |
| path = SysAllocString(buffW); | |
| folder = (void*)0xdeabeef; | |
| hr = IFileSystem3_CreateFolder(fs3, path, &folder); | |
| ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr); | |
| ok(folder == NULL, "got %p\n", folder); | |
| SysFreeString(path); | |
| RemoveDirectoryW(buffW); | |
| } | |
| static void test_textstream(void) | |
| { | |
| static const WCHAR testfileW[] = {'t','e','s','t','f','i','l','e','.','t','x','t',0}; | |
| ITextStream *stream; | |
| VARIANT_BOOL b; | |
| DWORD written; | |
| HANDLE file; | |
| HRESULT hr; | |
| BSTR name, data; | |
| BOOL ret; | |
| file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
| CloseHandle(file); | |
| name = SysAllocString(testfileW); | |
| b = VARIANT_FALSE; | |
| hr = IFileSystem3_FileExists(fs3, name, &b); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(b == VARIANT_TRUE, "got %x\n", b); | |
| /* different mode combinations */ | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_Read(stream, 1, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_Read(stream, 1, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| /* try to write when open for reading */ | |
| hr = ITextStream_WriteLine(stream, name); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_Write(stream, name); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_get_AtEndOfStream(stream, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| b = 10; | |
| hr = ITextStream_get_AtEndOfStream(stream, &b); | |
| ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr); | |
| ok(b == VARIANT_TRUE, "got 0x%x\n", b); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| b = 10; | |
| hr = ITextStream_get_AtEndOfStream(stream, &b); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b); | |
| b = 10; | |
| hr = ITextStream_get_AtEndOfLine(stream, &b); | |
| todo_wine { | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b); | |
| } | |
| hr = ITextStream_Read(stream, 1, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_ReadLine(stream, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_ReadAll(stream, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| b = 10; | |
| hr = ITextStream_get_AtEndOfStream(stream, &b); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b); | |
| b = 10; | |
| hr = ITextStream_get_AtEndOfLine(stream, &b); | |
| todo_wine { | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b); | |
| } | |
| hr = ITextStream_Read(stream, 1, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_ReadLine(stream, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_ReadAll(stream, &data); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| /* now with non-empty file */ | |
| file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL); | |
| ok(ret && written == sizeof(testfileW), "got %d\n", ret); | |
| CloseHandle(file); | |
| hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| b = 10; | |
| hr = ITextStream_get_AtEndOfStream(stream, &b); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(b == VARIANT_FALSE, "got 0x%x\n", b); | |
| ITextStream_Release(stream); | |
| SysFreeString(name); | |
| DeleteFileW(testfileW); | |
| } | |
| static void test_GetFileVersion(void) | |
| { | |
| static const WCHAR k32W[] = {'\\','k','e','r','n','e','l','3','2','.','d','l','l',0}; | |
| static const WCHAR k33W[] = {'\\','k','e','r','n','e','l','3','3','.','d','l','l',0}; | |
| WCHAR pathW[MAX_PATH], filenameW[MAX_PATH]; | |
| BSTR path, version; | |
| HRESULT hr; | |
| GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR)); | |
| lstrcpyW(filenameW, pathW); | |
| lstrcatW(filenameW, k32W); | |
| path = SysAllocString(filenameW); | |
| hr = IFileSystem3_GetFileVersion(fs3, path, &version); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(*version != 0, "got %s\n", wine_dbgstr_w(version)); | |
| SysFreeString(version); | |
| SysFreeString(path); | |
| lstrcpyW(filenameW, pathW); | |
| lstrcatW(filenameW, k33W); | |
| path = SysAllocString(filenameW); | |
| version = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetFileVersion(fs3, path, &version); | |
| ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); | |
| if (hr == S_OK) | |
| { | |
| ok(*version == 0, "got %s\n", wine_dbgstr_w(version)); | |
| SysFreeString(version); | |
| } | |
| else | |
| ok(version == (void*)0xdeadbeef, "got %p\n", version); | |
| SysFreeString(path); | |
| } | |
| static void test_GetParentFolderName(void) | |
| { | |
| static const WCHAR path1[] = {'a',0}; | |
| static const WCHAR path2[] = {'a','/','a','/','a',0}; | |
| static const WCHAR path3[] = {'a','\\','a','\\','a',0}; | |
| static const WCHAR path4[] = {'a','/','a','/','/','\\','\\',0}; | |
| static const WCHAR path5[] = {'c',':','\\','\\','a',0}; | |
| static const WCHAR path6[] = {'a','c',':','\\','a',0}; | |
| static const WCHAR result2[] = {'a','/','a',0}; | |
| static const WCHAR result3[] = {'a','\\','a',0}; | |
| static const WCHAR result4[] = {'a',0}; | |
| static const WCHAR result5[] = {'c',':','\\',0}; | |
| static const WCHAR result6[] = {'a','c',':',0}; | |
| static const struct { | |
| const WCHAR *path; | |
| const WCHAR *result; | |
| } tests[] = { | |
| {NULL, NULL}, | |
| {path1, NULL}, | |
| {path2, result2}, | |
| {path3, result3}, | |
| {path4, result4}, | |
| {path5, result5}, | |
| {path6, result6} | |
| }; | |
| BSTR path, result; | |
| HRESULT hr; | |
| int i; | |
| hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr); | |
| for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) { | |
| result = (BSTR)0xdeadbeef; | |
| path = tests[i].path ? SysAllocString(tests[i].path) : NULL; | |
| hr = IFileSystem3_GetParentFolderName(fs3, path, &result); | |
| ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr); | |
| if(!tests[i].result) | |
| ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result)); | |
| else | |
| ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result)); | |
| SysFreeString(path); | |
| SysFreeString(result); | |
| } | |
| } | |
| static void test_GetFileName(void) | |
| { | |
| static const WCHAR path1[] = {'a',0}; | |
| static const WCHAR path2[] = {'a','/','a','.','b',0}; | |
| static const WCHAR path3[] = {'a','\\',0}; | |
| static const WCHAR path4[] = {'c',':',0}; | |
| static const WCHAR path5[] = {'/','\\',0}; | |
| static const WCHAR result2[] = {'a','.','b',0}; | |
| static const WCHAR result3[] = {'a',0}; | |
| static const struct { | |
| const WCHAR *path; | |
| const WCHAR *result; | |
| } tests[] = { | |
| {NULL, NULL}, | |
| {path1, path1}, | |
| {path2, result2}, | |
| {path3, result3}, | |
| {path4, NULL}, | |
| {path5, NULL} | |
| }; | |
| BSTR path, result; | |
| HRESULT hr; | |
| int i; | |
| hr = IFileSystem3_GetFileName(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr); | |
| for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) { | |
| result = (BSTR)0xdeadbeef; | |
| path = tests[i].path ? SysAllocString(tests[i].path) : NULL; | |
| hr = IFileSystem3_GetFileName(fs3, path, &result); | |
| ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr); | |
| if(!tests[i].result) | |
| ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result)); | |
| else | |
| ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result)); | |
| SysFreeString(path); | |
| SysFreeString(result); | |
| } | |
| } | |
| static void test_GetBaseName(void) | |
| { | |
| static const WCHAR path1[] = {'a',0}; | |
| static const WCHAR path2[] = {'a','/','a','.','b','.','c',0}; | |
| static const WCHAR path3[] = {'a','.','b','\\',0}; | |
| static const WCHAR path4[] = {'c',':',0}; | |
| static const WCHAR path5[] = {'/','\\',0}; | |
| static const WCHAR path6[] = {'.','a',0}; | |
| static const WCHAR result1[] = {'a',0}; | |
| static const WCHAR result2[] = {'a','.','b',0}; | |
| static const WCHAR result6[] = {0}; | |
| static const struct { | |
| const WCHAR *path; | |
| const WCHAR *result; | |
| } tests[] = { | |
| {NULL, NULL}, | |
| {path1, result1}, | |
| {path2, result2}, | |
| {path3, result1}, | |
| {path4, NULL}, | |
| {path5, NULL}, | |
| {path6, result6} | |
| }; | |
| BSTR path, result; | |
| HRESULT hr; | |
| int i; | |
| hr = IFileSystem3_GetBaseName(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr); | |
| for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) { | |
| result = (BSTR)0xdeadbeef; | |
| path = tests[i].path ? SysAllocString(tests[i].path) : NULL; | |
| hr = IFileSystem3_GetBaseName(fs3, path, &result); | |
| ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr); | |
| if(!tests[i].result) | |
| ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result)); | |
| else | |
| ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result)); | |
| SysFreeString(path); | |
| SysFreeString(result); | |
| } | |
| } | |
| static void test_GetAbsolutePathName(void) | |
| { | |
| static const WCHAR dir1[] = {'t','e','s','t','_','d','i','r','1',0}; | |
| static const WCHAR dir2[] = {'t','e','s','t','_','d','i','r','2',0}; | |
| static const WCHAR dir_match1[] = {'t','e','s','t','_','d','i','r','*',0}; | |
| static const WCHAR dir_match2[] = {'t','e','s','t','_','d','i','*',0}; | |
| static const WCHAR cur_dir[] = {'.',0}; | |
| WIN32_FIND_DATAW fdata; | |
| HANDLE find; | |
| WCHAR buf[MAX_PATH], buf2[MAX_PATH]; | |
| BSTR path, result; | |
| HRESULT hr; | |
| hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr); | |
| hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result); | |
| ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); | |
| GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL); | |
| ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf)); | |
| SysFreeString(result); | |
| find = FindFirstFileW(dir_match2, &fdata); | |
| if(find != INVALID_HANDLE_VALUE) { | |
| skip("GetAbsolutePathName tests\n"); | |
| FindClose(find); | |
| return; | |
| } | |
| path = SysAllocString(dir_match1); | |
| hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); | |
| ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); | |
| GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL); | |
| ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2)); | |
| SysFreeString(result); | |
| ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1)); | |
| hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); | |
| ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); | |
| GetFullPathNameW(dir1, MAX_PATH, buf, NULL); | |
| ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n", | |
| wine_dbgstr_w(result), wine_dbgstr_w(buf)); | |
| SysFreeString(result); | |
| ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2)); | |
| hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); | |
| ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); | |
| if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) { | |
| ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n", | |
| wine_dbgstr_w(result), wine_dbgstr_w(buf)); | |
| }else { | |
| GetFullPathNameW(dir2, MAX_PATH, buf, NULL); | |
| ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", | |
| wine_dbgstr_w(result), wine_dbgstr_w(buf)); | |
| } | |
| SysFreeString(result); | |
| SysFreeString(path); | |
| path = SysAllocString(dir_match2); | |
| hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result); | |
| ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr); | |
| GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL); | |
| ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf)); | |
| SysFreeString(result); | |
| SysFreeString(path); | |
| RemoveDirectoryW(dir1); | |
| RemoveDirectoryW(dir2); | |
| } | |
| static void test_GetFile(void) | |
| { | |
| static const WCHAR slW[] = {'\\',0}; | |
| BSTR path, str; | |
| WCHAR pathW[MAX_PATH]; | |
| FileAttribute fa; | |
| VARIANT size; | |
| DWORD gfa, new_gfa; | |
| IFile *file; | |
| HRESULT hr; | |
| HANDLE hf; | |
| BOOL ret; | |
| DATE date; | |
| get_temp_path(NULL, pathW); | |
| path = SysAllocString(pathW); | |
| hr = IFileSystem3_GetFile(fs3, path, NULL); | |
| ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr); | |
| hr = IFileSystem3_GetFile(fs3, NULL, &file); | |
| ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr); | |
| file = (IFile*)0xdeadbeef; | |
| hr = IFileSystem3_GetFile(fs3, path, &file); | |
| ok(!file, "file != NULL\n"); | |
| ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); | |
| hf = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL); | |
| if(hf == INVALID_HANDLE_VALUE) { | |
| skip("Can't create temporary file\n"); | |
| SysFreeString(path); | |
| return; | |
| } | |
| CloseHandle(hf); | |
| hr = IFileSystem3_GetFile(fs3, path, &file); | |
| ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr); | |
| hr = IFile_get_DateLastModified(file, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| date = 0.0; | |
| hr = IFile_get_DateLastModified(file, &date); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(date > 0.0, "got %f\n", date); | |
| hr = IFile_get_Path(file, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFile_get_Path(file, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(!lstrcmpiW(str, pathW), "got %s\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| #define FILE_ATTR_MASK (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \ | |
| FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | \ | |
| FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED) | |
| hr = IFile_get_Attributes(file, &fa); | |
| gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK; | |
| ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr); | |
| ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa); | |
| hr = IFile_put_Attributes(file, gfa | FILE_ATTRIBUTE_READONLY); | |
| ok(hr == S_OK, "put_Attributes failed: %08x\n", hr); | |
| new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK; | |
| ok(new_gfa == (gfa|FILE_ATTRIBUTE_READONLY), "new_gfa = %x, expected %x\n", new_gfa, gfa|FILE_ATTRIBUTE_READONLY); | |
| hr = IFile_get_Attributes(file, &fa); | |
| ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr); | |
| ok(fa == new_gfa, "fa = %x, expected %x\n", fa, new_gfa); | |
| hr = IFile_put_Attributes(file, gfa); | |
| ok(hr == S_OK, "put_Attributes failed: %08x\n", hr); | |
| new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK; | |
| ok(new_gfa == gfa, "new_gfa = %x, expected %x\n", new_gfa, gfa); | |
| hr = IFile_get_Attributes(file, &fa); | |
| ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr); | |
| ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa); | |
| hr = IFile_get_Size(file, &size); | |
| ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr); | |
| ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size)); | |
| ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size)); | |
| IFile_Release(file); | |
| hr = IFileSystem3_DeleteFile(fs3, path, FALSE); | |
| ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK), | |
| "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr); | |
| if(hr != S_OK) { | |
| hr = IFileSystem3_DeleteFile(fs3, path, TRUE); | |
| ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr); | |
| } | |
| hr = IFileSystem3_DeleteFile(fs3, path, TRUE); | |
| ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); | |
| SysFreeString(path); | |
| /* try with directory */ | |
| lstrcatW(pathW, slW); | |
| ret = CreateDirectoryW(pathW, NULL); | |
| ok(ret, "got %d, error %d\n", ret, GetLastError()); | |
| path = SysAllocString(pathW); | |
| hr = IFileSystem3_GetFile(fs3, path, &file); | |
| ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected S_OK\n", hr); | |
| SysFreeString(path); | |
| RemoveDirectoryW(pathW); | |
| } | |
| static inline BOOL create_file(const WCHAR *name) | |
| { | |
| HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); | |
| CloseHandle(f); | |
| return f != INVALID_HANDLE_VALUE; | |
| } | |
| static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret) | |
| { | |
| DWORD len = lstrlenW(folder); | |
| memmove(ret, folder, len*sizeof(WCHAR)); | |
| ret[len] = '\\'; | |
| memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR)); | |
| } | |
| static void test_CopyFolder(void) | |
| { | |
| static const WCHAR filesystem3_dir[] = {'f','i','l','e','s','y','s','t','e','m','3','_','t','e','s','t',0}; | |
| static const WCHAR s1[] = {'s','r','c','1',0}; | |
| static const WCHAR s[] = {'s','r','c','*',0}; | |
| static const WCHAR d[] = {'d','s','t',0}; | |
| static const WCHAR empty[] = {0}; | |
| WCHAR tmp[MAX_PATH]; | |
| BSTR bsrc, bdst; | |
| HRESULT hr; | |
| if(!CreateDirectoryW(filesystem3_dir, NULL)) { | |
| skip("can't create temporary directory\n"); | |
| return; | |
| } | |
| create_path(filesystem3_dir, s1, tmp); | |
| bsrc = SysAllocString(tmp); | |
| create_path(filesystem3_dir, d, tmp); | |
| bdst = SysAllocString(tmp); | |
| hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr); | |
| ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc)); | |
| hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr); | |
| hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE); | |
| ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr); | |
| ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc)); | |
| hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr); | |
| hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); | |
| create_path(tmp, s1, tmp); | |
| ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES, | |
| "%s file exists\n", wine_dbgstr_w(tmp)); | |
| create_path(filesystem3_dir, d, tmp); | |
| create_path(tmp, empty, tmp); | |
| SysFreeString(bdst); | |
| bdst = SysAllocString(tmp); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); | |
| create_path(tmp, s1, tmp); | |
| ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES, | |
| "%s directory doesn't exist\n", wine_dbgstr_w(tmp)); | |
| ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp)); | |
| create_path(filesystem3_dir, d, tmp); | |
| SysFreeString(bdst); | |
| bdst = SysAllocString(tmp); | |
| create_path(filesystem3_dir, s, tmp); | |
| SysFreeString(bsrc); | |
| bsrc = SysAllocString(tmp); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); | |
| create_path(filesystem3_dir, d, tmp); | |
| create_path(tmp, s1, tmp); | |
| ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES, | |
| "%s directory doesn't exist\n", wine_dbgstr_w(tmp)); | |
| hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE); | |
| ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr); | |
| create_path(filesystem3_dir, s1, tmp); | |
| SysFreeString(bsrc); | |
| bsrc = SysAllocString(tmp); | |
| create_path(tmp, s1, tmp); | |
| ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp)); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE); | |
| ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE); | |
| ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr); | |
| hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE); | |
| ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr); | |
| SysFreeString(bsrc); | |
| SysFreeString(bdst); | |
| bsrc = SysAllocString(filesystem3_dir); | |
| hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE); | |
| ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr); | |
| SysFreeString(bsrc); | |
| } | |
| static BSTR bstr_from_str(const char *str) | |
| { | |
| int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); | |
| BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */ | |
| MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); | |
| return ret; | |
| } | |
| struct buildpath_test | |
| { | |
| const char *path; | |
| const char *name; | |
| const char *result; | |
| }; | |
| static struct buildpath_test buildpath_data[] = | |
| { | |
| { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" }, | |
| { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" }, | |
| { "C:\\path", "name.tmp", "C:\\path\\name.tmp" }, | |
| { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" }, | |
| { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" }, | |
| { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" }, | |
| { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" }, | |
| { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" }, | |
| { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" }, | |
| { "C:", "name.tmp", "C:name.tmp" }, | |
| { "C:", "\\\\name.tmp", "C:\\\\name.tmp" }, | |
| { NULL } | |
| }; | |
| static void test_BuildPath(void) | |
| { | |
| struct buildpath_test *ptr = buildpath_data; | |
| BSTR ret, path; | |
| HRESULT hr; | |
| int i = 0; | |
| hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| ret = (BSTR)0xdeadbeef; | |
| hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(*ret == 0, "got %p\n", ret); | |
| SysFreeString(ret); | |
| ret = (BSTR)0xdeadbeef; | |
| path = bstr_from_str("path"); | |
| hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret)); | |
| SysFreeString(ret); | |
| SysFreeString(path); | |
| ret = (BSTR)0xdeadbeef; | |
| path = bstr_from_str("path"); | |
| hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret)); | |
| SysFreeString(ret); | |
| SysFreeString(path); | |
| while (ptr->path) | |
| { | |
| BSTR name, result; | |
| ret = NULL; | |
| path = bstr_from_str(ptr->path); | |
| name = bstr_from_str(ptr->name); | |
| result = bstr_from_str(ptr->result); | |
| hr = IFileSystem3_BuildPath(fs3, path, name, &ret); | |
| ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); | |
| if (hr == S_OK) | |
| { | |
| ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret), | |
| wine_dbgstr_w(result)); | |
| SysFreeString(ret); | |
| } | |
| SysFreeString(path); | |
| SysFreeString(name); | |
| SysFreeString(result); | |
| i++; | |
| ptr++; | |
| } | |
| } | |
| static void test_GetFolder(void) | |
| { | |
| static const WCHAR dummyW[] = {'d','u','m','m','y',0}; | |
| WCHAR buffW[MAX_PATH]; | |
| IFolder *folder; | |
| HRESULT hr; | |
| BSTR str; | |
| folder = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetFolder(fs3, NULL, &folder); | |
| ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); | |
| ok(folder == NULL, "got %p\n", folder); | |
| hr = IFileSystem3_GetFolder(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| /* something that doesn't exist */ | |
| str = SysAllocString(dummyW); | |
| hr = IFileSystem3_GetFolder(fs3, str, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| folder = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetFolder(fs3, str, &folder); | |
| ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr); | |
| ok(folder == NULL, "got %p\n", folder); | |
| SysFreeString(str); | |
| GetWindowsDirectoryW(buffW, MAX_PATH); | |
| str = SysAllocString(buffW); | |
| hr = IFileSystem3_GetFolder(fs3, str, &folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| test_provideclassinfo(folder, &CLSID_Folder); | |
| IFolder_Release(folder); | |
| } | |
| /* Please keep the tests for IFolderCollection and IFileCollection in sync */ | |
| static void test_FolderCollection(void) | |
| { | |
| static const WCHAR fooW[] = {'f','o','o',0}; | |
| static const WCHAR aW[] = {'\\','a',0}; | |
| static const WCHAR bW[] = {'\\','b',0}; | |
| static const WCHAR cW[] = {'\\','c',0}; | |
| IFolderCollection *folders; | |
| WCHAR buffW[MAX_PATH], pathW[MAX_PATH]; | |
| IEnumVARIANT *enumvar, *clone; | |
| LONG count, ref, ref2, i; | |
| IUnknown *unk, *unk2; | |
| IFolder *folder; | |
| ULONG fetched; | |
| VARIANT var, var2[2]; | |
| HRESULT hr; | |
| BSTR str; | |
| int found_a = 0, found_b = 0, found_c = 0; | |
| get_temp_path(fooW, buffW); | |
| CreateDirectoryW(buffW, NULL); | |
| str = SysAllocString(buffW); | |
| hr = IFileSystem3_GetFolder(fs3, str, &folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| hr = IFolder_get_SubFolders(folder, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFolder_get_Path(folder, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFolder_get_Path(folder, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(!lstrcmpiW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW)); | |
| SysFreeString(str); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, aW); | |
| CreateDirectoryW(pathW, NULL); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, bW); | |
| CreateDirectoryW(pathW, NULL); | |
| hr = IFolder_get_SubFolders(folder, &folders); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| test_provideclassinfo(folders, &CLSID_Folders); | |
| IFolder_Release(folder); | |
| count = 0; | |
| hr = IFolderCollection_get_Count(folders, &count); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(count == 2, "got %d\n", count); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, cW); | |
| CreateDirectoryW(pathW, NULL); | |
| /* every time property is requested it scans directory */ | |
| count = 0; | |
| hr = IFolderCollection_get_Count(folders, &count); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(count == 3, "got %d\n", count); | |
| hr = IFolderCollection_get__NewEnum(folders, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk); | |
| ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); | |
| /* NewEnum creates new instance each time it's called */ | |
| ref = GET_REFCOUNT(folders); | |
| unk = NULL; | |
| hr = IFolderCollection_get__NewEnum(folders, &unk); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ref2 = GET_REFCOUNT(folders); | |
| ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref); | |
| unk2 = NULL; | |
| hr = IFolderCollection_get__NewEnum(folders, &unk2); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(unk != unk2, "got %p, %p\n", unk2, unk); | |
| IUnknown_Release(unk2); | |
| /* now get IEnumVARIANT */ | |
| ref = GET_REFCOUNT(folders); | |
| hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ref2 = GET_REFCOUNT(folders); | |
| ok(ref2 == ref, "got %d, %d\n", ref2, ref); | |
| /* clone enumerator */ | |
| hr = IEnumVARIANT_Clone(enumvar, &clone); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(clone != enumvar, "got %p, %p\n", enumvar, clone); | |
| IEnumVARIANT_Release(clone); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| for (i = 0; i < 3; i++) | |
| { | |
| VariantInit(&var); | |
| fetched = 0; | |
| hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); | |
| ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); | |
| ok(fetched == 1, "%d: got %d\n", i, fetched); | |
| ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var)); | |
| hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = NULL; | |
| hr = IFolder_get_Name(folder, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (!lstrcmpW(str, aW + 1)) | |
| found_a++; | |
| else if (!lstrcmpW(str, bW + 1)) | |
| found_b++; | |
| else if (!lstrcmpW(str, cW + 1)) | |
| found_c++; | |
| else | |
| ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| IFolder_Release(folder); | |
| VariantClear(&var); | |
| } | |
| ok(found_a == 1 && found_b == 1 && found_c == 1, | |
| "each folder should be found 1 time instead of %d/%d/%d\n", | |
| found_a, found_b, found_c); | |
| VariantInit(&var); | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| ok(fetched == 0, "got %d\n", fetched); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 2); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 0); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&var2[0]); | |
| VariantInit(&var2[1]); | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(fetched == 0, "got %d\n", fetched); | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| ok(fetched == 1, "got %d\n", fetched); | |
| ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0])); | |
| VariantClear(&var2[0]); | |
| VariantClear(&var2[1]); | |
| IEnumVARIANT_Release(enumvar); | |
| IUnknown_Release(unk); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, aW); | |
| RemoveDirectoryW(pathW); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, bW); | |
| RemoveDirectoryW(pathW); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, cW); | |
| RemoveDirectoryW(pathW); | |
| RemoveDirectoryW(buffW); | |
| IFolderCollection_Release(folders); | |
| } | |
| /* Please keep the tests for IFolderCollection and IFileCollection in sync */ | |
| static void test_FileCollection(void) | |
| { | |
| static const WCHAR fooW[] = {'\\','f','o','o',0}; | |
| static const WCHAR aW[] = {'\\','a',0}; | |
| static const WCHAR bW[] = {'\\','b',0}; | |
| static const WCHAR cW[] = {'\\','c',0}; | |
| WCHAR buffW[MAX_PATH], pathW[MAX_PATH]; | |
| IFolder *folder; | |
| IFileCollection *files; | |
| IFile *file; | |
| IEnumVARIANT *enumvar, *clone; | |
| LONG count, ref, ref2, i; | |
| IUnknown *unk, *unk2; | |
| ULONG fetched; | |
| VARIANT var, var2[2]; | |
| HRESULT hr; | |
| BSTR str; | |
| HANDLE file_a, file_b, file_c; | |
| int found_a = 0, found_b = 0, found_c = 0; | |
| get_temp_path(fooW, buffW); | |
| CreateDirectoryW(buffW, NULL); | |
| str = SysAllocString(buffW); | |
| hr = IFileSystem3_GetFolder(fs3, str, &folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| hr = IFolder_get_Files(folder, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, aW); | |
| file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, | |
| FILE_FLAG_DELETE_ON_CLOSE, 0); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, bW); | |
| file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, | |
| FILE_FLAG_DELETE_ON_CLOSE, 0); | |
| hr = IFolder_get_Files(folder, &files); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| test_provideclassinfo(files, &CLSID_Files); | |
| IFolder_Release(folder); | |
| count = 0; | |
| hr = IFileCollection_get_Count(files, &count); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(count == 2, "got %d\n", count); | |
| lstrcpyW(pathW, buffW); | |
| lstrcatW(pathW, cW); | |
| file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, | |
| FILE_FLAG_DELETE_ON_CLOSE, 0); | |
| /* every time property is requested it scans directory */ | |
| count = 0; | |
| hr = IFileCollection_get_Count(files, &count); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(count == 3, "got %d\n", count); | |
| hr = IFileCollection_get__NewEnum(files, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk); | |
| ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); | |
| /* NewEnum creates new instance each time it's called */ | |
| ref = GET_REFCOUNT(files); | |
| unk = NULL; | |
| hr = IFileCollection_get__NewEnum(files, &unk); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ref2 = GET_REFCOUNT(files); | |
| ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref); | |
| unk2 = NULL; | |
| hr = IFileCollection_get__NewEnum(files, &unk2); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(unk != unk2, "got %p, %p\n", unk2, unk); | |
| IUnknown_Release(unk2); | |
| /* now get IEnumVARIANT */ | |
| ref = GET_REFCOUNT(files); | |
| hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ref2 = GET_REFCOUNT(files); | |
| ok(ref2 == ref, "got %d, %d\n", ref2, ref); | |
| /* clone enumerator */ | |
| hr = IEnumVARIANT_Clone(enumvar, &clone); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(clone != enumvar, "got %p, %p\n", enumvar, clone); | |
| IEnumVARIANT_Release(clone); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| for (i = 0; i < 3; i++) | |
| { | |
| VariantInit(&var); | |
| fetched = 0; | |
| hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); | |
| ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); | |
| ok(fetched == 1, "%d: got %d\n", i, fetched); | |
| ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var)); | |
| hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| test_provideclassinfo(file, &CLSID_File); | |
| str = NULL; | |
| hr = IFile_get_Name(file, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (!lstrcmpW(str, aW + 1)) | |
| found_a++; | |
| else if (!lstrcmpW(str, bW + 1)) | |
| found_b++; | |
| else if (!lstrcmpW(str, cW + 1)) | |
| found_c++; | |
| else | |
| ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| IFile_Release(file); | |
| VariantClear(&var); | |
| } | |
| ok(found_a == 1 && found_b == 1 && found_c == 1, | |
| "each file should be found 1 time instead of %d/%d/%d\n", | |
| found_a, found_b, found_c); | |
| VariantInit(&var); | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| ok(fetched == 0, "got %d\n", fetched); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 2); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 0); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&var2[0]); | |
| VariantInit(&var2[1]); | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(fetched == 0, "got %d\n", fetched); | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| ok(fetched == 1, "got %d\n", fetched); | |
| ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0])); | |
| VariantClear(&var2[0]); | |
| VariantClear(&var2[1]); | |
| IEnumVARIANT_Release(enumvar); | |
| IUnknown_Release(unk); | |
| CloseHandle(file_a); | |
| CloseHandle(file_b); | |
| CloseHandle(file_c); | |
| RemoveDirectoryW(buffW); | |
| IFileCollection_Release(files); | |
| } | |
| static void test_DriveCollection(void) | |
| { | |
| IDriveCollection *drives; | |
| IEnumVARIANT *enumvar; | |
| ULONG fetched; | |
| VARIANT var; | |
| HRESULT hr; | |
| LONG count; | |
| hr = IFileSystem3_get_Drives(fs3, &drives); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| test_provideclassinfo(drives, &CLSID_Drives); | |
| hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDriveCollection_get_Count(drives, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| count = 0; | |
| hr = IDriveCollection_get_Count(drives, &count); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(count > 0, "got %d\n", count); | |
| V_VT(&var) = VT_EMPTY; | |
| fetched = -1; | |
| hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(fetched == 0, "got %d\n", fetched); | |
| hr = IEnumVARIANT_Skip(enumvar, 0); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, count); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 1); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| /* reset and iterate again */ | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) { | |
| IDrive *drive = (IDrive*)V_DISPATCH(&var); | |
| DriveTypeConst type; | |
| BSTR str; | |
| hr = IDrive_get_DriveType(drive, &type); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDrive_get_DriveLetter(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IDrive_get_DriveLetter(drive, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| hr = IDrive_get_IsReady(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IDrive_get_TotalSize(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IDrive_get_AvailableSpace(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IDrive_get_FreeSpace(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| if (type == Fixed) { | |
| VARIANT_BOOL ready = VARIANT_FALSE; | |
| VARIANT size; | |
| hr = IDrive_get_IsReady(drive, &ready); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(ready == VARIANT_TRUE, "got %x\n", ready); | |
| if (ready != VARIANT_TRUE) { | |
| hr = IDrive_get_DriveLetter(drive, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| skip("Drive %s is not ready, skipping some tests\n", wine_dbgstr_w(str)); | |
| VariantClear(&var); | |
| SysFreeString(str); | |
| continue; | |
| } | |
| V_VT(&size) = VT_EMPTY; | |
| hr = IDrive_get_TotalSize(drive, &size); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size)); | |
| if (V_VT(&size) == VT_R8) | |
| ok(V_R8(&size) > 0, "got %f\n", V_R8(&size)); | |
| else | |
| ok(V_I4(&size) > 0, "got %d\n", V_I4(&size)); | |
| V_VT(&size) = VT_EMPTY; | |
| hr = IDrive_get_AvailableSpace(drive, &size); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size)); | |
| if (V_VT(&size) == VT_R8) | |
| ok(V_R8(&size) > (double)INT_MAX, "got %f\n", V_R8(&size)); | |
| else | |
| ok(V_I4(&size) > 0, "got %d\n", V_I4(&size)); | |
| V_VT(&size) = VT_EMPTY; | |
| hr = IDrive_get_FreeSpace(drive, &size); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size)); | |
| if (V_VT(&size) == VT_R8) | |
| ok(V_R8(&size) > 0, "got %f\n", V_R8(&size)); | |
| else | |
| ok(V_I4(&size) > 0, "got %d\n", V_I4(&size)); | |
| } | |
| VariantClear(&var); | |
| } | |
| IEnumVARIANT_Release(enumvar); | |
| IDriveCollection_Release(drives); | |
| } | |
| static void test_CreateTextFile(void) | |
| { | |
| static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; | |
| static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; | |
| WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10]; | |
| ITextStream *stream; | |
| BSTR nameW, str; | |
| HANDLE file; | |
| HRESULT hr; | |
| BOOL ret; | |
| GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW); | |
| lstrcatW(pathW, scrrunW); | |
| lstrcpyW(dirW, pathW); | |
| lstrcatW(pathW, testfileW); | |
| /* dir doesn't exist */ | |
| nameW = SysAllocString(pathW); | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); | |
| ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr); | |
| ret = CreateDirectoryW(dirW, NULL); | |
| ok(ret, "got %d, %d\n", ret, GetLastError()); | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| test_provideclassinfo(stream, &CLSID_TextStream); | |
| hr = ITextStream_Read(stream, 1, &str); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| hr = ITextStream_Close(stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_Read(stream, 1, &str); | |
| ok(hr == CTL_E_BADFILEMODE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr); | |
| hr = ITextStream_Close(stream); | |
| ok(hr == S_FALSE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| /* check it's created */ | |
| file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| ok(file != INVALID_HANDLE_VALUE, "got %p\n", file); | |
| CloseHandle(file); | |
| /* try to create again with no-overwrite mode */ | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); | |
| ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr); | |
| /* now overwrite */ | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| /* overwrite in Unicode mode, check for BOM */ | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode | |
| treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */ | |
| buffW[0] = 0; | |
| MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR)); | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW)); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| DeleteFileW(nameW); | |
| RemoveDirectoryW(dirW); | |
| SysFreeString(nameW); | |
| } | |
| static void test_WriteLine(void) | |
| { | |
| static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; | |
| static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; | |
| WCHAR pathW[MAX_PATH], dirW[MAX_PATH]; | |
| WCHAR buffW[MAX_PATH], buff2W[MAX_PATH]; | |
| char buffA[MAX_PATH]; | |
| ITextStream *stream; | |
| DWORD r, len; | |
| HANDLE file; | |
| BSTR nameW; | |
| HRESULT hr; | |
| BOOL ret; | |
| GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW); | |
| lstrcatW(pathW, scrrunW); | |
| lstrcpyW(dirW, pathW); | |
| lstrcatW(pathW, testfileW); | |
| ret = CreateDirectoryW(dirW, NULL); | |
| ok(ret, "got %d, %d\n", ret, GetLastError()); | |
| /* create as ASCII file first */ | |
| nameW = SysAllocString(pathW); | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_WriteLine(stream, nameW); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| /* check contents */ | |
| file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| ok(file != INVALID_HANDLE_VALUE, "got %p\n", file); | |
| r = 0; | |
| ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL); | |
| ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError()); | |
| len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, sizeof(buffW)/sizeof(WCHAR)); | |
| buffW[len] = 0; | |
| lstrcpyW(buff2W, nameW); | |
| lstrcatW(buff2W, crlfW); | |
| ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W)); | |
| CloseHandle(file); | |
| DeleteFileW(nameW); | |
| /* same for unicode file */ | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_WriteLine(stream, nameW); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ITextStream_Release(stream); | |
| /* check contents */ | |
| file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| ok(file != INVALID_HANDLE_VALUE, "got %p\n", file); | |
| r = 0; | |
| ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL); | |
| ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError()); | |
| buffW[r/sizeof(WCHAR)] = 0; | |
| buff2W[0] = 0xfeff; | |
| buff2W[1] = 0; | |
| lstrcatW(buff2W, nameW); | |
| lstrcatW(buff2W, crlfW); | |
| ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W)); | |
| CloseHandle(file); | |
| DeleteFileW(nameW); | |
| RemoveDirectoryW(dirW); | |
| SysFreeString(nameW); | |
| } | |
| static void test_ReadAll(void) | |
| { | |
| static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; | |
| static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; | |
| static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0}; | |
| static const WCHAR aW[] = {'A',0}; | |
| WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500]; | |
| ITextStream *stream; | |
| BSTR nameW; | |
| HRESULT hr; | |
| BOOL ret; | |
| BSTR str; | |
| GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW); | |
| lstrcatW(pathW, scrrunW); | |
| lstrcpyW(dirW, pathW); | |
| lstrcatW(pathW, testfileW); | |
| ret = CreateDirectoryW(dirW, NULL); | |
| ok(ret, "got %d, %d\n", ret, GetLastError()); | |
| /* Unicode file -> read with ascii stream */ | |
| nameW = SysAllocString(pathW); | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_WriteLine(stream, nameW); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = SysAllocString(secondlineW); | |
| hr = ITextStream_WriteLine(stream, str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| hr = ITextStream_ReadAll(stream, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_ReadAll(stream, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */ | |
| str = NULL; | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| buffW[0] = 0; | |
| MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR)); | |
| ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str)); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| /* Unicode file -> read with unicode stream */ | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| lstrcpyW(buffW, nameW); | |
| lstrcatW(buffW, crlfW); | |
| lstrcatW(buffW, secondlineW); | |
| lstrcatW(buffW, crlfW); | |
| str = NULL; | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| /* ReadAll one more time */ | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); | |
| ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); | |
| /* ReadLine fails the same way */ | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_ReadLine(stream, &str); | |
| ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); | |
| ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); | |
| ITextStream_Release(stream); | |
| /* Open again and skip first line before ReadAll */ | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = NULL; | |
| hr = ITextStream_ReadLine(stream, &str); | |
| todo_wine { | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(str != NULL, "got %p\n", str); | |
| } | |
| SysFreeString(str); | |
| lstrcpyW(buffW, secondlineW); | |
| lstrcatW(buffW, crlfW); | |
| str = NULL; | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| todo_wine | |
| ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| /* ASCII file, read with Unicode stream */ | |
| /* 1. one byte content, not enough for Unicode read */ | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = SysAllocString(aW); | |
| hr = ITextStream_Write(stream, str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_ReadAll(stream, &str); | |
| ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); | |
| ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str); | |
| ITextStream_Release(stream); | |
| DeleteFileW(nameW); | |
| RemoveDirectoryW(dirW); | |
| SysFreeString(nameW); | |
| } | |
| static void test_Read(void) | |
| { | |
| static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; | |
| static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; | |
| static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0}; | |
| static const WCHAR aW[] = {'A',0}; | |
| WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500]; | |
| ITextStream *stream; | |
| BSTR nameW; | |
| HRESULT hr; | |
| BOOL ret; | |
| BSTR str; | |
| GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW); | |
| lstrcatW(pathW, scrrunW); | |
| lstrcpyW(dirW, pathW); | |
| lstrcatW(pathW, testfileW); | |
| ret = CreateDirectoryW(dirW, NULL); | |
| ok(ret, "got %d, %d\n", ret, GetLastError()); | |
| /* Unicode file -> read with ascii stream */ | |
| nameW = SysAllocString(pathW); | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_WriteLine(stream, nameW); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = SysAllocString(secondlineW); | |
| hr = ITextStream_WriteLine(stream, str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| hr = ITextStream_Read(stream, 0, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = ITextStream_Read(stream, 1, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = ITextStream_Read(stream, -1, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_Read(stream, 1, &str); | |
| ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr); | |
| ok(str == NULL, "got %p\n", str); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = ITextStream_Read(stream, 1, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_Read(stream, -1, &str); | |
| ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); | |
| ok(str == NULL, "got %p\n", str); | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_Read(stream, 0, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(str == NULL, "got %p\n", str); | |
| /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */ | |
| str = NULL; | |
| hr = ITextStream_Read(stream, 2, &str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| buffW[0] = 0; | |
| MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR)); | |
| ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW)); | |
| ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str)); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| /* Unicode file -> read with unicode stream */ | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| lstrcpyW(buffW, nameW); | |
| lstrcatW(buffW, crlfW); | |
| lstrcatW(buffW, secondlineW); | |
| lstrcatW(buffW, crlfW); | |
| str = NULL; | |
| hr = ITextStream_Read(stream, 500, &str); | |
| ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| /* ReadAll one more time */ | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_Read(stream, 10, &str); | |
| ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); | |
| ok(str == NULL, "got %p\n", str); | |
| /* ReadLine fails the same way */ | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_ReadLine(stream, &str); | |
| ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); | |
| ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str); | |
| ITextStream_Release(stream); | |
| /* Open again and skip first line before ReadAll */ | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = NULL; | |
| hr = ITextStream_ReadLine(stream, &str); | |
| todo_wine { | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(str != NULL, "got %p\n", str); | |
| } | |
| SysFreeString(str); | |
| lstrcpyW(buffW, secondlineW); | |
| lstrcatW(buffW, crlfW); | |
| str = NULL; | |
| hr = ITextStream_Read(stream, 100, &str); | |
| ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| todo_wine | |
| ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str)); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| /* ASCII file, read with Unicode stream */ | |
| /* 1. one byte content, not enough for Unicode read */ | |
| hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = SysAllocString(aW); | |
| hr = ITextStream_Write(stream, str); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| SysFreeString(str); | |
| ITextStream_Release(stream); | |
| hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = (void*)0xdeadbeef; | |
| hr = ITextStream_Read(stream, 500, &str); | |
| ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr); | |
| ok(str == NULL, "got %p\n", str); | |
| ITextStream_Release(stream); | |
| DeleteFileW(nameW); | |
| RemoveDirectoryW(dirW); | |
| SysFreeString(nameW); | |
| } | |
| struct driveexists_test { | |
| const WCHAR drivespec[10]; | |
| const INT drivetype; | |
| const VARIANT_BOOL expected_ret; | |
| }; | |
| /* If 'drivetype' != -1, the first character of 'drivespec' will be replaced | |
| * with the drive letter of a drive of this type. If such a drive does not exist, | |
| * the test will be skipped. */ | |
| static const struct driveexists_test driveexiststestdata[] = { | |
| { {'N',':','\\',0}, DRIVE_NO_ROOT_DIR, VARIANT_FALSE }, | |
| { {'R',':','\\',0}, DRIVE_REMOVABLE, VARIANT_TRUE }, | |
| { {'F',':','\\',0}, DRIVE_FIXED, VARIANT_TRUE }, | |
| { {'F',':',0}, DRIVE_FIXED, VARIANT_TRUE }, | |
| { {'F','?',0}, DRIVE_FIXED, VARIANT_FALSE }, | |
| { {'F',0}, DRIVE_FIXED, VARIANT_TRUE }, | |
| { {'?',0}, -1, VARIANT_FALSE }, | |
| { { 0 } } | |
| }; | |
| static void test_DriveExists(void) | |
| { | |
| const struct driveexists_test *ptr = driveexiststestdata; | |
| HRESULT hr; | |
| VARIANT_BOOL ret; | |
| BSTR drivespec; | |
| WCHAR root[] = {'?',':','\\',0}; | |
| hr = IFileSystem3_DriveExists(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| ret = VARIANT_TRUE; | |
| hr = IFileSystem3_DriveExists(fs3, NULL, &ret); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(ret == VARIANT_FALSE, "got %x\n", ret); | |
| drivespec = SysAllocString(root); | |
| hr = IFileSystem3_DriveExists(fs3, drivespec, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| SysFreeString(drivespec); | |
| for (; *ptr->drivespec; ptr++) { | |
| drivespec = SysAllocString(ptr->drivespec); | |
| if (ptr->drivetype != -1) { | |
| for (root[0] = 'A'; root[0] <= 'Z'; root[0]++) | |
| if (GetDriveTypeW(root) == ptr->drivetype) | |
| break; | |
| if (root[0] > 'Z') { | |
| skip("No drive with type 0x%x found, skipping test %s.\n", | |
| ptr->drivetype, wine_dbgstr_w(ptr->drivespec)); | |
| SysFreeString(drivespec); | |
| continue; | |
| } | |
| /* Test both upper and lower case drive letters. */ | |
| drivespec[0] = root[0]; | |
| ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE; | |
| hr = IFileSystem3_DriveExists(fs3, drivespec, &ret); | |
| ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n", | |
| hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); | |
| ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n", | |
| ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); | |
| drivespec[0] = tolower(root[0]); | |
| } | |
| ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE; | |
| hr = IFileSystem3_DriveExists(fs3, drivespec, &ret); | |
| ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n", | |
| hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); | |
| ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n", | |
| ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec)); | |
| SysFreeString(drivespec); | |
| } | |
| } | |
| struct getdrivename_test { | |
| const WCHAR path[10]; | |
| const WCHAR drive[5]; | |
| }; | |
| static const struct getdrivename_test getdrivenametestdata[] = { | |
| { {'C',':','\\','1','.','t','s','t',0}, {'C',':',0} }, | |
| { {'O',':','\\','1','.','t','s','t',0}, {'O',':',0} }, | |
| { {'O',':',0}, {'O',':',0} }, | |
| { {'o',':',0}, {'o',':',0} }, | |
| { {'O','O',':',0} }, | |
| { {':',0} }, | |
| { {'O',0} }, | |
| { { 0 } } | |
| }; | |
| static void test_GetDriveName(void) | |
| { | |
| const struct getdrivename_test *ptr = getdrivenametestdata; | |
| HRESULT hr; | |
| BSTR name; | |
| hr = IFileSystem3_GetDriveName(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| name = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetDriveName(fs3, NULL, &name); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(name == NULL, "got %p\n", name); | |
| while (*ptr->path) { | |
| BSTR path = SysAllocString(ptr->path); | |
| name = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetDriveName(fs3, path, &name); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (name) | |
| ok(!lstrcmpW(ptr->drive, name), "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive)); | |
| else | |
| ok(!*ptr->drive, "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive)); | |
| SysFreeString(path); | |
| SysFreeString(name); | |
| ptr++; | |
| } | |
| } | |
| struct getdrive_test { | |
| const WCHAR drivespec[12]; | |
| HRESULT res; | |
| const WCHAR driveletter[2]; | |
| }; | |
| static void test_GetDrive(void) | |
| { | |
| HRESULT hr; | |
| IDrive *drive_fixed, *drive; | |
| BSTR dl_fixed, drivespec; | |
| WCHAR root[] = {'?',':','\\',0}; | |
| drive = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetDrive(fs3, NULL, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| ok(drive == (void*)0xdeadbeef, "got %p\n", drive); | |
| for (root[0] = 'A'; root[0] <= 'Z'; root[0]++) | |
| if (GetDriveTypeW(root) == DRIVE_NO_ROOT_DIR) | |
| break; | |
| if (root[0] > 'Z') | |
| skip("All drive letters are occupied, skipping test for nonexisting drive.\n"); | |
| else { | |
| drivespec = SysAllocString(root); | |
| drive = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetDrive(fs3, drivespec, &drive); | |
| ok(hr == CTL_E_DEVICEUNAVAILABLE, "got 0x%08x\n", hr); | |
| ok(drive == NULL, "got %p\n", drive); | |
| SysFreeString(drivespec); | |
| } | |
| drive_fixed = get_fixed_drive(); | |
| if (!drive_fixed) { | |
| skip("No fixed drive found, skipping test.\n"); | |
| return; | |
| } | |
| hr = IDrive_get_DriveLetter(drive_fixed, &dl_fixed); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (FAILED(hr)) | |
| skip("Could not retrieve drive letter of fixed drive, skipping test.\n"); | |
| else { | |
| WCHAR dl_upper = toupper(dl_fixed[0]); | |
| WCHAR dl_lower = tolower(dl_fixed[0]); | |
| struct getdrive_test testdata[] = { | |
| { {dl_upper,0}, S_OK, {dl_upper,0} }, | |
| { {dl_upper,':',0}, S_OK, {dl_upper,0} }, | |
| { {dl_upper,':','\\',0}, S_OK, {dl_upper,0} }, | |
| { {dl_lower,':','\\',0}, S_OK, {dl_upper,0} }, | |
| { {dl_upper,'\\',0}, E_INVALIDARG, { 0 } }, | |
| { {dl_lower,'\\',0}, E_INVALIDARG, { 0 } }, | |
| { {'$',':','\\',0}, E_INVALIDARG, { 0 } }, | |
| { {'\\','h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } }, | |
| { {'h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } }, | |
| { { 0 } }, | |
| }; | |
| struct getdrive_test *ptr = &testdata[0]; | |
| for (; *ptr->drivespec; ptr++) { | |
| drivespec = SysAllocString(ptr->drivespec); | |
| drive = (void*)0xdeadbeef; | |
| hr = IFileSystem3_GetDrive(fs3, drivespec, &drive); | |
| ok(hr == ptr->res, "got 0x%08x, expected 0x%08x for drive spec %s\n", | |
| hr, ptr->res, wine_dbgstr_w(ptr->drivespec)); | |
| ok(!lstrcmpW(ptr->drivespec, drivespec), "GetDrive modified its DriveSpec argument\n"); | |
| SysFreeString(drivespec); | |
| if (*ptr->driveletter) { | |
| BSTR driveletter; | |
| hr = IDrive_get_DriveLetter(drive, &driveletter); | |
| ok(hr == S_OK, "got 0x%08x for drive spec %s\n", hr, wine_dbgstr_w(ptr->drivespec)); | |
| if (SUCCEEDED(hr)) { | |
| ok(!lstrcmpW(ptr->driveletter, driveletter), "got %s, expected %s for drive spec %s\n", | |
| wine_dbgstr_w(driveletter), wine_dbgstr_w(ptr->driveletter), | |
| wine_dbgstr_w(ptr->drivespec)); | |
| SysFreeString(driveletter); | |
| } | |
| test_provideclassinfo(drive, &CLSID_Drive); | |
| IDrive_Release(drive); | |
| } else | |
| ok(drive == NULL, "got %p for drive spec %s\n", drive, wine_dbgstr_w(ptr->drivespec)); | |
| } | |
| SysFreeString(dl_fixed); | |
| } | |
| } | |
| static void test_SerialNumber(void) | |
| { | |
| IDrive *drive; | |
| LONG serial; | |
| HRESULT hr; | |
| BSTR name; | |
| drive = get_fixed_drive(); | |
| if (!drive) { | |
| skip("No fixed drive found, skipping test.\n"); | |
| return; | |
| } | |
| hr = IDrive_get_SerialNumber(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| serial = 0xdeadbeef; | |
| hr = IDrive_get_SerialNumber(drive, &serial); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(serial != 0xdeadbeef, "got %x\n", serial); | |
| hr = IDrive_get_FileSystem(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| name = NULL; | |
| hr = IDrive_get_FileSystem(drive, &name); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(name != NULL, "got %p\n", name); | |
| SysFreeString(name); | |
| hr = IDrive_get_VolumeName(drive, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| name = NULL; | |
| hr = IDrive_get_VolumeName(drive, &name); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(name != NULL, "got %p\n", name); | |
| SysFreeString(name); | |
| IDrive_Release(drive); | |
| } | |
| static const struct extension_test { | |
| WCHAR path[20]; | |
| WCHAR ext[10]; | |
| } extension_tests[] = { | |
| { {'n','o','e','x','t',0}, {0} }, | |
| { {'n','.','o','.','e','x','t',0}, {'e','x','t',0} }, | |
| { {'n','.','o','.','e','X','t',0}, {'e','X','t',0} }, | |
| { { 0 } } | |
| }; | |
| static void test_GetExtensionName(void) | |
| { | |
| BSTR path, ext; | |
| HRESULT hr; | |
| int i; | |
| for (i = 0; i < sizeof(extension_tests)/sizeof(extension_tests[0]); i++) { | |
| path = SysAllocString(extension_tests[i].path); | |
| ext = NULL; | |
| hr = IFileSystem3_GetExtensionName(fs3, path, &ext); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (*extension_tests[i].ext) | |
| ok(!lstrcmpW(ext, extension_tests[i].ext), "%d: path %s, got %s, expected %s\n", i, | |
| wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext)); | |
| else | |
| ok(ext == NULL, "%d: path %s, got %s, expected %s\n", i, | |
| wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext)); | |
| SysFreeString(path); | |
| SysFreeString(ext); | |
| } | |
| } | |
| static void test_GetSpecialFolder(void) | |
| { | |
| WCHAR pathW[MAX_PATH]; | |
| IFolder *folder; | |
| HRESULT hr; | |
| DWORD ret; | |
| BSTR path; | |
| hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, NULL); | |
| ok(hr == E_POINTER, "got 0x%08x\n", hr); | |
| hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, &folder); | |
| ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); | |
| hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, &folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IFolder_get_Path(folder, &path); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR)); | |
| ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW)); | |
| SysFreeString(path); | |
| IFolder_Release(folder); | |
| hr = IFileSystem3_GetSpecialFolder(fs3, SystemFolder, &folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IFolder_get_Path(folder, &path); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR)); | |
| ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW)); | |
| SysFreeString(path); | |
| IFolder_Release(folder); | |
| hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder, &folder); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IFolder_get_Path(folder, &path); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ret = GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW); | |
| if (ret && pathW[ret-1] == '\\') | |
| pathW[ret-1] = 0; | |
| ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW)); | |
| SysFreeString(path); | |
| IFolder_Release(folder); | |
| } | |
| START_TEST(filesystem) | |
| { | |
| HRESULT hr; | |
| CoInitialize(NULL); | |
| hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IFileSystem3, (void**)&fs3); | |
| if(FAILED(hr)) { | |
| win_skip("Could not create FileSystem object: %08x\n", hr); | |
| return; | |
| } | |
| test_interfaces(); | |
| test_createfolder(); | |
| test_textstream(); | |
| test_GetFileVersion(); | |
| test_GetParentFolderName(); | |
| test_GetFileName(); | |
| test_GetBaseName(); | |
| test_GetAbsolutePathName(); | |
| test_GetFile(); | |
| test_CopyFolder(); | |
| test_BuildPath(); | |
| test_GetFolder(); | |
| test_FolderCollection(); | |
| test_FileCollection(); | |
| test_DriveCollection(); | |
| test_CreateTextFile(); | |
| test_WriteLine(); | |
| test_ReadAll(); | |
| test_Read(); | |
| test_DriveExists(); | |
| test_GetDriveName(); | |
| test_GetDrive(); | |
| test_SerialNumber(); | |
| test_GetExtensionName(); | |
| test_GetSpecialFolder(); | |
| IFileSystem3_Release(fs3); | |
| CoUninitialize(); | |
| } |