2 * Copyright 2012 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "scrrun_private.h"
35 #include "wine/debug.h"
36 #include "wine/heap.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(scrrun
);
40 static const WCHAR bsW
[] = {'\\',0};
41 static const WCHAR utf16bom
= 0xfeff;
44 struct provideclassinfo classinfo
;
45 IFileSystem3 IFileSystem3_iface
;
48 struct foldercollection
{
49 struct provideclassinfo classinfo
;
50 IFolderCollection IFolderCollection_iface
;
55 struct filecollection
{
56 struct provideclassinfo classinfo
;
57 IFileCollection IFileCollection_iface
;
62 struct drivecollection
{
63 struct provideclassinfo classinfo
;
64 IDriveCollection IDriveCollection_iface
;
75 struct foldercollection
*coll
;
80 struct filecollection
*coll
;
85 struct drivecollection
*coll
;
92 IEnumVARIANT IEnumVARIANT_iface
;
99 struct provideclassinfo classinfo
;
106 struct provideclassinfo classinfo
;
107 IFolder IFolder_iface
;
113 struct provideclassinfo classinfo
;
121 struct provideclassinfo classinfo
;
122 ITextStream ITextStream_iface
;
132 size_t read_buf_size
;
140 static inline struct filesystem
*impl_from_IFileSystem3(IFileSystem3
*iface
)
142 return CONTAINING_RECORD(iface
, struct filesystem
, IFileSystem3_iface
);
145 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
147 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
150 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
152 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
155 static inline struct file
*impl_from_IFile(IFile
*iface
)
157 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
160 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
162 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
165 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
167 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
170 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
172 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
175 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
177 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
180 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
182 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
185 static inline HRESULT
create_error(DWORD err
)
188 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
189 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
190 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
191 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
192 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
194 FIXME("Unsupported error code: %d\n", err
);
199 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
200 static HRESULT
create_file(BSTR
, IFile
**);
201 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
202 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
203 static HRESULT
create_drivecoll_enum(struct drivecollection
*, IUnknown
**);
205 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
207 static const WCHAR dotdotW
[] = {'.','.',0};
208 static const WCHAR dotW
[] = {'.',0};
210 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
211 wcscmp(data
->cFileName
, dotdotW
) &&
212 wcscmp(data
->cFileName
, dotW
);
215 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
217 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
220 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
222 int len
= SysStringLen(path
);
223 WCHAR buffW
[MAX_PATH
];
225 lstrcpyW(buffW
, path
);
226 if (path
[len
-1] != '\\')
227 lstrcatW(buffW
, bsW
);
228 lstrcatW(buffW
, data
->cFileName
);
230 return SysAllocString(buffW
);
233 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
236 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
238 return This
->mode
== ForReading
;
241 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
243 struct textstream
*This
= impl_from_ITextStream(iface
);
245 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
247 if (IsEqualIID(riid
, &IID_ITextStream
) ||
248 IsEqualIID(riid
, &IID_IDispatch
) ||
249 IsEqualIID(riid
, &IID_IUnknown
))
251 *obj
= &This
->ITextStream_iface
;
253 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
255 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
258 return E_NOINTERFACE
;
260 IUnknown_AddRef((IUnknown
*)*obj
);
264 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
266 struct textstream
*This
= impl_from_ITextStream(iface
);
267 ULONG ref
= InterlockedIncrement(&This
->ref
);
268 TRACE("(%p)->(%d)\n", This
, ref
);
272 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
274 struct textstream
*This
= impl_from_ITextStream(iface
);
275 ULONG ref
= InterlockedDecrement(&This
->ref
);
276 TRACE("(%p)->(%d)\n", This
, ref
);
280 if (This
->read_buf_size
) heap_free(This
->read_buf
);
281 CloseHandle(This
->file
);
288 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
290 struct textstream
*This
= impl_from_ITextStream(iface
);
291 TRACE("(%p)->(%p)\n", This
, pctinfo
);
296 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
297 LCID lcid
, ITypeInfo
**ppTInfo
)
299 struct textstream
*This
= impl_from_ITextStream(iface
);
300 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
301 return get_typeinfo(ITextStream_tid
, ppTInfo
);
304 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
305 LPOLESTR
*rgszNames
, UINT cNames
,
306 LCID lcid
, DISPID
*rgDispId
)
308 struct textstream
*This
= impl_from_ITextStream(iface
);
312 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
314 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
317 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
318 ITypeInfo_Release(typeinfo
);
324 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
325 REFIID riid
, LCID lcid
, WORD wFlags
,
326 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
327 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
329 struct textstream
*This
= impl_from_ITextStream(iface
);
333 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
334 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
336 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
339 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
340 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
341 ITypeInfo_Release(typeinfo
);
347 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
349 struct textstream
*This
= impl_from_ITextStream(iface
);
350 FIXME("(%p)->(%p): stub\n", This
, line
);
354 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
356 struct textstream
*This
= impl_from_ITextStream(iface
);
357 FIXME("(%p)->(%p): stub\n", This
, column
);
361 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
363 struct textstream
*This
= impl_from_ITextStream(iface
);
365 TRACE("(%p)->(%p)\n", This
, eos
);
370 if (textstream_check_iomode(This
, IORead
)) {
372 return CTL_E_BADFILEMODE
;
375 *eos
= (This
->eof
&& !This
->read_buf_size
) ? VARIANT_TRUE
: VARIANT_FALSE
;
379 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
381 struct textstream
*This
= impl_from_ITextStream(iface
);
382 FIXME("(%p)->(%p): stub\n", This
, eol
);
386 static HRESULT
append_read_data(struct textstream
*stream
, const char *buf
, size_t buf_size
)
388 LARGE_INTEGER revert
;
395 len
= buf_size
/ sizeof(WCHAR
);
396 if (buf_size
& 1) revert
.QuadPart
= -1;
400 for (len
= 0; len
< buf_size
; len
++)
402 if (!IsDBCSLeadByte(buf
[len
])) continue;
403 if (len
+ 1 == buf_size
)
405 revert
.QuadPart
= -1;
411 len
= MultiByteToWideChar(CP_ACP
, 0, buf
, buf_size
, NULL
, 0);
416 SetFilePointerEx(stream
->file
, revert
, NULL
, FILE_CURRENT
);
418 if (!stream
->read_buf_size
)
419 new_buf
= heap_alloc(len
* sizeof(WCHAR
));
421 new_buf
= heap_realloc(stream
->read_buf
, (len
+ stream
->read_buf_size
) * sizeof(WCHAR
));
422 if (!new_buf
) return E_OUTOFMEMORY
;
425 memcpy(new_buf
+ stream
->read_buf_size
, buf
, len
* sizeof(WCHAR
));
427 MultiByteToWideChar(CP_ACP
, 0, buf
, buf_size
, new_buf
+ stream
->read_buf_size
, len
);
428 stream
->read_buf
= new_buf
;
429 stream
->read_buf_size
+= len
;
433 static HRESULT
read_more_data(struct textstream
*stream
)
438 if (stream
->eof
) return S_OK
;
440 if (!ReadFile(stream
->file
, buf
, sizeof(buf
), &read
, NULL
))
442 ITextStream_Release(&stream
->ITextStream_iface
);
443 return create_error(GetLastError());
446 stream
->eof
= read
!= sizeof(buf
);
447 return append_read_data(stream
, buf
, read
);
450 static BOOL
read_from_buffer(struct textstream
*stream
, size_t len
, BSTR
*ret
, size_t skip
)
452 assert(len
+ skip
<= stream
->read_buf_size
);
454 if (!(*ret
= SysAllocStringLen(stream
->read_buf
, len
))) return FALSE
;
457 stream
->read_buf_size
-= len
;
458 if (stream
->read_buf_size
)
459 memmove(stream
->read_buf
, stream
->read_buf
+ len
, stream
->read_buf_size
* sizeof(WCHAR
));
461 heap_free(stream
->read_buf
);
465 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
467 struct textstream
*This
= impl_from_ITextStream(iface
);
470 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
477 return len
== 0 ? S_OK
: E_INVALIDARG
;
479 if (textstream_check_iomode(This
, IORead
))
480 return CTL_E_BADFILEMODE
;
482 while (!This
->eof
&& len
> This
->read_buf_size
)
484 if (FAILED(hr
= read_more_data(This
)))
488 if (This
->eof
&& !This
->read_buf_size
)
489 return CTL_E_ENDOFFILE
;
491 if (len
> This
->read_buf_size
)
493 len
= This
->read_buf_size
;
497 return read_from_buffer(This
, len
, text
, 0) ? hr
: E_OUTOFMEMORY
;
500 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
502 struct textstream
*This
= impl_from_ITextStream(iface
);
503 unsigned int skip
= 0;
507 TRACE("(%p)->(%p)\n", This
, text
);
513 if (textstream_check_iomode(This
, IORead
))
514 return CTL_E_BADFILEMODE
;
516 while (!(nl
= wmemchr(This
->read_buf
, '\n', This
->read_buf_size
)) && !This
->eof
)
518 if (FAILED(hr
= read_more_data(This
)))
522 if (This
->eof
&& !This
->read_buf_size
)
523 return CTL_E_ENDOFFILE
;
527 nl
= This
->read_buf
+ This
->read_buf_size
;
530 else if (nl
> This
->read_buf
&& nl
[-1] == '\r')
537 return read_from_buffer(This
, nl
- This
->read_buf
, text
, skip
) ? hr
: E_OUTOFMEMORY
;
540 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
542 struct textstream
*This
= impl_from_ITextStream(iface
);
545 TRACE("(%p)->(%p)\n", This
, text
);
551 if (textstream_check_iomode(This
, IORead
))
552 return CTL_E_BADFILEMODE
;
556 if (FAILED(hr
= read_more_data(This
)))
560 if (This
->eof
&& !This
->read_buf_size
)
561 return CTL_E_ENDOFFILE
;
563 return read_from_buffer(This
, This
->read_buf_size
, text
, 0) ? S_FALSE
: E_OUTOFMEMORY
;
566 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
571 if (stream
->unicode
) {
572 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
573 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
575 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
579 buffA
= heap_alloc(len
);
581 return E_OUTOFMEMORY
;
583 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
584 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
585 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
591 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
593 struct textstream
*This
= impl_from_ITextStream(iface
);
595 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
597 if (textstream_check_iomode(This
, IOWrite
))
598 return CTL_E_BADFILEMODE
;
600 return textstream_writestr(This
, text
);
603 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
605 static const WCHAR crlfW
[] = {'\r','\n'};
606 static const char crlfA
[] = {'\r','\n'};
607 DWORD written
= 0, len
;
611 if (stream
->unicode
) {
620 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
621 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
624 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
626 struct textstream
*This
= impl_from_ITextStream(iface
);
629 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
631 if (textstream_check_iomode(This
, IOWrite
))
632 return CTL_E_BADFILEMODE
;
634 hr
= textstream_writestr(This
, text
);
636 hr
= textstream_writecrlf(This
);
640 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
642 struct textstream
*This
= impl_from_ITextStream(iface
);
643 FIXME("(%p)->(%d): stub\n", This
, lines
);
647 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
649 struct textstream
*This
= impl_from_ITextStream(iface
);
650 FIXME("(%p)->(%d): stub\n", This
, count
);
654 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
656 struct textstream
*This
= impl_from_ITextStream(iface
);
657 FIXME("(%p): stub\n", This
);
661 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
663 struct textstream
*This
= impl_from_ITextStream(iface
);
666 TRACE("(%p)\n", This
);
668 if(!CloseHandle(This
->file
))
676 static const ITextStreamVtbl textstreamvtbl
= {
677 textstream_QueryInterface
,
680 textstream_GetTypeInfoCount
,
681 textstream_GetTypeInfo
,
682 textstream_GetIDsOfNames
,
685 textstream_get_Column
,
686 textstream_get_AtEndOfStream
,
687 textstream_get_AtEndOfLine
,
692 textstream_WriteLine
,
693 textstream_WriteBlankLines
,
699 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, Tristate format
, ITextStream
**ret
)
701 struct textstream
*stream
;
705 /* map access mode */
709 access
= GENERIC_READ
;
712 access
= GENERIC_WRITE
;
715 access
= GENERIC_READ
| GENERIC_WRITE
;
721 stream
= heap_alloc(sizeof(struct textstream
));
722 if (!stream
) return E_OUTOFMEMORY
;
724 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
728 stream
->read_buf
= NULL
;
729 stream
->read_buf_size
= 0;
731 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
732 if (stream
->file
== INVALID_HANDLE_VALUE
)
734 HRESULT hr
= create_error(GetLastError());
739 if (mode
== ForReading
)
740 GetFileSizeEx(stream
->file
, &stream
->size
);
742 stream
->size
.QuadPart
= 0;
744 if (mode
== ForWriting
)
746 stream
->unicode
= format
== TristateTrue
;
747 /* Write Unicode BOM */
748 if (stream
->unicode
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
750 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
751 if (!ret
|| written
!= sizeof(utf16bom
)) {
752 ITextStream_Release(&stream
->ITextStream_iface
);
753 return create_error(GetLastError());
759 DWORD read
, buf_offset
= 0;
762 if (format
== TristateUseDefault
|| mode
== ForReading
)
764 if (!ReadFile(stream
->file
, buf
, sizeof(buf
), &read
, NULL
))
766 ITextStream_Release(&stream
->ITextStream_iface
);
767 return create_error(GetLastError());
771 if (format
== TristateUseDefault
)
772 stream
->unicode
= IsTextUnicode(buf
, read
, NULL
);
774 stream
->unicode
= format
!= TristateFalse
;
776 if (mode
== ForReading
)
778 if (stream
->unicode
&& read
>= 2 && buf
[0] == 0xff && buf
[1] == 0xfe)
779 buf_offset
+= 2; /* skip utf16 BOM */
781 hr
= append_read_data(stream
, (const char *)buf
+ buf_offset
, read
- buf_offset
);
784 ITextStream_Release(&stream
->ITextStream_iface
);
788 stream
->eof
= read
!= sizeof(buf
);
790 else SetFilePointer(stream
->file
, 0, 0, FILE_END
);
793 init_classinfo(&CLSID_TextStream
, (IUnknown
*)&stream
->ITextStream_iface
, &stream
->classinfo
);
794 *ret
= &stream
->ITextStream_iface
;
798 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
800 struct drive
*This
= impl_from_IDrive(iface
);
802 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
806 if (IsEqualIID( riid
, &IID_IDrive
) ||
807 IsEqualIID( riid
, &IID_IDispatch
) ||
808 IsEqualIID( riid
, &IID_IUnknown
))
810 *obj
= &This
->IDrive_iface
;
812 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
814 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
817 return E_NOINTERFACE
;
819 IUnknown_AddRef((IUnknown
*)*obj
);
823 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
825 struct drive
*This
= impl_from_IDrive(iface
);
826 ULONG ref
= InterlockedIncrement(&This
->ref
);
827 TRACE("(%p)->(%d)\n", This
, ref
);
831 static ULONG WINAPI
drive_Release(IDrive
*iface
)
833 struct drive
*This
= impl_from_IDrive(iface
);
834 ULONG ref
= InterlockedDecrement(&This
->ref
);
835 TRACE("(%p)->(%d)\n", This
, ref
);
839 SysFreeString(This
->root
);
846 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
848 struct drive
*This
= impl_from_IDrive(iface
);
849 TRACE("(%p)->(%p)\n", This
, pctinfo
);
854 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
855 LCID lcid
, ITypeInfo
**ppTInfo
)
857 struct drive
*This
= impl_from_IDrive(iface
);
858 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
859 return get_typeinfo(IDrive_tid
, ppTInfo
);
862 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
863 LPOLESTR
*rgszNames
, UINT cNames
,
864 LCID lcid
, DISPID
*rgDispId
)
866 struct drive
*This
= impl_from_IDrive(iface
);
870 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
872 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
875 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
876 ITypeInfo_Release(typeinfo
);
882 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
883 REFIID riid
, LCID lcid
, WORD wFlags
,
884 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
885 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
887 struct drive
*This
= impl_from_IDrive(iface
);
891 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
892 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
894 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
897 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
898 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
899 ITypeInfo_Release(typeinfo
);
905 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
907 struct drive
*This
= impl_from_IDrive(iface
);
908 FIXME("(%p)->(%p): stub\n", This
, path
);
912 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
914 struct drive
*This
= impl_from_IDrive(iface
);
916 TRACE("(%p)->(%p)\n", This
, letter
);
921 *letter
= SysAllocStringLen(This
->root
, 1);
923 return E_OUTOFMEMORY
;
928 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
930 struct drive
*This
= impl_from_IDrive(iface
);
931 FIXME("(%p)->(%p): stub\n", This
, share_name
);
935 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
937 struct drive
*This
= impl_from_IDrive(iface
);
939 TRACE("(%p)->(%p)\n", This
, type
);
941 switch (GetDriveTypeW(This
->root
))
943 case DRIVE_REMOVABLE
:
966 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
968 struct drive
*This
= impl_from_IDrive(iface
);
969 FIXME("(%p)->(%p): stub\n", This
, folder
);
973 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
977 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
980 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
985 V_I4(v
) = src
->u
.LowPart
;
991 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
993 struct drive
*This
= impl_from_IDrive(iface
);
994 ULARGE_INTEGER avail
;
996 TRACE("(%p)->(%p)\n", This
, v
);
1001 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
1004 return variant_from_largeint(&avail
, v
);
1007 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
1009 struct drive
*This
= impl_from_IDrive(iface
);
1010 ULARGE_INTEGER freespace
;
1012 TRACE("(%p)->(%p)\n", This
, v
);
1017 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
1020 return variant_from_largeint(&freespace
, v
);
1023 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
1025 struct drive
*This
= impl_from_IDrive(iface
);
1026 ULARGE_INTEGER total
;
1028 TRACE("(%p)->(%p)\n", This
, v
);
1033 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
1036 return variant_from_largeint(&total
, v
);
1039 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
1041 struct drive
*This
= impl_from_IDrive(iface
);
1042 WCHAR nameW
[MAX_PATH
+1];
1045 TRACE("(%p)->(%p)\n", This
, name
);
1051 ret
= GetVolumeInformationW(This
->root
, nameW
, ARRAY_SIZE(nameW
), NULL
, NULL
, NULL
, NULL
, 0);
1053 *name
= SysAllocString(nameW
);
1054 return ret
? S_OK
: E_FAIL
;
1057 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
1059 struct drive
*This
= impl_from_IDrive(iface
);
1060 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1064 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
1066 struct drive
*This
= impl_from_IDrive(iface
);
1067 WCHAR nameW
[MAX_PATH
+1];
1070 TRACE("(%p)->(%p)\n", This
, fs
);
1076 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, ARRAY_SIZE(nameW
));
1078 *fs
= SysAllocString(nameW
);
1079 return ret
? S_OK
: E_FAIL
;
1082 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
1084 struct drive
*This
= impl_from_IDrive(iface
);
1087 TRACE("(%p)->(%p)\n", This
, serial
);
1092 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1093 return ret
? S_OK
: E_FAIL
;
1096 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1098 struct drive
*This
= impl_from_IDrive(iface
);
1099 ULARGE_INTEGER freespace
;
1102 TRACE("(%p)->(%p)\n", This
, ready
);
1107 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1108 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1112 static const IDriveVtbl drivevtbl
= {
1113 drive_QueryInterface
,
1116 drive_GetTypeInfoCount
,
1118 drive_GetIDsOfNames
,
1121 drive_get_DriveLetter
,
1122 drive_get_ShareName
,
1123 drive_get_DriveType
,
1124 drive_get_RootFolder
,
1125 drive_get_AvailableSpace
,
1126 drive_get_FreeSpace
,
1127 drive_get_TotalSize
,
1128 drive_get_VolumeName
,
1129 drive_put_VolumeName
,
1130 drive_get_FileSystem
,
1131 drive_get_SerialNumber
,
1135 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1141 This
= heap_alloc(sizeof(*This
));
1142 if (!This
) return E_OUTOFMEMORY
;
1144 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1146 This
->root
= SysAllocStringLen(NULL
, 3);
1150 return E_OUTOFMEMORY
;
1152 This
->root
[0] = letter
;
1153 This
->root
[1] = ':';
1154 This
->root
[2] = '\\';
1157 init_classinfo(&CLSID_Drive
, (IUnknown
*)&This
->IDrive_iface
, &This
->classinfo
);
1158 *drive
= &This
->IDrive_iface
;
1162 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1164 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1166 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1170 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1171 IsEqualIID( riid
, &IID_IUnknown
))
1174 IEnumVARIANT_AddRef(iface
);
1177 return E_NOINTERFACE
;
1182 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1184 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1185 ULONG ref
= InterlockedIncrement(&This
->ref
);
1186 TRACE("(%p)->(%d)\n", This
, ref
);
1190 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1192 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1193 ULONG ref
= InterlockedDecrement(&This
->ref
);
1195 TRACE("(%p)->(%d)\n", This
, ref
);
1199 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1200 FindClose(This
->data
.u
.foldercoll
.find
);
1207 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1209 static const WCHAR allW
[] = {'*',0};
1210 WCHAR pathW
[MAX_PATH
];
1214 lstrcpyW(pathW
, path
);
1215 len
= lstrlenW(pathW
);
1216 if (len
&& pathW
[len
-1] != '\\')
1217 lstrcatW(pathW
, bsW
);
1218 lstrcatW(pathW
, allW
);
1219 handle
= FindFirstFileW(pathW
, data
);
1220 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1222 /* find first dir/file */
1225 if (file
? is_file_data(data
) : is_dir_data(data
))
1228 if (!FindNextFileW(handle
, data
))
1237 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1239 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1240 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1241 WIN32_FIND_DATAW data
;
1244 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1249 if (!celt
) return S_OK
;
1253 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1254 if (!handle
) return S_FALSE
;
1256 This
->data
.u
.foldercoll
.find
= handle
;
1260 if (!FindNextFileW(handle
, &data
))
1266 if (is_dir_data(&data
))
1272 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1273 hr
= create_folder(str
, &folder
);
1275 if (FAILED(hr
)) return hr
;
1277 V_VT(&var
[count
]) = VT_DISPATCH
;
1278 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1281 if (count
>= celt
) break;
1283 } while (FindNextFileW(handle
, &data
));
1288 return (count
< celt
) ? S_FALSE
: S_OK
;
1291 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1293 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1294 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1295 WIN32_FIND_DATAW data
;
1297 TRACE("(%p)->(%d)\n", This
, celt
);
1299 if (!celt
) return S_OK
;
1303 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1304 if (!handle
) return S_FALSE
;
1306 This
->data
.u
.foldercoll
.find
= handle
;
1310 if (!FindNextFileW(handle
, &data
))
1316 if (is_dir_data(&data
))
1320 } while (FindNextFileW(handle
, &data
));
1322 return celt
? S_FALSE
: S_OK
;
1325 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1327 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1329 TRACE("(%p)\n", This
);
1331 FindClose(This
->data
.u
.foldercoll
.find
);
1332 This
->data
.u
.foldercoll
.find
= NULL
;
1337 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1339 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1340 TRACE("(%p)->(%p)\n", This
, pclone
);
1341 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1344 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1345 enumvariant_QueryInterface
,
1347 foldercoll_enumvariant_Release
,
1348 foldercoll_enumvariant_Next
,
1349 foldercoll_enumvariant_Skip
,
1350 foldercoll_enumvariant_Reset
,
1351 foldercoll_enumvariant_Clone
1354 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1356 struct enumvariant
*This
;
1360 This
= heap_alloc(sizeof(*This
));
1361 if (!This
) return E_OUTOFMEMORY
;
1363 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1365 This
->data
.u
.foldercoll
.find
= NULL
;
1366 This
->data
.u
.foldercoll
.coll
= collection
;
1367 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1369 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1374 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1376 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1377 ULONG ref
= InterlockedDecrement(&This
->ref
);
1379 TRACE("(%p)->(%d)\n", This
, ref
);
1383 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1384 FindClose(This
->data
.u
.filecoll
.find
);
1391 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1393 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1394 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1395 WIN32_FIND_DATAW data
;
1398 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1403 if (!celt
) return S_OK
;
1407 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1408 if (!handle
) return S_FALSE
;
1409 This
->data
.u
.filecoll
.find
= handle
;
1411 else if (!FindNextFileW(handle
, &data
))
1416 if (is_file_data(&data
))
1422 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1423 hr
= create_file(str
, &file
);
1425 if (FAILED(hr
)) return hr
;
1427 V_VT(&var
[count
]) = VT_DISPATCH
;
1428 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1429 if (++count
>= celt
) break;
1431 } while (FindNextFileW(handle
, &data
));
1436 return (count
< celt
) ? S_FALSE
: S_OK
;
1439 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1441 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1442 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1443 WIN32_FIND_DATAW data
;
1445 TRACE("(%p)->(%d)\n", This
, celt
);
1447 if (!celt
) return S_OK
;
1451 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1452 if (!handle
) return S_FALSE
;
1453 This
->data
.u
.filecoll
.find
= handle
;
1455 else if (!FindNextFileW(handle
, &data
))
1460 if (is_file_data(&data
))
1462 } while (celt
&& FindNextFileW(handle
, &data
));
1464 return celt
? S_FALSE
: S_OK
;
1467 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1469 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1471 TRACE("(%p)\n", This
);
1473 FindClose(This
->data
.u
.filecoll
.find
);
1474 This
->data
.u
.filecoll
.find
= NULL
;
1479 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1481 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1482 TRACE("(%p)->(%p)\n", This
, pclone
);
1483 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1486 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1487 enumvariant_QueryInterface
,
1489 filecoll_enumvariant_Release
,
1490 filecoll_enumvariant_Next
,
1491 filecoll_enumvariant_Skip
,
1492 filecoll_enumvariant_Reset
,
1493 filecoll_enumvariant_Clone
1496 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1498 struct enumvariant
*This
;
1502 This
= heap_alloc(sizeof(*This
));
1503 if (!This
) return E_OUTOFMEMORY
;
1505 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1507 This
->data
.u
.filecoll
.find
= NULL
;
1508 This
->data
.u
.filecoll
.coll
= collection
;
1509 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1511 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1516 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1518 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1519 ULONG ref
= InterlockedDecrement(&This
->ref
);
1521 TRACE("(%p)->(%d)\n", This
, ref
);
1525 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1532 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1534 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1537 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1539 penum
->data
.u
.drivecoll
.cur
= i
;
1546 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1548 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1551 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1556 if (!celt
) return S_OK
;
1558 while (find_next_drive(This
) == S_OK
)
1563 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1564 if (FAILED(hr
)) return hr
;
1566 V_VT(&var
[count
]) = VT_DISPATCH
;
1567 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1569 if (++count
>= celt
) break;
1575 return (count
< celt
) ? S_FALSE
: S_OK
;
1578 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1580 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1582 TRACE("(%p)->(%d)\n", This
, celt
);
1584 if (!celt
) return S_OK
;
1586 while (celt
&& find_next_drive(This
) == S_OK
)
1589 return celt
? S_FALSE
: S_OK
;
1592 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1594 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1596 TRACE("(%p)\n", This
);
1598 This
->data
.u
.drivecoll
.cur
= -1;
1602 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1604 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1605 TRACE("(%p)->(%p)\n", This
, pclone
);
1606 return create_drivecoll_enum(This
->data
.u
.drivecoll
.coll
, (IUnknown
**)pclone
);
1609 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1610 enumvariant_QueryInterface
,
1612 drivecoll_enumvariant_Release
,
1613 drivecoll_enumvariant_Next
,
1614 drivecoll_enumvariant_Skip
,
1615 drivecoll_enumvariant_Reset
,
1616 drivecoll_enumvariant_Clone
1619 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1621 struct enumvariant
*This
;
1625 This
= heap_alloc(sizeof(*This
));
1626 if (!This
) return E_OUTOFMEMORY
;
1628 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1630 This
->data
.u
.drivecoll
.coll
= collection
;
1631 This
->data
.u
.drivecoll
.cur
= -1;
1632 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1634 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1639 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1641 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1643 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1647 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1648 IsEqualIID( riid
, &IID_IDispatch
) ||
1649 IsEqualIID( riid
, &IID_IUnknown
))
1651 *obj
= &This
->IFolderCollection_iface
;
1653 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1655 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1658 return E_NOINTERFACE
;
1660 IUnknown_AddRef((IUnknown
*)*obj
);
1664 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1666 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1667 ULONG ref
= InterlockedIncrement(&This
->ref
);
1668 TRACE("(%p)->(%d)\n", This
, ref
);
1672 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1674 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1675 ULONG ref
= InterlockedDecrement(&This
->ref
);
1676 TRACE("(%p)->(%d)\n", This
, ref
);
1680 SysFreeString(This
->path
);
1687 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1689 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1690 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1695 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1696 LCID lcid
, ITypeInfo
**ppTInfo
)
1698 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1699 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1700 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1703 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1704 LPOLESTR
*rgszNames
, UINT cNames
,
1705 LCID lcid
, DISPID
*rgDispId
)
1707 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1708 ITypeInfo
*typeinfo
;
1711 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1713 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1716 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1717 ITypeInfo_Release(typeinfo
);
1723 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1724 REFIID riid
, LCID lcid
, WORD wFlags
,
1725 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1726 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1728 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1729 ITypeInfo
*typeinfo
;
1732 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1733 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1735 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1738 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1739 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1740 ITypeInfo_Release(typeinfo
);
1746 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1748 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1749 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1753 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1755 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1756 FIXME("(%p)->(%p): stub\n", This
, folder
);
1760 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1762 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1764 TRACE("(%p)->(%p)\n", This
, newenum
);
1769 return create_foldercoll_enum(This
, newenum
);
1772 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1774 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1775 static const WCHAR allW
[] = {'\\','*',0};
1776 WIN32_FIND_DATAW data
;
1777 WCHAR pathW
[MAX_PATH
];
1780 TRACE("(%p)->(%p)\n", This
, count
);
1787 lstrcpyW(pathW
, This
->path
);
1788 lstrcatW(pathW
, allW
);
1789 handle
= FindFirstFileW(pathW
, &data
);
1790 if (handle
== INVALID_HANDLE_VALUE
)
1791 return HRESULT_FROM_WIN32(GetLastError());
1795 if (is_dir_data(&data
))
1797 } while (FindNextFileW(handle
, &data
));
1803 static const IFolderCollectionVtbl foldercollvtbl
= {
1804 foldercoll_QueryInterface
,
1807 foldercoll_GetTypeInfoCount
,
1808 foldercoll_GetTypeInfo
,
1809 foldercoll_GetIDsOfNames
,
1812 foldercoll_get_Item
,
1813 foldercoll_get__NewEnum
,
1814 foldercoll_get_Count
1817 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1819 struct foldercollection
*This
;
1823 This
= heap_alloc(sizeof(struct foldercollection
));
1824 if (!This
) return E_OUTOFMEMORY
;
1826 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1828 This
->path
= SysAllocString(path
);
1832 return E_OUTOFMEMORY
;
1835 init_classinfo(&CLSID_Folders
, (IUnknown
*)&This
->IFolderCollection_iface
, &This
->classinfo
);
1836 *folders
= &This
->IFolderCollection_iface
;
1841 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1843 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1845 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1849 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1850 IsEqualIID( riid
, &IID_IDispatch
) ||
1851 IsEqualIID( riid
, &IID_IUnknown
))
1853 *obj
= &This
->IFileCollection_iface
;
1855 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1857 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1860 return E_NOINTERFACE
;
1862 IUnknown_AddRef((IUnknown
*)*obj
);
1866 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1868 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1869 ULONG ref
= InterlockedIncrement(&This
->ref
);
1870 TRACE("(%p)->(%d)\n", This
, ref
);
1874 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1876 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1877 ULONG ref
= InterlockedDecrement(&This
->ref
);
1878 TRACE("(%p)->(%d)\n", This
, ref
);
1882 SysFreeString(This
->path
);
1889 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1891 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1892 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1897 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1898 LCID lcid
, ITypeInfo
**ppTInfo
)
1900 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1901 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1902 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1905 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1906 LPOLESTR
*rgszNames
, UINT cNames
,
1907 LCID lcid
, DISPID
*rgDispId
)
1909 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1910 ITypeInfo
*typeinfo
;
1913 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1915 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1918 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1919 ITypeInfo_Release(typeinfo
);
1925 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1926 REFIID riid
, LCID lcid
, WORD wFlags
,
1927 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1928 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1930 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1931 ITypeInfo
*typeinfo
;
1934 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1935 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1937 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1940 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1941 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1942 ITypeInfo_Release(typeinfo
);
1948 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1950 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1951 FIXME("(%p)->(%p)\n", This
, file
);
1955 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1957 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1959 TRACE("(%p)->(%p)\n", This
, ppenum
);
1964 return create_filecoll_enum(This
, ppenum
);
1967 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1969 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1970 static const WCHAR allW
[] = {'\\','*',0};
1971 WIN32_FIND_DATAW data
;
1972 WCHAR pathW
[MAX_PATH
];
1975 TRACE("(%p)->(%p)\n", This
, count
);
1982 lstrcpyW(pathW
, This
->path
);
1983 lstrcatW(pathW
, allW
);
1984 handle
= FindFirstFileW(pathW
, &data
);
1985 if (handle
== INVALID_HANDLE_VALUE
)
1986 return HRESULT_FROM_WIN32(GetLastError());
1990 if (is_file_data(&data
))
1992 } while (FindNextFileW(handle
, &data
));
1998 static const IFileCollectionVtbl filecollectionvtbl
= {
1999 filecoll_QueryInterface
,
2002 filecoll_GetTypeInfoCount
,
2003 filecoll_GetTypeInfo
,
2004 filecoll_GetIDsOfNames
,
2007 filecoll_get__NewEnum
,
2011 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
2013 struct filecollection
*This
;
2017 This
= heap_alloc(sizeof(*This
));
2018 if (!This
) return E_OUTOFMEMORY
;
2020 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
2022 This
->path
= SysAllocString(path
);
2026 return E_OUTOFMEMORY
;
2029 init_classinfo(&CLSID_Files
, (IUnknown
*)&This
->IFileCollection_iface
, &This
->classinfo
);
2030 *files
= &This
->IFileCollection_iface
;
2034 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
2036 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2038 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2042 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
2043 IsEqualIID( riid
, &IID_IDispatch
) ||
2044 IsEqualIID( riid
, &IID_IUnknown
))
2046 *obj
= &This
->IDriveCollection_iface
;
2048 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2050 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2053 return E_NOINTERFACE
;
2055 IUnknown_AddRef((IUnknown
*)*obj
);
2059 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
2061 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2062 ULONG ref
= InterlockedIncrement(&This
->ref
);
2063 TRACE("(%p)->(%d)\n", This
, ref
);
2067 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
2069 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2070 ULONG ref
= InterlockedDecrement(&This
->ref
);
2071 TRACE("(%p)->(%d)\n", This
, ref
);
2079 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
2081 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2082 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2087 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
2088 LCID lcid
, ITypeInfo
**ppTInfo
)
2090 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2091 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2092 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
2095 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
2096 LPOLESTR
*rgszNames
, UINT cNames
,
2097 LCID lcid
, DISPID
*rgDispId
)
2099 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2100 ITypeInfo
*typeinfo
;
2103 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2105 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2108 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2109 ITypeInfo_Release(typeinfo
);
2115 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2116 REFIID riid
, LCID lcid
, WORD wFlags
,
2117 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2118 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2120 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2121 ITypeInfo
*typeinfo
;
2124 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2125 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2127 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2130 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2131 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2132 ITypeInfo_Release(typeinfo
);
2138 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2140 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2141 FIXME("(%p)->(%p): stub\n", This
, drive
);
2145 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2147 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2149 TRACE("(%p)->(%p)\n", This
, ppenum
);
2154 return create_drivecoll_enum(This
, ppenum
);
2157 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2159 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2161 TRACE("(%p)->(%p)\n", This
, count
);
2163 if (!count
) return E_POINTER
;
2165 *count
= This
->count
;
2169 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2170 drivecoll_QueryInterface
,
2173 drivecoll_GetTypeInfoCount
,
2174 drivecoll_GetTypeInfo
,
2175 drivecoll_GetIDsOfNames
,
2178 drivecoll_get__NewEnum
,
2182 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2184 struct drivecollection
*This
;
2189 This
= heap_alloc(sizeof(*This
));
2190 if (!This
) return E_OUTOFMEMORY
;
2192 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2194 This
->drives
= mask
= GetLogicalDrives();
2195 /* count set bits */
2196 for (This
->count
= 0; mask
; This
->count
++)
2199 init_classinfo(&CLSID_Drives
, (IUnknown
*)&This
->IDriveCollection_iface
, &This
->classinfo
);
2200 *drives
= &This
->IDriveCollection_iface
;
2204 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2206 struct folder
*This
= impl_from_IFolder(iface
);
2208 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2212 if (IsEqualIID( riid
, &IID_IFolder
) ||
2213 IsEqualIID( riid
, &IID_IDispatch
) ||
2214 IsEqualIID( riid
, &IID_IUnknown
))
2216 *obj
= &This
->IFolder_iface
;
2218 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2220 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2223 return E_NOINTERFACE
;
2225 IUnknown_AddRef((IUnknown
*)*obj
);
2229 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2231 struct folder
*This
= impl_from_IFolder(iface
);
2232 ULONG ref
= InterlockedIncrement(&This
->ref
);
2233 TRACE("(%p)->(%d)\n", This
, ref
);
2237 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2239 struct folder
*This
= impl_from_IFolder(iface
);
2240 ULONG ref
= InterlockedDecrement(&This
->ref
);
2241 TRACE("(%p)->(%d)\n", This
, ref
);
2245 SysFreeString(This
->path
);
2252 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2254 struct folder
*This
= impl_from_IFolder(iface
);
2255 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2260 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2261 LCID lcid
, ITypeInfo
**ppTInfo
)
2263 struct folder
*This
= impl_from_IFolder(iface
);
2264 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2265 return get_typeinfo(IFolder_tid
, ppTInfo
);
2268 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2269 LPOLESTR
*rgszNames
, UINT cNames
,
2270 LCID lcid
, DISPID
*rgDispId
)
2272 struct folder
*This
= impl_from_IFolder(iface
);
2273 ITypeInfo
*typeinfo
;
2276 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2278 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2281 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2282 ITypeInfo_Release(typeinfo
);
2288 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2289 REFIID riid
, LCID lcid
, WORD wFlags
,
2290 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2291 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2293 struct folder
*This
= impl_from_IFolder(iface
);
2294 ITypeInfo
*typeinfo
;
2297 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2298 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2300 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2303 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2304 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2305 ITypeInfo_Release(typeinfo
);
2311 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2313 struct folder
*This
= impl_from_IFolder(iface
);
2315 TRACE("(%p)->(%p)\n", This
, path
);
2320 *path
= SysAllocString(This
->path
);
2321 return *path
? S_OK
: E_OUTOFMEMORY
;
2324 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2326 struct folder
*This
= impl_from_IFolder(iface
);
2329 TRACE("(%p)->(%p)\n", This
, name
);
2336 ptr
= wcsrchr(This
->path
, '\\');
2339 *name
= SysAllocString(ptr
+1);
2340 TRACE("%s\n", debugstr_w(*name
));
2341 if (!*name
) return E_OUTOFMEMORY
;
2349 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2351 struct folder
*This
= impl_from_IFolder(iface
);
2352 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2356 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2358 struct folder
*This
= impl_from_IFolder(iface
);
2359 FIXME("(%p)->(%p): stub\n", This
, path
);
2363 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2365 struct folder
*This
= impl_from_IFolder(iface
);
2366 FIXME("(%p)->(%p): stub\n", This
, name
);
2370 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2372 struct folder
*This
= impl_from_IFolder(iface
);
2373 FIXME("(%p)->(%p): stub\n", This
, drive
);
2377 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2379 struct folder
*This
= impl_from_IFolder(iface
);
2380 FIXME("(%p)->(%p): stub\n", This
, parent
);
2384 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2386 struct folder
*This
= impl_from_IFolder(iface
);
2387 FIXME("(%p)->(%p): stub\n", This
, attr
);
2391 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2393 struct folder
*This
= impl_from_IFolder(iface
);
2394 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2398 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2400 struct folder
*This
= impl_from_IFolder(iface
);
2401 FIXME("(%p)->(%p): stub\n", This
, date
);
2405 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2407 struct folder
*This
= impl_from_IFolder(iface
);
2408 FIXME("(%p)->(%p): stub\n", This
, date
);
2412 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2414 struct folder
*This
= impl_from_IFolder(iface
);
2415 FIXME("(%p)->(%p): stub\n", This
, date
);
2419 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2421 struct folder
*This
= impl_from_IFolder(iface
);
2422 FIXME("(%p)->(%p): stub\n", This
, type
);
2426 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2428 struct folder
*This
= impl_from_IFolder(iface
);
2429 FIXME("(%p)->(%x): stub\n", This
, force
);
2433 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2435 struct folder
*This
= impl_from_IFolder(iface
);
2436 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2440 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2442 struct folder
*This
= impl_from_IFolder(iface
);
2443 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2447 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2449 struct folder
*This
= impl_from_IFolder(iface
);
2450 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2454 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2456 struct folder
*This
= impl_from_IFolder(iface
);
2457 FIXME("(%p)->(%p): stub\n", This
, size
);
2461 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2463 struct folder
*This
= impl_from_IFolder(iface
);
2465 TRACE("(%p)->(%p)\n", This
, folders
);
2470 return create_foldercoll(This
->path
, folders
);
2473 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2475 struct folder
*This
= impl_from_IFolder(iface
);
2477 TRACE("(%p)->(%p)\n", This
, files
);
2482 return create_filecoll(This
->path
, files
);
2485 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2486 VARIANT_BOOL unicode
, ITextStream
**stream
)
2488 struct folder
*This
= impl_from_IFolder(iface
);
2489 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2493 static const IFolderVtbl foldervtbl
= {
2494 folder_QueryInterface
,
2497 folder_GetTypeInfoCount
,
2499 folder_GetIDsOfNames
,
2504 folder_get_ShortPath
,
2505 folder_get_ShortName
,
2507 folder_get_ParentFolder
,
2508 folder_get_Attributes
,
2509 folder_put_Attributes
,
2510 folder_get_DateCreated
,
2511 folder_get_DateLastModified
,
2512 folder_get_DateLastAccessed
,
2517 folder_get_IsRootFolder
,
2519 folder_get_SubFolders
,
2521 folder_CreateTextFile
2524 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2526 struct folder
*This
;
2530 TRACE("%s\n", debugstr_w(path
));
2532 This
= heap_alloc(sizeof(struct folder
));
2533 if (!This
) return E_OUTOFMEMORY
;
2535 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2537 This
->path
= SysAllocString(path
);
2541 return E_OUTOFMEMORY
;
2544 init_classinfo(&CLSID_Folder
, (IUnknown
*)&This
->IFolder_iface
, &This
->classinfo
);
2545 *folder
= &This
->IFolder_iface
;
2550 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2552 struct file
*This
= impl_from_IFile(iface
);
2554 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2558 if (IsEqualIID(riid
, &IID_IFile
) ||
2559 IsEqualIID(riid
, &IID_IDispatch
) ||
2560 IsEqualIID(riid
, &IID_IUnknown
))
2562 *obj
= &This
->IFile_iface
;
2564 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2566 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2569 return E_NOINTERFACE
;
2571 IUnknown_AddRef((IUnknown
*)*obj
);
2575 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2577 struct file
*This
= impl_from_IFile(iface
);
2578 LONG ref
= InterlockedIncrement(&This
->ref
);
2580 TRACE("(%p) ref=%d\n", This
, ref
);
2585 static ULONG WINAPI
file_Release(IFile
*iface
)
2587 struct file
*This
= impl_from_IFile(iface
);
2588 LONG ref
= InterlockedDecrement(&This
->ref
);
2590 TRACE("(%p) ref=%d\n", This
, ref
);
2594 heap_free(This
->path
);
2601 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2603 struct file
*This
= impl_from_IFile(iface
);
2605 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2611 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2612 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2614 struct file
*This
= impl_from_IFile(iface
);
2616 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2618 return get_typeinfo(IFile_tid
, ppTInfo
);
2621 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2622 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2624 struct file
*This
= impl_from_IFile(iface
);
2625 ITypeInfo
*typeinfo
;
2628 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2629 rgszNames
, cNames
, lcid
, rgDispId
);
2631 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2633 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2634 ITypeInfo_Release(typeinfo
);
2639 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2641 struct file
*This
= impl_from_IFile(iface
);
2642 ITypeInfo
*typeinfo
;
2645 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2646 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2648 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2651 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2652 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2653 ITypeInfo_Release(typeinfo
);
2658 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2660 struct file
*This
= impl_from_IFile(iface
);
2662 TRACE("(%p)->(%p)\n", This
, path
);
2667 *path
= SysAllocString(This
->path
);
2669 return E_OUTOFMEMORY
;
2674 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2676 struct file
*This
= impl_from_IFile(iface
);
2679 TRACE("(%p)->(%p)\n", This
, name
);
2686 ptr
= wcsrchr(This
->path
, '\\');
2689 *name
= SysAllocString(ptr
+1);
2690 TRACE("%s\n", debugstr_w(*name
));
2691 if (!*name
) return E_OUTOFMEMORY
;
2699 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2701 struct file
*This
= impl_from_IFile(iface
);
2702 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2706 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2708 struct file
*This
= impl_from_IFile(iface
);
2709 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2713 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2715 struct file
*This
= impl_from_IFile(iface
);
2716 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2720 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2722 struct file
*This
= impl_from_IFile(iface
);
2723 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2727 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2729 struct file
*This
= impl_from_IFile(iface
);
2730 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2734 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2736 struct file
*This
= impl_from_IFile(iface
);
2739 TRACE("(%p)->(%p)\n", This
, pfa
);
2744 fa
= GetFileAttributesW(This
->path
);
2745 if(fa
== INVALID_FILE_ATTRIBUTES
)
2746 return create_error(GetLastError());
2748 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2749 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2750 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2754 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2756 struct file
*This
= impl_from_IFile(iface
);
2758 TRACE("(%p)->(%x)\n", This
, pfa
);
2760 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2763 static HRESULT
get_date_from_filetime(const FILETIME
*ft
, DATE
*date
)
2771 FileTimeToLocalFileTime(ft
, &ftlocal
);
2772 FileTimeToSystemTime(&ftlocal
, &st
);
2773 SystemTimeToVariantTime(&st
, date
);
2778 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2780 struct file
*This
= impl_from_IFile(iface
);
2781 FIXME("(%p)->(%p)\n", This
, pdate
);
2785 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*date
)
2787 struct file
*This
= impl_from_IFile(iface
);
2788 WIN32_FILE_ATTRIBUTE_DATA attrs
;
2790 TRACE("(%p)->(%p)\n", This
, date
);
2792 if (GetFileAttributesExW(This
->path
, GetFileExInfoStandard
, &attrs
))
2793 return get_date_from_filetime(&attrs
.ftLastWriteTime
, date
);
2798 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2800 struct file
*This
= impl_from_IFile(iface
);
2801 FIXME("(%p)->(%p)\n", This
, pdate
);
2805 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2807 struct file
*This
= impl_from_IFile(iface
);
2808 ULARGE_INTEGER size
;
2809 WIN32_FIND_DATAW fd
;
2812 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2817 f
= FindFirstFileW(This
->path
, &fd
);
2818 if(f
== INVALID_HANDLE_VALUE
)
2819 return create_error(GetLastError());
2822 size
.u
.LowPart
= fd
.nFileSizeLow
;
2823 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2825 return variant_from_largeint(&size
, pvarSize
);
2828 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2830 struct file
*This
= impl_from_IFile(iface
);
2831 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2835 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2837 struct file
*This
= impl_from_IFile(iface
);
2838 FIXME("(%p)->(%x)\n", This
, Force
);
2842 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2844 struct file
*This
= impl_from_IFile(iface
);
2845 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2849 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2851 struct file
*This
= impl_from_IFile(iface
);
2852 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2856 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2858 struct file
*This
= impl_from_IFile(iface
);
2860 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2862 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
, stream
);
2865 static const IFileVtbl file_vtbl
= {
2866 file_QueryInterface
,
2869 file_GetTypeInfoCount
,
2879 file_get_ParentFolder
,
2880 file_get_Attributes
,
2881 file_put_Attributes
,
2882 file_get_DateCreated
,
2883 file_get_DateLastModified
,
2884 file_get_DateLastAccessed
,
2890 file_OpenAsTextStream
2893 static HRESULT
create_file(BSTR path
, IFile
**file
)
2900 f
= heap_alloc(sizeof(struct file
));
2902 return E_OUTOFMEMORY
;
2904 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2907 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2913 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2916 return E_OUTOFMEMORY
;
2919 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2925 attrs
= GetFileAttributesW(f
->path
);
2926 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2927 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2930 return create_error(GetLastError());
2933 init_classinfo(&CLSID_File
, (IUnknown
*)&f
->IFile_iface
, &f
->classinfo
);
2934 *file
= &f
->IFile_iface
;
2938 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2940 struct filesystem
*This
= impl_from_IFileSystem3(iface
);
2942 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2944 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2945 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2946 IsEqualGUID( riid
, &IID_IDispatch
) ||
2947 IsEqualGUID( riid
, &IID_IUnknown
) )
2949 *ppvObject
= &This
->IFileSystem3_iface
;
2951 else if (IsEqualGUID( riid
, &IID_IProvideClassInfo
))
2953 *ppvObject
= &This
->classinfo
.IProvideClassInfo_iface
;
2955 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2957 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2959 return E_NOINTERFACE
;
2961 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2963 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2965 return E_NOINTERFACE
;
2969 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2970 return E_NOINTERFACE
;
2973 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2978 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2980 TRACE("%p\n", iface
);
2985 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2987 TRACE("%p\n", iface
);
2992 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2994 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
3000 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
3001 LCID lcid
, ITypeInfo
**ppTInfo
)
3003 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
3004 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
3007 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
3008 LPOLESTR
*rgszNames
, UINT cNames
,
3009 LCID lcid
, DISPID
*rgDispId
)
3011 ITypeInfo
*typeinfo
;
3014 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
3016 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
3019 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
3020 ITypeInfo_Release(typeinfo
);
3026 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
3027 REFIID riid
, LCID lcid
, WORD wFlags
,
3028 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
3029 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
3031 ITypeInfo
*typeinfo
;
3034 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
3035 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
3037 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
3040 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
3041 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
3042 ITypeInfo_Release(typeinfo
);
3048 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
3050 TRACE("%p %p\n", iface
, ppdrives
);
3051 return create_drivecoll(ppdrives
);
3054 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
3055 BSTR Name
, BSTR
*Result
)
3059 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
3061 if (!Result
) return E_POINTER
;
3065 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
3067 /* if both parts have backslashes strip one from Path */
3068 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
3072 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3075 lstrcpyW(ret
, Path
);
3077 lstrcatW(ret
, Name
);
3080 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
3082 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
3085 lstrcpyW(ret
, Path
);
3086 if (Path
[path_len
-1] != ':')
3088 lstrcatW(ret
, Name
);
3093 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3096 lstrcpyW(ret
, Path
);
3097 lstrcatW(ret
, Name
);
3101 else if (Path
|| Name
)
3102 ret
= SysAllocString(Path
? Path
: Name
);
3104 ret
= SysAllocStringLen(NULL
, 0);
3106 if (!ret
) return E_OUTOFMEMORY
;
3112 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
3114 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
3121 if (path
&& lstrlenW(path
) > 1 && path
[1] == ':')
3122 *drive
= SysAllocStringLen(path
, 2);
3127 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
3134 for(i
=len
-1; i
>=0; i
--)
3135 if(path
[i
]!='/' && path
[i
]!='\\')
3139 if(path
[i
]=='/' || path
[i
]=='\\')
3143 if(path
[i
]!='/' && path
[i
]!='\\')
3149 if(path
[i
]==':' && i
==1)
3154 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3159 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3164 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3166 *pbstrResult
= NULL
;
3170 *pbstrResult
= SysAllocStringLen(Path
, len
);
3172 return E_OUTOFMEMORY
;
3176 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3181 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3187 *pbstrResult
= NULL
;
3191 for(end
=lstrlenW(Path
)-1; end
>=0; end
--)
3192 if(Path
[end
]!='/' && Path
[end
]!='\\')
3195 for(i
=end
; i
>=0; i
--)
3196 if(Path
[i
]=='/' || Path
[i
]=='\\')
3200 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3201 *pbstrResult
= NULL
;
3205 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3207 return E_OUTOFMEMORY
;
3211 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3216 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3222 *pbstrResult
= NULL
;
3226 for(end
=lstrlenW(Path
)-1; end
>=0; end
--)
3227 if(Path
[end
]!='/' && Path
[end
]!='\\')
3230 for(i
=end
; i
>=0; i
--) {
3231 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3233 if(Path
[i
]=='/' || Path
[i
]=='\\')
3238 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3239 *pbstrResult
= NULL
;
3243 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3245 return E_OUTOFMEMORY
;
3249 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3254 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3257 len
= SysStringLen(path
);
3259 if (path
[len
-1] == '.') {
3260 *ext
= SysAllocString(&path
[len
]);
3262 return E_OUTOFMEMORY
;
3271 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3274 static const WCHAR cur_path
[] = {'.',0};
3276 WCHAR buf
[MAX_PATH
], ch
;
3278 DWORD i
, beg
, len
, exp_len
;
3279 WIN32_FIND_DATAW fdata
;
3282 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3292 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3296 buf
[0] = towupper(buf
[0]);
3297 if(len
>3 && buf
[len
-1] == '\\')
3300 for(beg
=3, i
=3; i
<=len
; i
++) {
3301 if(buf
[i
]!='\\' && buf
[i
])
3306 fh
= FindFirstFileW(buf
, &fdata
);
3307 if(fh
== INVALID_HANDLE_VALUE
)
3310 exp_len
= lstrlenW(fdata
.cFileName
);
3311 if(exp_len
== i
-beg
)
3312 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3318 *pbstrResult
= SysAllocString(buf
);
3320 return E_OUTOFMEMORY
;
3324 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3326 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3330 TRACE("%p %p\n", iface
, pbstrResult
);
3335 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3337 return E_OUTOFMEMORY
;
3339 if(!RtlGenRandom(&random
, sizeof(random
)))
3341 swprintf(*pbstrResult
, 12, fmt
, random
& 0xfffff);
3345 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3346 VARIANT_BOOL
*pfExists
)
3350 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3352 if (!pfExists
) return E_POINTER
;
3354 *pfExists
= VARIANT_FALSE
;
3355 len
= SysStringLen(DriveSpec
);
3358 driveletter
= towupper(DriveSpec
[0]);
3359 if (driveletter
>= 'A' && driveletter
<= 'Z'
3360 && (len
< 2 || DriveSpec
[1] == ':')
3361 && (len
< 3 || DriveSpec
[2] == '\\')) {
3362 const WCHAR root
[] = {driveletter
, ':', '\\', 0};
3363 UINT drivetype
= GetDriveTypeW(root
);
3364 *pfExists
= drivetype
!= DRIVE_NO_ROOT_DIR
&& drivetype
!= DRIVE_UNKNOWN
? VARIANT_TRUE
: VARIANT_FALSE
;
3371 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3374 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3376 if (!ret
) return E_POINTER
;
3378 attrs
= GetFileAttributesW(path
);
3379 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3383 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3386 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3388 if (!ret
) return E_POINTER
;
3390 attrs
= GetFileAttributesW(path
);
3391 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3396 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3402 VARIANT_BOOL drive_exists
;
3404 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3411 /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3412 len
= SysStringLen(DriveSpec
);
3414 return E_INVALIDARG
;
3415 else if (len
<= 3) {
3416 driveletter
= towupper(DriveSpec
[0]);
3417 if (driveletter
< 'A' || driveletter
> 'Z'
3418 || (len
>= 2 && DriveSpec
[1] != ':')
3419 || (len
== 3 && DriveSpec
[2] != '\\'))
3420 return E_INVALIDARG
;
3421 hr
= IFileSystem3_DriveExists(iface
, DriveSpec
, &drive_exists
);
3424 if (drive_exists
== VARIANT_FALSE
)
3425 return CTL_E_DEVICEUNAVAILABLE
;
3426 return create_drive(driveletter
, ppdrive
);
3428 if (DriveSpec
[0] != '\\' || DriveSpec
[1] != '\\')
3429 return E_INVALIDARG
;
3430 FIXME("%s not implemented yet\n", debugstr_w(DriveSpec
));
3435 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3438 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3443 return E_INVALIDARG
;
3445 return create_file(FilePath
, ppfile
);
3448 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3453 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3460 return E_INVALIDARG
;
3462 attrs
= GetFileAttributesW(FolderPath
);
3463 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3464 return CTL_E_PATHNOTFOUND
;
3466 return create_folder(FolderPath
, folder
);
3469 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3470 SpecialFolderConst SpecialFolder
,
3473 WCHAR pathW
[MAX_PATH
];
3476 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3483 switch (SpecialFolder
)
3486 ret
= GetWindowsDirectoryW(pathW
, ARRAY_SIZE(pathW
));
3489 ret
= GetSystemDirectoryW(pathW
, ARRAY_SIZE(pathW
));
3491 case TemporaryFolder
:
3492 ret
= GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
3493 /* we don't want trailing backslash */
3494 if (ret
&& pathW
[ret
-1] == '\\')
3498 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3499 return E_INVALIDARG
;
3503 return HRESULT_FROM_WIN32(GetLastError());
3505 return create_folder(pathW
, folder
);
3508 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3510 WCHAR path
[MAX_PATH
];
3511 DWORD len
, name_len
;
3512 WIN32_FIND_DATAW ffd
;
3515 f
= FindFirstFileW(file
, &ffd
);
3516 if(f
== INVALID_HANDLE_VALUE
)
3517 return create_error(GetLastError());
3519 len
= get_parent_folder_name(file
, file_len
);
3520 if(len
+1 >= MAX_PATH
) {
3525 memcpy(path
, file
, len
*sizeof(WCHAR
));
3530 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3533 name_len
= lstrlenW(ffd
.cFileName
);
3534 if(len
+name_len
+1 >= MAX_PATH
) {
3538 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3540 TRACE("deleting %s\n", debugstr_w(path
));
3542 if(!DeleteFileW(path
)) {
3543 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3544 || !DeleteFileW(path
)) {
3546 return create_error(GetLastError());
3549 } while(FindNextFileW(f
, &ffd
));
3555 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3558 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3563 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3566 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3568 WCHAR path
[MAX_PATH
];
3569 DWORD len
, name_len
;
3570 WIN32_FIND_DATAW ffd
;
3574 f
= FindFirstFileW(folder
, &ffd
);
3575 if(f
== INVALID_HANDLE_VALUE
)
3576 return create_error(GetLastError());
3578 len
= get_parent_folder_name(folder
, folder_len
);
3579 if(len
+1 >= MAX_PATH
) {
3584 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3589 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3591 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3592 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3595 name_len
= lstrlenW(ffd
.cFileName
);
3596 if(len
+name_len
+3 >= MAX_PATH
) {
3600 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3601 path
[len
+name_len
] = '\\';
3602 path
[len
+name_len
+1] = '*';
3603 path
[len
+name_len
+2] = 0;
3605 hr
= delete_file(path
, len
+name_len
+2, force
);
3611 hr
= delete_folder(path
, len
+name_len
+2, force
);
3617 path
[len
+name_len
] = 0;
3618 TRACE("deleting %s\n", debugstr_w(path
));
3620 if(!RemoveDirectoryW(path
)) {
3622 return create_error(GetLastError());
3624 } while(FindNextFileW(f
, &ffd
));
3630 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3633 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3638 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3641 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR source
, BSTR destination
)
3643 TRACE("%p %s %s\n", iface
, debugstr_w(source
), debugstr_w(destination
));
3645 return MoveFileW(source
, destination
) ? S_OK
: create_error(GetLastError());
3648 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3651 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3656 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3657 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3660 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3661 DWORD src_len
, dst_len
, name_len
;
3662 WIN32_FIND_DATAW ffd
;
3666 if(!source
[0] || !destination
[0])
3667 return E_INVALIDARG
;
3669 attrs
= GetFileAttributesW(destination
);
3670 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3671 attrs
= GetFileAttributesW(source
);
3672 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3673 return create_error(GetLastError());
3674 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3675 return CTL_E_FILENOTFOUND
;
3677 if(!CopyFileW(source
, destination
, !overwrite
))
3678 return create_error(GetLastError());
3682 f
= FindFirstFileW(source
, &ffd
);
3683 if(f
== INVALID_HANDLE_VALUE
)
3684 return CTL_E_FILENOTFOUND
;
3686 src_len
= get_parent_folder_name(source
, source_len
);
3687 if(src_len
+1 >= MAX_PATH
) {
3692 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3693 src_path
[src_len
++] = '\\';
3696 dst_len
= destination_len
;
3697 if(dst_len
+1 >= MAX_PATH
) {
3701 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3702 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3703 dst_path
[dst_len
++] = '\\';
3705 hr
= CTL_E_FILENOTFOUND
;
3707 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3710 name_len
= lstrlenW(ffd
.cFileName
);
3711 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3715 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3716 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3718 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3720 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3722 return create_error(GetLastError());
3726 } while(FindNextFileW(f
, &ffd
));
3732 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3733 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3735 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3737 if(!Source
|| !Destination
)
3740 return copy_file(Source
, SysStringLen(Source
), Destination
,
3741 SysStringLen(Destination
), OverWriteFiles
);
3744 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3745 DWORD destination_len
, VARIANT_BOOL overwrite
)
3747 DWORD tmp
, src_len
, dst_len
, name_len
;
3748 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3749 WIN32_FIND_DATAW ffd
;
3752 BOOL copied
= FALSE
;
3754 if(!source
[0] || !destination
[0])
3755 return E_INVALIDARG
;
3757 dst_len
= destination_len
;
3758 if(dst_len
+1 >= MAX_PATH
)
3760 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3762 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3763 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3764 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3765 if(!CreateDirectoryW(dst
, NULL
)) {
3766 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3767 tmp
= GetFileAttributesW(dst
);
3768 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3769 return CTL_E_FILEALREADYEXISTS
;
3771 return create_error(GetLastError());
3776 src_len
= source_len
;
3777 if(src_len
+2 >= MAX_PATH
)
3779 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3780 src
[src_len
++] = '\\';
3784 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3785 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3786 return create_error(GetLastError());
3788 f
= FindFirstFileW(src
, &ffd
);
3790 src_len
= get_parent_folder_name(source
, source_len
);
3791 if(src_len
+2 >= MAX_PATH
)
3793 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3795 src
[src_len
++] = '\\';
3797 f
= FindFirstFileW(source
, &ffd
);
3799 if(f
== INVALID_HANDLE_VALUE
)
3800 return CTL_E_PATHNOTFOUND
;
3802 dst
[dst_len
++] = '\\';
3806 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3808 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3809 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3812 name_len
= lstrlenW(ffd
.cFileName
);
3813 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3817 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3818 dst
[dst_len
+name_len
] = 0;
3819 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3820 src
[src_len
+name_len
] = '\\';
3821 src
[src_len
+name_len
+1] = '*';
3822 src
[src_len
+name_len
+2] = 0;
3824 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3826 if(!CreateDirectoryW(dst
, NULL
)) {
3827 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3828 tmp
= GetFileAttributesW(dst
);
3829 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3831 return CTL_E_FILEALREADYEXISTS
;
3836 return create_error(GetLastError());
3840 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3841 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3846 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3847 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3851 } while(FindNextFileW(f
, &ffd
));
3854 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3857 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3858 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3860 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3862 if(!Source
|| !Destination
)
3865 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3866 SysStringLen(Destination
), OverWriteFiles
);
3869 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3874 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3876 ret
= CreateDirectoryW(path
, NULL
);
3880 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3881 return HRESULT_FROM_WIN32(GetLastError());
3884 return create_folder(path
, folder
);
3887 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3888 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3889 ITextStream
**stream
)
3893 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3895 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3896 return create_textstream(filename
, disposition
, ForWriting
, unicode
? TristateTrue
: TristateFalse
, stream
);
3899 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3900 IOMode mode
, VARIANT_BOOL create
,
3901 Tristate format
, ITextStream
**stream
)
3905 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3907 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3908 return create_textstream(filename
, disposition
, mode
, format
, stream
);
3911 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3912 StandardStreamTypes StandardStreamType
,
3913 VARIANT_BOOL Unicode
,
3916 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3921 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3923 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3927 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3928 a
= (WORD
)( version
>> 48);
3929 b
= (WORD
)((version
>> 32) & 0xffff);
3930 c
= (WORD
)((version
>> 16) & 0xffff);
3931 d
= (WORD
)( version
& 0xffff);
3933 swprintf(ver
, 30, fmtW
, a
, b
, c
, d
);
3936 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3938 static const WCHAR rootW
[] = {'\\',0};
3939 VS_FIXEDFILEINFO
*info
;
3945 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3947 len
= GetFileVersionInfoSizeW(name
, NULL
);
3949 return HRESULT_FROM_WIN32(GetLastError());
3951 ptr
= heap_alloc(len
);
3952 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3955 return HRESULT_FROM_WIN32(GetLastError());
3958 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3962 return HRESULT_FROM_WIN32(GetLastError());
3965 get_versionstring(info
, ver
);
3968 *version
= SysAllocString(ver
);
3969 TRACE("version=%s\n", debugstr_w(ver
));
3974 static const struct IFileSystem3Vtbl filesys_vtbl
=
3976 filesys_QueryInterface
,
3979 filesys_GetTypeInfoCount
,
3980 filesys_GetTypeInfo
,
3981 filesys_GetIDsOfNames
,
3985 filesys_GetDriveName
,
3986 filesys_GetParentFolderName
,
3987 filesys_GetFileName
,
3988 filesys_GetBaseName
,
3989 filesys_GetExtensionName
,
3990 filesys_GetAbsolutePathName
,
3991 filesys_GetTempName
,
3992 filesys_DriveExists
,
3994 filesys_FolderExists
,
3998 filesys_GetSpecialFolder
,
4000 filesys_DeleteFolder
,
4005 filesys_CreateFolder
,
4006 filesys_CreateTextFile
,
4007 filesys_OpenTextFile
,
4008 filesys_GetStandardStream
,
4009 filesys_GetFileVersion
4012 static struct filesystem filesystem
;
4014 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
4016 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
4018 filesystem
.IFileSystem3_iface
.lpVtbl
= &filesys_vtbl
;
4019 init_classinfo(&CLSID_FileSystemObject
, (IUnknown
*)&filesystem
.IFileSystem3_iface
, &filesystem
.classinfo
);
4020 return IFileSystem3_QueryInterface(&filesystem
.IFileSystem3_iface
, riid
, ppv
);