2 * Copyright 2012 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "scrrun_private.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(scrrun
);
39 static const WCHAR bsW
[] = {'\\',0};
41 struct foldercollection
{
42 IFolderCollection IFolderCollection_iface
;
47 struct filecollection
{
48 IFileCollection IFileCollection_iface
;
53 struct drivecollection
{
54 IDriveCollection IDriveCollection_iface
;
65 struct foldercollection
*coll
;
70 struct filecollection
*coll
;
75 struct drivecollection
*coll
;
82 IEnumVARIANT IEnumVARIANT_iface
;
95 IFolder IFolder_iface
;
108 ITextStream ITextStream_iface
;
123 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
125 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
128 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
130 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
133 static inline struct file
*impl_from_IFile(IFile
*iface
)
135 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
138 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
140 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
143 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
145 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
148 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
150 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
153 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
155 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
158 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
160 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
163 static inline HRESULT
create_error(DWORD err
)
166 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
167 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
168 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
169 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
170 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
172 FIXME("Unsupported error code: %d\n", err
);
177 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
178 static HRESULT
create_file(BSTR
, IFile
**);
179 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
180 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
182 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
184 static const WCHAR dotdotW
[] = {'.','.',0};
185 static const WCHAR dotW
[] = {'.',0};
187 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
188 strcmpW(data
->cFileName
, dotdotW
) &&
189 strcmpW(data
->cFileName
, dotW
);
192 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
194 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
197 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
199 int len
= SysStringLen(path
);
200 WCHAR buffW
[MAX_PATH
];
202 strcpyW(buffW
, path
);
203 if (path
[len
-1] != '\\')
205 strcatW(buffW
, data
->cFileName
);
207 return SysAllocString(buffW
);
210 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
213 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
215 return This
->mode
== ForReading
;
218 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
220 struct textstream
*This
= impl_from_ITextStream(iface
);
222 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
224 if (IsEqualIID(riid
, &IID_ITextStream
) ||
225 IsEqualIID(riid
, &IID_IDispatch
) ||
226 IsEqualIID(riid
, &IID_IUnknown
))
229 ITextStream_AddRef(iface
);
234 return E_NOINTERFACE
;
237 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
239 struct textstream
*This
= impl_from_ITextStream(iface
);
240 ULONG ref
= InterlockedIncrement(&This
->ref
);
241 TRACE("(%p)->(%d)\n", This
, ref
);
245 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
247 struct textstream
*This
= impl_from_ITextStream(iface
);
248 ULONG ref
= InterlockedDecrement(&This
->ref
);
249 TRACE("(%p)->(%d)\n", This
, ref
);
253 CloseHandle(This
->file
);
260 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
262 struct textstream
*This
= impl_from_ITextStream(iface
);
263 TRACE("(%p)->(%p)\n", This
, pctinfo
);
268 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
269 LCID lcid
, ITypeInfo
**ppTInfo
)
271 struct textstream
*This
= impl_from_ITextStream(iface
);
272 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
273 return get_typeinfo(ITextStream_tid
, ppTInfo
);
276 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
277 LPOLESTR
*rgszNames
, UINT cNames
,
278 LCID lcid
, DISPID
*rgDispId
)
280 struct textstream
*This
= impl_from_ITextStream(iface
);
284 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
286 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
289 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
290 ITypeInfo_Release(typeinfo
);
296 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
297 REFIID riid
, LCID lcid
, WORD wFlags
,
298 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
299 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
301 struct textstream
*This
= impl_from_ITextStream(iface
);
305 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
306 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
308 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
311 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
312 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
313 ITypeInfo_Release(typeinfo
);
319 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
321 struct textstream
*This
= impl_from_ITextStream(iface
);
322 FIXME("(%p)->(%p): stub\n", This
, line
);
326 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
328 struct textstream
*This
= impl_from_ITextStream(iface
);
329 FIXME("(%p)->(%p): stub\n", This
, column
);
333 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
335 struct textstream
*This
= impl_from_ITextStream(iface
);
336 LARGE_INTEGER pos
, dist
;
338 TRACE("(%p)->(%p)\n", This
, eos
);
343 if (textstream_check_iomode(This
, IORead
)) {
345 return CTL_E_BADFILEMODE
;
349 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
352 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? VARIANT_TRUE
: VARIANT_FALSE
;
356 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
358 struct textstream
*This
= impl_from_ITextStream(iface
);
359 FIXME("(%p)->(%p): stub\n", This
, eol
);
363 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
365 struct textstream
*This
= impl_from_ITextStream(iface
);
366 FIXME("(%p)->(%p): stub\n", This
, text
);
368 if (textstream_check_iomode(This
, IORead
))
369 return CTL_E_BADFILEMODE
;
374 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
376 struct textstream
*This
= impl_from_ITextStream(iface
);
377 FIXME("(%p)->(%p): stub\n", This
, text
);
379 if (textstream_check_iomode(This
, IORead
))
380 return CTL_E_BADFILEMODE
;
385 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
387 struct textstream
*This
= impl_from_ITextStream(iface
);
388 FIXME("(%p)->(%p): stub\n", This
, text
);
390 if (textstream_check_iomode(This
, IORead
))
391 return CTL_E_BADFILEMODE
;
396 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
401 if (stream
->unicode
) {
402 if (stream
->first_write
) {
403 static const WCHAR utf16bom
= 0xfeff;
405 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
406 if (!ret
|| written
!= sizeof(utf16bom
))
407 return create_error(GetLastError());
408 stream
->first_write
= FALSE
;
411 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
412 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
414 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
418 buffA
= heap_alloc(len
);
420 return E_OUTOFMEMORY
;
422 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
423 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
424 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
430 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
432 struct textstream
*This
= impl_from_ITextStream(iface
);
434 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
436 if (textstream_check_iomode(This
, IOWrite
))
437 return CTL_E_BADFILEMODE
;
439 return textstream_writestr(This
, text
);
442 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
444 static const WCHAR crlfW
[] = {'\r','\n'};
445 static const char crlfA
[] = {'\r','\n'};
446 DWORD written
= 0, len
;
450 if (stream
->unicode
) {
459 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
460 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
463 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
465 struct textstream
*This
= impl_from_ITextStream(iface
);
468 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
470 if (textstream_check_iomode(This
, IOWrite
))
471 return CTL_E_BADFILEMODE
;
473 hr
= textstream_writestr(This
, text
);
475 hr
= textstream_writecrlf(This
);
479 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
481 struct textstream
*This
= impl_from_ITextStream(iface
);
482 FIXME("(%p)->(%d): stub\n", This
, lines
);
486 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
488 struct textstream
*This
= impl_from_ITextStream(iface
);
489 FIXME("(%p)->(%d): stub\n", This
, count
);
493 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
495 struct textstream
*This
= impl_from_ITextStream(iface
);
496 FIXME("(%p): stub\n", This
);
500 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
502 struct textstream
*This
= impl_from_ITextStream(iface
);
503 FIXME("(%p): stub\n", This
);
507 static const ITextStreamVtbl textstreamvtbl
= {
508 textstream_QueryInterface
,
511 textstream_GetTypeInfoCount
,
512 textstream_GetTypeInfo
,
513 textstream_GetIDsOfNames
,
516 textstream_get_Column
,
517 textstream_get_AtEndOfStream
,
518 textstream_get_AtEndOfLine
,
523 textstream_WriteLine
,
524 textstream_WriteBlankLines
,
530 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
532 struct textstream
*stream
;
535 /* map access mode */
539 access
= GENERIC_READ
;
542 access
= GENERIC_WRITE
;
545 access
= FILE_APPEND_DATA
;
551 stream
= heap_alloc(sizeof(struct textstream
));
552 if (!stream
) return E_OUTOFMEMORY
;
554 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
557 stream
->unicode
= unicode
;
558 stream
->first_write
= TRUE
;
560 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
561 if (stream
->file
== INVALID_HANDLE_VALUE
)
563 HRESULT hr
= create_error(GetLastError());
568 if (mode
== ForReading
)
569 GetFileSizeEx(stream
->file
, &stream
->size
);
571 stream
->size
.QuadPart
= 0;
573 *ret
= &stream
->ITextStream_iface
;
577 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
579 struct drive
*This
= impl_from_IDrive(iface
);
581 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
585 if (IsEqualIID( riid
, &IID_IDrive
) ||
586 IsEqualIID( riid
, &IID_IDispatch
) ||
587 IsEqualIID( riid
, &IID_IUnknown
))
590 IDrive_AddRef(iface
);
593 return E_NOINTERFACE
;
598 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
600 struct drive
*This
= impl_from_IDrive(iface
);
601 ULONG ref
= InterlockedIncrement(&This
->ref
);
602 TRACE("(%p)->(%d)\n", This
, ref
);
606 static ULONG WINAPI
drive_Release(IDrive
*iface
)
608 struct drive
*This
= impl_from_IDrive(iface
);
609 ULONG ref
= InterlockedDecrement(&This
->ref
);
610 TRACE("(%p)->(%d)\n", This
, ref
);
614 SysFreeString(This
->root
);
621 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
623 struct drive
*This
= impl_from_IDrive(iface
);
624 TRACE("(%p)->(%p)\n", This
, pctinfo
);
629 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
630 LCID lcid
, ITypeInfo
**ppTInfo
)
632 struct drive
*This
= impl_from_IDrive(iface
);
633 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
634 return get_typeinfo(IDrive_tid
, ppTInfo
);
637 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
638 LPOLESTR
*rgszNames
, UINT cNames
,
639 LCID lcid
, DISPID
*rgDispId
)
641 struct drive
*This
= impl_from_IDrive(iface
);
645 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
647 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
650 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
651 ITypeInfo_Release(typeinfo
);
657 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
658 REFIID riid
, LCID lcid
, WORD wFlags
,
659 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
660 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
662 struct drive
*This
= impl_from_IDrive(iface
);
666 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
667 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
669 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
672 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
673 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
674 ITypeInfo_Release(typeinfo
);
680 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
682 struct drive
*This
= impl_from_IDrive(iface
);
683 FIXME("(%p)->(%p): stub\n", This
, path
);
687 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
689 struct drive
*This
= impl_from_IDrive(iface
);
690 FIXME("(%p)->(%p): stub\n", This
, letter
);
694 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
696 struct drive
*This
= impl_from_IDrive(iface
);
697 FIXME("(%p)->(%p): stub\n", This
, share_name
);
701 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
703 struct drive
*This
= impl_from_IDrive(iface
);
705 TRACE("(%p)->(%p)\n", This
, type
);
707 switch (GetDriveTypeW(This
->root
))
709 case DRIVE_REMOVABLE
:
732 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
734 struct drive
*This
= impl_from_IDrive(iface
);
735 FIXME("(%p)->(%p): stub\n", This
, folder
);
739 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*avail
)
741 struct drive
*This
= impl_from_IDrive(iface
);
742 FIXME("(%p)->(%p): stub\n", This
, avail
);
746 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
748 struct drive
*This
= impl_from_IDrive(iface
);
749 FIXME("(%p)->(%p): stub\n", This
, v
);
753 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
755 struct drive
*This
= impl_from_IDrive(iface
);
756 FIXME("(%p)->(%p): stub\n", This
, v
);
760 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
762 struct drive
*This
= impl_from_IDrive(iface
);
763 FIXME("(%p)->(%p): stub\n", This
, name
);
767 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
769 struct drive
*This
= impl_from_IDrive(iface
);
770 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
774 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
776 struct drive
*This
= impl_from_IDrive(iface
);
777 FIXME("(%p)->(%p): stub\n", This
, fs
);
781 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
783 struct drive
*This
= impl_from_IDrive(iface
);
784 FIXME("(%p)->(%p): stub\n", This
, serial
);
788 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
790 struct drive
*This
= impl_from_IDrive(iface
);
791 FIXME("(%p)->(%p): stub\n", This
, ready
);
795 static const IDriveVtbl drivevtbl
= {
796 drive_QueryInterface
,
799 drive_GetTypeInfoCount
,
804 drive_get_DriveLetter
,
807 drive_get_RootFolder
,
808 drive_get_AvailableSpace
,
811 drive_get_VolumeName
,
812 drive_put_VolumeName
,
813 drive_get_FileSystem
,
814 drive_get_SerialNumber
,
818 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
824 This
= heap_alloc(sizeof(*This
));
825 if (!This
) return E_OUTOFMEMORY
;
827 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
829 This
->root
= SysAllocStringLen(NULL
, 3);
833 return E_OUTOFMEMORY
;
835 This
->root
[0] = letter
;
837 This
->root
[2] = '\\';
840 *drive
= &This
->IDrive_iface
;
844 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
846 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
848 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
852 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
853 IsEqualIID( riid
, &IID_IUnknown
))
856 IEnumVARIANT_AddRef(iface
);
859 return E_NOINTERFACE
;
864 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
866 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
867 ULONG ref
= InterlockedIncrement(&This
->ref
);
868 TRACE("(%p)->(%d)\n", This
, ref
);
872 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
874 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
875 ULONG ref
= InterlockedDecrement(&This
->ref
);
877 TRACE("(%p)->(%d)\n", This
, ref
);
881 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
882 FindClose(This
->data
.u
.foldercoll
.find
);
889 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
891 static const WCHAR allW
[] = {'*',0};
892 WCHAR pathW
[MAX_PATH
];
896 strcpyW(pathW
, path
);
897 len
= strlenW(pathW
);
898 if (pathW
[len
-1] != '\\')
900 strcatW(pathW
, allW
);
901 handle
= FindFirstFileW(pathW
, data
);
902 if (handle
== INVALID_HANDLE_VALUE
) return 0;
904 /* find first dir/file */
907 if (file
? is_file_data(data
) : is_dir_data(data
))
910 if (!FindNextFileW(handle
, data
))
919 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
921 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
922 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
923 WIN32_FIND_DATAW data
;
926 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
931 if (!celt
) return S_OK
;
935 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
936 if (!handle
) return S_FALSE
;
938 This
->data
.u
.foldercoll
.find
= handle
;
942 if (!FindNextFileW(handle
, &data
))
948 if (is_dir_data(&data
))
954 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
955 hr
= create_folder(str
, &folder
);
957 if (FAILED(hr
)) return hr
;
959 V_VT(&var
[count
]) = VT_DISPATCH
;
960 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
963 if (count
>= celt
) break;
965 } while (FindNextFileW(handle
, &data
));
970 return (count
< celt
) ? S_FALSE
: S_OK
;
973 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
975 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
976 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
977 WIN32_FIND_DATAW data
;
979 TRACE("(%p)->(%d)\n", This
, celt
);
981 if (!celt
) return S_OK
;
985 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
986 if (!handle
) return S_FALSE
;
988 This
->data
.u
.foldercoll
.find
= handle
;
992 if (!FindNextFileW(handle
, &data
))
998 if (is_dir_data(&data
))
1002 } while (FindNextFileW(handle
, &data
));
1004 return celt
? S_FALSE
: S_OK
;
1007 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1009 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1011 TRACE("(%p)\n", This
);
1013 FindClose(This
->data
.u
.foldercoll
.find
);
1014 This
->data
.u
.foldercoll
.find
= NULL
;
1019 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1021 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1022 TRACE("(%p)->(%p)\n", This
, pclone
);
1023 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1026 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1027 enumvariant_QueryInterface
,
1029 foldercoll_enumvariant_Release
,
1030 foldercoll_enumvariant_Next
,
1031 foldercoll_enumvariant_Skip
,
1032 foldercoll_enumvariant_Reset
,
1033 foldercoll_enumvariant_Clone
1036 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1038 struct enumvariant
*This
;
1042 This
= heap_alloc(sizeof(*This
));
1043 if (!This
) return E_OUTOFMEMORY
;
1045 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1047 This
->data
.u
.foldercoll
.find
= NULL
;
1048 This
->data
.u
.foldercoll
.coll
= collection
;
1049 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1051 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1056 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1058 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1059 ULONG ref
= InterlockedDecrement(&This
->ref
);
1061 TRACE("(%p)->(%d)\n", This
, ref
);
1065 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1066 FindClose(This
->data
.u
.filecoll
.find
);
1073 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1075 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1076 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1077 WIN32_FIND_DATAW data
;
1080 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1085 if (!celt
) return S_OK
;
1089 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1090 if (!handle
) return S_FALSE
;
1091 This
->data
.u
.filecoll
.find
= handle
;
1093 else if (!FindNextFileW(handle
, &data
))
1098 if (is_file_data(&data
))
1104 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1105 hr
= create_file(str
, &file
);
1107 if (FAILED(hr
)) return hr
;
1109 V_VT(&var
[count
]) = VT_DISPATCH
;
1110 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1111 if (++count
>= celt
) break;
1113 } while (FindNextFileW(handle
, &data
));
1118 return (count
< celt
) ? S_FALSE
: S_OK
;
1121 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1123 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1124 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1125 WIN32_FIND_DATAW data
;
1127 TRACE("(%p)->(%d)\n", This
, celt
);
1129 if (!celt
) return S_OK
;
1133 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1134 if (!handle
) return S_FALSE
;
1135 This
->data
.u
.filecoll
.find
= handle
;
1137 else if (!FindNextFileW(handle
, &data
))
1142 if (is_file_data(&data
))
1144 } while (celt
&& FindNextFileW(handle
, &data
));
1146 return celt
? S_FALSE
: S_OK
;
1149 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1151 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1153 TRACE("(%p)\n", This
);
1155 FindClose(This
->data
.u
.filecoll
.find
);
1156 This
->data
.u
.filecoll
.find
= NULL
;
1161 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1163 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1164 TRACE("(%p)->(%p)\n", This
, pclone
);
1165 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1168 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1169 enumvariant_QueryInterface
,
1171 filecoll_enumvariant_Release
,
1172 filecoll_enumvariant_Next
,
1173 filecoll_enumvariant_Skip
,
1174 filecoll_enumvariant_Reset
,
1175 filecoll_enumvariant_Clone
1178 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1180 struct enumvariant
*This
;
1184 This
= heap_alloc(sizeof(*This
));
1185 if (!This
) return E_OUTOFMEMORY
;
1187 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1189 This
->data
.u
.filecoll
.find
= NULL
;
1190 This
->data
.u
.filecoll
.coll
= collection
;
1191 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1193 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1198 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1200 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1201 ULONG ref
= InterlockedDecrement(&This
->ref
);
1203 TRACE("(%p)->(%d)\n", This
, ref
);
1207 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1214 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1216 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1219 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1221 penum
->data
.u
.drivecoll
.cur
= i
;
1228 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1230 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1233 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1238 if (!celt
) return S_OK
;
1240 while (find_next_drive(This
) == S_OK
)
1245 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1246 if (FAILED(hr
)) return hr
;
1248 V_VT(&var
[count
]) = VT_DISPATCH
;
1249 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1251 if (++count
>= celt
) break;
1257 return (count
< celt
) ? S_FALSE
: S_OK
;
1260 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1262 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1264 TRACE("(%p)->(%d)\n", This
, celt
);
1266 if (!celt
) return S_OK
;
1268 while (celt
&& find_next_drive(This
) == S_OK
)
1271 return celt
? S_FALSE
: S_OK
;
1274 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1276 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1278 TRACE("(%p)\n", This
);
1280 This
->data
.u
.drivecoll
.cur
= -1;
1284 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1286 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1287 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1291 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1292 enumvariant_QueryInterface
,
1294 drivecoll_enumvariant_Release
,
1295 drivecoll_enumvariant_Next
,
1296 drivecoll_enumvariant_Skip
,
1297 drivecoll_enumvariant_Reset
,
1298 drivecoll_enumvariant_Clone
1301 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1303 struct enumvariant
*This
;
1307 This
= heap_alloc(sizeof(*This
));
1308 if (!This
) return E_OUTOFMEMORY
;
1310 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1312 This
->data
.u
.drivecoll
.coll
= collection
;
1313 This
->data
.u
.drivecoll
.cur
= -1;
1314 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1316 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1321 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1323 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1325 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1329 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1330 IsEqualIID( riid
, &IID_IDispatch
) ||
1331 IsEqualIID( riid
, &IID_IUnknown
))
1334 IFolderCollection_AddRef(iface
);
1337 return E_NOINTERFACE
;
1342 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1344 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1345 ULONG ref
= InterlockedIncrement(&This
->ref
);
1346 TRACE("(%p)->(%d)\n", This
, ref
);
1350 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1352 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1353 ULONG ref
= InterlockedDecrement(&This
->ref
);
1354 TRACE("(%p)->(%d)\n", This
, ref
);
1358 SysFreeString(This
->path
);
1365 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1367 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1368 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1373 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1374 LCID lcid
, ITypeInfo
**ppTInfo
)
1376 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1377 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1378 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1381 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1382 LPOLESTR
*rgszNames
, UINT cNames
,
1383 LCID lcid
, DISPID
*rgDispId
)
1385 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1386 ITypeInfo
*typeinfo
;
1389 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1391 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1394 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1395 ITypeInfo_Release(typeinfo
);
1401 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1402 REFIID riid
, LCID lcid
, WORD wFlags
,
1403 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1404 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1406 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1407 ITypeInfo
*typeinfo
;
1410 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1411 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1413 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1416 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1417 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1418 ITypeInfo_Release(typeinfo
);
1424 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1426 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1427 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1431 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1433 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1434 FIXME("(%p)->(%p): stub\n", This
, folder
);
1438 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1440 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1442 TRACE("(%p)->(%p)\n", This
, newenum
);
1447 return create_foldercoll_enum(This
, newenum
);
1450 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1452 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1453 static const WCHAR allW
[] = {'\\','*',0};
1454 WIN32_FIND_DATAW data
;
1455 WCHAR pathW
[MAX_PATH
];
1458 TRACE("(%p)->(%p)\n", This
, count
);
1465 strcpyW(pathW
, This
->path
);
1466 strcatW(pathW
, allW
);
1467 handle
= FindFirstFileW(pathW
, &data
);
1468 if (handle
== INVALID_HANDLE_VALUE
)
1469 return HRESULT_FROM_WIN32(GetLastError());
1473 if (is_dir_data(&data
))
1475 } while (FindNextFileW(handle
, &data
));
1481 static const IFolderCollectionVtbl foldercollvtbl
= {
1482 foldercoll_QueryInterface
,
1485 foldercoll_GetTypeInfoCount
,
1486 foldercoll_GetTypeInfo
,
1487 foldercoll_GetIDsOfNames
,
1490 foldercoll_get_Item
,
1491 foldercoll_get__NewEnum
,
1492 foldercoll_get_Count
1495 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1497 struct foldercollection
*This
;
1501 This
= heap_alloc(sizeof(struct foldercollection
));
1502 if (!This
) return E_OUTOFMEMORY
;
1504 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1506 This
->path
= SysAllocString(path
);
1510 return E_OUTOFMEMORY
;
1513 *folders
= &This
->IFolderCollection_iface
;
1518 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1520 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1522 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1526 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1527 IsEqualIID( riid
, &IID_IDispatch
) ||
1528 IsEqualIID( riid
, &IID_IUnknown
))
1531 IFileCollection_AddRef(iface
);
1534 return E_NOINTERFACE
;
1539 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1541 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1542 ULONG ref
= InterlockedIncrement(&This
->ref
);
1543 TRACE("(%p)->(%d)\n", This
, ref
);
1547 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1549 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1550 ULONG ref
= InterlockedDecrement(&This
->ref
);
1551 TRACE("(%p)->(%d)\n", This
, ref
);
1555 SysFreeString(This
->path
);
1562 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1564 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1565 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1570 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1571 LCID lcid
, ITypeInfo
**ppTInfo
)
1573 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1574 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1575 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1578 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1579 LPOLESTR
*rgszNames
, UINT cNames
,
1580 LCID lcid
, DISPID
*rgDispId
)
1582 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1583 ITypeInfo
*typeinfo
;
1586 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1588 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1591 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1592 ITypeInfo_Release(typeinfo
);
1598 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1599 REFIID riid
, LCID lcid
, WORD wFlags
,
1600 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1601 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1603 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1604 ITypeInfo
*typeinfo
;
1607 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1608 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1610 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1613 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1614 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1615 ITypeInfo_Release(typeinfo
);
1621 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1623 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1624 FIXME("(%p)->(%p)\n", This
, file
);
1628 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1630 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1632 TRACE("(%p)->(%p)\n", This
, ppenum
);
1637 return create_filecoll_enum(This
, ppenum
);
1640 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1642 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1643 FIXME("(%p)->(%p)\n", This
, count
);
1647 static const IFileCollectionVtbl filecollectionvtbl
= {
1648 filecoll_QueryInterface
,
1651 filecoll_GetTypeInfoCount
,
1652 filecoll_GetTypeInfo
,
1653 filecoll_GetIDsOfNames
,
1656 filecoll_get__NewEnum
,
1660 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1662 struct filecollection
*This
;
1666 This
= heap_alloc(sizeof(*This
));
1667 if (!This
) return E_OUTOFMEMORY
;
1669 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1671 This
->path
= SysAllocString(path
);
1675 return E_OUTOFMEMORY
;
1678 *files
= &This
->IFileCollection_iface
;
1682 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1684 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1686 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1690 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1691 IsEqualIID( riid
, &IID_IDispatch
) ||
1692 IsEqualIID( riid
, &IID_IUnknown
))
1695 IDriveCollection_AddRef(iface
);
1698 return E_NOINTERFACE
;
1703 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
1705 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1706 ULONG ref
= InterlockedIncrement(&This
->ref
);
1707 TRACE("(%p)->(%d)\n", This
, ref
);
1711 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
1713 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1714 ULONG ref
= InterlockedDecrement(&This
->ref
);
1715 TRACE("(%p)->(%d)\n", This
, ref
);
1723 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
1725 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1726 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1731 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
1732 LCID lcid
, ITypeInfo
**ppTInfo
)
1734 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1735 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1736 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
1739 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
1740 LPOLESTR
*rgszNames
, UINT cNames
,
1741 LCID lcid
, DISPID
*rgDispId
)
1743 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1744 ITypeInfo
*typeinfo
;
1747 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1749 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
1752 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1753 ITypeInfo_Release(typeinfo
);
1759 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
1760 REFIID riid
, LCID lcid
, WORD wFlags
,
1761 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1762 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1764 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1765 ITypeInfo
*typeinfo
;
1768 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1769 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1771 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
1774 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1775 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1776 ITypeInfo_Release(typeinfo
);
1782 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
1784 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1785 FIXME("(%p)->(%p): stub\n", This
, drive
);
1789 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
1791 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1793 TRACE("(%p)->(%p)\n", This
, ppenum
);
1798 return create_drivecoll_enum(This
, ppenum
);
1801 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
1803 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1805 TRACE("(%p)->(%p)\n", This
, count
);
1807 if (!count
) return E_POINTER
;
1809 *count
= This
->count
;
1813 static const IDriveCollectionVtbl drivecollectionvtbl
= {
1814 drivecoll_QueryInterface
,
1817 drivecoll_GetTypeInfoCount
,
1818 drivecoll_GetTypeInfo
,
1819 drivecoll_GetIDsOfNames
,
1822 drivecoll_get__NewEnum
,
1826 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
1828 struct drivecollection
*This
;
1833 This
= heap_alloc(sizeof(*This
));
1834 if (!This
) return E_OUTOFMEMORY
;
1836 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
1838 This
->drives
= mask
= GetLogicalDrives();
1839 /* count set bits */
1840 for (This
->count
= 0; mask
; This
->count
++)
1843 *drives
= &This
->IDriveCollection_iface
;
1847 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
1849 struct folder
*This
= impl_from_IFolder(iface
);
1851 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1855 if (IsEqualIID( riid
, &IID_IFolder
) ||
1856 IsEqualIID( riid
, &IID_IDispatch
) ||
1857 IsEqualIID( riid
, &IID_IUnknown
))
1860 IFolder_AddRef(iface
);
1863 return E_NOINTERFACE
;
1868 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
1870 struct folder
*This
= impl_from_IFolder(iface
);
1871 ULONG ref
= InterlockedIncrement(&This
->ref
);
1872 TRACE("(%p)->(%d)\n", This
, ref
);
1876 static ULONG WINAPI
folder_Release(IFolder
*iface
)
1878 struct folder
*This
= impl_from_IFolder(iface
);
1879 ULONG ref
= InterlockedDecrement(&This
->ref
);
1880 TRACE("(%p)->(%d)\n", This
, ref
);
1884 SysFreeString(This
->path
);
1891 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
1893 struct folder
*This
= impl_from_IFolder(iface
);
1894 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1899 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
1900 LCID lcid
, ITypeInfo
**ppTInfo
)
1902 struct folder
*This
= impl_from_IFolder(iface
);
1903 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1904 return get_typeinfo(IFolder_tid
, ppTInfo
);
1907 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
1908 LPOLESTR
*rgszNames
, UINT cNames
,
1909 LCID lcid
, DISPID
*rgDispId
)
1911 struct folder
*This
= impl_from_IFolder(iface
);
1912 ITypeInfo
*typeinfo
;
1915 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1917 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
1920 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1921 ITypeInfo_Release(typeinfo
);
1927 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
1928 REFIID riid
, LCID lcid
, WORD wFlags
,
1929 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1930 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1932 struct folder
*This
= impl_from_IFolder(iface
);
1933 ITypeInfo
*typeinfo
;
1936 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1937 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1939 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
1942 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1943 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1944 ITypeInfo_Release(typeinfo
);
1950 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
1952 struct folder
*This
= impl_from_IFolder(iface
);
1954 TRACE("(%p)->(%p)\n", This
, path
);
1959 *path
= SysAllocString(This
->path
);
1960 return *path
? S_OK
: E_OUTOFMEMORY
;
1963 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
1965 struct folder
*This
= impl_from_IFolder(iface
);
1968 TRACE("(%p)->(%p)\n", This
, name
);
1975 ptr
= strrchrW(This
->path
, '\\');
1978 *name
= SysAllocString(ptr
+1);
1979 TRACE("%s\n", debugstr_w(*name
));
1980 if (!*name
) return E_OUTOFMEMORY
;
1988 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
1990 struct folder
*This
= impl_from_IFolder(iface
);
1991 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1995 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
1997 struct folder
*This
= impl_from_IFolder(iface
);
1998 FIXME("(%p)->(%p): stub\n", This
, path
);
2002 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2004 struct folder
*This
= impl_from_IFolder(iface
);
2005 FIXME("(%p)->(%p): stub\n", This
, name
);
2009 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2011 struct folder
*This
= impl_from_IFolder(iface
);
2012 FIXME("(%p)->(%p): stub\n", This
, drive
);
2016 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2018 struct folder
*This
= impl_from_IFolder(iface
);
2019 FIXME("(%p)->(%p): stub\n", This
, parent
);
2023 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2025 struct folder
*This
= impl_from_IFolder(iface
);
2026 FIXME("(%p)->(%p): stub\n", This
, attr
);
2030 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2032 struct folder
*This
= impl_from_IFolder(iface
);
2033 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2037 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2039 struct folder
*This
= impl_from_IFolder(iface
);
2040 FIXME("(%p)->(%p): stub\n", This
, date
);
2044 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2046 struct folder
*This
= impl_from_IFolder(iface
);
2047 FIXME("(%p)->(%p): stub\n", This
, date
);
2051 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2053 struct folder
*This
= impl_from_IFolder(iface
);
2054 FIXME("(%p)->(%p): stub\n", This
, date
);
2058 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2060 struct folder
*This
= impl_from_IFolder(iface
);
2061 FIXME("(%p)->(%p): stub\n", This
, type
);
2065 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2067 struct folder
*This
= impl_from_IFolder(iface
);
2068 FIXME("(%p)->(%x): stub\n", This
, force
);
2072 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2074 struct folder
*This
= impl_from_IFolder(iface
);
2075 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2079 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2081 struct folder
*This
= impl_from_IFolder(iface
);
2082 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2086 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2088 struct folder
*This
= impl_from_IFolder(iface
);
2089 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2093 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2095 struct folder
*This
= impl_from_IFolder(iface
);
2096 FIXME("(%p)->(%p): stub\n", This
, size
);
2100 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2102 struct folder
*This
= impl_from_IFolder(iface
);
2104 TRACE("(%p)->(%p)\n", This
, folders
);
2109 return create_foldercoll(This
->path
, folders
);
2112 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2114 struct folder
*This
= impl_from_IFolder(iface
);
2116 TRACE("(%p)->(%p)\n", This
, files
);
2121 return create_filecoll(This
->path
, files
);
2124 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2125 VARIANT_BOOL unicode
, ITextStream
**stream
)
2127 struct folder
*This
= impl_from_IFolder(iface
);
2128 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2132 static const IFolderVtbl foldervtbl
= {
2133 folder_QueryInterface
,
2136 folder_GetTypeInfoCount
,
2138 folder_GetIDsOfNames
,
2143 folder_get_ShortPath
,
2144 folder_get_ShortName
,
2146 folder_get_ParentFolder
,
2147 folder_get_Attributes
,
2148 folder_put_Attributes
,
2149 folder_get_DateCreated
,
2150 folder_get_DateLastModified
,
2151 folder_get_DateLastAccessed
,
2156 folder_get_IsRootFolder
,
2158 folder_get_SubFolders
,
2160 folder_CreateTextFile
2163 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2165 struct folder
*This
;
2169 TRACE("%s\n", debugstr_w(path
));
2171 This
= heap_alloc(sizeof(struct folder
));
2172 if (!This
) return E_OUTOFMEMORY
;
2174 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2176 This
->path
= SysAllocString(path
);
2180 return E_OUTOFMEMORY
;
2183 *folder
= &This
->IFolder_iface
;
2188 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2190 struct file
*This
= impl_from_IFile(iface
);
2192 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2194 if (IsEqualIID(riid
, &IID_IFile
) ||
2195 IsEqualIID(riid
, &IID_IDispatch
) ||
2196 IsEqualIID(riid
, &IID_IUnknown
))
2199 IFile_AddRef(iface
);
2204 return E_NOINTERFACE
;
2207 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2209 struct file
*This
= impl_from_IFile(iface
);
2210 LONG ref
= InterlockedIncrement(&This
->ref
);
2212 TRACE("(%p) ref=%d\n", This
, ref
);
2217 static ULONG WINAPI
file_Release(IFile
*iface
)
2219 struct file
*This
= impl_from_IFile(iface
);
2220 LONG ref
= InterlockedDecrement(&This
->ref
);
2222 TRACE("(%p) ref=%d\n", This
, ref
);
2226 heap_free(This
->path
);
2233 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2235 struct file
*This
= impl_from_IFile(iface
);
2237 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2243 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2244 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2246 struct file
*This
= impl_from_IFile(iface
);
2248 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2250 return get_typeinfo(IFile_tid
, ppTInfo
);
2253 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2254 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2256 struct file
*This
= impl_from_IFile(iface
);
2257 ITypeInfo
*typeinfo
;
2260 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2261 rgszNames
, cNames
, lcid
, rgDispId
);
2263 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2265 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2266 ITypeInfo_Release(typeinfo
);
2271 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2273 struct file
*This
= impl_from_IFile(iface
);
2274 ITypeInfo
*typeinfo
;
2277 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2278 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2280 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2283 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2284 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2285 ITypeInfo_Release(typeinfo
);
2290 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
2292 struct file
*This
= impl_from_IFile(iface
);
2293 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2297 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2299 struct file
*This
= impl_from_IFile(iface
);
2302 TRACE("(%p)->(%p)\n", This
, name
);
2309 ptr
= strrchrW(This
->path
, '\\');
2312 *name
= SysAllocString(ptr
+1);
2313 TRACE("%s\n", debugstr_w(*name
));
2314 if (!*name
) return E_OUTOFMEMORY
;
2322 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2324 struct file
*This
= impl_from_IFile(iface
);
2325 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2329 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2331 struct file
*This
= impl_from_IFile(iface
);
2332 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2336 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2338 struct file
*This
= impl_from_IFile(iface
);
2339 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2343 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2345 struct file
*This
= impl_from_IFile(iface
);
2346 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2350 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2352 struct file
*This
= impl_from_IFile(iface
);
2353 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2357 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2359 struct file
*This
= impl_from_IFile(iface
);
2362 TRACE("(%p)->(%p)\n", This
, pfa
);
2367 fa
= GetFileAttributesW(This
->path
);
2368 if(fa
== INVALID_FILE_ATTRIBUTES
)
2369 return create_error(GetLastError());
2371 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2372 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2373 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2377 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2379 struct file
*This
= impl_from_IFile(iface
);
2380 FIXME("(%p)->(%x)\n", This
, pfa
);
2384 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2386 struct file
*This
= impl_from_IFile(iface
);
2387 FIXME("(%p)->(%p)\n", This
, pdate
);
2391 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2393 struct file
*This
= impl_from_IFile(iface
);
2394 FIXME("(%p)->(%p)\n", This
, pdate
);
2398 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2400 struct file
*This
= impl_from_IFile(iface
);
2401 FIXME("(%p)->(%p)\n", This
, pdate
);
2405 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2407 struct file
*This
= impl_from_IFile(iface
);
2408 WIN32_FIND_DATAW fd
;
2411 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2416 f
= FindFirstFileW(This
->path
, &fd
);
2417 if(f
== INVALID_HANDLE_VALUE
)
2418 return create_error(GetLastError());
2421 if(fd
.nFileSizeHigh
|| fd
.nFileSizeLow
>INT_MAX
) {
2422 V_VT(pvarSize
) = VT_R8
;
2423 V_R8(pvarSize
) = ((ULONGLONG
)fd
.nFileSizeHigh
<<32) + fd
.nFileSizeLow
;
2425 V_VT(pvarSize
) = VT_I4
;
2426 V_I4(pvarSize
) = fd
.nFileSizeLow
;
2431 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2433 struct file
*This
= impl_from_IFile(iface
);
2434 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2438 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2440 struct file
*This
= impl_from_IFile(iface
);
2441 FIXME("(%p)->(%x)\n", This
, Force
);
2445 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2447 struct file
*This
= impl_from_IFile(iface
);
2448 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2452 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2454 struct file
*This
= impl_from_IFile(iface
);
2455 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2459 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode IOMode
, Tristate Format
, ITextStream
**ppts
)
2461 struct file
*This
= impl_from_IFile(iface
);
2462 FIXME("(%p)->(%x %x %p)\n", This
, IOMode
, Format
, ppts
);
2466 static const IFileVtbl file_vtbl
= {
2467 file_QueryInterface
,
2470 file_GetTypeInfoCount
,
2480 file_get_ParentFolder
,
2481 file_get_Attributes
,
2482 file_put_Attributes
,
2483 file_get_DateCreated
,
2484 file_get_DateLastModified
,
2485 file_get_DateLastAccessed
,
2491 file_OpenAsTextStream
2494 static HRESULT
create_file(BSTR path
, IFile
**file
)
2501 f
= heap_alloc(sizeof(struct file
));
2503 return E_OUTOFMEMORY
;
2505 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2508 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2514 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2517 return E_OUTOFMEMORY
;
2520 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2526 if(path
[len
-1]=='/' || path
[len
-1]=='\\')
2529 attrs
= GetFileAttributesW(f
->path
);
2530 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2531 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2534 return create_error(GetLastError());
2537 *file
= &f
->IFile_iface
;
2541 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2543 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2545 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2546 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2547 IsEqualGUID( riid
, &IID_IDispatch
) ||
2548 IsEqualGUID( riid
, &IID_IUnknown
) )
2552 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2554 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2556 return E_NOINTERFACE
;
2558 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2560 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2562 return E_NOINTERFACE
;
2566 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2567 return E_NOINTERFACE
;
2570 IFileSystem3_AddRef(iface
);
2575 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2577 TRACE("%p\n", iface
);
2582 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2584 TRACE("%p\n", iface
);
2589 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2591 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2597 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2598 LCID lcid
, ITypeInfo
**ppTInfo
)
2600 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2601 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2604 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2605 LPOLESTR
*rgszNames
, UINT cNames
,
2606 LCID lcid
, DISPID
*rgDispId
)
2608 ITypeInfo
*typeinfo
;
2611 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2613 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2616 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2617 ITypeInfo_Release(typeinfo
);
2623 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2624 REFIID riid
, LCID lcid
, WORD wFlags
,
2625 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2626 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2628 ITypeInfo
*typeinfo
;
2631 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2632 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2634 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2637 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2638 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2639 ITypeInfo_Release(typeinfo
);
2645 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2647 TRACE("%p %p\n", iface
, ppdrives
);
2648 return create_drivecoll(ppdrives
);
2651 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2652 BSTR Name
, BSTR
*Result
)
2656 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2658 if (!Result
) return E_POINTER
;
2662 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
2664 /* if both parts have backslashes strip one from Path */
2665 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
2669 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2677 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
2679 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
2683 if (Path
[path_len
-1] != ':')
2690 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2698 else if (Path
|| Name
)
2699 ret
= SysAllocString(Path
? Path
: Name
);
2701 ret
= SysAllocStringLen(NULL
, 0);
2703 if (!ret
) return E_OUTOFMEMORY
;
2709 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR Path
,
2712 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2717 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
2724 for(i
=len
-1; i
>=0; i
--)
2725 if(path
[i
]!='/' && path
[i
]!='\\')
2729 if(path
[i
]=='/' || path
[i
]=='\\')
2733 if(path
[i
]!='/' && path
[i
]!='\\')
2739 if(path
[i
]==':' && i
==1)
2744 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
2749 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2754 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
2756 *pbstrResult
= NULL
;
2760 *pbstrResult
= SysAllocStringLen(Path
, len
);
2762 return E_OUTOFMEMORY
;
2766 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
2771 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2777 *pbstrResult
= NULL
;
2781 for(end
=strlenW(Path
)-1; end
>=0; end
--)
2782 if(Path
[end
]!='/' && Path
[end
]!='\\')
2785 for(i
=end
; i
>=0; i
--)
2786 if(Path
[i
]=='/' || Path
[i
]=='\\')
2790 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
2791 *pbstrResult
= NULL
;
2795 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
2797 return E_OUTOFMEMORY
;
2801 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
2806 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2812 *pbstrResult
= NULL
;
2816 for(end
=strlenW(Path
)-1; end
>=0; end
--)
2817 if(Path
[end
]!='/' && Path
[end
]!='\\')
2820 for(i
=end
; i
>=0; i
--) {
2821 if(Path
[i
]=='.' && Path
[end
+1]!='.')
2823 if(Path
[i
]=='/' || Path
[i
]=='\\')
2828 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
2829 *pbstrResult
= NULL
;
2833 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
2835 return E_OUTOFMEMORY
;
2839 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
2842 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2847 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
2850 static const WCHAR cur_path
[] = {'.',0};
2852 WCHAR buf
[MAX_PATH
], ch
;
2854 DWORD i
, beg
, len
, exp_len
;
2855 WIN32_FIND_DATAW fdata
;
2858 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2868 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
2872 buf
[0] = toupperW(buf
[0]);
2873 if(len
>3 && buf
[len
-1] == '\\')
2876 for(beg
=3, i
=3; i
<=len
; i
++) {
2877 if(buf
[i
]!='\\' && buf
[i
])
2882 fh
= FindFirstFileW(buf
, &fdata
);
2883 if(fh
== INVALID_HANDLE_VALUE
)
2886 exp_len
= strlenW(fdata
.cFileName
);
2887 if(exp_len
== i
-beg
)
2888 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
2894 *pbstrResult
= SysAllocString(buf
);
2896 return E_OUTOFMEMORY
;
2900 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
2902 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
2906 TRACE("%p %p\n", iface
, pbstrResult
);
2911 *pbstrResult
= SysAllocStringLen(NULL
, 12);
2913 return E_OUTOFMEMORY
;
2915 if(!RtlGenRandom(&random
, sizeof(random
)))
2917 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
2921 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
2922 VARIANT_BOOL
*pfExists
)
2924 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
2929 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
2932 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
2934 if (!ret
) return E_POINTER
;
2936 attrs
= GetFileAttributesW(path
);
2937 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2941 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
2944 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
2946 if (!ret
) return E_POINTER
;
2948 attrs
= GetFileAttributesW(path
);
2949 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2954 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
2957 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
2962 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
2965 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
2970 return E_INVALIDARG
;
2972 return create_file(FilePath
, ppfile
);
2975 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
2980 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
2987 return E_INVALIDARG
;
2989 attrs
= GetFileAttributesW(FolderPath
);
2990 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
2991 return CTL_E_PATHNOTFOUND
;
2993 return create_folder(FolderPath
, folder
);
2996 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
2997 SpecialFolderConst SpecialFolder
,
3000 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
3005 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3007 WCHAR path
[MAX_PATH
];
3008 DWORD len
, name_len
;
3009 WIN32_FIND_DATAW ffd
;
3012 f
= FindFirstFileW(file
, &ffd
);
3013 if(f
== INVALID_HANDLE_VALUE
)
3014 return create_error(GetLastError());
3016 len
= get_parent_folder_name(file
, file_len
);
3017 if(len
+1 >= MAX_PATH
) {
3022 memcpy(path
, file
, len
*sizeof(WCHAR
));
3027 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3030 name_len
= strlenW(ffd
.cFileName
);
3031 if(len
+name_len
+1 >= MAX_PATH
) {
3035 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3037 TRACE("deleting %s\n", debugstr_w(path
));
3039 if(!DeleteFileW(path
)) {
3040 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3041 || !DeleteFileW(path
)) {
3043 return create_error(GetLastError());
3046 } while(FindNextFileW(f
, &ffd
));
3052 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3055 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3060 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3063 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3065 WCHAR path
[MAX_PATH
];
3066 DWORD len
, name_len
;
3067 WIN32_FIND_DATAW ffd
;
3071 f
= FindFirstFileW(folder
, &ffd
);
3072 if(f
== INVALID_HANDLE_VALUE
)
3073 return create_error(GetLastError());
3075 len
= get_parent_folder_name(folder
, folder_len
);
3076 if(len
+1 >= MAX_PATH
) {
3081 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3086 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3088 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3089 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3092 name_len
= strlenW(ffd
.cFileName
);
3093 if(len
+name_len
+3 >= MAX_PATH
) {
3097 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3098 path
[len
+name_len
] = '\\';
3099 path
[len
+name_len
+1] = '*';
3100 path
[len
+name_len
+2] = 0;
3102 hr
= delete_file(path
, len
+name_len
+2, force
);
3108 hr
= delete_folder(path
, len
+name_len
+2, force
);
3114 path
[len
+name_len
] = 0;
3115 TRACE("deleting %s\n", debugstr_w(path
));
3117 if(!RemoveDirectoryW(path
)) {
3119 return create_error(GetLastError());
3121 } while(FindNextFileW(f
, &ffd
));
3127 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3130 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3135 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3138 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3141 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3146 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3149 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3154 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3155 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3158 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3159 DWORD src_len
, dst_len
, name_len
;
3160 WIN32_FIND_DATAW ffd
;
3164 if(!source
[0] || !destination
[0])
3165 return E_INVALIDARG
;
3167 attrs
= GetFileAttributesW(destination
);
3168 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3169 attrs
= GetFileAttributesW(source
);
3170 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3171 return create_error(GetLastError());
3172 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3173 return CTL_E_FILENOTFOUND
;
3175 if(!CopyFileW(source
, destination
, !overwrite
))
3176 return create_error(GetLastError());
3180 f
= FindFirstFileW(source
, &ffd
);
3181 if(f
== INVALID_HANDLE_VALUE
)
3182 return CTL_E_FILENOTFOUND
;
3184 src_len
= get_parent_folder_name(source
, source_len
);
3185 if(src_len
+1 >= MAX_PATH
)
3188 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3189 src_path
[src_len
++] = '\\';
3192 dst_len
= destination_len
;
3193 if(dst_len
+1 >= MAX_PATH
) {
3197 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3198 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3199 dst_path
[dst_len
++] = '\\';
3201 hr
= CTL_E_FILENOTFOUND
;
3203 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3206 name_len
= strlenW(ffd
.cFileName
);
3207 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3211 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3212 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3214 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3216 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3218 return create_error(GetLastError());
3222 } while(FindNextFileW(f
, &ffd
));
3228 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3229 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3231 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3233 if(!Source
|| !Destination
)
3236 return copy_file(Source
, SysStringLen(Source
), Destination
,
3237 SysStringLen(Destination
), OverWriteFiles
);
3240 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3241 DWORD destination_len
, VARIANT_BOOL overwrite
)
3243 DWORD tmp
, src_len
, dst_len
, name_len
;
3244 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3245 WIN32_FIND_DATAW ffd
;
3248 BOOL copied
= FALSE
;
3250 if(!source
[0] || !destination
[0])
3251 return E_INVALIDARG
;
3253 dst_len
= destination_len
;
3254 if(dst_len
+1 >= MAX_PATH
)
3256 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3258 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3259 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3260 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3261 if(!CreateDirectoryW(dst
, NULL
)) {
3262 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3263 tmp
= GetFileAttributesW(dst
);
3264 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3265 return CTL_E_FILEALREADYEXISTS
;
3267 return create_error(GetLastError());
3272 src_len
= source_len
;
3273 if(src_len
+2 >= MAX_PATH
)
3275 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3276 src
[src_len
++] = '\\';
3280 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3281 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3282 return create_error(GetLastError());
3284 f
= FindFirstFileW(src
, &ffd
);
3286 src_len
= get_parent_folder_name(source
, source_len
);
3287 if(src_len
+2 >= MAX_PATH
)
3289 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3291 src
[src_len
++] = '\\';
3293 f
= FindFirstFileW(source
, &ffd
);
3295 if(f
== INVALID_HANDLE_VALUE
)
3296 return CTL_E_PATHNOTFOUND
;
3298 dst
[dst_len
++] = '\\';
3302 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3304 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3305 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3308 name_len
= strlenW(ffd
.cFileName
);
3309 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3313 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3314 dst
[dst_len
+name_len
] = 0;
3315 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3316 src
[src_len
+name_len
] = '\\';
3317 src
[src_len
+name_len
+1] = '*';
3318 src
[src_len
+name_len
+2] = 0;
3320 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3322 if(!CreateDirectoryW(dst
, NULL
)) {
3323 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3324 tmp
= GetFileAttributesW(dst
);
3325 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3327 return CTL_E_FILEALREADYEXISTS
;
3331 return create_error(GetLastError());
3333 return create_error(GetLastError());
3337 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3338 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3343 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3344 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3348 } while(FindNextFileW(f
, &ffd
));
3351 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3354 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3355 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3357 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3359 if(!Source
|| !Destination
)
3362 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3363 SysStringLen(Destination
), OverWriteFiles
);
3366 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3371 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3373 ret
= CreateDirectoryW(path
, NULL
);
3377 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3378 return HRESULT_FROM_WIN32(GetLastError());
3381 return create_folder(path
, folder
);
3384 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3385 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3386 ITextStream
**stream
)
3390 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3392 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3393 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3396 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3397 IOMode mode
, VARIANT_BOOL create
,
3398 Tristate format
, ITextStream
**stream
)
3402 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3403 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3405 if (format
== TristateUseDefault
) {
3406 FIXME("default format not handled, defaulting to unicode\n");
3407 format
= TristateTrue
;
3410 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3413 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3414 StandardStreamTypes StandardStreamType
,
3415 VARIANT_BOOL Unicode
,
3418 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3423 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3425 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3429 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3430 a
= (WORD
)( version
>> 48);
3431 b
= (WORD
)((version
>> 32) & 0xffff);
3432 c
= (WORD
)((version
>> 16) & 0xffff);
3433 d
= (WORD
)( version
& 0xffff);
3435 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3438 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3440 static const WCHAR rootW
[] = {'\\',0};
3441 VS_FIXEDFILEINFO
*info
;
3447 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3449 len
= GetFileVersionInfoSizeW(name
, NULL
);
3451 return HRESULT_FROM_WIN32(GetLastError());
3453 ptr
= heap_alloc(len
);
3454 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3457 return HRESULT_FROM_WIN32(GetLastError());
3460 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3463 return HRESULT_FROM_WIN32(GetLastError());
3465 get_versionstring(info
, ver
);
3466 *version
= SysAllocString(ver
);
3467 TRACE("version=%s\n", debugstr_w(ver
));
3472 static const struct IFileSystem3Vtbl filesys_vtbl
=
3474 filesys_QueryInterface
,
3477 filesys_GetTypeInfoCount
,
3478 filesys_GetTypeInfo
,
3479 filesys_GetIDsOfNames
,
3483 filesys_GetDriveName
,
3484 filesys_GetParentFolderName
,
3485 filesys_GetFileName
,
3486 filesys_GetBaseName
,
3487 filesys_GetExtensionName
,
3488 filesys_GetAbsolutePathName
,
3489 filesys_GetTempName
,
3490 filesys_DriveExists
,
3492 filesys_FolderExists
,
3496 filesys_GetSpecialFolder
,
3498 filesys_DeleteFolder
,
3503 filesys_CreateFolder
,
3504 filesys_CreateTextFile
,
3505 filesys_OpenTextFile
,
3506 filesys_GetStandardStream
,
3507 filesys_GetFileVersion
3510 static IFileSystem3 filesystem
= { &filesys_vtbl
};
3512 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3514 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3516 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);