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"
37 WINE_DEFAULT_DEBUG_CHANNEL(scrrun
);
39 static const WCHAR bsW
[] = {'\\',0};
40 static const WCHAR utf16bom
= 0xfeff;
43 struct provideclassinfo classinfo
;
44 IFileSystem3 IFileSystem3_iface
;
47 struct foldercollection
{
48 struct provideclassinfo classinfo
;
49 IFolderCollection IFolderCollection_iface
;
54 struct filecollection
{
55 struct provideclassinfo classinfo
;
56 IFileCollection IFileCollection_iface
;
61 struct drivecollection
{
62 struct provideclassinfo classinfo
;
63 IDriveCollection IDriveCollection_iface
;
74 struct foldercollection
*coll
;
79 struct filecollection
*coll
;
84 struct drivecollection
*coll
;
91 IEnumVARIANT IEnumVARIANT_iface
;
98 struct provideclassinfo classinfo
;
105 struct provideclassinfo classinfo
;
106 IFolder IFolder_iface
;
112 struct provideclassinfo classinfo
;
120 struct provideclassinfo classinfo
;
121 ITextStream ITextStream_iface
;
136 static inline struct filesystem
*impl_from_IFileSystem3(IFileSystem3
*iface
)
138 return CONTAINING_RECORD(iface
, struct filesystem
, IFileSystem3_iface
);
141 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
143 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
146 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
148 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
151 static inline struct file
*impl_from_IFile(IFile
*iface
)
153 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
156 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
158 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
161 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
163 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
166 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
168 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
171 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
173 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
176 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
178 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
181 static inline HRESULT
create_error(DWORD err
)
184 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
185 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
186 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
187 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
188 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
190 FIXME("Unsupported error code: %d\n", err
);
195 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
196 static HRESULT
create_file(BSTR
, IFile
**);
197 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
198 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
200 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
202 static const WCHAR dotdotW
[] = {'.','.',0};
203 static const WCHAR dotW
[] = {'.',0};
205 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
206 strcmpW(data
->cFileName
, dotdotW
) &&
207 strcmpW(data
->cFileName
, dotW
);
210 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
212 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
215 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
217 int len
= SysStringLen(path
);
218 WCHAR buffW
[MAX_PATH
];
220 strcpyW(buffW
, path
);
221 if (path
[len
-1] != '\\')
223 strcatW(buffW
, data
->cFileName
);
225 return SysAllocString(buffW
);
228 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
231 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
233 return This
->mode
== ForReading
;
236 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
238 struct textstream
*This
= impl_from_ITextStream(iface
);
240 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
242 if (IsEqualIID(riid
, &IID_ITextStream
) ||
243 IsEqualIID(riid
, &IID_IDispatch
) ||
244 IsEqualIID(riid
, &IID_IUnknown
))
246 *obj
= &This
->ITextStream_iface
;
248 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
250 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
253 return E_NOINTERFACE
;
255 IUnknown_AddRef((IUnknown
*)*obj
);
259 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
261 struct textstream
*This
= impl_from_ITextStream(iface
);
262 ULONG ref
= InterlockedIncrement(&This
->ref
);
263 TRACE("(%p)->(%d)\n", This
, ref
);
267 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
269 struct textstream
*This
= impl_from_ITextStream(iface
);
270 ULONG ref
= InterlockedDecrement(&This
->ref
);
271 TRACE("(%p)->(%d)\n", This
, ref
);
275 CloseHandle(This
->file
);
282 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
284 struct textstream
*This
= impl_from_ITextStream(iface
);
285 TRACE("(%p)->(%p)\n", This
, pctinfo
);
290 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
291 LCID lcid
, ITypeInfo
**ppTInfo
)
293 struct textstream
*This
= impl_from_ITextStream(iface
);
294 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
295 return get_typeinfo(ITextStream_tid
, ppTInfo
);
298 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
299 LPOLESTR
*rgszNames
, UINT cNames
,
300 LCID lcid
, DISPID
*rgDispId
)
302 struct textstream
*This
= impl_from_ITextStream(iface
);
306 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
308 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
311 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
312 ITypeInfo_Release(typeinfo
);
318 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
319 REFIID riid
, LCID lcid
, WORD wFlags
,
320 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
321 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
323 struct textstream
*This
= impl_from_ITextStream(iface
);
327 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
328 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
330 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
333 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
334 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
335 ITypeInfo_Release(typeinfo
);
341 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
343 struct textstream
*This
= impl_from_ITextStream(iface
);
344 FIXME("(%p)->(%p): stub\n", This
, line
);
348 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
350 struct textstream
*This
= impl_from_ITextStream(iface
);
351 FIXME("(%p)->(%p): stub\n", This
, column
);
355 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
357 struct textstream
*This
= impl_from_ITextStream(iface
);
358 LARGE_INTEGER pos
, dist
;
360 TRACE("(%p)->(%p)\n", This
, eos
);
365 if (textstream_check_iomode(This
, IORead
)) {
367 return CTL_E_BADFILEMODE
;
371 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
374 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? VARIANT_TRUE
: VARIANT_FALSE
;
378 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
380 struct textstream
*This
= impl_from_ITextStream(iface
);
381 FIXME("(%p)->(%p): stub\n", This
, eol
);
386 Reads 'toread' bytes from a file, converts if needed
387 BOM is skipped if 'bof' is set.
389 static HRESULT
textstream_read(struct textstream
*stream
, LONG toread
, BOOL bof
, BSTR
*text
)
397 *text
= SysAllocStringLen(NULL
, 0);
398 return *text
? S_FALSE
: E_OUTOFMEMORY
;
401 if (toread
< sizeof(WCHAR
))
402 return CTL_E_ENDOFFILE
;
404 buff
= heap_alloc(toread
);
406 return E_OUTOFMEMORY
;
408 ret
= ReadFile(stream
->file
, buff
, toread
, &read
, NULL
);
409 if (!ret
|| toread
!= read
) {
410 WARN("failed to read from file %d, %d, error %d\n", read
, toread
, GetLastError());
415 if (stream
->unicode
) {
419 if (bof
&& *(WCHAR
*)buff
== utf16bom
) {
420 read
-= sizeof(WCHAR
);
424 *text
= SysAllocStringLen(read
? (WCHAR
*)&buff
[i
] : NULL
, read
/sizeof(WCHAR
));
425 if (!*text
) hr
= E_OUTOFMEMORY
;
428 INT len
= MultiByteToWideChar(CP_ACP
, 0, buff
, read
, NULL
, 0);
429 *text
= SysAllocStringLen(NULL
, len
);
431 MultiByteToWideChar(CP_ACP
, 0, buff
, read
, *text
, len
);
440 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
442 struct textstream
*This
= impl_from_ITextStream(iface
);
443 LARGE_INTEGER start
, end
, dist
;
447 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
454 return len
== 0 ? S_OK
: E_INVALIDARG
;
456 if (textstream_check_iomode(This
, IORead
))
457 return CTL_E_BADFILEMODE
;
459 if (!This
->first_read
) {
463 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
467 if (eos
== VARIANT_TRUE
)
468 return CTL_E_ENDOFFILE
;
471 /* read everything from current position */
473 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
474 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
475 toread
= end
.QuadPart
- start
.QuadPart
;
477 dist
.QuadPart
= start
.QuadPart
;
478 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
480 This
->first_read
= FALSE
;
481 if (This
->unicode
) len
*= sizeof(WCHAR
);
483 hr
= textstream_read(This
, min(toread
, len
), start
.QuadPart
== 0, text
);
487 return toread
<= len
? S_FALSE
: S_OK
;
490 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
492 struct textstream
*This
= impl_from_ITextStream(iface
);
496 FIXME("(%p)->(%p): stub\n", This
, text
);
502 if (textstream_check_iomode(This
, IORead
))
503 return CTL_E_BADFILEMODE
;
506 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
510 if (eos
== VARIANT_TRUE
)
511 return CTL_E_ENDOFFILE
;
516 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
518 struct textstream
*This
= impl_from_ITextStream(iface
);
519 LARGE_INTEGER start
, end
, dist
;
523 TRACE("(%p)->(%p)\n", This
, text
);
529 if (textstream_check_iomode(This
, IORead
))
530 return CTL_E_BADFILEMODE
;
532 if (!This
->first_read
) {
536 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
540 if (eos
== VARIANT_TRUE
)
541 return CTL_E_ENDOFFILE
;
544 /* read everything from current position */
546 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
547 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
548 toread
= end
.QuadPart
- start
.QuadPart
;
550 dist
.QuadPart
= start
.QuadPart
;
551 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
553 This
->first_read
= FALSE
;
555 hr
= textstream_read(This
, toread
, start
.QuadPart
== 0, text
);
556 return FAILED(hr
) ? hr
: S_FALSE
;
559 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
564 if (stream
->unicode
) {
565 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
566 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
568 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
572 buffA
= heap_alloc(len
);
574 return E_OUTOFMEMORY
;
576 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
577 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
578 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
584 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
586 struct textstream
*This
= impl_from_ITextStream(iface
);
588 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
590 if (textstream_check_iomode(This
, IOWrite
))
591 return CTL_E_BADFILEMODE
;
593 return textstream_writestr(This
, text
);
596 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
598 static const WCHAR crlfW
[] = {'\r','\n'};
599 static const char crlfA
[] = {'\r','\n'};
600 DWORD written
= 0, len
;
604 if (stream
->unicode
) {
613 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
614 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
617 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
619 struct textstream
*This
= impl_from_ITextStream(iface
);
622 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
624 if (textstream_check_iomode(This
, IOWrite
))
625 return CTL_E_BADFILEMODE
;
627 hr
= textstream_writestr(This
, text
);
629 hr
= textstream_writecrlf(This
);
633 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
635 struct textstream
*This
= impl_from_ITextStream(iface
);
636 FIXME("(%p)->(%d): stub\n", This
, lines
);
640 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
642 struct textstream
*This
= impl_from_ITextStream(iface
);
643 FIXME("(%p)->(%d): stub\n", This
, count
);
647 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
649 struct textstream
*This
= impl_from_ITextStream(iface
);
650 FIXME("(%p): stub\n", This
);
654 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
656 struct textstream
*This
= impl_from_ITextStream(iface
);
659 TRACE("(%p)\n", This
);
661 if(!CloseHandle(This
->file
))
669 static const ITextStreamVtbl textstreamvtbl
= {
670 textstream_QueryInterface
,
673 textstream_GetTypeInfoCount
,
674 textstream_GetTypeInfo
,
675 textstream_GetIDsOfNames
,
678 textstream_get_Column
,
679 textstream_get_AtEndOfStream
,
680 textstream_get_AtEndOfLine
,
685 textstream_WriteLine
,
686 textstream_WriteBlankLines
,
692 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
694 struct textstream
*stream
;
697 /* map access mode */
701 access
= GENERIC_READ
;
704 access
= GENERIC_WRITE
;
707 access
= FILE_APPEND_DATA
;
713 stream
= heap_alloc(sizeof(struct textstream
));
714 if (!stream
) return E_OUTOFMEMORY
;
716 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
719 stream
->unicode
= unicode
;
720 stream
->first_read
= TRUE
;
722 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
723 if (stream
->file
== INVALID_HANDLE_VALUE
)
725 HRESULT hr
= create_error(GetLastError());
730 if (mode
== ForReading
)
731 GetFileSizeEx(stream
->file
, &stream
->size
);
733 stream
->size
.QuadPart
= 0;
735 /* Write Unicode BOM */
736 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
738 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
739 if (!ret
|| written
!= sizeof(utf16bom
)) {
740 ITextStream_Release(&stream
->ITextStream_iface
);
741 return create_error(GetLastError());
745 init_classinfo(&CLSID_TextStream
, (IUnknown
*)&stream
->ITextStream_iface
, &stream
->classinfo
);
746 *ret
= &stream
->ITextStream_iface
;
750 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
752 struct drive
*This
= impl_from_IDrive(iface
);
754 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
758 if (IsEqualIID( riid
, &IID_IDrive
) ||
759 IsEqualIID( riid
, &IID_IDispatch
) ||
760 IsEqualIID( riid
, &IID_IUnknown
))
762 *obj
= &This
->IDrive_iface
;
764 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
766 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
769 return E_NOINTERFACE
;
771 IUnknown_AddRef((IUnknown
*)*obj
);
775 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
777 struct drive
*This
= impl_from_IDrive(iface
);
778 ULONG ref
= InterlockedIncrement(&This
->ref
);
779 TRACE("(%p)->(%d)\n", This
, ref
);
783 static ULONG WINAPI
drive_Release(IDrive
*iface
)
785 struct drive
*This
= impl_from_IDrive(iface
);
786 ULONG ref
= InterlockedDecrement(&This
->ref
);
787 TRACE("(%p)->(%d)\n", This
, ref
);
791 SysFreeString(This
->root
);
798 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
800 struct drive
*This
= impl_from_IDrive(iface
);
801 TRACE("(%p)->(%p)\n", This
, pctinfo
);
806 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
807 LCID lcid
, ITypeInfo
**ppTInfo
)
809 struct drive
*This
= impl_from_IDrive(iface
);
810 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
811 return get_typeinfo(IDrive_tid
, ppTInfo
);
814 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
815 LPOLESTR
*rgszNames
, UINT cNames
,
816 LCID lcid
, DISPID
*rgDispId
)
818 struct drive
*This
= impl_from_IDrive(iface
);
822 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
824 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
827 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
828 ITypeInfo_Release(typeinfo
);
834 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
835 REFIID riid
, LCID lcid
, WORD wFlags
,
836 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
837 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
839 struct drive
*This
= impl_from_IDrive(iface
);
843 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
844 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
846 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
849 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
850 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
851 ITypeInfo_Release(typeinfo
);
857 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
859 struct drive
*This
= impl_from_IDrive(iface
);
860 FIXME("(%p)->(%p): stub\n", This
, path
);
864 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
866 struct drive
*This
= impl_from_IDrive(iface
);
868 TRACE("(%p)->(%p)\n", This
, letter
);
873 *letter
= SysAllocStringLen(This
->root
, 1);
875 return E_OUTOFMEMORY
;
880 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
882 struct drive
*This
= impl_from_IDrive(iface
);
883 FIXME("(%p)->(%p): stub\n", This
, share_name
);
887 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
889 struct drive
*This
= impl_from_IDrive(iface
);
891 TRACE("(%p)->(%p)\n", This
, type
);
893 switch (GetDriveTypeW(This
->root
))
895 case DRIVE_REMOVABLE
:
918 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
920 struct drive
*This
= impl_from_IDrive(iface
);
921 FIXME("(%p)->(%p): stub\n", This
, folder
);
925 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
929 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
932 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
937 V_I4(v
) = src
->u
.LowPart
;
943 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
945 struct drive
*This
= impl_from_IDrive(iface
);
946 ULARGE_INTEGER avail
;
948 TRACE("(%p)->(%p)\n", This
, v
);
953 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
956 return variant_from_largeint(&avail
, v
);
959 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
961 struct drive
*This
= impl_from_IDrive(iface
);
962 ULARGE_INTEGER freespace
;
964 TRACE("(%p)->(%p)\n", This
, v
);
969 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
972 return variant_from_largeint(&freespace
, v
);
975 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
977 struct drive
*This
= impl_from_IDrive(iface
);
978 ULARGE_INTEGER total
;
980 TRACE("(%p)->(%p)\n", This
, v
);
985 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
988 return variant_from_largeint(&total
, v
);
991 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
993 struct drive
*This
= impl_from_IDrive(iface
);
994 WCHAR nameW
[MAX_PATH
+1];
997 TRACE("(%p)->(%p)\n", This
, name
);
1003 ret
= GetVolumeInformationW(This
->root
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, NULL
, NULL
, NULL
, 0);
1005 *name
= SysAllocString(nameW
);
1006 return ret
? S_OK
: E_FAIL
;
1009 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
1011 struct drive
*This
= impl_from_IDrive(iface
);
1012 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1016 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
1018 struct drive
*This
= impl_from_IDrive(iface
);
1019 WCHAR nameW
[MAX_PATH
+1];
1022 TRACE("(%p)->(%p)\n", This
, fs
);
1028 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
1030 *fs
= SysAllocString(nameW
);
1031 return ret
? S_OK
: E_FAIL
;
1034 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
1036 struct drive
*This
= impl_from_IDrive(iface
);
1039 TRACE("(%p)->(%p)\n", This
, serial
);
1044 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1045 return ret
? S_OK
: E_FAIL
;
1048 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1050 struct drive
*This
= impl_from_IDrive(iface
);
1051 ULARGE_INTEGER freespace
;
1054 TRACE("(%p)->(%p)\n", This
, ready
);
1059 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1060 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1064 static const IDriveVtbl drivevtbl
= {
1065 drive_QueryInterface
,
1068 drive_GetTypeInfoCount
,
1070 drive_GetIDsOfNames
,
1073 drive_get_DriveLetter
,
1074 drive_get_ShareName
,
1075 drive_get_DriveType
,
1076 drive_get_RootFolder
,
1077 drive_get_AvailableSpace
,
1078 drive_get_FreeSpace
,
1079 drive_get_TotalSize
,
1080 drive_get_VolumeName
,
1081 drive_put_VolumeName
,
1082 drive_get_FileSystem
,
1083 drive_get_SerialNumber
,
1087 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1093 This
= heap_alloc(sizeof(*This
));
1094 if (!This
) return E_OUTOFMEMORY
;
1096 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1098 This
->root
= SysAllocStringLen(NULL
, 3);
1102 return E_OUTOFMEMORY
;
1104 This
->root
[0] = letter
;
1105 This
->root
[1] = ':';
1106 This
->root
[2] = '\\';
1109 init_classinfo(&CLSID_Drive
, (IUnknown
*)&This
->IDrive_iface
, &This
->classinfo
);
1110 *drive
= &This
->IDrive_iface
;
1114 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1116 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1118 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1122 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1123 IsEqualIID( riid
, &IID_IUnknown
))
1126 IEnumVARIANT_AddRef(iface
);
1129 return E_NOINTERFACE
;
1134 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1136 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1137 ULONG ref
= InterlockedIncrement(&This
->ref
);
1138 TRACE("(%p)->(%d)\n", This
, ref
);
1142 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1144 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1145 ULONG ref
= InterlockedDecrement(&This
->ref
);
1147 TRACE("(%p)->(%d)\n", This
, ref
);
1151 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1152 FindClose(This
->data
.u
.foldercoll
.find
);
1159 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1161 static const WCHAR allW
[] = {'*',0};
1162 WCHAR pathW
[MAX_PATH
];
1166 strcpyW(pathW
, path
);
1167 len
= strlenW(pathW
);
1168 if (len
&& pathW
[len
-1] != '\\')
1169 strcatW(pathW
, bsW
);
1170 strcatW(pathW
, allW
);
1171 handle
= FindFirstFileW(pathW
, data
);
1172 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1174 /* find first dir/file */
1177 if (file
? is_file_data(data
) : is_dir_data(data
))
1180 if (!FindNextFileW(handle
, data
))
1189 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1191 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1192 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1193 WIN32_FIND_DATAW data
;
1196 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1201 if (!celt
) return S_OK
;
1205 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1206 if (!handle
) return S_FALSE
;
1208 This
->data
.u
.foldercoll
.find
= handle
;
1212 if (!FindNextFileW(handle
, &data
))
1218 if (is_dir_data(&data
))
1224 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1225 hr
= create_folder(str
, &folder
);
1227 if (FAILED(hr
)) return hr
;
1229 V_VT(&var
[count
]) = VT_DISPATCH
;
1230 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1233 if (count
>= celt
) break;
1235 } while (FindNextFileW(handle
, &data
));
1240 return (count
< celt
) ? S_FALSE
: S_OK
;
1243 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1245 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1246 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1247 WIN32_FIND_DATAW data
;
1249 TRACE("(%p)->(%d)\n", This
, celt
);
1251 if (!celt
) return S_OK
;
1255 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1256 if (!handle
) return S_FALSE
;
1258 This
->data
.u
.foldercoll
.find
= handle
;
1262 if (!FindNextFileW(handle
, &data
))
1268 if (is_dir_data(&data
))
1272 } while (FindNextFileW(handle
, &data
));
1274 return celt
? S_FALSE
: S_OK
;
1277 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1279 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1281 TRACE("(%p)\n", This
);
1283 FindClose(This
->data
.u
.foldercoll
.find
);
1284 This
->data
.u
.foldercoll
.find
= NULL
;
1289 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1291 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1292 TRACE("(%p)->(%p)\n", This
, pclone
);
1293 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1296 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1297 enumvariant_QueryInterface
,
1299 foldercoll_enumvariant_Release
,
1300 foldercoll_enumvariant_Next
,
1301 foldercoll_enumvariant_Skip
,
1302 foldercoll_enumvariant_Reset
,
1303 foldercoll_enumvariant_Clone
1306 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1308 struct enumvariant
*This
;
1312 This
= heap_alloc(sizeof(*This
));
1313 if (!This
) return E_OUTOFMEMORY
;
1315 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1317 This
->data
.u
.foldercoll
.find
= NULL
;
1318 This
->data
.u
.foldercoll
.coll
= collection
;
1319 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1321 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1326 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1328 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1329 ULONG ref
= InterlockedDecrement(&This
->ref
);
1331 TRACE("(%p)->(%d)\n", This
, ref
);
1335 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1336 FindClose(This
->data
.u
.filecoll
.find
);
1343 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1345 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1346 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1347 WIN32_FIND_DATAW data
;
1350 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1355 if (!celt
) return S_OK
;
1359 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1360 if (!handle
) return S_FALSE
;
1361 This
->data
.u
.filecoll
.find
= handle
;
1363 else if (!FindNextFileW(handle
, &data
))
1368 if (is_file_data(&data
))
1374 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1375 hr
= create_file(str
, &file
);
1377 if (FAILED(hr
)) return hr
;
1379 V_VT(&var
[count
]) = VT_DISPATCH
;
1380 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1381 if (++count
>= celt
) break;
1383 } while (FindNextFileW(handle
, &data
));
1388 return (count
< celt
) ? S_FALSE
: S_OK
;
1391 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1393 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1394 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1395 WIN32_FIND_DATAW data
;
1397 TRACE("(%p)->(%d)\n", This
, celt
);
1399 if (!celt
) return S_OK
;
1403 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1404 if (!handle
) return S_FALSE
;
1405 This
->data
.u
.filecoll
.find
= handle
;
1407 else if (!FindNextFileW(handle
, &data
))
1412 if (is_file_data(&data
))
1414 } while (celt
&& FindNextFileW(handle
, &data
));
1416 return celt
? S_FALSE
: S_OK
;
1419 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1421 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1423 TRACE("(%p)\n", This
);
1425 FindClose(This
->data
.u
.filecoll
.find
);
1426 This
->data
.u
.filecoll
.find
= NULL
;
1431 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1433 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1434 TRACE("(%p)->(%p)\n", This
, pclone
);
1435 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1438 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1439 enumvariant_QueryInterface
,
1441 filecoll_enumvariant_Release
,
1442 filecoll_enumvariant_Next
,
1443 filecoll_enumvariant_Skip
,
1444 filecoll_enumvariant_Reset
,
1445 filecoll_enumvariant_Clone
1448 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1450 struct enumvariant
*This
;
1454 This
= heap_alloc(sizeof(*This
));
1455 if (!This
) return E_OUTOFMEMORY
;
1457 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1459 This
->data
.u
.filecoll
.find
= NULL
;
1460 This
->data
.u
.filecoll
.coll
= collection
;
1461 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1463 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1468 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1470 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1471 ULONG ref
= InterlockedDecrement(&This
->ref
);
1473 TRACE("(%p)->(%d)\n", This
, ref
);
1477 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1484 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1486 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1489 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1491 penum
->data
.u
.drivecoll
.cur
= i
;
1498 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1500 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1503 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1508 if (!celt
) return S_OK
;
1510 while (find_next_drive(This
) == S_OK
)
1515 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1516 if (FAILED(hr
)) return hr
;
1518 V_VT(&var
[count
]) = VT_DISPATCH
;
1519 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1521 if (++count
>= celt
) break;
1527 return (count
< celt
) ? S_FALSE
: S_OK
;
1530 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1532 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1534 TRACE("(%p)->(%d)\n", This
, celt
);
1536 if (!celt
) return S_OK
;
1538 while (celt
&& find_next_drive(This
) == S_OK
)
1541 return celt
? S_FALSE
: S_OK
;
1544 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1546 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1548 TRACE("(%p)\n", This
);
1550 This
->data
.u
.drivecoll
.cur
= -1;
1554 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1556 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1557 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1561 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1562 enumvariant_QueryInterface
,
1564 drivecoll_enumvariant_Release
,
1565 drivecoll_enumvariant_Next
,
1566 drivecoll_enumvariant_Skip
,
1567 drivecoll_enumvariant_Reset
,
1568 drivecoll_enumvariant_Clone
1571 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1573 struct enumvariant
*This
;
1577 This
= heap_alloc(sizeof(*This
));
1578 if (!This
) return E_OUTOFMEMORY
;
1580 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1582 This
->data
.u
.drivecoll
.coll
= collection
;
1583 This
->data
.u
.drivecoll
.cur
= -1;
1584 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1586 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1591 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1593 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1595 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1599 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1600 IsEqualIID( riid
, &IID_IDispatch
) ||
1601 IsEqualIID( riid
, &IID_IUnknown
))
1603 *obj
= &This
->IFolderCollection_iface
;
1605 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1607 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1610 return E_NOINTERFACE
;
1612 IUnknown_AddRef((IUnknown
*)*obj
);
1616 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1618 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1619 ULONG ref
= InterlockedIncrement(&This
->ref
);
1620 TRACE("(%p)->(%d)\n", This
, ref
);
1624 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1626 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1627 ULONG ref
= InterlockedDecrement(&This
->ref
);
1628 TRACE("(%p)->(%d)\n", This
, ref
);
1632 SysFreeString(This
->path
);
1639 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1641 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1642 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1647 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1648 LCID lcid
, ITypeInfo
**ppTInfo
)
1650 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1651 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1652 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1655 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1656 LPOLESTR
*rgszNames
, UINT cNames
,
1657 LCID lcid
, DISPID
*rgDispId
)
1659 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1660 ITypeInfo
*typeinfo
;
1663 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1665 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1668 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1669 ITypeInfo_Release(typeinfo
);
1675 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1676 REFIID riid
, LCID lcid
, WORD wFlags
,
1677 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1678 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1680 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1681 ITypeInfo
*typeinfo
;
1684 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1685 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1687 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1690 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1691 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1692 ITypeInfo_Release(typeinfo
);
1698 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1700 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1701 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1705 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1707 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1708 FIXME("(%p)->(%p): stub\n", This
, folder
);
1712 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1714 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1716 TRACE("(%p)->(%p)\n", This
, newenum
);
1721 return create_foldercoll_enum(This
, newenum
);
1724 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1726 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1727 static const WCHAR allW
[] = {'\\','*',0};
1728 WIN32_FIND_DATAW data
;
1729 WCHAR pathW
[MAX_PATH
];
1732 TRACE("(%p)->(%p)\n", This
, count
);
1739 strcpyW(pathW
, This
->path
);
1740 strcatW(pathW
, allW
);
1741 handle
= FindFirstFileW(pathW
, &data
);
1742 if (handle
== INVALID_HANDLE_VALUE
)
1743 return HRESULT_FROM_WIN32(GetLastError());
1747 if (is_dir_data(&data
))
1749 } while (FindNextFileW(handle
, &data
));
1755 static const IFolderCollectionVtbl foldercollvtbl
= {
1756 foldercoll_QueryInterface
,
1759 foldercoll_GetTypeInfoCount
,
1760 foldercoll_GetTypeInfo
,
1761 foldercoll_GetIDsOfNames
,
1764 foldercoll_get_Item
,
1765 foldercoll_get__NewEnum
,
1766 foldercoll_get_Count
1769 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1771 struct foldercollection
*This
;
1775 This
= heap_alloc(sizeof(struct foldercollection
));
1776 if (!This
) return E_OUTOFMEMORY
;
1778 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1780 This
->path
= SysAllocString(path
);
1784 return E_OUTOFMEMORY
;
1787 init_classinfo(&CLSID_Folders
, (IUnknown
*)&This
->IFolderCollection_iface
, &This
->classinfo
);
1788 *folders
= &This
->IFolderCollection_iface
;
1793 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1795 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1797 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1801 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1802 IsEqualIID( riid
, &IID_IDispatch
) ||
1803 IsEqualIID( riid
, &IID_IUnknown
))
1805 *obj
= &This
->IFileCollection_iface
;
1807 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1809 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1812 return E_NOINTERFACE
;
1814 IUnknown_AddRef((IUnknown
*)*obj
);
1818 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1820 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1821 ULONG ref
= InterlockedIncrement(&This
->ref
);
1822 TRACE("(%p)->(%d)\n", This
, ref
);
1826 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1828 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1829 ULONG ref
= InterlockedDecrement(&This
->ref
);
1830 TRACE("(%p)->(%d)\n", This
, ref
);
1834 SysFreeString(This
->path
);
1841 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1843 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1844 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1849 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1850 LCID lcid
, ITypeInfo
**ppTInfo
)
1852 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1853 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1854 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1857 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1858 LPOLESTR
*rgszNames
, UINT cNames
,
1859 LCID lcid
, DISPID
*rgDispId
)
1861 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1862 ITypeInfo
*typeinfo
;
1865 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1867 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1870 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1871 ITypeInfo_Release(typeinfo
);
1877 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1878 REFIID riid
, LCID lcid
, WORD wFlags
,
1879 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1880 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1882 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1883 ITypeInfo
*typeinfo
;
1886 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1887 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1889 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1892 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1893 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1894 ITypeInfo_Release(typeinfo
);
1900 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1902 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1903 FIXME("(%p)->(%p)\n", This
, file
);
1907 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1909 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1911 TRACE("(%p)->(%p)\n", This
, ppenum
);
1916 return create_filecoll_enum(This
, ppenum
);
1919 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1921 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1922 static const WCHAR allW
[] = {'\\','*',0};
1923 WIN32_FIND_DATAW data
;
1924 WCHAR pathW
[MAX_PATH
];
1927 TRACE("(%p)->(%p)\n", This
, count
);
1934 strcpyW(pathW
, This
->path
);
1935 strcatW(pathW
, allW
);
1936 handle
= FindFirstFileW(pathW
, &data
);
1937 if (handle
== INVALID_HANDLE_VALUE
)
1938 return HRESULT_FROM_WIN32(GetLastError());
1942 if (is_file_data(&data
))
1944 } while (FindNextFileW(handle
, &data
));
1950 static const IFileCollectionVtbl filecollectionvtbl
= {
1951 filecoll_QueryInterface
,
1954 filecoll_GetTypeInfoCount
,
1955 filecoll_GetTypeInfo
,
1956 filecoll_GetIDsOfNames
,
1959 filecoll_get__NewEnum
,
1963 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1965 struct filecollection
*This
;
1969 This
= heap_alloc(sizeof(*This
));
1970 if (!This
) return E_OUTOFMEMORY
;
1972 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1974 This
->path
= SysAllocString(path
);
1978 return E_OUTOFMEMORY
;
1981 init_classinfo(&CLSID_Files
, (IUnknown
*)&This
->IFileCollection_iface
, &This
->classinfo
);
1982 *files
= &This
->IFileCollection_iface
;
1986 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1988 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1990 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1994 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1995 IsEqualIID( riid
, &IID_IDispatch
) ||
1996 IsEqualIID( riid
, &IID_IUnknown
))
1998 *obj
= &This
->IDriveCollection_iface
;
2000 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2002 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2005 return E_NOINTERFACE
;
2007 IUnknown_AddRef((IUnknown
*)*obj
);
2011 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
2013 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2014 ULONG ref
= InterlockedIncrement(&This
->ref
);
2015 TRACE("(%p)->(%d)\n", This
, ref
);
2019 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
2021 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2022 ULONG ref
= InterlockedDecrement(&This
->ref
);
2023 TRACE("(%p)->(%d)\n", This
, ref
);
2031 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
2033 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2034 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2039 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
2040 LCID lcid
, ITypeInfo
**ppTInfo
)
2042 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2043 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2044 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
2047 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
2048 LPOLESTR
*rgszNames
, UINT cNames
,
2049 LCID lcid
, DISPID
*rgDispId
)
2051 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2052 ITypeInfo
*typeinfo
;
2055 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2057 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2060 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2061 ITypeInfo_Release(typeinfo
);
2067 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2068 REFIID riid
, LCID lcid
, WORD wFlags
,
2069 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2070 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2072 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2073 ITypeInfo
*typeinfo
;
2076 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2077 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2079 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2082 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2083 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2084 ITypeInfo_Release(typeinfo
);
2090 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2092 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2093 FIXME("(%p)->(%p): stub\n", This
, drive
);
2097 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2099 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2101 TRACE("(%p)->(%p)\n", This
, ppenum
);
2106 return create_drivecoll_enum(This
, ppenum
);
2109 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2111 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2113 TRACE("(%p)->(%p)\n", This
, count
);
2115 if (!count
) return E_POINTER
;
2117 *count
= This
->count
;
2121 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2122 drivecoll_QueryInterface
,
2125 drivecoll_GetTypeInfoCount
,
2126 drivecoll_GetTypeInfo
,
2127 drivecoll_GetIDsOfNames
,
2130 drivecoll_get__NewEnum
,
2134 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2136 struct drivecollection
*This
;
2141 This
= heap_alloc(sizeof(*This
));
2142 if (!This
) return E_OUTOFMEMORY
;
2144 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2146 This
->drives
= mask
= GetLogicalDrives();
2147 /* count set bits */
2148 for (This
->count
= 0; mask
; This
->count
++)
2151 init_classinfo(&CLSID_Drives
, (IUnknown
*)&This
->IDriveCollection_iface
, &This
->classinfo
);
2152 *drives
= &This
->IDriveCollection_iface
;
2156 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2158 struct folder
*This
= impl_from_IFolder(iface
);
2160 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2164 if (IsEqualIID( riid
, &IID_IFolder
) ||
2165 IsEqualIID( riid
, &IID_IDispatch
) ||
2166 IsEqualIID( riid
, &IID_IUnknown
))
2168 *obj
= &This
->IFolder_iface
;
2170 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2172 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2175 return E_NOINTERFACE
;
2177 IUnknown_AddRef((IUnknown
*)*obj
);
2181 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2183 struct folder
*This
= impl_from_IFolder(iface
);
2184 ULONG ref
= InterlockedIncrement(&This
->ref
);
2185 TRACE("(%p)->(%d)\n", This
, ref
);
2189 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2191 struct folder
*This
= impl_from_IFolder(iface
);
2192 ULONG ref
= InterlockedDecrement(&This
->ref
);
2193 TRACE("(%p)->(%d)\n", This
, ref
);
2197 SysFreeString(This
->path
);
2204 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2206 struct folder
*This
= impl_from_IFolder(iface
);
2207 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2212 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2213 LCID lcid
, ITypeInfo
**ppTInfo
)
2215 struct folder
*This
= impl_from_IFolder(iface
);
2216 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2217 return get_typeinfo(IFolder_tid
, ppTInfo
);
2220 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2221 LPOLESTR
*rgszNames
, UINT cNames
,
2222 LCID lcid
, DISPID
*rgDispId
)
2224 struct folder
*This
= impl_from_IFolder(iface
);
2225 ITypeInfo
*typeinfo
;
2228 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2230 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2233 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2234 ITypeInfo_Release(typeinfo
);
2240 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2241 REFIID riid
, LCID lcid
, WORD wFlags
,
2242 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2243 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2245 struct folder
*This
= impl_from_IFolder(iface
);
2246 ITypeInfo
*typeinfo
;
2249 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2250 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2252 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2255 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2256 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2257 ITypeInfo_Release(typeinfo
);
2263 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2265 struct folder
*This
= impl_from_IFolder(iface
);
2267 TRACE("(%p)->(%p)\n", This
, path
);
2272 *path
= SysAllocString(This
->path
);
2273 return *path
? S_OK
: E_OUTOFMEMORY
;
2276 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2278 struct folder
*This
= impl_from_IFolder(iface
);
2281 TRACE("(%p)->(%p)\n", This
, name
);
2288 ptr
= strrchrW(This
->path
, '\\');
2291 *name
= SysAllocString(ptr
+1);
2292 TRACE("%s\n", debugstr_w(*name
));
2293 if (!*name
) return E_OUTOFMEMORY
;
2301 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2303 struct folder
*This
= impl_from_IFolder(iface
);
2304 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2308 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2310 struct folder
*This
= impl_from_IFolder(iface
);
2311 FIXME("(%p)->(%p): stub\n", This
, path
);
2315 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2317 struct folder
*This
= impl_from_IFolder(iface
);
2318 FIXME("(%p)->(%p): stub\n", This
, name
);
2322 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2324 struct folder
*This
= impl_from_IFolder(iface
);
2325 FIXME("(%p)->(%p): stub\n", This
, drive
);
2329 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2331 struct folder
*This
= impl_from_IFolder(iface
);
2332 FIXME("(%p)->(%p): stub\n", This
, parent
);
2336 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2338 struct folder
*This
= impl_from_IFolder(iface
);
2339 FIXME("(%p)->(%p): stub\n", This
, attr
);
2343 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2345 struct folder
*This
= impl_from_IFolder(iface
);
2346 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2350 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2352 struct folder
*This
= impl_from_IFolder(iface
);
2353 FIXME("(%p)->(%p): stub\n", This
, date
);
2357 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2359 struct folder
*This
= impl_from_IFolder(iface
);
2360 FIXME("(%p)->(%p): stub\n", This
, date
);
2364 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2366 struct folder
*This
= impl_from_IFolder(iface
);
2367 FIXME("(%p)->(%p): stub\n", This
, date
);
2371 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2373 struct folder
*This
= impl_from_IFolder(iface
);
2374 FIXME("(%p)->(%p): stub\n", This
, type
);
2378 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2380 struct folder
*This
= impl_from_IFolder(iface
);
2381 FIXME("(%p)->(%x): stub\n", This
, force
);
2385 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2387 struct folder
*This
= impl_from_IFolder(iface
);
2388 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2392 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2394 struct folder
*This
= impl_from_IFolder(iface
);
2395 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2399 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2401 struct folder
*This
= impl_from_IFolder(iface
);
2402 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2406 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2408 struct folder
*This
= impl_from_IFolder(iface
);
2409 FIXME("(%p)->(%p): stub\n", This
, size
);
2413 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2415 struct folder
*This
= impl_from_IFolder(iface
);
2417 TRACE("(%p)->(%p)\n", This
, folders
);
2422 return create_foldercoll(This
->path
, folders
);
2425 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2427 struct folder
*This
= impl_from_IFolder(iface
);
2429 TRACE("(%p)->(%p)\n", This
, files
);
2434 return create_filecoll(This
->path
, files
);
2437 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2438 VARIANT_BOOL unicode
, ITextStream
**stream
)
2440 struct folder
*This
= impl_from_IFolder(iface
);
2441 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2445 static const IFolderVtbl foldervtbl
= {
2446 folder_QueryInterface
,
2449 folder_GetTypeInfoCount
,
2451 folder_GetIDsOfNames
,
2456 folder_get_ShortPath
,
2457 folder_get_ShortName
,
2459 folder_get_ParentFolder
,
2460 folder_get_Attributes
,
2461 folder_put_Attributes
,
2462 folder_get_DateCreated
,
2463 folder_get_DateLastModified
,
2464 folder_get_DateLastAccessed
,
2469 folder_get_IsRootFolder
,
2471 folder_get_SubFolders
,
2473 folder_CreateTextFile
2476 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2478 struct folder
*This
;
2482 TRACE("%s\n", debugstr_w(path
));
2484 This
= heap_alloc(sizeof(struct folder
));
2485 if (!This
) return E_OUTOFMEMORY
;
2487 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2489 This
->path
= SysAllocString(path
);
2493 return E_OUTOFMEMORY
;
2496 init_classinfo(&CLSID_Folder
, (IUnknown
*)&This
->IFolder_iface
, &This
->classinfo
);
2497 *folder
= &This
->IFolder_iface
;
2502 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2504 struct file
*This
= impl_from_IFile(iface
);
2506 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2510 if (IsEqualIID(riid
, &IID_IFile
) ||
2511 IsEqualIID(riid
, &IID_IDispatch
) ||
2512 IsEqualIID(riid
, &IID_IUnknown
))
2514 *obj
= &This
->IFile_iface
;
2516 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2518 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2521 return E_NOINTERFACE
;
2523 IUnknown_AddRef((IUnknown
*)*obj
);
2527 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2529 struct file
*This
= impl_from_IFile(iface
);
2530 LONG ref
= InterlockedIncrement(&This
->ref
);
2532 TRACE("(%p) ref=%d\n", This
, ref
);
2537 static ULONG WINAPI
file_Release(IFile
*iface
)
2539 struct file
*This
= impl_from_IFile(iface
);
2540 LONG ref
= InterlockedDecrement(&This
->ref
);
2542 TRACE("(%p) ref=%d\n", This
, ref
);
2546 heap_free(This
->path
);
2553 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2555 struct file
*This
= impl_from_IFile(iface
);
2557 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2563 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2564 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2566 struct file
*This
= impl_from_IFile(iface
);
2568 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2570 return get_typeinfo(IFile_tid
, ppTInfo
);
2573 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2574 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2576 struct file
*This
= impl_from_IFile(iface
);
2577 ITypeInfo
*typeinfo
;
2580 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2581 rgszNames
, cNames
, lcid
, rgDispId
);
2583 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2585 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2586 ITypeInfo_Release(typeinfo
);
2591 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2593 struct file
*This
= impl_from_IFile(iface
);
2594 ITypeInfo
*typeinfo
;
2597 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2598 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2600 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2603 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2604 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2605 ITypeInfo_Release(typeinfo
);
2610 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2612 struct file
*This
= impl_from_IFile(iface
);
2614 TRACE("(%p)->(%p)\n", This
, path
);
2619 *path
= SysAllocString(This
->path
);
2621 return E_OUTOFMEMORY
;
2626 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2628 struct file
*This
= impl_from_IFile(iface
);
2631 TRACE("(%p)->(%p)\n", This
, name
);
2638 ptr
= strrchrW(This
->path
, '\\');
2641 *name
= SysAllocString(ptr
+1);
2642 TRACE("%s\n", debugstr_w(*name
));
2643 if (!*name
) return E_OUTOFMEMORY
;
2651 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2653 struct file
*This
= impl_from_IFile(iface
);
2654 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2658 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2660 struct file
*This
= impl_from_IFile(iface
);
2661 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2665 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2667 struct file
*This
= impl_from_IFile(iface
);
2668 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2672 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2674 struct file
*This
= impl_from_IFile(iface
);
2675 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2679 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2681 struct file
*This
= impl_from_IFile(iface
);
2682 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2686 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2688 struct file
*This
= impl_from_IFile(iface
);
2691 TRACE("(%p)->(%p)\n", This
, pfa
);
2696 fa
= GetFileAttributesW(This
->path
);
2697 if(fa
== INVALID_FILE_ATTRIBUTES
)
2698 return create_error(GetLastError());
2700 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2701 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2702 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2706 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2708 struct file
*This
= impl_from_IFile(iface
);
2710 TRACE("(%p)->(%x)\n", This
, pfa
);
2712 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2715 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2717 struct file
*This
= impl_from_IFile(iface
);
2718 FIXME("(%p)->(%p)\n", This
, pdate
);
2722 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2724 struct file
*This
= impl_from_IFile(iface
);
2725 FIXME("(%p)->(%p)\n", This
, pdate
);
2729 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2731 struct file
*This
= impl_from_IFile(iface
);
2732 FIXME("(%p)->(%p)\n", This
, pdate
);
2736 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2738 struct file
*This
= impl_from_IFile(iface
);
2739 ULARGE_INTEGER size
;
2740 WIN32_FIND_DATAW fd
;
2743 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2748 f
= FindFirstFileW(This
->path
, &fd
);
2749 if(f
== INVALID_HANDLE_VALUE
)
2750 return create_error(GetLastError());
2753 size
.u
.LowPart
= fd
.nFileSizeLow
;
2754 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2756 return variant_from_largeint(&size
, pvarSize
);
2759 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2761 struct file
*This
= impl_from_IFile(iface
);
2762 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2766 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2768 struct file
*This
= impl_from_IFile(iface
);
2769 FIXME("(%p)->(%x)\n", This
, Force
);
2773 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2775 struct file
*This
= impl_from_IFile(iface
);
2776 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2780 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2782 struct file
*This
= impl_from_IFile(iface
);
2783 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2787 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2789 struct file
*This
= impl_from_IFile(iface
);
2791 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2793 if (format
== TristateUseDefault
) {
2794 FIXME("default format not handled, defaulting to unicode\n");
2795 format
= TristateTrue
;
2798 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2801 static const IFileVtbl file_vtbl
= {
2802 file_QueryInterface
,
2805 file_GetTypeInfoCount
,
2815 file_get_ParentFolder
,
2816 file_get_Attributes
,
2817 file_put_Attributes
,
2818 file_get_DateCreated
,
2819 file_get_DateLastModified
,
2820 file_get_DateLastAccessed
,
2826 file_OpenAsTextStream
2829 static HRESULT
create_file(BSTR path
, IFile
**file
)
2836 f
= heap_alloc(sizeof(struct file
));
2838 return E_OUTOFMEMORY
;
2840 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2843 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2849 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2852 return E_OUTOFMEMORY
;
2855 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2861 attrs
= GetFileAttributesW(f
->path
);
2862 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2863 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2866 return create_error(GetLastError());
2869 init_classinfo(&CLSID_File
, (IUnknown
*)&f
->IFile_iface
, &f
->classinfo
);
2870 *file
= &f
->IFile_iface
;
2874 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2876 struct filesystem
*This
= impl_from_IFileSystem3(iface
);
2878 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2880 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2881 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2882 IsEqualGUID( riid
, &IID_IDispatch
) ||
2883 IsEqualGUID( riid
, &IID_IUnknown
) )
2885 *ppvObject
= &This
->IFileSystem3_iface
;
2887 else if (IsEqualGUID( riid
, &IID_IProvideClassInfo
))
2889 *ppvObject
= &This
->classinfo
.IProvideClassInfo_iface
;
2891 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2893 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2895 return E_NOINTERFACE
;
2897 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2899 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2901 return E_NOINTERFACE
;
2905 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2906 return E_NOINTERFACE
;
2909 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2914 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2916 TRACE("%p\n", iface
);
2921 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2923 TRACE("%p\n", iface
);
2928 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2930 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2936 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2937 LCID lcid
, ITypeInfo
**ppTInfo
)
2939 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2940 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2943 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2944 LPOLESTR
*rgszNames
, UINT cNames
,
2945 LCID lcid
, DISPID
*rgDispId
)
2947 ITypeInfo
*typeinfo
;
2950 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2952 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2955 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2956 ITypeInfo_Release(typeinfo
);
2962 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2963 REFIID riid
, LCID lcid
, WORD wFlags
,
2964 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2965 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2967 ITypeInfo
*typeinfo
;
2970 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2971 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2973 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2976 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2977 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2978 ITypeInfo_Release(typeinfo
);
2984 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2986 TRACE("%p %p\n", iface
, ppdrives
);
2987 return create_drivecoll(ppdrives
);
2990 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2991 BSTR Name
, BSTR
*Result
)
2995 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2997 if (!Result
) return E_POINTER
;
3001 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
3003 /* if both parts have backslashes strip one from Path */
3004 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
3008 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3016 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
3018 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
3022 if (Path
[path_len
-1] != ':')
3029 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3037 else if (Path
|| Name
)
3038 ret
= SysAllocString(Path
? Path
: Name
);
3040 ret
= SysAllocStringLen(NULL
, 0);
3042 if (!ret
) return E_OUTOFMEMORY
;
3048 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
3050 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
3057 if (path
&& strlenW(path
) > 1 && path
[1] == ':')
3058 *drive
= SysAllocStringLen(path
, 2);
3063 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
3070 for(i
=len
-1; i
>=0; i
--)
3071 if(path
[i
]!='/' && path
[i
]!='\\')
3075 if(path
[i
]=='/' || path
[i
]=='\\')
3079 if(path
[i
]!='/' && path
[i
]!='\\')
3085 if(path
[i
]==':' && i
==1)
3090 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3095 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3100 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3102 *pbstrResult
= NULL
;
3106 *pbstrResult
= SysAllocStringLen(Path
, len
);
3108 return E_OUTOFMEMORY
;
3112 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3117 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3123 *pbstrResult
= NULL
;
3127 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3128 if(Path
[end
]!='/' && Path
[end
]!='\\')
3131 for(i
=end
; i
>=0; i
--)
3132 if(Path
[i
]=='/' || Path
[i
]=='\\')
3136 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3137 *pbstrResult
= NULL
;
3141 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3143 return E_OUTOFMEMORY
;
3147 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3152 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3158 *pbstrResult
= NULL
;
3162 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3163 if(Path
[end
]!='/' && Path
[end
]!='\\')
3166 for(i
=end
; i
>=0; i
--) {
3167 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3169 if(Path
[i
]=='/' || Path
[i
]=='\\')
3174 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3175 *pbstrResult
= NULL
;
3179 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3181 return E_OUTOFMEMORY
;
3185 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3190 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3193 len
= SysStringLen(path
);
3195 if (path
[len
-1] == '.') {
3196 *ext
= SysAllocString(&path
[len
]);
3198 return E_OUTOFMEMORY
;
3207 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3210 static const WCHAR cur_path
[] = {'.',0};
3212 WCHAR buf
[MAX_PATH
], ch
;
3214 DWORD i
, beg
, len
, exp_len
;
3215 WIN32_FIND_DATAW fdata
;
3218 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3228 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3232 buf
[0] = toupperW(buf
[0]);
3233 if(len
>3 && buf
[len
-1] == '\\')
3236 for(beg
=3, i
=3; i
<=len
; i
++) {
3237 if(buf
[i
]!='\\' && buf
[i
])
3242 fh
= FindFirstFileW(buf
, &fdata
);
3243 if(fh
== INVALID_HANDLE_VALUE
)
3246 exp_len
= strlenW(fdata
.cFileName
);
3247 if(exp_len
== i
-beg
)
3248 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3254 *pbstrResult
= SysAllocString(buf
);
3256 return E_OUTOFMEMORY
;
3260 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3262 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3266 TRACE("%p %p\n", iface
, pbstrResult
);
3271 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3273 return E_OUTOFMEMORY
;
3275 if(!RtlGenRandom(&random
, sizeof(random
)))
3277 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3281 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3282 VARIANT_BOOL
*pfExists
)
3286 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3288 if (!pfExists
) return E_POINTER
;
3290 *pfExists
= VARIANT_FALSE
;
3291 len
= SysStringLen(DriveSpec
);
3294 driveletter
= toupperW(DriveSpec
[0]);
3295 if (driveletter
>= 'A' && driveletter
<= 'Z'
3296 && (len
< 2 || DriveSpec
[1] == ':')
3297 && (len
< 3 || DriveSpec
[2] == '\\')) {
3298 const WCHAR root
[] = {driveletter
, ':', '\\', 0};
3299 UINT drivetype
= GetDriveTypeW(root
);
3300 *pfExists
= drivetype
!= DRIVE_NO_ROOT_DIR
&& drivetype
!= DRIVE_UNKNOWN
? VARIANT_TRUE
: VARIANT_FALSE
;
3307 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3310 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3312 if (!ret
) return E_POINTER
;
3314 attrs
= GetFileAttributesW(path
);
3315 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3319 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3322 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3324 if (!ret
) return E_POINTER
;
3326 attrs
= GetFileAttributesW(path
);
3327 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3332 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3338 VARIANT_BOOL drive_exists
;
3340 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3347 /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3348 len
= SysStringLen(DriveSpec
);
3350 return E_INVALIDARG
;
3351 else if (len
<= 3) {
3352 driveletter
= toupperW(DriveSpec
[0]);
3353 if (driveletter
< 'A' || driveletter
> 'Z'
3354 || (len
>= 2 && DriveSpec
[1] != ':')
3355 || (len
== 3 && DriveSpec
[2] != '\\'))
3356 return E_INVALIDARG
;
3357 hr
= IFileSystem3_DriveExists(iface
, DriveSpec
, &drive_exists
);
3360 if (drive_exists
== VARIANT_FALSE
)
3361 return CTL_E_DEVICEUNAVAILABLE
;
3362 return create_drive(driveletter
, ppdrive
);
3364 if (DriveSpec
[0] != '\\' || DriveSpec
[1] != '\\')
3365 return E_INVALIDARG
;
3366 FIXME("%s not implemented yet\n", debugstr_w(DriveSpec
));
3371 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3374 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3379 return E_INVALIDARG
;
3381 return create_file(FilePath
, ppfile
);
3384 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3389 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3396 return E_INVALIDARG
;
3398 attrs
= GetFileAttributesW(FolderPath
);
3399 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3400 return CTL_E_PATHNOTFOUND
;
3402 return create_folder(FolderPath
, folder
);
3405 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3406 SpecialFolderConst SpecialFolder
,
3409 WCHAR pathW
[MAX_PATH
];
3412 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3419 switch (SpecialFolder
)
3422 ret
= GetWindowsDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3425 ret
= GetSystemDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3427 case TemporaryFolder
:
3428 ret
= GetTempPathW(sizeof(pathW
)/sizeof(WCHAR
), pathW
);
3429 /* we don't want trailing backslash */
3430 if (ret
&& pathW
[ret
-1] == '\\')
3434 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3435 return E_INVALIDARG
;
3439 return HRESULT_FROM_WIN32(GetLastError());
3441 return create_folder(pathW
, folder
);
3444 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3446 WCHAR path
[MAX_PATH
];
3447 DWORD len
, name_len
;
3448 WIN32_FIND_DATAW ffd
;
3451 f
= FindFirstFileW(file
, &ffd
);
3452 if(f
== INVALID_HANDLE_VALUE
)
3453 return create_error(GetLastError());
3455 len
= get_parent_folder_name(file
, file_len
);
3456 if(len
+1 >= MAX_PATH
) {
3461 memcpy(path
, file
, len
*sizeof(WCHAR
));
3466 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3469 name_len
= strlenW(ffd
.cFileName
);
3470 if(len
+name_len
+1 >= MAX_PATH
) {
3474 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3476 TRACE("deleting %s\n", debugstr_w(path
));
3478 if(!DeleteFileW(path
)) {
3479 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3480 || !DeleteFileW(path
)) {
3482 return create_error(GetLastError());
3485 } while(FindNextFileW(f
, &ffd
));
3491 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3494 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3499 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3502 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3504 WCHAR path
[MAX_PATH
];
3505 DWORD len
, name_len
;
3506 WIN32_FIND_DATAW ffd
;
3510 f
= FindFirstFileW(folder
, &ffd
);
3511 if(f
== INVALID_HANDLE_VALUE
)
3512 return create_error(GetLastError());
3514 len
= get_parent_folder_name(folder
, folder_len
);
3515 if(len
+1 >= MAX_PATH
) {
3520 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3525 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3527 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3528 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3531 name_len
= strlenW(ffd
.cFileName
);
3532 if(len
+name_len
+3 >= MAX_PATH
) {
3536 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3537 path
[len
+name_len
] = '\\';
3538 path
[len
+name_len
+1] = '*';
3539 path
[len
+name_len
+2] = 0;
3541 hr
= delete_file(path
, len
+name_len
+2, force
);
3547 hr
= delete_folder(path
, len
+name_len
+2, force
);
3553 path
[len
+name_len
] = 0;
3554 TRACE("deleting %s\n", debugstr_w(path
));
3556 if(!RemoveDirectoryW(path
)) {
3558 return create_error(GetLastError());
3560 } while(FindNextFileW(f
, &ffd
));
3566 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3569 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3574 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3577 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3580 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3585 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3588 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3593 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3594 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3597 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3598 DWORD src_len
, dst_len
, name_len
;
3599 WIN32_FIND_DATAW ffd
;
3603 if(!source
[0] || !destination
[0])
3604 return E_INVALIDARG
;
3606 attrs
= GetFileAttributesW(destination
);
3607 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3608 attrs
= GetFileAttributesW(source
);
3609 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3610 return create_error(GetLastError());
3611 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3612 return CTL_E_FILENOTFOUND
;
3614 if(!CopyFileW(source
, destination
, !overwrite
))
3615 return create_error(GetLastError());
3619 f
= FindFirstFileW(source
, &ffd
);
3620 if(f
== INVALID_HANDLE_VALUE
)
3621 return CTL_E_FILENOTFOUND
;
3623 src_len
= get_parent_folder_name(source
, source_len
);
3624 if(src_len
+1 >= MAX_PATH
) {
3629 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3630 src_path
[src_len
++] = '\\';
3633 dst_len
= destination_len
;
3634 if(dst_len
+1 >= MAX_PATH
) {
3638 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3639 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3640 dst_path
[dst_len
++] = '\\';
3642 hr
= CTL_E_FILENOTFOUND
;
3644 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3647 name_len
= strlenW(ffd
.cFileName
);
3648 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3652 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3653 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3655 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3657 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3659 return create_error(GetLastError());
3663 } while(FindNextFileW(f
, &ffd
));
3669 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3670 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3672 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3674 if(!Source
|| !Destination
)
3677 return copy_file(Source
, SysStringLen(Source
), Destination
,
3678 SysStringLen(Destination
), OverWriteFiles
);
3681 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3682 DWORD destination_len
, VARIANT_BOOL overwrite
)
3684 DWORD tmp
, src_len
, dst_len
, name_len
;
3685 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3686 WIN32_FIND_DATAW ffd
;
3689 BOOL copied
= FALSE
;
3691 if(!source
[0] || !destination
[0])
3692 return E_INVALIDARG
;
3694 dst_len
= destination_len
;
3695 if(dst_len
+1 >= MAX_PATH
)
3697 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3699 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3700 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3701 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3702 if(!CreateDirectoryW(dst
, NULL
)) {
3703 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3704 tmp
= GetFileAttributesW(dst
);
3705 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3706 return CTL_E_FILEALREADYEXISTS
;
3708 return create_error(GetLastError());
3713 src_len
= source_len
;
3714 if(src_len
+2 >= MAX_PATH
)
3716 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3717 src
[src_len
++] = '\\';
3721 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3722 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3723 return create_error(GetLastError());
3725 f
= FindFirstFileW(src
, &ffd
);
3727 src_len
= get_parent_folder_name(source
, source_len
);
3728 if(src_len
+2 >= MAX_PATH
)
3730 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3732 src
[src_len
++] = '\\';
3734 f
= FindFirstFileW(source
, &ffd
);
3736 if(f
== INVALID_HANDLE_VALUE
)
3737 return CTL_E_PATHNOTFOUND
;
3739 dst
[dst_len
++] = '\\';
3743 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3745 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3746 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3749 name_len
= strlenW(ffd
.cFileName
);
3750 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3754 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3755 dst
[dst_len
+name_len
] = 0;
3756 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3757 src
[src_len
+name_len
] = '\\';
3758 src
[src_len
+name_len
+1] = '*';
3759 src
[src_len
+name_len
+2] = 0;
3761 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3763 if(!CreateDirectoryW(dst
, NULL
)) {
3764 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3765 tmp
= GetFileAttributesW(dst
);
3766 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3768 return CTL_E_FILEALREADYEXISTS
;
3773 return create_error(GetLastError());
3777 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3778 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3783 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3784 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3788 } while(FindNextFileW(f
, &ffd
));
3791 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3794 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3795 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3797 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3799 if(!Source
|| !Destination
)
3802 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3803 SysStringLen(Destination
), OverWriteFiles
);
3806 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3811 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3813 ret
= CreateDirectoryW(path
, NULL
);
3817 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3818 return HRESULT_FROM_WIN32(GetLastError());
3821 return create_folder(path
, folder
);
3824 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3825 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3826 ITextStream
**stream
)
3830 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3832 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3833 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3836 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3837 IOMode mode
, VARIANT_BOOL create
,
3838 Tristate format
, ITextStream
**stream
)
3842 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3843 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3845 if (format
== TristateUseDefault
) {
3846 FIXME("default format not handled, defaulting to unicode\n");
3847 format
= TristateTrue
;
3850 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3853 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3854 StandardStreamTypes StandardStreamType
,
3855 VARIANT_BOOL Unicode
,
3858 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3863 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3865 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3869 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3870 a
= (WORD
)( version
>> 48);
3871 b
= (WORD
)((version
>> 32) & 0xffff);
3872 c
= (WORD
)((version
>> 16) & 0xffff);
3873 d
= (WORD
)( version
& 0xffff);
3875 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3878 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3880 static const WCHAR rootW
[] = {'\\',0};
3881 VS_FIXEDFILEINFO
*info
;
3887 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3889 len
= GetFileVersionInfoSizeW(name
, NULL
);
3891 return HRESULT_FROM_WIN32(GetLastError());
3893 ptr
= heap_alloc(len
);
3894 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3897 return HRESULT_FROM_WIN32(GetLastError());
3900 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3904 return HRESULT_FROM_WIN32(GetLastError());
3907 get_versionstring(info
, ver
);
3910 *version
= SysAllocString(ver
);
3911 TRACE("version=%s\n", debugstr_w(ver
));
3916 static const struct IFileSystem3Vtbl filesys_vtbl
=
3918 filesys_QueryInterface
,
3921 filesys_GetTypeInfoCount
,
3922 filesys_GetTypeInfo
,
3923 filesys_GetIDsOfNames
,
3927 filesys_GetDriveName
,
3928 filesys_GetParentFolderName
,
3929 filesys_GetFileName
,
3930 filesys_GetBaseName
,
3931 filesys_GetExtensionName
,
3932 filesys_GetAbsolutePathName
,
3933 filesys_GetTempName
,
3934 filesys_DriveExists
,
3936 filesys_FolderExists
,
3940 filesys_GetSpecialFolder
,
3942 filesys_DeleteFolder
,
3947 filesys_CreateFolder
,
3948 filesys_CreateTextFile
,
3949 filesys_OpenTextFile
,
3950 filesys_GetStandardStream
,
3951 filesys_GetFileVersion
3954 static struct filesystem filesystem
;
3956 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3958 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3960 filesystem
.IFileSystem3_iface
.lpVtbl
= &filesys_vtbl
;
3961 init_classinfo(&CLSID_FileSystemObject
, (IUnknown
*)&filesystem
.IFileSystem3_iface
, &filesystem
.classinfo
);
3962 return IFileSystem3_QueryInterface(&filesystem
.IFileSystem3_iface
, riid
, ppv
);