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
);
638 TRACE("(%p)\n", This
);
640 if(!CloseHandle(This
->file
))
648 static const ITextStreamVtbl textstreamvtbl
= {
649 textstream_QueryInterface
,
652 textstream_GetTypeInfoCount
,
653 textstream_GetTypeInfo
,
654 textstream_GetIDsOfNames
,
657 textstream_get_Column
,
658 textstream_get_AtEndOfStream
,
659 textstream_get_AtEndOfLine
,
664 textstream_WriteLine
,
665 textstream_WriteBlankLines
,
671 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
673 struct textstream
*stream
;
676 /* map access mode */
680 access
= GENERIC_READ
;
683 access
= GENERIC_WRITE
;
686 access
= FILE_APPEND_DATA
;
692 stream
= heap_alloc(sizeof(struct textstream
));
693 if (!stream
) return E_OUTOFMEMORY
;
695 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
698 stream
->unicode
= unicode
;
699 stream
->first_read
= TRUE
;
701 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
702 if (stream
->file
== INVALID_HANDLE_VALUE
)
704 HRESULT hr
= create_error(GetLastError());
709 if (mode
== ForReading
)
710 GetFileSizeEx(stream
->file
, &stream
->size
);
712 stream
->size
.QuadPart
= 0;
714 /* Write Unicode BOM */
715 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
717 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
718 if (!ret
|| written
!= sizeof(utf16bom
)) {
719 ITextStream_Release(&stream
->ITextStream_iface
);
720 return create_error(GetLastError());
724 *ret
= &stream
->ITextStream_iface
;
728 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
730 struct drive
*This
= impl_from_IDrive(iface
);
732 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
736 if (IsEqualIID( riid
, &IID_IDrive
) ||
737 IsEqualIID( riid
, &IID_IDispatch
) ||
738 IsEqualIID( riid
, &IID_IUnknown
))
741 IDrive_AddRef(iface
);
744 return E_NOINTERFACE
;
749 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
751 struct drive
*This
= impl_from_IDrive(iface
);
752 ULONG ref
= InterlockedIncrement(&This
->ref
);
753 TRACE("(%p)->(%d)\n", This
, ref
);
757 static ULONG WINAPI
drive_Release(IDrive
*iface
)
759 struct drive
*This
= impl_from_IDrive(iface
);
760 ULONG ref
= InterlockedDecrement(&This
->ref
);
761 TRACE("(%p)->(%d)\n", This
, ref
);
765 SysFreeString(This
->root
);
772 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
774 struct drive
*This
= impl_from_IDrive(iface
);
775 TRACE("(%p)->(%p)\n", This
, pctinfo
);
780 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
781 LCID lcid
, ITypeInfo
**ppTInfo
)
783 struct drive
*This
= impl_from_IDrive(iface
);
784 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
785 return get_typeinfo(IDrive_tid
, ppTInfo
);
788 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
789 LPOLESTR
*rgszNames
, UINT cNames
,
790 LCID lcid
, DISPID
*rgDispId
)
792 struct drive
*This
= impl_from_IDrive(iface
);
796 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
798 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
801 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
802 ITypeInfo_Release(typeinfo
);
808 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
809 REFIID riid
, LCID lcid
, WORD wFlags
,
810 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
811 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
813 struct drive
*This
= impl_from_IDrive(iface
);
817 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
818 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
820 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
823 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
824 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
825 ITypeInfo_Release(typeinfo
);
831 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
833 struct drive
*This
= impl_from_IDrive(iface
);
834 FIXME("(%p)->(%p): stub\n", This
, path
);
838 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
840 struct drive
*This
= impl_from_IDrive(iface
);
842 TRACE("(%p)->(%p)\n", This
, letter
);
847 *letter
= SysAllocStringLen(This
->root
, 1);
849 return E_OUTOFMEMORY
;
854 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
856 struct drive
*This
= impl_from_IDrive(iface
);
857 FIXME("(%p)->(%p): stub\n", This
, share_name
);
861 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
863 struct drive
*This
= impl_from_IDrive(iface
);
865 TRACE("(%p)->(%p)\n", This
, type
);
867 switch (GetDriveTypeW(This
->root
))
869 case DRIVE_REMOVABLE
:
892 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
894 struct drive
*This
= impl_from_IDrive(iface
);
895 FIXME("(%p)->(%p): stub\n", This
, folder
);
899 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
903 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
906 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
911 V_I4(v
) = src
->u
.LowPart
;
917 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
919 struct drive
*This
= impl_from_IDrive(iface
);
920 ULARGE_INTEGER avail
;
922 TRACE("(%p)->(%p)\n", This
, v
);
927 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
930 return variant_from_largeint(&avail
, v
);
933 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
935 struct drive
*This
= impl_from_IDrive(iface
);
936 ULARGE_INTEGER freespace
;
938 TRACE("(%p)->(%p)\n", This
, v
);
943 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
946 return variant_from_largeint(&freespace
, v
);
949 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
951 struct drive
*This
= impl_from_IDrive(iface
);
952 ULARGE_INTEGER total
;
954 TRACE("(%p)->(%p)\n", This
, v
);
959 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
962 return variant_from_largeint(&total
, v
);
965 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
967 struct drive
*This
= impl_from_IDrive(iface
);
968 WCHAR nameW
[MAX_PATH
+1];
971 TRACE("(%p)->(%p)\n", This
, name
);
977 ret
= GetVolumeInformationW(This
->root
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, NULL
, NULL
, NULL
, 0);
979 *name
= SysAllocString(nameW
);
980 return ret
? S_OK
: E_FAIL
;
983 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
985 struct drive
*This
= impl_from_IDrive(iface
);
986 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
990 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
992 struct drive
*This
= impl_from_IDrive(iface
);
993 WCHAR nameW
[MAX_PATH
+1];
996 TRACE("(%p)->(%p)\n", This
, fs
);
1002 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
1004 *fs
= SysAllocString(nameW
);
1005 return ret
? S_OK
: E_FAIL
;
1008 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
1010 struct drive
*This
= impl_from_IDrive(iface
);
1013 TRACE("(%p)->(%p)\n", This
, serial
);
1018 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1019 return ret
? S_OK
: E_FAIL
;
1022 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1024 struct drive
*This
= impl_from_IDrive(iface
);
1025 ULARGE_INTEGER freespace
;
1028 TRACE("(%p)->(%p)\n", This
, ready
);
1033 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1034 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1038 static const IDriveVtbl drivevtbl
= {
1039 drive_QueryInterface
,
1042 drive_GetTypeInfoCount
,
1044 drive_GetIDsOfNames
,
1047 drive_get_DriveLetter
,
1048 drive_get_ShareName
,
1049 drive_get_DriveType
,
1050 drive_get_RootFolder
,
1051 drive_get_AvailableSpace
,
1052 drive_get_FreeSpace
,
1053 drive_get_TotalSize
,
1054 drive_get_VolumeName
,
1055 drive_put_VolumeName
,
1056 drive_get_FileSystem
,
1057 drive_get_SerialNumber
,
1061 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1067 This
= heap_alloc(sizeof(*This
));
1068 if (!This
) return E_OUTOFMEMORY
;
1070 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1072 This
->root
= SysAllocStringLen(NULL
, 3);
1076 return E_OUTOFMEMORY
;
1078 This
->root
[0] = letter
;
1079 This
->root
[1] = ':';
1080 This
->root
[2] = '\\';
1083 *drive
= &This
->IDrive_iface
;
1087 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1089 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1091 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1095 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1096 IsEqualIID( riid
, &IID_IUnknown
))
1099 IEnumVARIANT_AddRef(iface
);
1102 return E_NOINTERFACE
;
1107 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1109 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1110 ULONG ref
= InterlockedIncrement(&This
->ref
);
1111 TRACE("(%p)->(%d)\n", This
, ref
);
1115 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1117 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1118 ULONG ref
= InterlockedDecrement(&This
->ref
);
1120 TRACE("(%p)->(%d)\n", This
, ref
);
1124 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1125 FindClose(This
->data
.u
.foldercoll
.find
);
1132 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1134 static const WCHAR allW
[] = {'*',0};
1135 WCHAR pathW
[MAX_PATH
];
1139 strcpyW(pathW
, path
);
1140 len
= strlenW(pathW
);
1141 if (len
&& pathW
[len
-1] != '\\')
1142 strcatW(pathW
, bsW
);
1143 strcatW(pathW
, allW
);
1144 handle
= FindFirstFileW(pathW
, data
);
1145 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1147 /* find first dir/file */
1150 if (file
? is_file_data(data
) : is_dir_data(data
))
1153 if (!FindNextFileW(handle
, data
))
1162 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1164 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1165 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1166 WIN32_FIND_DATAW data
;
1169 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1174 if (!celt
) return S_OK
;
1178 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1179 if (!handle
) return S_FALSE
;
1181 This
->data
.u
.foldercoll
.find
= handle
;
1185 if (!FindNextFileW(handle
, &data
))
1191 if (is_dir_data(&data
))
1197 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1198 hr
= create_folder(str
, &folder
);
1200 if (FAILED(hr
)) return hr
;
1202 V_VT(&var
[count
]) = VT_DISPATCH
;
1203 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1206 if (count
>= celt
) break;
1208 } while (FindNextFileW(handle
, &data
));
1213 return (count
< celt
) ? S_FALSE
: S_OK
;
1216 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1218 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1219 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1220 WIN32_FIND_DATAW data
;
1222 TRACE("(%p)->(%d)\n", This
, celt
);
1224 if (!celt
) return S_OK
;
1228 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1229 if (!handle
) return S_FALSE
;
1231 This
->data
.u
.foldercoll
.find
= handle
;
1235 if (!FindNextFileW(handle
, &data
))
1241 if (is_dir_data(&data
))
1245 } while (FindNextFileW(handle
, &data
));
1247 return celt
? S_FALSE
: S_OK
;
1250 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1252 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1254 TRACE("(%p)\n", This
);
1256 FindClose(This
->data
.u
.foldercoll
.find
);
1257 This
->data
.u
.foldercoll
.find
= NULL
;
1262 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1264 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1265 TRACE("(%p)->(%p)\n", This
, pclone
);
1266 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1269 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1270 enumvariant_QueryInterface
,
1272 foldercoll_enumvariant_Release
,
1273 foldercoll_enumvariant_Next
,
1274 foldercoll_enumvariant_Skip
,
1275 foldercoll_enumvariant_Reset
,
1276 foldercoll_enumvariant_Clone
1279 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1281 struct enumvariant
*This
;
1285 This
= heap_alloc(sizeof(*This
));
1286 if (!This
) return E_OUTOFMEMORY
;
1288 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1290 This
->data
.u
.foldercoll
.find
= NULL
;
1291 This
->data
.u
.foldercoll
.coll
= collection
;
1292 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1294 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1299 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1301 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1302 ULONG ref
= InterlockedDecrement(&This
->ref
);
1304 TRACE("(%p)->(%d)\n", This
, ref
);
1308 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1309 FindClose(This
->data
.u
.filecoll
.find
);
1316 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1318 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1319 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1320 WIN32_FIND_DATAW data
;
1323 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1328 if (!celt
) return S_OK
;
1332 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1333 if (!handle
) return S_FALSE
;
1334 This
->data
.u
.filecoll
.find
= handle
;
1336 else if (!FindNextFileW(handle
, &data
))
1341 if (is_file_data(&data
))
1347 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1348 hr
= create_file(str
, &file
);
1350 if (FAILED(hr
)) return hr
;
1352 V_VT(&var
[count
]) = VT_DISPATCH
;
1353 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1354 if (++count
>= celt
) break;
1356 } while (FindNextFileW(handle
, &data
));
1361 return (count
< celt
) ? S_FALSE
: S_OK
;
1364 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1366 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1367 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1368 WIN32_FIND_DATAW data
;
1370 TRACE("(%p)->(%d)\n", This
, celt
);
1372 if (!celt
) return S_OK
;
1376 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1377 if (!handle
) return S_FALSE
;
1378 This
->data
.u
.filecoll
.find
= handle
;
1380 else if (!FindNextFileW(handle
, &data
))
1385 if (is_file_data(&data
))
1387 } while (celt
&& FindNextFileW(handle
, &data
));
1389 return celt
? S_FALSE
: S_OK
;
1392 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1394 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1396 TRACE("(%p)\n", This
);
1398 FindClose(This
->data
.u
.filecoll
.find
);
1399 This
->data
.u
.filecoll
.find
= NULL
;
1404 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1406 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1407 TRACE("(%p)->(%p)\n", This
, pclone
);
1408 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1411 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1412 enumvariant_QueryInterface
,
1414 filecoll_enumvariant_Release
,
1415 filecoll_enumvariant_Next
,
1416 filecoll_enumvariant_Skip
,
1417 filecoll_enumvariant_Reset
,
1418 filecoll_enumvariant_Clone
1421 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1423 struct enumvariant
*This
;
1427 This
= heap_alloc(sizeof(*This
));
1428 if (!This
) return E_OUTOFMEMORY
;
1430 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1432 This
->data
.u
.filecoll
.find
= NULL
;
1433 This
->data
.u
.filecoll
.coll
= collection
;
1434 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1436 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1441 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1443 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1444 ULONG ref
= InterlockedDecrement(&This
->ref
);
1446 TRACE("(%p)->(%d)\n", This
, ref
);
1450 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1457 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1459 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1462 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1464 penum
->data
.u
.drivecoll
.cur
= i
;
1471 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1473 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1476 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1481 if (!celt
) return S_OK
;
1483 while (find_next_drive(This
) == S_OK
)
1488 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1489 if (FAILED(hr
)) return hr
;
1491 V_VT(&var
[count
]) = VT_DISPATCH
;
1492 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1494 if (++count
>= celt
) break;
1500 return (count
< celt
) ? S_FALSE
: S_OK
;
1503 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1505 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1507 TRACE("(%p)->(%d)\n", This
, celt
);
1509 if (!celt
) return S_OK
;
1511 while (celt
&& find_next_drive(This
) == S_OK
)
1514 return celt
? S_FALSE
: S_OK
;
1517 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1519 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1521 TRACE("(%p)\n", This
);
1523 This
->data
.u
.drivecoll
.cur
= -1;
1527 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1529 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1530 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1534 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1535 enumvariant_QueryInterface
,
1537 drivecoll_enumvariant_Release
,
1538 drivecoll_enumvariant_Next
,
1539 drivecoll_enumvariant_Skip
,
1540 drivecoll_enumvariant_Reset
,
1541 drivecoll_enumvariant_Clone
1544 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1546 struct enumvariant
*This
;
1550 This
= heap_alloc(sizeof(*This
));
1551 if (!This
) return E_OUTOFMEMORY
;
1553 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1555 This
->data
.u
.drivecoll
.coll
= collection
;
1556 This
->data
.u
.drivecoll
.cur
= -1;
1557 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1559 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1564 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1566 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1568 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1572 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1573 IsEqualIID( riid
, &IID_IDispatch
) ||
1574 IsEqualIID( riid
, &IID_IUnknown
))
1577 IFolderCollection_AddRef(iface
);
1580 return E_NOINTERFACE
;
1585 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1587 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1588 ULONG ref
= InterlockedIncrement(&This
->ref
);
1589 TRACE("(%p)->(%d)\n", This
, ref
);
1593 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1595 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1596 ULONG ref
= InterlockedDecrement(&This
->ref
);
1597 TRACE("(%p)->(%d)\n", This
, ref
);
1601 SysFreeString(This
->path
);
1608 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1610 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1611 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1616 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1617 LCID lcid
, ITypeInfo
**ppTInfo
)
1619 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1620 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1621 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1624 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1625 LPOLESTR
*rgszNames
, UINT cNames
,
1626 LCID lcid
, DISPID
*rgDispId
)
1628 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1629 ITypeInfo
*typeinfo
;
1632 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1634 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1637 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1638 ITypeInfo_Release(typeinfo
);
1644 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1645 REFIID riid
, LCID lcid
, WORD wFlags
,
1646 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1647 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1649 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1650 ITypeInfo
*typeinfo
;
1653 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1654 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1656 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1659 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1660 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1661 ITypeInfo_Release(typeinfo
);
1667 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1669 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1670 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1674 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1676 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1677 FIXME("(%p)->(%p): stub\n", This
, folder
);
1681 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1683 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1685 TRACE("(%p)->(%p)\n", This
, newenum
);
1690 return create_foldercoll_enum(This
, newenum
);
1693 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1695 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1696 static const WCHAR allW
[] = {'\\','*',0};
1697 WIN32_FIND_DATAW data
;
1698 WCHAR pathW
[MAX_PATH
];
1701 TRACE("(%p)->(%p)\n", This
, count
);
1708 strcpyW(pathW
, This
->path
);
1709 strcatW(pathW
, allW
);
1710 handle
= FindFirstFileW(pathW
, &data
);
1711 if (handle
== INVALID_HANDLE_VALUE
)
1712 return HRESULT_FROM_WIN32(GetLastError());
1716 if (is_dir_data(&data
))
1718 } while (FindNextFileW(handle
, &data
));
1724 static const IFolderCollectionVtbl foldercollvtbl
= {
1725 foldercoll_QueryInterface
,
1728 foldercoll_GetTypeInfoCount
,
1729 foldercoll_GetTypeInfo
,
1730 foldercoll_GetIDsOfNames
,
1733 foldercoll_get_Item
,
1734 foldercoll_get__NewEnum
,
1735 foldercoll_get_Count
1738 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1740 struct foldercollection
*This
;
1744 This
= heap_alloc(sizeof(struct foldercollection
));
1745 if (!This
) return E_OUTOFMEMORY
;
1747 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1749 This
->path
= SysAllocString(path
);
1753 return E_OUTOFMEMORY
;
1756 *folders
= &This
->IFolderCollection_iface
;
1761 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1763 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1765 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1769 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1770 IsEqualIID( riid
, &IID_IDispatch
) ||
1771 IsEqualIID( riid
, &IID_IUnknown
))
1774 IFileCollection_AddRef(iface
);
1777 return E_NOINTERFACE
;
1782 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1784 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1785 ULONG ref
= InterlockedIncrement(&This
->ref
);
1786 TRACE("(%p)->(%d)\n", This
, ref
);
1790 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1792 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1793 ULONG ref
= InterlockedDecrement(&This
->ref
);
1794 TRACE("(%p)->(%d)\n", This
, ref
);
1798 SysFreeString(This
->path
);
1805 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1807 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1808 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1813 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1814 LCID lcid
, ITypeInfo
**ppTInfo
)
1816 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1817 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1818 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1821 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1822 LPOLESTR
*rgszNames
, UINT cNames
,
1823 LCID lcid
, DISPID
*rgDispId
)
1825 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1826 ITypeInfo
*typeinfo
;
1829 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1831 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1834 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1835 ITypeInfo_Release(typeinfo
);
1841 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1842 REFIID riid
, LCID lcid
, WORD wFlags
,
1843 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1844 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1846 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1847 ITypeInfo
*typeinfo
;
1850 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1851 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1853 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1856 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1857 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1858 ITypeInfo_Release(typeinfo
);
1864 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1866 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1867 FIXME("(%p)->(%p)\n", This
, file
);
1871 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1873 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1875 TRACE("(%p)->(%p)\n", This
, ppenum
);
1880 return create_filecoll_enum(This
, ppenum
);
1883 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1885 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1886 static const WCHAR allW
[] = {'\\','*',0};
1887 WIN32_FIND_DATAW data
;
1888 WCHAR pathW
[MAX_PATH
];
1891 TRACE("(%p)->(%p)\n", This
, count
);
1898 strcpyW(pathW
, This
->path
);
1899 strcatW(pathW
, allW
);
1900 handle
= FindFirstFileW(pathW
, &data
);
1901 if (handle
== INVALID_HANDLE_VALUE
)
1902 return HRESULT_FROM_WIN32(GetLastError());
1906 if (is_file_data(&data
))
1908 } while (FindNextFileW(handle
, &data
));
1914 static const IFileCollectionVtbl filecollectionvtbl
= {
1915 filecoll_QueryInterface
,
1918 filecoll_GetTypeInfoCount
,
1919 filecoll_GetTypeInfo
,
1920 filecoll_GetIDsOfNames
,
1923 filecoll_get__NewEnum
,
1927 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1929 struct filecollection
*This
;
1933 This
= heap_alloc(sizeof(*This
));
1934 if (!This
) return E_OUTOFMEMORY
;
1936 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1938 This
->path
= SysAllocString(path
);
1942 return E_OUTOFMEMORY
;
1945 *files
= &This
->IFileCollection_iface
;
1949 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1951 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1953 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1957 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1958 IsEqualIID( riid
, &IID_IDispatch
) ||
1959 IsEqualIID( riid
, &IID_IUnknown
))
1962 IDriveCollection_AddRef(iface
);
1965 return E_NOINTERFACE
;
1970 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
1972 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1973 ULONG ref
= InterlockedIncrement(&This
->ref
);
1974 TRACE("(%p)->(%d)\n", This
, ref
);
1978 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
1980 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1981 ULONG ref
= InterlockedDecrement(&This
->ref
);
1982 TRACE("(%p)->(%d)\n", This
, ref
);
1990 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
1992 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1993 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1998 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
1999 LCID lcid
, ITypeInfo
**ppTInfo
)
2001 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2002 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2003 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
2006 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
2007 LPOLESTR
*rgszNames
, UINT cNames
,
2008 LCID lcid
, DISPID
*rgDispId
)
2010 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2011 ITypeInfo
*typeinfo
;
2014 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2016 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2019 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2020 ITypeInfo_Release(typeinfo
);
2026 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2027 REFIID riid
, LCID lcid
, WORD wFlags
,
2028 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2029 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2031 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2032 ITypeInfo
*typeinfo
;
2035 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2036 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2038 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2041 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2042 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2043 ITypeInfo_Release(typeinfo
);
2049 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2051 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2052 FIXME("(%p)->(%p): stub\n", This
, drive
);
2056 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2058 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2060 TRACE("(%p)->(%p)\n", This
, ppenum
);
2065 return create_drivecoll_enum(This
, ppenum
);
2068 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2070 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2072 TRACE("(%p)->(%p)\n", This
, count
);
2074 if (!count
) return E_POINTER
;
2076 *count
= This
->count
;
2080 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2081 drivecoll_QueryInterface
,
2084 drivecoll_GetTypeInfoCount
,
2085 drivecoll_GetTypeInfo
,
2086 drivecoll_GetIDsOfNames
,
2089 drivecoll_get__NewEnum
,
2093 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2095 struct drivecollection
*This
;
2100 This
= heap_alloc(sizeof(*This
));
2101 if (!This
) return E_OUTOFMEMORY
;
2103 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2105 This
->drives
= mask
= GetLogicalDrives();
2106 /* count set bits */
2107 for (This
->count
= 0; mask
; This
->count
++)
2110 *drives
= &This
->IDriveCollection_iface
;
2114 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2116 struct folder
*This
= impl_from_IFolder(iface
);
2118 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2122 if (IsEqualIID( riid
, &IID_IFolder
) ||
2123 IsEqualIID( riid
, &IID_IDispatch
) ||
2124 IsEqualIID( riid
, &IID_IUnknown
))
2127 IFolder_AddRef(iface
);
2130 return E_NOINTERFACE
;
2135 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2137 struct folder
*This
= impl_from_IFolder(iface
);
2138 ULONG ref
= InterlockedIncrement(&This
->ref
);
2139 TRACE("(%p)->(%d)\n", This
, ref
);
2143 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2145 struct folder
*This
= impl_from_IFolder(iface
);
2146 ULONG ref
= InterlockedDecrement(&This
->ref
);
2147 TRACE("(%p)->(%d)\n", This
, ref
);
2151 SysFreeString(This
->path
);
2158 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2160 struct folder
*This
= impl_from_IFolder(iface
);
2161 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2166 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2167 LCID lcid
, ITypeInfo
**ppTInfo
)
2169 struct folder
*This
= impl_from_IFolder(iface
);
2170 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2171 return get_typeinfo(IFolder_tid
, ppTInfo
);
2174 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2175 LPOLESTR
*rgszNames
, UINT cNames
,
2176 LCID lcid
, DISPID
*rgDispId
)
2178 struct folder
*This
= impl_from_IFolder(iface
);
2179 ITypeInfo
*typeinfo
;
2182 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2184 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2187 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2188 ITypeInfo_Release(typeinfo
);
2194 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2195 REFIID riid
, LCID lcid
, WORD wFlags
,
2196 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2197 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2199 struct folder
*This
= impl_from_IFolder(iface
);
2200 ITypeInfo
*typeinfo
;
2203 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2204 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2206 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2209 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2210 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2211 ITypeInfo_Release(typeinfo
);
2217 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2219 struct folder
*This
= impl_from_IFolder(iface
);
2221 TRACE("(%p)->(%p)\n", This
, path
);
2226 *path
= SysAllocString(This
->path
);
2227 return *path
? S_OK
: E_OUTOFMEMORY
;
2230 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2232 struct folder
*This
= impl_from_IFolder(iface
);
2235 TRACE("(%p)->(%p)\n", This
, name
);
2242 ptr
= strrchrW(This
->path
, '\\');
2245 *name
= SysAllocString(ptr
+1);
2246 TRACE("%s\n", debugstr_w(*name
));
2247 if (!*name
) return E_OUTOFMEMORY
;
2255 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2257 struct folder
*This
= impl_from_IFolder(iface
);
2258 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2262 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2264 struct folder
*This
= impl_from_IFolder(iface
);
2265 FIXME("(%p)->(%p): stub\n", This
, path
);
2269 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2271 struct folder
*This
= impl_from_IFolder(iface
);
2272 FIXME("(%p)->(%p): stub\n", This
, name
);
2276 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2278 struct folder
*This
= impl_from_IFolder(iface
);
2279 FIXME("(%p)->(%p): stub\n", This
, drive
);
2283 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2285 struct folder
*This
= impl_from_IFolder(iface
);
2286 FIXME("(%p)->(%p): stub\n", This
, parent
);
2290 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2292 struct folder
*This
= impl_from_IFolder(iface
);
2293 FIXME("(%p)->(%p): stub\n", This
, attr
);
2297 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2299 struct folder
*This
= impl_from_IFolder(iface
);
2300 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2304 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2306 struct folder
*This
= impl_from_IFolder(iface
);
2307 FIXME("(%p)->(%p): stub\n", This
, date
);
2311 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2313 struct folder
*This
= impl_from_IFolder(iface
);
2314 FIXME("(%p)->(%p): stub\n", This
, date
);
2318 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2320 struct folder
*This
= impl_from_IFolder(iface
);
2321 FIXME("(%p)->(%p): stub\n", This
, date
);
2325 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2327 struct folder
*This
= impl_from_IFolder(iface
);
2328 FIXME("(%p)->(%p): stub\n", This
, type
);
2332 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2334 struct folder
*This
= impl_from_IFolder(iface
);
2335 FIXME("(%p)->(%x): stub\n", This
, force
);
2339 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2341 struct folder
*This
= impl_from_IFolder(iface
);
2342 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2346 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2348 struct folder
*This
= impl_from_IFolder(iface
);
2349 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2353 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2355 struct folder
*This
= impl_from_IFolder(iface
);
2356 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2360 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2362 struct folder
*This
= impl_from_IFolder(iface
);
2363 FIXME("(%p)->(%p): stub\n", This
, size
);
2367 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2369 struct folder
*This
= impl_from_IFolder(iface
);
2371 TRACE("(%p)->(%p)\n", This
, folders
);
2376 return create_foldercoll(This
->path
, folders
);
2379 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2381 struct folder
*This
= impl_from_IFolder(iface
);
2383 TRACE("(%p)->(%p)\n", This
, files
);
2388 return create_filecoll(This
->path
, files
);
2391 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2392 VARIANT_BOOL unicode
, ITextStream
**stream
)
2394 struct folder
*This
= impl_from_IFolder(iface
);
2395 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2399 static const IFolderVtbl foldervtbl
= {
2400 folder_QueryInterface
,
2403 folder_GetTypeInfoCount
,
2405 folder_GetIDsOfNames
,
2410 folder_get_ShortPath
,
2411 folder_get_ShortName
,
2413 folder_get_ParentFolder
,
2414 folder_get_Attributes
,
2415 folder_put_Attributes
,
2416 folder_get_DateCreated
,
2417 folder_get_DateLastModified
,
2418 folder_get_DateLastAccessed
,
2423 folder_get_IsRootFolder
,
2425 folder_get_SubFolders
,
2427 folder_CreateTextFile
2430 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2432 struct folder
*This
;
2436 TRACE("%s\n", debugstr_w(path
));
2438 This
= heap_alloc(sizeof(struct folder
));
2439 if (!This
) return E_OUTOFMEMORY
;
2441 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2443 This
->path
= SysAllocString(path
);
2447 return E_OUTOFMEMORY
;
2450 *folder
= &This
->IFolder_iface
;
2455 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2457 struct file
*This
= impl_from_IFile(iface
);
2459 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2461 if (IsEqualIID(riid
, &IID_IFile
) ||
2462 IsEqualIID(riid
, &IID_IDispatch
) ||
2463 IsEqualIID(riid
, &IID_IUnknown
))
2466 IFile_AddRef(iface
);
2471 return E_NOINTERFACE
;
2474 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2476 struct file
*This
= impl_from_IFile(iface
);
2477 LONG ref
= InterlockedIncrement(&This
->ref
);
2479 TRACE("(%p) ref=%d\n", This
, ref
);
2484 static ULONG WINAPI
file_Release(IFile
*iface
)
2486 struct file
*This
= impl_from_IFile(iface
);
2487 LONG ref
= InterlockedDecrement(&This
->ref
);
2489 TRACE("(%p) ref=%d\n", This
, ref
);
2493 heap_free(This
->path
);
2500 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2502 struct file
*This
= impl_from_IFile(iface
);
2504 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2510 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2511 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2513 struct file
*This
= impl_from_IFile(iface
);
2515 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2517 return get_typeinfo(IFile_tid
, ppTInfo
);
2520 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2521 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2523 struct file
*This
= impl_from_IFile(iface
);
2524 ITypeInfo
*typeinfo
;
2527 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2528 rgszNames
, cNames
, lcid
, rgDispId
);
2530 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2532 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2533 ITypeInfo_Release(typeinfo
);
2538 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2540 struct file
*This
= impl_from_IFile(iface
);
2541 ITypeInfo
*typeinfo
;
2544 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2545 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2547 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2550 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2551 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2552 ITypeInfo_Release(typeinfo
);
2557 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2559 struct file
*This
= impl_from_IFile(iface
);
2561 TRACE("(%p)->(%p)\n", This
, path
);
2566 *path
= SysAllocString(This
->path
);
2568 return E_OUTOFMEMORY
;
2573 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2575 struct file
*This
= impl_from_IFile(iface
);
2578 TRACE("(%p)->(%p)\n", This
, name
);
2585 ptr
= strrchrW(This
->path
, '\\');
2588 *name
= SysAllocString(ptr
+1);
2589 TRACE("%s\n", debugstr_w(*name
));
2590 if (!*name
) return E_OUTOFMEMORY
;
2598 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2600 struct file
*This
= impl_from_IFile(iface
);
2601 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2605 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2607 struct file
*This
= impl_from_IFile(iface
);
2608 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2612 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2614 struct file
*This
= impl_from_IFile(iface
);
2615 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2619 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2621 struct file
*This
= impl_from_IFile(iface
);
2622 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2626 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2628 struct file
*This
= impl_from_IFile(iface
);
2629 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2633 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2635 struct file
*This
= impl_from_IFile(iface
);
2638 TRACE("(%p)->(%p)\n", This
, pfa
);
2643 fa
= GetFileAttributesW(This
->path
);
2644 if(fa
== INVALID_FILE_ATTRIBUTES
)
2645 return create_error(GetLastError());
2647 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2648 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2649 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2653 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2655 struct file
*This
= impl_from_IFile(iface
);
2657 TRACE("(%p)->(%x)\n", This
, pfa
);
2659 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2662 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2664 struct file
*This
= impl_from_IFile(iface
);
2665 FIXME("(%p)->(%p)\n", This
, pdate
);
2669 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2671 struct file
*This
= impl_from_IFile(iface
);
2672 FIXME("(%p)->(%p)\n", This
, pdate
);
2676 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2678 struct file
*This
= impl_from_IFile(iface
);
2679 FIXME("(%p)->(%p)\n", This
, pdate
);
2683 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2685 struct file
*This
= impl_from_IFile(iface
);
2686 ULARGE_INTEGER size
;
2687 WIN32_FIND_DATAW fd
;
2690 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2695 f
= FindFirstFileW(This
->path
, &fd
);
2696 if(f
== INVALID_HANDLE_VALUE
)
2697 return create_error(GetLastError());
2700 size
.u
.LowPart
= fd
.nFileSizeLow
;
2701 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2703 return variant_from_largeint(&size
, pvarSize
);
2706 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2708 struct file
*This
= impl_from_IFile(iface
);
2709 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2713 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2715 struct file
*This
= impl_from_IFile(iface
);
2716 FIXME("(%p)->(%x)\n", This
, Force
);
2720 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2722 struct file
*This
= impl_from_IFile(iface
);
2723 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2727 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2729 struct file
*This
= impl_from_IFile(iface
);
2730 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2734 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2736 struct file
*This
= impl_from_IFile(iface
);
2738 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2740 if (format
== TristateUseDefault
) {
2741 FIXME("default format not handled, defaulting to unicode\n");
2742 format
= TristateTrue
;
2745 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2748 static const IFileVtbl file_vtbl
= {
2749 file_QueryInterface
,
2752 file_GetTypeInfoCount
,
2762 file_get_ParentFolder
,
2763 file_get_Attributes
,
2764 file_put_Attributes
,
2765 file_get_DateCreated
,
2766 file_get_DateLastModified
,
2767 file_get_DateLastAccessed
,
2773 file_OpenAsTextStream
2776 static HRESULT
create_file(BSTR path
, IFile
**file
)
2783 f
= heap_alloc(sizeof(struct file
));
2785 return E_OUTOFMEMORY
;
2787 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2790 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2796 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2799 return E_OUTOFMEMORY
;
2802 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2808 attrs
= GetFileAttributesW(f
->path
);
2809 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2810 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2813 return create_error(GetLastError());
2816 *file
= &f
->IFile_iface
;
2820 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2822 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2824 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2825 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2826 IsEqualGUID( riid
, &IID_IDispatch
) ||
2827 IsEqualGUID( riid
, &IID_IUnknown
) )
2831 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2833 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2835 return E_NOINTERFACE
;
2837 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2839 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2841 return E_NOINTERFACE
;
2845 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2846 return E_NOINTERFACE
;
2849 IFileSystem3_AddRef(iface
);
2854 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2856 TRACE("%p\n", iface
);
2861 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2863 TRACE("%p\n", iface
);
2868 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2870 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2876 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2877 LCID lcid
, ITypeInfo
**ppTInfo
)
2879 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2880 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2883 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2884 LPOLESTR
*rgszNames
, UINT cNames
,
2885 LCID lcid
, DISPID
*rgDispId
)
2887 ITypeInfo
*typeinfo
;
2890 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2892 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2895 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2896 ITypeInfo_Release(typeinfo
);
2902 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2903 REFIID riid
, LCID lcid
, WORD wFlags
,
2904 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2905 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2907 ITypeInfo
*typeinfo
;
2910 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2911 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2913 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2916 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2917 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2918 ITypeInfo_Release(typeinfo
);
2924 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2926 TRACE("%p %p\n", iface
, ppdrives
);
2927 return create_drivecoll(ppdrives
);
2930 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2931 BSTR Name
, BSTR
*Result
)
2935 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2937 if (!Result
) return E_POINTER
;
2941 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
2943 /* if both parts have backslashes strip one from Path */
2944 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
2948 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2956 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
2958 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
2962 if (Path
[path_len
-1] != ':')
2969 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2977 else if (Path
|| Name
)
2978 ret
= SysAllocString(Path
? Path
: Name
);
2980 ret
= SysAllocStringLen(NULL
, 0);
2982 if (!ret
) return E_OUTOFMEMORY
;
2988 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
2990 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
2997 if (path
&& strlenW(path
) > 1 && path
[1] == ':')
2998 *drive
= SysAllocStringLen(path
, 2);
3003 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
3010 for(i
=len
-1; i
>=0; i
--)
3011 if(path
[i
]!='/' && path
[i
]!='\\')
3015 if(path
[i
]=='/' || path
[i
]=='\\')
3019 if(path
[i
]!='/' && path
[i
]!='\\')
3025 if(path
[i
]==':' && i
==1)
3030 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3035 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3040 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3042 *pbstrResult
= NULL
;
3046 *pbstrResult
= SysAllocStringLen(Path
, len
);
3048 return E_OUTOFMEMORY
;
3052 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3057 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3063 *pbstrResult
= NULL
;
3067 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3068 if(Path
[end
]!='/' && Path
[end
]!='\\')
3071 for(i
=end
; i
>=0; i
--)
3072 if(Path
[i
]=='/' || Path
[i
]=='\\')
3076 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3077 *pbstrResult
= NULL
;
3081 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3083 return E_OUTOFMEMORY
;
3087 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3092 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3098 *pbstrResult
= NULL
;
3102 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3103 if(Path
[end
]!='/' && Path
[end
]!='\\')
3106 for(i
=end
; i
>=0; i
--) {
3107 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3109 if(Path
[i
]=='/' || Path
[i
]=='\\')
3114 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3115 *pbstrResult
= NULL
;
3119 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3121 return E_OUTOFMEMORY
;
3125 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3130 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3133 len
= SysStringLen(path
);
3135 if (path
[len
-1] == '.') {
3136 *ext
= SysAllocString(&path
[len
]);
3138 return E_OUTOFMEMORY
;
3147 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3150 static const WCHAR cur_path
[] = {'.',0};
3152 WCHAR buf
[MAX_PATH
], ch
;
3154 DWORD i
, beg
, len
, exp_len
;
3155 WIN32_FIND_DATAW fdata
;
3158 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3168 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3172 buf
[0] = toupperW(buf
[0]);
3173 if(len
>3 && buf
[len
-1] == '\\')
3176 for(beg
=3, i
=3; i
<=len
; i
++) {
3177 if(buf
[i
]!='\\' && buf
[i
])
3182 fh
= FindFirstFileW(buf
, &fdata
);
3183 if(fh
== INVALID_HANDLE_VALUE
)
3186 exp_len
= strlenW(fdata
.cFileName
);
3187 if(exp_len
== i
-beg
)
3188 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3194 *pbstrResult
= SysAllocString(buf
);
3196 return E_OUTOFMEMORY
;
3200 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3202 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3206 TRACE("%p %p\n", iface
, pbstrResult
);
3211 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3213 return E_OUTOFMEMORY
;
3215 if(!RtlGenRandom(&random
, sizeof(random
)))
3217 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3221 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3222 VARIANT_BOOL
*pfExists
)
3226 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3228 if (!pfExists
) return E_POINTER
;
3230 *pfExists
= VARIANT_FALSE
;
3231 len
= SysStringLen(DriveSpec
);
3234 driveletter
= toupperW(DriveSpec
[0]);
3235 if (driveletter
>= 'A' && driveletter
<= 'Z'
3236 && (len
< 2 || DriveSpec
[1] == ':')
3237 && (len
< 3 || DriveSpec
[2] == '\\')) {
3238 const WCHAR root
[] = {driveletter
, ':', '\\', 0};
3239 UINT drivetype
= GetDriveTypeW(root
);
3240 *pfExists
= drivetype
!= DRIVE_NO_ROOT_DIR
&& drivetype
!= DRIVE_UNKNOWN
? VARIANT_TRUE
: VARIANT_FALSE
;
3247 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3250 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3252 if (!ret
) return E_POINTER
;
3254 attrs
= GetFileAttributesW(path
);
3255 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3259 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3262 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3264 if (!ret
) return E_POINTER
;
3266 attrs
= GetFileAttributesW(path
);
3267 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3272 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3278 VARIANT_BOOL drive_exists
;
3280 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3287 /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3288 len
= SysStringLen(DriveSpec
);
3290 return E_INVALIDARG
;
3291 else if (len
<= 3) {
3292 driveletter
= toupperW(DriveSpec
[0]);
3293 if (driveletter
< 'A' || driveletter
> 'Z'
3294 || (len
>= 2 && DriveSpec
[1] != ':')
3295 || (len
== 3 && DriveSpec
[2] != '\\'))
3296 return E_INVALIDARG
;
3297 hr
= IFileSystem3_DriveExists(iface
, DriveSpec
, &drive_exists
);
3300 if (drive_exists
== VARIANT_FALSE
)
3301 return CTL_E_DEVICEUNAVAILABLE
;
3302 return create_drive(driveletter
, ppdrive
);
3304 if (DriveSpec
[0] != '\\' || DriveSpec
[1] != '\\')
3305 return E_INVALIDARG
;
3306 FIXME("%s not implemented yet\n", debugstr_w(DriveSpec
));
3311 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3314 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3319 return E_INVALIDARG
;
3321 return create_file(FilePath
, ppfile
);
3324 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3329 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3336 return E_INVALIDARG
;
3338 attrs
= GetFileAttributesW(FolderPath
);
3339 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3340 return CTL_E_PATHNOTFOUND
;
3342 return create_folder(FolderPath
, folder
);
3345 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3346 SpecialFolderConst SpecialFolder
,
3349 WCHAR pathW
[MAX_PATH
];
3352 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3359 switch (SpecialFolder
)
3362 ret
= GetWindowsDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3365 ret
= GetSystemDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3367 case TemporaryFolder
:
3368 ret
= GetTempPathW(sizeof(pathW
)/sizeof(WCHAR
), pathW
);
3369 /* we don't want trailing backslash */
3370 if (ret
&& pathW
[ret
-1] == '\\')
3374 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3375 return E_INVALIDARG
;
3379 return HRESULT_FROM_WIN32(GetLastError());
3381 return create_folder(pathW
, folder
);
3384 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3386 WCHAR path
[MAX_PATH
];
3387 DWORD len
, name_len
;
3388 WIN32_FIND_DATAW ffd
;
3391 f
= FindFirstFileW(file
, &ffd
);
3392 if(f
== INVALID_HANDLE_VALUE
)
3393 return create_error(GetLastError());
3395 len
= get_parent_folder_name(file
, file_len
);
3396 if(len
+1 >= MAX_PATH
) {
3401 memcpy(path
, file
, len
*sizeof(WCHAR
));
3406 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3409 name_len
= strlenW(ffd
.cFileName
);
3410 if(len
+name_len
+1 >= MAX_PATH
) {
3414 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3416 TRACE("deleting %s\n", debugstr_w(path
));
3418 if(!DeleteFileW(path
)) {
3419 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3420 || !DeleteFileW(path
)) {
3422 return create_error(GetLastError());
3425 } while(FindNextFileW(f
, &ffd
));
3431 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3434 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3439 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3442 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3444 WCHAR path
[MAX_PATH
];
3445 DWORD len
, name_len
;
3446 WIN32_FIND_DATAW ffd
;
3450 f
= FindFirstFileW(folder
, &ffd
);
3451 if(f
== INVALID_HANDLE_VALUE
)
3452 return create_error(GetLastError());
3454 len
= get_parent_folder_name(folder
, folder_len
);
3455 if(len
+1 >= MAX_PATH
) {
3460 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3465 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3467 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3468 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3471 name_len
= strlenW(ffd
.cFileName
);
3472 if(len
+name_len
+3 >= MAX_PATH
) {
3476 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3477 path
[len
+name_len
] = '\\';
3478 path
[len
+name_len
+1] = '*';
3479 path
[len
+name_len
+2] = 0;
3481 hr
= delete_file(path
, len
+name_len
+2, force
);
3487 hr
= delete_folder(path
, len
+name_len
+2, force
);
3493 path
[len
+name_len
] = 0;
3494 TRACE("deleting %s\n", debugstr_w(path
));
3496 if(!RemoveDirectoryW(path
)) {
3498 return create_error(GetLastError());
3500 } while(FindNextFileW(f
, &ffd
));
3506 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3509 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3514 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3517 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3520 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3525 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3528 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3533 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3534 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3537 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3538 DWORD src_len
, dst_len
, name_len
;
3539 WIN32_FIND_DATAW ffd
;
3543 if(!source
[0] || !destination
[0])
3544 return E_INVALIDARG
;
3546 attrs
= GetFileAttributesW(destination
);
3547 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3548 attrs
= GetFileAttributesW(source
);
3549 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3550 return create_error(GetLastError());
3551 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3552 return CTL_E_FILENOTFOUND
;
3554 if(!CopyFileW(source
, destination
, !overwrite
))
3555 return create_error(GetLastError());
3559 f
= FindFirstFileW(source
, &ffd
);
3560 if(f
== INVALID_HANDLE_VALUE
)
3561 return CTL_E_FILENOTFOUND
;
3563 src_len
= get_parent_folder_name(source
, source_len
);
3564 if(src_len
+1 >= MAX_PATH
) {
3569 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3570 src_path
[src_len
++] = '\\';
3573 dst_len
= destination_len
;
3574 if(dst_len
+1 >= MAX_PATH
) {
3578 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3579 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3580 dst_path
[dst_len
++] = '\\';
3582 hr
= CTL_E_FILENOTFOUND
;
3584 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3587 name_len
= strlenW(ffd
.cFileName
);
3588 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3592 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3593 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3595 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3597 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3599 return create_error(GetLastError());
3603 } while(FindNextFileW(f
, &ffd
));
3609 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3610 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3612 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3614 if(!Source
|| !Destination
)
3617 return copy_file(Source
, SysStringLen(Source
), Destination
,
3618 SysStringLen(Destination
), OverWriteFiles
);
3621 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3622 DWORD destination_len
, VARIANT_BOOL overwrite
)
3624 DWORD tmp
, src_len
, dst_len
, name_len
;
3625 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3626 WIN32_FIND_DATAW ffd
;
3629 BOOL copied
= FALSE
;
3631 if(!source
[0] || !destination
[0])
3632 return E_INVALIDARG
;
3634 dst_len
= destination_len
;
3635 if(dst_len
+1 >= MAX_PATH
)
3637 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3639 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3640 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3641 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3642 if(!CreateDirectoryW(dst
, NULL
)) {
3643 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3644 tmp
= GetFileAttributesW(dst
);
3645 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3646 return CTL_E_FILEALREADYEXISTS
;
3648 return create_error(GetLastError());
3653 src_len
= source_len
;
3654 if(src_len
+2 >= MAX_PATH
)
3656 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3657 src
[src_len
++] = '\\';
3661 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3662 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3663 return create_error(GetLastError());
3665 f
= FindFirstFileW(src
, &ffd
);
3667 src_len
= get_parent_folder_name(source
, source_len
);
3668 if(src_len
+2 >= MAX_PATH
)
3670 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3672 src
[src_len
++] = '\\';
3674 f
= FindFirstFileW(source
, &ffd
);
3676 if(f
== INVALID_HANDLE_VALUE
)
3677 return CTL_E_PATHNOTFOUND
;
3679 dst
[dst_len
++] = '\\';
3683 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3685 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3686 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3689 name_len
= strlenW(ffd
.cFileName
);
3690 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3694 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3695 dst
[dst_len
+name_len
] = 0;
3696 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3697 src
[src_len
+name_len
] = '\\';
3698 src
[src_len
+name_len
+1] = '*';
3699 src
[src_len
+name_len
+2] = 0;
3701 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3703 if(!CreateDirectoryW(dst
, NULL
)) {
3704 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3705 tmp
= GetFileAttributesW(dst
);
3706 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3708 return CTL_E_FILEALREADYEXISTS
;
3713 return create_error(GetLastError());
3717 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3718 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3723 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3724 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3728 } while(FindNextFileW(f
, &ffd
));
3731 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3734 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3735 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3737 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3739 if(!Source
|| !Destination
)
3742 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3743 SysStringLen(Destination
), OverWriteFiles
);
3746 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3751 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3753 ret
= CreateDirectoryW(path
, NULL
);
3757 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3758 return HRESULT_FROM_WIN32(GetLastError());
3761 return create_folder(path
, folder
);
3764 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3765 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3766 ITextStream
**stream
)
3770 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3772 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3773 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3776 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3777 IOMode mode
, VARIANT_BOOL create
,
3778 Tristate format
, ITextStream
**stream
)
3782 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3783 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3785 if (format
== TristateUseDefault
) {
3786 FIXME("default format not handled, defaulting to unicode\n");
3787 format
= TristateTrue
;
3790 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3793 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3794 StandardStreamTypes StandardStreamType
,
3795 VARIANT_BOOL Unicode
,
3798 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3803 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3805 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3809 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3810 a
= (WORD
)( version
>> 48);
3811 b
= (WORD
)((version
>> 32) & 0xffff);
3812 c
= (WORD
)((version
>> 16) & 0xffff);
3813 d
= (WORD
)( version
& 0xffff);
3815 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3818 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3820 static const WCHAR rootW
[] = {'\\',0};
3821 VS_FIXEDFILEINFO
*info
;
3827 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3829 len
= GetFileVersionInfoSizeW(name
, NULL
);
3831 return HRESULT_FROM_WIN32(GetLastError());
3833 ptr
= heap_alloc(len
);
3834 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3837 return HRESULT_FROM_WIN32(GetLastError());
3840 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3844 return HRESULT_FROM_WIN32(GetLastError());
3847 get_versionstring(info
, ver
);
3850 *version
= SysAllocString(ver
);
3851 TRACE("version=%s\n", debugstr_w(ver
));
3856 static const struct IFileSystem3Vtbl filesys_vtbl
=
3858 filesys_QueryInterface
,
3861 filesys_GetTypeInfoCount
,
3862 filesys_GetTypeInfo
,
3863 filesys_GetIDsOfNames
,
3867 filesys_GetDriveName
,
3868 filesys_GetParentFolderName
,
3869 filesys_GetFileName
,
3870 filesys_GetBaseName
,
3871 filesys_GetExtensionName
,
3872 filesys_GetAbsolutePathName
,
3873 filesys_GetTempName
,
3874 filesys_DriveExists
,
3876 filesys_FolderExists
,
3880 filesys_GetSpecialFolder
,
3882 filesys_DeleteFolder
,
3887 filesys_CreateFolder
,
3888 filesys_CreateTextFile
,
3889 filesys_OpenTextFile
,
3890 filesys_GetStandardStream
,
3891 filesys_GetFileVersion
3894 static IFileSystem3 filesystem
= { &filesys_vtbl
};
3896 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3898 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3900 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);