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
19 #include "scrrun_private.h"
24 #include <wine/unicode.h>
26 static const WCHAR bsW
[] = {'\\',0};
27 static const WCHAR utf16bom
= 0xfeff;
30 struct provideclassinfo classinfo
;
31 IFileSystem3 IFileSystem3_iface
;
34 struct foldercollection
{
35 struct provideclassinfo classinfo
;
36 IFolderCollection IFolderCollection_iface
;
41 struct filecollection
{
42 struct provideclassinfo classinfo
;
43 IFileCollection IFileCollection_iface
;
48 struct drivecollection
{
49 struct provideclassinfo classinfo
;
50 IDriveCollection IDriveCollection_iface
;
61 struct foldercollection
*coll
;
66 struct filecollection
*coll
;
71 struct drivecollection
*coll
;
78 IEnumVARIANT IEnumVARIANT_iface
;
85 struct provideclassinfo classinfo
;
92 struct provideclassinfo classinfo
;
93 IFolder IFolder_iface
;
99 struct provideclassinfo classinfo
;
107 struct provideclassinfo classinfo
;
108 ITextStream ITextStream_iface
;
123 static inline struct filesystem
*impl_from_IFileSystem3(IFileSystem3
*iface
)
125 return CONTAINING_RECORD(iface
, struct filesystem
, IFileSystem3_iface
);
128 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
130 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
133 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
135 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
138 static inline struct file
*impl_from_IFile(IFile
*iface
)
140 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
143 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
145 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
148 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
150 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
153 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
155 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
158 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
160 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
163 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
165 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
168 static inline HRESULT
create_error(DWORD err
)
171 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
172 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
173 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
174 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
175 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
177 FIXME("Unsupported error code: %d\n", err
);
182 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
183 static HRESULT
create_file(BSTR
, IFile
**);
184 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
185 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
187 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
189 static const WCHAR dotdotW
[] = {'.','.',0};
190 static const WCHAR dotW
[] = {'.',0};
192 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
193 strcmpW(data
->cFileName
, dotdotW
) &&
194 strcmpW(data
->cFileName
, dotW
);
197 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
199 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
202 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
204 int len
= SysStringLen(path
);
205 WCHAR buffW
[MAX_PATH
];
207 strcpyW(buffW
, path
);
208 if (path
[len
-1] != '\\')
210 strcatW(buffW
, data
->cFileName
);
212 return SysAllocString(buffW
);
215 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
218 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
220 return This
->mode
== ForReading
;
223 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
225 struct textstream
*This
= impl_from_ITextStream(iface
);
227 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
229 if (IsEqualIID(riid
, &IID_ITextStream
) ||
230 IsEqualIID(riid
, &IID_IDispatch
) ||
231 IsEqualIID(riid
, &IID_IUnknown
))
233 *obj
= &This
->ITextStream_iface
;
235 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
237 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
240 return E_NOINTERFACE
;
242 IUnknown_AddRef((IUnknown
*)*obj
);
246 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
248 struct textstream
*This
= impl_from_ITextStream(iface
);
249 ULONG ref
= InterlockedIncrement(&This
->ref
);
250 TRACE("(%p)->(%d)\n", This
, ref
);
254 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
256 struct textstream
*This
= impl_from_ITextStream(iface
);
257 ULONG ref
= InterlockedDecrement(&This
->ref
);
258 TRACE("(%p)->(%d)\n", This
, ref
);
262 CloseHandle(This
->file
);
269 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
271 struct textstream
*This
= impl_from_ITextStream(iface
);
272 TRACE("(%p)->(%p)\n", This
, pctinfo
);
277 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
278 LCID lcid
, ITypeInfo
**ppTInfo
)
280 struct textstream
*This
= impl_from_ITextStream(iface
);
281 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
282 return get_typeinfo(ITextStream_tid
, ppTInfo
);
285 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
286 LPOLESTR
*rgszNames
, UINT cNames
,
287 LCID lcid
, DISPID
*rgDispId
)
289 struct textstream
*This
= impl_from_ITextStream(iface
);
293 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
295 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
298 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
299 ITypeInfo_Release(typeinfo
);
305 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
306 REFIID riid
, LCID lcid
, WORD wFlags
,
307 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
308 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
310 struct textstream
*This
= impl_from_ITextStream(iface
);
314 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
315 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
317 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
320 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
321 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
322 ITypeInfo_Release(typeinfo
);
328 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
330 struct textstream
*This
= impl_from_ITextStream(iface
);
331 FIXME("(%p)->(%p): stub\n", This
, line
);
335 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
337 struct textstream
*This
= impl_from_ITextStream(iface
);
338 FIXME("(%p)->(%p): stub\n", This
, column
);
342 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
344 struct textstream
*This
= impl_from_ITextStream(iface
);
345 LARGE_INTEGER pos
, dist
;
347 TRACE("(%p)->(%p)\n", This
, eos
);
352 if (textstream_check_iomode(This
, IORead
)) {
354 return CTL_E_BADFILEMODE
;
358 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
361 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? VARIANT_TRUE
: VARIANT_FALSE
;
365 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
367 struct textstream
*This
= impl_from_ITextStream(iface
);
368 FIXME("(%p)->(%p): stub\n", This
, eol
);
373 Reads 'toread' bytes from a file, converts if needed
374 BOM is skipped if 'bof' is set.
376 static HRESULT
textstream_read(struct textstream
*stream
, LONG toread
, BOOL bof
, BSTR
*text
)
384 *text
= SysAllocStringLen(NULL
, 0);
385 return *text
? S_FALSE
: E_OUTOFMEMORY
;
388 if (toread
< sizeof(WCHAR
))
389 return CTL_E_ENDOFFILE
;
391 buff
= heap_alloc(toread
);
393 return E_OUTOFMEMORY
;
395 ret
= ReadFile(stream
->file
, buff
, toread
, &read
, NULL
);
396 if (!ret
|| toread
!= read
) {
397 WARN("failed to read from file %d, %d, error %d\n", read
, toread
, GetLastError());
402 if (stream
->unicode
) {
406 if (bof
&& *(WCHAR
*)buff
== utf16bom
) {
407 read
-= sizeof(WCHAR
);
411 *text
= SysAllocStringLen(read
? (WCHAR
*)&buff
[i
] : NULL
, read
/sizeof(WCHAR
));
412 if (!*text
) hr
= E_OUTOFMEMORY
;
415 INT len
= MultiByteToWideChar(CP_ACP
, 0, buff
, read
, NULL
, 0);
416 *text
= SysAllocStringLen(NULL
, len
);
418 MultiByteToWideChar(CP_ACP
, 0, buff
, read
, *text
, len
);
427 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
429 struct textstream
*This
= impl_from_ITextStream(iface
);
430 LARGE_INTEGER start
, end
, dist
;
434 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
441 return len
== 0 ? S_OK
: E_INVALIDARG
;
443 if (textstream_check_iomode(This
, IORead
))
444 return CTL_E_BADFILEMODE
;
446 if (!This
->first_read
) {
450 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
454 if (eos
== VARIANT_TRUE
)
455 return CTL_E_ENDOFFILE
;
458 /* read everything from current position */
460 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
461 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
462 toread
= end
.QuadPart
- start
.QuadPart
;
464 dist
.QuadPart
= start
.QuadPart
;
465 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
467 This
->first_read
= FALSE
;
468 if (This
->unicode
) len
*= sizeof(WCHAR
);
470 hr
= textstream_read(This
, min(toread
, len
), start
.QuadPart
== 0, text
);
474 return toread
<= len
? S_FALSE
: S_OK
;
477 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
479 struct textstream
*This
= impl_from_ITextStream(iface
);
483 FIXME("(%p)->(%p): stub\n", This
, text
);
489 if (textstream_check_iomode(This
, IORead
))
490 return CTL_E_BADFILEMODE
;
493 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
497 if (eos
== VARIANT_TRUE
)
498 return CTL_E_ENDOFFILE
;
503 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
505 struct textstream
*This
= impl_from_ITextStream(iface
);
506 LARGE_INTEGER start
, end
, dist
;
510 TRACE("(%p)->(%p)\n", This
, text
);
516 if (textstream_check_iomode(This
, IORead
))
517 return CTL_E_BADFILEMODE
;
519 if (!This
->first_read
) {
523 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
527 if (eos
== VARIANT_TRUE
)
528 return CTL_E_ENDOFFILE
;
531 /* read everything from current position */
533 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
534 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
535 toread
= end
.QuadPart
- start
.QuadPart
;
537 dist
.QuadPart
= start
.QuadPart
;
538 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
540 This
->first_read
= FALSE
;
542 hr
= textstream_read(This
, toread
, start
.QuadPart
== 0, text
);
543 return FAILED(hr
) ? hr
: S_FALSE
;
546 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
551 if (stream
->unicode
) {
552 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
553 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
555 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
559 buffA
= heap_alloc(len
);
561 return E_OUTOFMEMORY
;
563 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
564 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
565 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
571 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
573 struct textstream
*This
= impl_from_ITextStream(iface
);
575 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
577 if (textstream_check_iomode(This
, IOWrite
))
578 return CTL_E_BADFILEMODE
;
580 return textstream_writestr(This
, text
);
583 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
585 static const WCHAR crlfW
[] = {'\r','\n'};
586 static const char crlfA
[] = {'\r','\n'};
587 DWORD written
= 0, len
;
591 if (stream
->unicode
) {
600 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
601 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
604 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
606 struct textstream
*This
= impl_from_ITextStream(iface
);
609 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
611 if (textstream_check_iomode(This
, IOWrite
))
612 return CTL_E_BADFILEMODE
;
614 hr
= textstream_writestr(This
, text
);
616 hr
= textstream_writecrlf(This
);
620 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
622 struct textstream
*This
= impl_from_ITextStream(iface
);
623 FIXME("(%p)->(%d): stub\n", This
, lines
);
627 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
629 struct textstream
*This
= impl_from_ITextStream(iface
);
630 FIXME("(%p)->(%d): stub\n", This
, count
);
634 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
636 struct textstream
*This
= impl_from_ITextStream(iface
);
637 FIXME("(%p): stub\n", This
);
641 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
643 struct textstream
*This
= impl_from_ITextStream(iface
);
646 TRACE("(%p)\n", This
);
648 if(!CloseHandle(This
->file
))
656 static const ITextStreamVtbl textstreamvtbl
= {
657 textstream_QueryInterface
,
660 textstream_GetTypeInfoCount
,
661 textstream_GetTypeInfo
,
662 textstream_GetIDsOfNames
,
665 textstream_get_Column
,
666 textstream_get_AtEndOfStream
,
667 textstream_get_AtEndOfLine
,
672 textstream_WriteLine
,
673 textstream_WriteBlankLines
,
679 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
681 struct textstream
*stream
;
684 /* map access mode */
688 access
= GENERIC_READ
;
691 access
= GENERIC_WRITE
;
694 access
= FILE_APPEND_DATA
;
700 stream
= heap_alloc(sizeof(struct textstream
));
701 if (!stream
) return E_OUTOFMEMORY
;
703 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
706 stream
->unicode
= unicode
;
707 stream
->first_read
= TRUE
;
709 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
710 if (stream
->file
== INVALID_HANDLE_VALUE
)
712 HRESULT hr
= create_error(GetLastError());
717 if (mode
== ForReading
)
718 GetFileSizeEx(stream
->file
, &stream
->size
);
720 stream
->size
.QuadPart
= 0;
722 /* Write Unicode BOM */
723 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
725 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
726 if (!ret
|| written
!= sizeof(utf16bom
)) {
727 ITextStream_Release(&stream
->ITextStream_iface
);
728 return create_error(GetLastError());
732 init_classinfo(&CLSID_TextStream
, (IUnknown
*)&stream
->ITextStream_iface
, &stream
->classinfo
);
733 *ret
= &stream
->ITextStream_iface
;
737 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
739 struct drive
*This
= impl_from_IDrive(iface
);
741 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
745 if (IsEqualIID( riid
, &IID_IDrive
) ||
746 IsEqualIID( riid
, &IID_IDispatch
) ||
747 IsEqualIID( riid
, &IID_IUnknown
))
749 *obj
= &This
->IDrive_iface
;
751 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
753 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
756 return E_NOINTERFACE
;
758 IUnknown_AddRef((IUnknown
*)*obj
);
762 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
764 struct drive
*This
= impl_from_IDrive(iface
);
765 ULONG ref
= InterlockedIncrement(&This
->ref
);
766 TRACE("(%p)->(%d)\n", This
, ref
);
770 static ULONG WINAPI
drive_Release(IDrive
*iface
)
772 struct drive
*This
= impl_from_IDrive(iface
);
773 ULONG ref
= InterlockedDecrement(&This
->ref
);
774 TRACE("(%p)->(%d)\n", This
, ref
);
778 SysFreeString(This
->root
);
785 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
787 struct drive
*This
= impl_from_IDrive(iface
);
788 TRACE("(%p)->(%p)\n", This
, pctinfo
);
793 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
794 LCID lcid
, ITypeInfo
**ppTInfo
)
796 struct drive
*This
= impl_from_IDrive(iface
);
797 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
798 return get_typeinfo(IDrive_tid
, ppTInfo
);
801 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
802 LPOLESTR
*rgszNames
, UINT cNames
,
803 LCID lcid
, DISPID
*rgDispId
)
805 struct drive
*This
= impl_from_IDrive(iface
);
809 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
811 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
814 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
815 ITypeInfo_Release(typeinfo
);
821 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
822 REFIID riid
, LCID lcid
, WORD wFlags
,
823 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
824 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
826 struct drive
*This
= impl_from_IDrive(iface
);
830 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
831 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
833 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
836 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
837 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
838 ITypeInfo_Release(typeinfo
);
844 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
846 struct drive
*This
= impl_from_IDrive(iface
);
847 FIXME("(%p)->(%p): stub\n", This
, path
);
851 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
853 struct drive
*This
= impl_from_IDrive(iface
);
855 TRACE("(%p)->(%p)\n", This
, letter
);
860 *letter
= SysAllocStringLen(This
->root
, 1);
862 return E_OUTOFMEMORY
;
867 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
869 struct drive
*This
= impl_from_IDrive(iface
);
870 FIXME("(%p)->(%p): stub\n", This
, share_name
);
874 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
876 struct drive
*This
= impl_from_IDrive(iface
);
878 TRACE("(%p)->(%p)\n", This
, type
);
880 switch (GetDriveTypeW(This
->root
))
882 case DRIVE_REMOVABLE
:
905 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
907 struct drive
*This
= impl_from_IDrive(iface
);
908 FIXME("(%p)->(%p): stub\n", This
, folder
);
912 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
916 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
919 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
924 V_I4(v
) = src
->u
.LowPart
;
930 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
932 struct drive
*This
= impl_from_IDrive(iface
);
933 ULARGE_INTEGER avail
;
935 TRACE("(%p)->(%p)\n", This
, v
);
940 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
943 return variant_from_largeint(&avail
, v
);
946 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
948 struct drive
*This
= impl_from_IDrive(iface
);
949 ULARGE_INTEGER freespace
;
951 TRACE("(%p)->(%p)\n", This
, v
);
956 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
959 return variant_from_largeint(&freespace
, v
);
962 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
964 struct drive
*This
= impl_from_IDrive(iface
);
965 ULARGE_INTEGER total
;
967 TRACE("(%p)->(%p)\n", This
, v
);
972 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
975 return variant_from_largeint(&total
, v
);
978 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
980 struct drive
*This
= impl_from_IDrive(iface
);
981 WCHAR nameW
[MAX_PATH
+1];
984 TRACE("(%p)->(%p)\n", This
, name
);
990 ret
= GetVolumeInformationW(This
->root
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, NULL
, NULL
, NULL
, 0);
992 *name
= SysAllocString(nameW
);
993 return ret
? S_OK
: E_FAIL
;
996 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
998 struct drive
*This
= impl_from_IDrive(iface
);
999 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1003 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
1005 struct drive
*This
= impl_from_IDrive(iface
);
1006 WCHAR nameW
[MAX_PATH
+1];
1009 TRACE("(%p)->(%p)\n", This
, fs
);
1015 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
1017 *fs
= SysAllocString(nameW
);
1018 return ret
? S_OK
: E_FAIL
;
1021 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
1023 struct drive
*This
= impl_from_IDrive(iface
);
1026 TRACE("(%p)->(%p)\n", This
, serial
);
1031 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1032 return ret
? S_OK
: E_FAIL
;
1035 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1037 struct drive
*This
= impl_from_IDrive(iface
);
1038 ULARGE_INTEGER freespace
;
1041 TRACE("(%p)->(%p)\n", This
, ready
);
1046 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1047 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1051 static const IDriveVtbl drivevtbl
= {
1052 drive_QueryInterface
,
1055 drive_GetTypeInfoCount
,
1057 drive_GetIDsOfNames
,
1060 drive_get_DriveLetter
,
1061 drive_get_ShareName
,
1062 drive_get_DriveType
,
1063 drive_get_RootFolder
,
1064 drive_get_AvailableSpace
,
1065 drive_get_FreeSpace
,
1066 drive_get_TotalSize
,
1067 drive_get_VolumeName
,
1068 drive_put_VolumeName
,
1069 drive_get_FileSystem
,
1070 drive_get_SerialNumber
,
1074 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1080 This
= heap_alloc(sizeof(*This
));
1081 if (!This
) return E_OUTOFMEMORY
;
1083 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1085 This
->root
= SysAllocStringLen(NULL
, 3);
1089 return E_OUTOFMEMORY
;
1091 This
->root
[0] = letter
;
1092 This
->root
[1] = ':';
1093 This
->root
[2] = '\\';
1096 init_classinfo(&CLSID_Drive
, (IUnknown
*)&This
->IDrive_iface
, &This
->classinfo
);
1097 *drive
= &This
->IDrive_iface
;
1101 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1103 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1105 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1109 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1110 IsEqualIID( riid
, &IID_IUnknown
))
1113 IEnumVARIANT_AddRef(iface
);
1116 return E_NOINTERFACE
;
1121 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1123 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1124 ULONG ref
= InterlockedIncrement(&This
->ref
);
1125 TRACE("(%p)->(%d)\n", This
, ref
);
1129 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1131 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1132 ULONG ref
= InterlockedDecrement(&This
->ref
);
1134 TRACE("(%p)->(%d)\n", This
, ref
);
1138 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1139 FindClose(This
->data
.u
.foldercoll
.find
);
1146 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1148 static const WCHAR allW
[] = {'*',0};
1149 WCHAR pathW
[MAX_PATH
];
1153 strcpyW(pathW
, path
);
1154 len
= strlenW(pathW
);
1155 if (len
&& pathW
[len
-1] != '\\')
1156 strcatW(pathW
, bsW
);
1157 strcatW(pathW
, allW
);
1158 handle
= FindFirstFileW(pathW
, data
);
1159 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1161 /* find first dir/file */
1164 if (file
? is_file_data(data
) : is_dir_data(data
))
1167 if (!FindNextFileW(handle
, data
))
1176 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1178 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1179 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1180 WIN32_FIND_DATAW data
;
1183 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1188 if (!celt
) return S_OK
;
1192 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1193 if (!handle
) return S_FALSE
;
1195 This
->data
.u
.foldercoll
.find
= handle
;
1199 if (!FindNextFileW(handle
, &data
))
1205 if (is_dir_data(&data
))
1211 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1212 hr
= create_folder(str
, &folder
);
1214 if (FAILED(hr
)) return hr
;
1216 V_VT(&var
[count
]) = VT_DISPATCH
;
1217 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1220 if (count
>= celt
) break;
1222 } while (FindNextFileW(handle
, &data
));
1227 return (count
< celt
) ? S_FALSE
: S_OK
;
1230 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1232 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1233 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1234 WIN32_FIND_DATAW data
;
1236 TRACE("(%p)->(%d)\n", This
, celt
);
1238 if (!celt
) return S_OK
;
1242 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1243 if (!handle
) return S_FALSE
;
1245 This
->data
.u
.foldercoll
.find
= handle
;
1249 if (!FindNextFileW(handle
, &data
))
1255 if (is_dir_data(&data
))
1259 } while (FindNextFileW(handle
, &data
));
1261 return celt
? S_FALSE
: S_OK
;
1264 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1266 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1268 TRACE("(%p)\n", This
);
1270 FindClose(This
->data
.u
.foldercoll
.find
);
1271 This
->data
.u
.foldercoll
.find
= NULL
;
1276 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1278 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1279 TRACE("(%p)->(%p)\n", This
, pclone
);
1280 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1283 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1284 enumvariant_QueryInterface
,
1286 foldercoll_enumvariant_Release
,
1287 foldercoll_enumvariant_Next
,
1288 foldercoll_enumvariant_Skip
,
1289 foldercoll_enumvariant_Reset
,
1290 foldercoll_enumvariant_Clone
1293 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1295 struct enumvariant
*This
;
1299 This
= heap_alloc(sizeof(*This
));
1300 if (!This
) return E_OUTOFMEMORY
;
1302 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1304 This
->data
.u
.foldercoll
.find
= NULL
;
1305 This
->data
.u
.foldercoll
.coll
= collection
;
1306 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1308 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1313 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1315 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1316 ULONG ref
= InterlockedDecrement(&This
->ref
);
1318 TRACE("(%p)->(%d)\n", This
, ref
);
1322 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1323 FindClose(This
->data
.u
.filecoll
.find
);
1330 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1332 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1333 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1334 WIN32_FIND_DATAW data
;
1337 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1342 if (!celt
) return S_OK
;
1346 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1347 if (!handle
) return S_FALSE
;
1348 This
->data
.u
.filecoll
.find
= handle
;
1350 else if (!FindNextFileW(handle
, &data
))
1355 if (is_file_data(&data
))
1361 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1362 hr
= create_file(str
, &file
);
1364 if (FAILED(hr
)) return hr
;
1366 V_VT(&var
[count
]) = VT_DISPATCH
;
1367 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1368 if (++count
>= celt
) break;
1370 } while (FindNextFileW(handle
, &data
));
1375 return (count
< celt
) ? S_FALSE
: S_OK
;
1378 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1380 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1381 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1382 WIN32_FIND_DATAW data
;
1384 TRACE("(%p)->(%d)\n", This
, celt
);
1386 if (!celt
) return S_OK
;
1390 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1391 if (!handle
) return S_FALSE
;
1392 This
->data
.u
.filecoll
.find
= handle
;
1394 else if (!FindNextFileW(handle
, &data
))
1399 if (is_file_data(&data
))
1401 } while (celt
&& FindNextFileW(handle
, &data
));
1403 return celt
? S_FALSE
: S_OK
;
1406 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1408 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1410 TRACE("(%p)\n", This
);
1412 FindClose(This
->data
.u
.filecoll
.find
);
1413 This
->data
.u
.filecoll
.find
= NULL
;
1418 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1420 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1421 TRACE("(%p)->(%p)\n", This
, pclone
);
1422 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1425 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1426 enumvariant_QueryInterface
,
1428 filecoll_enumvariant_Release
,
1429 filecoll_enumvariant_Next
,
1430 filecoll_enumvariant_Skip
,
1431 filecoll_enumvariant_Reset
,
1432 filecoll_enumvariant_Clone
1435 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1437 struct enumvariant
*This
;
1441 This
= heap_alloc(sizeof(*This
));
1442 if (!This
) return E_OUTOFMEMORY
;
1444 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1446 This
->data
.u
.filecoll
.find
= NULL
;
1447 This
->data
.u
.filecoll
.coll
= collection
;
1448 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1450 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1455 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1457 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1458 ULONG ref
= InterlockedDecrement(&This
->ref
);
1460 TRACE("(%p)->(%d)\n", This
, ref
);
1464 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1471 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1473 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1476 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1478 penum
->data
.u
.drivecoll
.cur
= i
;
1485 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1487 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1490 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1495 if (!celt
) return S_OK
;
1497 while (find_next_drive(This
) == S_OK
)
1502 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1503 if (FAILED(hr
)) return hr
;
1505 V_VT(&var
[count
]) = VT_DISPATCH
;
1506 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1508 if (++count
>= celt
) break;
1514 return (count
< celt
) ? S_FALSE
: S_OK
;
1517 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1519 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1521 TRACE("(%p)->(%d)\n", This
, celt
);
1523 if (!celt
) return S_OK
;
1525 while (celt
&& find_next_drive(This
) == S_OK
)
1528 return celt
? S_FALSE
: S_OK
;
1531 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1533 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1535 TRACE("(%p)\n", This
);
1537 This
->data
.u
.drivecoll
.cur
= -1;
1541 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1543 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1544 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1548 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1549 enumvariant_QueryInterface
,
1551 drivecoll_enumvariant_Release
,
1552 drivecoll_enumvariant_Next
,
1553 drivecoll_enumvariant_Skip
,
1554 drivecoll_enumvariant_Reset
,
1555 drivecoll_enumvariant_Clone
1558 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1560 struct enumvariant
*This
;
1564 This
= heap_alloc(sizeof(*This
));
1565 if (!This
) return E_OUTOFMEMORY
;
1567 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1569 This
->data
.u
.drivecoll
.coll
= collection
;
1570 This
->data
.u
.drivecoll
.cur
= -1;
1571 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1573 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1578 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1580 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1582 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1586 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1587 IsEqualIID( riid
, &IID_IDispatch
) ||
1588 IsEqualIID( riid
, &IID_IUnknown
))
1590 *obj
= &This
->IFolderCollection_iface
;
1592 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1594 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1597 return E_NOINTERFACE
;
1599 IUnknown_AddRef((IUnknown
*)*obj
);
1603 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1605 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1606 ULONG ref
= InterlockedIncrement(&This
->ref
);
1607 TRACE("(%p)->(%d)\n", This
, ref
);
1611 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1613 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1614 ULONG ref
= InterlockedDecrement(&This
->ref
);
1615 TRACE("(%p)->(%d)\n", This
, ref
);
1619 SysFreeString(This
->path
);
1626 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1628 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1629 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1634 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1635 LCID lcid
, ITypeInfo
**ppTInfo
)
1637 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1638 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1639 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1642 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1643 LPOLESTR
*rgszNames
, UINT cNames
,
1644 LCID lcid
, DISPID
*rgDispId
)
1646 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1647 ITypeInfo
*typeinfo
;
1650 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1652 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1655 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1656 ITypeInfo_Release(typeinfo
);
1662 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1663 REFIID riid
, LCID lcid
, WORD wFlags
,
1664 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1665 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1667 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1668 ITypeInfo
*typeinfo
;
1671 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1672 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1674 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1677 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1678 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1679 ITypeInfo_Release(typeinfo
);
1685 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1687 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1688 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1692 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1694 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1695 FIXME("(%p)->(%p): stub\n", This
, folder
);
1699 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1701 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1703 TRACE("(%p)->(%p)\n", This
, newenum
);
1708 return create_foldercoll_enum(This
, newenum
);
1711 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1713 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1714 static const WCHAR allW
[] = {'\\','*',0};
1715 WIN32_FIND_DATAW data
;
1716 WCHAR pathW
[MAX_PATH
];
1719 TRACE("(%p)->(%p)\n", This
, count
);
1726 strcpyW(pathW
, This
->path
);
1727 strcatW(pathW
, allW
);
1728 handle
= FindFirstFileW(pathW
, &data
);
1729 if (handle
== INVALID_HANDLE_VALUE
)
1730 return HRESULT_FROM_WIN32(GetLastError());
1734 if (is_dir_data(&data
))
1736 } while (FindNextFileW(handle
, &data
));
1742 static const IFolderCollectionVtbl foldercollvtbl
= {
1743 foldercoll_QueryInterface
,
1746 foldercoll_GetTypeInfoCount
,
1747 foldercoll_GetTypeInfo
,
1748 foldercoll_GetIDsOfNames
,
1751 foldercoll_get_Item
,
1752 foldercoll_get__NewEnum
,
1753 foldercoll_get_Count
1756 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1758 struct foldercollection
*This
;
1762 This
= heap_alloc(sizeof(struct foldercollection
));
1763 if (!This
) return E_OUTOFMEMORY
;
1765 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1767 This
->path
= SysAllocString(path
);
1771 return E_OUTOFMEMORY
;
1774 init_classinfo(&CLSID_Folders
, (IUnknown
*)&This
->IFolderCollection_iface
, &This
->classinfo
);
1775 *folders
= &This
->IFolderCollection_iface
;
1780 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1782 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1784 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1788 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1789 IsEqualIID( riid
, &IID_IDispatch
) ||
1790 IsEqualIID( riid
, &IID_IUnknown
))
1792 *obj
= &This
->IFileCollection_iface
;
1794 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1796 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1799 return E_NOINTERFACE
;
1801 IUnknown_AddRef((IUnknown
*)*obj
);
1805 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1807 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1808 ULONG ref
= InterlockedIncrement(&This
->ref
);
1809 TRACE("(%p)->(%d)\n", This
, ref
);
1813 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1815 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1816 ULONG ref
= InterlockedDecrement(&This
->ref
);
1817 TRACE("(%p)->(%d)\n", This
, ref
);
1821 SysFreeString(This
->path
);
1828 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1830 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1831 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1836 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1837 LCID lcid
, ITypeInfo
**ppTInfo
)
1839 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1840 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1841 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1844 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1845 LPOLESTR
*rgszNames
, UINT cNames
,
1846 LCID lcid
, DISPID
*rgDispId
)
1848 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1849 ITypeInfo
*typeinfo
;
1852 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1854 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1857 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1858 ITypeInfo_Release(typeinfo
);
1864 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1865 REFIID riid
, LCID lcid
, WORD wFlags
,
1866 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1867 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1869 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1870 ITypeInfo
*typeinfo
;
1873 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1874 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1876 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1879 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1880 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1881 ITypeInfo_Release(typeinfo
);
1887 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1889 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1890 FIXME("(%p)->(%p)\n", This
, file
);
1894 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1896 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1898 TRACE("(%p)->(%p)\n", This
, ppenum
);
1903 return create_filecoll_enum(This
, ppenum
);
1906 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1908 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1909 static const WCHAR allW
[] = {'\\','*',0};
1910 WIN32_FIND_DATAW data
;
1911 WCHAR pathW
[MAX_PATH
];
1914 TRACE("(%p)->(%p)\n", This
, count
);
1921 strcpyW(pathW
, This
->path
);
1922 strcatW(pathW
, allW
);
1923 handle
= FindFirstFileW(pathW
, &data
);
1924 if (handle
== INVALID_HANDLE_VALUE
)
1925 return HRESULT_FROM_WIN32(GetLastError());
1929 if (is_file_data(&data
))
1931 } while (FindNextFileW(handle
, &data
));
1937 static const IFileCollectionVtbl filecollectionvtbl
= {
1938 filecoll_QueryInterface
,
1941 filecoll_GetTypeInfoCount
,
1942 filecoll_GetTypeInfo
,
1943 filecoll_GetIDsOfNames
,
1946 filecoll_get__NewEnum
,
1950 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1952 struct filecollection
*This
;
1956 This
= heap_alloc(sizeof(*This
));
1957 if (!This
) return E_OUTOFMEMORY
;
1959 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1961 This
->path
= SysAllocString(path
);
1965 return E_OUTOFMEMORY
;
1968 init_classinfo(&CLSID_Files
, (IUnknown
*)&This
->IFileCollection_iface
, &This
->classinfo
);
1969 *files
= &This
->IFileCollection_iface
;
1973 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1975 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1977 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1981 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1982 IsEqualIID( riid
, &IID_IDispatch
) ||
1983 IsEqualIID( riid
, &IID_IUnknown
))
1985 *obj
= &This
->IDriveCollection_iface
;
1987 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1989 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1992 return E_NOINTERFACE
;
1994 IUnknown_AddRef((IUnknown
*)*obj
);
1998 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
2000 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2001 ULONG ref
= InterlockedIncrement(&This
->ref
);
2002 TRACE("(%p)->(%d)\n", This
, ref
);
2006 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
2008 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2009 ULONG ref
= InterlockedDecrement(&This
->ref
);
2010 TRACE("(%p)->(%d)\n", This
, ref
);
2018 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
2020 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2021 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2026 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
2027 LCID lcid
, ITypeInfo
**ppTInfo
)
2029 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2030 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2031 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
2034 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
2035 LPOLESTR
*rgszNames
, UINT cNames
,
2036 LCID lcid
, DISPID
*rgDispId
)
2038 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2039 ITypeInfo
*typeinfo
;
2042 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2044 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2047 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2048 ITypeInfo_Release(typeinfo
);
2054 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2055 REFIID riid
, LCID lcid
, WORD wFlags
,
2056 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2057 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2059 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2060 ITypeInfo
*typeinfo
;
2063 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2064 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2066 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2069 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2070 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2071 ITypeInfo_Release(typeinfo
);
2077 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2079 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2080 FIXME("(%p)->(%p): stub\n", This
, drive
);
2084 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2086 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2088 TRACE("(%p)->(%p)\n", This
, ppenum
);
2093 return create_drivecoll_enum(This
, ppenum
);
2096 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2098 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2100 TRACE("(%p)->(%p)\n", This
, count
);
2102 if (!count
) return E_POINTER
;
2104 *count
= This
->count
;
2108 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2109 drivecoll_QueryInterface
,
2112 drivecoll_GetTypeInfoCount
,
2113 drivecoll_GetTypeInfo
,
2114 drivecoll_GetIDsOfNames
,
2117 drivecoll_get__NewEnum
,
2121 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2123 struct drivecollection
*This
;
2128 This
= heap_alloc(sizeof(*This
));
2129 if (!This
) return E_OUTOFMEMORY
;
2131 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2133 This
->drives
= mask
= GetLogicalDrives();
2134 /* count set bits */
2135 for (This
->count
= 0; mask
; This
->count
++)
2138 init_classinfo(&CLSID_Drives
, (IUnknown
*)&This
->IDriveCollection_iface
, &This
->classinfo
);
2139 *drives
= &This
->IDriveCollection_iface
;
2143 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2145 struct folder
*This
= impl_from_IFolder(iface
);
2147 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2151 if (IsEqualIID( riid
, &IID_IFolder
) ||
2152 IsEqualIID( riid
, &IID_IDispatch
) ||
2153 IsEqualIID( riid
, &IID_IUnknown
))
2155 *obj
= &This
->IFolder_iface
;
2157 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2159 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2162 return E_NOINTERFACE
;
2164 IUnknown_AddRef((IUnknown
*)*obj
);
2168 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2170 struct folder
*This
= impl_from_IFolder(iface
);
2171 ULONG ref
= InterlockedIncrement(&This
->ref
);
2172 TRACE("(%p)->(%d)\n", This
, ref
);
2176 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2178 struct folder
*This
= impl_from_IFolder(iface
);
2179 ULONG ref
= InterlockedDecrement(&This
->ref
);
2180 TRACE("(%p)->(%d)\n", This
, ref
);
2184 SysFreeString(This
->path
);
2191 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2193 struct folder
*This
= impl_from_IFolder(iface
);
2194 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2199 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2200 LCID lcid
, ITypeInfo
**ppTInfo
)
2202 struct folder
*This
= impl_from_IFolder(iface
);
2203 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2204 return get_typeinfo(IFolder_tid
, ppTInfo
);
2207 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2208 LPOLESTR
*rgszNames
, UINT cNames
,
2209 LCID lcid
, DISPID
*rgDispId
)
2211 struct folder
*This
= impl_from_IFolder(iface
);
2212 ITypeInfo
*typeinfo
;
2215 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2217 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2220 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2221 ITypeInfo_Release(typeinfo
);
2227 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2228 REFIID riid
, LCID lcid
, WORD wFlags
,
2229 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2230 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2232 struct folder
*This
= impl_from_IFolder(iface
);
2233 ITypeInfo
*typeinfo
;
2236 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2237 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2239 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2242 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2243 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2244 ITypeInfo_Release(typeinfo
);
2250 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2252 struct folder
*This
= impl_from_IFolder(iface
);
2254 TRACE("(%p)->(%p)\n", This
, path
);
2259 *path
= SysAllocString(This
->path
);
2260 return *path
? S_OK
: E_OUTOFMEMORY
;
2263 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2265 struct folder
*This
= impl_from_IFolder(iface
);
2268 TRACE("(%p)->(%p)\n", This
, name
);
2275 ptr
= strrchrW(This
->path
, '\\');
2278 *name
= SysAllocString(ptr
+1);
2279 TRACE("%s\n", debugstr_w(*name
));
2280 if (!*name
) return E_OUTOFMEMORY
;
2288 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2290 struct folder
*This
= impl_from_IFolder(iface
);
2291 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2295 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2297 struct folder
*This
= impl_from_IFolder(iface
);
2298 FIXME("(%p)->(%p): stub\n", This
, path
);
2302 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2304 struct folder
*This
= impl_from_IFolder(iface
);
2305 FIXME("(%p)->(%p): stub\n", This
, name
);
2309 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2311 struct folder
*This
= impl_from_IFolder(iface
);
2312 FIXME("(%p)->(%p): stub\n", This
, drive
);
2316 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2318 struct folder
*This
= impl_from_IFolder(iface
);
2319 FIXME("(%p)->(%p): stub\n", This
, parent
);
2323 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2325 struct folder
*This
= impl_from_IFolder(iface
);
2326 FIXME("(%p)->(%p): stub\n", This
, attr
);
2330 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2332 struct folder
*This
= impl_from_IFolder(iface
);
2333 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2337 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2339 struct folder
*This
= impl_from_IFolder(iface
);
2340 FIXME("(%p)->(%p): stub\n", This
, date
);
2344 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2346 struct folder
*This
= impl_from_IFolder(iface
);
2347 FIXME("(%p)->(%p): stub\n", This
, date
);
2351 static HRESULT WINAPI
folder_get_DateLastAccessed(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_Type(IFolder
*iface
, BSTR
*type
)
2360 struct folder
*This
= impl_from_IFolder(iface
);
2361 FIXME("(%p)->(%p): stub\n", This
, type
);
2365 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2367 struct folder
*This
= impl_from_IFolder(iface
);
2368 FIXME("(%p)->(%x): stub\n", This
, force
);
2372 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2374 struct folder
*This
= impl_from_IFolder(iface
);
2375 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2379 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2381 struct folder
*This
= impl_from_IFolder(iface
);
2382 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2386 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2388 struct folder
*This
= impl_from_IFolder(iface
);
2389 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2393 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2395 struct folder
*This
= impl_from_IFolder(iface
);
2396 FIXME("(%p)->(%p): stub\n", This
, size
);
2400 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2402 struct folder
*This
= impl_from_IFolder(iface
);
2404 TRACE("(%p)->(%p)\n", This
, folders
);
2409 return create_foldercoll(This
->path
, folders
);
2412 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2414 struct folder
*This
= impl_from_IFolder(iface
);
2416 TRACE("(%p)->(%p)\n", This
, files
);
2421 return create_filecoll(This
->path
, files
);
2424 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2425 VARIANT_BOOL unicode
, ITextStream
**stream
)
2427 struct folder
*This
= impl_from_IFolder(iface
);
2428 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2432 static const IFolderVtbl foldervtbl
= {
2433 folder_QueryInterface
,
2436 folder_GetTypeInfoCount
,
2438 folder_GetIDsOfNames
,
2443 folder_get_ShortPath
,
2444 folder_get_ShortName
,
2446 folder_get_ParentFolder
,
2447 folder_get_Attributes
,
2448 folder_put_Attributes
,
2449 folder_get_DateCreated
,
2450 folder_get_DateLastModified
,
2451 folder_get_DateLastAccessed
,
2456 folder_get_IsRootFolder
,
2458 folder_get_SubFolders
,
2460 folder_CreateTextFile
2463 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2465 struct folder
*This
;
2469 TRACE("%s\n", debugstr_w(path
));
2471 This
= heap_alloc(sizeof(struct folder
));
2472 if (!This
) return E_OUTOFMEMORY
;
2474 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2476 This
->path
= SysAllocString(path
);
2480 return E_OUTOFMEMORY
;
2483 init_classinfo(&CLSID_Folder
, (IUnknown
*)&This
->IFolder_iface
, &This
->classinfo
);
2484 *folder
= &This
->IFolder_iface
;
2489 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2491 struct file
*This
= impl_from_IFile(iface
);
2493 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2497 if (IsEqualIID(riid
, &IID_IFile
) ||
2498 IsEqualIID(riid
, &IID_IDispatch
) ||
2499 IsEqualIID(riid
, &IID_IUnknown
))
2501 *obj
= &This
->IFile_iface
;
2503 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2505 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2508 return E_NOINTERFACE
;
2510 IUnknown_AddRef((IUnknown
*)*obj
);
2514 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2516 struct file
*This
= impl_from_IFile(iface
);
2517 LONG ref
= InterlockedIncrement(&This
->ref
);
2519 TRACE("(%p) ref=%d\n", This
, ref
);
2524 static ULONG WINAPI
file_Release(IFile
*iface
)
2526 struct file
*This
= impl_from_IFile(iface
);
2527 LONG ref
= InterlockedDecrement(&This
->ref
);
2529 TRACE("(%p) ref=%d\n", This
, ref
);
2533 heap_free(This
->path
);
2540 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2542 struct file
*This
= impl_from_IFile(iface
);
2544 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2550 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2551 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2553 struct file
*This
= impl_from_IFile(iface
);
2555 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2557 return get_typeinfo(IFile_tid
, ppTInfo
);
2560 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2561 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2563 struct file
*This
= impl_from_IFile(iface
);
2564 ITypeInfo
*typeinfo
;
2567 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2568 rgszNames
, cNames
, lcid
, rgDispId
);
2570 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2572 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2573 ITypeInfo_Release(typeinfo
);
2578 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2580 struct file
*This
= impl_from_IFile(iface
);
2581 ITypeInfo
*typeinfo
;
2584 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2585 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2587 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2590 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2591 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2592 ITypeInfo_Release(typeinfo
);
2597 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2599 struct file
*This
= impl_from_IFile(iface
);
2601 TRACE("(%p)->(%p)\n", This
, path
);
2606 *path
= SysAllocString(This
->path
);
2608 return E_OUTOFMEMORY
;
2613 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2615 struct file
*This
= impl_from_IFile(iface
);
2618 TRACE("(%p)->(%p)\n", This
, name
);
2625 ptr
= strrchrW(This
->path
, '\\');
2628 *name
= SysAllocString(ptr
+1);
2629 TRACE("%s\n", debugstr_w(*name
));
2630 if (!*name
) return E_OUTOFMEMORY
;
2638 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2640 struct file
*This
= impl_from_IFile(iface
);
2641 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2645 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2647 struct file
*This
= impl_from_IFile(iface
);
2648 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2652 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2654 struct file
*This
= impl_from_IFile(iface
);
2655 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2659 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2661 struct file
*This
= impl_from_IFile(iface
);
2662 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2666 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2668 struct file
*This
= impl_from_IFile(iface
);
2669 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2673 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2675 struct file
*This
= impl_from_IFile(iface
);
2678 TRACE("(%p)->(%p)\n", This
, pfa
);
2683 fa
= GetFileAttributesW(This
->path
);
2684 if(fa
== INVALID_FILE_ATTRIBUTES
)
2685 return create_error(GetLastError());
2687 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2688 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2689 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2693 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2695 struct file
*This
= impl_from_IFile(iface
);
2697 TRACE("(%p)->(%x)\n", This
, pfa
);
2699 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2702 static HRESULT
get_date_from_filetime(const FILETIME
*ft
, DATE
*date
)
2710 FileTimeToLocalFileTime(ft
, &ftlocal
);
2711 FileTimeToSystemTime(&ftlocal
, &st
);
2712 SystemTimeToVariantTime(&st
, date
);
2717 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2719 struct file
*This
= impl_from_IFile(iface
);
2720 FIXME("(%p)->(%p)\n", This
, pdate
);
2724 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*date
)
2726 struct file
*This
= impl_from_IFile(iface
);
2727 WIN32_FILE_ATTRIBUTE_DATA attrs
;
2729 TRACE("(%p)->(%p)\n", This
, date
);
2731 if (GetFileAttributesExW(This
->path
, GetFileExInfoStandard
, &attrs
))
2732 return get_date_from_filetime(&attrs
.ftLastWriteTime
, date
);
2737 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2739 struct file
*This
= impl_from_IFile(iface
);
2740 FIXME("(%p)->(%p)\n", This
, pdate
);
2744 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2746 struct file
*This
= impl_from_IFile(iface
);
2747 ULARGE_INTEGER size
;
2748 WIN32_FIND_DATAW fd
;
2751 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2756 f
= FindFirstFileW(This
->path
, &fd
);
2757 if(f
== INVALID_HANDLE_VALUE
)
2758 return create_error(GetLastError());
2761 size
.u
.LowPart
= fd
.nFileSizeLow
;
2762 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2764 return variant_from_largeint(&size
, pvarSize
);
2767 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2769 struct file
*This
= impl_from_IFile(iface
);
2770 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2774 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2776 struct file
*This
= impl_from_IFile(iface
);
2777 FIXME("(%p)->(%x)\n", This
, Force
);
2781 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2783 struct file
*This
= impl_from_IFile(iface
);
2784 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2788 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2790 struct file
*This
= impl_from_IFile(iface
);
2791 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2795 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2797 struct file
*This
= impl_from_IFile(iface
);
2799 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2801 if (format
== TristateUseDefault
) {
2802 FIXME("default format not handled, defaulting to unicode\n");
2803 format
= TristateTrue
;
2806 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2809 static const IFileVtbl file_vtbl
= {
2810 file_QueryInterface
,
2813 file_GetTypeInfoCount
,
2823 file_get_ParentFolder
,
2824 file_get_Attributes
,
2825 file_put_Attributes
,
2826 file_get_DateCreated
,
2827 file_get_DateLastModified
,
2828 file_get_DateLastAccessed
,
2834 file_OpenAsTextStream
2837 static HRESULT
create_file(BSTR path
, IFile
**file
)
2844 f
= heap_alloc(sizeof(struct file
));
2846 return E_OUTOFMEMORY
;
2848 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2851 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2857 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2860 return E_OUTOFMEMORY
;
2863 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2869 attrs
= GetFileAttributesW(f
->path
);
2870 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2871 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2874 return create_error(GetLastError());
2877 init_classinfo(&CLSID_File
, (IUnknown
*)&f
->IFile_iface
, &f
->classinfo
);
2878 *file
= &f
->IFile_iface
;
2882 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2884 struct filesystem
*This
= impl_from_IFileSystem3(iface
);
2886 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2888 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2889 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2890 IsEqualGUID( riid
, &IID_IDispatch
) ||
2891 IsEqualGUID( riid
, &IID_IUnknown
) )
2893 *ppvObject
= &This
->IFileSystem3_iface
;
2895 else if (IsEqualGUID( riid
, &IID_IProvideClassInfo
))
2897 *ppvObject
= &This
->classinfo
.IProvideClassInfo_iface
;
2899 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2901 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2903 return E_NOINTERFACE
;
2905 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2907 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2909 return E_NOINTERFACE
;
2913 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2914 return E_NOINTERFACE
;
2917 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2922 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2924 TRACE("%p\n", iface
);
2929 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2931 TRACE("%p\n", iface
);
2936 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2938 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2944 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2945 LCID lcid
, ITypeInfo
**ppTInfo
)
2947 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2948 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2951 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2952 LPOLESTR
*rgszNames
, UINT cNames
,
2953 LCID lcid
, DISPID
*rgDispId
)
2955 ITypeInfo
*typeinfo
;
2958 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2960 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2963 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2964 ITypeInfo_Release(typeinfo
);
2970 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2971 REFIID riid
, LCID lcid
, WORD wFlags
,
2972 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2973 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2975 ITypeInfo
*typeinfo
;
2978 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2979 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2981 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2984 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2985 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2986 ITypeInfo_Release(typeinfo
);
2992 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2994 TRACE("%p %p\n", iface
, ppdrives
);
2995 return create_drivecoll(ppdrives
);
2998 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2999 BSTR Name
, BSTR
*Result
)
3003 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
3005 if (!Result
) return E_POINTER
;
3009 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
3011 /* if both parts have backslashes strip one from Path */
3012 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
3016 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3024 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
3026 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
3030 if (Path
[path_len
-1] != ':')
3037 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
3045 else if (Path
|| Name
)
3046 ret
= SysAllocString(Path
? Path
: Name
);
3048 ret
= SysAllocStringLen(NULL
, 0);
3050 if (!ret
) return E_OUTOFMEMORY
;
3056 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
3058 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
3065 if (path
&& strlenW(path
) > 1 && path
[1] == ':')
3066 *drive
= SysAllocStringLen(path
, 2);
3071 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
3078 for(i
=len
-1; i
>=0; i
--)
3079 if(path
[i
]!='/' && path
[i
]!='\\')
3083 if(path
[i
]=='/' || path
[i
]=='\\')
3087 if(path
[i
]!='/' && path
[i
]!='\\')
3093 if(path
[i
]==':' && i
==1)
3098 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3103 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3108 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3110 *pbstrResult
= NULL
;
3114 *pbstrResult
= SysAllocStringLen(Path
, len
);
3116 return E_OUTOFMEMORY
;
3120 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3125 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3131 *pbstrResult
= NULL
;
3135 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3136 if(Path
[end
]!='/' && Path
[end
]!='\\')
3139 for(i
=end
; i
>=0; i
--)
3140 if(Path
[i
]=='/' || Path
[i
]=='\\')
3144 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3145 *pbstrResult
= NULL
;
3149 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3151 return E_OUTOFMEMORY
;
3155 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3160 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3166 *pbstrResult
= NULL
;
3170 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3171 if(Path
[end
]!='/' && Path
[end
]!='\\')
3174 for(i
=end
; i
>=0; i
--) {
3175 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3177 if(Path
[i
]=='/' || Path
[i
]=='\\')
3182 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3183 *pbstrResult
= NULL
;
3187 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3189 return E_OUTOFMEMORY
;
3193 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3198 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3201 len
= SysStringLen(path
);
3203 if (path
[len
-1] == '.') {
3204 *ext
= SysAllocString(&path
[len
]);
3206 return E_OUTOFMEMORY
;
3215 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3218 static const WCHAR cur_path
[] = {'.',0};
3220 WCHAR buf
[MAX_PATH
], ch
;
3222 DWORD i
, beg
, len
, exp_len
;
3223 WIN32_FIND_DATAW fdata
;
3226 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3236 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3240 buf
[0] = toupperW(buf
[0]);
3241 if(len
>3 && buf
[len
-1] == '\\')
3244 for(beg
=3, i
=3; i
<=len
; i
++) {
3245 if(buf
[i
]!='\\' && buf
[i
])
3250 fh
= FindFirstFileW(buf
, &fdata
);
3251 if(fh
== INVALID_HANDLE_VALUE
)
3254 exp_len
= strlenW(fdata
.cFileName
);
3255 if(exp_len
== i
-beg
)
3256 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3262 *pbstrResult
= SysAllocString(buf
);
3264 return E_OUTOFMEMORY
;
3268 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3270 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3274 TRACE("%p %p\n", iface
, pbstrResult
);
3279 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3281 return E_OUTOFMEMORY
;
3283 if(!RtlGenRandom(&random
, sizeof(random
)))
3285 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3289 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3290 VARIANT_BOOL
*pfExists
)
3294 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3296 if (!pfExists
) return E_POINTER
;
3298 *pfExists
= VARIANT_FALSE
;
3299 len
= SysStringLen(DriveSpec
);
3302 driveletter
= toupperW(DriveSpec
[0]);
3303 if (driveletter
>= 'A' && driveletter
<= 'Z'
3304 && (len
< 2 || DriveSpec
[1] == ':')
3305 && (len
< 3 || DriveSpec
[2] == '\\')) {
3306 const WCHAR root
[] = {driveletter
, ':', '\\', 0};
3307 UINT drivetype
= GetDriveTypeW(root
);
3308 *pfExists
= drivetype
!= DRIVE_NO_ROOT_DIR
&& drivetype
!= DRIVE_UNKNOWN
? VARIANT_TRUE
: VARIANT_FALSE
;
3315 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3318 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3320 if (!ret
) return E_POINTER
;
3322 attrs
= GetFileAttributesW(path
);
3323 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3327 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3330 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3332 if (!ret
) return E_POINTER
;
3334 attrs
= GetFileAttributesW(path
);
3335 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3340 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3346 VARIANT_BOOL drive_exists
;
3348 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3355 /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3356 len
= SysStringLen(DriveSpec
);
3358 return E_INVALIDARG
;
3359 else if (len
<= 3) {
3360 driveletter
= toupperW(DriveSpec
[0]);
3361 if (driveletter
< 'A' || driveletter
> 'Z'
3362 || (len
>= 2 && DriveSpec
[1] != ':')
3363 || (len
== 3 && DriveSpec
[2] != '\\'))
3364 return E_INVALIDARG
;
3365 hr
= IFileSystem3_DriveExists(iface
, DriveSpec
, &drive_exists
);
3368 if (drive_exists
== VARIANT_FALSE
)
3369 return CTL_E_DEVICEUNAVAILABLE
;
3370 return create_drive(driveletter
, ppdrive
);
3372 if (DriveSpec
[0] != '\\' || DriveSpec
[1] != '\\')
3373 return E_INVALIDARG
;
3374 FIXME("%s not implemented yet\n", debugstr_w(DriveSpec
));
3379 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3382 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3387 return E_INVALIDARG
;
3389 return create_file(FilePath
, ppfile
);
3392 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3397 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3404 return E_INVALIDARG
;
3406 attrs
= GetFileAttributesW(FolderPath
);
3407 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3408 return CTL_E_PATHNOTFOUND
;
3410 return create_folder(FolderPath
, folder
);
3413 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3414 SpecialFolderConst SpecialFolder
,
3417 WCHAR pathW
[MAX_PATH
];
3420 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3427 switch (SpecialFolder
)
3430 ret
= GetWindowsDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3433 ret
= GetSystemDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3435 case TemporaryFolder
:
3436 ret
= GetTempPathW(sizeof(pathW
)/sizeof(WCHAR
), pathW
);
3437 /* we don't want trailing backslash */
3438 if (ret
&& pathW
[ret
-1] == '\\')
3442 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3443 return E_INVALIDARG
;
3447 return HRESULT_FROM_WIN32(GetLastError());
3449 return create_folder(pathW
, folder
);
3452 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3454 WCHAR path
[MAX_PATH
];
3455 DWORD len
, name_len
;
3456 WIN32_FIND_DATAW ffd
;
3459 f
= FindFirstFileW(file
, &ffd
);
3460 if(f
== INVALID_HANDLE_VALUE
)
3461 return create_error(GetLastError());
3463 len
= get_parent_folder_name(file
, file_len
);
3464 if(len
+1 >= MAX_PATH
) {
3469 memcpy(path
, file
, len
*sizeof(WCHAR
));
3474 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3477 name_len
= strlenW(ffd
.cFileName
);
3478 if(len
+name_len
+1 >= MAX_PATH
) {
3482 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3484 TRACE("deleting %s\n", debugstr_w(path
));
3486 if(!DeleteFileW(path
)) {
3487 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3488 || !DeleteFileW(path
)) {
3490 return create_error(GetLastError());
3493 } while(FindNextFileW(f
, &ffd
));
3499 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3502 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3507 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3510 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3512 WCHAR path
[MAX_PATH
];
3513 DWORD len
, name_len
;
3514 WIN32_FIND_DATAW ffd
;
3518 f
= FindFirstFileW(folder
, &ffd
);
3519 if(f
== INVALID_HANDLE_VALUE
)
3520 return create_error(GetLastError());
3522 len
= get_parent_folder_name(folder
, folder_len
);
3523 if(len
+1 >= MAX_PATH
) {
3528 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3533 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3535 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3536 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3539 name_len
= strlenW(ffd
.cFileName
);
3540 if(len
+name_len
+3 >= MAX_PATH
) {
3544 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3545 path
[len
+name_len
] = '\\';
3546 path
[len
+name_len
+1] = '*';
3547 path
[len
+name_len
+2] = 0;
3549 hr
= delete_file(path
, len
+name_len
+2, force
);
3555 hr
= delete_folder(path
, len
+name_len
+2, force
);
3561 path
[len
+name_len
] = 0;
3562 TRACE("deleting %s\n", debugstr_w(path
));
3564 if(!RemoveDirectoryW(path
)) {
3566 return create_error(GetLastError());
3568 } while(FindNextFileW(f
, &ffd
));
3574 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3577 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3582 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3585 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3588 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3593 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3596 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3601 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3602 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3605 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3606 DWORD src_len
, dst_len
, name_len
;
3607 WIN32_FIND_DATAW ffd
;
3611 if(!source
[0] || !destination
[0])
3612 return E_INVALIDARG
;
3614 attrs
= GetFileAttributesW(destination
);
3615 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3616 attrs
= GetFileAttributesW(source
);
3617 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3618 return create_error(GetLastError());
3619 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3620 return CTL_E_FILENOTFOUND
;
3622 if(!CopyFileW(source
, destination
, !overwrite
))
3623 return create_error(GetLastError());
3627 f
= FindFirstFileW(source
, &ffd
);
3628 if(f
== INVALID_HANDLE_VALUE
)
3629 return CTL_E_FILENOTFOUND
;
3631 src_len
= get_parent_folder_name(source
, source_len
);
3632 if(src_len
+1 >= MAX_PATH
) {
3637 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3638 src_path
[src_len
++] = '\\';
3641 dst_len
= destination_len
;
3642 if(dst_len
+1 >= MAX_PATH
) {
3646 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3647 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3648 dst_path
[dst_len
++] = '\\';
3650 hr
= CTL_E_FILENOTFOUND
;
3652 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3655 name_len
= strlenW(ffd
.cFileName
);
3656 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3660 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3661 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3663 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3665 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3667 return create_error(GetLastError());
3671 } while(FindNextFileW(f
, &ffd
));
3677 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3678 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3680 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3682 if(!Source
|| !Destination
)
3685 return copy_file(Source
, SysStringLen(Source
), Destination
,
3686 SysStringLen(Destination
), OverWriteFiles
);
3689 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3690 DWORD destination_len
, VARIANT_BOOL overwrite
)
3692 DWORD tmp
, src_len
, dst_len
, name_len
;
3693 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3694 WIN32_FIND_DATAW ffd
;
3697 BOOL copied
= FALSE
;
3699 if(!source
[0] || !destination
[0])
3700 return E_INVALIDARG
;
3702 dst_len
= destination_len
;
3703 if(dst_len
+1 >= MAX_PATH
)
3705 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3707 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3708 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3709 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3710 if(!CreateDirectoryW(dst
, NULL
)) {
3711 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3712 tmp
= GetFileAttributesW(dst
);
3713 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3714 return CTL_E_FILEALREADYEXISTS
;
3716 return create_error(GetLastError());
3721 src_len
= source_len
;
3722 if(src_len
+2 >= MAX_PATH
)
3724 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3725 src
[src_len
++] = '\\';
3729 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3730 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3731 return create_error(GetLastError());
3733 f
= FindFirstFileW(src
, &ffd
);
3735 src_len
= get_parent_folder_name(source
, source_len
);
3736 if(src_len
+2 >= MAX_PATH
)
3738 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3740 src
[src_len
++] = '\\';
3742 f
= FindFirstFileW(source
, &ffd
);
3744 if(f
== INVALID_HANDLE_VALUE
)
3745 return CTL_E_PATHNOTFOUND
;
3747 dst
[dst_len
++] = '\\';
3751 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3753 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3754 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3757 name_len
= strlenW(ffd
.cFileName
);
3758 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3762 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3763 dst
[dst_len
+name_len
] = 0;
3764 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3765 src
[src_len
+name_len
] = '\\';
3766 src
[src_len
+name_len
+1] = '*';
3767 src
[src_len
+name_len
+2] = 0;
3769 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3771 if(!CreateDirectoryW(dst
, NULL
)) {
3772 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3773 tmp
= GetFileAttributesW(dst
);
3774 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3776 return CTL_E_FILEALREADYEXISTS
;
3781 return create_error(GetLastError());
3785 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3786 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3791 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3792 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3796 } while(FindNextFileW(f
, &ffd
));
3799 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3802 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3803 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3805 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3807 if(!Source
|| !Destination
)
3810 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3811 SysStringLen(Destination
), OverWriteFiles
);
3814 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3819 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3821 ret
= CreateDirectoryW(path
, NULL
);
3825 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3826 return HRESULT_FROM_WIN32(GetLastError());
3829 return create_folder(path
, folder
);
3832 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3833 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3834 ITextStream
**stream
)
3838 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3840 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3841 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3844 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3845 IOMode mode
, VARIANT_BOOL create
,
3846 Tristate format
, ITextStream
**stream
)
3850 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3851 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3853 if (format
== TristateUseDefault
) {
3854 FIXME("default format not handled, defaulting to unicode\n");
3855 format
= TristateTrue
;
3858 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3861 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3862 StandardStreamTypes StandardStreamType
,
3863 VARIANT_BOOL Unicode
,
3866 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3871 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3873 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3877 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3878 a
= (WORD
)( version
>> 48);
3879 b
= (WORD
)((version
>> 32) & 0xffff);
3880 c
= (WORD
)((version
>> 16) & 0xffff);
3881 d
= (WORD
)( version
& 0xffff);
3883 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3886 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3888 static const WCHAR rootW
[] = {'\\',0};
3889 VS_FIXEDFILEINFO
*info
;
3895 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3897 len
= GetFileVersionInfoSizeW(name
, NULL
);
3899 return HRESULT_FROM_WIN32(GetLastError());
3901 ptr
= heap_alloc(len
);
3902 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3905 return HRESULT_FROM_WIN32(GetLastError());
3908 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3912 return HRESULT_FROM_WIN32(GetLastError());
3915 get_versionstring(info
, ver
);
3918 *version
= SysAllocString(ver
);
3919 TRACE("version=%s\n", debugstr_w(ver
));
3924 static const struct IFileSystem3Vtbl filesys_vtbl
=
3926 filesys_QueryInterface
,
3929 filesys_GetTypeInfoCount
,
3930 filesys_GetTypeInfo
,
3931 filesys_GetIDsOfNames
,
3935 filesys_GetDriveName
,
3936 filesys_GetParentFolderName
,
3937 filesys_GetFileName
,
3938 filesys_GetBaseName
,
3939 filesys_GetExtensionName
,
3940 filesys_GetAbsolutePathName
,
3941 filesys_GetTempName
,
3942 filesys_DriveExists
,
3944 filesys_FolderExists
,
3948 filesys_GetSpecialFolder
,
3950 filesys_DeleteFolder
,
3955 filesys_CreateFolder
,
3956 filesys_CreateTextFile
,
3957 filesys_OpenTextFile
,
3958 filesys_GetStandardStream
,
3959 filesys_GetFileVersion
3962 static struct filesystem filesystem
;
3964 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3966 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3968 filesystem
.IFileSystem3_iface
.lpVtbl
= &filesys_vtbl
;
3969 init_classinfo(&CLSID_FileSystemObject
, (IUnknown
*)&filesystem
.IFileSystem3_iface
, &filesystem
.classinfo
);
3970 return IFileSystem3_QueryInterface(&filesystem
.IFileSystem3_iface
, riid
, ppv
);