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
;
58 struct foldercollection
*coll
;
63 struct filecollection
*coll
;
70 IEnumVARIANT IEnumVARIANT_iface
;
77 IFolder IFolder_iface
;
90 ITextStream ITextStream_iface
;
101 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
103 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
106 static inline struct file
*impl_from_IFile(IFile
*iface
)
108 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
111 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
113 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
116 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
118 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
121 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
123 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
126 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
128 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
131 static inline HRESULT
create_error(DWORD err
)
134 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
135 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
136 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
137 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
138 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
140 FIXME("Unsupported error code: %d\n", err
);
145 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
146 static HRESULT
create_file(BSTR
, IFile
**);
147 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
148 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
150 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
152 static const WCHAR dotdotW
[] = {'.','.',0};
153 static const WCHAR dotW
[] = {'.',0};
155 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
156 strcmpW(data
->cFileName
, dotdotW
) &&
157 strcmpW(data
->cFileName
, dotW
);
160 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
162 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
165 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
167 int len
= SysStringLen(path
);
168 WCHAR buffW
[MAX_PATH
];
170 strcpyW(buffW
, path
);
171 if (path
[len
-1] != '\\')
173 strcatW(buffW
, data
->cFileName
);
175 return SysAllocString(buffW
);
178 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
181 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
186 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
188 struct textstream
*This
= impl_from_ITextStream(iface
);
190 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
192 if (IsEqualIID(riid
, &IID_ITextStream
) ||
193 IsEqualIID(riid
, &IID_IDispatch
) ||
194 IsEqualIID(riid
, &IID_IUnknown
))
197 ITextStream_AddRef(iface
);
202 return E_NOINTERFACE
;
205 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
207 struct textstream
*This
= impl_from_ITextStream(iface
);
208 ULONG ref
= InterlockedIncrement(&This
->ref
);
209 TRACE("(%p)->(%d)\n", This
, ref
);
213 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
215 struct textstream
*This
= impl_from_ITextStream(iface
);
216 ULONG ref
= InterlockedDecrement(&This
->ref
);
217 TRACE("(%p)->(%d)\n", This
, ref
);
225 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
227 struct textstream
*This
= impl_from_ITextStream(iface
);
228 TRACE("(%p)->(%p)\n", This
, pctinfo
);
233 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
234 LCID lcid
, ITypeInfo
**ppTInfo
)
236 struct textstream
*This
= impl_from_ITextStream(iface
);
237 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
238 return get_typeinfo(ITextStream_tid
, ppTInfo
);
241 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
242 LPOLESTR
*rgszNames
, UINT cNames
,
243 LCID lcid
, DISPID
*rgDispId
)
245 struct textstream
*This
= impl_from_ITextStream(iface
);
249 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
251 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
254 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
255 ITypeInfo_Release(typeinfo
);
261 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
262 REFIID riid
, LCID lcid
, WORD wFlags
,
263 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
264 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
266 struct textstream
*This
= impl_from_ITextStream(iface
);
270 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
271 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
273 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
276 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
277 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
278 ITypeInfo_Release(typeinfo
);
284 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
286 struct textstream
*This
= impl_from_ITextStream(iface
);
287 FIXME("(%p)->(%p): stub\n", This
, line
);
291 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
293 struct textstream
*This
= impl_from_ITextStream(iface
);
294 FIXME("(%p)->(%p): stub\n", This
, column
);
298 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
300 struct textstream
*This
= impl_from_ITextStream(iface
);
301 FIXME("(%p)->(%p): stub\n", This
, eos
);
305 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
307 struct textstream
*This
= impl_from_ITextStream(iface
);
308 FIXME("(%p)->(%p): stub\n", This
, eol
);
312 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
314 struct textstream
*This
= impl_from_ITextStream(iface
);
315 FIXME("(%p)->(%p): stub\n", This
, text
);
317 if (textstream_check_iomode(This
, IORead
))
318 return CTL_E_BADFILEMODE
;
323 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
325 struct textstream
*This
= impl_from_ITextStream(iface
);
326 FIXME("(%p)->(%p): stub\n", This
, text
);
328 if (textstream_check_iomode(This
, IORead
))
329 return CTL_E_BADFILEMODE
;
334 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
336 struct textstream
*This
= impl_from_ITextStream(iface
);
337 FIXME("(%p)->(%p): stub\n", This
, text
);
339 if (textstream_check_iomode(This
, IORead
))
340 return CTL_E_BADFILEMODE
;
345 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
347 struct textstream
*This
= impl_from_ITextStream(iface
);
348 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(text
));
352 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
354 struct textstream
*This
= impl_from_ITextStream(iface
);
355 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(text
));
359 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
361 struct textstream
*This
= impl_from_ITextStream(iface
);
362 FIXME("(%p)->(%d): stub\n", This
, lines
);
366 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
368 struct textstream
*This
= impl_from_ITextStream(iface
);
369 FIXME("(%p)->(%d): stub\n", This
, count
);
373 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
375 struct textstream
*This
= impl_from_ITextStream(iface
);
376 FIXME("(%p): stub\n", This
);
380 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
382 struct textstream
*This
= impl_from_ITextStream(iface
);
383 FIXME("(%p): stub\n", This
);
387 static const ITextStreamVtbl textstreamvtbl
= {
388 textstream_QueryInterface
,
391 textstream_GetTypeInfoCount
,
392 textstream_GetTypeInfo
,
393 textstream_GetIDsOfNames
,
396 textstream_get_Column
,
397 textstream_get_AtEndOfStream
,
398 textstream_get_AtEndOfLine
,
403 textstream_WriteLine
,
404 textstream_WriteBlankLines
,
410 static HRESULT
create_textstream(IOMode mode
, ITextStream
**ret
)
412 struct textstream
*stream
;
414 stream
= heap_alloc(sizeof(struct textstream
));
415 if (!stream
) return E_OUTOFMEMORY
;
417 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
421 *ret
= &stream
->ITextStream_iface
;
425 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
427 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
429 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
433 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
434 IsEqualIID( riid
, &IID_IUnknown
))
437 IEnumVARIANT_AddRef(iface
);
440 return E_NOINTERFACE
;
445 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
447 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
448 ULONG ref
= InterlockedIncrement(&This
->ref
);
449 TRACE("(%p)->(%d)\n", This
, ref
);
453 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
455 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
456 ULONG ref
= InterlockedDecrement(&This
->ref
);
458 TRACE("(%p)->(%d)\n", This
, ref
);
462 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
463 FindClose(This
->data
.u
.foldercoll
.find
);
470 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
)
472 static const WCHAR allW
[] = {'*',0};
473 WCHAR pathW
[MAX_PATH
];
477 strcpyW(pathW
, path
);
478 len
= strlenW(pathW
);
479 if (pathW
[len
-1] != '\\')
481 strcatW(pathW
, allW
);
482 handle
= FindFirstFileW(pathW
, data
);
483 if (handle
== INVALID_HANDLE_VALUE
) return 0;
488 if (is_dir_data(data
))
491 if (!FindNextFileW(handle
, data
))
500 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
502 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
503 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
504 WIN32_FIND_DATAW data
;
507 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
512 if (!celt
) return S_OK
;
516 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
);
517 if (!handle
) return S_FALSE
;
519 This
->data
.u
.foldercoll
.find
= handle
;
523 if (!FindNextFileW(handle
, &data
))
529 if (is_dir_data(&data
))
535 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
536 hr
= create_folder(str
, &folder
);
538 if (FAILED(hr
)) return hr
;
540 V_VT(&var
[count
]) = VT_DISPATCH
;
541 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
544 if (count
>= celt
) break;
546 } while (FindNextFileW(handle
, &data
));
551 return (count
< celt
) ? S_FALSE
: S_OK
;
554 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
556 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
557 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
558 WIN32_FIND_DATAW data
;
560 TRACE("(%p)->(%d)\n", This
, celt
);
562 if (!celt
) return S_OK
;
566 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
);
567 if (!handle
) return S_FALSE
;
569 This
->data
.u
.foldercoll
.find
= handle
;
573 if (!FindNextFileW(handle
, &data
))
579 if (is_dir_data(&data
))
583 } while (FindNextFileW(handle
, &data
));
585 return celt
? S_FALSE
: S_OK
;
588 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
590 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
592 TRACE("(%p)\n", This
);
594 FindClose(This
->data
.u
.foldercoll
.find
);
595 This
->data
.u
.foldercoll
.find
= NULL
;
600 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
602 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
603 TRACE("(%p)->(%p)\n", This
, pclone
);
604 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
607 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
608 enumvariant_QueryInterface
,
610 foldercoll_enumvariant_Release
,
611 foldercoll_enumvariant_Next
,
612 foldercoll_enumvariant_Skip
,
613 foldercoll_enumvariant_Reset
,
614 foldercoll_enumvariant_Clone
617 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
619 struct enumvariant
*This
;
623 This
= heap_alloc(sizeof(*This
));
624 if (!This
) return E_OUTOFMEMORY
;
626 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
628 This
->data
.u
.foldercoll
.find
= NULL
;
629 This
->data
.u
.foldercoll
.coll
= collection
;
630 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
632 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
637 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
639 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
640 ULONG ref
= InterlockedDecrement(&This
->ref
);
642 TRACE("(%p)->(%d)\n", This
, ref
);
646 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
647 FindClose(This
->data
.u
.filecoll
.find
);
654 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
656 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
657 HANDLE handle
= This
->data
.u
.filecoll
.find
;
658 WIN32_FIND_DATAW data
;
661 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
668 static const WCHAR allW
[] = {'*',0};
669 WCHAR pathW
[MAX_PATH
];
670 BSTR parent
= This
->data
.u
.filecoll
.coll
->path
;
673 strcpyW(pathW
, parent
);
674 len
= SysStringLen(parent
);
675 if (parent
[len
-1] != '\\')
677 strcatW(pathW
, allW
);
678 handle
= FindFirstFileW(pathW
, &data
);
679 if (handle
== INVALID_HANDLE_VALUE
)
684 if (is_file_data(&data
))
687 if (!FindNextFileW(handle
, &data
))
694 This
->data
.u
.filecoll
.find
= handle
;
697 FindNextFileW(handle
, &data
);
701 if (count
>= celt
) break;
703 if (is_file_data(&data
))
709 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
710 hr
= create_file(str
, &file
);
712 if (FAILED(hr
)) return hr
;
714 V_VT(&var
[count
]) = VT_DISPATCH
;
715 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
718 } while (FindNextFileW(handle
, &data
));
729 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
731 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
732 HANDLE handle
= This
->data
.u
.filecoll
.find
;
733 WIN32_FIND_DATAW data
;
735 TRACE("(%p)->(%d)\n", This
, celt
);
737 while (FindNextFileW(handle
, &data
) && celt
)
738 if (is_file_data(&data
))
741 return celt
? S_FALSE
: S_OK
;
744 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
746 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
748 TRACE("(%p)\n", This
);
750 FindClose(This
->data
.u
.filecoll
.find
);
751 This
->data
.u
.filecoll
.find
= NULL
;
756 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
758 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
759 TRACE("(%p)->(%p)\n", This
, pclone
);
760 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
763 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
764 enumvariant_QueryInterface
,
766 filecoll_enumvariant_Release
,
767 filecoll_enumvariant_Next
,
768 filecoll_enumvariant_Skip
,
769 filecoll_enumvariant_Reset
,
770 filecoll_enumvariant_Clone
773 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
775 struct enumvariant
*This
;
779 This
= heap_alloc(sizeof(*This
));
780 if (!This
) return E_OUTOFMEMORY
;
782 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
784 This
->data
.u
.filecoll
.coll
= collection
;
785 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
787 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
792 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
794 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
796 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
800 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
801 IsEqualIID( riid
, &IID_IDispatch
) ||
802 IsEqualIID( riid
, &IID_IUnknown
))
805 IFolderCollection_AddRef(iface
);
808 return E_NOINTERFACE
;
813 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
815 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
816 ULONG ref
= InterlockedIncrement(&This
->ref
);
817 TRACE("(%p)->(%d)\n", This
, ref
);
821 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
823 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
824 ULONG ref
= InterlockedDecrement(&This
->ref
);
825 TRACE("(%p)->(%d)\n", This
, ref
);
829 SysFreeString(This
->path
);
836 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
838 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
839 TRACE("(%p)->(%p)\n", This
, pctinfo
);
844 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
845 LCID lcid
, ITypeInfo
**ppTInfo
)
847 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
848 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
849 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
852 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
853 LPOLESTR
*rgszNames
, UINT cNames
,
854 LCID lcid
, DISPID
*rgDispId
)
856 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
860 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
862 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
865 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
866 ITypeInfo_Release(typeinfo
);
872 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
873 REFIID riid
, LCID lcid
, WORD wFlags
,
874 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
875 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
877 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
881 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
882 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
884 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
887 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
888 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
889 ITypeInfo_Release(typeinfo
);
895 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
897 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
898 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
902 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
904 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
905 FIXME("(%p)->(%p): stub\n", This
, folder
);
909 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
911 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
913 TRACE("(%p)->(%p)\n", This
, newenum
);
918 return create_foldercoll_enum(This
, newenum
);
921 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
923 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
924 static const WCHAR allW
[] = {'\\','*',0};
925 WIN32_FIND_DATAW data
;
926 WCHAR pathW
[MAX_PATH
];
929 TRACE("(%p)->(%p)\n", This
, count
);
936 strcpyW(pathW
, This
->path
);
937 strcatW(pathW
, allW
);
938 handle
= FindFirstFileW(pathW
, &data
);
939 if (handle
== INVALID_HANDLE_VALUE
)
940 return HRESULT_FROM_WIN32(GetLastError());
944 if (is_dir_data(&data
))
946 } while (FindNextFileW(handle
, &data
));
952 static const IFolderCollectionVtbl foldercollvtbl
= {
953 foldercoll_QueryInterface
,
956 foldercoll_GetTypeInfoCount
,
957 foldercoll_GetTypeInfo
,
958 foldercoll_GetIDsOfNames
,
962 foldercoll_get__NewEnum
,
966 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
968 struct foldercollection
*This
;
972 This
= heap_alloc(sizeof(struct foldercollection
));
973 if (!This
) return E_OUTOFMEMORY
;
975 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
977 This
->path
= SysAllocString(path
);
981 return E_OUTOFMEMORY
;
984 *folders
= &This
->IFolderCollection_iface
;
989 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
991 struct filecollection
*This
= impl_from_IFileCollection(iface
);
993 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
997 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
998 IsEqualIID( riid
, &IID_IDispatch
) ||
999 IsEqualIID( riid
, &IID_IUnknown
))
1002 IFileCollection_AddRef(iface
);
1005 return E_NOINTERFACE
;
1010 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1012 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1013 ULONG ref
= InterlockedIncrement(&This
->ref
);
1014 TRACE("(%p)->(%d)\n", This
, ref
);
1018 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1020 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1021 ULONG ref
= InterlockedDecrement(&This
->ref
);
1022 TRACE("(%p)->(%d)\n", This
, ref
);
1026 SysFreeString(This
->path
);
1033 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1035 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1036 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1041 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1042 LCID lcid
, ITypeInfo
**ppTInfo
)
1044 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1045 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1046 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1049 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1050 LPOLESTR
*rgszNames
, UINT cNames
,
1051 LCID lcid
, DISPID
*rgDispId
)
1053 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1054 ITypeInfo
*typeinfo
;
1057 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1059 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1062 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1063 ITypeInfo_Release(typeinfo
);
1069 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1070 REFIID riid
, LCID lcid
, WORD wFlags
,
1071 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1072 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1074 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1075 ITypeInfo
*typeinfo
;
1078 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1079 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1081 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1084 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1085 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1086 ITypeInfo_Release(typeinfo
);
1092 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1094 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1095 FIXME("(%p)->(%p)\n", This
, file
);
1099 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1101 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1103 TRACE("(%p)->(%p)\n", This
, ppenum
);
1108 return create_filecoll_enum(This
, ppenum
);
1111 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1113 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1114 FIXME("(%p)->(%p)\n", This
, count
);
1118 static const IFileCollectionVtbl filecollectionvtbl
= {
1119 filecoll_QueryInterface
,
1122 filecoll_GetTypeInfoCount
,
1123 filecoll_GetTypeInfo
,
1124 filecoll_GetIDsOfNames
,
1127 filecoll_get__NewEnum
,
1131 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1133 struct filecollection
*This
;
1137 This
= heap_alloc(sizeof(*This
));
1138 if (!This
) return E_OUTOFMEMORY
;
1140 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1142 This
->path
= SysAllocString(path
);
1146 return E_OUTOFMEMORY
;
1149 *files
= &This
->IFileCollection_iface
;
1153 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
1155 struct folder
*This
= impl_from_IFolder(iface
);
1157 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1161 if (IsEqualIID( riid
, &IID_IFolder
) ||
1162 IsEqualIID( riid
, &IID_IDispatch
) ||
1163 IsEqualIID( riid
, &IID_IUnknown
))
1166 IFolder_AddRef(iface
);
1169 return E_NOINTERFACE
;
1174 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
1176 struct folder
*This
= impl_from_IFolder(iface
);
1177 ULONG ref
= InterlockedIncrement(&This
->ref
);
1178 TRACE("(%p)->(%d)\n", This
, ref
);
1182 static ULONG WINAPI
folder_Release(IFolder
*iface
)
1184 struct folder
*This
= impl_from_IFolder(iface
);
1185 ULONG ref
= InterlockedDecrement(&This
->ref
);
1186 TRACE("(%p)->(%d)\n", This
, ref
);
1190 SysFreeString(This
->path
);
1197 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
1199 struct folder
*This
= impl_from_IFolder(iface
);
1200 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1205 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
1206 LCID lcid
, ITypeInfo
**ppTInfo
)
1208 struct folder
*This
= impl_from_IFolder(iface
);
1209 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1210 return get_typeinfo(IFolder_tid
, ppTInfo
);
1213 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
1214 LPOLESTR
*rgszNames
, UINT cNames
,
1215 LCID lcid
, DISPID
*rgDispId
)
1217 struct folder
*This
= impl_from_IFolder(iface
);
1218 ITypeInfo
*typeinfo
;
1221 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1223 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
1226 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1227 ITypeInfo_Release(typeinfo
);
1233 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
1234 REFIID riid
, LCID lcid
, WORD wFlags
,
1235 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1236 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1238 struct folder
*This
= impl_from_IFolder(iface
);
1239 ITypeInfo
*typeinfo
;
1242 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1243 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1245 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
1248 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1249 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1250 ITypeInfo_Release(typeinfo
);
1256 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
1258 struct folder
*This
= impl_from_IFolder(iface
);
1259 FIXME("(%p)->(%p): stub\n", This
, path
);
1263 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
1265 struct folder
*This
= impl_from_IFolder(iface
);
1268 TRACE("(%p)->(%p)\n", This
, name
);
1275 ptr
= strrchrW(This
->path
, '\\');
1278 *name
= SysAllocString(ptr
+1);
1279 TRACE("%s\n", debugstr_w(*name
));
1280 if (!*name
) return E_OUTOFMEMORY
;
1288 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
1290 struct folder
*This
= impl_from_IFolder(iface
);
1291 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1295 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
1297 struct folder
*This
= impl_from_IFolder(iface
);
1298 FIXME("(%p)->(%p): stub\n", This
, path
);
1302 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
1304 struct folder
*This
= impl_from_IFolder(iface
);
1305 FIXME("(%p)->(%p): stub\n", This
, name
);
1309 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
1311 struct folder
*This
= impl_from_IFolder(iface
);
1312 FIXME("(%p)->(%p): stub\n", This
, drive
);
1316 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
1318 struct folder
*This
= impl_from_IFolder(iface
);
1319 FIXME("(%p)->(%p): stub\n", This
, parent
);
1323 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
1325 struct folder
*This
= impl_from_IFolder(iface
);
1326 FIXME("(%p)->(%p): stub\n", This
, attr
);
1330 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
1332 struct folder
*This
= impl_from_IFolder(iface
);
1333 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
1337 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
1339 struct folder
*This
= impl_from_IFolder(iface
);
1340 FIXME("(%p)->(%p): stub\n", This
, date
);
1344 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
1346 struct folder
*This
= impl_from_IFolder(iface
);
1347 FIXME("(%p)->(%p): stub\n", This
, date
);
1351 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
1353 struct folder
*This
= impl_from_IFolder(iface
);
1354 FIXME("(%p)->(%p): stub\n", This
, date
);
1358 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
1360 struct folder
*This
= impl_from_IFolder(iface
);
1361 FIXME("(%p)->(%p): stub\n", This
, type
);
1365 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
1367 struct folder
*This
= impl_from_IFolder(iface
);
1368 FIXME("(%p)->(%x): stub\n", This
, force
);
1372 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
1374 struct folder
*This
= impl_from_IFolder(iface
);
1375 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
1379 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
1381 struct folder
*This
= impl_from_IFolder(iface
);
1382 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
1386 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
1388 struct folder
*This
= impl_from_IFolder(iface
);
1389 FIXME("(%p)->(%p): stub\n", This
, isroot
);
1393 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
1395 struct folder
*This
= impl_from_IFolder(iface
);
1396 FIXME("(%p)->(%p): stub\n", This
, size
);
1400 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
1402 struct folder
*This
= impl_from_IFolder(iface
);
1404 TRACE("(%p)->(%p)\n", This
, folders
);
1409 return create_foldercoll(This
->path
, folders
);
1412 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
1414 struct folder
*This
= impl_from_IFolder(iface
);
1416 TRACE("(%p)->(%p)\n", This
, files
);
1421 return create_filecoll(This
->path
, files
);
1424 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
1425 VARIANT_BOOL unicode
, ITextStream
**stream
)
1427 struct folder
*This
= impl_from_IFolder(iface
);
1428 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
1432 static const IFolderVtbl foldervtbl
= {
1433 folder_QueryInterface
,
1436 folder_GetTypeInfoCount
,
1438 folder_GetIDsOfNames
,
1443 folder_get_ShortPath
,
1444 folder_get_ShortName
,
1446 folder_get_ParentFolder
,
1447 folder_get_Attributes
,
1448 folder_put_Attributes
,
1449 folder_get_DateCreated
,
1450 folder_get_DateLastModified
,
1451 folder_get_DateLastAccessed
,
1456 folder_get_IsRootFolder
,
1458 folder_get_SubFolders
,
1460 folder_CreateTextFile
1463 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
1465 struct folder
*This
;
1469 TRACE("%s\n", debugstr_w(path
));
1471 This
= heap_alloc(sizeof(struct folder
));
1472 if (!This
) return E_OUTOFMEMORY
;
1474 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
1476 This
->path
= SysAllocString(path
);
1480 return E_OUTOFMEMORY
;
1483 *folder
= &This
->IFolder_iface
;
1488 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
1490 struct file
*This
= impl_from_IFile(iface
);
1492 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1494 if (IsEqualIID(riid
, &IID_IFile
) ||
1495 IsEqualIID(riid
, &IID_IDispatch
) ||
1496 IsEqualIID(riid
, &IID_IUnknown
))
1499 IFile_AddRef(iface
);
1504 return E_NOINTERFACE
;
1507 static ULONG WINAPI
file_AddRef(IFile
*iface
)
1509 struct file
*This
= impl_from_IFile(iface
);
1510 LONG ref
= InterlockedIncrement(&This
->ref
);
1512 TRACE("(%p) ref=%d\n", This
, ref
);
1517 static ULONG WINAPI
file_Release(IFile
*iface
)
1519 struct file
*This
= impl_from_IFile(iface
);
1520 LONG ref
= InterlockedDecrement(&This
->ref
);
1522 TRACE("(%p) ref=%d\n", This
, ref
);
1526 heap_free(This
->path
);
1533 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
1535 struct file
*This
= impl_from_IFile(iface
);
1537 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1543 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
1544 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1546 struct file
*This
= impl_from_IFile(iface
);
1548 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1550 return get_typeinfo(IFile_tid
, ppTInfo
);
1553 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
1554 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1556 struct file
*This
= impl_from_IFile(iface
);
1557 ITypeInfo
*typeinfo
;
1560 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
1561 rgszNames
, cNames
, lcid
, rgDispId
);
1563 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
1565 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1566 ITypeInfo_Release(typeinfo
);
1571 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1573 struct file
*This
= impl_from_IFile(iface
);
1574 ITypeInfo
*typeinfo
;
1577 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1578 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1580 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
1583 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1584 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1585 ITypeInfo_Release(typeinfo
);
1590 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
1592 struct file
*This
= impl_from_IFile(iface
);
1593 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
1597 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
1599 struct file
*This
= impl_from_IFile(iface
);
1602 TRACE("(%p)->(%p)\n", This
, name
);
1609 ptr
= strrchrW(This
->path
, '\\');
1612 *name
= SysAllocString(ptr
+1);
1613 TRACE("%s\n", debugstr_w(*name
));
1614 if (!*name
) return E_OUTOFMEMORY
;
1622 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
1624 struct file
*This
= impl_from_IFile(iface
);
1625 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
1629 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
1631 struct file
*This
= impl_from_IFile(iface
);
1632 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
1636 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
1638 struct file
*This
= impl_from_IFile(iface
);
1639 FIXME("(%p)->(%p)\n", This
, pbstrName
);
1643 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
1645 struct file
*This
= impl_from_IFile(iface
);
1646 FIXME("(%p)->(%p)\n", This
, ppdrive
);
1650 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
1652 struct file
*This
= impl_from_IFile(iface
);
1653 FIXME("(%p)->(%p)\n", This
, ppfolder
);
1657 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
1659 struct file
*This
= impl_from_IFile(iface
);
1662 TRACE("(%p)->(%p)\n", This
, pfa
);
1667 fa
= GetFileAttributesW(This
->path
);
1668 if(fa
== INVALID_FILE_ATTRIBUTES
)
1669 return create_error(GetLastError());
1671 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
1672 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
1673 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
1677 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
1679 struct file
*This
= impl_from_IFile(iface
);
1680 FIXME("(%p)->(%x)\n", This
, pfa
);
1684 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
1686 struct file
*This
= impl_from_IFile(iface
);
1687 FIXME("(%p)->(%p)\n", This
, pdate
);
1691 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
1693 struct file
*This
= impl_from_IFile(iface
);
1694 FIXME("(%p)->(%p)\n", This
, pdate
);
1698 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
1700 struct file
*This
= impl_from_IFile(iface
);
1701 FIXME("(%p)->(%p)\n", This
, pdate
);
1705 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
1707 struct file
*This
= impl_from_IFile(iface
);
1708 WIN32_FIND_DATAW fd
;
1711 TRACE("(%p)->(%p)\n", This
, pvarSize
);
1716 f
= FindFirstFileW(This
->path
, &fd
);
1717 if(f
== INVALID_HANDLE_VALUE
)
1718 return create_error(GetLastError());
1721 if(fd
.nFileSizeHigh
|| fd
.nFileSizeLow
>INT_MAX
) {
1722 V_VT(pvarSize
) = VT_R8
;
1723 V_R8(pvarSize
) = ((ULONGLONG
)fd
.nFileSizeHigh
<<32) + fd
.nFileSizeLow
;
1725 V_VT(pvarSize
) = VT_I4
;
1726 V_I4(pvarSize
) = fd
.nFileSizeLow
;
1731 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
1733 struct file
*This
= impl_from_IFile(iface
);
1734 FIXME("(%p)->(%p)\n", This
, pbstrType
);
1738 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
1740 struct file
*This
= impl_from_IFile(iface
);
1741 FIXME("(%p)->(%x)\n", This
, Force
);
1745 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
1747 struct file
*This
= impl_from_IFile(iface
);
1748 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
1752 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
1754 struct file
*This
= impl_from_IFile(iface
);
1755 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
1759 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode IOMode
, Tristate Format
, ITextStream
**ppts
)
1761 struct file
*This
= impl_from_IFile(iface
);
1762 FIXME("(%p)->(%x %x %p)\n", This
, IOMode
, Format
, ppts
);
1766 static const IFileVtbl file_vtbl
= {
1767 file_QueryInterface
,
1770 file_GetTypeInfoCount
,
1780 file_get_ParentFolder
,
1781 file_get_Attributes
,
1782 file_put_Attributes
,
1783 file_get_DateCreated
,
1784 file_get_DateLastModified
,
1785 file_get_DateLastAccessed
,
1791 file_OpenAsTextStream
1794 static HRESULT
create_file(BSTR path
, IFile
**file
)
1801 f
= heap_alloc(sizeof(struct file
));
1803 return E_OUTOFMEMORY
;
1805 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
1808 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
1814 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
1817 return E_OUTOFMEMORY
;
1820 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
1826 if(path
[len
-1]=='/' || path
[len
-1]=='\\')
1829 attrs
= GetFileAttributesW(f
->path
);
1830 if(attrs
==INVALID_FILE_ATTRIBUTES
||
1831 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
1834 return create_error(GetLastError());
1837 *file
= &f
->IFile_iface
;
1841 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
1843 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
1845 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
1846 IsEqualGUID( riid
, &IID_IFileSystem
) ||
1847 IsEqualGUID( riid
, &IID_IDispatch
) ||
1848 IsEqualGUID( riid
, &IID_IUnknown
) )
1852 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
1854 TRACE("Interface IDispatchEx not supported - returning NULL\n");
1856 return E_NOINTERFACE
;
1858 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
1860 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
1862 return E_NOINTERFACE
;
1866 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
1867 return E_NOINTERFACE
;
1870 IFileSystem3_AddRef(iface
);
1875 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
1877 TRACE("%p\n", iface
);
1882 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
1884 TRACE("%p\n", iface
);
1889 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
1891 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
1897 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
1898 LCID lcid
, ITypeInfo
**ppTInfo
)
1900 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
1901 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
1904 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
1905 LPOLESTR
*rgszNames
, UINT cNames
,
1906 LCID lcid
, DISPID
*rgDispId
)
1908 ITypeInfo
*typeinfo
;
1911 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1913 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
1916 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1917 ITypeInfo_Release(typeinfo
);
1923 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
1924 REFIID riid
, LCID lcid
, WORD wFlags
,
1925 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1926 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1928 ITypeInfo
*typeinfo
;
1931 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
1932 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1934 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
1937 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1938 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1939 ITypeInfo_Release(typeinfo
);
1945 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
1947 FIXME("%p %p\n", iface
, ppdrives
);
1952 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
1953 BSTR Name
, BSTR
*Result
)
1957 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
1959 if (!Result
) return E_POINTER
;
1963 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
1965 /* if both parts have backslashes strip one from Path */
1966 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
1970 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
1978 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
1980 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
1984 if (Path
[path_len
-1] != ':')
1991 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
1999 else if (Path
|| Name
)
2000 ret
= SysAllocString(Path
? Path
: Name
);
2002 ret
= SysAllocStringLen(NULL
, 0);
2004 if (!ret
) return E_OUTOFMEMORY
;
2010 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR Path
,
2013 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2018 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
2025 for(i
=len
-1; i
>=0; i
--)
2026 if(path
[i
]!='/' && path
[i
]!='\\')
2030 if(path
[i
]=='/' || path
[i
]=='\\')
2034 if(path
[i
]!='/' && path
[i
]!='\\')
2040 if(path
[i
]==':' && i
==1)
2045 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
2050 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2055 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
2057 *pbstrResult
= NULL
;
2061 *pbstrResult
= SysAllocStringLen(Path
, len
);
2063 return E_OUTOFMEMORY
;
2067 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
2072 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2078 *pbstrResult
= NULL
;
2082 for(end
=strlenW(Path
)-1; end
>=0; end
--)
2083 if(Path
[end
]!='/' && Path
[end
]!='\\')
2086 for(i
=end
; i
>=0; i
--)
2087 if(Path
[i
]=='/' || Path
[i
]=='\\')
2091 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
2092 *pbstrResult
= NULL
;
2096 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
2098 return E_OUTOFMEMORY
;
2102 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
2107 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2113 *pbstrResult
= NULL
;
2117 for(end
=strlenW(Path
)-1; end
>=0; end
--)
2118 if(Path
[end
]!='/' && Path
[end
]!='\\')
2121 for(i
=end
; i
>=0; i
--) {
2122 if(Path
[i
]=='.' && Path
[end
+1]!='.')
2124 if(Path
[i
]=='/' || Path
[i
]=='\\')
2129 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
2130 *pbstrResult
= NULL
;
2134 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
2136 return E_OUTOFMEMORY
;
2140 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
2143 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2148 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
2151 static const WCHAR cur_path
[] = {'.',0};
2153 WCHAR buf
[MAX_PATH
], ch
;
2155 DWORD i
, beg
, len
, exp_len
;
2156 WIN32_FIND_DATAW fdata
;
2159 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2169 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
2173 buf
[0] = toupperW(buf
[0]);
2174 if(len
>3 && buf
[len
-1] == '\\')
2177 for(beg
=3, i
=3; i
<=len
; i
++) {
2178 if(buf
[i
]!='\\' && buf
[i
])
2183 fh
= FindFirstFileW(buf
, &fdata
);
2184 if(fh
== INVALID_HANDLE_VALUE
)
2187 exp_len
= strlenW(fdata
.cFileName
);
2188 if(exp_len
== i
-beg
)
2189 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
2195 *pbstrResult
= SysAllocString(buf
);
2197 return E_OUTOFMEMORY
;
2201 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
2203 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
2207 TRACE("%p %p\n", iface
, pbstrResult
);
2212 *pbstrResult
= SysAllocStringLen(NULL
, 12);
2214 return E_OUTOFMEMORY
;
2216 if(!RtlGenRandom(&random
, sizeof(random
)))
2218 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
2222 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
2223 VARIANT_BOOL
*pfExists
)
2225 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
2230 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
2233 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
2235 if (!ret
) return E_POINTER
;
2237 attrs
= GetFileAttributesW(path
);
2238 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2242 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
2245 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
2247 if (!ret
) return E_POINTER
;
2249 attrs
= GetFileAttributesW(path
);
2250 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2255 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
2258 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
2263 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
2266 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
2271 return E_INVALIDARG
;
2273 return create_file(FilePath
, ppfile
);
2276 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
2281 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
2288 return E_INVALIDARG
;
2290 attrs
= GetFileAttributesW(FolderPath
);
2291 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
2292 return CTL_E_PATHNOTFOUND
;
2294 return create_folder(FolderPath
, folder
);
2297 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
2298 SpecialFolderConst SpecialFolder
,
2301 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
2306 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
2308 WCHAR path
[MAX_PATH
];
2309 DWORD len
, name_len
;
2310 WIN32_FIND_DATAW ffd
;
2313 f
= FindFirstFileW(file
, &ffd
);
2314 if(f
== INVALID_HANDLE_VALUE
)
2315 return create_error(GetLastError());
2317 len
= get_parent_folder_name(file
, file_len
);
2318 if(len
+1 >= MAX_PATH
) {
2323 memcpy(path
, file
, len
*sizeof(WCHAR
));
2328 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
2331 name_len
= strlenW(ffd
.cFileName
);
2332 if(len
+name_len
+1 >= MAX_PATH
) {
2336 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
2338 TRACE("deleting %s\n", debugstr_w(path
));
2340 if(!DeleteFileW(path
)) {
2341 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
2342 || !DeleteFileW(path
)) {
2344 return create_error(GetLastError());
2347 } while(FindNextFileW(f
, &ffd
));
2353 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
2356 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
2361 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
2364 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
2366 WCHAR path
[MAX_PATH
];
2367 DWORD len
, name_len
;
2368 WIN32_FIND_DATAW ffd
;
2372 f
= FindFirstFileW(folder
, &ffd
);
2373 if(f
== INVALID_HANDLE_VALUE
)
2374 return create_error(GetLastError());
2376 len
= get_parent_folder_name(folder
, folder_len
);
2377 if(len
+1 >= MAX_PATH
) {
2382 memcpy(path
, folder
, len
*sizeof(WCHAR
));
2387 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
2389 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
2390 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
2393 name_len
= strlenW(ffd
.cFileName
);
2394 if(len
+name_len
+3 >= MAX_PATH
) {
2398 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
2399 path
[len
+name_len
] = '\\';
2400 path
[len
+name_len
+1] = '*';
2401 path
[len
+name_len
+2] = 0;
2403 hr
= delete_file(path
, len
+name_len
+2, force
);
2409 hr
= delete_folder(path
, len
+name_len
+2, force
);
2415 path
[len
+name_len
] = 0;
2416 TRACE("deleting %s\n", debugstr_w(path
));
2418 if(!RemoveDirectoryW(path
)) {
2420 return create_error(GetLastError());
2422 } while(FindNextFileW(f
, &ffd
));
2428 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
2431 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
2436 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
2439 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
2442 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
2447 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
2450 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
2455 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
2456 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
2459 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
2460 DWORD src_len
, dst_len
, name_len
;
2461 WIN32_FIND_DATAW ffd
;
2465 if(!source
[0] || !destination
[0])
2466 return E_INVALIDARG
;
2468 attrs
= GetFileAttributesW(destination
);
2469 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
2470 attrs
= GetFileAttributesW(source
);
2471 if(attrs
== INVALID_FILE_ATTRIBUTES
)
2472 return create_error(GetLastError());
2473 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
2474 return CTL_E_FILENOTFOUND
;
2476 if(!CopyFileW(source
, destination
, !overwrite
))
2477 return create_error(GetLastError());
2481 f
= FindFirstFileW(source
, &ffd
);
2482 if(f
== INVALID_HANDLE_VALUE
)
2483 return CTL_E_FILENOTFOUND
;
2485 src_len
= get_parent_folder_name(source
, source_len
);
2486 if(src_len
+1 >= MAX_PATH
)
2489 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
2490 src_path
[src_len
++] = '\\';
2493 dst_len
= destination_len
;
2494 if(dst_len
+1 >= MAX_PATH
) {
2498 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
2499 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
2500 dst_path
[dst_len
++] = '\\';
2502 hr
= CTL_E_FILENOTFOUND
;
2504 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
2507 name_len
= strlenW(ffd
.cFileName
);
2508 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
2512 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
2513 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
2515 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
2517 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
2519 return create_error(GetLastError());
2523 } while(FindNextFileW(f
, &ffd
));
2529 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
2530 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2532 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
2534 if(!Source
|| !Destination
)
2537 return copy_file(Source
, SysStringLen(Source
), Destination
,
2538 SysStringLen(Destination
), OverWriteFiles
);
2541 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
2542 DWORD destination_len
, VARIANT_BOOL overwrite
)
2544 DWORD tmp
, src_len
, dst_len
, name_len
;
2545 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
2546 WIN32_FIND_DATAW ffd
;
2549 BOOL copied
= FALSE
;
2551 if(!source
[0] || !destination
[0])
2552 return E_INVALIDARG
;
2554 dst_len
= destination_len
;
2555 if(dst_len
+1 >= MAX_PATH
)
2557 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
2559 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
2560 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
2561 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
2562 if(!CreateDirectoryW(dst
, NULL
)) {
2563 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
2564 tmp
= GetFileAttributesW(dst
);
2565 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
2566 return CTL_E_FILEALREADYEXISTS
;
2568 return create_error(GetLastError());
2573 src_len
= source_len
;
2574 if(src_len
+2 >= MAX_PATH
)
2576 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
2577 src
[src_len
++] = '\\';
2581 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
2582 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
2583 return create_error(GetLastError());
2585 f
= FindFirstFileW(src
, &ffd
);
2587 src_len
= get_parent_folder_name(source
, source_len
);
2588 if(src_len
+2 >= MAX_PATH
)
2590 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
2592 src
[src_len
++] = '\\';
2594 f
= FindFirstFileW(source
, &ffd
);
2596 if(f
== INVALID_HANDLE_VALUE
)
2597 return CTL_E_PATHNOTFOUND
;
2599 dst
[dst_len
++] = '\\';
2603 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
2605 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
2606 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
2609 name_len
= strlenW(ffd
.cFileName
);
2610 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
2614 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
2615 dst
[dst_len
+name_len
] = 0;
2616 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
2617 src
[src_len
+name_len
] = '\\';
2618 src
[src_len
+name_len
+1] = '*';
2619 src
[src_len
+name_len
+2] = 0;
2621 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
2623 if(!CreateDirectoryW(dst
, NULL
)) {
2624 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
2625 tmp
= GetFileAttributesW(dst
);
2626 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
2628 return CTL_E_FILEALREADYEXISTS
;
2632 return create_error(GetLastError());
2634 return create_error(GetLastError());
2638 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
2639 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
2644 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
2645 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
2649 } while(FindNextFileW(f
, &ffd
));
2652 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
2655 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
2656 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2658 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
2660 if(!Source
|| !Destination
)
2663 return copy_folder(Source
, SysStringLen(Source
), Destination
,
2664 SysStringLen(Destination
), OverWriteFiles
);
2667 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
2672 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
2674 ret
= CreateDirectoryW(path
, NULL
);
2678 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
2679 return HRESULT_FROM_WIN32(GetLastError());
2682 return create_folder(path
, folder
);
2685 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR FileName
,
2686 VARIANT_BOOL Overwrite
, VARIANT_BOOL Unicode
,
2689 FIXME("%p %s %d %d %p\n", iface
, debugstr_w(FileName
), Overwrite
, Unicode
, ppts
);
2694 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
2695 IOMode mode
, VARIANT_BOOL create
,
2696 Tristate format
, ITextStream
**stream
)
2698 FIXME("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
2699 return create_textstream(mode
, stream
);
2702 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
2703 StandardStreamTypes StandardStreamType
,
2704 VARIANT_BOOL Unicode
,
2707 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
2712 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
2714 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
2718 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
2719 a
= (WORD
)( version
>> 48);
2720 b
= (WORD
)((version
>> 32) & 0xffff);
2721 c
= (WORD
)((version
>> 16) & 0xffff);
2722 d
= (WORD
)( version
& 0xffff);
2724 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
2727 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
2729 static const WCHAR rootW
[] = {'\\',0};
2730 VS_FIXEDFILEINFO
*info
;
2736 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
2738 len
= GetFileVersionInfoSizeW(name
, NULL
);
2740 return HRESULT_FROM_WIN32(GetLastError());
2742 ptr
= heap_alloc(len
);
2743 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
2746 return HRESULT_FROM_WIN32(GetLastError());
2749 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
2752 return HRESULT_FROM_WIN32(GetLastError());
2754 get_versionstring(info
, ver
);
2755 *version
= SysAllocString(ver
);
2756 TRACE("version=%s\n", debugstr_w(ver
));
2761 static const struct IFileSystem3Vtbl filesys_vtbl
=
2763 filesys_QueryInterface
,
2766 filesys_GetTypeInfoCount
,
2767 filesys_GetTypeInfo
,
2768 filesys_GetIDsOfNames
,
2772 filesys_GetDriveName
,
2773 filesys_GetParentFolderName
,
2774 filesys_GetFileName
,
2775 filesys_GetBaseName
,
2776 filesys_GetExtensionName
,
2777 filesys_GetAbsolutePathName
,
2778 filesys_GetTempName
,
2779 filesys_DriveExists
,
2781 filesys_FolderExists
,
2785 filesys_GetSpecialFolder
,
2787 filesys_DeleteFolder
,
2792 filesys_CreateFolder
,
2793 filesys_CreateTextFile
,
2794 filesys_OpenTextFile
,
2795 filesys_GetStandardStream
,
2796 filesys_GetFileVersion
2799 static IFileSystem3 filesystem
= { &filesys_vtbl
};
2801 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
2803 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
2805 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);