[PATCH 3/3] scrrun: Added IProvideClassInfo support for filesystem objects

Nikolay Sivov nsivov at codeweavers.com
Wed Dec 7 04:33:59 CST 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/scrrun/filesystem.c       | 110 ++++++++++++++++++++++++++++++++---------
 dlls/scrrun/tests/filesystem.c |  36 ++++++++++++++
 2 files changed, 122 insertions(+), 24 deletions(-)

diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index 818079e..45040b3 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -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);
 }
diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c
index cd0e6d6..5516099 100644
--- a/dlls/scrrun/tests/filesystem.c
+++ b/dlls/scrrun/tests/filesystem.c
@@ -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));
-- 
2.10.2




More information about the wine-patches mailing list