scrrun: Added IProvideClassInfo support for filesystem objects.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-12-07 13:33:59 +03:00 committed by Alexandre Julliard
parent ba2e6fb2be
commit eda5d61c54
2 changed files with 122 additions and 24 deletions

View File

@ -39,19 +39,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(scrrun);
static const WCHAR bsW[] = {'\\',0};
static const WCHAR utf16bom = 0xfeff;
struct filesystem {
struct provideclassinfo classinfo;
IFileSystem3 IFileSystem3_iface;
};
struct foldercollection {
struct provideclassinfo classinfo;
IFolderCollection IFolderCollection_iface;
LONG ref;
BSTR path;
};
struct filecollection {
struct provideclassinfo classinfo;
IFileCollection IFileCollection_iface;
LONG ref;
BSTR path;
};
struct drivecollection {
struct provideclassinfo classinfo;
IDriveCollection IDriveCollection_iface;
LONG ref;
DWORD drives;
@ -87,18 +95,21 @@ struct enumvariant {
};
struct drive {
struct provideclassinfo classinfo;
IDrive IDrive_iface;
LONG ref;
BSTR root;
};
struct folder {
struct provideclassinfo classinfo;
IFolder IFolder_iface;
LONG ref;
BSTR path;
};
struct file {
struct provideclassinfo classinfo;
IFile IFile_iface;
LONG ref;
@ -106,6 +117,7 @@ struct file {
};
struct textstream {
struct provideclassinfo classinfo;
ITextStream ITextStream_iface;
LONG ref;
@ -121,6 +133,11 @@ enum iotype {
IOWrite
};
static inline struct filesystem *impl_from_IFileSystem3(IFileSystem3 *iface)
{
return CONTAINING_RECORD(iface, struct filesystem, IFileSystem3_iface);
}
static inline struct drive *impl_from_IDrive(IDrive *iface)
{
return CONTAINING_RECORD(iface, struct drive, IDrive_iface);
@ -226,13 +243,17 @@ static HRESULT WINAPI textstream_QueryInterface(ITextStream *iface, REFIID riid,
IsEqualIID(riid, &IID_IDispatch) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
ITextStream_AddRef(iface);
return S_OK;
*obj = &This->ITextStream_iface;
}
else if (IsEqualIID(riid, &IID_IProvideClassInfo))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
*obj = NULL;
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
static ULONG WINAPI textstream_AddRef(ITextStream *iface)
@ -721,6 +742,7 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
}
}
init_classinfo(&CLSID_TextStream, (IUnknown *)&stream->ITextStream_iface, &stream->classinfo);
*ret = &stream->ITextStream_iface;
return S_OK;
}
@ -737,12 +759,16 @@ static HRESULT WINAPI drive_QueryInterface(IDrive *iface, REFIID riid, void **ob
IsEqualIID( riid, &IID_IDispatch ) ||
IsEqualIID( riid, &IID_IUnknown))
{
*obj = iface;
IDrive_AddRef(iface);
*obj = &This->IDrive_iface;
}
else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
@ -1080,6 +1106,7 @@ static HRESULT create_drive(WCHAR letter, IDrive **drive)
This->root[2] = '\\';
This->root[3] = 0;
init_classinfo(&CLSID_Drive, (IUnknown *)&This->IDrive_iface, &This->classinfo);
*drive = &This->IDrive_iface;
return S_OK;
}
@ -1573,12 +1600,16 @@ static HRESULT WINAPI foldercoll_QueryInterface(IFolderCollection *iface, REFIID
IsEqualIID( riid, &IID_IDispatch ) ||
IsEqualIID( riid, &IID_IUnknown ))
{
*obj = iface;
IFolderCollection_AddRef(iface);
*obj = &This->IFolderCollection_iface;
}
else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
@ -1753,6 +1784,7 @@ static HRESULT create_foldercoll(BSTR path, IFolderCollection **folders)
return E_OUTOFMEMORY;
}
init_classinfo(&CLSID_Folders, (IUnknown *)&This->IFolderCollection_iface, &This->classinfo);
*folders = &This->IFolderCollection_iface;
return S_OK;
@ -1770,12 +1802,16 @@ static HRESULT WINAPI filecoll_QueryInterface(IFileCollection *iface, REFIID rii
IsEqualIID( riid, &IID_IDispatch ) ||
IsEqualIID( riid, &IID_IUnknown ))
{
*obj = iface;
IFileCollection_AddRef(iface);
*obj = &This->IFileCollection_iface;
}
else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
@ -1942,6 +1978,7 @@ static HRESULT create_filecoll(BSTR path, IFileCollection **files)
return E_OUTOFMEMORY;
}
init_classinfo(&CLSID_Files, (IUnknown *)&This->IFileCollection_iface, &This->classinfo);
*files = &This->IFileCollection_iface;
return S_OK;
}
@ -1958,12 +1995,16 @@ static HRESULT WINAPI drivecoll_QueryInterface(IDriveCollection *iface, REFIID r
IsEqualIID( riid, &IID_IDispatch ) ||
IsEqualIID( riid, &IID_IUnknown ))
{
*obj = iface;
IDriveCollection_AddRef(iface);
*obj = &This->IDriveCollection_iface;
}
else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
@ -2107,6 +2148,7 @@ static HRESULT create_drivecoll(IDriveCollection **drives)
for (This->count = 0; mask; This->count++)
mask &= mask - 1;
init_classinfo(&CLSID_Drives, (IUnknown *)&This->IDriveCollection_iface, &This->classinfo);
*drives = &This->IDriveCollection_iface;
return S_OK;
}
@ -2123,12 +2165,16 @@ static HRESULT WINAPI folder_QueryInterface(IFolder *iface, REFIID riid, void **
IsEqualIID( riid, &IID_IDispatch ) ||
IsEqualIID( riid, &IID_IUnknown))
{
*obj = iface;
IFolder_AddRef(iface);
*obj = &This->IFolder_iface;
}
else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
@ -2447,6 +2493,7 @@ HRESULT create_folder(const WCHAR *path, IFolder **folder)
return E_OUTOFMEMORY;
}
init_classinfo(&CLSID_Folder, (IUnknown *)&This->IFolder_iface, &This->classinfo);
*folder = &This->IFolder_iface;
return S_OK;
@ -2458,17 +2505,23 @@ static HRESULT WINAPI file_QueryInterface(IFile *iface, REFIID riid, void **obj)
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
*obj = NULL;
if (IsEqualIID(riid, &IID_IFile) ||
IsEqualIID(riid, &IID_IDispatch) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IFile_AddRef(iface);
return S_OK;
*obj = &This->IFile_iface;
}
else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
{
*obj = &This->classinfo.IProvideClassInfo_iface;
}
else
return E_NOINTERFACE;
*obj = NULL;
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*obj);
return S_OK;
}
static ULONG WINAPI file_AddRef(IFile *iface)
@ -2813,12 +2866,15 @@ static HRESULT create_file(BSTR path, IFile **file)
return create_error(GetLastError());
}
init_classinfo(&CLSID_File, (IUnknown *)&f->IFile_iface, &f->classinfo);
*file = &f->IFile_iface;
return S_OK;
}
static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, void **ppvObject)
{
struct filesystem *This = impl_from_IFileSystem3(iface);
TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
if ( IsEqualGUID( riid, &IID_IFileSystem3 ) ||
@ -2826,7 +2882,11 @@ static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, v
IsEqualGUID( riid, &IID_IDispatch ) ||
IsEqualGUID( riid, &IID_IUnknown ) )
{
*ppvObject = iface;
*ppvObject = &This->IFileSystem3_iface;
}
else if (IsEqualGUID( riid, &IID_IProvideClassInfo ))
{
*ppvObject = &This->classinfo.IProvideClassInfo_iface;
}
else if ( IsEqualGUID( riid, &IID_IDispatchEx ))
{
@ -2846,7 +2906,7 @@ static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, v
return E_NOINTERFACE;
}
IFileSystem3_AddRef(iface);
IUnknown_AddRef((IUnknown*)*ppvObject);
return S_OK;
}
@ -3891,11 +3951,13 @@ static const struct IFileSystem3Vtbl filesys_vtbl =
filesys_GetFileVersion
};
static IFileSystem3 filesystem = { &filesys_vtbl };
static struct filesystem filesystem;
HRESULT WINAPI FileSystem_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
{
TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
return IFileSystem3_QueryInterface(&filesystem, riid, ppv);
filesystem.IFileSystem3_iface.lpVtbl = &filesys_vtbl;
init_classinfo(&CLSID_FileSystemObject, (IUnknown *)&filesystem.IFileSystem3_iface, &filesystem.classinfo);
return IFileSystem3_QueryInterface(&filesystem.IFileSystem3_iface, riid, ppv);
}

View File

@ -100,6 +100,31 @@ static IDrive *get_fixed_drive(void)
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;
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));
IProvideClassInfo_Release(classinfo);
ITypeInfo_ReleaseTypeAttr(ti, attr);
ITypeInfo_Release(ti);
}
static void test_interfaces(void)
{
static const WCHAR nonexistent_dirW[] = {
@ -122,6 +147,8 @@ static void test_interfaces(void)
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);
@ -927,6 +954,7 @@ static void test_GetFolder(void)
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);
}
@ -978,6 +1006,7 @@ static void test_FolderCollection(void)
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;
@ -1153,6 +1182,7 @@ static void test_FileCollection(void)
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;
@ -1220,6 +1250,7 @@ static void test_FileCollection(void)
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);
@ -1292,6 +1323,8 @@ static void test_DriveCollection(void)
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);
@ -1419,6 +1452,8 @@ static void test_CreateTextFile(void)
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);
@ -2033,6 +2068,7 @@ static void test_GetDrive(void)
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));