diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c index abbf3759896..2e45809b822 100644 --- a/dlls/scrrun/filesystem.c +++ b/dlls/scrrun/filesystem.c @@ -53,6 +53,7 @@ struct filecollection { struct drivecollection { IDriveCollection IDriveCollection_iface; LONG ref; + DWORD drives; }; struct enumdata { @@ -71,6 +72,7 @@ struct enumdata { struct { struct drivecollection *coll; + INT cur; } drivecoll; } u; }; @@ -82,6 +84,12 @@ struct enumvariant { struct enumdata data; }; +struct drive { + IDrive IDrive_iface; + LONG ref; + BSTR root; +}; + struct folder { IFolder IFolder_iface; LONG ref; @@ -107,6 +115,11 @@ enum iotype { IOWrite }; +static inline struct drive *impl_from_IDrive(IDrive *iface) +{ + return CONTAINING_RECORD(iface, struct drive, IDrive_iface); +} + static inline struct folder *impl_from_IFolder(IFolder *iface) { return CONTAINING_RECORD(iface, struct folder, IFolder_iface); @@ -436,6 +449,249 @@ static HRESULT create_textstream(IOMode mode, ITextStream **ret) return S_OK; } +static HRESULT WINAPI drive_QueryInterface(IDrive *iface, REFIID riid, void **obj) +{ + struct drive *This = impl_from_IDrive(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); + + *obj = NULL; + + if (IsEqualIID( riid, &IID_IDrive ) || + IsEqualIID( riid, &IID_IDispatch ) || + IsEqualIID( riid, &IID_IUnknown)) + { + *obj = iface; + IDrive_AddRef(iface); + } + else + return E_NOINTERFACE; + + return S_OK; +} + +static ULONG WINAPI drive_AddRef(IDrive *iface) +{ + struct drive *This = impl_from_IDrive(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); + return ref; +} + +static ULONG WINAPI drive_Release(IDrive *iface) +{ + struct drive *This = impl_from_IDrive(iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); + + if (!ref) + { + SysFreeString(This->root); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI drive_GetTypeInfoCount(IDrive *iface, UINT *pctinfo) +{ + struct drive *This = impl_from_IDrive(iface); + TRACE("(%p)->(%p)\n", This, pctinfo); + *pctinfo = 1; + return S_OK; +} + +static HRESULT WINAPI drive_GetTypeInfo(IDrive *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + struct drive *This = impl_from_IDrive(iface); + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + return get_typeinfo(IDrive_tid, ppTInfo); +} + +static HRESULT WINAPI drive_GetIDsOfNames(IDrive *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + struct drive *This = impl_from_IDrive(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + + hr = get_typeinfo(IDrive_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI drive_Invoke(IDrive *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + struct drive *This = impl_from_IDrive(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(IDrive_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI drive_get_Path(IDrive *iface, BSTR *path) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, path); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_DriveLetter(IDrive *iface, BSTR *letter) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, letter); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_ShareName(IDrive *iface, BSTR *share_name) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, share_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_DriveType(IDrive *iface, DriveTypeConst *ptype) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, ptype); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_RootFolder(IDrive *iface, IFolder **folder) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, folder); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_AvailableSpace(IDrive *iface, VARIANT *avail) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, avail); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_FreeSpace(IDrive *iface, VARIANT *v) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, v); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_TotalSize(IDrive *iface, VARIANT *v) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, v); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_VolumeName(IDrive *iface, BSTR *name) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, name); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_put_VolumeName(IDrive *iface, BSTR name) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%s): stub\n", This, debugstr_w(name)); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_FileSystem(IDrive *iface, BSTR *fs) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, fs); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_SerialNumber(IDrive *iface, LONG *serial) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, serial); + return E_NOTIMPL; +} + +static HRESULT WINAPI drive_get_IsReady(IDrive *iface, VARIANT_BOOL *ready) +{ + struct drive *This = impl_from_IDrive(iface); + FIXME("(%p)->(%p): stub\n", This, ready); + return E_NOTIMPL; +} + +static const IDriveVtbl drivevtbl = { + drive_QueryInterface, + drive_AddRef, + drive_Release, + drive_GetTypeInfoCount, + drive_GetTypeInfo, + drive_GetIDsOfNames, + drive_Invoke, + drive_get_Path, + drive_get_DriveLetter, + drive_get_ShareName, + drive_get_DriveType, + drive_get_RootFolder, + drive_get_AvailableSpace, + drive_get_FreeSpace, + drive_get_TotalSize, + drive_get_VolumeName, + drive_put_VolumeName, + drive_get_FileSystem, + drive_get_SerialNumber, + drive_get_IsReady +}; + +static HRESULT create_drive(WCHAR letter, IDrive **drive) +{ + struct drive *This; + + *drive = NULL; + + This = heap_alloc(sizeof(*This)); + if (!This) return E_OUTOFMEMORY; + + This->IDrive_iface.lpVtbl = &drivevtbl; + This->ref = 1; + This->root = SysAllocStringLen(NULL, 3); + if (!This->root) + { + heap_free(This); + return E_OUTOFMEMORY; + } + This->root[0] = letter; + This->root[1] = ':'; + This->root[2] = '\\'; + This->root[3] = 0; + + *drive = &This->IDrive_iface; + return S_OK; +} + static HRESULT WINAPI enumvariant_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **obj) { struct enumvariant *This = impl_from_IEnumVARIANT(iface); @@ -819,13 +1075,51 @@ static ULONG WINAPI drivecoll_enumvariant_Release(IEnumVARIANT *iface) return ref; } +static HRESULT find_next_drive(struct enumvariant *penum) +{ + int i = penum->data.u.drivecoll.cur == -1 ? 0 : penum->data.u.drivecoll.cur + 1; + + for (; i < 32; i++) + if (penum->data.u.drivecoll.coll->drives & (1 << i)) + { + penum->data.u.drivecoll.cur = i; + return S_OK; + } + + return S_FALSE; +} + static HRESULT WINAPI drivecoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched) { struct enumvariant *This = impl_from_IEnumVARIANT(iface); + ULONG count = 0; + HRESULT hr; - FIXME("(%p)->(%d %p %p): stub\n", This, celt, var, fetched); + TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched); - return E_NOTIMPL; + if (fetched) + *fetched = 0; + + while (find_next_drive(This) == S_OK) + { + IDrive *drive; + + hr = create_drive('A' + This->data.u.drivecoll.cur, &drive); + if (FAILED(hr)) return hr; + + V_VT(&var[count]) = VT_DISPATCH; + V_DISPATCH(&var[count]) = (IDispatch*)drive; + + if (++count >= celt) break; + } + + if (count < celt) + return S_FALSE; + + if (fetched) + *fetched = count; + + return S_OK; } static HRESULT WINAPI drivecoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt) @@ -841,9 +1135,10 @@ static HRESULT WINAPI drivecoll_enumvariant_Reset(IEnumVARIANT *iface) { struct enumvariant *This = impl_from_IEnumVARIANT(iface); - FIXME("(%p): stub\n", This); + TRACE("(%p)\n", This); - return E_NOTIMPL; + This->data.u.drivecoll.cur = -1; + return S_OK; } static HRESULT WINAPI drivecoll_enumvariant_Clone(IEnumVARIANT *iface, IEnumVARIANT **pclone) @@ -875,6 +1170,7 @@ static HRESULT create_drivecoll_enum(struct drivecollection *collection, IUnknow This->IEnumVARIANT_iface.lpVtbl = &drivecollenumvariantvtbl; This->ref = 1; This->data.u.drivecoll.coll = collection; + This->data.u.drivecoll.cur = -1; IDriveCollection_AddRef(&collection->IDriveCollection_iface); *newenum = (IUnknown*)&This->IEnumVARIANT_iface; @@ -1393,6 +1689,7 @@ static HRESULT create_drivecoll(IDriveCollection **drives) This->IDriveCollection_iface.lpVtbl = &drivecollectionvtbl; This->ref = 1; + This->drives = GetLogicalDrives(); *drives = &This->IDriveCollection_iface; return S_OK; diff --git a/dlls/scrrun/scrrun.c b/dlls/scrrun/scrrun.c index b88dda1972e..bad5b1c9717 100644 --- a/dlls/scrrun/scrrun.c +++ b/dlls/scrrun/scrrun.c @@ -103,6 +103,7 @@ static ITypeInfo *typeinfos[LAST_tid]; static REFIID tid_ids[] = { &IID_NULL, &IID_IDictionary, + &IID_IDrive, &IID_IDriveCollection, &IID_IFile, &IID_IFileCollection, diff --git a/dlls/scrrun/scrrun.idl b/dlls/scrrun/scrrun.idl index 016eeb6d71a..91c6314c203 100644 --- a/dlls/scrrun/scrrun.idl +++ b/dlls/scrrun/scrrun.idl @@ -287,8 +287,8 @@ library Scripting HRESULT Path([out, retval] BSTR* pbstrPath); [id(0x00002710), propget] - HRESULT DriveLetter([out, retval] BSTR* pbstrLetter) -; + HRESULT DriveLetter([out, retval] BSTR* pbstrLetter); + [id(0x00002711), propget] HRESULT ShareName([out, retval] BSTR* pbstrShareName); diff --git a/dlls/scrrun/scrrun_private.h b/dlls/scrrun/scrrun_private.h index 4d3e7be0936..a149202b0fe 100644 --- a/dlls/scrrun/scrrun_private.h +++ b/dlls/scrrun/scrrun_private.h @@ -25,6 +25,7 @@ typedef enum tid_t { NULL_tid, IDictionary_tid, + IDrive_tid, IDriveCollection_tid, IFile_tid, IFileCollection_tid,