2 * Copyright 2012 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "scrrun_private.h"
24 #include <wine/unicode.h>
26 static const WCHAR bsW
[] = {'\\',0};
27 static const WCHAR utf16bom
= 0xfeff;
29 struct foldercollection
{
30 IFolderCollection IFolderCollection_iface
;
35 struct filecollection
{
36 IFileCollection IFileCollection_iface
;
41 struct drivecollection
{
42 IDriveCollection IDriveCollection_iface
;
53 struct foldercollection
*coll
;
58 struct filecollection
*coll
;
63 struct drivecollection
*coll
;
70 IEnumVARIANT IEnumVARIANT_iface
;
83 IFolder IFolder_iface
;
96 ITextStream ITextStream_iface
;
111 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
113 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
116 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
118 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
121 static inline struct file
*impl_from_IFile(IFile
*iface
)
123 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
126 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
128 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
131 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
133 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
136 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
138 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
141 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
143 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
146 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
148 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
151 static inline HRESULT
create_error(DWORD err
)
154 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
155 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
156 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
157 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
158 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
160 FIXME("Unsupported error code: %d\n", err
);
165 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
166 static HRESULT
create_file(BSTR
, IFile
**);
167 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
168 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
170 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
172 static const WCHAR dotdotW
[] = {'.','.',0};
173 static const WCHAR dotW
[] = {'.',0};
175 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
176 strcmpW(data
->cFileName
, dotdotW
) &&
177 strcmpW(data
->cFileName
, dotW
);
180 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
182 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
185 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
187 int len
= SysStringLen(path
);
188 WCHAR buffW
[MAX_PATH
];
190 strcpyW(buffW
, path
);
191 if (path
[len
-1] != '\\')
193 strcatW(buffW
, data
->cFileName
);
195 return SysAllocString(buffW
);
198 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
201 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
203 return This
->mode
== ForReading
;
206 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
208 struct textstream
*This
= impl_from_ITextStream(iface
);
210 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
212 if (IsEqualIID(riid
, &IID_ITextStream
) ||
213 IsEqualIID(riid
, &IID_IDispatch
) ||
214 IsEqualIID(riid
, &IID_IUnknown
))
217 ITextStream_AddRef(iface
);
222 return E_NOINTERFACE
;
225 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
227 struct textstream
*This
= impl_from_ITextStream(iface
);
228 ULONG ref
= InterlockedIncrement(&This
->ref
);
229 TRACE("(%p)->(%d)\n", This
, ref
);
233 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
235 struct textstream
*This
= impl_from_ITextStream(iface
);
236 ULONG ref
= InterlockedDecrement(&This
->ref
);
237 TRACE("(%p)->(%d)\n", This
, ref
);
241 CloseHandle(This
->file
);
248 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
250 struct textstream
*This
= impl_from_ITextStream(iface
);
251 TRACE("(%p)->(%p)\n", This
, pctinfo
);
256 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
257 LCID lcid
, ITypeInfo
**ppTInfo
)
259 struct textstream
*This
= impl_from_ITextStream(iface
);
260 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
261 return get_typeinfo(ITextStream_tid
, ppTInfo
);
264 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
265 LPOLESTR
*rgszNames
, UINT cNames
,
266 LCID lcid
, DISPID
*rgDispId
)
268 struct textstream
*This
= impl_from_ITextStream(iface
);
272 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
274 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
277 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
278 ITypeInfo_Release(typeinfo
);
284 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
285 REFIID riid
, LCID lcid
, WORD wFlags
,
286 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
287 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
289 struct textstream
*This
= impl_from_ITextStream(iface
);
293 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
294 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
296 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
299 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
300 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
301 ITypeInfo_Release(typeinfo
);
307 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
309 struct textstream
*This
= impl_from_ITextStream(iface
);
310 FIXME("(%p)->(%p): stub\n", This
, line
);
314 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
316 struct textstream
*This
= impl_from_ITextStream(iface
);
317 FIXME("(%p)->(%p): stub\n", This
, column
);
321 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
323 struct textstream
*This
= impl_from_ITextStream(iface
);
324 LARGE_INTEGER pos
, dist
;
326 TRACE("(%p)->(%p)\n", This
, eos
);
331 if (textstream_check_iomode(This
, IORead
)) {
333 return CTL_E_BADFILEMODE
;
337 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
340 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? VARIANT_TRUE
: VARIANT_FALSE
;
344 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
346 struct textstream
*This
= impl_from_ITextStream(iface
);
347 FIXME("(%p)->(%p): stub\n", This
, eol
);
352 Reads 'toread' bytes from a file, converts if needed
353 BOM is skipped if 'bof' is set.
355 static HRESULT
textstream_read(struct textstream
*stream
, LONG toread
, BOOL bof
, BSTR
*text
)
363 *text
= SysAllocStringLen(NULL
, 0);
364 return *text
? S_FALSE
: E_OUTOFMEMORY
;
367 if (toread
< sizeof(WCHAR
))
368 return CTL_E_ENDOFFILE
;
370 buff
= heap_alloc(toread
);
372 return E_OUTOFMEMORY
;
374 ret
= ReadFile(stream
->file
, buff
, toread
, &read
, NULL
);
375 if (!ret
|| toread
!= read
) {
376 WARN("failed to read from file %d, %d, error %d\n", read
, toread
, GetLastError());
381 if (stream
->unicode
) {
385 if (bof
&& *(WCHAR
*)buff
== utf16bom
) {
386 read
-= sizeof(WCHAR
);
390 *text
= SysAllocStringLen(read
? (WCHAR
*)&buff
[i
] : NULL
, read
/sizeof(WCHAR
));
391 if (!*text
) hr
= E_OUTOFMEMORY
;
394 INT len
= MultiByteToWideChar(CP_ACP
, 0, buff
, read
, NULL
, 0);
395 *text
= SysAllocStringLen(NULL
, len
);
397 MultiByteToWideChar(CP_ACP
, 0, buff
, read
, *text
, len
);
406 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
408 struct textstream
*This
= impl_from_ITextStream(iface
);
409 LARGE_INTEGER start
, end
, dist
;
413 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
420 return len
== 0 ? S_OK
: E_INVALIDARG
;
422 if (textstream_check_iomode(This
, IORead
))
423 return CTL_E_BADFILEMODE
;
425 if (!This
->first_read
) {
429 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
433 if (eos
== VARIANT_TRUE
)
434 return CTL_E_ENDOFFILE
;
437 /* read everything from current position */
439 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
440 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
441 toread
= end
.QuadPart
- start
.QuadPart
;
443 dist
.QuadPart
= start
.QuadPart
;
444 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
446 This
->first_read
= FALSE
;
447 if (This
->unicode
) len
*= sizeof(WCHAR
);
449 hr
= textstream_read(This
, min(toread
, len
), start
.QuadPart
== 0, text
);
453 return toread
<= len
? S_FALSE
: S_OK
;
456 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
458 struct textstream
*This
= impl_from_ITextStream(iface
);
462 FIXME("(%p)->(%p): stub\n", This
, text
);
468 if (textstream_check_iomode(This
, IORead
))
469 return CTL_E_BADFILEMODE
;
472 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
476 if (eos
== VARIANT_TRUE
)
477 return CTL_E_ENDOFFILE
;
482 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
484 struct textstream
*This
= impl_from_ITextStream(iface
);
485 LARGE_INTEGER start
, end
, dist
;
489 TRACE("(%p)->(%p)\n", This
, text
);
495 if (textstream_check_iomode(This
, IORead
))
496 return CTL_E_BADFILEMODE
;
498 if (!This
->first_read
) {
502 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
506 if (eos
== VARIANT_TRUE
)
507 return CTL_E_ENDOFFILE
;
510 /* read everything from current position */
512 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
513 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
514 toread
= end
.QuadPart
- start
.QuadPart
;
516 dist
.QuadPart
= start
.QuadPart
;
517 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
519 This
->first_read
= FALSE
;
521 hr
= textstream_read(This
, toread
, start
.QuadPart
== 0, text
);
522 return FAILED(hr
) ? hr
: S_FALSE
;
525 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
530 if (stream
->unicode
) {
531 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
532 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
534 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
538 buffA
= heap_alloc(len
);
540 return E_OUTOFMEMORY
;
542 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
543 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
544 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
550 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
552 struct textstream
*This
= impl_from_ITextStream(iface
);
554 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
556 if (textstream_check_iomode(This
, IOWrite
))
557 return CTL_E_BADFILEMODE
;
559 return textstream_writestr(This
, text
);
562 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
564 static const WCHAR crlfW
[] = {'\r','\n'};
565 static const char crlfA
[] = {'\r','\n'};
566 DWORD written
= 0, len
;
570 if (stream
->unicode
) {
579 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
580 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
583 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
585 struct textstream
*This
= impl_from_ITextStream(iface
);
588 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
590 if (textstream_check_iomode(This
, IOWrite
))
591 return CTL_E_BADFILEMODE
;
593 hr
= textstream_writestr(This
, text
);
595 hr
= textstream_writecrlf(This
);
599 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
601 struct textstream
*This
= impl_from_ITextStream(iface
);
602 FIXME("(%p)->(%d): stub\n", This
, lines
);
606 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
608 struct textstream
*This
= impl_from_ITextStream(iface
);
609 FIXME("(%p)->(%d): stub\n", This
, count
);
613 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
615 struct textstream
*This
= impl_from_ITextStream(iface
);
616 FIXME("(%p): stub\n", This
);
620 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
622 struct textstream
*This
= impl_from_ITextStream(iface
);
623 FIXME("(%p): stub\n", This
);
627 static const ITextStreamVtbl textstreamvtbl
= {
628 textstream_QueryInterface
,
631 textstream_GetTypeInfoCount
,
632 textstream_GetTypeInfo
,
633 textstream_GetIDsOfNames
,
636 textstream_get_Column
,
637 textstream_get_AtEndOfStream
,
638 textstream_get_AtEndOfLine
,
643 textstream_WriteLine
,
644 textstream_WriteBlankLines
,
650 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
652 struct textstream
*stream
;
655 /* map access mode */
659 access
= GENERIC_READ
;
662 access
= GENERIC_WRITE
;
665 access
= FILE_APPEND_DATA
;
671 stream
= heap_alloc(sizeof(struct textstream
));
672 if (!stream
) return E_OUTOFMEMORY
;
674 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
677 stream
->unicode
= unicode
;
678 stream
->first_read
= TRUE
;
680 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
681 if (stream
->file
== INVALID_HANDLE_VALUE
)
683 HRESULT hr
= create_error(GetLastError());
688 if (mode
== ForReading
)
689 GetFileSizeEx(stream
->file
, &stream
->size
);
691 stream
->size
.QuadPart
= 0;
693 /* Write Unicode BOM */
694 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
696 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
697 if (!ret
|| written
!= sizeof(utf16bom
)) {
698 ITextStream_Release(&stream
->ITextStream_iface
);
699 return create_error(GetLastError());
703 *ret
= &stream
->ITextStream_iface
;
707 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
709 struct drive
*This
= impl_from_IDrive(iface
);
711 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
715 if (IsEqualIID( riid
, &IID_IDrive
) ||
716 IsEqualIID( riid
, &IID_IDispatch
) ||
717 IsEqualIID( riid
, &IID_IUnknown
))
720 IDrive_AddRef(iface
);
723 return E_NOINTERFACE
;
728 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
730 struct drive
*This
= impl_from_IDrive(iface
);
731 ULONG ref
= InterlockedIncrement(&This
->ref
);
732 TRACE("(%p)->(%d)\n", This
, ref
);
736 static ULONG WINAPI
drive_Release(IDrive
*iface
)
738 struct drive
*This
= impl_from_IDrive(iface
);
739 ULONG ref
= InterlockedDecrement(&This
->ref
);
740 TRACE("(%p)->(%d)\n", This
, ref
);
744 SysFreeString(This
->root
);
751 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
753 struct drive
*This
= impl_from_IDrive(iface
);
754 TRACE("(%p)->(%p)\n", This
, pctinfo
);
759 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
760 LCID lcid
, ITypeInfo
**ppTInfo
)
762 struct drive
*This
= impl_from_IDrive(iface
);
763 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
764 return get_typeinfo(IDrive_tid
, ppTInfo
);
767 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
768 LPOLESTR
*rgszNames
, UINT cNames
,
769 LCID lcid
, DISPID
*rgDispId
)
771 struct drive
*This
= impl_from_IDrive(iface
);
775 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
777 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
780 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
781 ITypeInfo_Release(typeinfo
);
787 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
788 REFIID riid
, LCID lcid
, WORD wFlags
,
789 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
790 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
792 struct drive
*This
= impl_from_IDrive(iface
);
796 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
797 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
799 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
802 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
803 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
804 ITypeInfo_Release(typeinfo
);
810 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
812 struct drive
*This
= impl_from_IDrive(iface
);
813 FIXME("(%p)->(%p): stub\n", This
, path
);
817 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
819 struct drive
*This
= impl_from_IDrive(iface
);
821 TRACE("(%p)->(%p)\n", This
, letter
);
826 *letter
= SysAllocStringLen(This
->root
, 1);
828 return E_OUTOFMEMORY
;
833 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
835 struct drive
*This
= impl_from_IDrive(iface
);
836 FIXME("(%p)->(%p): stub\n", This
, share_name
);
840 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
842 struct drive
*This
= impl_from_IDrive(iface
);
844 TRACE("(%p)->(%p)\n", This
, type
);
846 switch (GetDriveTypeW(This
->root
))
848 case DRIVE_REMOVABLE
:
871 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
873 struct drive
*This
= impl_from_IDrive(iface
);
874 FIXME("(%p)->(%p): stub\n", This
, folder
);
878 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
882 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
885 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
890 V_I4(v
) = src
->u
.LowPart
;
896 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
898 struct drive
*This
= impl_from_IDrive(iface
);
899 ULARGE_INTEGER avail
;
901 TRACE("(%p)->(%p)\n", This
, v
);
906 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
909 return variant_from_largeint(&avail
, v
);
912 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
914 struct drive
*This
= impl_from_IDrive(iface
);
915 ULARGE_INTEGER freespace
;
917 TRACE("(%p)->(%p)\n", This
, v
);
922 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
925 return variant_from_largeint(&freespace
, v
);
928 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
930 struct drive
*This
= impl_from_IDrive(iface
);
931 ULARGE_INTEGER total
;
933 TRACE("(%p)->(%p)\n", This
, v
);
938 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
941 return variant_from_largeint(&total
, v
);
944 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
946 struct drive
*This
= impl_from_IDrive(iface
);
947 WCHAR nameW
[MAX_PATH
+1];
950 TRACE("(%p)->(%p)\n", This
, name
);
956 ret
= GetVolumeInformationW(This
->root
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, NULL
, NULL
, NULL
, 0);
958 *name
= SysAllocString(nameW
);
959 return ret
? S_OK
: E_FAIL
;
962 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
964 struct drive
*This
= impl_from_IDrive(iface
);
965 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
969 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
971 struct drive
*This
= impl_from_IDrive(iface
);
972 WCHAR nameW
[MAX_PATH
+1];
975 TRACE("(%p)->(%p)\n", This
, fs
);
981 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
983 *fs
= SysAllocString(nameW
);
984 return ret
? S_OK
: E_FAIL
;
987 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
989 struct drive
*This
= impl_from_IDrive(iface
);
992 TRACE("(%p)->(%p)\n", This
, serial
);
997 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
998 return ret
? S_OK
: E_FAIL
;
1001 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1003 struct drive
*This
= impl_from_IDrive(iface
);
1004 ULARGE_INTEGER freespace
;
1007 TRACE("(%p)->(%p)\n", This
, ready
);
1012 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1013 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1017 static const IDriveVtbl drivevtbl
= {
1018 drive_QueryInterface
,
1021 drive_GetTypeInfoCount
,
1023 drive_GetIDsOfNames
,
1026 drive_get_DriveLetter
,
1027 drive_get_ShareName
,
1028 drive_get_DriveType
,
1029 drive_get_RootFolder
,
1030 drive_get_AvailableSpace
,
1031 drive_get_FreeSpace
,
1032 drive_get_TotalSize
,
1033 drive_get_VolumeName
,
1034 drive_put_VolumeName
,
1035 drive_get_FileSystem
,
1036 drive_get_SerialNumber
,
1040 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1046 This
= heap_alloc(sizeof(*This
));
1047 if (!This
) return E_OUTOFMEMORY
;
1049 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1051 This
->root
= SysAllocStringLen(NULL
, 3);
1055 return E_OUTOFMEMORY
;
1057 This
->root
[0] = letter
;
1058 This
->root
[1] = ':';
1059 This
->root
[2] = '\\';
1062 *drive
= &This
->IDrive_iface
;
1066 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1068 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1070 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1074 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1075 IsEqualIID( riid
, &IID_IUnknown
))
1078 IEnumVARIANT_AddRef(iface
);
1081 return E_NOINTERFACE
;
1086 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1088 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1089 ULONG ref
= InterlockedIncrement(&This
->ref
);
1090 TRACE("(%p)->(%d)\n", This
, ref
);
1094 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1096 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1097 ULONG ref
= InterlockedDecrement(&This
->ref
);
1099 TRACE("(%p)->(%d)\n", This
, ref
);
1103 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1104 FindClose(This
->data
.u
.foldercoll
.find
);
1111 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1113 static const WCHAR allW
[] = {'*',0};
1114 WCHAR pathW
[MAX_PATH
];
1118 strcpyW(pathW
, path
);
1119 len
= strlenW(pathW
);
1120 if (len
&& pathW
[len
-1] != '\\')
1121 strcatW(pathW
, bsW
);
1122 strcatW(pathW
, allW
);
1123 handle
= FindFirstFileW(pathW
, data
);
1124 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1126 /* find first dir/file */
1129 if (file
? is_file_data(data
) : is_dir_data(data
))
1132 if (!FindNextFileW(handle
, data
))
1141 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1143 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1144 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1145 WIN32_FIND_DATAW data
;
1148 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1153 if (!celt
) return S_OK
;
1157 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1158 if (!handle
) return S_FALSE
;
1160 This
->data
.u
.foldercoll
.find
= handle
;
1164 if (!FindNextFileW(handle
, &data
))
1170 if (is_dir_data(&data
))
1176 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1177 hr
= create_folder(str
, &folder
);
1179 if (FAILED(hr
)) return hr
;
1181 V_VT(&var
[count
]) = VT_DISPATCH
;
1182 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1185 if (count
>= celt
) break;
1187 } while (FindNextFileW(handle
, &data
));
1192 return (count
< celt
) ? S_FALSE
: S_OK
;
1195 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1197 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1198 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1199 WIN32_FIND_DATAW data
;
1201 TRACE("(%p)->(%d)\n", This
, celt
);
1203 if (!celt
) return S_OK
;
1207 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1208 if (!handle
) return S_FALSE
;
1210 This
->data
.u
.foldercoll
.find
= handle
;
1214 if (!FindNextFileW(handle
, &data
))
1220 if (is_dir_data(&data
))
1224 } while (FindNextFileW(handle
, &data
));
1226 return celt
? S_FALSE
: S_OK
;
1229 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1231 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1233 TRACE("(%p)\n", This
);
1235 FindClose(This
->data
.u
.foldercoll
.find
);
1236 This
->data
.u
.foldercoll
.find
= NULL
;
1241 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1243 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1244 TRACE("(%p)->(%p)\n", This
, pclone
);
1245 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1248 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1249 enumvariant_QueryInterface
,
1251 foldercoll_enumvariant_Release
,
1252 foldercoll_enumvariant_Next
,
1253 foldercoll_enumvariant_Skip
,
1254 foldercoll_enumvariant_Reset
,
1255 foldercoll_enumvariant_Clone
1258 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1260 struct enumvariant
*This
;
1264 This
= heap_alloc(sizeof(*This
));
1265 if (!This
) return E_OUTOFMEMORY
;
1267 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1269 This
->data
.u
.foldercoll
.find
= NULL
;
1270 This
->data
.u
.foldercoll
.coll
= collection
;
1271 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1273 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1278 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1280 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1281 ULONG ref
= InterlockedDecrement(&This
->ref
);
1283 TRACE("(%p)->(%d)\n", This
, ref
);
1287 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1288 FindClose(This
->data
.u
.filecoll
.find
);
1295 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1297 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1298 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1299 WIN32_FIND_DATAW data
;
1302 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1307 if (!celt
) return S_OK
;
1311 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1312 if (!handle
) return S_FALSE
;
1313 This
->data
.u
.filecoll
.find
= handle
;
1315 else if (!FindNextFileW(handle
, &data
))
1320 if (is_file_data(&data
))
1326 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1327 hr
= create_file(str
, &file
);
1329 if (FAILED(hr
)) return hr
;
1331 V_VT(&var
[count
]) = VT_DISPATCH
;
1332 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1333 if (++count
>= celt
) break;
1335 } while (FindNextFileW(handle
, &data
));
1340 return (count
< celt
) ? S_FALSE
: S_OK
;
1343 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1345 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1346 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1347 WIN32_FIND_DATAW data
;
1349 TRACE("(%p)->(%d)\n", This
, celt
);
1351 if (!celt
) return S_OK
;
1355 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1356 if (!handle
) return S_FALSE
;
1357 This
->data
.u
.filecoll
.find
= handle
;
1359 else if (!FindNextFileW(handle
, &data
))
1364 if (is_file_data(&data
))
1366 } while (celt
&& FindNextFileW(handle
, &data
));
1368 return celt
? S_FALSE
: S_OK
;
1371 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1373 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1375 TRACE("(%p)\n", This
);
1377 FindClose(This
->data
.u
.filecoll
.find
);
1378 This
->data
.u
.filecoll
.find
= NULL
;
1383 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1385 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1386 TRACE("(%p)->(%p)\n", This
, pclone
);
1387 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1390 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1391 enumvariant_QueryInterface
,
1393 filecoll_enumvariant_Release
,
1394 filecoll_enumvariant_Next
,
1395 filecoll_enumvariant_Skip
,
1396 filecoll_enumvariant_Reset
,
1397 filecoll_enumvariant_Clone
1400 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1402 struct enumvariant
*This
;
1406 This
= heap_alloc(sizeof(*This
));
1407 if (!This
) return E_OUTOFMEMORY
;
1409 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1411 This
->data
.u
.filecoll
.find
= NULL
;
1412 This
->data
.u
.filecoll
.coll
= collection
;
1413 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1415 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1420 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1422 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1423 ULONG ref
= InterlockedDecrement(&This
->ref
);
1425 TRACE("(%p)->(%d)\n", This
, ref
);
1429 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1436 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1438 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1441 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1443 penum
->data
.u
.drivecoll
.cur
= i
;
1450 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1452 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1455 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1460 if (!celt
) return S_OK
;
1462 while (find_next_drive(This
) == S_OK
)
1467 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1468 if (FAILED(hr
)) return hr
;
1470 V_VT(&var
[count
]) = VT_DISPATCH
;
1471 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1473 if (++count
>= celt
) break;
1479 return (count
< celt
) ? S_FALSE
: S_OK
;
1482 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1484 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1486 TRACE("(%p)->(%d)\n", This
, celt
);
1488 if (!celt
) return S_OK
;
1490 while (celt
&& find_next_drive(This
) == S_OK
)
1493 return celt
? S_FALSE
: S_OK
;
1496 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1498 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1500 TRACE("(%p)\n", This
);
1502 This
->data
.u
.drivecoll
.cur
= -1;
1506 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1508 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1509 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1513 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1514 enumvariant_QueryInterface
,
1516 drivecoll_enumvariant_Release
,
1517 drivecoll_enumvariant_Next
,
1518 drivecoll_enumvariant_Skip
,
1519 drivecoll_enumvariant_Reset
,
1520 drivecoll_enumvariant_Clone
1523 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1525 struct enumvariant
*This
;
1529 This
= heap_alloc(sizeof(*This
));
1530 if (!This
) return E_OUTOFMEMORY
;
1532 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1534 This
->data
.u
.drivecoll
.coll
= collection
;
1535 This
->data
.u
.drivecoll
.cur
= -1;
1536 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1538 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1543 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1545 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1547 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1551 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1552 IsEqualIID( riid
, &IID_IDispatch
) ||
1553 IsEqualIID( riid
, &IID_IUnknown
))
1556 IFolderCollection_AddRef(iface
);
1559 return E_NOINTERFACE
;
1564 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1566 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1567 ULONG ref
= InterlockedIncrement(&This
->ref
);
1568 TRACE("(%p)->(%d)\n", This
, ref
);
1572 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1574 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1575 ULONG ref
= InterlockedDecrement(&This
->ref
);
1576 TRACE("(%p)->(%d)\n", This
, ref
);
1580 SysFreeString(This
->path
);
1587 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1589 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1590 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1595 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1596 LCID lcid
, ITypeInfo
**ppTInfo
)
1598 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1599 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1600 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1603 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1604 LPOLESTR
*rgszNames
, UINT cNames
,
1605 LCID lcid
, DISPID
*rgDispId
)
1607 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1608 ITypeInfo
*typeinfo
;
1611 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1613 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1616 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1617 ITypeInfo_Release(typeinfo
);
1623 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1624 REFIID riid
, LCID lcid
, WORD wFlags
,
1625 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1626 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1628 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1629 ITypeInfo
*typeinfo
;
1632 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1633 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1635 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1638 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1639 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1640 ITypeInfo_Release(typeinfo
);
1646 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1648 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1649 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1653 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1655 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1656 FIXME("(%p)->(%p): stub\n", This
, folder
);
1660 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1662 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1664 TRACE("(%p)->(%p)\n", This
, newenum
);
1669 return create_foldercoll_enum(This
, newenum
);
1672 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1674 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1675 static const WCHAR allW
[] = {'\\','*',0};
1676 WIN32_FIND_DATAW data
;
1677 WCHAR pathW
[MAX_PATH
];
1680 TRACE("(%p)->(%p)\n", This
, count
);
1687 strcpyW(pathW
, This
->path
);
1688 strcatW(pathW
, allW
);
1689 handle
= FindFirstFileW(pathW
, &data
);
1690 if (handle
== INVALID_HANDLE_VALUE
)
1691 return HRESULT_FROM_WIN32(GetLastError());
1695 if (is_dir_data(&data
))
1697 } while (FindNextFileW(handle
, &data
));
1703 static const IFolderCollectionVtbl foldercollvtbl
= {
1704 foldercoll_QueryInterface
,
1707 foldercoll_GetTypeInfoCount
,
1708 foldercoll_GetTypeInfo
,
1709 foldercoll_GetIDsOfNames
,
1712 foldercoll_get_Item
,
1713 foldercoll_get__NewEnum
,
1714 foldercoll_get_Count
1717 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1719 struct foldercollection
*This
;
1723 This
= heap_alloc(sizeof(struct foldercollection
));
1724 if (!This
) return E_OUTOFMEMORY
;
1726 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1728 This
->path
= SysAllocString(path
);
1732 return E_OUTOFMEMORY
;
1735 *folders
= &This
->IFolderCollection_iface
;
1740 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1742 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1744 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1748 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1749 IsEqualIID( riid
, &IID_IDispatch
) ||
1750 IsEqualIID( riid
, &IID_IUnknown
))
1753 IFileCollection_AddRef(iface
);
1756 return E_NOINTERFACE
;
1761 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1763 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1764 ULONG ref
= InterlockedIncrement(&This
->ref
);
1765 TRACE("(%p)->(%d)\n", This
, ref
);
1769 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1771 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1772 ULONG ref
= InterlockedDecrement(&This
->ref
);
1773 TRACE("(%p)->(%d)\n", This
, ref
);
1777 SysFreeString(This
->path
);
1784 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1786 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1787 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1792 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1793 LCID lcid
, ITypeInfo
**ppTInfo
)
1795 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1796 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1797 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1800 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1801 LPOLESTR
*rgszNames
, UINT cNames
,
1802 LCID lcid
, DISPID
*rgDispId
)
1804 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1805 ITypeInfo
*typeinfo
;
1808 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1810 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1813 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1814 ITypeInfo_Release(typeinfo
);
1820 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1821 REFIID riid
, LCID lcid
, WORD wFlags
,
1822 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1823 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1825 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1826 ITypeInfo
*typeinfo
;
1829 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1830 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1832 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1835 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1836 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1837 ITypeInfo_Release(typeinfo
);
1843 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1845 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1846 FIXME("(%p)->(%p)\n", This
, file
);
1850 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1852 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1854 TRACE("(%p)->(%p)\n", This
, ppenum
);
1859 return create_filecoll_enum(This
, ppenum
);
1862 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1864 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1865 static const WCHAR allW
[] = {'\\','*',0};
1866 WIN32_FIND_DATAW data
;
1867 WCHAR pathW
[MAX_PATH
];
1870 TRACE("(%p)->(%p)\n", This
, count
);
1877 strcpyW(pathW
, This
->path
);
1878 strcatW(pathW
, allW
);
1879 handle
= FindFirstFileW(pathW
, &data
);
1880 if (handle
== INVALID_HANDLE_VALUE
)
1881 return HRESULT_FROM_WIN32(GetLastError());
1885 if (is_file_data(&data
))
1887 } while (FindNextFileW(handle
, &data
));
1893 static const IFileCollectionVtbl filecollectionvtbl
= {
1894 filecoll_QueryInterface
,
1897 filecoll_GetTypeInfoCount
,
1898 filecoll_GetTypeInfo
,
1899 filecoll_GetIDsOfNames
,
1902 filecoll_get__NewEnum
,
1906 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1908 struct filecollection
*This
;
1912 This
= heap_alloc(sizeof(*This
));
1913 if (!This
) return E_OUTOFMEMORY
;
1915 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1917 This
->path
= SysAllocString(path
);
1921 return E_OUTOFMEMORY
;
1924 *files
= &This
->IFileCollection_iface
;
1928 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1930 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1932 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1936 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1937 IsEqualIID( riid
, &IID_IDispatch
) ||
1938 IsEqualIID( riid
, &IID_IUnknown
))
1941 IDriveCollection_AddRef(iface
);
1944 return E_NOINTERFACE
;
1949 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
1951 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1952 ULONG ref
= InterlockedIncrement(&This
->ref
);
1953 TRACE("(%p)->(%d)\n", This
, ref
);
1957 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
1959 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1960 ULONG ref
= InterlockedDecrement(&This
->ref
);
1961 TRACE("(%p)->(%d)\n", This
, ref
);
1969 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
1971 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1972 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1977 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
1978 LCID lcid
, ITypeInfo
**ppTInfo
)
1980 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1981 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1982 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
1985 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
1986 LPOLESTR
*rgszNames
, UINT cNames
,
1987 LCID lcid
, DISPID
*rgDispId
)
1989 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1990 ITypeInfo
*typeinfo
;
1993 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1995 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
1998 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1999 ITypeInfo_Release(typeinfo
);
2005 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2006 REFIID riid
, LCID lcid
, WORD wFlags
,
2007 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2008 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2010 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2011 ITypeInfo
*typeinfo
;
2014 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2015 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2017 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2020 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2021 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2022 ITypeInfo_Release(typeinfo
);
2028 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2030 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2031 FIXME("(%p)->(%p): stub\n", This
, drive
);
2035 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2037 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2039 TRACE("(%p)->(%p)\n", This
, ppenum
);
2044 return create_drivecoll_enum(This
, ppenum
);
2047 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2049 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2051 TRACE("(%p)->(%p)\n", This
, count
);
2053 if (!count
) return E_POINTER
;
2055 *count
= This
->count
;
2059 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2060 drivecoll_QueryInterface
,
2063 drivecoll_GetTypeInfoCount
,
2064 drivecoll_GetTypeInfo
,
2065 drivecoll_GetIDsOfNames
,
2068 drivecoll_get__NewEnum
,
2072 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2074 struct drivecollection
*This
;
2079 This
= heap_alloc(sizeof(*This
));
2080 if (!This
) return E_OUTOFMEMORY
;
2082 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2084 This
->drives
= mask
= GetLogicalDrives();
2085 /* count set bits */
2086 for (This
->count
= 0; mask
; This
->count
++)
2089 *drives
= &This
->IDriveCollection_iface
;
2093 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2095 struct folder
*This
= impl_from_IFolder(iface
);
2097 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2101 if (IsEqualIID( riid
, &IID_IFolder
) ||
2102 IsEqualIID( riid
, &IID_IDispatch
) ||
2103 IsEqualIID( riid
, &IID_IUnknown
))
2106 IFolder_AddRef(iface
);
2109 return E_NOINTERFACE
;
2114 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2116 struct folder
*This
= impl_from_IFolder(iface
);
2117 ULONG ref
= InterlockedIncrement(&This
->ref
);
2118 TRACE("(%p)->(%d)\n", This
, ref
);
2122 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2124 struct folder
*This
= impl_from_IFolder(iface
);
2125 ULONG ref
= InterlockedDecrement(&This
->ref
);
2126 TRACE("(%p)->(%d)\n", This
, ref
);
2130 SysFreeString(This
->path
);
2137 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2139 struct folder
*This
= impl_from_IFolder(iface
);
2140 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2145 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2146 LCID lcid
, ITypeInfo
**ppTInfo
)
2148 struct folder
*This
= impl_from_IFolder(iface
);
2149 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2150 return get_typeinfo(IFolder_tid
, ppTInfo
);
2153 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2154 LPOLESTR
*rgszNames
, UINT cNames
,
2155 LCID lcid
, DISPID
*rgDispId
)
2157 struct folder
*This
= impl_from_IFolder(iface
);
2158 ITypeInfo
*typeinfo
;
2161 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2163 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2166 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2167 ITypeInfo_Release(typeinfo
);
2173 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2174 REFIID riid
, LCID lcid
, WORD wFlags
,
2175 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2176 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2178 struct folder
*This
= impl_from_IFolder(iface
);
2179 ITypeInfo
*typeinfo
;
2182 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2183 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2185 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2188 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2189 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2190 ITypeInfo_Release(typeinfo
);
2196 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2198 struct folder
*This
= impl_from_IFolder(iface
);
2200 TRACE("(%p)->(%p)\n", This
, path
);
2205 *path
= SysAllocString(This
->path
);
2206 return *path
? S_OK
: E_OUTOFMEMORY
;
2209 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2211 struct folder
*This
= impl_from_IFolder(iface
);
2214 TRACE("(%p)->(%p)\n", This
, name
);
2221 ptr
= strrchrW(This
->path
, '\\');
2224 *name
= SysAllocString(ptr
+1);
2225 TRACE("%s\n", debugstr_w(*name
));
2226 if (!*name
) return E_OUTOFMEMORY
;
2234 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2236 struct folder
*This
= impl_from_IFolder(iface
);
2237 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2241 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2243 struct folder
*This
= impl_from_IFolder(iface
);
2244 FIXME("(%p)->(%p): stub\n", This
, path
);
2248 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2250 struct folder
*This
= impl_from_IFolder(iface
);
2251 FIXME("(%p)->(%p): stub\n", This
, name
);
2255 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2257 struct folder
*This
= impl_from_IFolder(iface
);
2258 FIXME("(%p)->(%p): stub\n", This
, drive
);
2262 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2264 struct folder
*This
= impl_from_IFolder(iface
);
2265 FIXME("(%p)->(%p): stub\n", This
, parent
);
2269 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2271 struct folder
*This
= impl_from_IFolder(iface
);
2272 FIXME("(%p)->(%p): stub\n", This
, attr
);
2276 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2278 struct folder
*This
= impl_from_IFolder(iface
);
2279 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2283 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2285 struct folder
*This
= impl_from_IFolder(iface
);
2286 FIXME("(%p)->(%p): stub\n", This
, date
);
2290 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2292 struct folder
*This
= impl_from_IFolder(iface
);
2293 FIXME("(%p)->(%p): stub\n", This
, date
);
2297 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2299 struct folder
*This
= impl_from_IFolder(iface
);
2300 FIXME("(%p)->(%p): stub\n", This
, date
);
2304 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2306 struct folder
*This
= impl_from_IFolder(iface
);
2307 FIXME("(%p)->(%p): stub\n", This
, type
);
2311 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2313 struct folder
*This
= impl_from_IFolder(iface
);
2314 FIXME("(%p)->(%x): stub\n", This
, force
);
2318 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2320 struct folder
*This
= impl_from_IFolder(iface
);
2321 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2325 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2327 struct folder
*This
= impl_from_IFolder(iface
);
2328 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2332 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2334 struct folder
*This
= impl_from_IFolder(iface
);
2335 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2339 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2341 struct folder
*This
= impl_from_IFolder(iface
);
2342 FIXME("(%p)->(%p): stub\n", This
, size
);
2346 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2348 struct folder
*This
= impl_from_IFolder(iface
);
2350 TRACE("(%p)->(%p)\n", This
, folders
);
2355 return create_foldercoll(This
->path
, folders
);
2358 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2360 struct folder
*This
= impl_from_IFolder(iface
);
2362 TRACE("(%p)->(%p)\n", This
, files
);
2367 return create_filecoll(This
->path
, files
);
2370 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2371 VARIANT_BOOL unicode
, ITextStream
**stream
)
2373 struct folder
*This
= impl_from_IFolder(iface
);
2374 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2378 static const IFolderVtbl foldervtbl
= {
2379 folder_QueryInterface
,
2382 folder_GetTypeInfoCount
,
2384 folder_GetIDsOfNames
,
2389 folder_get_ShortPath
,
2390 folder_get_ShortName
,
2392 folder_get_ParentFolder
,
2393 folder_get_Attributes
,
2394 folder_put_Attributes
,
2395 folder_get_DateCreated
,
2396 folder_get_DateLastModified
,
2397 folder_get_DateLastAccessed
,
2402 folder_get_IsRootFolder
,
2404 folder_get_SubFolders
,
2406 folder_CreateTextFile
2409 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2411 struct folder
*This
;
2415 TRACE("%s\n", debugstr_w(path
));
2417 This
= heap_alloc(sizeof(struct folder
));
2418 if (!This
) return E_OUTOFMEMORY
;
2420 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2422 This
->path
= SysAllocString(path
);
2426 return E_OUTOFMEMORY
;
2429 *folder
= &This
->IFolder_iface
;
2434 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2436 struct file
*This
= impl_from_IFile(iface
);
2438 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2440 if (IsEqualIID(riid
, &IID_IFile
) ||
2441 IsEqualIID(riid
, &IID_IDispatch
) ||
2442 IsEqualIID(riid
, &IID_IUnknown
))
2445 IFile_AddRef(iface
);
2450 return E_NOINTERFACE
;
2453 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2455 struct file
*This
= impl_from_IFile(iface
);
2456 LONG ref
= InterlockedIncrement(&This
->ref
);
2458 TRACE("(%p) ref=%d\n", This
, ref
);
2463 static ULONG WINAPI
file_Release(IFile
*iface
)
2465 struct file
*This
= impl_from_IFile(iface
);
2466 LONG ref
= InterlockedDecrement(&This
->ref
);
2468 TRACE("(%p) ref=%d\n", This
, ref
);
2472 heap_free(This
->path
);
2479 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2481 struct file
*This
= impl_from_IFile(iface
);
2483 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2489 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2490 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2492 struct file
*This
= impl_from_IFile(iface
);
2494 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2496 return get_typeinfo(IFile_tid
, ppTInfo
);
2499 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2500 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2502 struct file
*This
= impl_from_IFile(iface
);
2503 ITypeInfo
*typeinfo
;
2506 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2507 rgszNames
, cNames
, lcid
, rgDispId
);
2509 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2511 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2512 ITypeInfo_Release(typeinfo
);
2517 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2519 struct file
*This
= impl_from_IFile(iface
);
2520 ITypeInfo
*typeinfo
;
2523 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2524 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2526 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2529 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2530 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2531 ITypeInfo_Release(typeinfo
);
2536 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
2538 struct file
*This
= impl_from_IFile(iface
);
2539 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2543 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2545 struct file
*This
= impl_from_IFile(iface
);
2548 TRACE("(%p)->(%p)\n", This
, name
);
2555 ptr
= strrchrW(This
->path
, '\\');
2558 *name
= SysAllocString(ptr
+1);
2559 TRACE("%s\n", debugstr_w(*name
));
2560 if (!*name
) return E_OUTOFMEMORY
;
2568 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2570 struct file
*This
= impl_from_IFile(iface
);
2571 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2575 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2577 struct file
*This
= impl_from_IFile(iface
);
2578 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2582 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2584 struct file
*This
= impl_from_IFile(iface
);
2585 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2589 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2591 struct file
*This
= impl_from_IFile(iface
);
2592 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2596 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2598 struct file
*This
= impl_from_IFile(iface
);
2599 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2603 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2605 struct file
*This
= impl_from_IFile(iface
);
2608 TRACE("(%p)->(%p)\n", This
, pfa
);
2613 fa
= GetFileAttributesW(This
->path
);
2614 if(fa
== INVALID_FILE_ATTRIBUTES
)
2615 return create_error(GetLastError());
2617 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2618 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2619 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2623 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2625 struct file
*This
= impl_from_IFile(iface
);
2626 FIXME("(%p)->(%x)\n", This
, pfa
);
2630 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2632 struct file
*This
= impl_from_IFile(iface
);
2633 FIXME("(%p)->(%p)\n", This
, pdate
);
2637 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2639 struct file
*This
= impl_from_IFile(iface
);
2640 FIXME("(%p)->(%p)\n", This
, pdate
);
2644 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2646 struct file
*This
= impl_from_IFile(iface
);
2647 FIXME("(%p)->(%p)\n", This
, pdate
);
2651 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2653 struct file
*This
= impl_from_IFile(iface
);
2654 ULARGE_INTEGER size
;
2655 WIN32_FIND_DATAW fd
;
2658 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2663 f
= FindFirstFileW(This
->path
, &fd
);
2664 if(f
== INVALID_HANDLE_VALUE
)
2665 return create_error(GetLastError());
2668 size
.u
.LowPart
= fd
.nFileSizeLow
;
2669 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2671 return variant_from_largeint(&size
, pvarSize
);
2674 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2676 struct file
*This
= impl_from_IFile(iface
);
2677 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2681 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2683 struct file
*This
= impl_from_IFile(iface
);
2684 FIXME("(%p)->(%x)\n", This
, Force
);
2688 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2690 struct file
*This
= impl_from_IFile(iface
);
2691 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2695 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2697 struct file
*This
= impl_from_IFile(iface
);
2698 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2702 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2704 struct file
*This
= impl_from_IFile(iface
);
2706 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2708 if (format
== TristateUseDefault
) {
2709 FIXME("default format not handled, defaulting to unicode\n");
2710 format
= TristateTrue
;
2713 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2716 static const IFileVtbl file_vtbl
= {
2717 file_QueryInterface
,
2720 file_GetTypeInfoCount
,
2730 file_get_ParentFolder
,
2731 file_get_Attributes
,
2732 file_put_Attributes
,
2733 file_get_DateCreated
,
2734 file_get_DateLastModified
,
2735 file_get_DateLastAccessed
,
2741 file_OpenAsTextStream
2744 static HRESULT
create_file(BSTR path
, IFile
**file
)
2751 f
= heap_alloc(sizeof(struct file
));
2753 return E_OUTOFMEMORY
;
2755 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2758 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2764 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2767 return E_OUTOFMEMORY
;
2770 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2776 attrs
= GetFileAttributesW(f
->path
);
2777 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2778 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2781 return create_error(GetLastError());
2784 *file
= &f
->IFile_iface
;
2788 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2790 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2792 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2793 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2794 IsEqualGUID( riid
, &IID_IDispatch
) ||
2795 IsEqualGUID( riid
, &IID_IUnknown
) )
2799 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2801 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2803 return E_NOINTERFACE
;
2805 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2807 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2809 return E_NOINTERFACE
;
2813 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2814 return E_NOINTERFACE
;
2817 IFileSystem3_AddRef(iface
);
2822 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2824 TRACE("%p\n", iface
);
2829 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2831 TRACE("%p\n", iface
);
2836 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2838 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2844 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2845 LCID lcid
, ITypeInfo
**ppTInfo
)
2847 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2848 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2851 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2852 LPOLESTR
*rgszNames
, UINT cNames
,
2853 LCID lcid
, DISPID
*rgDispId
)
2855 ITypeInfo
*typeinfo
;
2858 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2860 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2863 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2864 ITypeInfo_Release(typeinfo
);
2870 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2871 REFIID riid
, LCID lcid
, WORD wFlags
,
2872 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2873 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2875 ITypeInfo
*typeinfo
;
2878 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2879 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2881 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2884 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2885 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2886 ITypeInfo_Release(typeinfo
);
2892 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2894 TRACE("%p %p\n", iface
, ppdrives
);
2895 return create_drivecoll(ppdrives
);
2898 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2899 BSTR Name
, BSTR
*Result
)
2903 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2905 if (!Result
) return E_POINTER
;
2909 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
2911 /* if both parts have backslashes strip one from Path */
2912 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
2916 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2924 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
2926 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
2930 if (Path
[path_len
-1] != ':')
2937 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2945 else if (Path
|| Name
)
2946 ret
= SysAllocString(Path
? Path
: Name
);
2948 ret
= SysAllocStringLen(NULL
, 0);
2950 if (!ret
) return E_OUTOFMEMORY
;
2956 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
2958 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
2965 if (path
&& strlenW(path
) > 1 && path
[1] == ':')
2966 *drive
= SysAllocStringLen(path
, 2);
2971 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
2978 for(i
=len
-1; i
>=0; i
--)
2979 if(path
[i
]!='/' && path
[i
]!='\\')
2983 if(path
[i
]=='/' || path
[i
]=='\\')
2987 if(path
[i
]!='/' && path
[i
]!='\\')
2993 if(path
[i
]==':' && i
==1)
2998 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3003 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3008 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3010 *pbstrResult
= NULL
;
3014 *pbstrResult
= SysAllocStringLen(Path
, len
);
3016 return E_OUTOFMEMORY
;
3020 static HRESULT WINAPI
filesys_GetFileName(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
[i
]=='\\')
3044 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3045 *pbstrResult
= NULL
;
3049 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3051 return E_OUTOFMEMORY
;
3055 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3060 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3066 *pbstrResult
= NULL
;
3070 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3071 if(Path
[end
]!='/' && Path
[end
]!='\\')
3074 for(i
=end
; i
>=0; i
--) {
3075 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3077 if(Path
[i
]=='/' || Path
[i
]=='\\')
3082 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3083 *pbstrResult
= NULL
;
3087 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3089 return E_OUTOFMEMORY
;
3093 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
3096 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3101 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3104 static const WCHAR cur_path
[] = {'.',0};
3106 WCHAR buf
[MAX_PATH
], ch
;
3108 DWORD i
, beg
, len
, exp_len
;
3109 WIN32_FIND_DATAW fdata
;
3112 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3122 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3126 buf
[0] = toupperW(buf
[0]);
3127 if(len
>3 && buf
[len
-1] == '\\')
3130 for(beg
=3, i
=3; i
<=len
; i
++) {
3131 if(buf
[i
]!='\\' && buf
[i
])
3136 fh
= FindFirstFileW(buf
, &fdata
);
3137 if(fh
== INVALID_HANDLE_VALUE
)
3140 exp_len
= strlenW(fdata
.cFileName
);
3141 if(exp_len
== i
-beg
)
3142 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3148 *pbstrResult
= SysAllocString(buf
);
3150 return E_OUTOFMEMORY
;
3154 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3156 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3160 TRACE("%p %p\n", iface
, pbstrResult
);
3165 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3167 return E_OUTOFMEMORY
;
3169 if(!RtlGenRandom(&random
, sizeof(random
)))
3171 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3175 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3176 VARIANT_BOOL
*pfExists
)
3178 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3183 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3186 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3188 if (!ret
) return E_POINTER
;
3190 attrs
= GetFileAttributesW(path
);
3191 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3195 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3198 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3200 if (!ret
) return E_POINTER
;
3202 attrs
= GetFileAttributesW(path
);
3203 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3208 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3211 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3216 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3219 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3224 return E_INVALIDARG
;
3226 return create_file(FilePath
, ppfile
);
3229 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3234 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3241 return E_INVALIDARG
;
3243 attrs
= GetFileAttributesW(FolderPath
);
3244 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3245 return CTL_E_PATHNOTFOUND
;
3247 return create_folder(FolderPath
, folder
);
3250 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3251 SpecialFolderConst SpecialFolder
,
3254 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
3259 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3261 WCHAR path
[MAX_PATH
];
3262 DWORD len
, name_len
;
3263 WIN32_FIND_DATAW ffd
;
3266 f
= FindFirstFileW(file
, &ffd
);
3267 if(f
== INVALID_HANDLE_VALUE
)
3268 return create_error(GetLastError());
3270 len
= get_parent_folder_name(file
, file_len
);
3271 if(len
+1 >= MAX_PATH
) {
3276 memcpy(path
, file
, len
*sizeof(WCHAR
));
3281 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3284 name_len
= strlenW(ffd
.cFileName
);
3285 if(len
+name_len
+1 >= MAX_PATH
) {
3289 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3291 TRACE("deleting %s\n", debugstr_w(path
));
3293 if(!DeleteFileW(path
)) {
3294 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3295 || !DeleteFileW(path
)) {
3297 return create_error(GetLastError());
3300 } while(FindNextFileW(f
, &ffd
));
3306 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3309 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3314 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3317 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3319 WCHAR path
[MAX_PATH
];
3320 DWORD len
, name_len
;
3321 WIN32_FIND_DATAW ffd
;
3325 f
= FindFirstFileW(folder
, &ffd
);
3326 if(f
== INVALID_HANDLE_VALUE
)
3327 return create_error(GetLastError());
3329 len
= get_parent_folder_name(folder
, folder_len
);
3330 if(len
+1 >= MAX_PATH
) {
3335 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3340 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3342 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3343 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3346 name_len
= strlenW(ffd
.cFileName
);
3347 if(len
+name_len
+3 >= MAX_PATH
) {
3351 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3352 path
[len
+name_len
] = '\\';
3353 path
[len
+name_len
+1] = '*';
3354 path
[len
+name_len
+2] = 0;
3356 hr
= delete_file(path
, len
+name_len
+2, force
);
3362 hr
= delete_folder(path
, len
+name_len
+2, force
);
3368 path
[len
+name_len
] = 0;
3369 TRACE("deleting %s\n", debugstr_w(path
));
3371 if(!RemoveDirectoryW(path
)) {
3373 return create_error(GetLastError());
3375 } while(FindNextFileW(f
, &ffd
));
3381 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3384 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3389 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3392 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3395 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3400 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3403 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3408 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3409 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3412 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3413 DWORD src_len
, dst_len
, name_len
;
3414 WIN32_FIND_DATAW ffd
;
3418 if(!source
[0] || !destination
[0])
3419 return E_INVALIDARG
;
3421 attrs
= GetFileAttributesW(destination
);
3422 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3423 attrs
= GetFileAttributesW(source
);
3424 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3425 return create_error(GetLastError());
3426 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3427 return CTL_E_FILENOTFOUND
;
3429 if(!CopyFileW(source
, destination
, !overwrite
))
3430 return create_error(GetLastError());
3434 f
= FindFirstFileW(source
, &ffd
);
3435 if(f
== INVALID_HANDLE_VALUE
)
3436 return CTL_E_FILENOTFOUND
;
3438 src_len
= get_parent_folder_name(source
, source_len
);
3439 if(src_len
+1 >= MAX_PATH
) {
3444 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3445 src_path
[src_len
++] = '\\';
3448 dst_len
= destination_len
;
3449 if(dst_len
+1 >= MAX_PATH
) {
3453 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3454 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3455 dst_path
[dst_len
++] = '\\';
3457 hr
= CTL_E_FILENOTFOUND
;
3459 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3462 name_len
= strlenW(ffd
.cFileName
);
3463 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3467 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3468 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3470 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3472 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3474 return create_error(GetLastError());
3478 } while(FindNextFileW(f
, &ffd
));
3484 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3485 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3487 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3489 if(!Source
|| !Destination
)
3492 return copy_file(Source
, SysStringLen(Source
), Destination
,
3493 SysStringLen(Destination
), OverWriteFiles
);
3496 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3497 DWORD destination_len
, VARIANT_BOOL overwrite
)
3499 DWORD tmp
, src_len
, dst_len
, name_len
;
3500 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3501 WIN32_FIND_DATAW ffd
;
3504 BOOL copied
= FALSE
;
3506 if(!source
[0] || !destination
[0])
3507 return E_INVALIDARG
;
3509 dst_len
= destination_len
;
3510 if(dst_len
+1 >= MAX_PATH
)
3512 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3514 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3515 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3516 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3517 if(!CreateDirectoryW(dst
, NULL
)) {
3518 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3519 tmp
= GetFileAttributesW(dst
);
3520 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3521 return CTL_E_FILEALREADYEXISTS
;
3523 return create_error(GetLastError());
3528 src_len
= source_len
;
3529 if(src_len
+2 >= MAX_PATH
)
3531 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3532 src
[src_len
++] = '\\';
3536 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3537 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3538 return create_error(GetLastError());
3540 f
= FindFirstFileW(src
, &ffd
);
3542 src_len
= get_parent_folder_name(source
, source_len
);
3543 if(src_len
+2 >= MAX_PATH
)
3545 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3547 src
[src_len
++] = '\\';
3549 f
= FindFirstFileW(source
, &ffd
);
3551 if(f
== INVALID_HANDLE_VALUE
)
3552 return CTL_E_PATHNOTFOUND
;
3554 dst
[dst_len
++] = '\\';
3558 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3560 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3561 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3564 name_len
= strlenW(ffd
.cFileName
);
3565 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3569 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3570 dst
[dst_len
+name_len
] = 0;
3571 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3572 src
[src_len
+name_len
] = '\\';
3573 src
[src_len
+name_len
+1] = '*';
3574 src
[src_len
+name_len
+2] = 0;
3576 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3578 if(!CreateDirectoryW(dst
, NULL
)) {
3579 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3580 tmp
= GetFileAttributesW(dst
);
3581 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3583 return CTL_E_FILEALREADYEXISTS
;
3588 return create_error(GetLastError());
3592 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3593 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3598 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3599 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3603 } while(FindNextFileW(f
, &ffd
));
3606 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3609 static HRESULT WINAPI
filesys_CopyFolder(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_folder(Source
, SysStringLen(Source
), Destination
,
3618 SysStringLen(Destination
), OverWriteFiles
);
3621 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3626 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3628 ret
= CreateDirectoryW(path
, NULL
);
3632 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3633 return HRESULT_FROM_WIN32(GetLastError());
3636 return create_folder(path
, folder
);
3639 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3640 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3641 ITextStream
**stream
)
3645 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3647 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3648 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3651 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3652 IOMode mode
, VARIANT_BOOL create
,
3653 Tristate format
, ITextStream
**stream
)
3657 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3658 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3660 if (format
== TristateUseDefault
) {
3661 FIXME("default format not handled, defaulting to unicode\n");
3662 format
= TristateTrue
;
3665 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3668 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3669 StandardStreamTypes StandardStreamType
,
3670 VARIANT_BOOL Unicode
,
3673 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3678 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3680 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3684 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3685 a
= (WORD
)( version
>> 48);
3686 b
= (WORD
)((version
>> 32) & 0xffff);
3687 c
= (WORD
)((version
>> 16) & 0xffff);
3688 d
= (WORD
)( version
& 0xffff);
3690 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3693 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3695 static const WCHAR rootW
[] = {'\\',0};
3696 VS_FIXEDFILEINFO
*info
;
3702 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3704 len
= GetFileVersionInfoSizeW(name
, NULL
);
3706 return HRESULT_FROM_WIN32(GetLastError());
3708 ptr
= heap_alloc(len
);
3709 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3712 return HRESULT_FROM_WIN32(GetLastError());
3715 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3719 return HRESULT_FROM_WIN32(GetLastError());
3722 get_versionstring(info
, ver
);
3725 *version
= SysAllocString(ver
);
3726 TRACE("version=%s\n", debugstr_w(ver
));
3731 static const struct IFileSystem3Vtbl filesys_vtbl
=
3733 filesys_QueryInterface
,
3736 filesys_GetTypeInfoCount
,
3737 filesys_GetTypeInfo
,
3738 filesys_GetIDsOfNames
,
3742 filesys_GetDriveName
,
3743 filesys_GetParentFolderName
,
3744 filesys_GetFileName
,
3745 filesys_GetBaseName
,
3746 filesys_GetExtensionName
,
3747 filesys_GetAbsolutePathName
,
3748 filesys_GetTempName
,
3749 filesys_DriveExists
,
3751 filesys_FolderExists
,
3755 filesys_GetSpecialFolder
,
3757 filesys_DeleteFolder
,
3762 filesys_CreateFolder
,
3763 filesys_CreateTextFile
,
3764 filesys_OpenTextFile
,
3765 filesys_GetStandardStream
,
3766 filesys_GetFileVersion
3769 static IFileSystem3 filesystem
= { &filesys_vtbl
};
3771 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3773 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3775 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);