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
32 #include "scrrun_private.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.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
;
137 static inline struct filesystem
*impl_from_IFileSystem3(IFileSystem3
*iface
)
139 return CONTAINING_RECORD(iface
, struct filesystem
, IFileSystem3_iface
);
142 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
144 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
147 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
149 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
152 static inline struct file
*impl_from_IFile(IFile
*iface
)
154 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
157 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
159 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
162 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
164 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
167 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
169 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
172 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
174 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
177 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
179 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
182 static inline HRESULT
create_error(DWORD err
)
185 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
186 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
187 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
188 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
189 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
191 FIXME("Unsupported error code: %d\n", err
);
196 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
197 static HRESULT
create_file(BSTR
, IFile
**);
198 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
199 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
201 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
203 static const WCHAR dotdotW
[] = {'.','.',0};
204 static const WCHAR dotW
[] = {'.',0};
206 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
207 strcmpW(data
->cFileName
, dotdotW
) &&
208 strcmpW(data
->cFileName
, dotW
);
211 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
213 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
216 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
218 int len
= SysStringLen(path
);
219 WCHAR buffW
[MAX_PATH
];
221 strcpyW(buffW
, path
);
222 if (path
[len
-1] != '\\')
224 strcatW(buffW
, data
->cFileName
);
226 return SysAllocString(buffW
);
229 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
232 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
234 return This
->mode
== ForReading
;
237 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
239 struct textstream
*This
= impl_from_ITextStream(iface
);
241 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
243 if (IsEqualIID(riid
, &IID_ITextStream
) ||
244 IsEqualIID(riid
, &IID_IDispatch
) ||
245 IsEqualIID(riid
, &IID_IUnknown
))
247 *obj
= &This
->ITextStream_iface
;
249 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
251 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
254 return E_NOINTERFACE
;
256 IUnknown_AddRef((IUnknown
*)*obj
);
260 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
262 struct textstream
*This
= impl_from_ITextStream(iface
);
263 ULONG ref
= InterlockedIncrement(&This
->ref
);
264 TRACE("(%p)->(%d)\n", This
, ref
);
268 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
270 struct textstream
*This
= impl_from_ITextStream(iface
);
271 ULONG ref
= InterlockedDecrement(&This
->ref
);
272 TRACE("(%p)->(%d)\n", This
, ref
);
276 CloseHandle(This
->file
);
283 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
285 struct textstream
*This
= impl_from_ITextStream(iface
);
286 TRACE("(%p)->(%p)\n", This
, pctinfo
);
291 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
292 LCID lcid
, ITypeInfo
**ppTInfo
)
294 struct textstream
*This
= impl_from_ITextStream(iface
);
295 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
296 return get_typeinfo(ITextStream_tid
, ppTInfo
);
299 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
300 LPOLESTR
*rgszNames
, UINT cNames
,
301 LCID lcid
, DISPID
*rgDispId
)
303 struct textstream
*This
= impl_from_ITextStream(iface
);
307 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
309 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
312 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
313 ITypeInfo_Release(typeinfo
);
319 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
320 REFIID riid
, LCID lcid
, WORD wFlags
,
321 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
322 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
324 struct textstream
*This
= impl_from_ITextStream(iface
);
328 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
329 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
331 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
334 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
335 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
336 ITypeInfo_Release(typeinfo
);
342 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
344 struct textstream
*This
= impl_from_ITextStream(iface
);
345 FIXME("(%p)->(%p): stub\n", This
, line
);
349 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
351 struct textstream
*This
= impl_from_ITextStream(iface
);
352 FIXME("(%p)->(%p): stub\n", This
, column
);
356 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
358 struct textstream
*This
= impl_from_ITextStream(iface
);
359 LARGE_INTEGER pos
, dist
;
361 TRACE("(%p)->(%p)\n", This
, eos
);
366 if (textstream_check_iomode(This
, IORead
)) {
368 return CTL_E_BADFILEMODE
;
372 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
375 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? 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
);
387 Reads 'toread' bytes from a file, converts if needed
388 BOM is skipped if 'bof' is set.
390 static HRESULT
textstream_read(struct textstream
*stream
, LONG toread
, BOOL bof
, BSTR
*text
)
398 *text
= SysAllocStringLen(NULL
, 0);
399 return *text
? S_FALSE
: E_OUTOFMEMORY
;
402 if (toread
< sizeof(WCHAR
))
403 return CTL_E_ENDOFFILE
;
405 buff
= heap_alloc(toread
);
407 return E_OUTOFMEMORY
;
409 ret
= ReadFile(stream
->file
, buff
, toread
, &read
, NULL
);
410 if (!ret
|| toread
!= read
) {
411 WARN("failed to read from file %d, %d, error %d\n", read
, toread
, GetLastError());
416 if (stream
->unicode
) {
420 if (bof
&& *(WCHAR
*)buff
== utf16bom
) {
421 read
-= sizeof(WCHAR
);
425 *text
= SysAllocStringLen(read
? (WCHAR
*)&buff
[i
] : NULL
, read
/sizeof(WCHAR
));
426 if (!*text
) hr
= E_OUTOFMEMORY
;
429 INT len
= MultiByteToWideChar(CP_ACP
, 0, buff
, read
, NULL
, 0);
430 *text
= SysAllocStringLen(NULL
, len
);
432 MultiByteToWideChar(CP_ACP
, 0, buff
, read
, *text
, len
);
441 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
443 struct textstream
*This
= impl_from_ITextStream(iface
);
444 LARGE_INTEGER start
, end
, dist
;
448 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
455 return len
== 0 ? S_OK
: E_INVALIDARG
;
457 if (textstream_check_iomode(This
, IORead
))
458 return CTL_E_BADFILEMODE
;
460 if (!This
->first_read
) {
464 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
468 if (eos
== VARIANT_TRUE
)
469 return CTL_E_ENDOFFILE
;
472 /* read everything from current position */
474 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
475 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
476 toread
= end
.QuadPart
- start
.QuadPart
;
478 dist
.QuadPart
= start
.QuadPart
;
479 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
481 This
->first_read
= FALSE
;
482 if (This
->unicode
) len
*= sizeof(WCHAR
);
484 hr
= textstream_read(This
, min(toread
, len
), start
.QuadPart
== 0, text
);
488 return toread
<= len
? S_FALSE
: S_OK
;
491 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
493 struct textstream
*This
= impl_from_ITextStream(iface
);
497 FIXME("(%p)->(%p): stub\n", This
, text
);
503 if (textstream_check_iomode(This
, IORead
))
504 return CTL_E_BADFILEMODE
;
507 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
511 if (eos
== VARIANT_TRUE
)
512 return CTL_E_ENDOFFILE
;
517 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
519 struct textstream
*This
= impl_from_ITextStream(iface
);
520 LARGE_INTEGER start
, end
, dist
;
524 TRACE("(%p)->(%p)\n", This
, text
);
530 if (textstream_check_iomode(This
, IORead
))
531 return CTL_E_BADFILEMODE
;
533 if (!This
->first_read
) {
537 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
541 if (eos
== VARIANT_TRUE
)
542 return CTL_E_ENDOFFILE
;
545 /* read everything from current position */
547 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
548 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
549 toread
= end
.QuadPart
- start
.QuadPart
;
551 dist
.QuadPart
= start
.QuadPart
;
552 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
554 This
->first_read
= FALSE
;
556 hr
= textstream_read(This
, toread
, start
.QuadPart
== 0, text
);
557 return FAILED(hr
) ? hr
: S_FALSE
;
560 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
565 if (stream
->unicode
) {
566 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
567 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
569 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
573 buffA
= heap_alloc(len
);
575 return E_OUTOFMEMORY
;
577 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
578 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
579 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
585 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
587 struct textstream
*This
= impl_from_ITextStream(iface
);
589 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
591 if (textstream_check_iomode(This
, IOWrite
))
592 return CTL_E_BADFILEMODE
;
594 return textstream_writestr(This
, text
);
597 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
599 static const WCHAR crlfW
[] = {'\r','\n'};
600 static const char crlfA
[] = {'\r','\n'};
601 DWORD written
= 0, len
;
605 if (stream
->unicode
) {
614 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
615 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
618 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
620 struct textstream
*This
= impl_from_ITextStream(iface
);
623 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
625 if (textstream_check_iomode(This
, IOWrite
))
626 return CTL_E_BADFILEMODE
;
628 hr
= textstream_writestr(This
, text
);
630 hr
= textstream_writecrlf(This
);
634 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
636 struct textstream
*This
= impl_from_ITextStream(iface
);
637 FIXME("(%p)->(%d): stub\n", This
, lines
);
641 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
643 struct textstream
*This
= impl_from_ITextStream(iface
);
644 FIXME("(%p)->(%d): stub\n", This
, count
);
648 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
650 struct textstream
*This
= impl_from_ITextStream(iface
);
651 FIXME("(%p): stub\n", This
);
655 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
657 struct textstream
*This
= impl_from_ITextStream(iface
);
660 TRACE("(%p)\n", This
);
662 if(!CloseHandle(This
->file
))
670 static const ITextStreamVtbl textstreamvtbl
= {
671 textstream_QueryInterface
,
674 textstream_GetTypeInfoCount
,
675 textstream_GetTypeInfo
,
676 textstream_GetIDsOfNames
,
679 textstream_get_Column
,
680 textstream_get_AtEndOfStream
,
681 textstream_get_AtEndOfLine
,
686 textstream_WriteLine
,
687 textstream_WriteBlankLines
,
693 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
695 struct textstream
*stream
;
698 /* map access mode */
702 access
= GENERIC_READ
;
705 access
= GENERIC_WRITE
;
708 access
= FILE_APPEND_DATA
;
714 stream
= heap_alloc(sizeof(struct textstream
));
715 if (!stream
) return E_OUTOFMEMORY
;
717 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
720 stream
->unicode
= unicode
;
721 stream
->first_read
= TRUE
;
723 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
724 if (stream
->file
== INVALID_HANDLE_VALUE
)
726 HRESULT hr
= create_error(GetLastError());
731 if (mode
== ForReading
)
732 GetFileSizeEx(stream
->file
, &stream
->size
);
734 stream
->size
.QuadPart
= 0;
736 /* Write Unicode BOM */
737 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
739 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
740 if (!ret
|| written
!= sizeof(utf16bom
)) {
741 ITextStream_Release(&stream
->ITextStream_iface
);
742 return create_error(GetLastError());
746 init_classinfo(&CLSID_TextStream
, (IUnknown
*)&stream
->ITextStream_iface
, &stream
->classinfo
);
747 *ret
= &stream
->ITextStream_iface
;
751 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
753 struct drive
*This
= impl_from_IDrive(iface
);
755 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
759 if (IsEqualIID( riid
, &IID_IDrive
) ||
760 IsEqualIID( riid
, &IID_IDispatch
) ||
761 IsEqualIID( riid
, &IID_IUnknown
))
763 *obj
= &This
->IDrive_iface
;
765 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
767 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
770 return E_NOINTERFACE
;
772 IUnknown_AddRef((IUnknown
*)*obj
);
776 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
778 struct drive
*This
= impl_from_IDrive(iface
);
779 ULONG ref
= InterlockedIncrement(&This
->ref
);
780 TRACE("(%p)->(%d)\n", This
, ref
);
784 static ULONG WINAPI
drive_Release(IDrive
*iface
)
786 struct drive
*This
= impl_from_IDrive(iface
);
787 ULONG ref
= InterlockedDecrement(&This
->ref
);
788 TRACE("(%p)->(%d)\n", This
, ref
);
792 SysFreeString(This
->root
);
799 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
801 struct drive
*This
= impl_from_IDrive(iface
);
802 TRACE("(%p)->(%p)\n", This
, pctinfo
);
807 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
808 LCID lcid
, ITypeInfo
**ppTInfo
)
810 struct drive
*This
= impl_from_IDrive(iface
);
811 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
812 return get_typeinfo(IDrive_tid
, ppTInfo
);
815 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
816 LPOLESTR
*rgszNames
, UINT cNames
,
817 LCID lcid
, DISPID
*rgDispId
)
819 struct drive
*This
= impl_from_IDrive(iface
);
823 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
825 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
828 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
829 ITypeInfo_Release(typeinfo
);
835 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
836 REFIID riid
, LCID lcid
, WORD wFlags
,
837 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
838 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
840 struct drive
*This
= impl_from_IDrive(iface
);
844 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
845 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
847 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
850 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
851 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
852 ITypeInfo_Release(typeinfo
);
858 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
860 struct drive
*This
= impl_from_IDrive(iface
);
861 FIXME("(%p)->(%p): stub\n", This
, path
);
865 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
867 struct drive
*This
= impl_from_IDrive(iface
);
869 TRACE("(%p)->(%p)\n", This
, letter
);
874 *letter
= SysAllocStringLen(This
->root
, 1);
876 return E_OUTOFMEMORY
;
881 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
883 struct drive
*This
= impl_from_IDrive(iface
);
884 FIXME("(%p)->(%p): stub\n", This
, share_name
);
888 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
890 struct drive
*This
= impl_from_IDrive(iface
);
892 TRACE("(%p)->(%p)\n", This
, type
);
894 switch (GetDriveTypeW(This
->root
))
896 case DRIVE_REMOVABLE
:
919 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
921 struct drive
*This
= impl_from_IDrive(iface
);
922 FIXME("(%p)->(%p): stub\n", This
, folder
);
926 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
930 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
933 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
938 V_I4(v
) = src
->u
.LowPart
;
944 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
946 struct drive
*This
= impl_from_IDrive(iface
);
947 ULARGE_INTEGER avail
;
949 TRACE("(%p)->(%p)\n", This
, v
);
954 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
957 return variant_from_largeint(&avail
, v
);
960 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
962 struct drive
*This
= impl_from_IDrive(iface
);
963 ULARGE_INTEGER freespace
;
965 TRACE("(%p)->(%p)\n", This
, v
);
970 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
973 return variant_from_largeint(&freespace
, v
);
976 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
978 struct drive
*This
= impl_from_IDrive(iface
);
979 ULARGE_INTEGER total
;
981 TRACE("(%p)->(%p)\n", This
, v
);
986 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
989 return variant_from_largeint(&total
, v
);
992 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
994 struct drive
*This
= impl_from_IDrive(iface
);
995 WCHAR nameW
[MAX_PATH
+1];
998 TRACE("(%p)->(%p)\n", This
, name
);
1004 ret
= GetVolumeInformationW(This
->root
, nameW
, ARRAY_SIZE(nameW
), NULL
, NULL
, NULL
, NULL
, 0);
1006 *name
= SysAllocString(nameW
);
1007 return ret
? S_OK
: E_FAIL
;
1010 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
1012 struct drive
*This
= impl_from_IDrive(iface
);
1013 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1017 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
1019 struct drive
*This
= impl_from_IDrive(iface
);
1020 WCHAR nameW
[MAX_PATH
+1];
1023 TRACE("(%p)->(%p)\n", This
, fs
);
1029 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, ARRAY_SIZE(nameW
));
1031 *fs
= SysAllocString(nameW
);
1032 return ret
? S_OK
: E_FAIL
;
1035 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
1037 struct drive
*This
= impl_from_IDrive(iface
);
1040 TRACE("(%p)->(%p)\n", This
, serial
);
1045 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1046 return ret
? S_OK
: E_FAIL
;
1049 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1051 struct drive
*This
= impl_from_IDrive(iface
);
1052 ULARGE_INTEGER freespace
;
1055 TRACE("(%p)->(%p)\n", This
, ready
);
1060 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1061 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1065 static const IDriveVtbl drivevtbl
= {
1066 drive_QueryInterface
,
1069 drive_GetTypeInfoCount
,
1071 drive_GetIDsOfNames
,
1074 drive_get_DriveLetter
,
1075 drive_get_ShareName
,
1076 drive_get_DriveType
,
1077 drive_get_RootFolder
,
1078 drive_get_AvailableSpace
,
1079 drive_get_FreeSpace
,
1080 drive_get_TotalSize
,
1081 drive_get_VolumeName
,
1082 drive_put_VolumeName
,
1083 drive_get_FileSystem
,
1084 drive_get_SerialNumber
,
1088 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1094 This
= heap_alloc(sizeof(*This
));
1095 if (!This
) return E_OUTOFMEMORY
;
1097 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1099 This
->root
= SysAllocStringLen(NULL
, 3);
1103 return E_OUTOFMEMORY
;
1105 This
->root
[0] = letter
;
1106 This
->root
[1] = ':';
1107 This
->root
[2] = '\\';
1110 init_classinfo(&CLSID_Drive
, (IUnknown
*)&This
->IDrive_iface
, &This
->classinfo
);
1111 *drive
= &This
->IDrive_iface
;
1115 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1117 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1119 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1123 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1124 IsEqualIID( riid
, &IID_IUnknown
))
1127 IEnumVARIANT_AddRef(iface
);
1130 return E_NOINTERFACE
;
1135 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1137 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1138 ULONG ref
= InterlockedIncrement(&This
->ref
);
1139 TRACE("(%p)->(%d)\n", This
, ref
);
1143 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1145 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1146 ULONG ref
= InterlockedDecrement(&This
->ref
);
1148 TRACE("(%p)->(%d)\n", This
, ref
);
1152 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1153 FindClose(This
->data
.u
.foldercoll
.find
);
1160 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1162 static const WCHAR allW
[] = {'*',0};
1163 WCHAR pathW
[MAX_PATH
];
1167 strcpyW(pathW
, path
);
1168 len
= strlenW(pathW
);
1169 if (len
&& pathW
[len
-1] != '\\')
1170 strcatW(pathW
, bsW
);
1171 strcatW(pathW
, allW
);
1172 handle
= FindFirstFileW(pathW
, data
);
1173 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1175 /* find first dir/file */
1178 if (file
? is_file_data(data
) : is_dir_data(data
))
1181 if (!FindNextFileW(handle
, data
))
1190 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1192 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1193 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1194 WIN32_FIND_DATAW data
;
1197 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1202 if (!celt
) return S_OK
;
1206 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1207 if (!handle
) return S_FALSE
;
1209 This
->data
.u
.foldercoll
.find
= handle
;
1213 if (!FindNextFileW(handle
, &data
))
1219 if (is_dir_data(&data
))
1225 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1226 hr
= create_folder(str
, &folder
);
1228 if (FAILED(hr
)) return hr
;
1230 V_VT(&var
[count
]) = VT_DISPATCH
;
1231 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1234 if (count
>= celt
) break;
1236 } while (FindNextFileW(handle
, &data
));
1241 return (count
< celt
) ? S_FALSE
: S_OK
;
1244 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1246 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1247 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1248 WIN32_FIND_DATAW data
;
1250 TRACE("(%p)->(%d)\n", This
, celt
);
1252 if (!celt
) return S_OK
;
1256 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1257 if (!handle
) return S_FALSE
;
1259 This
->data
.u
.foldercoll
.find
= handle
;
1263 if (!FindNextFileW(handle
, &data
))
1269 if (is_dir_data(&data
))
1273 } while (FindNextFileW(handle
, &data
));
1275 return celt
? S_FALSE
: S_OK
;
1278 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1280 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1282 TRACE("(%p)\n", This
);
1284 FindClose(This
->data
.u
.foldercoll
.find
);
1285 This
->data
.u
.foldercoll
.find
= NULL
;
1290 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1292 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1293 TRACE("(%p)->(%p)\n", This
, pclone
);
1294 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1297 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1298 enumvariant_QueryInterface
,
1300 foldercoll_enumvariant_Release
,
1301 foldercoll_enumvariant_Next
,
1302 foldercoll_enumvariant_Skip
,
1303 foldercoll_enumvariant_Reset
,
1304 foldercoll_enumvariant_Clone
1307 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1309 struct enumvariant
*This
;
1313 This
= heap_alloc(sizeof(*This
));
1314 if (!This
) return E_OUTOFMEMORY
;
1316 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1318 This
->data
.u
.foldercoll
.find
= NULL
;
1319 This
->data
.u
.foldercoll
.coll
= collection
;
1320 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1322 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1327 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1329 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1330 ULONG ref
= InterlockedDecrement(&This
->ref
);
1332 TRACE("(%p)->(%d)\n", This
, ref
);
1336 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1337 FindClose(This
->data
.u
.filecoll
.find
);
1344 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1346 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1347 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1348 WIN32_FIND_DATAW data
;
1351 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1356 if (!celt
) return S_OK
;
1360 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1361 if (!handle
) return S_FALSE
;
1362 This
->data
.u
.filecoll
.find
= handle
;
1364 else if (!FindNextFileW(handle
, &data
))
1369 if (is_file_data(&data
))
1375 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1376 hr
= create_file(str
, &file
);
1378 if (FAILED(hr
)) return hr
;
1380 V_VT(&var
[count
]) = VT_DISPATCH
;
1381 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1382 if (++count
>= celt
) break;
1384 } while (FindNextFileW(handle
, &data
));
1389 return (count
< celt
) ? S_FALSE
: S_OK
;
1392 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1394 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1395 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1396 WIN32_FIND_DATAW data
;
1398 TRACE("(%p)->(%d)\n", This
, celt
);
1400 if (!celt
) return S_OK
;
1404 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1405 if (!handle
) return S_FALSE
;
1406 This
->data
.u
.filecoll
.find
= handle
;
1408 else if (!FindNextFileW(handle
, &data
))
1413 if (is_file_data(&data
))
1415 } while (celt
&& FindNextFileW(handle
, &data
));
1417 return celt
? S_FALSE
: S_OK
;
1420 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1422 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1424 TRACE("(%p)\n", This
);
1426 FindClose(This
->data
.u
.filecoll
.find
);
1427 This
->data
.u
.filecoll
.find
= NULL
;
1432 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1434 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1435 TRACE("(%p)->(%p)\n", This
, pclone
);
1436 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1439 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1440 enumvariant_QueryInterface
,
1442 filecoll_enumvariant_Release
,
1443 filecoll_enumvariant_Next
,
1444 filecoll_enumvariant_Skip
,
1445 filecoll_enumvariant_Reset
,
1446 filecoll_enumvariant_Clone
1449 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1451 struct enumvariant
*This
;
1455 This
= heap_alloc(sizeof(*This
));
1456 if (!This
) return E_OUTOFMEMORY
;
1458 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1460 This
->data
.u
.filecoll
.find
= NULL
;
1461 This
->data
.u
.filecoll
.coll
= collection
;
1462 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1464 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1469 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1471 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1472 ULONG ref
= InterlockedDecrement(&This
->ref
);
1474 TRACE("(%p)->(%d)\n", This
, ref
);
1478 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1485 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1487 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1490 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1492 penum
->data
.u
.drivecoll
.cur
= i
;
1499 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1501 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1504 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1509 if (!celt
) return S_OK
;
1511 while (find_next_drive(This
) == S_OK
)
1516 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1517 if (FAILED(hr
)) return hr
;
1519 V_VT(&var
[count
]) = VT_DISPATCH
;
1520 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1522 if (++count
>= celt
) break;
1528 return (count
< celt
) ? S_FALSE
: S_OK
;
1531 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1533 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1535 TRACE("(%p)->(%d)\n", This
, celt
);
1537 if (!celt
) return S_OK
;
1539 while (celt
&& find_next_drive(This
) == S_OK
)
1542 return celt
? S_FALSE
: S_OK
;
1545 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1547 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1549 TRACE("(%p)\n", This
);
1551 This
->data
.u
.drivecoll
.cur
= -1;
1555 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1557 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1558 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1562 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1563 enumvariant_QueryInterface
,
1565 drivecoll_enumvariant_Release
,
1566 drivecoll_enumvariant_Next
,
1567 drivecoll_enumvariant_Skip
,
1568 drivecoll_enumvariant_Reset
,
1569 drivecoll_enumvariant_Clone
1572 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1574 struct enumvariant
*This
;
1578 This
= heap_alloc(sizeof(*This
));
1579 if (!This
) return E_OUTOFMEMORY
;
1581 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1583 This
->data
.u
.drivecoll
.coll
= collection
;
1584 This
->data
.u
.drivecoll
.cur
= -1;
1585 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1587 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1592 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1594 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1596 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1600 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1601 IsEqualIID( riid
, &IID_IDispatch
) ||
1602 IsEqualIID( riid
, &IID_IUnknown
))
1604 *obj
= &This
->IFolderCollection_iface
;
1606 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1608 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1611 return E_NOINTERFACE
;
1613 IUnknown_AddRef((IUnknown
*)*obj
);
1617 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1619 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1620 ULONG ref
= InterlockedIncrement(&This
->ref
);
1621 TRACE("(%p)->(%d)\n", This
, ref
);
1625 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1627 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1628 ULONG ref
= InterlockedDecrement(&This
->ref
);
1629 TRACE("(%p)->(%d)\n", This
, ref
);
1633 SysFreeString(This
->path
);
1640 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1642 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1643 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1648 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1649 LCID lcid
, ITypeInfo
**ppTInfo
)
1651 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1652 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1653 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1656 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1657 LPOLESTR
*rgszNames
, UINT cNames
,
1658 LCID lcid
, DISPID
*rgDispId
)
1660 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1661 ITypeInfo
*typeinfo
;
1664 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1666 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1669 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1670 ITypeInfo_Release(typeinfo
);
1676 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1677 REFIID riid
, LCID lcid
, WORD wFlags
,
1678 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1679 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1681 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1682 ITypeInfo
*typeinfo
;
1685 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1686 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1688 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1691 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1692 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1693 ITypeInfo_Release(typeinfo
);
1699 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1701 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1702 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1706 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1708 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1709 FIXME("(%p)->(%p): stub\n", This
, folder
);
1713 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1715 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1717 TRACE("(%p)->(%p)\n", This
, newenum
);
1722 return create_foldercoll_enum(This
, newenum
);
1725 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1727 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1728 static const WCHAR allW
[] = {'\\','*',0};
1729 WIN32_FIND_DATAW data
;
1730 WCHAR pathW
[MAX_PATH
];
1733 TRACE("(%p)->(%p)\n", This
, count
);
1740 strcpyW(pathW
, This
->path
);
1741 strcatW(pathW
, allW
);
1742 handle
= FindFirstFileW(pathW
, &data
);
1743 if (handle
== INVALID_HANDLE_VALUE
)
1744 return HRESULT_FROM_WIN32(GetLastError());
1748 if (is_dir_data(&data
))
1750 } while (FindNextFileW(handle
, &data
));
1756 static const IFolderCollectionVtbl foldercollvtbl
= {
1757 foldercoll_QueryInterface
,
1760 foldercoll_GetTypeInfoCount
,
1761 foldercoll_GetTypeInfo
,
1762 foldercoll_GetIDsOfNames
,
1765 foldercoll_get_Item
,
1766 foldercoll_get__NewEnum
,
1767 foldercoll_get_Count
1770 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1772 struct foldercollection
*This
;
1776 This
= heap_alloc(sizeof(struct foldercollection
));
1777 if (!This
) return E_OUTOFMEMORY
;
1779 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1781 This
->path
= SysAllocString(path
);
1785 return E_OUTOFMEMORY
;
1788 init_classinfo(&CLSID_Folders
, (IUnknown
*)&This
->IFolderCollection_iface
, &This
->classinfo
);
1789 *folders
= &This
->IFolderCollection_iface
;
1794 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1796 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1798 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1802 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1803 IsEqualIID( riid
, &IID_IDispatch
) ||
1804 IsEqualIID( riid
, &IID_IUnknown
))
1806 *obj
= &This
->IFileCollection_iface
;
1808 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1810 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1813 return E_NOINTERFACE
;
1815 IUnknown_AddRef((IUnknown
*)*obj
);
1819 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1821 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1822 ULONG ref
= InterlockedIncrement(&This
->ref
);
1823 TRACE("(%p)->(%d)\n", This
, ref
);
1827 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1829 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1830 ULONG ref
= InterlockedDecrement(&This
->ref
);
1831 TRACE("(%p)->(%d)\n", This
, ref
);
1835 SysFreeString(This
->path
);
1842 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1844 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1845 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1850 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1851 LCID lcid
, ITypeInfo
**ppTInfo
)
1853 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1854 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1855 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1858 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1859 LPOLESTR
*rgszNames
, UINT cNames
,
1860 LCID lcid
, DISPID
*rgDispId
)
1862 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1863 ITypeInfo
*typeinfo
;
1866 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1868 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1871 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1872 ITypeInfo_Release(typeinfo
);
1878 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1879 REFIID riid
, LCID lcid
, WORD wFlags
,
1880 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1881 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1883 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1884 ITypeInfo
*typeinfo
;
1887 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1888 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1890 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1893 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1894 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1895 ITypeInfo_Release(typeinfo
);
1901 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1903 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1904 FIXME("(%p)->(%p)\n", This
, file
);
1908 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1910 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1912 TRACE("(%p)->(%p)\n", This
, ppenum
);
1917 return create_filecoll_enum(This
, ppenum
);
1920 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1922 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1923 static const WCHAR allW
[] = {'\\','*',0};
1924 WIN32_FIND_DATAW data
;
1925 WCHAR pathW
[MAX_PATH
];
1928 TRACE("(%p)->(%p)\n", This
, count
);
1935 strcpyW(pathW
, This
->path
);
1936 strcatW(pathW
, allW
);
1937 handle
= FindFirstFileW(pathW
, &data
);
1938 if (handle
== INVALID_HANDLE_VALUE
)
1939 return HRESULT_FROM_WIN32(GetLastError());
1943 if (is_file_data(&data
))
1945 } while (FindNextFileW(handle
, &data
));
1951 static const IFileCollectionVtbl filecollectionvtbl
= {
1952 filecoll_QueryInterface
,
1955 filecoll_GetTypeInfoCount
,
1956 filecoll_GetTypeInfo
,
1957 filecoll_GetIDsOfNames
,
1960 filecoll_get__NewEnum
,
1964 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1966 struct filecollection
*This
;
1970 This
= heap_alloc(sizeof(*This
));
1971 if (!This
) return E_OUTOFMEMORY
;
1973 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1975 This
->path
= SysAllocString(path
);
1979 return E_OUTOFMEMORY
;
1982 init_classinfo(&CLSID_Files
, (IUnknown
*)&This
->IFileCollection_iface
, &This
->classinfo
);
1983 *files
= &This
->IFileCollection_iface
;
1987 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1989 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1991 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1995 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1996 IsEqualIID( riid
, &IID_IDispatch
) ||
1997 IsEqualIID( riid
, &IID_IUnknown
))
1999 *obj
= &This
->IDriveCollection_iface
;
2001 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2003 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2006 return E_NOINTERFACE
;
2008 IUnknown_AddRef((IUnknown
*)*obj
);
2012 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
2014 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2015 ULONG ref
= InterlockedIncrement(&This
->ref
);
2016 TRACE("(%p)->(%d)\n", This
, ref
);
2020 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
2022 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2023 ULONG ref
= InterlockedDecrement(&This
->ref
);
2024 TRACE("(%p)->(%d)\n", This
, ref
);
2032 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
2034 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2035 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2040 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
2041 LCID lcid
, ITypeInfo
**ppTInfo
)
2043 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2044 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2045 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
2048 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
2049 LPOLESTR
*rgszNames
, UINT cNames
,
2050 LCID lcid
, DISPID
*rgDispId
)
2052 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2053 ITypeInfo
*typeinfo
;
2056 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2058 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2061 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2062 ITypeInfo_Release(typeinfo
);
2068 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2069 REFIID riid
, LCID lcid
, WORD wFlags
,
2070 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2071 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2073 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2074 ITypeInfo
*typeinfo
;
2077 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2078 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2080 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2083 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2084 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2085 ITypeInfo_Release(typeinfo
);
2091 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2093 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2094 FIXME("(%p)->(%p): stub\n", This
, drive
);
2098 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2100 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2102 TRACE("(%p)->(%p)\n", This
, ppenum
);
2107 return create_drivecoll_enum(This
, ppenum
);
2110 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2112 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2114 TRACE("(%p)->(%p)\n", This
, count
);
2116 if (!count
) return E_POINTER
;
2118 *count
= This
->count
;
2122 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2123 drivecoll_QueryInterface
,
2126 drivecoll_GetTypeInfoCount
,
2127 drivecoll_GetTypeInfo
,
2128 drivecoll_GetIDsOfNames
,
2131 drivecoll_get__NewEnum
,
2135 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2137 struct drivecollection
*This
;
2142 This
= heap_alloc(sizeof(*This
));
2143 if (!This
) return E_OUTOFMEMORY
;
2145 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2147 This
->drives
= mask
= GetLogicalDrives();
2148 /* count set bits */
2149 for (This
->count
= 0; mask
; This
->count
++)
2152 init_classinfo(&CLSID_Drives
, (IUnknown
*)&This
->IDriveCollection_iface
, &This
->classinfo
);
2153 *drives
= &This
->IDriveCollection_iface
;
2157 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2159 struct folder
*This
= impl_from_IFolder(iface
);
2161 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2165 if (IsEqualIID( riid
, &IID_IFolder
) ||
2166 IsEqualIID( riid
, &IID_IDispatch
) ||
2167 IsEqualIID( riid
, &IID_IUnknown
))
2169 *obj
= &This
->IFolder_iface
;
2171 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2173 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2176 return E_NOINTERFACE
;
2178 IUnknown_AddRef((IUnknown
*)*obj
);
2182 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2184 struct folder
*This
= impl_from_IFolder(iface
);
2185 ULONG ref
= InterlockedIncrement(&This
->ref
);
2186 TRACE("(%p)->(%d)\n", This
, ref
);
2190 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2192 struct folder
*This
= impl_from_IFolder(iface
);
2193 ULONG ref
= InterlockedDecrement(&This
->ref
);
2194 TRACE("(%p)->(%d)\n", This
, ref
);
2198 SysFreeString(This
->path
);
2205 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2207 struct folder
*This
= impl_from_IFolder(iface
);
2208 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2213 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2214 LCID lcid
, ITypeInfo
**ppTInfo
)
2216 struct folder
*This
= impl_from_IFolder(iface
);
2217 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2218 return get_typeinfo(IFolder_tid
, ppTInfo
);
2221 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2222 LPOLESTR
*rgszNames
, UINT cNames
,
2223 LCID lcid
, DISPID
*rgDispId
)
2225 struct folder
*This
= impl_from_IFolder(iface
);
2226 ITypeInfo
*typeinfo
;
2229 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2231 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2234 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2235 ITypeInfo_Release(typeinfo
);
2241 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2242 REFIID riid
, LCID lcid
, WORD wFlags
,
2243 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2244 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2246 struct folder
*This
= impl_from_IFolder(iface
);
2247 ITypeInfo
*typeinfo
;
2250 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2251 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2253 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2256 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2257 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2258 ITypeInfo_Release(typeinfo
);
2264 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2266 struct folder
*This
= impl_from_IFolder(iface
);
2268 TRACE("(%p)->(%p)\n", This
, path
);
2273 *path
= SysAllocString(This
->path
);
2274 return *path
? S_OK
: E_OUTOFMEMORY
;
2277 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2279 struct folder
*This
= impl_from_IFolder(iface
);
2282 TRACE("(%p)->(%p)\n", This
, name
);
2289 ptr
= strrchrW(This
->path
, '\\');
2292 *name
= SysAllocString(ptr
+1);
2293 TRACE("%s\n", debugstr_w(*name
));
2294 if (!*name
) return E_OUTOFMEMORY
;
2302 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2304 struct folder
*This
= impl_from_IFolder(iface
);
2305 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2309 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2311 struct folder
*This
= impl_from_IFolder(iface
);
2312 FIXME("(%p)->(%p): stub\n", This
, path
);
2316 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2318 struct folder
*This
= impl_from_IFolder(iface
);
2319 FIXME("(%p)->(%p): stub\n", This
, name
);
2323 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2325 struct folder
*This
= impl_from_IFolder(iface
);
2326 FIXME("(%p)->(%p): stub\n", This
, drive
);
2330 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2332 struct folder
*This
= impl_from_IFolder(iface
);
2333 FIXME("(%p)->(%p): stub\n", This
, parent
);
2337 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2339 struct folder
*This
= impl_from_IFolder(iface
);
2340 FIXME("(%p)->(%p): stub\n", This
, attr
);
2344 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2346 struct folder
*This
= impl_from_IFolder(iface
);
2347 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2351 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2353 struct folder
*This
= impl_from_IFolder(iface
);
2354 FIXME("(%p)->(%p): stub\n", This
, date
);
2358 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2360 struct folder
*This
= impl_from_IFolder(iface
);
2361 FIXME("(%p)->(%p): stub\n", This
, date
);
2365 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2367 struct folder
*This
= impl_from_IFolder(iface
);
2368 FIXME("(%p)->(%p): stub\n", This
, date
);
2372 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2374 struct folder
*This
= impl_from_IFolder(iface
);
2375 FIXME("(%p)->(%p): stub\n", This
, type
);
2379 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2381 struct folder
*This
= impl_from_IFolder(iface
);
2382 FIXME("(%p)->(%x): stub\n", This
, force
);
2386 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2388 struct folder
*This
= impl_from_IFolder(iface
);
2389 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2393 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2395 struct folder
*This
= impl_from_IFolder(iface
);
2396 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2400 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2402 struct folder
*This
= impl_from_IFolder(iface
);
2403 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2407 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2409 struct folder
*This
= impl_from_IFolder(iface
);
2410 FIXME("(%p)->(%p): stub\n", This
, size
);
2414 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2416 struct folder
*This
= impl_from_IFolder(iface
);
2418 TRACE("(%p)->(%p)\n", This
, folders
);
2423 return create_foldercoll(This
->path
, folders
);
2426 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2428 struct folder
*This
= impl_from_IFolder(iface
);
2430 TRACE("(%p)->(%p)\n", This
, files
);
2435 return create_filecoll(This
->path
, files
);
2438 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2439 VARIANT_BOOL unicode
, ITextStream
**stream
)
2441 struct folder
*This
= impl_from_IFolder(iface
);
2442 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2446 static const IFolderVtbl foldervtbl
= {
2447 folder_QueryInterface
,
2450 folder_GetTypeInfoCount
,
2452 folder_GetIDsOfNames
,
2457 folder_get_ShortPath
,
2458 folder_get_ShortName
,
2460 folder_get_ParentFolder
,
2461 folder_get_Attributes
,
2462 folder_put_Attributes
,
2463 folder_get_DateCreated
,
2464 folder_get_DateLastModified
,
2465 folder_get_DateLastAccessed
,
2470 folder_get_IsRootFolder
,
2472 folder_get_SubFolders
,
2474 folder_CreateTextFile
2477 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2479 struct folder
*This
;
2483 TRACE("%s\n", debugstr_w(path
));
2485 This
= heap_alloc(sizeof(struct folder
));
2486 if (!This
) return E_OUTOFMEMORY
;
2488 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2490 This
->path
= SysAllocString(path
);
2494 return E_OUTOFMEMORY
;
2497 init_classinfo(&CLSID_Folder
, (IUnknown
*)&This
->IFolder_iface
, &This
->classinfo
);
2498 *folder
= &This
->IFolder_iface
;
2503 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2505 struct file
*This
= impl_from_IFile(iface
);
2507 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2511 if (IsEqualIID(riid
, &IID_IFile
) ||
2512 IsEqualIID(riid
, &IID_IDispatch
) ||
2513 IsEqualIID(riid
, &IID_IUnknown
))
2515 *obj
= &This
->IFile_iface
;
2517 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2519 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2522 return E_NOINTERFACE
;
2524 IUnknown_AddRef((IUnknown
*)*obj
);
2528 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2530 struct file
*This
= impl_from_IFile(iface
);
2531 LONG ref
= InterlockedIncrement(&This
->ref
);
2533 TRACE("(%p) ref=%d\n", This
, ref
);
2538 static ULONG WINAPI
file_Release(IFile
*iface
)
2540 struct file
*This
= impl_from_IFile(iface
);
2541 LONG ref
= InterlockedDecrement(&This
->ref
);
2543 TRACE("(%p) ref=%d\n", This
, ref
);
2547 heap_free(This
->path
);
2554 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2556 struct file
*This
= impl_from_IFile(iface
);
2558 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2564 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2565 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2567 struct file
*This
= impl_from_IFile(iface
);
2569 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2571 return get_typeinfo(IFile_tid
, ppTInfo
);
2574 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2575 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2577 struct file
*This
= impl_from_IFile(iface
);
2578 ITypeInfo
*typeinfo
;
2581 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2582 rgszNames
, cNames
, lcid
, rgDispId
);
2584 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2586 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2587 ITypeInfo_Release(typeinfo
);
2592 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2594 struct file
*This
= impl_from_IFile(iface
);
2595 ITypeInfo
*typeinfo
;
2598 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2599 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2601 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2604 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2605 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2606 ITypeInfo_Release(typeinfo
);
2611 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2613 struct file
*This
= impl_from_IFile(iface
);
2615 TRACE("(%p)->(%p)\n", This
, path
);
2620 *path
= SysAllocString(This
->path
);
2622 return E_OUTOFMEMORY
;
2627 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2629 struct file
*This
= impl_from_IFile(iface
);
2632 TRACE("(%p)->(%p)\n", This
, name
);
2639 ptr
= strrchrW(This
->path
, '\\');
2642 *name
= SysAllocString(ptr
+1);
2643 TRACE("%s\n", debugstr_w(*name
));
2644 if (!*name
) return E_OUTOFMEMORY
;
2652 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2654 struct file
*This
= impl_from_IFile(iface
);
2655 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2659 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2661 struct file
*This
= impl_from_IFile(iface
);
2662 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2666 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2668 struct file
*This
= impl_from_IFile(iface
);
2669 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2673 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2675 struct file
*This
= impl_from_IFile(iface
);
2676 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2680 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2682 struct file
*This
= impl_from_IFile(iface
);
2683 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2687 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2689 struct file
*This
= impl_from_IFile(iface
);
2692 TRACE("(%p)->(%p)\n", This
, pfa
);
2697 fa
= GetFileAttributesW(This
->path
);
2698 if(fa
== INVALID_FILE_ATTRIBUTES
)
2699 return create_error(GetLastError());
2701 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2702 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2703 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2707 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2709 struct file
*This
= impl_from_IFile(iface
);
2711 TRACE("(%p)->(%x)\n", This
, pfa
);
2713 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2716 static HRESULT
get_date_from_filetime(const FILETIME
*ft
, DATE
*date
)
2724 FileTimeToLocalFileTime(ft
, &ftlocal
);
2725 FileTimeToSystemTime(&ftlocal
, &st
);
2726 SystemTimeToVariantTime(&st
, date
);
2731 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2733 struct file
*This
= impl_from_IFile(iface
);
2734 FIXME("(%p)->(%p)\n", This
, pdate
);
2738 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*date
)
2740 struct file
*This
= impl_from_IFile(iface
);
2741 WIN32_FILE_ATTRIBUTE_DATA attrs
;
2743 TRACE("(%p)->(%p)\n", This
, date
);
2745 if (GetFileAttributesExW(This
->path
, GetFileExInfoStandard
, &attrs
))
2746 return get_date_from_filetime(&attrs
.ftLastWriteTime
, date
);
2751 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2753 struct file
*This
= impl_from_IFile(iface
);
2754 FIXME("(%p)->(%p)\n", This
, pdate
);
2758 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2760 struct file
*This
= impl_from_IFile(iface
);
2761 ULARGE_INTEGER size
;
2762 WIN32_FIND_DATAW fd
;
2765 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2770 f
= FindFirstFileW(This
->path
, &fd
);
2771 if(f
== INVALID_HANDLE_VALUE
)
2772 return create_error(GetLastError());
2775 size
.u
.LowPart
= fd
.nFileSizeLow
;
2776 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2778 return variant_from_largeint(&size
, pvarSize
);
2781 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2783 struct file
*This
= impl_from_IFile(iface
);
2784 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2788 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2790 struct file
*This
= impl_from_IFile(iface
);
2791 FIXME("(%p)->(%x)\n", This
, Force
);
2795 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2797 struct file
*This
= impl_from_IFile(iface
);
2798 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2802 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2804 struct file
*This
= impl_from_IFile(iface
);
2805 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2809 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2811 struct file
*This
= impl_from_IFile(iface
);
2813 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2815 if (format
== TristateUseDefault
) {
2816 FIXME("default format not handled, defaulting to unicode\n");
2817 format
= TristateTrue
;
2820 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2823 static const IFileVtbl file_vtbl
= {
2824 file_QueryInterface
,
2827 file_GetTypeInfoCount
,
2837 file_get_ParentFolder
,
2838 file_get_Attributes
,
2839 file_put_Attributes
,
2840 file_get_DateCreated
,
2841 file_get_DateLastModified
,
2842 file_get_DateLastAccessed
,
2848 file_OpenAsTextStream
2851 static HRESULT
create_file(BSTR path
, IFile
**file
)
2858 f
= heap_alloc(sizeof(struct file
));
2860 return E_OUTOFMEMORY
;
2862 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2865 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2871 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2874 return E_OUTOFMEMORY
;
2877 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2883 attrs
= GetFileAttributesW(f
->path
);
2884 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2885 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2888 return create_error(GetLastError());
2891 init_classinfo(&CLSID_File
, (IUnknown
*)&f
->IFile_iface
, &f
->classinfo
);
2892 *file
= &f
->IFile_iface
;
2896 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2898 struct filesystem
*This
= impl_from_IFileSystem3(iface
);
2900 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2902 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2903 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2904 IsEqualGUID( riid
, &IID_IDispatch
) ||
2905 IsEqualGUID( riid
, &IID_IUnknown
) )
2907 *ppvObject
= &This
->IFileSystem3_iface
;
2909 else if (IsEqualGUID( riid
, &IID_IProvideClassInfo
))
2911 *ppvObject
= &This
->classinfo
.IProvideClassInfo_iface
;
2913 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2915 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2917 return E_NOINTERFACE
;
2919 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2921 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2923 return E_NOINTERFACE
;
2927 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2928 return E_NOINTERFACE
;
2931 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2936 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2938 TRACE("%p\n", iface
);
2943 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2945 TRACE("%p\n", iface
);
2950 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2952 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2958 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2959 LCID lcid
, ITypeInfo
**ppTInfo
)
2961 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2962 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2965 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2966 LPOLESTR
*rgszNames
, UINT cNames
,
2967 LCID lcid
, DISPID
*rgDispId
)
2969 ITypeInfo
*typeinfo
;
2972 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2974 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2977 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2978 ITypeInfo_Release(typeinfo
);
2984 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2985 REFIID riid
, LCID lcid
, WORD wFlags
,
2986 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2987 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2989 ITypeInfo
*typeinfo
;
2992 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2993 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2995 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2998 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2999 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
3000 ITypeInfo_Release(typeinfo
);
3006 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
3008 TRACE("%p %p\n", iface
, ppdrives
);
3009 return create_drivecoll(ppdrives
);
3012 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
3013 BSTR Name
, BSTR
*Result
)
3017 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
3019 if (!Result
) return E_POINTER
;
3023 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
3025 /* if both parts have backslashes strip one from Path */
3026 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
3030 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3038 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
3040 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
3044 if (Path
[path_len
-1] != ':')
3051 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3059 else if (Path
|| Name
)
3060 ret
= SysAllocString(Path
? Path
: Name
);
3062 ret
= SysAllocStringLen(NULL
, 0);
3064 if (!ret
) return E_OUTOFMEMORY
;
3070 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
3072 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
3079 if (path
&& strlenW(path
) > 1 && path
[1] == ':')
3080 *drive
= SysAllocStringLen(path
, 2);
3085 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
3092 for(i
=len
-1; i
>=0; i
--)
3093 if(path
[i
]!='/' && path
[i
]!='\\')
3097 if(path
[i
]=='/' || path
[i
]=='\\')
3101 if(path
[i
]!='/' && path
[i
]!='\\')
3107 if(path
[i
]==':' && i
==1)
3112 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3117 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3122 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3124 *pbstrResult
= NULL
;
3128 *pbstrResult
= SysAllocStringLen(Path
, len
);
3130 return E_OUTOFMEMORY
;
3134 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3139 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3145 *pbstrResult
= NULL
;
3149 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3150 if(Path
[end
]!='/' && Path
[end
]!='\\')
3153 for(i
=end
; i
>=0; i
--)
3154 if(Path
[i
]=='/' || Path
[i
]=='\\')
3158 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3159 *pbstrResult
= NULL
;
3163 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3165 return E_OUTOFMEMORY
;
3169 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3174 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3180 *pbstrResult
= NULL
;
3184 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3185 if(Path
[end
]!='/' && Path
[end
]!='\\')
3188 for(i
=end
; i
>=0; i
--) {
3189 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3191 if(Path
[i
]=='/' || Path
[i
]=='\\')
3196 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3197 *pbstrResult
= NULL
;
3201 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3203 return E_OUTOFMEMORY
;
3207 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3212 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3215 len
= SysStringLen(path
);
3217 if (path
[len
-1] == '.') {
3218 *ext
= SysAllocString(&path
[len
]);
3220 return E_OUTOFMEMORY
;
3229 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3232 static const WCHAR cur_path
[] = {'.',0};
3234 WCHAR buf
[MAX_PATH
], ch
;
3236 DWORD i
, beg
, len
, exp_len
;
3237 WIN32_FIND_DATAW fdata
;
3240 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3250 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3254 buf
[0] = toupperW(buf
[0]);
3255 if(len
>3 && buf
[len
-1] == '\\')
3258 for(beg
=3, i
=3; i
<=len
; i
++) {
3259 if(buf
[i
]!='\\' && buf
[i
])
3264 fh
= FindFirstFileW(buf
, &fdata
);
3265 if(fh
== INVALID_HANDLE_VALUE
)
3268 exp_len
= strlenW(fdata
.cFileName
);
3269 if(exp_len
== i
-beg
)
3270 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3276 *pbstrResult
= SysAllocString(buf
);
3278 return E_OUTOFMEMORY
;
3282 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3284 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3288 TRACE("%p %p\n", iface
, pbstrResult
);
3293 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3295 return E_OUTOFMEMORY
;
3297 if(!RtlGenRandom(&random
, sizeof(random
)))
3299 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3303 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3304 VARIANT_BOOL
*pfExists
)
3308 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3310 if (!pfExists
) return E_POINTER
;
3312 *pfExists
= VARIANT_FALSE
;
3313 len
= SysStringLen(DriveSpec
);
3316 driveletter
= toupperW(DriveSpec
[0]);
3317 if (driveletter
>= 'A' && driveletter
<= 'Z'
3318 && (len
< 2 || DriveSpec
[1] == ':')
3319 && (len
< 3 || DriveSpec
[2] == '\\')) {
3320 const WCHAR root
[] = {driveletter
, ':', '\\', 0};
3321 UINT drivetype
= GetDriveTypeW(root
);
3322 *pfExists
= drivetype
!= DRIVE_NO_ROOT_DIR
&& drivetype
!= DRIVE_UNKNOWN
? VARIANT_TRUE
: VARIANT_FALSE
;
3329 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3332 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3334 if (!ret
) return E_POINTER
;
3336 attrs
= GetFileAttributesW(path
);
3337 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3341 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3344 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3346 if (!ret
) return E_POINTER
;
3348 attrs
= GetFileAttributesW(path
);
3349 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3354 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3360 VARIANT_BOOL drive_exists
;
3362 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3369 /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3370 len
= SysStringLen(DriveSpec
);
3372 return E_INVALIDARG
;
3373 else if (len
<= 3) {
3374 driveletter
= toupperW(DriveSpec
[0]);
3375 if (driveletter
< 'A' || driveletter
> 'Z'
3376 || (len
>= 2 && DriveSpec
[1] != ':')
3377 || (len
== 3 && DriveSpec
[2] != '\\'))
3378 return E_INVALIDARG
;
3379 hr
= IFileSystem3_DriveExists(iface
, DriveSpec
, &drive_exists
);
3382 if (drive_exists
== VARIANT_FALSE
)
3383 return CTL_E_DEVICEUNAVAILABLE
;
3384 return create_drive(driveletter
, ppdrive
);
3386 if (DriveSpec
[0] != '\\' || DriveSpec
[1] != '\\')
3387 return E_INVALIDARG
;
3388 FIXME("%s not implemented yet\n", debugstr_w(DriveSpec
));
3393 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3396 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3401 return E_INVALIDARG
;
3403 return create_file(FilePath
, ppfile
);
3406 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3411 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3418 return E_INVALIDARG
;
3420 attrs
= GetFileAttributesW(FolderPath
);
3421 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3422 return CTL_E_PATHNOTFOUND
;
3424 return create_folder(FolderPath
, folder
);
3427 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3428 SpecialFolderConst SpecialFolder
,
3431 WCHAR pathW
[MAX_PATH
];
3434 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3441 switch (SpecialFolder
)
3444 ret
= GetWindowsDirectoryW(pathW
, ARRAY_SIZE(pathW
));
3447 ret
= GetSystemDirectoryW(pathW
, ARRAY_SIZE(pathW
));
3449 case TemporaryFolder
:
3450 ret
= GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
3451 /* we don't want trailing backslash */
3452 if (ret
&& pathW
[ret
-1] == '\\')
3456 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3457 return E_INVALIDARG
;
3461 return HRESULT_FROM_WIN32(GetLastError());
3463 return create_folder(pathW
, folder
);
3466 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3468 WCHAR path
[MAX_PATH
];
3469 DWORD len
, name_len
;
3470 WIN32_FIND_DATAW ffd
;
3473 f
= FindFirstFileW(file
, &ffd
);
3474 if(f
== INVALID_HANDLE_VALUE
)
3475 return create_error(GetLastError());
3477 len
= get_parent_folder_name(file
, file_len
);
3478 if(len
+1 >= MAX_PATH
) {
3483 memcpy(path
, file
, len
*sizeof(WCHAR
));
3488 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3491 name_len
= strlenW(ffd
.cFileName
);
3492 if(len
+name_len
+1 >= MAX_PATH
) {
3496 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3498 TRACE("deleting %s\n", debugstr_w(path
));
3500 if(!DeleteFileW(path
)) {
3501 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3502 || !DeleteFileW(path
)) {
3504 return create_error(GetLastError());
3507 } while(FindNextFileW(f
, &ffd
));
3513 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3516 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3521 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3524 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3526 WCHAR path
[MAX_PATH
];
3527 DWORD len
, name_len
;
3528 WIN32_FIND_DATAW ffd
;
3532 f
= FindFirstFileW(folder
, &ffd
);
3533 if(f
== INVALID_HANDLE_VALUE
)
3534 return create_error(GetLastError());
3536 len
= get_parent_folder_name(folder
, folder_len
);
3537 if(len
+1 >= MAX_PATH
) {
3542 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3547 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3549 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3550 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3553 name_len
= strlenW(ffd
.cFileName
);
3554 if(len
+name_len
+3 >= MAX_PATH
) {
3558 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3559 path
[len
+name_len
] = '\\';
3560 path
[len
+name_len
+1] = '*';
3561 path
[len
+name_len
+2] = 0;
3563 hr
= delete_file(path
, len
+name_len
+2, force
);
3569 hr
= delete_folder(path
, len
+name_len
+2, force
);
3575 path
[len
+name_len
] = 0;
3576 TRACE("deleting %s\n", debugstr_w(path
));
3578 if(!RemoveDirectoryW(path
)) {
3580 return create_error(GetLastError());
3582 } while(FindNextFileW(f
, &ffd
));
3588 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3591 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3596 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3599 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3602 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3607 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3610 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3615 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3616 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3619 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3620 DWORD src_len
, dst_len
, name_len
;
3621 WIN32_FIND_DATAW ffd
;
3625 if(!source
[0] || !destination
[0])
3626 return E_INVALIDARG
;
3628 attrs
= GetFileAttributesW(destination
);
3629 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3630 attrs
= GetFileAttributesW(source
);
3631 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3632 return create_error(GetLastError());
3633 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3634 return CTL_E_FILENOTFOUND
;
3636 if(!CopyFileW(source
, destination
, !overwrite
))
3637 return create_error(GetLastError());
3641 f
= FindFirstFileW(source
, &ffd
);
3642 if(f
== INVALID_HANDLE_VALUE
)
3643 return CTL_E_FILENOTFOUND
;
3645 src_len
= get_parent_folder_name(source
, source_len
);
3646 if(src_len
+1 >= MAX_PATH
) {
3651 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3652 src_path
[src_len
++] = '\\';
3655 dst_len
= destination_len
;
3656 if(dst_len
+1 >= MAX_PATH
) {
3660 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3661 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3662 dst_path
[dst_len
++] = '\\';
3664 hr
= CTL_E_FILENOTFOUND
;
3666 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3669 name_len
= strlenW(ffd
.cFileName
);
3670 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3674 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3675 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3677 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3679 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3681 return create_error(GetLastError());
3685 } while(FindNextFileW(f
, &ffd
));
3691 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3692 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3694 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3696 if(!Source
|| !Destination
)
3699 return copy_file(Source
, SysStringLen(Source
), Destination
,
3700 SysStringLen(Destination
), OverWriteFiles
);
3703 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3704 DWORD destination_len
, VARIANT_BOOL overwrite
)
3706 DWORD tmp
, src_len
, dst_len
, name_len
;
3707 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3708 WIN32_FIND_DATAW ffd
;
3711 BOOL copied
= FALSE
;
3713 if(!source
[0] || !destination
[0])
3714 return E_INVALIDARG
;
3716 dst_len
= destination_len
;
3717 if(dst_len
+1 >= MAX_PATH
)
3719 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3721 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3722 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3723 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3724 if(!CreateDirectoryW(dst
, NULL
)) {
3725 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3726 tmp
= GetFileAttributesW(dst
);
3727 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3728 return CTL_E_FILEALREADYEXISTS
;
3730 return create_error(GetLastError());
3735 src_len
= source_len
;
3736 if(src_len
+2 >= MAX_PATH
)
3738 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3739 src
[src_len
++] = '\\';
3743 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3744 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3745 return create_error(GetLastError());
3747 f
= FindFirstFileW(src
, &ffd
);
3749 src_len
= get_parent_folder_name(source
, source_len
);
3750 if(src_len
+2 >= MAX_PATH
)
3752 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3754 src
[src_len
++] = '\\';
3756 f
= FindFirstFileW(source
, &ffd
);
3758 if(f
== INVALID_HANDLE_VALUE
)
3759 return CTL_E_PATHNOTFOUND
;
3761 dst
[dst_len
++] = '\\';
3765 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3767 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3768 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3771 name_len
= strlenW(ffd
.cFileName
);
3772 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3776 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3777 dst
[dst_len
+name_len
] = 0;
3778 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3779 src
[src_len
+name_len
] = '\\';
3780 src
[src_len
+name_len
+1] = '*';
3781 src
[src_len
+name_len
+2] = 0;
3783 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3785 if(!CreateDirectoryW(dst
, NULL
)) {
3786 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3787 tmp
= GetFileAttributesW(dst
);
3788 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3790 return CTL_E_FILEALREADYEXISTS
;
3795 return create_error(GetLastError());
3799 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3800 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3805 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3806 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3810 } while(FindNextFileW(f
, &ffd
));
3813 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3816 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3817 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3819 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3821 if(!Source
|| !Destination
)
3824 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3825 SysStringLen(Destination
), OverWriteFiles
);
3828 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3833 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3835 ret
= CreateDirectoryW(path
, NULL
);
3839 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3840 return HRESULT_FROM_WIN32(GetLastError());
3843 return create_folder(path
, folder
);
3846 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3847 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3848 ITextStream
**stream
)
3852 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3854 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3855 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3858 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3859 IOMode mode
, VARIANT_BOOL create
,
3860 Tristate format
, ITextStream
**stream
)
3864 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3865 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3867 if (format
== TristateUseDefault
) {
3868 FIXME("default format not handled, defaulting to unicode\n");
3869 format
= TristateTrue
;
3872 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3875 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3876 StandardStreamTypes StandardStreamType
,
3877 VARIANT_BOOL Unicode
,
3880 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3885 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3887 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3891 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3892 a
= (WORD
)( version
>> 48);
3893 b
= (WORD
)((version
>> 32) & 0xffff);
3894 c
= (WORD
)((version
>> 16) & 0xffff);
3895 d
= (WORD
)( version
& 0xffff);
3897 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3900 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3902 static const WCHAR rootW
[] = {'\\',0};
3903 VS_FIXEDFILEINFO
*info
;
3909 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3911 len
= GetFileVersionInfoSizeW(name
, NULL
);
3913 return HRESULT_FROM_WIN32(GetLastError());
3915 ptr
= heap_alloc(len
);
3916 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3919 return HRESULT_FROM_WIN32(GetLastError());
3922 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3926 return HRESULT_FROM_WIN32(GetLastError());
3929 get_versionstring(info
, ver
);
3932 *version
= SysAllocString(ver
);
3933 TRACE("version=%s\n", debugstr_w(ver
));
3938 static const struct IFileSystem3Vtbl filesys_vtbl
=
3940 filesys_QueryInterface
,
3943 filesys_GetTypeInfoCount
,
3944 filesys_GetTypeInfo
,
3945 filesys_GetIDsOfNames
,
3949 filesys_GetDriveName
,
3950 filesys_GetParentFolderName
,
3951 filesys_GetFileName
,
3952 filesys_GetBaseName
,
3953 filesys_GetExtensionName
,
3954 filesys_GetAbsolutePathName
,
3955 filesys_GetTempName
,
3956 filesys_DriveExists
,
3958 filesys_FolderExists
,
3962 filesys_GetSpecialFolder
,
3964 filesys_DeleteFolder
,
3969 filesys_CreateFolder
,
3970 filesys_CreateTextFile
,
3971 filesys_OpenTextFile
,
3972 filesys_GetStandardStream
,
3973 filesys_GetFileVersion
3976 static struct filesystem filesystem
;
3978 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3980 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3982 filesystem
.IFileSystem3_iface
.lpVtbl
= &filesys_vtbl
;
3983 init_classinfo(&CLSID_FileSystemObject
, (IUnknown
*)&filesystem
.IFileSystem3_iface
, &filesystem
.classinfo
);
3984 return IFileSystem3_QueryInterface(&filesystem
.IFileSystem3_iface
, riid
, ppv
);