>From d76f39fbde12ef9d53c35a40b89b8d10ddb54deb Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Fri, 30 Dec 2011 16:13:40 +0300
Subject: [PATCH 2/2] Added IWshCollection stub and some tests

---
 .gitignore                       |    1 +
 dlls/wshom.ocx/shell.c           |  182 +++++++++++-
 dlls/wshom.ocx/tests/Makefile.in |    2 +
 dlls/wshom.ocx/tests/wshom.c     |   51 +++-
 dlls/wshom.ocx/tests/wshom.idl   |  602 ++++++++++++++++++++++++++++++++++++++
 dlls/wshom.ocx/wshom.idl         |  279 ++++++++++++++++++
 dlls/wshom.ocx/wshom_main.c      |    3 +-
 dlls/wshom.ocx/wshom_private.h   |    1 +
 8 files changed, 1096 insertions(+), 25 deletions(-)
 create mode 100644 dlls/wshom.ocx/tests/wshom.idl

diff --git a/.gitignore b/.gitignore
index 22d7762..9164c25 100644
--- a/.gitignore
+++ b/.gitignore
@@ -130,6 +130,7 @@ dlls/vbscript/vbscript_classes.h
 dlls/vbscript/vbsglobal.h
 dlls/windowscodecs/windowscodecs_wincodec.h
 dlls/windowscodecs/windowscodecs_wincodec_p.c
+dlls/wshom.ocx/tests/wshom.h
 dlls/wshom.ocx/wshom.h
 include/activaut.h
 include/activdbg.h
diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c
index 857a48d..4e76a4c 100644
--- a/dlls/wshom.ocx/shell.c
+++ b/dlls/wshom.ocx/shell.c
@@ -25,16 +25,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(wshom);
 
 static IWshShell3 WshShell3;
 
-static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
+typedef struct
 {
-    if(IsEqualGUID(riid, &IID_IUnknown)) {
-        TRACE("(IID_IUnknown %p)\n", ppv);
-        *ppv = iface;
-    }else if(IsEqualGUID(riid, &IID_IDispatch)) {
-        TRACE("(IID_IDispatch %p)\n", ppv);
-        *ppv = iface;
-    }else if(IsEqualGUID(riid, &IID_IWshShell3)) {
-        TRACE("(IID_IWshShell3 %p)\n", ppv);
+    IWshCollection IWshCollection_iface;
+    LONG ref;
+} WshCollection;
+
+static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface )
+{
+    return CONTAINING_RECORD(iface, WshCollection, IWshCollection_iface);
+}
+
+static HRESULT WINAPI WshCollection_QueryInterface(IWshCollection *iface, REFIID riid, void **ppv)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+
+    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
+
+    if (IsEqualGUID(riid, &IID_IUnknown)  ||
+        IsEqualGUID(riid, &IID_IDispatch) ||
+        IsEqualGUID(riid, &IID_IWshCollection))
+    {
         *ppv = iface;
     }else {
         FIXME("Unknown iface %s\n", debugstr_guid(riid));
@@ -46,6 +57,153 @@ static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, v
     return S_OK;
 }
 
+static ULONG WINAPI WshCollection_AddRef(IWshCollection *iface)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    LONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p) ref = %d\n", This, ref);
+    return ref;
+}
+
+static ULONG WINAPI WshCollection_Release(IWshCollection *iface)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+    TRACE("(%p) ref = %d\n", This, ref);
+    return ref;
+}
+
+static HRESULT WINAPI WshCollection_GetTypeInfoCount(IWshCollection *iface, UINT *pctinfo)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    TRACE("(%p)->(%p)\n", This, pctinfo);
+    *pctinfo = 1;
+    return S_OK;
+}
+
+static HRESULT WINAPI WshCollection_GetTypeInfo(IWshCollection *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
+    return get_typeinfo(IWshCollection_tid, ppTInfo);
+}
+
+static HRESULT WINAPI WshCollection_GetIDsOfNames(IWshCollection *iface, REFIID riid, LPOLESTR *rgszNames,
+        UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
+
+    hr = get_typeinfo(IWshCollection_tid, &typeinfo);
+    if(SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
+        ITypeInfo_Release(typeinfo);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI WshCollection_Invoke(IWshCollection *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+        WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
+          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+
+    hr = get_typeinfo(IWshCollection_tid, &typeinfo);
+    if(SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_Invoke(typeinfo, &This->IWshCollection_iface, dispIdMember, wFlags,
+                pDispParams, pVarResult, pExcepInfo, puArgErr);
+        ITypeInfo_Release(typeinfo);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI WshCollection_Item(IWshCollection *iface, VARIANT *index, VARIANT *value)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    FIXME("(%p)->(%p %p): stub\n", This, index, value);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI WshCollection_Count(IWshCollection *iface, LONG *count)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    FIXME("(%p)->(%p): stub\n", This, count);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI WshCollection_get_length(IWshCollection *iface, LONG *count)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    FIXME("(%p)->(%p): stub\n", This, count);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI WshCollection__NewEnum(IWshCollection *iface, IUnknown *Enum)
+{
+    WshCollection *This = impl_from_IWshCollection(iface);
+    FIXME("(%p)->(%p): stub\n", This, Enum);
+    return E_NOTIMPL;
+}
+
+static const IWshCollectionVtbl WshCollectionVtbl = {
+    WshCollection_QueryInterface,
+    WshCollection_AddRef,
+    WshCollection_Release,
+    WshCollection_GetTypeInfoCount,
+    WshCollection_GetTypeInfo,
+    WshCollection_GetIDsOfNames,
+    WshCollection_Invoke,
+    WshCollection_Item,
+    WshCollection_Count,
+    WshCollection_get_length,
+    WshCollection__NewEnum
+};
+
+static HRESULT WshCollection_Create(IWshCollection **collection)
+{
+    WshCollection *This;
+
+    This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+    if (!This) return E_OUTOFMEMORY;
+
+    This->IWshCollection_iface.lpVtbl = &WshCollectionVtbl;
+    This->ref = 1;
+
+    *collection = &This->IWshCollection_iface;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
+{
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+
+    if(IsEqualGUID(riid, &IID_IUnknown)   ||
+       IsEqualGUID(riid, &IID_IDispatch) ||
+       IsEqualGUID(riid, &IID_IWshShell3))
+    {
+        *ppv = iface;
+    }else {
+        FIXME("Unknown iface %s\n", debugstr_guid(riid));
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IWshShell3_AddRef(iface);
+    return S_OK;
+}
+
 static ULONG WINAPI WshShell3_AddRef(IWshShell3 *iface)
 {
     TRACE("()\n");
@@ -109,10 +267,10 @@ static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, R
     return hr;
 }
 
-static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **out_Folders)
+static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **folders)
 {
-    FIXME("(%p): stub\n", out_Folders);
-    return E_NOTIMPL;
+    TRACE("(%p)\n", folders);
+    return WshCollection_Create(folders);
 }
 
 static HRESULT WINAPI WshShell3_get_Environment(IWshShell3 *iface, VARIANT *Type, IWshEnvironment **out_Env)
diff --git a/dlls/wshom.ocx/tests/Makefile.in b/dlls/wshom.ocx/tests/Makefile.in
index 90094fb..e062b3c 100644
--- a/dlls/wshom.ocx/tests/Makefile.in
+++ b/dlls/wshom.ocx/tests/Makefile.in
@@ -4,4 +4,6 @@ IMPORTS   = ole32
 C_SRCS = \
 	wshom.c
 
+IDL_H_SRCS = wshom.idl
+
 @MAKE_TEST_RULES@
diff --git a/dlls/wshom.ocx/tests/wshom.c b/dlls/wshom.ocx/tests/wshom.c
index 36081aa..414378f 100644
--- a/dlls/wshom.ocx/tests/wshom.c
+++ b/dlls/wshom.ocx/tests/wshom.c
@@ -23,33 +23,60 @@
 #include <ole2.h>
 #include <dispex.h>
 
+#include "wshom.h"
 #include "wine/test.h"
 
-DEFINE_GUID(CLSID_WshShell, 0x72c24dd5, 0xd70a, 0x438b, 0x8a,0x42, 0x98,0x42,0x4b,0x88,0xaf,0xb8);
-
-DEFINE_GUID(IID_IWshShell3, 0x41904400, 0xbe18, 0x11d3, 0xa2,0x8b, 0x00,0x10,0x4b,0xd3,0x50,0x90);
+#define EXPECT_HR(hr,hr_exp) \
+    ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
 
 static void test_wshshell(void)
 {
+    IWshShell3 *sh3;
     IDispatchEx *dispex;
+    IWshCollection *coll;
     IDispatch *disp;
     IUnknown *shell;
-    HRESULT hres;
+    IFolderCollection *folders;
+    ITypeInfo *ti;
+    HRESULT hr;
+    TYPEATTR *tattr;
 
-    hres = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+    hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
             &IID_IDispatch, (void**)&disp);
-    if(FAILED(hres)) {
-        win_skip("Could not create WshShell object: %08x\n", hres);
+    if(FAILED(hr)) {
+        win_skip("Could not create WshShell object: %08x\n", hr);
         return;
     }
 
-    hres = IDispatch_QueryInterface(disp, &IID_IWshShell3, (void**)&shell);
-    ok(hres == S_OK, "Could not get IWshShell3 iface: %08x\n", hres);
+    hr = IDispatch_QueryInterface(disp, &IID_IWshShell3, (void**)&shell);
+    EXPECT_HR(hr, S_OK);
+    IDispatch_Release(disp);
 
-    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
-    ok(hres == E_NOINTERFACE, "got %08x\n", hres);
+    hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    EXPECT_HR(hr, E_NOINTERFACE);
+
+    hr = IDispatch_QueryInterface(shell, &IID_IWshShell3, (void**)&sh3);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IWshShell3_get_SpecialFolders(sh3, &coll);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IWshCollection_QueryInterface(coll, &IID_IFolderCollection, (void**)&folders);
+    EXPECT_HR(hr, E_NOINTERFACE);
+
+    hr = IWshCollection_QueryInterface(coll, &IID_IDispatch, (void**)&disp);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IDispatch_GetTypeInfo(disp, 0, 0, &ti);
+    EXPECT_HR(hr, S_OK);
+
+    hr = ITypeInfo_GetTypeAttr(ti, &tattr);
+    EXPECT_HR(hr, S_OK);
+    ok(IsEqualIID(&tattr->guid, &IID_IWshCollection), "got \n");
+    ITypeInfo_ReleaseTypeAttr(ti, tattr);
+
+    IWshShell3_Release(sh3);
 
-    IDispatch_Release(disp);
     IUnknown_Release(shell);
 }
 
diff --git a/dlls/wshom.ocx/tests/wshom.idl b/dlls/wshom.ocx/tests/wshom.idl
new file mode 100644
index 0000000..cdd6363
--- /dev/null
+++ b/dlls/wshom.ocx/tests/wshom.idl
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2011 Jacek Caban for CodeWeavers
+ *
+ * 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
+ */
+
+import "oaidl.idl";
+cpp_quote("#undef ExpandEnvironmentStrings")
+
+[
+    helpstring("Windows Script Host Object Model"),
+    uuid(f935dc20-1cf0-11d0-adb9-00c04fd58a0b),
+    version(1.0)
+]
+library IWshRuntimeLibrary
+{
+    importlib("stdole2.tlb");
+
+    typedef enum {
+        WshRunning  = 0,
+        WshFinished,
+        WshFailed
+    } WshExecStatus;
+
+    typedef enum {
+        UnknownType = 0,
+        Removable,
+        Fixed,
+        Remote,
+        CDRom,
+        RamDisk
+    } DriveTypeConst;
+
+    typedef enum {
+        Normal     = 0x000,
+        ReadOnly   = 0x001,
+        Hidden     = 0x002,
+        System     = 0x004,
+        Volume     = 0x008,
+        Directory  = 0x010,
+        Archive    = 0x020,
+        Alias      = 0x400,
+        Compressed = 0x800
+    } FileAttribute;
+
+    typedef enum {
+        ForReading   = 0x1,
+        ForWriting   = 0x2,
+        ForAppending = 0x8
+    } IOMode;
+
+    typedef enum {
+        TristateTrue       = -1,
+        TristateFalse      =  0,
+        TristateUseDefault = -2,
+        TristateMixed      = -2
+    } Tristate;
+
+    interface IFolder;
+    interface IFolderCollection;
+
+    [
+        uuid(53bad8c1-e718-11cf-893d-00a0c9054228),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface ITextStream : IDispatch {
+        [id(0x2710), propget]
+        HRESULT Line([out, retval] long* Line);
+
+        [id(0xfffffdef), propget]
+        HRESULT Column([out, retval] long* Column);
+
+        [id(0x2712), propget]
+        HRESULT AtEndOfStream([out, retval] VARIANT_BOOL* EOS);
+
+        [id(0x2713), propget]
+        HRESULT AtEndOfLine([out, retval] VARIANT_BOOL* EOL);
+
+        [id(0x2714)]
+        HRESULT Read([in] long Characters, [out, retval] BSTR* Text);
+
+        [id(0x2715)]
+        HRESULT ReadLine([out, retval] BSTR* Text);
+
+        [id(0x2716)]
+        HRESULT ReadAll([out, retval] BSTR* Text);
+
+        [id(0x2717)]
+        HRESULT Write([in] BSTR Text);
+
+        [id(0x2718)]
+        HRESULT WriteLine([in, optional, defaultvalue("")] BSTR Text);
+
+        [id(0x2719)]
+        HRESULT WriteBlankLines([in] long Lines);
+
+        [id(0x271a)]
+        HRESULT Skip([in] long Characters);
+
+        [id(0x271b)]
+        HRESULT SkipLine();
+
+        [id(0x271c)]
+        HRESULT Close();
+    };
+
+    [
+        uuid(c7c3f5a0-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IDrive : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* path);
+
+        [id(0x2710), propget]
+        HRESULT DriveLetter([out, retval] BSTR* letter);
+
+        [id(0x2711), propget]
+        HRESULT ShareName([out, retval] BSTR* ShareName);
+
+        [id(0x2712), propget]
+        HRESULT DriveType([out, retval] DriveTypeConst* type);
+
+        [id(0x2713), propget]
+        HRESULT RootFolder([out, retval] IFolder** folder);
+
+        [id(0x2715), propget]
+        HRESULT AvailableSpace([out, retval] VARIANT* Avail);
+
+        [id(0x2714), propget]
+        HRESULT FreeSpace([out, retval] VARIANT* pFree);
+
+        [id(0x2716), propget]
+        HRESULT TotalSize([out, retval] VARIANT* Total);
+
+        [id(0x2717), propget]
+        HRESULT VolumeName([out, retval] BSTR* Name);
+
+        [id(0x2717), propput]
+        HRESULT VolumeName([in] BSTR Name);
+
+        [id(0x2718), propget]
+        HRESULT FileSystem([out, retval] BSTR* pFileSystem);
+
+        [id(0x2719), propget]
+        HRESULT SerialNumber([out, retval] long* SerialNumber);
+
+        [id(0x271a), propget]
+        HRESULT IsReady([out, retval] VARIANT_BOOL* pfReady);
+    };
+
+    [
+        uuid(c7c3f5a4-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFile : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* path);
+
+        [id(0x03e8), propget]
+        HRESULT Name([out, retval] BSTR* Name);
+
+        [id(0x03e8), propput]
+        HRESULT Name([in] BSTR Name);
+
+        [id(0x03ea), propget]
+        HRESULT ShortPath([out, retval] BSTR* path);
+
+        [id(0x03e9), propget]
+        HRESULT ShortName([out, retval] BSTR* Name);
+
+        [id(0x03ec), propget]
+        HRESULT Drive([out, retval] IDrive** drive);
+
+        [id(0x03ed), propget]
+        HRESULT ParentFolder([out, retval] IFolder** folder);
+
+        [id(0x03eb), propget]
+        HRESULT Attributes([out, retval] FileAttribute* attr);
+
+        [id(0x03eb), propput]
+        HRESULT Attributes([in] FileAttribute attr);
+
+        [id(0x03ee), propget]
+        HRESULT DateCreated([out, retval] DATE* date);
+
+        [id(0x03ef), propget]
+        HRESULT DateLastModified([out, retval] DATE* date);
+
+        [id(0x03f0), propget]
+        HRESULT DateLastAccessed([out, retval] DATE* date);
+
+        [id(0x03f1), propget]
+        HRESULT Size([out, retval] VARIANT* Size);
+
+        [id(0x03f2), propget]
+        HRESULT Type([out, retval] BSTR* Type);
+
+        [id(0x04b0)]
+        HRESULT Delete([in, optional, defaultvalue(0)] VARIANT_BOOL Force);
+
+        [id(0x04b2)]
+        HRESULT Copy(
+                    [in] BSTR Destination,
+                    [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+
+        [id(0x04b4)]
+        HRESULT Move([in] BSTR Destination);
+
+        [id(0x044c)]
+        HRESULT OpenAsTextStream(
+                    [in, optional, defaultvalue(1)] IOMode IOMode,
+                    [in, optional, defaultvalue(0)] Tristate Format,
+                    [out, retval] ITextStream** ppts);
+    };
+
+    [
+        uuid(c7c3f5a5-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFileCollection : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Item(
+                    [in] VARIANT Key,
+                    [out, retval] IFile** ppfile);
+        [id(DISPID_NEWENUM), propget, restricted, hidden]
+        HRESULT _NewEnum([out, retval] IUnknown** ppenum);
+        [id(1), propget]
+        HRESULT Count([out, retval] long* count);
+    };
+
+    [
+        uuid(c7c3f5a2-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFolder : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* path);
+
+        [id(0x03e8), propget]
+        HRESULT Name([out, retval] BSTR* name);
+
+        [id(0x03e8), propput]
+        HRESULT Name([in] BSTR name);
+
+        [id(0x03ea), propget]
+        HRESULT ShortPath([out, retval] BSTR* path);
+
+        [id(0x03e9), propget]
+        HRESULT ShortName([out, retval] BSTR* name);
+
+        [id(0x03ec), propget]
+        HRESULT Drive([out, retval] IDrive** drive);
+
+        [id(0x03ed), propget]
+        HRESULT ParentFolder([out, retval] IFolder** folder);
+
+        [id(0x03eb), propget]
+        HRESULT Attributes([out, retval] FileAttribute* attr);
+
+        [id(0x03eb), propput]
+        HRESULT Attributes([in] FileAttribute attr);
+
+        [id(0x03ee), propget]
+        HRESULT DateCreated([out, retval] DATE* date);
+
+        [id(0x03ef), propget]
+        HRESULT DateLastModified([out, retval] DATE* date);
+
+        [id(0x03f0), propget]
+        HRESULT DateLastAccessed([out, retval] DATE* date);
+
+        [id(0x03f2), propget]
+        HRESULT Type([out, retval] BSTR* type);
+
+        [id(0x04b1)]
+        HRESULT Delete([in, optional, defaultvalue(0)] VARIANT_BOOL force);
+
+        [id(0x04b3)]
+        HRESULT Copy(
+                    [in] BSTR Destination,
+                    [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+
+        [id(0x04b5)]
+        HRESULT Move([in] BSTR Destination);
+
+        [id(0x2710), propget]
+        HRESULT IsRootFolder([out, retval] VARIANT_BOOL* root);
+
+        [id(0x03f1), propget]
+        HRESULT Size([out, retval] VARIANT* size);
+
+        [id(0x2711), propget]
+        HRESULT SubFolders([out, retval] IFolderCollection** folders);
+
+        [id(0x2712), propget]
+        HRESULT Files([out, retval] IFileCollection** files);
+
+        [id(0x044d)]
+        HRESULT CreateTextFile(
+                    [in] BSTR FileName,
+                    [in, optional, defaultvalue(-1)] VARIANT_BOOL Overwrite,
+                    [in, optional, defaultvalue(0)] VARIANT_BOOL Unicode,
+                    [out, retval] ITextStream** ppts);
+    };
+
+    [
+        uuid(c7c3f5a3-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFolderCollection : IDispatch {
+        [id(2)]
+        HRESULT Add(
+                    [in] BSTR Name,
+                    [out, retval] IFolder** folder);
+
+        [id(DISPID_VALUE), propget]
+        HRESULT Item(
+                    [in] VARIANT Key,
+                    [out, retval] IFolder** folder);
+
+        [id(DISPID_NEWENUM), propget, restricted, hidden]
+        HRESULT _NewEnum([out, retval] IUnknown** ppenum);
+
+        [id(1), propget]
+        HRESULT Count([out, retval] long* count);
+    };
+
+    [
+        uuid(f935dc27-1cf0-11d0-adb9-00c04fd58a0b),
+        odl,
+        dual,
+        oleautomation
+    ]
+    interface IWshCollection : IDispatch {
+        [id(DISPID_VALUE)]
+        HRESULT Item(
+                [in] VARIANT *Index,
+                [out, retval] VARIANT *out_Value);
+
+        [id(1)]
+        HRESULT Count([out, retval] long *out_Count);
+
+        [id(2), propget]
+        HRESULT length([out, retval] long *out_Count);
+
+        [id(DISPID_NEWENUM)]
+        HRESULT _NewEnum([out, retval] IUnknown *out_Enum);
+    }
+
+    [
+        uuid(f935dc29-1cf0-11d0-adb9-00c04fd58a0b),
+        odl,
+        dual,
+        oleautomation
+    ]
+    interface IWshEnvironment : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Item(
+                [in] BSTR Name,
+                [out, retval] BSTR *out_Value);
+
+        [id(DISPID_VALUE), propput]
+        HRESULT Item(
+                [in] BSTR Name,
+                [in] BSTR out_Value);
+
+        [id(1)]
+        HRESULT Count([out, retval] long *out_Count);
+
+        [id(2), propget]
+        HRESULT length([out, retval] long *out_Count);
+
+        [id(DISPID_NEWENUM)]
+        HRESULT _NewEnum([out, retval] IUnknown *out_Enum);
+
+        [id(0x03e9)]
+        HRESULT Remove([in] BSTR Name);
+    }
+
+    [
+        uuid(08fed190-be19-11d3-a28b-00104bd35090),
+        odl,
+        dual,
+        oleautomation
+    ]
+    interface IWshExec : IDispatch {
+        [id(0x0001), propget]
+        HRESULT Status([out, retval] WshExecStatus* Status);
+
+        [id(0x0003), propget]
+        HRESULT StdIn([out, retval] ITextStream** stream);
+
+        [id(0x0004), propget]
+        HRESULT StdOut([out, retval] ITextStream** stream);
+
+        [id(0x0005), propget]
+        HRESULT StdErr([out, retval] ITextStream** stream);
+
+        [id(0x0006), propget]
+        HRESULT ProcessID([out, retval] long* pid);
+
+        [id(0x0007), propget]
+        HRESULT ExitCode([out, retval] long* ExitCode);
+
+        [id(0x0008)]
+        HRESULT Terminate();
+    };
+
+    [
+        uuid(f935dc21-1cf0-11d0-adb9-00c04fd58a0b),
+        odl,
+        dual,
+        oleautomation,
+        hidden
+    ]
+    interface IWshShell : IDispatch {
+        [id(0x0064), propget]
+        HRESULT SpecialFolders([out, retval] IWshCollection** out_Folders);
+
+        [id(0x00c8), propget]
+        HRESULT Environment(
+            [in, optional] VARIANT* Type,
+            [out, retval] IWshEnvironment** out_Env);
+
+        [id(0x03e8)]
+        HRESULT Run(
+            [in] BSTR Command,
+            [in, optional] VARIANT* WindowStyle,
+            [in, optional] VARIANT* WaitOnReturn,
+            [out, retval] int* out_ExitCode);
+
+        [id(0x03e9)]
+        HRESULT Popup(
+            [in] BSTR Text,
+            [in, optional] VARIANT* SecondsToWait,
+            [in, optional] VARIANT* Title,
+            [in, optional] VARIANT* Type,
+            [out, retval] int* out_Button);
+
+        [id(0x03ea)]
+        HRESULT CreateShortcut(
+            [in] BSTR PathLink,
+            [out, retval] IDispatch** out_Shortcut);
+
+        [id(0x03ee)]
+        HRESULT ExpandEnvironmentStrings(
+            [in] BSTR Src,
+            [out, retval] BSTR* out_Dst);
+
+        [id(0x07d0)]
+        HRESULT RegRead(
+            [in] BSTR Name,
+            [out, retval] VARIANT* out_Value);
+
+        [id(0x07d1)]
+        HRESULT RegWrite(
+            [in] BSTR Name,
+            [in] VARIANT* Value,
+            [in, optional] VARIANT* Type);
+
+        [id(0x07d2)]
+        HRESULT RegDelete([in] BSTR Name);
+    };
+
+    [
+      uuid(24be5a30-edfe-11d2-b933-00104b365c9f),
+      odl,
+      dual,
+      oleautomation,
+      hidden
+    ]
+    interface IWshShell2 : IWshShell {
+        [id(0x0bb8)]
+        HRESULT LogEvent(
+            [in] VARIANT* Type,
+            [in] BSTR Message,
+            [in, optional, defaultvalue("")] BSTR Target,
+            [out, retval] VARIANT_BOOL* out_Success);
+
+        [id(0x0bc2)]
+        HRESULT AppActivate(
+            [in] VARIANT* App,
+            [in, optional] VARIANT* Wait,
+            [out, retval] VARIANT_BOOL* out_Success);
+
+        [id(0x0bc3)]
+        HRESULT SendKeys(
+            [in] BSTR Keys,
+            [in, optional] VARIANT* Wait);
+    };
+
+    [
+        uuid(41904400-be18-11d3-a28b-00104bd35090),
+        odl,
+        dual,
+        oleautomation
+    ]
+    interface IWshShell3 : IWshShell2 {
+        [id(0x0bc4)]
+        HRESULT Exec(
+            [in] BSTR Command,
+            [out, retval] IWshExec** out_Exec);
+
+        [id(0x0bc5), propget]
+        HRESULT CurrentDirectory([out, retval] BSTR* out_Directory);
+
+        [id(0x0bc5), propput]
+        HRESULT CurrentDirectory([in] BSTR out_Directory);
+    };
+
+    [
+        uuid(24be5a31-edfe-11d2-b933-00104b365c9f),
+        odl,
+        dual,
+        oleautomation
+    ]
+    interface IWshNetwork2 : IDispatch {
+        [id(0x60020000), propget]
+        HRESULT UserDomain([out, retval] BSTR *out_UserDomain);
+    }
+
+    [
+        helpstring("Windows Script Host Shell Object"),
+        uuid(f935dc22-1cf0-11d0-adb9-00c04fd58a0b),
+        threading(apartment),
+        progid("WScript.Shell.1"),
+        vi_progid("WScript.Shell")
+    ]
+    coclass IWshShell_Class {
+        [default] interface IWshShell3;
+    }
+
+    [
+        helpstring("Windows Script Host Shell Object"),
+        uuid(72c24dd5-d70a-438b-8a42-98424b88afb8),
+        threading(apartment),
+        progid("WScript.Shell.1"),
+        vi_progid("WScript.Shell")
+    ]
+    coclass WshShell {
+        [default] interface IWshShell3;
+    }
+
+    [
+        helpstring("Windows Script Host Network Object"),
+        uuid(f935dc26-1cf0-11d0-adb9-00c04fd58a0b),
+        threading(apartment),
+        progid("WScript.Network.1"),
+        vi_progid("WScript.Network")
+    ]
+    coclass IWshNetwork_Class {
+        [default] interface IWshNetwork2;
+    }
+
+    [
+        helpstring("Windows Script Host Network Object"),
+        uuid(093ff999-1ea0-4079-9525-9614c3504b74),
+        threading(apartment),
+        progid("WScript.Network.1"),
+        vi_progid("WScript.Network")
+    ]
+    coclass WshNetwork {
+        [default] interface IWshNetwork2;
+    }
+}
diff --git a/dlls/wshom.ocx/wshom.idl b/dlls/wshom.ocx/wshom.idl
index 8d0b8e1..cdd6363 100644
--- a/dlls/wshom.ocx/wshom.idl
+++ b/dlls/wshom.ocx/wshom.idl
@@ -34,6 +34,43 @@ library IWshRuntimeLibrary
         WshFailed
     } WshExecStatus;
 
+    typedef enum {
+        UnknownType = 0,
+        Removable,
+        Fixed,
+        Remote,
+        CDRom,
+        RamDisk
+    } DriveTypeConst;
+
+    typedef enum {
+        Normal     = 0x000,
+        ReadOnly   = 0x001,
+        Hidden     = 0x002,
+        System     = 0x004,
+        Volume     = 0x008,
+        Directory  = 0x010,
+        Archive    = 0x020,
+        Alias      = 0x400,
+        Compressed = 0x800
+    } FileAttribute;
+
+    typedef enum {
+        ForReading   = 0x1,
+        ForWriting   = 0x2,
+        ForAppending = 0x8
+    } IOMode;
+
+    typedef enum {
+        TristateTrue       = -1,
+        TristateFalse      =  0,
+        TristateUseDefault = -2,
+        TristateMixed      = -2
+    } Tristate;
+
+    interface IFolder;
+    interface IFolderCollection;
+
     [
         uuid(53bad8c1-e718-11cf-893d-00a0c9054228),
         odl,
@@ -84,6 +121,248 @@ library IWshRuntimeLibrary
     };
 
     [
+        uuid(c7c3f5a0-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IDrive : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* path);
+
+        [id(0x2710), propget]
+        HRESULT DriveLetter([out, retval] BSTR* letter);
+
+        [id(0x2711), propget]
+        HRESULT ShareName([out, retval] BSTR* ShareName);
+
+        [id(0x2712), propget]
+        HRESULT DriveType([out, retval] DriveTypeConst* type);
+
+        [id(0x2713), propget]
+        HRESULT RootFolder([out, retval] IFolder** folder);
+
+        [id(0x2715), propget]
+        HRESULT AvailableSpace([out, retval] VARIANT* Avail);
+
+        [id(0x2714), propget]
+        HRESULT FreeSpace([out, retval] VARIANT* pFree);
+
+        [id(0x2716), propget]
+        HRESULT TotalSize([out, retval] VARIANT* Total);
+
+        [id(0x2717), propget]
+        HRESULT VolumeName([out, retval] BSTR* Name);
+
+        [id(0x2717), propput]
+        HRESULT VolumeName([in] BSTR Name);
+
+        [id(0x2718), propget]
+        HRESULT FileSystem([out, retval] BSTR* pFileSystem);
+
+        [id(0x2719), propget]
+        HRESULT SerialNumber([out, retval] long* SerialNumber);
+
+        [id(0x271a), propget]
+        HRESULT IsReady([out, retval] VARIANT_BOOL* pfReady);
+    };
+
+    [
+        uuid(c7c3f5a4-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFile : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* path);
+
+        [id(0x03e8), propget]
+        HRESULT Name([out, retval] BSTR* Name);
+
+        [id(0x03e8), propput]
+        HRESULT Name([in] BSTR Name);
+
+        [id(0x03ea), propget]
+        HRESULT ShortPath([out, retval] BSTR* path);
+
+        [id(0x03e9), propget]
+        HRESULT ShortName([out, retval] BSTR* Name);
+
+        [id(0x03ec), propget]
+        HRESULT Drive([out, retval] IDrive** drive);
+
+        [id(0x03ed), propget]
+        HRESULT ParentFolder([out, retval] IFolder** folder);
+
+        [id(0x03eb), propget]
+        HRESULT Attributes([out, retval] FileAttribute* attr);
+
+        [id(0x03eb), propput]
+        HRESULT Attributes([in] FileAttribute attr);
+
+        [id(0x03ee), propget]
+        HRESULT DateCreated([out, retval] DATE* date);
+
+        [id(0x03ef), propget]
+        HRESULT DateLastModified([out, retval] DATE* date);
+
+        [id(0x03f0), propget]
+        HRESULT DateLastAccessed([out, retval] DATE* date);
+
+        [id(0x03f1), propget]
+        HRESULT Size([out, retval] VARIANT* Size);
+
+        [id(0x03f2), propget]
+        HRESULT Type([out, retval] BSTR* Type);
+
+        [id(0x04b0)]
+        HRESULT Delete([in, optional, defaultvalue(0)] VARIANT_BOOL Force);
+
+        [id(0x04b2)]
+        HRESULT Copy(
+                    [in] BSTR Destination,
+                    [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+
+        [id(0x04b4)]
+        HRESULT Move([in] BSTR Destination);
+
+        [id(0x044c)]
+        HRESULT OpenAsTextStream(
+                    [in, optional, defaultvalue(1)] IOMode IOMode,
+                    [in, optional, defaultvalue(0)] Tristate Format,
+                    [out, retval] ITextStream** ppts);
+    };
+
+    [
+        uuid(c7c3f5a5-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFileCollection : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Item(
+                    [in] VARIANT Key,
+                    [out, retval] IFile** ppfile);
+        [id(DISPID_NEWENUM), propget, restricted, hidden]
+        HRESULT _NewEnum([out, retval] IUnknown** ppenum);
+        [id(1), propget]
+        HRESULT Count([out, retval] long* count);
+    };
+
+    [
+        uuid(c7c3f5a2-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFolder : IDispatch {
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* path);
+
+        [id(0x03e8), propget]
+        HRESULT Name([out, retval] BSTR* name);
+
+        [id(0x03e8), propput]
+        HRESULT Name([in] BSTR name);
+
+        [id(0x03ea), propget]
+        HRESULT ShortPath([out, retval] BSTR* path);
+
+        [id(0x03e9), propget]
+        HRESULT ShortName([out, retval] BSTR* name);
+
+        [id(0x03ec), propget]
+        HRESULT Drive([out, retval] IDrive** drive);
+
+        [id(0x03ed), propget]
+        HRESULT ParentFolder([out, retval] IFolder** folder);
+
+        [id(0x03eb), propget]
+        HRESULT Attributes([out, retval] FileAttribute* attr);
+
+        [id(0x03eb), propput]
+        HRESULT Attributes([in] FileAttribute attr);
+
+        [id(0x03ee), propget]
+        HRESULT DateCreated([out, retval] DATE* date);
+
+        [id(0x03ef), propget]
+        HRESULT DateLastModified([out, retval] DATE* date);
+
+        [id(0x03f0), propget]
+        HRESULT DateLastAccessed([out, retval] DATE* date);
+
+        [id(0x03f2), propget]
+        HRESULT Type([out, retval] BSTR* type);
+
+        [id(0x04b1)]
+        HRESULT Delete([in, optional, defaultvalue(0)] VARIANT_BOOL force);
+
+        [id(0x04b3)]
+        HRESULT Copy(
+                    [in] BSTR Destination,
+                    [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+
+        [id(0x04b5)]
+        HRESULT Move([in] BSTR Destination);
+
+        [id(0x2710), propget]
+        HRESULT IsRootFolder([out, retval] VARIANT_BOOL* root);
+
+        [id(0x03f1), propget]
+        HRESULT Size([out, retval] VARIANT* size);
+
+        [id(0x2711), propget]
+        HRESULT SubFolders([out, retval] IFolderCollection** folders);
+
+        [id(0x2712), propget]
+        HRESULT Files([out, retval] IFileCollection** files);
+
+        [id(0x044d)]
+        HRESULT CreateTextFile(
+                    [in] BSTR FileName,
+                    [in, optional, defaultvalue(-1)] VARIANT_BOOL Overwrite,
+                    [in, optional, defaultvalue(0)] VARIANT_BOOL Unicode,
+                    [out, retval] ITextStream** ppts);
+    };
+
+    [
+        uuid(c7c3f5a3-88a3-11d0-abcb-00a0c90fffc0),
+        odl,
+        hidden,
+        dual,
+        nonextensible,
+        oleautomation
+    ]
+    interface IFolderCollection : IDispatch {
+        [id(2)]
+        HRESULT Add(
+                    [in] BSTR Name,
+                    [out, retval] IFolder** folder);
+
+        [id(DISPID_VALUE), propget]
+        HRESULT Item(
+                    [in] VARIANT Key,
+                    [out, retval] IFolder** folder);
+
+        [id(DISPID_NEWENUM), propget, restricted, hidden]
+        HRESULT _NewEnum([out, retval] IUnknown** ppenum);
+
+        [id(1), propget]
+        HRESULT Count([out, retval] long* count);
+    };
+
+    [
         uuid(f935dc27-1cf0-11d0-adb9-00c04fd58a0b),
         odl,
         dual,
diff --git a/dlls/wshom.ocx/wshom_main.c b/dlls/wshom.ocx/wshom_main.c
index c750592..c76b815 100644
--- a/dlls/wshom.ocx/wshom_main.c
+++ b/dlls/wshom.ocx/wshom_main.c
@@ -33,7 +33,8 @@ static ITypeInfo *typeinfos[LAST_tid];
 
 static REFIID tid_ids[] = {
     &IID_NULL,
-    &IID_IWshShell3
+    &IID_IWshShell3,
+    &IID_IWshCollection
 };
 
 static HRESULT load_typelib(void)
diff --git a/dlls/wshom.ocx/wshom_private.h b/dlls/wshom.ocx/wshom_private.h
index 42be641..1b340ca 100644
--- a/dlls/wshom.ocx/wshom_private.h
+++ b/dlls/wshom.ocx/wshom_private.h
@@ -28,6 +28,7 @@
 typedef enum tid_t {
     NULL_tid,
     IWshShell3_tid,
+    IWshCollection_tid,
     LAST_tid
 } tid_t;
 
-- 
1.5.6.5


