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
);
625 TRACE("(%p)\n", This
);
627 if(!CloseHandle(This
->file
))
635 static const ITextStreamVtbl textstreamvtbl
= {
636 textstream_QueryInterface
,
639 textstream_GetTypeInfoCount
,
640 textstream_GetTypeInfo
,
641 textstream_GetIDsOfNames
,
644 textstream_get_Column
,
645 textstream_get_AtEndOfStream
,
646 textstream_get_AtEndOfLine
,
651 textstream_WriteLine
,
652 textstream_WriteBlankLines
,
658 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
660 struct textstream
*stream
;
663 /* map access mode */
667 access
= GENERIC_READ
;
670 access
= GENERIC_WRITE
;
673 access
= FILE_APPEND_DATA
;
679 stream
= heap_alloc(sizeof(struct textstream
));
680 if (!stream
) return E_OUTOFMEMORY
;
682 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
685 stream
->unicode
= unicode
;
686 stream
->first_read
= TRUE
;
688 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
689 if (stream
->file
== INVALID_HANDLE_VALUE
)
691 HRESULT hr
= create_error(GetLastError());
696 if (mode
== ForReading
)
697 GetFileSizeEx(stream
->file
, &stream
->size
);
699 stream
->size
.QuadPart
= 0;
701 /* Write Unicode BOM */
702 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
704 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
705 if (!ret
|| written
!= sizeof(utf16bom
)) {
706 ITextStream_Release(&stream
->ITextStream_iface
);
707 return create_error(GetLastError());
711 *ret
= &stream
->ITextStream_iface
;
715 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
717 struct drive
*This
= impl_from_IDrive(iface
);
719 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
723 if (IsEqualIID( riid
, &IID_IDrive
) ||
724 IsEqualIID( riid
, &IID_IDispatch
) ||
725 IsEqualIID( riid
, &IID_IUnknown
))
728 IDrive_AddRef(iface
);
731 return E_NOINTERFACE
;
736 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
738 struct drive
*This
= impl_from_IDrive(iface
);
739 ULONG ref
= InterlockedIncrement(&This
->ref
);
740 TRACE("(%p)->(%d)\n", This
, ref
);
744 static ULONG WINAPI
drive_Release(IDrive
*iface
)
746 struct drive
*This
= impl_from_IDrive(iface
);
747 ULONG ref
= InterlockedDecrement(&This
->ref
);
748 TRACE("(%p)->(%d)\n", This
, ref
);
752 SysFreeString(This
->root
);
759 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
761 struct drive
*This
= impl_from_IDrive(iface
);
762 TRACE("(%p)->(%p)\n", This
, pctinfo
);
767 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
768 LCID lcid
, ITypeInfo
**ppTInfo
)
770 struct drive
*This
= impl_from_IDrive(iface
);
771 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
772 return get_typeinfo(IDrive_tid
, ppTInfo
);
775 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
776 LPOLESTR
*rgszNames
, UINT cNames
,
777 LCID lcid
, DISPID
*rgDispId
)
779 struct drive
*This
= impl_from_IDrive(iface
);
783 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
785 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
788 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
789 ITypeInfo_Release(typeinfo
);
795 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
796 REFIID riid
, LCID lcid
, WORD wFlags
,
797 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
798 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
800 struct drive
*This
= impl_from_IDrive(iface
);
804 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
805 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
807 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
810 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
811 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
812 ITypeInfo_Release(typeinfo
);
818 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
820 struct drive
*This
= impl_from_IDrive(iface
);
821 FIXME("(%p)->(%p): stub\n", This
, path
);
825 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
827 struct drive
*This
= impl_from_IDrive(iface
);
829 TRACE("(%p)->(%p)\n", This
, letter
);
834 *letter
= SysAllocStringLen(This
->root
, 1);
836 return E_OUTOFMEMORY
;
841 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
843 struct drive
*This
= impl_from_IDrive(iface
);
844 FIXME("(%p)->(%p): stub\n", This
, share_name
);
848 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
850 struct drive
*This
= impl_from_IDrive(iface
);
852 TRACE("(%p)->(%p)\n", This
, type
);
854 switch (GetDriveTypeW(This
->root
))
856 case DRIVE_REMOVABLE
:
879 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
881 struct drive
*This
= impl_from_IDrive(iface
);
882 FIXME("(%p)->(%p): stub\n", This
, folder
);
886 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
890 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
893 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
898 V_I4(v
) = src
->u
.LowPart
;
904 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
906 struct drive
*This
= impl_from_IDrive(iface
);
907 ULARGE_INTEGER avail
;
909 TRACE("(%p)->(%p)\n", This
, v
);
914 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
917 return variant_from_largeint(&avail
, v
);
920 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
922 struct drive
*This
= impl_from_IDrive(iface
);
923 ULARGE_INTEGER freespace
;
925 TRACE("(%p)->(%p)\n", This
, v
);
930 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
933 return variant_from_largeint(&freespace
, v
);
936 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
938 struct drive
*This
= impl_from_IDrive(iface
);
939 ULARGE_INTEGER total
;
941 TRACE("(%p)->(%p)\n", This
, v
);
946 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
949 return variant_from_largeint(&total
, v
);
952 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
954 struct drive
*This
= impl_from_IDrive(iface
);
955 WCHAR nameW
[MAX_PATH
+1];
958 TRACE("(%p)->(%p)\n", This
, name
);
964 ret
= GetVolumeInformationW(This
->root
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, NULL
, NULL
, NULL
, 0);
966 *name
= SysAllocString(nameW
);
967 return ret
? S_OK
: E_FAIL
;
970 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
972 struct drive
*This
= impl_from_IDrive(iface
);
973 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
977 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
979 struct drive
*This
= impl_from_IDrive(iface
);
980 WCHAR nameW
[MAX_PATH
+1];
983 TRACE("(%p)->(%p)\n", This
, fs
);
989 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
991 *fs
= SysAllocString(nameW
);
992 return ret
? S_OK
: E_FAIL
;
995 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
997 struct drive
*This
= impl_from_IDrive(iface
);
1000 TRACE("(%p)->(%p)\n", This
, serial
);
1005 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1006 return ret
? S_OK
: E_FAIL
;
1009 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1011 struct drive
*This
= impl_from_IDrive(iface
);
1012 ULARGE_INTEGER freespace
;
1015 TRACE("(%p)->(%p)\n", This
, ready
);
1020 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1021 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1025 static const IDriveVtbl drivevtbl
= {
1026 drive_QueryInterface
,
1029 drive_GetTypeInfoCount
,
1031 drive_GetIDsOfNames
,
1034 drive_get_DriveLetter
,
1035 drive_get_ShareName
,
1036 drive_get_DriveType
,
1037 drive_get_RootFolder
,
1038 drive_get_AvailableSpace
,
1039 drive_get_FreeSpace
,
1040 drive_get_TotalSize
,
1041 drive_get_VolumeName
,
1042 drive_put_VolumeName
,
1043 drive_get_FileSystem
,
1044 drive_get_SerialNumber
,
1048 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1054 This
= heap_alloc(sizeof(*This
));
1055 if (!This
) return E_OUTOFMEMORY
;
1057 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1059 This
->root
= SysAllocStringLen(NULL
, 3);
1063 return E_OUTOFMEMORY
;
1065 This
->root
[0] = letter
;
1066 This
->root
[1] = ':';
1067 This
->root
[2] = '\\';
1070 *drive
= &This
->IDrive_iface
;
1074 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1076 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1078 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1082 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1083 IsEqualIID( riid
, &IID_IUnknown
))
1086 IEnumVARIANT_AddRef(iface
);
1089 return E_NOINTERFACE
;
1094 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1096 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1097 ULONG ref
= InterlockedIncrement(&This
->ref
);
1098 TRACE("(%p)->(%d)\n", This
, ref
);
1102 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1104 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1105 ULONG ref
= InterlockedDecrement(&This
->ref
);
1107 TRACE("(%p)->(%d)\n", This
, ref
);
1111 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1112 FindClose(This
->data
.u
.foldercoll
.find
);
1119 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1121 static const WCHAR allW
[] = {'*',0};
1122 WCHAR pathW
[MAX_PATH
];
1126 strcpyW(pathW
, path
);
1127 len
= strlenW(pathW
);
1128 if (len
&& pathW
[len
-1] != '\\')
1129 strcatW(pathW
, bsW
);
1130 strcatW(pathW
, allW
);
1131 handle
= FindFirstFileW(pathW
, data
);
1132 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1134 /* find first dir/file */
1137 if (file
? is_file_data(data
) : is_dir_data(data
))
1140 if (!FindNextFileW(handle
, data
))
1149 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1151 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1152 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1153 WIN32_FIND_DATAW data
;
1156 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1161 if (!celt
) return S_OK
;
1165 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1166 if (!handle
) return S_FALSE
;
1168 This
->data
.u
.foldercoll
.find
= handle
;
1172 if (!FindNextFileW(handle
, &data
))
1178 if (is_dir_data(&data
))
1184 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1185 hr
= create_folder(str
, &folder
);
1187 if (FAILED(hr
)) return hr
;
1189 V_VT(&var
[count
]) = VT_DISPATCH
;
1190 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1193 if (count
>= celt
) break;
1195 } while (FindNextFileW(handle
, &data
));
1200 return (count
< celt
) ? S_FALSE
: S_OK
;
1203 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1205 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1206 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1207 WIN32_FIND_DATAW data
;
1209 TRACE("(%p)->(%d)\n", This
, celt
);
1211 if (!celt
) return S_OK
;
1215 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1216 if (!handle
) return S_FALSE
;
1218 This
->data
.u
.foldercoll
.find
= handle
;
1222 if (!FindNextFileW(handle
, &data
))
1228 if (is_dir_data(&data
))
1232 } while (FindNextFileW(handle
, &data
));
1234 return celt
? S_FALSE
: S_OK
;
1237 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1239 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1241 TRACE("(%p)\n", This
);
1243 FindClose(This
->data
.u
.foldercoll
.find
);
1244 This
->data
.u
.foldercoll
.find
= NULL
;
1249 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1251 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1252 TRACE("(%p)->(%p)\n", This
, pclone
);
1253 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1256 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1257 enumvariant_QueryInterface
,
1259 foldercoll_enumvariant_Release
,
1260 foldercoll_enumvariant_Next
,
1261 foldercoll_enumvariant_Skip
,
1262 foldercoll_enumvariant_Reset
,
1263 foldercoll_enumvariant_Clone
1266 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1268 struct enumvariant
*This
;
1272 This
= heap_alloc(sizeof(*This
));
1273 if (!This
) return E_OUTOFMEMORY
;
1275 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1277 This
->data
.u
.foldercoll
.find
= NULL
;
1278 This
->data
.u
.foldercoll
.coll
= collection
;
1279 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1281 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1286 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1288 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1289 ULONG ref
= InterlockedDecrement(&This
->ref
);
1291 TRACE("(%p)->(%d)\n", This
, ref
);
1295 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1296 FindClose(This
->data
.u
.filecoll
.find
);
1303 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1305 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1306 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1307 WIN32_FIND_DATAW data
;
1310 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1315 if (!celt
) return S_OK
;
1319 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1320 if (!handle
) return S_FALSE
;
1321 This
->data
.u
.filecoll
.find
= handle
;
1323 else if (!FindNextFileW(handle
, &data
))
1328 if (is_file_data(&data
))
1334 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1335 hr
= create_file(str
, &file
);
1337 if (FAILED(hr
)) return hr
;
1339 V_VT(&var
[count
]) = VT_DISPATCH
;
1340 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1341 if (++count
>= celt
) break;
1343 } while (FindNextFileW(handle
, &data
));
1348 return (count
< celt
) ? S_FALSE
: S_OK
;
1351 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1353 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1354 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1355 WIN32_FIND_DATAW data
;
1357 TRACE("(%p)->(%d)\n", This
, celt
);
1359 if (!celt
) return S_OK
;
1363 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1364 if (!handle
) return S_FALSE
;
1365 This
->data
.u
.filecoll
.find
= handle
;
1367 else if (!FindNextFileW(handle
, &data
))
1372 if (is_file_data(&data
))
1374 } while (celt
&& FindNextFileW(handle
, &data
));
1376 return celt
? S_FALSE
: S_OK
;
1379 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1381 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1383 TRACE("(%p)\n", This
);
1385 FindClose(This
->data
.u
.filecoll
.find
);
1386 This
->data
.u
.filecoll
.find
= NULL
;
1391 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1393 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1394 TRACE("(%p)->(%p)\n", This
, pclone
);
1395 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1398 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1399 enumvariant_QueryInterface
,
1401 filecoll_enumvariant_Release
,
1402 filecoll_enumvariant_Next
,
1403 filecoll_enumvariant_Skip
,
1404 filecoll_enumvariant_Reset
,
1405 filecoll_enumvariant_Clone
1408 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1410 struct enumvariant
*This
;
1414 This
= heap_alloc(sizeof(*This
));
1415 if (!This
) return E_OUTOFMEMORY
;
1417 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1419 This
->data
.u
.filecoll
.find
= NULL
;
1420 This
->data
.u
.filecoll
.coll
= collection
;
1421 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1423 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1428 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1430 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1431 ULONG ref
= InterlockedDecrement(&This
->ref
);
1433 TRACE("(%p)->(%d)\n", This
, ref
);
1437 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1444 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1446 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1449 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1451 penum
->data
.u
.drivecoll
.cur
= i
;
1458 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1460 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1463 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1468 if (!celt
) return S_OK
;
1470 while (find_next_drive(This
) == S_OK
)
1475 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1476 if (FAILED(hr
)) return hr
;
1478 V_VT(&var
[count
]) = VT_DISPATCH
;
1479 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1481 if (++count
>= celt
) break;
1487 return (count
< celt
) ? S_FALSE
: S_OK
;
1490 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1492 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1494 TRACE("(%p)->(%d)\n", This
, celt
);
1496 if (!celt
) return S_OK
;
1498 while (celt
&& find_next_drive(This
) == S_OK
)
1501 return celt
? S_FALSE
: S_OK
;
1504 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1506 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1508 TRACE("(%p)\n", This
);
1510 This
->data
.u
.drivecoll
.cur
= -1;
1514 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1516 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1517 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1521 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1522 enumvariant_QueryInterface
,
1524 drivecoll_enumvariant_Release
,
1525 drivecoll_enumvariant_Next
,
1526 drivecoll_enumvariant_Skip
,
1527 drivecoll_enumvariant_Reset
,
1528 drivecoll_enumvariant_Clone
1531 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1533 struct enumvariant
*This
;
1537 This
= heap_alloc(sizeof(*This
));
1538 if (!This
) return E_OUTOFMEMORY
;
1540 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1542 This
->data
.u
.drivecoll
.coll
= collection
;
1543 This
->data
.u
.drivecoll
.cur
= -1;
1544 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1546 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1551 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1553 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1555 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1559 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1560 IsEqualIID( riid
, &IID_IDispatch
) ||
1561 IsEqualIID( riid
, &IID_IUnknown
))
1564 IFolderCollection_AddRef(iface
);
1567 return E_NOINTERFACE
;
1572 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1574 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1575 ULONG ref
= InterlockedIncrement(&This
->ref
);
1576 TRACE("(%p)->(%d)\n", This
, ref
);
1580 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1582 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1583 ULONG ref
= InterlockedDecrement(&This
->ref
);
1584 TRACE("(%p)->(%d)\n", This
, ref
);
1588 SysFreeString(This
->path
);
1595 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1597 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1598 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1603 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1604 LCID lcid
, ITypeInfo
**ppTInfo
)
1606 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1607 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1608 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1611 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1612 LPOLESTR
*rgszNames
, UINT cNames
,
1613 LCID lcid
, DISPID
*rgDispId
)
1615 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1616 ITypeInfo
*typeinfo
;
1619 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1621 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1624 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1625 ITypeInfo_Release(typeinfo
);
1631 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1632 REFIID riid
, LCID lcid
, WORD wFlags
,
1633 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1634 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1636 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1637 ITypeInfo
*typeinfo
;
1640 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1641 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1643 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1646 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1647 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1648 ITypeInfo_Release(typeinfo
);
1654 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1656 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1657 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1661 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1663 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1664 FIXME("(%p)->(%p): stub\n", This
, folder
);
1668 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1670 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1672 TRACE("(%p)->(%p)\n", This
, newenum
);
1677 return create_foldercoll_enum(This
, newenum
);
1680 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1682 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1683 static const WCHAR allW
[] = {'\\','*',0};
1684 WIN32_FIND_DATAW data
;
1685 WCHAR pathW
[MAX_PATH
];
1688 TRACE("(%p)->(%p)\n", This
, count
);
1695 strcpyW(pathW
, This
->path
);
1696 strcatW(pathW
, allW
);
1697 handle
= FindFirstFileW(pathW
, &data
);
1698 if (handle
== INVALID_HANDLE_VALUE
)
1699 return HRESULT_FROM_WIN32(GetLastError());
1703 if (is_dir_data(&data
))
1705 } while (FindNextFileW(handle
, &data
));
1711 static const IFolderCollectionVtbl foldercollvtbl
= {
1712 foldercoll_QueryInterface
,
1715 foldercoll_GetTypeInfoCount
,
1716 foldercoll_GetTypeInfo
,
1717 foldercoll_GetIDsOfNames
,
1720 foldercoll_get_Item
,
1721 foldercoll_get__NewEnum
,
1722 foldercoll_get_Count
1725 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1727 struct foldercollection
*This
;
1731 This
= heap_alloc(sizeof(struct foldercollection
));
1732 if (!This
) return E_OUTOFMEMORY
;
1734 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1736 This
->path
= SysAllocString(path
);
1740 return E_OUTOFMEMORY
;
1743 *folders
= &This
->IFolderCollection_iface
;
1748 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1750 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1752 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1756 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1757 IsEqualIID( riid
, &IID_IDispatch
) ||
1758 IsEqualIID( riid
, &IID_IUnknown
))
1761 IFileCollection_AddRef(iface
);
1764 return E_NOINTERFACE
;
1769 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1771 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1772 ULONG ref
= InterlockedIncrement(&This
->ref
);
1773 TRACE("(%p)->(%d)\n", This
, ref
);
1777 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1779 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1780 ULONG ref
= InterlockedDecrement(&This
->ref
);
1781 TRACE("(%p)->(%d)\n", This
, ref
);
1785 SysFreeString(This
->path
);
1792 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1794 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1795 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1800 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1801 LCID lcid
, ITypeInfo
**ppTInfo
)
1803 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1804 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1805 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1808 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1809 LPOLESTR
*rgszNames
, UINT cNames
,
1810 LCID lcid
, DISPID
*rgDispId
)
1812 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1813 ITypeInfo
*typeinfo
;
1816 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1818 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1821 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1822 ITypeInfo_Release(typeinfo
);
1828 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1829 REFIID riid
, LCID lcid
, WORD wFlags
,
1830 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1831 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1833 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1834 ITypeInfo
*typeinfo
;
1837 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1838 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1840 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1843 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1844 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1845 ITypeInfo_Release(typeinfo
);
1851 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1853 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1854 FIXME("(%p)->(%p)\n", This
, file
);
1858 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1860 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1862 TRACE("(%p)->(%p)\n", This
, ppenum
);
1867 return create_filecoll_enum(This
, ppenum
);
1870 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1872 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1873 static const WCHAR allW
[] = {'\\','*',0};
1874 WIN32_FIND_DATAW data
;
1875 WCHAR pathW
[MAX_PATH
];
1878 TRACE("(%p)->(%p)\n", This
, count
);
1885 strcpyW(pathW
, This
->path
);
1886 strcatW(pathW
, allW
);
1887 handle
= FindFirstFileW(pathW
, &data
);
1888 if (handle
== INVALID_HANDLE_VALUE
)
1889 return HRESULT_FROM_WIN32(GetLastError());
1893 if (is_file_data(&data
))
1895 } while (FindNextFileW(handle
, &data
));
1901 static const IFileCollectionVtbl filecollectionvtbl
= {
1902 filecoll_QueryInterface
,
1905 filecoll_GetTypeInfoCount
,
1906 filecoll_GetTypeInfo
,
1907 filecoll_GetIDsOfNames
,
1910 filecoll_get__NewEnum
,
1914 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1916 struct filecollection
*This
;
1920 This
= heap_alloc(sizeof(*This
));
1921 if (!This
) return E_OUTOFMEMORY
;
1923 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1925 This
->path
= SysAllocString(path
);
1929 return E_OUTOFMEMORY
;
1932 *files
= &This
->IFileCollection_iface
;
1936 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1938 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1940 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1944 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1945 IsEqualIID( riid
, &IID_IDispatch
) ||
1946 IsEqualIID( riid
, &IID_IUnknown
))
1949 IDriveCollection_AddRef(iface
);
1952 return E_NOINTERFACE
;
1957 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
1959 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1960 ULONG ref
= InterlockedIncrement(&This
->ref
);
1961 TRACE("(%p)->(%d)\n", This
, ref
);
1965 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
1967 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1968 ULONG ref
= InterlockedDecrement(&This
->ref
);
1969 TRACE("(%p)->(%d)\n", This
, ref
);
1977 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
1979 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1980 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1985 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
1986 LCID lcid
, ITypeInfo
**ppTInfo
)
1988 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1989 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1990 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
1993 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
1994 LPOLESTR
*rgszNames
, UINT cNames
,
1995 LCID lcid
, DISPID
*rgDispId
)
1997 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1998 ITypeInfo
*typeinfo
;
2001 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2003 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2006 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2007 ITypeInfo_Release(typeinfo
);
2013 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2014 REFIID riid
, LCID lcid
, WORD wFlags
,
2015 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2016 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2018 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2019 ITypeInfo
*typeinfo
;
2022 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2023 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2025 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2028 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2029 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2030 ITypeInfo_Release(typeinfo
);
2036 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2038 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2039 FIXME("(%p)->(%p): stub\n", This
, drive
);
2043 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2045 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2047 TRACE("(%p)->(%p)\n", This
, ppenum
);
2052 return create_drivecoll_enum(This
, ppenum
);
2055 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2057 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2059 TRACE("(%p)->(%p)\n", This
, count
);
2061 if (!count
) return E_POINTER
;
2063 *count
= This
->count
;
2067 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2068 drivecoll_QueryInterface
,
2071 drivecoll_GetTypeInfoCount
,
2072 drivecoll_GetTypeInfo
,
2073 drivecoll_GetIDsOfNames
,
2076 drivecoll_get__NewEnum
,
2080 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2082 struct drivecollection
*This
;
2087 This
= heap_alloc(sizeof(*This
));
2088 if (!This
) return E_OUTOFMEMORY
;
2090 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2092 This
->drives
= mask
= GetLogicalDrives();
2093 /* count set bits */
2094 for (This
->count
= 0; mask
; This
->count
++)
2097 *drives
= &This
->IDriveCollection_iface
;
2101 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2103 struct folder
*This
= impl_from_IFolder(iface
);
2105 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2109 if (IsEqualIID( riid
, &IID_IFolder
) ||
2110 IsEqualIID( riid
, &IID_IDispatch
) ||
2111 IsEqualIID( riid
, &IID_IUnknown
))
2114 IFolder_AddRef(iface
);
2117 return E_NOINTERFACE
;
2122 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2124 struct folder
*This
= impl_from_IFolder(iface
);
2125 ULONG ref
= InterlockedIncrement(&This
->ref
);
2126 TRACE("(%p)->(%d)\n", This
, ref
);
2130 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2132 struct folder
*This
= impl_from_IFolder(iface
);
2133 ULONG ref
= InterlockedDecrement(&This
->ref
);
2134 TRACE("(%p)->(%d)\n", This
, ref
);
2138 SysFreeString(This
->path
);
2145 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2147 struct folder
*This
= impl_from_IFolder(iface
);
2148 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2153 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2154 LCID lcid
, ITypeInfo
**ppTInfo
)
2156 struct folder
*This
= impl_from_IFolder(iface
);
2157 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2158 return get_typeinfo(IFolder_tid
, ppTInfo
);
2161 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2162 LPOLESTR
*rgszNames
, UINT cNames
,
2163 LCID lcid
, DISPID
*rgDispId
)
2165 struct folder
*This
= impl_from_IFolder(iface
);
2166 ITypeInfo
*typeinfo
;
2169 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2171 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2174 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2175 ITypeInfo_Release(typeinfo
);
2181 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2182 REFIID riid
, LCID lcid
, WORD wFlags
,
2183 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2184 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2186 struct folder
*This
= impl_from_IFolder(iface
);
2187 ITypeInfo
*typeinfo
;
2190 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2191 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2193 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2196 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2197 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2198 ITypeInfo_Release(typeinfo
);
2204 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2206 struct folder
*This
= impl_from_IFolder(iface
);
2208 TRACE("(%p)->(%p)\n", This
, path
);
2213 *path
= SysAllocString(This
->path
);
2214 return *path
? S_OK
: E_OUTOFMEMORY
;
2217 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2219 struct folder
*This
= impl_from_IFolder(iface
);
2222 TRACE("(%p)->(%p)\n", This
, name
);
2229 ptr
= strrchrW(This
->path
, '\\');
2232 *name
= SysAllocString(ptr
+1);
2233 TRACE("%s\n", debugstr_w(*name
));
2234 if (!*name
) return E_OUTOFMEMORY
;
2242 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2244 struct folder
*This
= impl_from_IFolder(iface
);
2245 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2249 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2251 struct folder
*This
= impl_from_IFolder(iface
);
2252 FIXME("(%p)->(%p): stub\n", This
, path
);
2256 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2258 struct folder
*This
= impl_from_IFolder(iface
);
2259 FIXME("(%p)->(%p): stub\n", This
, name
);
2263 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2265 struct folder
*This
= impl_from_IFolder(iface
);
2266 FIXME("(%p)->(%p): stub\n", This
, drive
);
2270 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2272 struct folder
*This
= impl_from_IFolder(iface
);
2273 FIXME("(%p)->(%p): stub\n", This
, parent
);
2277 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2279 struct folder
*This
= impl_from_IFolder(iface
);
2280 FIXME("(%p)->(%p): stub\n", This
, attr
);
2284 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2286 struct folder
*This
= impl_from_IFolder(iface
);
2287 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2291 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2293 struct folder
*This
= impl_from_IFolder(iface
);
2294 FIXME("(%p)->(%p): stub\n", This
, date
);
2298 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2300 struct folder
*This
= impl_from_IFolder(iface
);
2301 FIXME("(%p)->(%p): stub\n", This
, date
);
2305 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2307 struct folder
*This
= impl_from_IFolder(iface
);
2308 FIXME("(%p)->(%p): stub\n", This
, date
);
2312 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2314 struct folder
*This
= impl_from_IFolder(iface
);
2315 FIXME("(%p)->(%p): stub\n", This
, type
);
2319 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2321 struct folder
*This
= impl_from_IFolder(iface
);
2322 FIXME("(%p)->(%x): stub\n", This
, force
);
2326 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2328 struct folder
*This
= impl_from_IFolder(iface
);
2329 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2333 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2335 struct folder
*This
= impl_from_IFolder(iface
);
2336 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2340 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2342 struct folder
*This
= impl_from_IFolder(iface
);
2343 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2347 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2349 struct folder
*This
= impl_from_IFolder(iface
);
2350 FIXME("(%p)->(%p): stub\n", This
, size
);
2354 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2356 struct folder
*This
= impl_from_IFolder(iface
);
2358 TRACE("(%p)->(%p)\n", This
, folders
);
2363 return create_foldercoll(This
->path
, folders
);
2366 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2368 struct folder
*This
= impl_from_IFolder(iface
);
2370 TRACE("(%p)->(%p)\n", This
, files
);
2375 return create_filecoll(This
->path
, files
);
2378 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2379 VARIANT_BOOL unicode
, ITextStream
**stream
)
2381 struct folder
*This
= impl_from_IFolder(iface
);
2382 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2386 static const IFolderVtbl foldervtbl
= {
2387 folder_QueryInterface
,
2390 folder_GetTypeInfoCount
,
2392 folder_GetIDsOfNames
,
2397 folder_get_ShortPath
,
2398 folder_get_ShortName
,
2400 folder_get_ParentFolder
,
2401 folder_get_Attributes
,
2402 folder_put_Attributes
,
2403 folder_get_DateCreated
,
2404 folder_get_DateLastModified
,
2405 folder_get_DateLastAccessed
,
2410 folder_get_IsRootFolder
,
2412 folder_get_SubFolders
,
2414 folder_CreateTextFile
2417 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2419 struct folder
*This
;
2423 TRACE("%s\n", debugstr_w(path
));
2425 This
= heap_alloc(sizeof(struct folder
));
2426 if (!This
) return E_OUTOFMEMORY
;
2428 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2430 This
->path
= SysAllocString(path
);
2434 return E_OUTOFMEMORY
;
2437 *folder
= &This
->IFolder_iface
;
2442 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2444 struct file
*This
= impl_from_IFile(iface
);
2446 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2448 if (IsEqualIID(riid
, &IID_IFile
) ||
2449 IsEqualIID(riid
, &IID_IDispatch
) ||
2450 IsEqualIID(riid
, &IID_IUnknown
))
2453 IFile_AddRef(iface
);
2458 return E_NOINTERFACE
;
2461 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2463 struct file
*This
= impl_from_IFile(iface
);
2464 LONG ref
= InterlockedIncrement(&This
->ref
);
2466 TRACE("(%p) ref=%d\n", This
, ref
);
2471 static ULONG WINAPI
file_Release(IFile
*iface
)
2473 struct file
*This
= impl_from_IFile(iface
);
2474 LONG ref
= InterlockedDecrement(&This
->ref
);
2476 TRACE("(%p) ref=%d\n", This
, ref
);
2480 heap_free(This
->path
);
2487 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2489 struct file
*This
= impl_from_IFile(iface
);
2491 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2497 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2498 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2500 struct file
*This
= impl_from_IFile(iface
);
2502 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2504 return get_typeinfo(IFile_tid
, ppTInfo
);
2507 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2508 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2510 struct file
*This
= impl_from_IFile(iface
);
2511 ITypeInfo
*typeinfo
;
2514 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2515 rgszNames
, cNames
, lcid
, rgDispId
);
2517 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2519 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2520 ITypeInfo_Release(typeinfo
);
2525 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2527 struct file
*This
= impl_from_IFile(iface
);
2528 ITypeInfo
*typeinfo
;
2531 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2532 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2534 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2537 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2538 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2539 ITypeInfo_Release(typeinfo
);
2544 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2546 struct file
*This
= impl_from_IFile(iface
);
2548 TRACE("(%p)->(%p)\n", This
, path
);
2553 *path
= SysAllocString(This
->path
);
2555 return E_OUTOFMEMORY
;
2560 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2562 struct file
*This
= impl_from_IFile(iface
);
2565 TRACE("(%p)->(%p)\n", This
, name
);
2572 ptr
= strrchrW(This
->path
, '\\');
2575 *name
= SysAllocString(ptr
+1);
2576 TRACE("%s\n", debugstr_w(*name
));
2577 if (!*name
) return E_OUTOFMEMORY
;
2585 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2587 struct file
*This
= impl_from_IFile(iface
);
2588 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2592 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2594 struct file
*This
= impl_from_IFile(iface
);
2595 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2599 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2601 struct file
*This
= impl_from_IFile(iface
);
2602 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2606 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2608 struct file
*This
= impl_from_IFile(iface
);
2609 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2613 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2615 struct file
*This
= impl_from_IFile(iface
);
2616 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2620 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2622 struct file
*This
= impl_from_IFile(iface
);
2625 TRACE("(%p)->(%p)\n", This
, pfa
);
2630 fa
= GetFileAttributesW(This
->path
);
2631 if(fa
== INVALID_FILE_ATTRIBUTES
)
2632 return create_error(GetLastError());
2634 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2635 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2636 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2640 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2642 struct file
*This
= impl_from_IFile(iface
);
2644 TRACE("(%p)->(%x)\n", This
, pfa
);
2646 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2649 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2651 struct file
*This
= impl_from_IFile(iface
);
2652 FIXME("(%p)->(%p)\n", This
, pdate
);
2656 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2658 struct file
*This
= impl_from_IFile(iface
);
2659 FIXME("(%p)->(%p)\n", This
, pdate
);
2663 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2665 struct file
*This
= impl_from_IFile(iface
);
2666 FIXME("(%p)->(%p)\n", This
, pdate
);
2670 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2672 struct file
*This
= impl_from_IFile(iface
);
2673 ULARGE_INTEGER size
;
2674 WIN32_FIND_DATAW fd
;
2677 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2682 f
= FindFirstFileW(This
->path
, &fd
);
2683 if(f
== INVALID_HANDLE_VALUE
)
2684 return create_error(GetLastError());
2687 size
.u
.LowPart
= fd
.nFileSizeLow
;
2688 size
.u
.HighPart
= fd
.nFileSizeHigh
;
2690 return variant_from_largeint(&size
, pvarSize
);
2693 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2695 struct file
*This
= impl_from_IFile(iface
);
2696 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2700 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2702 struct file
*This
= impl_from_IFile(iface
);
2703 FIXME("(%p)->(%x)\n", This
, Force
);
2707 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2709 struct file
*This
= impl_from_IFile(iface
);
2710 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2714 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2716 struct file
*This
= impl_from_IFile(iface
);
2717 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2721 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2723 struct file
*This
= impl_from_IFile(iface
);
2725 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2727 if (format
== TristateUseDefault
) {
2728 FIXME("default format not handled, defaulting to unicode\n");
2729 format
= TristateTrue
;
2732 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2735 static const IFileVtbl file_vtbl
= {
2736 file_QueryInterface
,
2739 file_GetTypeInfoCount
,
2749 file_get_ParentFolder
,
2750 file_get_Attributes
,
2751 file_put_Attributes
,
2752 file_get_DateCreated
,
2753 file_get_DateLastModified
,
2754 file_get_DateLastAccessed
,
2760 file_OpenAsTextStream
2763 static HRESULT
create_file(BSTR path
, IFile
**file
)
2770 f
= heap_alloc(sizeof(struct file
));
2772 return E_OUTOFMEMORY
;
2774 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2777 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2783 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2786 return E_OUTOFMEMORY
;
2789 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2795 attrs
= GetFileAttributesW(f
->path
);
2796 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2797 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2800 return create_error(GetLastError());
2803 *file
= &f
->IFile_iface
;
2807 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2809 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2811 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2812 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2813 IsEqualGUID( riid
, &IID_IDispatch
) ||
2814 IsEqualGUID( riid
, &IID_IUnknown
) )
2818 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2820 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2822 return E_NOINTERFACE
;
2824 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2826 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2828 return E_NOINTERFACE
;
2832 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2833 return E_NOINTERFACE
;
2836 IFileSystem3_AddRef(iface
);
2841 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2843 TRACE("%p\n", iface
);
2848 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2850 TRACE("%p\n", iface
);
2855 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2857 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2863 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2864 LCID lcid
, ITypeInfo
**ppTInfo
)
2866 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2867 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2870 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2871 LPOLESTR
*rgszNames
, UINT cNames
,
2872 LCID lcid
, DISPID
*rgDispId
)
2874 ITypeInfo
*typeinfo
;
2877 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2879 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2882 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2883 ITypeInfo_Release(typeinfo
);
2889 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2890 REFIID riid
, LCID lcid
, WORD wFlags
,
2891 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2892 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2894 ITypeInfo
*typeinfo
;
2897 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2898 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2900 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2903 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2904 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2905 ITypeInfo_Release(typeinfo
);
2911 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2913 TRACE("%p %p\n", iface
, ppdrives
);
2914 return create_drivecoll(ppdrives
);
2917 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2918 BSTR Name
, BSTR
*Result
)
2922 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2924 if (!Result
) return E_POINTER
;
2928 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
2930 /* if both parts have backslashes strip one from Path */
2931 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
2935 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2943 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
2945 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
2949 if (Path
[path_len
-1] != ':')
2956 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2964 else if (Path
|| Name
)
2965 ret
= SysAllocString(Path
? Path
: Name
);
2967 ret
= SysAllocStringLen(NULL
, 0);
2969 if (!ret
) return E_OUTOFMEMORY
;
2975 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
2977 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
2984 if (path
&& strlenW(path
) > 1 && path
[1] == ':')
2985 *drive
= SysAllocStringLen(path
, 2);
2990 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
2997 for(i
=len
-1; i
>=0; i
--)
2998 if(path
[i
]!='/' && path
[i
]!='\\')
3002 if(path
[i
]=='/' || path
[i
]=='\\')
3006 if(path
[i
]!='/' && path
[i
]!='\\')
3012 if(path
[i
]==':' && i
==1)
3017 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3022 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3027 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3029 *pbstrResult
= NULL
;
3033 *pbstrResult
= SysAllocStringLen(Path
, len
);
3035 return E_OUTOFMEMORY
;
3039 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3044 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3050 *pbstrResult
= NULL
;
3054 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3055 if(Path
[end
]!='/' && Path
[end
]!='\\')
3058 for(i
=end
; i
>=0; i
--)
3059 if(Path
[i
]=='/' || Path
[i
]=='\\')
3063 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3064 *pbstrResult
= NULL
;
3068 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3070 return E_OUTOFMEMORY
;
3074 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3079 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3085 *pbstrResult
= NULL
;
3089 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3090 if(Path
[end
]!='/' && Path
[end
]!='\\')
3093 for(i
=end
; i
>=0; i
--) {
3094 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3096 if(Path
[i
]=='/' || Path
[i
]=='\\')
3101 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3102 *pbstrResult
= NULL
;
3106 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3108 return E_OUTOFMEMORY
;
3112 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3117 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3120 len
= SysStringLen(path
);
3122 if (path
[len
-1] == '.') {
3123 *ext
= SysAllocString(&path
[len
]);
3125 return E_OUTOFMEMORY
;
3134 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3137 static const WCHAR cur_path
[] = {'.',0};
3139 WCHAR buf
[MAX_PATH
], ch
;
3141 DWORD i
, beg
, len
, exp_len
;
3142 WIN32_FIND_DATAW fdata
;
3145 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3155 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3159 buf
[0] = toupperW(buf
[0]);
3160 if(len
>3 && buf
[len
-1] == '\\')
3163 for(beg
=3, i
=3; i
<=len
; i
++) {
3164 if(buf
[i
]!='\\' && buf
[i
])
3169 fh
= FindFirstFileW(buf
, &fdata
);
3170 if(fh
== INVALID_HANDLE_VALUE
)
3173 exp_len
= strlenW(fdata
.cFileName
);
3174 if(exp_len
== i
-beg
)
3175 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3181 *pbstrResult
= SysAllocString(buf
);
3183 return E_OUTOFMEMORY
;
3187 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3189 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3193 TRACE("%p %p\n", iface
, pbstrResult
);
3198 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3200 return E_OUTOFMEMORY
;
3202 if(!RtlGenRandom(&random
, sizeof(random
)))
3204 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3208 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3209 VARIANT_BOOL
*pfExists
)
3211 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3216 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3219 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3221 if (!ret
) return E_POINTER
;
3223 attrs
= GetFileAttributesW(path
);
3224 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3228 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3231 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3233 if (!ret
) return E_POINTER
;
3235 attrs
= GetFileAttributesW(path
);
3236 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3241 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3244 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3249 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3252 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3257 return E_INVALIDARG
;
3259 return create_file(FilePath
, ppfile
);
3262 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3267 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3274 return E_INVALIDARG
;
3276 attrs
= GetFileAttributesW(FolderPath
);
3277 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3278 return CTL_E_PATHNOTFOUND
;
3280 return create_folder(FolderPath
, folder
);
3283 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3284 SpecialFolderConst SpecialFolder
,
3287 WCHAR pathW
[MAX_PATH
];
3290 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3297 switch (SpecialFolder
)
3300 ret
= GetWindowsDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3303 ret
= GetSystemDirectoryW(pathW
, sizeof(pathW
)/sizeof(WCHAR
));
3305 case TemporaryFolder
:
3306 ret
= GetTempPathW(sizeof(pathW
)/sizeof(WCHAR
), pathW
);
3307 /* we don't want trailing backslash */
3308 if (ret
&& pathW
[ret
-1] == '\\')
3312 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3313 return E_INVALIDARG
;
3317 return HRESULT_FROM_WIN32(GetLastError());
3319 return create_folder(pathW
, folder
);
3322 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3324 WCHAR path
[MAX_PATH
];
3325 DWORD len
, name_len
;
3326 WIN32_FIND_DATAW ffd
;
3329 f
= FindFirstFileW(file
, &ffd
);
3330 if(f
== INVALID_HANDLE_VALUE
)
3331 return create_error(GetLastError());
3333 len
= get_parent_folder_name(file
, file_len
);
3334 if(len
+1 >= MAX_PATH
) {
3339 memcpy(path
, file
, len
*sizeof(WCHAR
));
3344 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3347 name_len
= strlenW(ffd
.cFileName
);
3348 if(len
+name_len
+1 >= MAX_PATH
) {
3352 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3354 TRACE("deleting %s\n", debugstr_w(path
));
3356 if(!DeleteFileW(path
)) {
3357 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3358 || !DeleteFileW(path
)) {
3360 return create_error(GetLastError());
3363 } while(FindNextFileW(f
, &ffd
));
3369 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3372 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3377 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3380 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3382 WCHAR path
[MAX_PATH
];
3383 DWORD len
, name_len
;
3384 WIN32_FIND_DATAW ffd
;
3388 f
= FindFirstFileW(folder
, &ffd
);
3389 if(f
== INVALID_HANDLE_VALUE
)
3390 return create_error(GetLastError());
3392 len
= get_parent_folder_name(folder
, folder_len
);
3393 if(len
+1 >= MAX_PATH
) {
3398 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3403 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3405 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3406 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3409 name_len
= strlenW(ffd
.cFileName
);
3410 if(len
+name_len
+3 >= MAX_PATH
) {
3414 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3415 path
[len
+name_len
] = '\\';
3416 path
[len
+name_len
+1] = '*';
3417 path
[len
+name_len
+2] = 0;
3419 hr
= delete_file(path
, len
+name_len
+2, force
);
3425 hr
= delete_folder(path
, len
+name_len
+2, force
);
3431 path
[len
+name_len
] = 0;
3432 TRACE("deleting %s\n", debugstr_w(path
));
3434 if(!RemoveDirectoryW(path
)) {
3436 return create_error(GetLastError());
3438 } while(FindNextFileW(f
, &ffd
));
3444 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3447 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3452 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3455 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3458 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3463 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3466 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3471 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3472 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3475 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3476 DWORD src_len
, dst_len
, name_len
;
3477 WIN32_FIND_DATAW ffd
;
3481 if(!source
[0] || !destination
[0])
3482 return E_INVALIDARG
;
3484 attrs
= GetFileAttributesW(destination
);
3485 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3486 attrs
= GetFileAttributesW(source
);
3487 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3488 return create_error(GetLastError());
3489 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3490 return CTL_E_FILENOTFOUND
;
3492 if(!CopyFileW(source
, destination
, !overwrite
))
3493 return create_error(GetLastError());
3497 f
= FindFirstFileW(source
, &ffd
);
3498 if(f
== INVALID_HANDLE_VALUE
)
3499 return CTL_E_FILENOTFOUND
;
3501 src_len
= get_parent_folder_name(source
, source_len
);
3502 if(src_len
+1 >= MAX_PATH
) {
3507 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3508 src_path
[src_len
++] = '\\';
3511 dst_len
= destination_len
;
3512 if(dst_len
+1 >= MAX_PATH
) {
3516 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3517 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3518 dst_path
[dst_len
++] = '\\';
3520 hr
= CTL_E_FILENOTFOUND
;
3522 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3525 name_len
= strlenW(ffd
.cFileName
);
3526 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3530 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3531 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3533 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3535 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3537 return create_error(GetLastError());
3541 } while(FindNextFileW(f
, &ffd
));
3547 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3548 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3550 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3552 if(!Source
|| !Destination
)
3555 return copy_file(Source
, SysStringLen(Source
), Destination
,
3556 SysStringLen(Destination
), OverWriteFiles
);
3559 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3560 DWORD destination_len
, VARIANT_BOOL overwrite
)
3562 DWORD tmp
, src_len
, dst_len
, name_len
;
3563 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3564 WIN32_FIND_DATAW ffd
;
3567 BOOL copied
= FALSE
;
3569 if(!source
[0] || !destination
[0])
3570 return E_INVALIDARG
;
3572 dst_len
= destination_len
;
3573 if(dst_len
+1 >= MAX_PATH
)
3575 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3577 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3578 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3579 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3580 if(!CreateDirectoryW(dst
, NULL
)) {
3581 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3582 tmp
= GetFileAttributesW(dst
);
3583 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3584 return CTL_E_FILEALREADYEXISTS
;
3586 return create_error(GetLastError());
3591 src_len
= source_len
;
3592 if(src_len
+2 >= MAX_PATH
)
3594 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3595 src
[src_len
++] = '\\';
3599 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3600 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3601 return create_error(GetLastError());
3603 f
= FindFirstFileW(src
, &ffd
);
3605 src_len
= get_parent_folder_name(source
, source_len
);
3606 if(src_len
+2 >= MAX_PATH
)
3608 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3610 src
[src_len
++] = '\\';
3612 f
= FindFirstFileW(source
, &ffd
);
3614 if(f
== INVALID_HANDLE_VALUE
)
3615 return CTL_E_PATHNOTFOUND
;
3617 dst
[dst_len
++] = '\\';
3621 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3623 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3624 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3627 name_len
= strlenW(ffd
.cFileName
);
3628 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3632 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3633 dst
[dst_len
+name_len
] = 0;
3634 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3635 src
[src_len
+name_len
] = '\\';
3636 src
[src_len
+name_len
+1] = '*';
3637 src
[src_len
+name_len
+2] = 0;
3639 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3641 if(!CreateDirectoryW(dst
, NULL
)) {
3642 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3643 tmp
= GetFileAttributesW(dst
);
3644 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3646 return CTL_E_FILEALREADYEXISTS
;
3651 return create_error(GetLastError());
3655 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3656 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3661 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3662 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3666 } while(FindNextFileW(f
, &ffd
));
3669 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3672 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3673 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3675 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3677 if(!Source
|| !Destination
)
3680 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3681 SysStringLen(Destination
), OverWriteFiles
);
3684 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3689 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3691 ret
= CreateDirectoryW(path
, NULL
);
3695 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3696 return HRESULT_FROM_WIN32(GetLastError());
3699 return create_folder(path
, folder
);
3702 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3703 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3704 ITextStream
**stream
)
3708 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3710 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3711 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3714 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3715 IOMode mode
, VARIANT_BOOL create
,
3716 Tristate format
, ITextStream
**stream
)
3720 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3721 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3723 if (format
== TristateUseDefault
) {
3724 FIXME("default format not handled, defaulting to unicode\n");
3725 format
= TristateTrue
;
3728 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3731 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3732 StandardStreamTypes StandardStreamType
,
3733 VARIANT_BOOL Unicode
,
3736 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3741 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3743 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3747 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3748 a
= (WORD
)( version
>> 48);
3749 b
= (WORD
)((version
>> 32) & 0xffff);
3750 c
= (WORD
)((version
>> 16) & 0xffff);
3751 d
= (WORD
)( version
& 0xffff);
3753 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3756 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3758 static const WCHAR rootW
[] = {'\\',0};
3759 VS_FIXEDFILEINFO
*info
;
3765 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3767 len
= GetFileVersionInfoSizeW(name
, NULL
);
3769 return HRESULT_FROM_WIN32(GetLastError());
3771 ptr
= heap_alloc(len
);
3772 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3775 return HRESULT_FROM_WIN32(GetLastError());
3778 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3782 return HRESULT_FROM_WIN32(GetLastError());
3785 get_versionstring(info
, ver
);
3788 *version
= SysAllocString(ver
);
3789 TRACE("version=%s\n", debugstr_w(ver
));
3794 static const struct IFileSystem3Vtbl filesys_vtbl
=
3796 filesys_QueryInterface
,
3799 filesys_GetTypeInfoCount
,
3800 filesys_GetTypeInfo
,
3801 filesys_GetIDsOfNames
,
3805 filesys_GetDriveName
,
3806 filesys_GetParentFolderName
,
3807 filesys_GetFileName
,
3808 filesys_GetBaseName
,
3809 filesys_GetExtensionName
,
3810 filesys_GetAbsolutePathName
,
3811 filesys_GetTempName
,
3812 filesys_DriveExists
,
3814 filesys_FolderExists
,
3818 filesys_GetSpecialFolder
,
3820 filesys_DeleteFolder
,
3825 filesys_CreateFolder
,
3826 filesys_CreateTextFile
,
3827 filesys_OpenTextFile
,
3828 filesys_GetStandardStream
,
3829 filesys_GetFileVersion
3832 static IFileSystem3 filesystem
= { &filesys_vtbl
};
3834 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3836 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3838 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);