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 HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
472 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
473 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
474 WIN32_FIND_DATAW data
;
477 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
484 static const WCHAR allW
[] = {'*',0};
485 WCHAR pathW
[MAX_PATH
];
486 BSTR parent
= This
->data
.u
.foldercoll
.coll
->path
;
489 strcpyW(pathW
, parent
);
490 len
= SysStringLen(parent
);
491 if (parent
[len
-1] != '\\')
493 strcatW(pathW
, allW
);
494 handle
= FindFirstFileW(pathW
, &data
);
495 if (handle
== INVALID_HANDLE_VALUE
)
501 if (is_dir_data(&data
))
504 if (!FindNextFileW(handle
, &data
))
511 This
->data
.u
.foldercoll
.find
= handle
;
514 FindNextFileW(handle
, &data
);
518 if (count
>= celt
) break;
520 if (is_dir_data(&data
))
526 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
527 hr
= create_folder(str
, &folder
);
529 if (FAILED(hr
)) return hr
;
531 V_VT(&var
[count
]) = VT_DISPATCH
;
532 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
535 } while (FindNextFileW(handle
, &data
));
546 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
548 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
549 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
550 WIN32_FIND_DATAW data
;
552 TRACE("(%p)->(%d)\n", This
, celt
);
554 while (FindNextFileW(handle
, &data
) && celt
)
555 if (is_dir_data(&data
))
558 return celt
? S_FALSE
: S_OK
;
561 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
563 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
565 TRACE("(%p)\n", This
);
567 FindClose(This
->data
.u
.foldercoll
.find
);
568 This
->data
.u
.foldercoll
.find
= NULL
;
573 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
575 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
576 TRACE("(%p)->(%p)\n", This
, pclone
);
577 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
580 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
581 enumvariant_QueryInterface
,
583 foldercoll_enumvariant_Release
,
584 foldercoll_enumvariant_Next
,
585 foldercoll_enumvariant_Skip
,
586 foldercoll_enumvariant_Reset
,
587 foldercoll_enumvariant_Clone
590 HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
592 struct enumvariant
*This
;
596 This
= heap_alloc(sizeof(*This
));
597 if (!This
) return E_OUTOFMEMORY
;
599 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
601 This
->data
.u
.foldercoll
.find
= NULL
;
602 This
->data
.u
.foldercoll
.coll
= collection
;
603 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
605 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
610 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
612 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
613 ULONG ref
= InterlockedDecrement(&This
->ref
);
615 TRACE("(%p)->(%d)\n", This
, ref
);
619 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
626 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
628 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
629 HANDLE handle
= This
->data
.u
.filecoll
.find
;
630 WIN32_FIND_DATAW data
;
633 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
640 static const WCHAR allW
[] = {'*',0};
641 WCHAR pathW
[MAX_PATH
];
642 BSTR parent
= This
->data
.u
.filecoll
.coll
->path
;
645 strcpyW(pathW
, parent
);
646 len
= SysStringLen(parent
);
647 if (parent
[len
-1] != '\\')
649 strcatW(pathW
, allW
);
650 handle
= FindFirstFileW(pathW
, &data
);
651 if (handle
== INVALID_HANDLE_VALUE
)
656 if (is_file_data(&data
))
659 if (!FindNextFileW(handle
, &data
))
666 This
->data
.u
.filecoll
.find
= handle
;
669 FindNextFileW(handle
, &data
);
673 if (count
>= celt
) break;
675 if (is_file_data(&data
))
681 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
682 hr
= create_file(str
, &file
);
684 if (FAILED(hr
)) return hr
;
686 V_VT(&var
[count
]) = VT_DISPATCH
;
687 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
690 } while (FindNextFileW(handle
, &data
));
701 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
703 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
704 HANDLE handle
= This
->data
.u
.filecoll
.find
;
705 WIN32_FIND_DATAW data
;
707 TRACE("(%p)->(%d)\n", This
, celt
);
709 while (FindNextFileW(handle
, &data
) && celt
)
710 if (is_file_data(&data
))
713 return celt
? S_FALSE
: S_OK
;
716 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
718 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
720 TRACE("(%p)\n", This
);
722 FindClose(This
->data
.u
.filecoll
.find
);
723 This
->data
.u
.filecoll
.find
= NULL
;
728 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
730 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
731 TRACE("(%p)->(%p)\n", This
, pclone
);
732 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
735 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
736 enumvariant_QueryInterface
,
738 filecoll_enumvariant_Release
,
739 filecoll_enumvariant_Next
,
740 filecoll_enumvariant_Skip
,
741 filecoll_enumvariant_Reset
,
742 filecoll_enumvariant_Clone
745 HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
747 struct enumvariant
*This
;
751 This
= heap_alloc(sizeof(*This
));
752 if (!This
) return E_OUTOFMEMORY
;
754 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
756 This
->data
.u
.filecoll
.coll
= collection
;
757 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
759 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
764 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
766 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
768 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
772 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
773 IsEqualIID( riid
, &IID_IDispatch
) ||
774 IsEqualIID( riid
, &IID_IUnknown
))
777 IFolderCollection_AddRef(iface
);
780 return E_NOINTERFACE
;
785 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
787 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
788 ULONG ref
= InterlockedIncrement(&This
->ref
);
789 TRACE("(%p)->(%d)\n", This
, ref
);
793 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
795 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
796 ULONG ref
= InterlockedDecrement(&This
->ref
);
797 TRACE("(%p)->(%d)\n", This
, ref
);
801 SysFreeString(This
->path
);
808 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
810 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
811 TRACE("(%p)->(%p)\n", This
, pctinfo
);
816 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
817 LCID lcid
, ITypeInfo
**ppTInfo
)
819 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
820 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
821 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
824 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
825 LPOLESTR
*rgszNames
, UINT cNames
,
826 LCID lcid
, DISPID
*rgDispId
)
828 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
832 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
834 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
837 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
838 ITypeInfo_Release(typeinfo
);
844 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
845 REFIID riid
, LCID lcid
, WORD wFlags
,
846 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
847 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
849 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
853 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
854 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
856 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
859 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
860 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
861 ITypeInfo_Release(typeinfo
);
867 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
869 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
870 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
874 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
876 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
877 FIXME("(%p)->(%p): stub\n", This
, folder
);
881 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
883 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
885 TRACE("(%p)->(%p)\n", This
, newenum
);
890 return create_foldercoll_enum(This
, newenum
);
893 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
895 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
896 static const WCHAR allW
[] = {'\\','*',0};
897 WIN32_FIND_DATAW data
;
898 WCHAR pathW
[MAX_PATH
];
901 TRACE("(%p)->(%p)\n", This
, count
);
908 strcpyW(pathW
, This
->path
);
909 strcatW(pathW
, allW
);
910 handle
= FindFirstFileW(pathW
, &data
);
911 if (handle
== INVALID_HANDLE_VALUE
)
912 return HRESULT_FROM_WIN32(GetLastError());
916 if (data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
918 } while (FindNextFileW(handle
, &data
));
924 static const IFolderCollectionVtbl foldercollvtbl
= {
925 foldercoll_QueryInterface
,
928 foldercoll_GetTypeInfoCount
,
929 foldercoll_GetTypeInfo
,
930 foldercoll_GetIDsOfNames
,
934 foldercoll_get__NewEnum
,
938 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
940 struct foldercollection
*This
;
944 This
= heap_alloc(sizeof(struct foldercollection
));
945 if (!This
) return E_OUTOFMEMORY
;
947 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
949 This
->path
= SysAllocString(path
);
953 return E_OUTOFMEMORY
;
956 *folders
= &This
->IFolderCollection_iface
;
961 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
963 struct filecollection
*This
= impl_from_IFileCollection(iface
);
965 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
969 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
970 IsEqualIID( riid
, &IID_IDispatch
) ||
971 IsEqualIID( riid
, &IID_IUnknown
))
974 IFileCollection_AddRef(iface
);
977 return E_NOINTERFACE
;
982 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
984 struct filecollection
*This
= impl_from_IFileCollection(iface
);
985 ULONG ref
= InterlockedIncrement(&This
->ref
);
986 TRACE("(%p)->(%d)\n", This
, ref
);
990 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
992 struct filecollection
*This
= impl_from_IFileCollection(iface
);
993 ULONG ref
= InterlockedDecrement(&This
->ref
);
994 TRACE("(%p)->(%d)\n", This
, ref
);
998 SysFreeString(This
->path
);
1005 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1007 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1008 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1013 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1014 LCID lcid
, ITypeInfo
**ppTInfo
)
1016 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1017 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1018 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1021 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1022 LPOLESTR
*rgszNames
, UINT cNames
,
1023 LCID lcid
, DISPID
*rgDispId
)
1025 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1026 ITypeInfo
*typeinfo
;
1029 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1031 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1034 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1035 ITypeInfo_Release(typeinfo
);
1041 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1042 REFIID riid
, LCID lcid
, WORD wFlags
,
1043 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1044 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1046 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1047 ITypeInfo
*typeinfo
;
1050 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1051 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1053 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1056 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1057 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1058 ITypeInfo_Release(typeinfo
);
1064 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1066 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1067 FIXME("(%p)->(%p)\n", This
, file
);
1071 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1073 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1075 TRACE("(%p)->(%p)\n", This
, ppenum
);
1080 return create_filecoll_enum(This
, ppenum
);
1083 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1085 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1086 FIXME("(%p)->(%p)\n", This
, count
);
1090 static const IFileCollectionVtbl filecollectionvtbl
= {
1091 filecoll_QueryInterface
,
1094 filecoll_GetTypeInfoCount
,
1095 filecoll_GetTypeInfo
,
1096 filecoll_GetIDsOfNames
,
1099 filecoll_get__NewEnum
,
1103 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1105 struct filecollection
*This
;
1109 This
= heap_alloc(sizeof(*This
));
1110 if (!This
) return E_OUTOFMEMORY
;
1112 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1114 This
->path
= SysAllocString(path
);
1118 return E_OUTOFMEMORY
;
1121 *files
= &This
->IFileCollection_iface
;
1125 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
1127 struct folder
*This
= impl_from_IFolder(iface
);
1129 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1133 if (IsEqualIID( riid
, &IID_IFolder
) ||
1134 IsEqualIID( riid
, &IID_IDispatch
) ||
1135 IsEqualIID( riid
, &IID_IUnknown
))
1138 IFolder_AddRef(iface
);
1141 return E_NOINTERFACE
;
1146 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
1148 struct folder
*This
= impl_from_IFolder(iface
);
1149 ULONG ref
= InterlockedIncrement(&This
->ref
);
1150 TRACE("(%p)->(%d)\n", This
, ref
);
1154 static ULONG WINAPI
folder_Release(IFolder
*iface
)
1156 struct folder
*This
= impl_from_IFolder(iface
);
1157 ULONG ref
= InterlockedDecrement(&This
->ref
);
1158 TRACE("(%p)->(%d)\n", This
, ref
);
1162 SysFreeString(This
->path
);
1169 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
1171 struct folder
*This
= impl_from_IFolder(iface
);
1172 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1177 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
1178 LCID lcid
, ITypeInfo
**ppTInfo
)
1180 struct folder
*This
= impl_from_IFolder(iface
);
1181 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1182 return get_typeinfo(IFolder_tid
, ppTInfo
);
1185 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
1186 LPOLESTR
*rgszNames
, UINT cNames
,
1187 LCID lcid
, DISPID
*rgDispId
)
1189 struct folder
*This
= impl_from_IFolder(iface
);
1190 ITypeInfo
*typeinfo
;
1193 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1195 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
1198 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1199 ITypeInfo_Release(typeinfo
);
1205 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
1206 REFIID riid
, LCID lcid
, WORD wFlags
,
1207 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1208 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1210 struct folder
*This
= impl_from_IFolder(iface
);
1211 ITypeInfo
*typeinfo
;
1214 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1215 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1217 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
1220 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1221 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1222 ITypeInfo_Release(typeinfo
);
1228 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
1230 struct folder
*This
= impl_from_IFolder(iface
);
1231 FIXME("(%p)->(%p): stub\n", This
, path
);
1235 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
1237 struct folder
*This
= impl_from_IFolder(iface
);
1240 TRACE("(%p)->(%p)\n", This
, name
);
1247 ptr
= strrchrW(This
->path
, '\\');
1250 *name
= SysAllocString(ptr
+1);
1251 TRACE("%s\n", debugstr_w(*name
));
1252 if (!*name
) return E_OUTOFMEMORY
;
1260 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
1262 struct folder
*This
= impl_from_IFolder(iface
);
1263 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1267 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
1269 struct folder
*This
= impl_from_IFolder(iface
);
1270 FIXME("(%p)->(%p): stub\n", This
, path
);
1274 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
1276 struct folder
*This
= impl_from_IFolder(iface
);
1277 FIXME("(%p)->(%p): stub\n", This
, name
);
1281 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
1283 struct folder
*This
= impl_from_IFolder(iface
);
1284 FIXME("(%p)->(%p): stub\n", This
, drive
);
1288 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
1290 struct folder
*This
= impl_from_IFolder(iface
);
1291 FIXME("(%p)->(%p): stub\n", This
, parent
);
1295 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
1297 struct folder
*This
= impl_from_IFolder(iface
);
1298 FIXME("(%p)->(%p): stub\n", This
, attr
);
1302 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
1304 struct folder
*This
= impl_from_IFolder(iface
);
1305 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
1309 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
1311 struct folder
*This
= impl_from_IFolder(iface
);
1312 FIXME("(%p)->(%p): stub\n", This
, date
);
1316 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
1318 struct folder
*This
= impl_from_IFolder(iface
);
1319 FIXME("(%p)->(%p): stub\n", This
, date
);
1323 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
1325 struct folder
*This
= impl_from_IFolder(iface
);
1326 FIXME("(%p)->(%p): stub\n", This
, date
);
1330 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
1332 struct folder
*This
= impl_from_IFolder(iface
);
1333 FIXME("(%p)->(%p): stub\n", This
, type
);
1337 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
1339 struct folder
*This
= impl_from_IFolder(iface
);
1340 FIXME("(%p)->(%x): stub\n", This
, force
);
1344 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
1346 struct folder
*This
= impl_from_IFolder(iface
);
1347 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
1351 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
1353 struct folder
*This
= impl_from_IFolder(iface
);
1354 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
1358 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
1360 struct folder
*This
= impl_from_IFolder(iface
);
1361 FIXME("(%p)->(%p): stub\n", This
, isroot
);
1365 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
1367 struct folder
*This
= impl_from_IFolder(iface
);
1368 FIXME("(%p)->(%p): stub\n", This
, size
);
1372 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
1374 struct folder
*This
= impl_from_IFolder(iface
);
1376 TRACE("(%p)->(%p)\n", This
, folders
);
1381 return create_foldercoll(This
->path
, folders
);
1384 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
1386 struct folder
*This
= impl_from_IFolder(iface
);
1388 TRACE("(%p)->(%p)\n", This
, files
);
1393 return create_filecoll(This
->path
, files
);
1396 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
1397 VARIANT_BOOL unicode
, ITextStream
**stream
)
1399 struct folder
*This
= impl_from_IFolder(iface
);
1400 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
1404 static const IFolderVtbl foldervtbl
= {
1405 folder_QueryInterface
,
1408 folder_GetTypeInfoCount
,
1410 folder_GetIDsOfNames
,
1415 folder_get_ShortPath
,
1416 folder_get_ShortName
,
1418 folder_get_ParentFolder
,
1419 folder_get_Attributes
,
1420 folder_put_Attributes
,
1421 folder_get_DateCreated
,
1422 folder_get_DateLastModified
,
1423 folder_get_DateLastAccessed
,
1428 folder_get_IsRootFolder
,
1430 folder_get_SubFolders
,
1432 folder_CreateTextFile
1435 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
1437 struct folder
*This
;
1441 TRACE("%s\n", debugstr_w(path
));
1443 This
= heap_alloc(sizeof(struct folder
));
1444 if (!This
) return E_OUTOFMEMORY
;
1446 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
1448 This
->path
= SysAllocString(path
);
1452 return E_OUTOFMEMORY
;
1455 *folder
= &This
->IFolder_iface
;
1460 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
1462 struct file
*This
= impl_from_IFile(iface
);
1464 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1466 if (IsEqualIID(riid
, &IID_IFile
) ||
1467 IsEqualIID(riid
, &IID_IDispatch
) ||
1468 IsEqualIID(riid
, &IID_IUnknown
))
1471 IFile_AddRef(iface
);
1476 return E_NOINTERFACE
;
1479 static ULONG WINAPI
file_AddRef(IFile
*iface
)
1481 struct file
*This
= impl_from_IFile(iface
);
1482 LONG ref
= InterlockedIncrement(&This
->ref
);
1484 TRACE("(%p) ref=%d\n", This
, ref
);
1489 static ULONG WINAPI
file_Release(IFile
*iface
)
1491 struct file
*This
= impl_from_IFile(iface
);
1492 LONG ref
= InterlockedDecrement(&This
->ref
);
1494 TRACE("(%p) ref=%d\n", This
, ref
);
1497 heap_free(This
->path
);
1502 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
1504 struct file
*This
= impl_from_IFile(iface
);
1506 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1512 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
1513 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1515 struct file
*This
= impl_from_IFile(iface
);
1517 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1519 return get_typeinfo(IFile_tid
, ppTInfo
);
1522 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
1523 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1525 struct file
*This
= impl_from_IFile(iface
);
1526 ITypeInfo
*typeinfo
;
1529 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
1530 rgszNames
, cNames
, lcid
, rgDispId
);
1532 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
1534 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1535 ITypeInfo_Release(typeinfo
);
1540 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1542 struct file
*This
= impl_from_IFile(iface
);
1543 ITypeInfo
*typeinfo
;
1546 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1547 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1549 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
1552 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1553 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1554 ITypeInfo_Release(typeinfo
);
1559 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
1561 struct file
*This
= impl_from_IFile(iface
);
1562 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
1566 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
1568 struct file
*This
= impl_from_IFile(iface
);
1571 TRACE("(%p)->(%p)\n", This
, name
);
1578 ptr
= strrchrW(This
->path
, '\\');
1581 *name
= SysAllocString(ptr
+1);
1582 TRACE("%s\n", debugstr_w(*name
));
1583 if (!*name
) return E_OUTOFMEMORY
;
1591 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
1593 struct file
*This
= impl_from_IFile(iface
);
1594 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
1598 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
1600 struct file
*This
= impl_from_IFile(iface
);
1601 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
1605 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
1607 struct file
*This
= impl_from_IFile(iface
);
1608 FIXME("(%p)->(%p)\n", This
, pbstrName
);
1612 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
1614 struct file
*This
= impl_from_IFile(iface
);
1615 FIXME("(%p)->(%p)\n", This
, ppdrive
);
1619 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
1621 struct file
*This
= impl_from_IFile(iface
);
1622 FIXME("(%p)->(%p)\n", This
, ppfolder
);
1626 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
1628 struct file
*This
= impl_from_IFile(iface
);
1631 TRACE("(%p)->(%p)\n", This
, pfa
);
1636 fa
= GetFileAttributesW(This
->path
);
1637 if(fa
== INVALID_FILE_ATTRIBUTES
)
1638 return create_error(GetLastError());
1640 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
1641 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
1642 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
1646 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
1648 struct file
*This
= impl_from_IFile(iface
);
1649 FIXME("(%p)->(%x)\n", This
, pfa
);
1653 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
1655 struct file
*This
= impl_from_IFile(iface
);
1656 FIXME("(%p)->(%p)\n", This
, pdate
);
1660 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
1662 struct file
*This
= impl_from_IFile(iface
);
1663 FIXME("(%p)->(%p)\n", This
, pdate
);
1667 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
1669 struct file
*This
= impl_from_IFile(iface
);
1670 FIXME("(%p)->(%p)\n", This
, pdate
);
1674 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
1676 struct file
*This
= impl_from_IFile(iface
);
1677 WIN32_FIND_DATAW fd
;
1680 TRACE("(%p)->(%p)\n", This
, pvarSize
);
1685 f
= FindFirstFileW(This
->path
, &fd
);
1686 if(f
== INVALID_HANDLE_VALUE
)
1687 return create_error(GetLastError());
1690 if(fd
.nFileSizeHigh
|| fd
.nFileSizeLow
>INT_MAX
) {
1691 V_VT(pvarSize
) = VT_R8
;
1692 V_R8(pvarSize
) = ((ULONGLONG
)fd
.nFileSizeHigh
<<32) + fd
.nFileSizeLow
;
1694 V_VT(pvarSize
) = VT_I4
;
1695 V_I4(pvarSize
) = fd
.nFileSizeLow
;
1700 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
1702 struct file
*This
= impl_from_IFile(iface
);
1703 FIXME("(%p)->(%p)\n", This
, pbstrType
);
1707 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
1709 struct file
*This
= impl_from_IFile(iface
);
1710 FIXME("(%p)->(%x)\n", This
, Force
);
1714 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
1716 struct file
*This
= impl_from_IFile(iface
);
1717 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
1721 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
1723 struct file
*This
= impl_from_IFile(iface
);
1724 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
1728 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode IOMode
, Tristate Format
, ITextStream
**ppts
)
1730 struct file
*This
= impl_from_IFile(iface
);
1731 FIXME("(%p)->(%x %x %p)\n", This
, IOMode
, Format
, ppts
);
1735 static const IFileVtbl file_vtbl
= {
1736 file_QueryInterface
,
1739 file_GetTypeInfoCount
,
1749 file_get_ParentFolder
,
1750 file_get_Attributes
,
1751 file_put_Attributes
,
1752 file_get_DateCreated
,
1753 file_get_DateLastModified
,
1754 file_get_DateLastAccessed
,
1760 file_OpenAsTextStream
1763 static HRESULT
create_file(BSTR path
, IFile
**file
)
1770 f
= heap_alloc(sizeof(struct file
));
1772 return E_OUTOFMEMORY
;
1774 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
1777 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
1783 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
1786 return E_OUTOFMEMORY
;
1789 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
1795 if(path
[len
-1]=='/' || path
[len
-1]=='\\')
1798 attrs
= GetFileAttributesW(f
->path
);
1799 if(attrs
==INVALID_FILE_ATTRIBUTES
||
1800 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
1803 return create_error(GetLastError());
1806 *file
= &f
->IFile_iface
;
1810 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
1812 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
1814 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
1815 IsEqualGUID( riid
, &IID_IFileSystem
) ||
1816 IsEqualGUID( riid
, &IID_IDispatch
) ||
1817 IsEqualGUID( riid
, &IID_IUnknown
) )
1821 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
1823 TRACE("Interface IDispatchEx not supported - returning NULL\n");
1825 return E_NOINTERFACE
;
1827 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
1829 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
1831 return E_NOINTERFACE
;
1835 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
1836 return E_NOINTERFACE
;
1839 IFileSystem3_AddRef(iface
);
1844 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
1846 TRACE("%p\n", iface
);
1851 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
1853 TRACE("%p\n", iface
);
1858 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
1860 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
1866 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
1867 LCID lcid
, ITypeInfo
**ppTInfo
)
1869 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
1870 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
1873 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
1874 LPOLESTR
*rgszNames
, UINT cNames
,
1875 LCID lcid
, DISPID
*rgDispId
)
1877 ITypeInfo
*typeinfo
;
1880 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1882 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
1885 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1886 ITypeInfo_Release(typeinfo
);
1892 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
1893 REFIID riid
, LCID lcid
, WORD wFlags
,
1894 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1895 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1897 ITypeInfo
*typeinfo
;
1900 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
1901 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1903 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
1906 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1907 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1908 ITypeInfo_Release(typeinfo
);
1914 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
1916 FIXME("%p %p\n", iface
, ppdrives
);
1921 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
1922 BSTR Name
, BSTR
*Result
)
1926 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
1928 if (!Result
) return E_POINTER
;
1932 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
1934 /* if both parts have backslashes strip one from Path */
1935 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
1939 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
1947 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
1949 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
1953 if (Path
[path_len
-1] != ':')
1960 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
1968 else if (Path
|| Name
)
1969 ret
= SysAllocString(Path
? Path
: Name
);
1971 ret
= SysAllocStringLen(NULL
, 0);
1973 if (!ret
) return E_OUTOFMEMORY
;
1979 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR Path
,
1982 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1987 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
1994 for(i
=len
-1; i
>=0; i
--)
1995 if(path
[i
]!='/' && path
[i
]!='\\')
1999 if(path
[i
]=='/' || path
[i
]=='\\')
2003 if(path
[i
]!='/' && path
[i
]!='\\')
2009 if(path
[i
]==':' && i
==1)
2014 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
2019 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2024 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
2026 *pbstrResult
= NULL
;
2030 *pbstrResult
= SysAllocStringLen(Path
, len
);
2032 return E_OUTOFMEMORY
;
2036 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
2041 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2047 *pbstrResult
= NULL
;
2051 for(end
=strlenW(Path
)-1; end
>=0; end
--)
2052 if(Path
[end
]!='/' && Path
[end
]!='\\')
2055 for(i
=end
; i
>=0; i
--)
2056 if(Path
[i
]=='/' || Path
[i
]=='\\')
2060 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
2061 *pbstrResult
= NULL
;
2065 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
2067 return E_OUTOFMEMORY
;
2071 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
2076 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2082 *pbstrResult
= NULL
;
2086 for(end
=strlenW(Path
)-1; end
>=0; end
--)
2087 if(Path
[end
]!='/' && Path
[end
]!='\\')
2090 for(i
=end
; i
>=0; i
--) {
2091 if(Path
[i
]=='.' && Path
[end
+1]!='.')
2093 if(Path
[i
]=='/' || Path
[i
]=='\\')
2098 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
2099 *pbstrResult
= NULL
;
2103 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
2105 return E_OUTOFMEMORY
;
2109 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
2112 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2117 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
2120 static const WCHAR cur_path
[] = {'.',0};
2122 WCHAR buf
[MAX_PATH
], ch
;
2124 DWORD i
, beg
, len
, exp_len
;
2125 WIN32_FIND_DATAW fdata
;
2128 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2138 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
2142 buf
[0] = toupperW(buf
[0]);
2143 if(len
>3 && buf
[len
-1] == '\\')
2146 for(beg
=3, i
=3; i
<=len
; i
++) {
2147 if(buf
[i
]!='\\' && buf
[i
])
2152 fh
= FindFirstFileW(buf
, &fdata
);
2153 if(fh
== INVALID_HANDLE_VALUE
)
2156 exp_len
= strlenW(fdata
.cFileName
);
2157 if(exp_len
== i
-beg
)
2158 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
2164 *pbstrResult
= SysAllocString(buf
);
2166 return E_OUTOFMEMORY
;
2170 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
2172 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
2176 TRACE("%p %p\n", iface
, pbstrResult
);
2181 *pbstrResult
= SysAllocStringLen(NULL
, 12);
2183 return E_OUTOFMEMORY
;
2185 if(!RtlGenRandom(&random
, sizeof(random
)))
2187 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
2191 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
2192 VARIANT_BOOL
*pfExists
)
2194 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
2199 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
2202 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
2204 if (!ret
) return E_POINTER
;
2206 attrs
= GetFileAttributesW(path
);
2207 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2211 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
2214 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
2216 if (!ret
) return E_POINTER
;
2218 attrs
= GetFileAttributesW(path
);
2219 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2224 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
2227 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
2232 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
2235 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
2240 return E_INVALIDARG
;
2242 return create_file(FilePath
, ppfile
);
2245 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
2250 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
2257 return E_INVALIDARG
;
2259 attrs
= GetFileAttributesW(FolderPath
);
2260 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
2261 return CTL_E_PATHNOTFOUND
;
2263 return create_folder(FolderPath
, folder
);
2266 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
2267 SpecialFolderConst SpecialFolder
,
2270 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
2275 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
2277 WCHAR path
[MAX_PATH
];
2278 DWORD len
, name_len
;
2279 WIN32_FIND_DATAW ffd
;
2282 f
= FindFirstFileW(file
, &ffd
);
2283 if(f
== INVALID_HANDLE_VALUE
)
2284 return create_error(GetLastError());
2286 len
= get_parent_folder_name(file
, file_len
);
2287 if(len
+1 >= MAX_PATH
) {
2292 memcpy(path
, file
, len
*sizeof(WCHAR
));
2297 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
2300 name_len
= strlenW(ffd
.cFileName
);
2301 if(len
+name_len
+1 >= MAX_PATH
) {
2305 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
2307 TRACE("deleting %s\n", debugstr_w(path
));
2309 if(!DeleteFileW(path
)) {
2310 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
2311 || !DeleteFileW(path
)) {
2313 return create_error(GetLastError());
2316 } while(FindNextFileW(f
, &ffd
));
2322 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
2325 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
2330 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
2333 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
2335 WCHAR path
[MAX_PATH
];
2336 DWORD len
, name_len
;
2337 WIN32_FIND_DATAW ffd
;
2341 f
= FindFirstFileW(folder
, &ffd
);
2342 if(f
== INVALID_HANDLE_VALUE
)
2343 return create_error(GetLastError());
2345 len
= get_parent_folder_name(folder
, folder_len
);
2346 if(len
+1 >= MAX_PATH
) {
2351 memcpy(path
, folder
, len
*sizeof(WCHAR
));
2356 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
2358 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
2359 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
2362 name_len
= strlenW(ffd
.cFileName
);
2363 if(len
+name_len
+3 >= MAX_PATH
) {
2367 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
2368 path
[len
+name_len
] = '\\';
2369 path
[len
+name_len
+1] = '*';
2370 path
[len
+name_len
+2] = 0;
2372 hr
= delete_file(path
, len
+name_len
+2, force
);
2378 hr
= delete_folder(path
, len
+name_len
+2, force
);
2384 path
[len
+name_len
] = 0;
2385 TRACE("deleting %s\n", debugstr_w(path
));
2387 if(!RemoveDirectoryW(path
)) {
2389 return create_error(GetLastError());
2391 } while(FindNextFileW(f
, &ffd
));
2397 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
2400 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
2405 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
2408 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
2411 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
2416 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
2419 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
2424 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
2425 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
2428 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
2429 DWORD src_len
, dst_len
, name_len
;
2430 WIN32_FIND_DATAW ffd
;
2434 if(!source
[0] || !destination
[0])
2435 return E_INVALIDARG
;
2437 attrs
= GetFileAttributesW(destination
);
2438 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
2439 attrs
= GetFileAttributesW(source
);
2440 if(attrs
== INVALID_FILE_ATTRIBUTES
)
2441 return create_error(GetLastError());
2442 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
2443 return CTL_E_FILENOTFOUND
;
2445 if(!CopyFileW(source
, destination
, !overwrite
))
2446 return create_error(GetLastError());
2450 f
= FindFirstFileW(source
, &ffd
);
2451 if(f
== INVALID_HANDLE_VALUE
)
2452 return CTL_E_FILENOTFOUND
;
2454 src_len
= get_parent_folder_name(source
, source_len
);
2455 if(src_len
+1 >= MAX_PATH
)
2458 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
2459 src_path
[src_len
++] = '\\';
2462 dst_len
= destination_len
;
2463 if(dst_len
+1 >= MAX_PATH
) {
2467 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
2468 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
2469 dst_path
[dst_len
++] = '\\';
2471 hr
= CTL_E_FILENOTFOUND
;
2473 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
2476 name_len
= strlenW(ffd
.cFileName
);
2477 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
2481 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
2482 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
2484 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
2486 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
2488 return create_error(GetLastError());
2492 } while(FindNextFileW(f
, &ffd
));
2498 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
2499 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2501 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
2503 if(!Source
|| !Destination
)
2506 return copy_file(Source
, SysStringLen(Source
), Destination
,
2507 SysStringLen(Destination
), OverWriteFiles
);
2510 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
2511 DWORD destination_len
, VARIANT_BOOL overwrite
)
2513 DWORD tmp
, src_len
, dst_len
, name_len
;
2514 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
2515 WIN32_FIND_DATAW ffd
;
2518 BOOL copied
= FALSE
;
2520 if(!source
[0] || !destination
[0])
2521 return E_INVALIDARG
;
2523 dst_len
= destination_len
;
2524 if(dst_len
+1 >= MAX_PATH
)
2526 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
2528 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
2529 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
2530 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
2531 if(!CreateDirectoryW(dst
, NULL
)) {
2532 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
2533 tmp
= GetFileAttributesW(dst
);
2534 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
2535 return CTL_E_FILEALREADYEXISTS
;
2537 return create_error(GetLastError());
2542 src_len
= source_len
;
2543 if(src_len
+2 >= MAX_PATH
)
2545 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
2546 src
[src_len
++] = '\\';
2550 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
2551 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
2552 return create_error(GetLastError());
2554 f
= FindFirstFileW(src
, &ffd
);
2556 src_len
= get_parent_folder_name(source
, source_len
);
2557 if(src_len
+2 >= MAX_PATH
)
2559 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
2561 src
[src_len
++] = '\\';
2563 f
= FindFirstFileW(source
, &ffd
);
2565 if(f
== INVALID_HANDLE_VALUE
)
2566 return CTL_E_PATHNOTFOUND
;
2568 dst
[dst_len
++] = '\\';
2572 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
2574 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
2575 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
2578 name_len
= strlenW(ffd
.cFileName
);
2579 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
2583 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
2584 dst
[dst_len
+name_len
] = 0;
2585 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
2586 src
[src_len
+name_len
] = '\\';
2587 src
[src_len
+name_len
+1] = '*';
2588 src
[src_len
+name_len
+2] = 0;
2590 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
2592 if(!CreateDirectoryW(dst
, NULL
)) {
2593 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
2594 tmp
= GetFileAttributesW(dst
);
2595 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
2597 return CTL_E_FILEALREADYEXISTS
;
2601 return create_error(GetLastError());
2603 return create_error(GetLastError());
2607 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
2608 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
2613 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
2614 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
2618 } while(FindNextFileW(f
, &ffd
));
2621 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
2624 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
2625 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2627 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
2629 if(!Source
|| !Destination
)
2632 return copy_folder(Source
, SysStringLen(Source
), Destination
,
2633 SysStringLen(Destination
), OverWriteFiles
);
2636 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
2641 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
2643 ret
= CreateDirectoryW(path
, NULL
);
2647 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
2648 return HRESULT_FROM_WIN32(GetLastError());
2651 return create_folder(path
, folder
);
2654 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR FileName
,
2655 VARIANT_BOOL Overwrite
, VARIANT_BOOL Unicode
,
2658 FIXME("%p %s %d %d %p\n", iface
, debugstr_w(FileName
), Overwrite
, Unicode
, ppts
);
2663 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
2664 IOMode mode
, VARIANT_BOOL create
,
2665 Tristate format
, ITextStream
**stream
)
2667 FIXME("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
2668 return create_textstream(mode
, stream
);
2671 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
2672 StandardStreamTypes StandardStreamType
,
2673 VARIANT_BOOL Unicode
,
2676 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
2681 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
2683 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
2687 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
2688 a
= (WORD
)( version
>> 48);
2689 b
= (WORD
)((version
>> 32) & 0xffff);
2690 c
= (WORD
)((version
>> 16) & 0xffff);
2691 d
= (WORD
)( version
& 0xffff);
2693 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
2696 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
2698 static const WCHAR rootW
[] = {'\\',0};
2699 VS_FIXEDFILEINFO
*info
;
2705 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
2707 len
= GetFileVersionInfoSizeW(name
, NULL
);
2709 return HRESULT_FROM_WIN32(GetLastError());
2711 ptr
= heap_alloc(len
);
2712 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
2715 return HRESULT_FROM_WIN32(GetLastError());
2718 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
2721 return HRESULT_FROM_WIN32(GetLastError());
2723 get_versionstring(info
, ver
);
2724 *version
= SysAllocString(ver
);
2725 TRACE("version=%s\n", debugstr_w(ver
));
2730 static const struct IFileSystem3Vtbl filesys_vtbl
=
2732 filesys_QueryInterface
,
2735 filesys_GetTypeInfoCount
,
2736 filesys_GetTypeInfo
,
2737 filesys_GetIDsOfNames
,
2741 filesys_GetDriveName
,
2742 filesys_GetParentFolderName
,
2743 filesys_GetFileName
,
2744 filesys_GetBaseName
,
2745 filesys_GetExtensionName
,
2746 filesys_GetAbsolutePathName
,
2747 filesys_GetTempName
,
2748 filesys_DriveExists
,
2750 filesys_FolderExists
,
2754 filesys_GetSpecialFolder
,
2756 filesys_DeleteFolder
,
2761 filesys_CreateFolder
,
2762 filesys_CreateTextFile
,
2763 filesys_OpenTextFile
,
2764 filesys_GetStandardStream
,
2765 filesys_GetFileVersion
2768 static IFileSystem3 filesystem
= { &filesys_vtbl
};
2770 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
2772 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
2774 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);