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;
42 struct foldercollection
{
43 IFolderCollection IFolderCollection_iface
;
48 struct filecollection
{
49 IFileCollection IFileCollection_iface
;
54 struct drivecollection
{
55 IDriveCollection IDriveCollection_iface
;
66 struct foldercollection
*coll
;
71 struct filecollection
*coll
;
76 struct drivecollection
*coll
;
83 IEnumVARIANT IEnumVARIANT_iface
;
96 IFolder IFolder_iface
;
109 ITextStream ITextStream_iface
;
124 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
126 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
129 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
131 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
134 static inline struct file
*impl_from_IFile(IFile
*iface
)
136 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
139 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
141 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
144 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
146 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
149 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
151 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
154 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
156 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
159 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
161 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
164 static inline HRESULT
create_error(DWORD err
)
167 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
168 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
169 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
170 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
171 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
173 FIXME("Unsupported error code: %d\n", err
);
178 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
179 static HRESULT
create_file(BSTR
, IFile
**);
180 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
181 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
183 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
185 static const WCHAR dotdotW
[] = {'.','.',0};
186 static const WCHAR dotW
[] = {'.',0};
188 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
189 strcmpW(data
->cFileName
, dotdotW
) &&
190 strcmpW(data
->cFileName
, dotW
);
193 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
195 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
198 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
200 int len
= SysStringLen(path
);
201 WCHAR buffW
[MAX_PATH
];
203 strcpyW(buffW
, path
);
204 if (path
[len
-1] != '\\')
206 strcatW(buffW
, data
->cFileName
);
208 return SysAllocString(buffW
);
211 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
214 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
216 return This
->mode
== ForReading
;
219 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
221 struct textstream
*This
= impl_from_ITextStream(iface
);
223 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
225 if (IsEqualIID(riid
, &IID_ITextStream
) ||
226 IsEqualIID(riid
, &IID_IDispatch
) ||
227 IsEqualIID(riid
, &IID_IUnknown
))
230 ITextStream_AddRef(iface
);
235 return E_NOINTERFACE
;
238 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
240 struct textstream
*This
= impl_from_ITextStream(iface
);
241 ULONG ref
= InterlockedIncrement(&This
->ref
);
242 TRACE("(%p)->(%d)\n", This
, ref
);
246 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
248 struct textstream
*This
= impl_from_ITextStream(iface
);
249 ULONG ref
= InterlockedDecrement(&This
->ref
);
250 TRACE("(%p)->(%d)\n", This
, ref
);
254 CloseHandle(This
->file
);
261 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
263 struct textstream
*This
= impl_from_ITextStream(iface
);
264 TRACE("(%p)->(%p)\n", This
, pctinfo
);
269 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
270 LCID lcid
, ITypeInfo
**ppTInfo
)
272 struct textstream
*This
= impl_from_ITextStream(iface
);
273 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
274 return get_typeinfo(ITextStream_tid
, ppTInfo
);
277 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
278 LPOLESTR
*rgszNames
, UINT cNames
,
279 LCID lcid
, DISPID
*rgDispId
)
281 struct textstream
*This
= impl_from_ITextStream(iface
);
285 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
287 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
290 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
291 ITypeInfo_Release(typeinfo
);
297 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
298 REFIID riid
, LCID lcid
, WORD wFlags
,
299 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
300 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
302 struct textstream
*This
= impl_from_ITextStream(iface
);
306 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
307 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
309 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
312 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
313 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
314 ITypeInfo_Release(typeinfo
);
320 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
322 struct textstream
*This
= impl_from_ITextStream(iface
);
323 FIXME("(%p)->(%p): stub\n", This
, line
);
327 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
329 struct textstream
*This
= impl_from_ITextStream(iface
);
330 FIXME("(%p)->(%p): stub\n", This
, column
);
334 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
336 struct textstream
*This
= impl_from_ITextStream(iface
);
337 LARGE_INTEGER pos
, dist
;
339 TRACE("(%p)->(%p)\n", This
, eos
);
344 if (textstream_check_iomode(This
, IORead
)) {
346 return CTL_E_BADFILEMODE
;
350 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
353 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? VARIANT_TRUE
: VARIANT_FALSE
;
357 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
359 struct textstream
*This
= impl_from_ITextStream(iface
);
360 FIXME("(%p)->(%p): stub\n", This
, eol
);
365 Reads 'toread' bytes from a file, converts if needed
366 BOM is skipped if 'bof' is set.
368 static HRESULT
textstream_read(struct textstream
*stream
, LONG toread
, BOOL bof
, BSTR
*text
)
376 *text
= SysAllocStringLen(NULL
, 0);
377 return *text
? S_FALSE
: E_OUTOFMEMORY
;
380 if (toread
< sizeof(WCHAR
))
381 return CTL_E_ENDOFFILE
;
383 buff
= heap_alloc(toread
);
385 return E_OUTOFMEMORY
;
387 ret
= ReadFile(stream
->file
, buff
, toread
, &read
, NULL
);
388 if (!ret
|| toread
!= read
) {
389 WARN("failed to read from file %d, %d, error %d\n", read
, toread
, GetLastError());
394 if (stream
->unicode
) {
398 if (bof
&& *(WCHAR
*)buff
== utf16bom
) {
399 read
-= sizeof(WCHAR
);
403 *text
= SysAllocStringLen(read
? (WCHAR
*)&buff
[i
] : NULL
, read
/sizeof(WCHAR
));
404 if (!*text
) hr
= E_OUTOFMEMORY
;
407 INT len
= MultiByteToWideChar(CP_ACP
, 0, buff
, read
, NULL
, 0);
408 *text
= SysAllocStringLen(NULL
, len
);
410 MultiByteToWideChar(CP_ACP
, 0, buff
, read
, *text
, len
);
419 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
421 struct textstream
*This
= impl_from_ITextStream(iface
);
422 LARGE_INTEGER start
, end
, dist
;
426 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
433 return len
== 0 ? S_OK
: E_INVALIDARG
;
435 if (textstream_check_iomode(This
, IORead
))
436 return CTL_E_BADFILEMODE
;
438 if (!This
->first_read
) {
442 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
446 if (eos
== VARIANT_TRUE
)
447 return CTL_E_ENDOFFILE
;
450 /* read everything from current position */
452 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
453 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
454 toread
= end
.QuadPart
- start
.QuadPart
;
456 dist
.QuadPart
= start
.QuadPart
;
457 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
459 This
->first_read
= FALSE
;
460 if (This
->unicode
) len
*= sizeof(WCHAR
);
462 hr
= textstream_read(This
, min(toread
, len
), start
.QuadPart
== 0, text
);
466 return toread
<= len
? S_FALSE
: S_OK
;
469 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
471 struct textstream
*This
= impl_from_ITextStream(iface
);
475 FIXME("(%p)->(%p): stub\n", This
, text
);
481 if (textstream_check_iomode(This
, IORead
))
482 return CTL_E_BADFILEMODE
;
485 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
489 if (eos
== VARIANT_TRUE
)
490 return CTL_E_ENDOFFILE
;
495 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
497 struct textstream
*This
= impl_from_ITextStream(iface
);
498 LARGE_INTEGER start
, end
, dist
;
502 TRACE("(%p)->(%p)\n", This
, text
);
508 if (textstream_check_iomode(This
, IORead
))
509 return CTL_E_BADFILEMODE
;
511 if (!This
->first_read
) {
515 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
519 if (eos
== VARIANT_TRUE
)
520 return CTL_E_ENDOFFILE
;
523 /* read everything from current position */
525 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
526 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
527 toread
= end
.QuadPart
- start
.QuadPart
;
529 dist
.QuadPart
= start
.QuadPart
;
530 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
532 This
->first_read
= FALSE
;
534 hr
= textstream_read(This
, toread
, start
.QuadPart
== 0, text
);
535 return FAILED(hr
) ? hr
: S_FALSE
;
538 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
543 if (stream
->unicode
) {
544 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
545 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
547 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
551 buffA
= heap_alloc(len
);
553 return E_OUTOFMEMORY
;
555 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
556 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
557 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
563 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
565 struct textstream
*This
= impl_from_ITextStream(iface
);
567 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
569 if (textstream_check_iomode(This
, IOWrite
))
570 return CTL_E_BADFILEMODE
;
572 return textstream_writestr(This
, text
);
575 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
577 static const WCHAR crlfW
[] = {'\r','\n'};
578 static const char crlfA
[] = {'\r','\n'};
579 DWORD written
= 0, len
;
583 if (stream
->unicode
) {
592 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
593 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
596 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
598 struct textstream
*This
= impl_from_ITextStream(iface
);
601 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
603 if (textstream_check_iomode(This
, IOWrite
))
604 return CTL_E_BADFILEMODE
;
606 hr
= textstream_writestr(This
, text
);
608 hr
= textstream_writecrlf(This
);
612 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
614 struct textstream
*This
= impl_from_ITextStream(iface
);
615 FIXME("(%p)->(%d): stub\n", This
, lines
);
619 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
621 struct textstream
*This
= impl_from_ITextStream(iface
);
622 FIXME("(%p)->(%d): stub\n", This
, count
);
626 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
628 struct textstream
*This
= impl_from_ITextStream(iface
);
629 FIXME("(%p): stub\n", This
);
633 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
635 struct textstream
*This
= impl_from_ITextStream(iface
);
636 FIXME("(%p): stub\n", This
);
640 static const ITextStreamVtbl textstreamvtbl
= {
641 textstream_QueryInterface
,
644 textstream_GetTypeInfoCount
,
645 textstream_GetTypeInfo
,
646 textstream_GetIDsOfNames
,
649 textstream_get_Column
,
650 textstream_get_AtEndOfStream
,
651 textstream_get_AtEndOfLine
,
656 textstream_WriteLine
,
657 textstream_WriteBlankLines
,
663 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
665 struct textstream
*stream
;
668 /* map access mode */
672 access
= GENERIC_READ
;
675 access
= GENERIC_WRITE
;
678 access
= FILE_APPEND_DATA
;
684 stream
= heap_alloc(sizeof(struct textstream
));
685 if (!stream
) return E_OUTOFMEMORY
;
687 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
690 stream
->unicode
= unicode
;
691 stream
->first_read
= TRUE
;
693 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
694 if (stream
->file
== INVALID_HANDLE_VALUE
)
696 HRESULT hr
= create_error(GetLastError());
701 if (mode
== ForReading
)
702 GetFileSizeEx(stream
->file
, &stream
->size
);
704 stream
->size
.QuadPart
= 0;
706 /* Write Unicode BOM */
707 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
709 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
710 if (!ret
|| written
!= sizeof(utf16bom
)) {
711 ITextStream_Release(&stream
->ITextStream_iface
);
712 return create_error(GetLastError());
716 *ret
= &stream
->ITextStream_iface
;
720 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
722 struct drive
*This
= impl_from_IDrive(iface
);
724 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
728 if (IsEqualIID( riid
, &IID_IDrive
) ||
729 IsEqualIID( riid
, &IID_IDispatch
) ||
730 IsEqualIID( riid
, &IID_IUnknown
))
733 IDrive_AddRef(iface
);
736 return E_NOINTERFACE
;
741 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
743 struct drive
*This
= impl_from_IDrive(iface
);
744 ULONG ref
= InterlockedIncrement(&This
->ref
);
745 TRACE("(%p)->(%d)\n", This
, ref
);
749 static ULONG WINAPI
drive_Release(IDrive
*iface
)
751 struct drive
*This
= impl_from_IDrive(iface
);
752 ULONG ref
= InterlockedDecrement(&This
->ref
);
753 TRACE("(%p)->(%d)\n", This
, ref
);
757 SysFreeString(This
->root
);
764 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
766 struct drive
*This
= impl_from_IDrive(iface
);
767 TRACE("(%p)->(%p)\n", This
, pctinfo
);
772 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
773 LCID lcid
, ITypeInfo
**ppTInfo
)
775 struct drive
*This
= impl_from_IDrive(iface
);
776 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
777 return get_typeinfo(IDrive_tid
, ppTInfo
);
780 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
781 LPOLESTR
*rgszNames
, UINT cNames
,
782 LCID lcid
, DISPID
*rgDispId
)
784 struct drive
*This
= impl_from_IDrive(iface
);
788 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
790 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
793 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
794 ITypeInfo_Release(typeinfo
);
800 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
801 REFIID riid
, LCID lcid
, WORD wFlags
,
802 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
803 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
805 struct drive
*This
= impl_from_IDrive(iface
);
809 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
810 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
812 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
815 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
816 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
817 ITypeInfo_Release(typeinfo
);
823 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
825 struct drive
*This
= impl_from_IDrive(iface
);
826 FIXME("(%p)->(%p): stub\n", This
, path
);
830 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
832 struct drive
*This
= impl_from_IDrive(iface
);
834 TRACE("(%p)->(%p)\n", This
, letter
);
839 *letter
= SysAllocStringLen(This
->root
, 1);
841 return E_OUTOFMEMORY
;
846 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
848 struct drive
*This
= impl_from_IDrive(iface
);
849 FIXME("(%p)->(%p): stub\n", This
, share_name
);
853 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
855 struct drive
*This
= impl_from_IDrive(iface
);
857 TRACE("(%p)->(%p)\n", This
, type
);
859 switch (GetDriveTypeW(This
->root
))
861 case DRIVE_REMOVABLE
:
884 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
886 struct drive
*This
= impl_from_IDrive(iface
);
887 FIXME("(%p)->(%p): stub\n", This
, folder
);
891 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
893 struct drive
*This
= impl_from_IDrive(iface
);
894 ULARGE_INTEGER avail
;
896 TRACE("(%p)->(%p)\n", This
, v
);
901 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
905 return VarR8FromUI8(avail
.QuadPart
, &V_R8(v
));
908 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
910 struct drive
*This
= impl_from_IDrive(iface
);
911 ULARGE_INTEGER freespace
;
913 TRACE("(%p)->(%p)\n", This
, v
);
918 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
922 return VarR8FromUI8(freespace
.QuadPart
, &V_R8(v
));
925 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
927 struct drive
*This
= impl_from_IDrive(iface
);
928 ULARGE_INTEGER total
;
930 TRACE("(%p)->(%p)\n", This
, v
);
935 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
939 return VarR8FromUI8(total
.QuadPart
, &V_R8(v
));
942 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
944 struct drive
*This
= impl_from_IDrive(iface
);
945 FIXME("(%p)->(%p): stub\n", This
, name
);
949 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
951 struct drive
*This
= impl_from_IDrive(iface
);
952 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
956 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
958 struct drive
*This
= impl_from_IDrive(iface
);
959 FIXME("(%p)->(%p): stub\n", This
, fs
);
963 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
965 struct drive
*This
= impl_from_IDrive(iface
);
966 FIXME("(%p)->(%p): stub\n", This
, serial
);
970 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
972 struct drive
*This
= impl_from_IDrive(iface
);
973 ULARGE_INTEGER freespace
;
976 TRACE("(%p)->(%p)\n", This
, ready
);
981 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
982 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
986 static const IDriveVtbl drivevtbl
= {
987 drive_QueryInterface
,
990 drive_GetTypeInfoCount
,
995 drive_get_DriveLetter
,
998 drive_get_RootFolder
,
999 drive_get_AvailableSpace
,
1000 drive_get_FreeSpace
,
1001 drive_get_TotalSize
,
1002 drive_get_VolumeName
,
1003 drive_put_VolumeName
,
1004 drive_get_FileSystem
,
1005 drive_get_SerialNumber
,
1009 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1015 This
= heap_alloc(sizeof(*This
));
1016 if (!This
) return E_OUTOFMEMORY
;
1018 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1020 This
->root
= SysAllocStringLen(NULL
, 3);
1024 return E_OUTOFMEMORY
;
1026 This
->root
[0] = letter
;
1027 This
->root
[1] = ':';
1028 This
->root
[2] = '\\';
1031 *drive
= &This
->IDrive_iface
;
1035 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1037 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1039 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1043 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1044 IsEqualIID( riid
, &IID_IUnknown
))
1047 IEnumVARIANT_AddRef(iface
);
1050 return E_NOINTERFACE
;
1055 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1057 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1058 ULONG ref
= InterlockedIncrement(&This
->ref
);
1059 TRACE("(%p)->(%d)\n", This
, ref
);
1063 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1065 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1066 ULONG ref
= InterlockedDecrement(&This
->ref
);
1068 TRACE("(%p)->(%d)\n", This
, ref
);
1072 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1073 FindClose(This
->data
.u
.foldercoll
.find
);
1080 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1082 static const WCHAR allW
[] = {'*',0};
1083 WCHAR pathW
[MAX_PATH
];
1087 strcpyW(pathW
, path
);
1088 len
= strlenW(pathW
);
1089 if (pathW
[len
-1] != '\\')
1090 strcatW(pathW
, bsW
);
1091 strcatW(pathW
, allW
);
1092 handle
= FindFirstFileW(pathW
, data
);
1093 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1095 /* find first dir/file */
1098 if (file
? is_file_data(data
) : is_dir_data(data
))
1101 if (!FindNextFileW(handle
, data
))
1110 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1112 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1113 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1114 WIN32_FIND_DATAW data
;
1117 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1122 if (!celt
) return S_OK
;
1126 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1127 if (!handle
) return S_FALSE
;
1129 This
->data
.u
.foldercoll
.find
= handle
;
1133 if (!FindNextFileW(handle
, &data
))
1139 if (is_dir_data(&data
))
1145 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1146 hr
= create_folder(str
, &folder
);
1148 if (FAILED(hr
)) return hr
;
1150 V_VT(&var
[count
]) = VT_DISPATCH
;
1151 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1154 if (count
>= celt
) break;
1156 } while (FindNextFileW(handle
, &data
));
1161 return (count
< celt
) ? S_FALSE
: S_OK
;
1164 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1166 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1167 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1168 WIN32_FIND_DATAW data
;
1170 TRACE("(%p)->(%d)\n", This
, celt
);
1172 if (!celt
) return S_OK
;
1176 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1177 if (!handle
) return S_FALSE
;
1179 This
->data
.u
.foldercoll
.find
= handle
;
1183 if (!FindNextFileW(handle
, &data
))
1189 if (is_dir_data(&data
))
1193 } while (FindNextFileW(handle
, &data
));
1195 return celt
? S_FALSE
: S_OK
;
1198 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1200 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1202 TRACE("(%p)\n", This
);
1204 FindClose(This
->data
.u
.foldercoll
.find
);
1205 This
->data
.u
.foldercoll
.find
= NULL
;
1210 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1212 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1213 TRACE("(%p)->(%p)\n", This
, pclone
);
1214 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1217 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1218 enumvariant_QueryInterface
,
1220 foldercoll_enumvariant_Release
,
1221 foldercoll_enumvariant_Next
,
1222 foldercoll_enumvariant_Skip
,
1223 foldercoll_enumvariant_Reset
,
1224 foldercoll_enumvariant_Clone
1227 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1229 struct enumvariant
*This
;
1233 This
= heap_alloc(sizeof(*This
));
1234 if (!This
) return E_OUTOFMEMORY
;
1236 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1238 This
->data
.u
.foldercoll
.find
= NULL
;
1239 This
->data
.u
.foldercoll
.coll
= collection
;
1240 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1242 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1247 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1249 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1250 ULONG ref
= InterlockedDecrement(&This
->ref
);
1252 TRACE("(%p)->(%d)\n", This
, ref
);
1256 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1257 FindClose(This
->data
.u
.filecoll
.find
);
1264 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1266 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1267 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1268 WIN32_FIND_DATAW data
;
1271 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1276 if (!celt
) return S_OK
;
1280 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1281 if (!handle
) return S_FALSE
;
1282 This
->data
.u
.filecoll
.find
= handle
;
1284 else if (!FindNextFileW(handle
, &data
))
1289 if (is_file_data(&data
))
1295 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1296 hr
= create_file(str
, &file
);
1298 if (FAILED(hr
)) return hr
;
1300 V_VT(&var
[count
]) = VT_DISPATCH
;
1301 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1302 if (++count
>= celt
) break;
1304 } while (FindNextFileW(handle
, &data
));
1309 return (count
< celt
) ? S_FALSE
: S_OK
;
1312 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1314 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1315 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1316 WIN32_FIND_DATAW data
;
1318 TRACE("(%p)->(%d)\n", This
, celt
);
1320 if (!celt
) return S_OK
;
1324 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1325 if (!handle
) return S_FALSE
;
1326 This
->data
.u
.filecoll
.find
= handle
;
1328 else if (!FindNextFileW(handle
, &data
))
1333 if (is_file_data(&data
))
1335 } while (celt
&& FindNextFileW(handle
, &data
));
1337 return celt
? S_FALSE
: S_OK
;
1340 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1342 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1344 TRACE("(%p)\n", This
);
1346 FindClose(This
->data
.u
.filecoll
.find
);
1347 This
->data
.u
.filecoll
.find
= NULL
;
1352 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1354 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1355 TRACE("(%p)->(%p)\n", This
, pclone
);
1356 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1359 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1360 enumvariant_QueryInterface
,
1362 filecoll_enumvariant_Release
,
1363 filecoll_enumvariant_Next
,
1364 filecoll_enumvariant_Skip
,
1365 filecoll_enumvariant_Reset
,
1366 filecoll_enumvariant_Clone
1369 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1371 struct enumvariant
*This
;
1375 This
= heap_alloc(sizeof(*This
));
1376 if (!This
) return E_OUTOFMEMORY
;
1378 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1380 This
->data
.u
.filecoll
.find
= NULL
;
1381 This
->data
.u
.filecoll
.coll
= collection
;
1382 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1384 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1389 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1391 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1392 ULONG ref
= InterlockedDecrement(&This
->ref
);
1394 TRACE("(%p)->(%d)\n", This
, ref
);
1398 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1405 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1407 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1410 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1412 penum
->data
.u
.drivecoll
.cur
= i
;
1419 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1421 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1424 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1429 if (!celt
) return S_OK
;
1431 while (find_next_drive(This
) == S_OK
)
1436 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1437 if (FAILED(hr
)) return hr
;
1439 V_VT(&var
[count
]) = VT_DISPATCH
;
1440 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1442 if (++count
>= celt
) break;
1448 return (count
< celt
) ? S_FALSE
: S_OK
;
1451 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1453 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1455 TRACE("(%p)->(%d)\n", This
, celt
);
1457 if (!celt
) return S_OK
;
1459 while (celt
&& find_next_drive(This
) == S_OK
)
1462 return celt
? S_FALSE
: S_OK
;
1465 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1467 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1469 TRACE("(%p)\n", This
);
1471 This
->data
.u
.drivecoll
.cur
= -1;
1475 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1477 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1478 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1482 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1483 enumvariant_QueryInterface
,
1485 drivecoll_enumvariant_Release
,
1486 drivecoll_enumvariant_Next
,
1487 drivecoll_enumvariant_Skip
,
1488 drivecoll_enumvariant_Reset
,
1489 drivecoll_enumvariant_Clone
1492 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1494 struct enumvariant
*This
;
1498 This
= heap_alloc(sizeof(*This
));
1499 if (!This
) return E_OUTOFMEMORY
;
1501 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1503 This
->data
.u
.drivecoll
.coll
= collection
;
1504 This
->data
.u
.drivecoll
.cur
= -1;
1505 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1507 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1512 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1514 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1516 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1520 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1521 IsEqualIID( riid
, &IID_IDispatch
) ||
1522 IsEqualIID( riid
, &IID_IUnknown
))
1525 IFolderCollection_AddRef(iface
);
1528 return E_NOINTERFACE
;
1533 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1535 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1536 ULONG ref
= InterlockedIncrement(&This
->ref
);
1537 TRACE("(%p)->(%d)\n", This
, ref
);
1541 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1543 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1544 ULONG ref
= InterlockedDecrement(&This
->ref
);
1545 TRACE("(%p)->(%d)\n", This
, ref
);
1549 SysFreeString(This
->path
);
1556 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1558 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1559 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1564 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1565 LCID lcid
, ITypeInfo
**ppTInfo
)
1567 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1568 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1569 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1572 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1573 LPOLESTR
*rgszNames
, UINT cNames
,
1574 LCID lcid
, DISPID
*rgDispId
)
1576 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1577 ITypeInfo
*typeinfo
;
1580 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1582 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1585 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1586 ITypeInfo_Release(typeinfo
);
1592 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1593 REFIID riid
, LCID lcid
, WORD wFlags
,
1594 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1595 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1597 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1598 ITypeInfo
*typeinfo
;
1601 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1602 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1604 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1607 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1608 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1609 ITypeInfo_Release(typeinfo
);
1615 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1617 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1618 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1622 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1624 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1625 FIXME("(%p)->(%p): stub\n", This
, folder
);
1629 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1631 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1633 TRACE("(%p)->(%p)\n", This
, newenum
);
1638 return create_foldercoll_enum(This
, newenum
);
1641 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1643 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1644 static const WCHAR allW
[] = {'\\','*',0};
1645 WIN32_FIND_DATAW data
;
1646 WCHAR pathW
[MAX_PATH
];
1649 TRACE("(%p)->(%p)\n", This
, count
);
1656 strcpyW(pathW
, This
->path
);
1657 strcatW(pathW
, allW
);
1658 handle
= FindFirstFileW(pathW
, &data
);
1659 if (handle
== INVALID_HANDLE_VALUE
)
1660 return HRESULT_FROM_WIN32(GetLastError());
1664 if (is_dir_data(&data
))
1666 } while (FindNextFileW(handle
, &data
));
1672 static const IFolderCollectionVtbl foldercollvtbl
= {
1673 foldercoll_QueryInterface
,
1676 foldercoll_GetTypeInfoCount
,
1677 foldercoll_GetTypeInfo
,
1678 foldercoll_GetIDsOfNames
,
1681 foldercoll_get_Item
,
1682 foldercoll_get__NewEnum
,
1683 foldercoll_get_Count
1686 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1688 struct foldercollection
*This
;
1692 This
= heap_alloc(sizeof(struct foldercollection
));
1693 if (!This
) return E_OUTOFMEMORY
;
1695 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1697 This
->path
= SysAllocString(path
);
1701 return E_OUTOFMEMORY
;
1704 *folders
= &This
->IFolderCollection_iface
;
1709 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1711 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1713 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1717 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1718 IsEqualIID( riid
, &IID_IDispatch
) ||
1719 IsEqualIID( riid
, &IID_IUnknown
))
1722 IFileCollection_AddRef(iface
);
1725 return E_NOINTERFACE
;
1730 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1732 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1733 ULONG ref
= InterlockedIncrement(&This
->ref
);
1734 TRACE("(%p)->(%d)\n", This
, ref
);
1738 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1740 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1741 ULONG ref
= InterlockedDecrement(&This
->ref
);
1742 TRACE("(%p)->(%d)\n", This
, ref
);
1746 SysFreeString(This
->path
);
1753 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1755 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1756 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1761 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1762 LCID lcid
, ITypeInfo
**ppTInfo
)
1764 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1765 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1766 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1769 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1770 LPOLESTR
*rgszNames
, UINT cNames
,
1771 LCID lcid
, DISPID
*rgDispId
)
1773 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1774 ITypeInfo
*typeinfo
;
1777 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1779 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1782 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1783 ITypeInfo_Release(typeinfo
);
1789 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1790 REFIID riid
, LCID lcid
, WORD wFlags
,
1791 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1792 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1794 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1795 ITypeInfo
*typeinfo
;
1798 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1799 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1801 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1804 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1805 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1806 ITypeInfo_Release(typeinfo
);
1812 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1814 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1815 FIXME("(%p)->(%p)\n", This
, file
);
1819 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1821 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1823 TRACE("(%p)->(%p)\n", This
, ppenum
);
1828 return create_filecoll_enum(This
, ppenum
);
1831 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1833 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1834 static const WCHAR allW
[] = {'\\','*',0};
1835 WIN32_FIND_DATAW data
;
1836 WCHAR pathW
[MAX_PATH
];
1839 TRACE("(%p)->(%p)\n", This
, count
);
1846 strcpyW(pathW
, This
->path
);
1847 strcatW(pathW
, allW
);
1848 handle
= FindFirstFileW(pathW
, &data
);
1849 if (handle
== INVALID_HANDLE_VALUE
)
1850 return HRESULT_FROM_WIN32(GetLastError());
1854 if (is_file_data(&data
))
1856 } while (FindNextFileW(handle
, &data
));
1862 static const IFileCollectionVtbl filecollectionvtbl
= {
1863 filecoll_QueryInterface
,
1866 filecoll_GetTypeInfoCount
,
1867 filecoll_GetTypeInfo
,
1868 filecoll_GetIDsOfNames
,
1871 filecoll_get__NewEnum
,
1875 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1877 struct filecollection
*This
;
1881 This
= heap_alloc(sizeof(*This
));
1882 if (!This
) return E_OUTOFMEMORY
;
1884 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1886 This
->path
= SysAllocString(path
);
1890 return E_OUTOFMEMORY
;
1893 *files
= &This
->IFileCollection_iface
;
1897 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1899 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1901 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1905 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1906 IsEqualIID( riid
, &IID_IDispatch
) ||
1907 IsEqualIID( riid
, &IID_IUnknown
))
1910 IDriveCollection_AddRef(iface
);
1913 return E_NOINTERFACE
;
1918 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
1920 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1921 ULONG ref
= InterlockedIncrement(&This
->ref
);
1922 TRACE("(%p)->(%d)\n", This
, ref
);
1926 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
1928 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1929 ULONG ref
= InterlockedDecrement(&This
->ref
);
1930 TRACE("(%p)->(%d)\n", This
, ref
);
1938 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
1940 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1941 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1946 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
1947 LCID lcid
, ITypeInfo
**ppTInfo
)
1949 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1950 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1951 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
1954 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
1955 LPOLESTR
*rgszNames
, UINT cNames
,
1956 LCID lcid
, DISPID
*rgDispId
)
1958 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1959 ITypeInfo
*typeinfo
;
1962 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1964 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
1967 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1968 ITypeInfo_Release(typeinfo
);
1974 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
1975 REFIID riid
, LCID lcid
, WORD wFlags
,
1976 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1977 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1979 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1980 ITypeInfo
*typeinfo
;
1983 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1984 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1986 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
1989 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1990 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1991 ITypeInfo_Release(typeinfo
);
1997 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
1999 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2000 FIXME("(%p)->(%p): stub\n", This
, drive
);
2004 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2006 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2008 TRACE("(%p)->(%p)\n", This
, ppenum
);
2013 return create_drivecoll_enum(This
, ppenum
);
2016 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2018 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2020 TRACE("(%p)->(%p)\n", This
, count
);
2022 if (!count
) return E_POINTER
;
2024 *count
= This
->count
;
2028 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2029 drivecoll_QueryInterface
,
2032 drivecoll_GetTypeInfoCount
,
2033 drivecoll_GetTypeInfo
,
2034 drivecoll_GetIDsOfNames
,
2037 drivecoll_get__NewEnum
,
2041 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2043 struct drivecollection
*This
;
2048 This
= heap_alloc(sizeof(*This
));
2049 if (!This
) return E_OUTOFMEMORY
;
2051 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2053 This
->drives
= mask
= GetLogicalDrives();
2054 /* count set bits */
2055 for (This
->count
= 0; mask
; This
->count
++)
2058 *drives
= &This
->IDriveCollection_iface
;
2062 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2064 struct folder
*This
= impl_from_IFolder(iface
);
2066 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2070 if (IsEqualIID( riid
, &IID_IFolder
) ||
2071 IsEqualIID( riid
, &IID_IDispatch
) ||
2072 IsEqualIID( riid
, &IID_IUnknown
))
2075 IFolder_AddRef(iface
);
2078 return E_NOINTERFACE
;
2083 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2085 struct folder
*This
= impl_from_IFolder(iface
);
2086 ULONG ref
= InterlockedIncrement(&This
->ref
);
2087 TRACE("(%p)->(%d)\n", This
, ref
);
2091 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2093 struct folder
*This
= impl_from_IFolder(iface
);
2094 ULONG ref
= InterlockedDecrement(&This
->ref
);
2095 TRACE("(%p)->(%d)\n", This
, ref
);
2099 SysFreeString(This
->path
);
2106 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2108 struct folder
*This
= impl_from_IFolder(iface
);
2109 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2114 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2115 LCID lcid
, ITypeInfo
**ppTInfo
)
2117 struct folder
*This
= impl_from_IFolder(iface
);
2118 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2119 return get_typeinfo(IFolder_tid
, ppTInfo
);
2122 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2123 LPOLESTR
*rgszNames
, UINT cNames
,
2124 LCID lcid
, DISPID
*rgDispId
)
2126 struct folder
*This
= impl_from_IFolder(iface
);
2127 ITypeInfo
*typeinfo
;
2130 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2132 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2135 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2136 ITypeInfo_Release(typeinfo
);
2142 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2143 REFIID riid
, LCID lcid
, WORD wFlags
,
2144 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2145 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2147 struct folder
*This
= impl_from_IFolder(iface
);
2148 ITypeInfo
*typeinfo
;
2151 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2152 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2154 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2157 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2158 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2159 ITypeInfo_Release(typeinfo
);
2165 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2167 struct folder
*This
= impl_from_IFolder(iface
);
2169 TRACE("(%p)->(%p)\n", This
, path
);
2174 *path
= SysAllocString(This
->path
);
2175 return *path
? S_OK
: E_OUTOFMEMORY
;
2178 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2180 struct folder
*This
= impl_from_IFolder(iface
);
2183 TRACE("(%p)->(%p)\n", This
, name
);
2190 ptr
= strrchrW(This
->path
, '\\');
2193 *name
= SysAllocString(ptr
+1);
2194 TRACE("%s\n", debugstr_w(*name
));
2195 if (!*name
) return E_OUTOFMEMORY
;
2203 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2205 struct folder
*This
= impl_from_IFolder(iface
);
2206 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2210 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2212 struct folder
*This
= impl_from_IFolder(iface
);
2213 FIXME("(%p)->(%p): stub\n", This
, path
);
2217 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2219 struct folder
*This
= impl_from_IFolder(iface
);
2220 FIXME("(%p)->(%p): stub\n", This
, name
);
2224 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2226 struct folder
*This
= impl_from_IFolder(iface
);
2227 FIXME("(%p)->(%p): stub\n", This
, drive
);
2231 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2233 struct folder
*This
= impl_from_IFolder(iface
);
2234 FIXME("(%p)->(%p): stub\n", This
, parent
);
2238 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2240 struct folder
*This
= impl_from_IFolder(iface
);
2241 FIXME("(%p)->(%p): stub\n", This
, attr
);
2245 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2247 struct folder
*This
= impl_from_IFolder(iface
);
2248 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2252 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2254 struct folder
*This
= impl_from_IFolder(iface
);
2255 FIXME("(%p)->(%p): stub\n", This
, date
);
2259 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2261 struct folder
*This
= impl_from_IFolder(iface
);
2262 FIXME("(%p)->(%p): stub\n", This
, date
);
2266 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2268 struct folder
*This
= impl_from_IFolder(iface
);
2269 FIXME("(%p)->(%p): stub\n", This
, date
);
2273 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2275 struct folder
*This
= impl_from_IFolder(iface
);
2276 FIXME("(%p)->(%p): stub\n", This
, type
);
2280 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2282 struct folder
*This
= impl_from_IFolder(iface
);
2283 FIXME("(%p)->(%x): stub\n", This
, force
);
2287 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2289 struct folder
*This
= impl_from_IFolder(iface
);
2290 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2294 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2296 struct folder
*This
= impl_from_IFolder(iface
);
2297 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2301 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2303 struct folder
*This
= impl_from_IFolder(iface
);
2304 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2308 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2310 struct folder
*This
= impl_from_IFolder(iface
);
2311 FIXME("(%p)->(%p): stub\n", This
, size
);
2315 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2317 struct folder
*This
= impl_from_IFolder(iface
);
2319 TRACE("(%p)->(%p)\n", This
, folders
);
2324 return create_foldercoll(This
->path
, folders
);
2327 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2329 struct folder
*This
= impl_from_IFolder(iface
);
2331 TRACE("(%p)->(%p)\n", This
, files
);
2336 return create_filecoll(This
->path
, files
);
2339 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2340 VARIANT_BOOL unicode
, ITextStream
**stream
)
2342 struct folder
*This
= impl_from_IFolder(iface
);
2343 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2347 static const IFolderVtbl foldervtbl
= {
2348 folder_QueryInterface
,
2351 folder_GetTypeInfoCount
,
2353 folder_GetIDsOfNames
,
2358 folder_get_ShortPath
,
2359 folder_get_ShortName
,
2361 folder_get_ParentFolder
,
2362 folder_get_Attributes
,
2363 folder_put_Attributes
,
2364 folder_get_DateCreated
,
2365 folder_get_DateLastModified
,
2366 folder_get_DateLastAccessed
,
2371 folder_get_IsRootFolder
,
2373 folder_get_SubFolders
,
2375 folder_CreateTextFile
2378 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2380 struct folder
*This
;
2384 TRACE("%s\n", debugstr_w(path
));
2386 This
= heap_alloc(sizeof(struct folder
));
2387 if (!This
) return E_OUTOFMEMORY
;
2389 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2391 This
->path
= SysAllocString(path
);
2395 return E_OUTOFMEMORY
;
2398 *folder
= &This
->IFolder_iface
;
2403 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2405 struct file
*This
= impl_from_IFile(iface
);
2407 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2409 if (IsEqualIID(riid
, &IID_IFile
) ||
2410 IsEqualIID(riid
, &IID_IDispatch
) ||
2411 IsEqualIID(riid
, &IID_IUnknown
))
2414 IFile_AddRef(iface
);
2419 return E_NOINTERFACE
;
2422 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2424 struct file
*This
= impl_from_IFile(iface
);
2425 LONG ref
= InterlockedIncrement(&This
->ref
);
2427 TRACE("(%p) ref=%d\n", This
, ref
);
2432 static ULONG WINAPI
file_Release(IFile
*iface
)
2434 struct file
*This
= impl_from_IFile(iface
);
2435 LONG ref
= InterlockedDecrement(&This
->ref
);
2437 TRACE("(%p) ref=%d\n", This
, ref
);
2441 heap_free(This
->path
);
2448 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2450 struct file
*This
= impl_from_IFile(iface
);
2452 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2458 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2459 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2461 struct file
*This
= impl_from_IFile(iface
);
2463 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2465 return get_typeinfo(IFile_tid
, ppTInfo
);
2468 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2469 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2471 struct file
*This
= impl_from_IFile(iface
);
2472 ITypeInfo
*typeinfo
;
2475 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2476 rgszNames
, cNames
, lcid
, rgDispId
);
2478 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2480 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2481 ITypeInfo_Release(typeinfo
);
2486 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2488 struct file
*This
= impl_from_IFile(iface
);
2489 ITypeInfo
*typeinfo
;
2492 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2493 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2495 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2498 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2499 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2500 ITypeInfo_Release(typeinfo
);
2505 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
2507 struct file
*This
= impl_from_IFile(iface
);
2508 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2512 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2514 struct file
*This
= impl_from_IFile(iface
);
2517 TRACE("(%p)->(%p)\n", This
, name
);
2524 ptr
= strrchrW(This
->path
, '\\');
2527 *name
= SysAllocString(ptr
+1);
2528 TRACE("%s\n", debugstr_w(*name
));
2529 if (!*name
) return E_OUTOFMEMORY
;
2537 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2539 struct file
*This
= impl_from_IFile(iface
);
2540 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2544 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2546 struct file
*This
= impl_from_IFile(iface
);
2547 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2551 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2553 struct file
*This
= impl_from_IFile(iface
);
2554 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2558 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2560 struct file
*This
= impl_from_IFile(iface
);
2561 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2565 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2567 struct file
*This
= impl_from_IFile(iface
);
2568 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2572 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2574 struct file
*This
= impl_from_IFile(iface
);
2577 TRACE("(%p)->(%p)\n", This
, pfa
);
2582 fa
= GetFileAttributesW(This
->path
);
2583 if(fa
== INVALID_FILE_ATTRIBUTES
)
2584 return create_error(GetLastError());
2586 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2587 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2588 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2592 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2594 struct file
*This
= impl_from_IFile(iface
);
2595 FIXME("(%p)->(%x)\n", This
, pfa
);
2599 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2601 struct file
*This
= impl_from_IFile(iface
);
2602 FIXME("(%p)->(%p)\n", This
, pdate
);
2606 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2608 struct file
*This
= impl_from_IFile(iface
);
2609 FIXME("(%p)->(%p)\n", This
, pdate
);
2613 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2615 struct file
*This
= impl_from_IFile(iface
);
2616 FIXME("(%p)->(%p)\n", This
, pdate
);
2620 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2622 struct file
*This
= impl_from_IFile(iface
);
2623 WIN32_FIND_DATAW fd
;
2626 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2631 f
= FindFirstFileW(This
->path
, &fd
);
2632 if(f
== INVALID_HANDLE_VALUE
)
2633 return create_error(GetLastError());
2636 if(fd
.nFileSizeHigh
|| fd
.nFileSizeLow
>INT_MAX
) {
2637 V_VT(pvarSize
) = VT_R8
;
2638 V_R8(pvarSize
) = ((ULONGLONG
)fd
.nFileSizeHigh
<<32) + fd
.nFileSizeLow
;
2640 V_VT(pvarSize
) = VT_I4
;
2641 V_I4(pvarSize
) = fd
.nFileSizeLow
;
2646 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2648 struct file
*This
= impl_from_IFile(iface
);
2649 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2653 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2655 struct file
*This
= impl_from_IFile(iface
);
2656 FIXME("(%p)->(%x)\n", This
, Force
);
2660 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2662 struct file
*This
= impl_from_IFile(iface
);
2663 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2667 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2669 struct file
*This
= impl_from_IFile(iface
);
2670 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2674 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2676 struct file
*This
= impl_from_IFile(iface
);
2678 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2680 if (format
== TristateUseDefault
) {
2681 FIXME("default format not handled, defaulting to unicode\n");
2682 format
= TristateTrue
;
2685 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2688 static const IFileVtbl file_vtbl
= {
2689 file_QueryInterface
,
2692 file_GetTypeInfoCount
,
2702 file_get_ParentFolder
,
2703 file_get_Attributes
,
2704 file_put_Attributes
,
2705 file_get_DateCreated
,
2706 file_get_DateLastModified
,
2707 file_get_DateLastAccessed
,
2713 file_OpenAsTextStream
2716 static HRESULT
create_file(BSTR path
, IFile
**file
)
2723 f
= heap_alloc(sizeof(struct file
));
2725 return E_OUTOFMEMORY
;
2727 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2730 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2736 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2739 return E_OUTOFMEMORY
;
2742 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2748 attrs
= GetFileAttributesW(f
->path
);
2749 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2750 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2753 return create_error(GetLastError());
2756 *file
= &f
->IFile_iface
;
2760 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2762 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2764 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2765 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2766 IsEqualGUID( riid
, &IID_IDispatch
) ||
2767 IsEqualGUID( riid
, &IID_IUnknown
) )
2771 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2773 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2775 return E_NOINTERFACE
;
2777 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2779 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2781 return E_NOINTERFACE
;
2785 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2786 return E_NOINTERFACE
;
2789 IFileSystem3_AddRef(iface
);
2794 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2796 TRACE("%p\n", iface
);
2801 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2803 TRACE("%p\n", iface
);
2808 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2810 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2816 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2817 LCID lcid
, ITypeInfo
**ppTInfo
)
2819 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2820 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2823 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2824 LPOLESTR
*rgszNames
, UINT cNames
,
2825 LCID lcid
, DISPID
*rgDispId
)
2827 ITypeInfo
*typeinfo
;
2830 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2832 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2835 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2836 ITypeInfo_Release(typeinfo
);
2842 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2843 REFIID riid
, LCID lcid
, WORD wFlags
,
2844 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2845 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2847 ITypeInfo
*typeinfo
;
2850 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2851 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2853 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2856 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2857 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2858 ITypeInfo_Release(typeinfo
);
2864 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2866 TRACE("%p %p\n", iface
, ppdrives
);
2867 return create_drivecoll(ppdrives
);
2870 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2871 BSTR Name
, BSTR
*Result
)
2875 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2877 if (!Result
) return E_POINTER
;
2881 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
2883 /* if both parts have backslashes strip one from Path */
2884 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
2888 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2896 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
2898 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
2902 if (Path
[path_len
-1] != ':')
2909 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2917 else if (Path
|| Name
)
2918 ret
= SysAllocString(Path
? Path
: Name
);
2920 ret
= SysAllocStringLen(NULL
, 0);
2922 if (!ret
) return E_OUTOFMEMORY
;
2928 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR Path
,
2931 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2936 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
2943 for(i
=len
-1; i
>=0; i
--)
2944 if(path
[i
]!='/' && path
[i
]!='\\')
2948 if(path
[i
]=='/' || path
[i
]=='\\')
2952 if(path
[i
]!='/' && path
[i
]!='\\')
2958 if(path
[i
]==':' && i
==1)
2963 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
2968 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2973 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
2975 *pbstrResult
= NULL
;
2979 *pbstrResult
= SysAllocStringLen(Path
, len
);
2981 return E_OUTOFMEMORY
;
2985 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
2990 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2996 *pbstrResult
= NULL
;
3000 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3001 if(Path
[end
]!='/' && Path
[end
]!='\\')
3004 for(i
=end
; i
>=0; i
--)
3005 if(Path
[i
]=='/' || Path
[i
]=='\\')
3009 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3010 *pbstrResult
= NULL
;
3014 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3016 return E_OUTOFMEMORY
;
3020 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3025 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3031 *pbstrResult
= NULL
;
3035 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3036 if(Path
[end
]!='/' && Path
[end
]!='\\')
3039 for(i
=end
; i
>=0; i
--) {
3040 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3042 if(Path
[i
]=='/' || Path
[i
]=='\\')
3047 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3048 *pbstrResult
= NULL
;
3052 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3054 return E_OUTOFMEMORY
;
3058 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
3061 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3066 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3069 static const WCHAR cur_path
[] = {'.',0};
3071 WCHAR buf
[MAX_PATH
], ch
;
3073 DWORD i
, beg
, len
, exp_len
;
3074 WIN32_FIND_DATAW fdata
;
3077 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3087 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3091 buf
[0] = toupperW(buf
[0]);
3092 if(len
>3 && buf
[len
-1] == '\\')
3095 for(beg
=3, i
=3; i
<=len
; i
++) {
3096 if(buf
[i
]!='\\' && buf
[i
])
3101 fh
= FindFirstFileW(buf
, &fdata
);
3102 if(fh
== INVALID_HANDLE_VALUE
)
3105 exp_len
= strlenW(fdata
.cFileName
);
3106 if(exp_len
== i
-beg
)
3107 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3113 *pbstrResult
= SysAllocString(buf
);
3115 return E_OUTOFMEMORY
;
3119 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3121 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3125 TRACE("%p %p\n", iface
, pbstrResult
);
3130 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3132 return E_OUTOFMEMORY
;
3134 if(!RtlGenRandom(&random
, sizeof(random
)))
3136 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3140 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3141 VARIANT_BOOL
*pfExists
)
3143 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3148 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3151 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3153 if (!ret
) return E_POINTER
;
3155 attrs
= GetFileAttributesW(path
);
3156 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3160 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3163 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3165 if (!ret
) return E_POINTER
;
3167 attrs
= GetFileAttributesW(path
);
3168 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3173 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3176 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3181 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3184 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3189 return E_INVALIDARG
;
3191 return create_file(FilePath
, ppfile
);
3194 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3199 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3206 return E_INVALIDARG
;
3208 attrs
= GetFileAttributesW(FolderPath
);
3209 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3210 return CTL_E_PATHNOTFOUND
;
3212 return create_folder(FolderPath
, folder
);
3215 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3216 SpecialFolderConst SpecialFolder
,
3219 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
3224 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3226 WCHAR path
[MAX_PATH
];
3227 DWORD len
, name_len
;
3228 WIN32_FIND_DATAW ffd
;
3231 f
= FindFirstFileW(file
, &ffd
);
3232 if(f
== INVALID_HANDLE_VALUE
)
3233 return create_error(GetLastError());
3235 len
= get_parent_folder_name(file
, file_len
);
3236 if(len
+1 >= MAX_PATH
) {
3241 memcpy(path
, file
, len
*sizeof(WCHAR
));
3246 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3249 name_len
= strlenW(ffd
.cFileName
);
3250 if(len
+name_len
+1 >= MAX_PATH
) {
3254 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3256 TRACE("deleting %s\n", debugstr_w(path
));
3258 if(!DeleteFileW(path
)) {
3259 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3260 || !DeleteFileW(path
)) {
3262 return create_error(GetLastError());
3265 } while(FindNextFileW(f
, &ffd
));
3271 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3274 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3279 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3282 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3284 WCHAR path
[MAX_PATH
];
3285 DWORD len
, name_len
;
3286 WIN32_FIND_DATAW ffd
;
3290 f
= FindFirstFileW(folder
, &ffd
);
3291 if(f
== INVALID_HANDLE_VALUE
)
3292 return create_error(GetLastError());
3294 len
= get_parent_folder_name(folder
, folder_len
);
3295 if(len
+1 >= MAX_PATH
) {
3300 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3305 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3307 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3308 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3311 name_len
= strlenW(ffd
.cFileName
);
3312 if(len
+name_len
+3 >= MAX_PATH
) {
3316 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3317 path
[len
+name_len
] = '\\';
3318 path
[len
+name_len
+1] = '*';
3319 path
[len
+name_len
+2] = 0;
3321 hr
= delete_file(path
, len
+name_len
+2, force
);
3327 hr
= delete_folder(path
, len
+name_len
+2, force
);
3333 path
[len
+name_len
] = 0;
3334 TRACE("deleting %s\n", debugstr_w(path
));
3336 if(!RemoveDirectoryW(path
)) {
3338 return create_error(GetLastError());
3340 } while(FindNextFileW(f
, &ffd
));
3346 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3349 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3354 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3357 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3360 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3365 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3368 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3373 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3374 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3377 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3378 DWORD src_len
, dst_len
, name_len
;
3379 WIN32_FIND_DATAW ffd
;
3383 if(!source
[0] || !destination
[0])
3384 return E_INVALIDARG
;
3386 attrs
= GetFileAttributesW(destination
);
3387 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3388 attrs
= GetFileAttributesW(source
);
3389 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3390 return create_error(GetLastError());
3391 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3392 return CTL_E_FILENOTFOUND
;
3394 if(!CopyFileW(source
, destination
, !overwrite
))
3395 return create_error(GetLastError());
3399 f
= FindFirstFileW(source
, &ffd
);
3400 if(f
== INVALID_HANDLE_VALUE
)
3401 return CTL_E_FILENOTFOUND
;
3403 src_len
= get_parent_folder_name(source
, source_len
);
3404 if(src_len
+1 >= MAX_PATH
) {
3409 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3410 src_path
[src_len
++] = '\\';
3413 dst_len
= destination_len
;
3414 if(dst_len
+1 >= MAX_PATH
) {
3418 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3419 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3420 dst_path
[dst_len
++] = '\\';
3422 hr
= CTL_E_FILENOTFOUND
;
3424 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3427 name_len
= strlenW(ffd
.cFileName
);
3428 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3432 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3433 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3435 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3437 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3439 return create_error(GetLastError());
3443 } while(FindNextFileW(f
, &ffd
));
3449 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3450 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3452 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3454 if(!Source
|| !Destination
)
3457 return copy_file(Source
, SysStringLen(Source
), Destination
,
3458 SysStringLen(Destination
), OverWriteFiles
);
3461 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3462 DWORD destination_len
, VARIANT_BOOL overwrite
)
3464 DWORD tmp
, src_len
, dst_len
, name_len
;
3465 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3466 WIN32_FIND_DATAW ffd
;
3469 BOOL copied
= FALSE
;
3471 if(!source
[0] || !destination
[0])
3472 return E_INVALIDARG
;
3474 dst_len
= destination_len
;
3475 if(dst_len
+1 >= MAX_PATH
)
3477 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3479 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3480 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3481 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3482 if(!CreateDirectoryW(dst
, NULL
)) {
3483 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3484 tmp
= GetFileAttributesW(dst
);
3485 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3486 return CTL_E_FILEALREADYEXISTS
;
3488 return create_error(GetLastError());
3493 src_len
= source_len
;
3494 if(src_len
+2 >= MAX_PATH
)
3496 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3497 src
[src_len
++] = '\\';
3501 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3502 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3503 return create_error(GetLastError());
3505 f
= FindFirstFileW(src
, &ffd
);
3507 src_len
= get_parent_folder_name(source
, source_len
);
3508 if(src_len
+2 >= MAX_PATH
)
3510 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3512 src
[src_len
++] = '\\';
3514 f
= FindFirstFileW(source
, &ffd
);
3516 if(f
== INVALID_HANDLE_VALUE
)
3517 return CTL_E_PATHNOTFOUND
;
3519 dst
[dst_len
++] = '\\';
3523 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3525 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3526 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3529 name_len
= strlenW(ffd
.cFileName
);
3530 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3534 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3535 dst
[dst_len
+name_len
] = 0;
3536 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3537 src
[src_len
+name_len
] = '\\';
3538 src
[src_len
+name_len
+1] = '*';
3539 src
[src_len
+name_len
+2] = 0;
3541 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3543 if(!CreateDirectoryW(dst
, NULL
)) {
3544 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3545 tmp
= GetFileAttributesW(dst
);
3546 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3548 return CTL_E_FILEALREADYEXISTS
;
3553 return create_error(GetLastError());
3557 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3558 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3563 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3564 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3568 } while(FindNextFileW(f
, &ffd
));
3571 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3574 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3575 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3577 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3579 if(!Source
|| !Destination
)
3582 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3583 SysStringLen(Destination
), OverWriteFiles
);
3586 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3591 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3593 ret
= CreateDirectoryW(path
, NULL
);
3597 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3598 return HRESULT_FROM_WIN32(GetLastError());
3601 return create_folder(path
, folder
);
3604 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3605 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3606 ITextStream
**stream
)
3610 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3612 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3613 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3616 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3617 IOMode mode
, VARIANT_BOOL create
,
3618 Tristate format
, ITextStream
**stream
)
3622 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3623 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3625 if (format
== TristateUseDefault
) {
3626 FIXME("default format not handled, defaulting to unicode\n");
3627 format
= TristateTrue
;
3630 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3633 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3634 StandardStreamTypes StandardStreamType
,
3635 VARIANT_BOOL Unicode
,
3638 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3643 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3645 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3649 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3650 a
= (WORD
)( version
>> 48);
3651 b
= (WORD
)((version
>> 32) & 0xffff);
3652 c
= (WORD
)((version
>> 16) & 0xffff);
3653 d
= (WORD
)( version
& 0xffff);
3655 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3658 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3660 static const WCHAR rootW
[] = {'\\',0};
3661 VS_FIXEDFILEINFO
*info
;
3667 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3669 len
= GetFileVersionInfoSizeW(name
, NULL
);
3671 return HRESULT_FROM_WIN32(GetLastError());
3673 ptr
= heap_alloc(len
);
3674 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3677 return HRESULT_FROM_WIN32(GetLastError());
3680 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3684 return HRESULT_FROM_WIN32(GetLastError());
3687 get_versionstring(info
, ver
);
3690 *version
= SysAllocString(ver
);
3691 TRACE("version=%s\n", debugstr_w(ver
));
3696 static const struct IFileSystem3Vtbl filesys_vtbl
=
3698 filesys_QueryInterface
,
3701 filesys_GetTypeInfoCount
,
3702 filesys_GetTypeInfo
,
3703 filesys_GetIDsOfNames
,
3707 filesys_GetDriveName
,
3708 filesys_GetParentFolderName
,
3709 filesys_GetFileName
,
3710 filesys_GetBaseName
,
3711 filesys_GetExtensionName
,
3712 filesys_GetAbsolutePathName
,
3713 filesys_GetTempName
,
3714 filesys_DriveExists
,
3716 filesys_FolderExists
,
3720 filesys_GetSpecialFolder
,
3722 filesys_DeleteFolder
,
3727 filesys_CreateFolder
,
3728 filesys_CreateTextFile
,
3729 filesys_OpenTextFile
,
3730 filesys_GetStandardStream
,
3731 filesys_GetFileVersion
3734 static IFileSystem3 filesystem
= { &filesys_vtbl
};
3736 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3738 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3740 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);