2 * Copyright 2012 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "scrrun_private.h"
24 #include <wine/unicode.h>
27 IFolder IFolder_iface
;
39 ITextStream ITextStream_iface
;
50 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
52 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
55 static inline struct file
*impl_from_IFile(IFile
*iface
)
57 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
60 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
62 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
65 static inline HRESULT
create_error(DWORD err
)
68 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
69 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
70 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
71 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
72 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
74 FIXME("Unsupported error code: %d\n", err
);
79 static int textstream_check_iomode(struct textstream
*This
, enum iotype type
)
82 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
87 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
89 struct textstream
*This
= impl_from_ITextStream(iface
);
91 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
93 if (IsEqualIID(riid
, &IID_ITextStream
) ||
94 IsEqualIID(riid
, &IID_IDispatch
) ||
95 IsEqualIID(riid
, &IID_IUnknown
))
98 ITextStream_AddRef(iface
);
103 return E_NOINTERFACE
;
106 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
108 struct textstream
*This
= impl_from_ITextStream(iface
);
109 ULONG ref
= InterlockedIncrement(&This
->ref
);
110 TRACE("(%p)->(%d)\n", This
, ref
);
114 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
116 struct textstream
*This
= impl_from_ITextStream(iface
);
117 ULONG ref
= InterlockedDecrement(&This
->ref
);
118 TRACE("(%p)->(%d)\n", This
, ref
);
126 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
128 struct textstream
*This
= impl_from_ITextStream(iface
);
129 TRACE("(%p)->(%p)\n", This
, pctinfo
);
134 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
135 LCID lcid
, ITypeInfo
**ppTInfo
)
137 struct textstream
*This
= impl_from_ITextStream(iface
);
138 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
139 return get_typeinfo(ITextStream_tid
, ppTInfo
);
142 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
143 LPOLESTR
*rgszNames
, UINT cNames
,
144 LCID lcid
, DISPID
*rgDispId
)
146 struct textstream
*This
= impl_from_ITextStream(iface
);
150 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
152 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
155 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
156 ITypeInfo_Release(typeinfo
);
162 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
163 REFIID riid
, LCID lcid
, WORD wFlags
,
164 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
165 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
167 struct textstream
*This
= impl_from_ITextStream(iface
);
171 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
172 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
174 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
177 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
178 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
179 ITypeInfo_Release(typeinfo
);
185 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
187 struct textstream
*This
= impl_from_ITextStream(iface
);
188 FIXME("(%p)->(%p): stub\n", This
, line
);
192 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
194 struct textstream
*This
= impl_from_ITextStream(iface
);
195 FIXME("(%p)->(%p): stub\n", This
, column
);
199 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
201 struct textstream
*This
= impl_from_ITextStream(iface
);
202 FIXME("(%p)->(%p): stub\n", This
, eos
);
206 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
208 struct textstream
*This
= impl_from_ITextStream(iface
);
209 FIXME("(%p)->(%p): stub\n", This
, eol
);
213 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
215 struct textstream
*This
= impl_from_ITextStream(iface
);
216 FIXME("(%p)->(%p): stub\n", This
, text
);
218 if (textstream_check_iomode(This
, IORead
))
219 return CTL_E_BADFILEMODE
;
224 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
226 struct textstream
*This
= impl_from_ITextStream(iface
);
227 FIXME("(%p)->(%p): stub\n", This
, text
);
229 if (textstream_check_iomode(This
, IORead
))
230 return CTL_E_BADFILEMODE
;
235 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
237 struct textstream
*This
= impl_from_ITextStream(iface
);
238 FIXME("(%p)->(%p): stub\n", This
, text
);
240 if (textstream_check_iomode(This
, IORead
))
241 return CTL_E_BADFILEMODE
;
246 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
248 struct textstream
*This
= impl_from_ITextStream(iface
);
249 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(text
));
253 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
255 struct textstream
*This
= impl_from_ITextStream(iface
);
256 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(text
));
260 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
262 struct textstream
*This
= impl_from_ITextStream(iface
);
263 FIXME("(%p)->(%d): stub\n", This
, lines
);
267 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
269 struct textstream
*This
= impl_from_ITextStream(iface
);
270 FIXME("(%p)->(%d): stub\n", This
, count
);
274 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
276 struct textstream
*This
= impl_from_ITextStream(iface
);
277 FIXME("(%p): stub\n", This
);
281 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
283 struct textstream
*This
= impl_from_ITextStream(iface
);
284 FIXME("(%p): stub\n", This
);
288 static const ITextStreamVtbl textstreamvtbl
= {
289 textstream_QueryInterface
,
292 textstream_GetTypeInfoCount
,
293 textstream_GetTypeInfo
,
294 textstream_GetIDsOfNames
,
297 textstream_get_Column
,
298 textstream_get_AtEndOfStream
,
299 textstream_get_AtEndOfLine
,
304 textstream_WriteLine
,
305 textstream_WriteBlankLines
,
311 static HRESULT
create_textstream(IOMode mode
, ITextStream
**ret
)
313 struct textstream
*stream
;
315 stream
= heap_alloc(sizeof(struct textstream
));
316 if (!stream
) return E_OUTOFMEMORY
;
318 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
322 *ret
= &stream
->ITextStream_iface
;
326 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
328 struct folder
*This
= impl_from_IFolder(iface
);
330 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
334 if (IsEqualGUID( riid
, &IID_IFolder
) ||
335 IsEqualGUID( riid
, &IID_IUnknown
))
338 IFolder_AddRef(iface
);
341 return E_NOINTERFACE
;
346 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
348 struct folder
*This
= impl_from_IFolder(iface
);
349 ULONG ref
= InterlockedIncrement(&This
->ref
);
350 TRACE("(%p)->(%d)\n", This
, ref
);
354 static ULONG WINAPI
folder_Release(IFolder
*iface
)
356 struct folder
*This
= impl_from_IFolder(iface
);
357 ULONG ref
= InterlockedDecrement(&This
->ref
);
358 TRACE("(%p)->(%d)\n", This
, ref
);
366 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
368 struct folder
*This
= impl_from_IFolder(iface
);
369 TRACE("(%p)->(%p)\n", This
, pctinfo
);
374 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
375 LCID lcid
, ITypeInfo
**ppTInfo
)
377 struct folder
*This
= impl_from_IFolder(iface
);
378 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
379 return get_typeinfo(IFolder_tid
, ppTInfo
);
382 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
383 LPOLESTR
*rgszNames
, UINT cNames
,
384 LCID lcid
, DISPID
*rgDispId
)
386 struct folder
*This
= impl_from_IFolder(iface
);
390 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
392 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
395 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
396 ITypeInfo_Release(typeinfo
);
402 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
403 REFIID riid
, LCID lcid
, WORD wFlags
,
404 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
405 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
407 struct folder
*This
= impl_from_IFolder(iface
);
411 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
412 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
414 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
417 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
418 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
419 ITypeInfo_Release(typeinfo
);
425 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
427 struct folder
*This
= impl_from_IFolder(iface
);
428 FIXME("(%p)->(%p): stub\n", This
, path
);
432 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
434 struct folder
*This
= impl_from_IFolder(iface
);
435 FIXME("(%p)->(%p): stub\n", This
, name
);
439 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
441 struct folder
*This
= impl_from_IFolder(iface
);
442 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
446 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
448 struct folder
*This
= impl_from_IFolder(iface
);
449 FIXME("(%p)->(%p): stub\n", This
, path
);
453 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
455 struct folder
*This
= impl_from_IFolder(iface
);
456 FIXME("(%p)->(%p): stub\n", This
, name
);
460 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
462 struct folder
*This
= impl_from_IFolder(iface
);
463 FIXME("(%p)->(%p): stub\n", This
, drive
);
467 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
469 struct folder
*This
= impl_from_IFolder(iface
);
470 FIXME("(%p)->(%p): stub\n", This
, parent
);
474 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
476 struct folder
*This
= impl_from_IFolder(iface
);
477 FIXME("(%p)->(%p): stub\n", This
, attr
);
481 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
483 struct folder
*This
= impl_from_IFolder(iface
);
484 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
488 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
490 struct folder
*This
= impl_from_IFolder(iface
);
491 FIXME("(%p)->(%p): stub\n", This
, date
);
495 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
497 struct folder
*This
= impl_from_IFolder(iface
);
498 FIXME("(%p)->(%p): stub\n", This
, date
);
502 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
504 struct folder
*This
= impl_from_IFolder(iface
);
505 FIXME("(%p)->(%p): stub\n", This
, date
);
509 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
511 struct folder
*This
= impl_from_IFolder(iface
);
512 FIXME("(%p)->(%p): stub\n", This
, type
);
516 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
518 struct folder
*This
= impl_from_IFolder(iface
);
519 FIXME("(%p)->(%x): stub\n", This
, force
);
523 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
525 struct folder
*This
= impl_from_IFolder(iface
);
526 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
530 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
532 struct folder
*This
= impl_from_IFolder(iface
);
533 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
537 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
539 struct folder
*This
= impl_from_IFolder(iface
);
540 FIXME("(%p)->(%p): stub\n", This
, isroot
);
544 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
546 struct folder
*This
= impl_from_IFolder(iface
);
547 FIXME("(%p)->(%p): stub\n", This
, size
);
551 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
553 struct folder
*This
= impl_from_IFolder(iface
);
554 FIXME("(%p)->(%p): stub\n", This
, folders
);
558 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
560 struct folder
*This
= impl_from_IFolder(iface
);
561 FIXME("(%p)->(%p): stub\n", This
, files
);
565 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
566 VARIANT_BOOL unicode
, ITextStream
**stream
)
568 struct folder
*This
= impl_from_IFolder(iface
);
569 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
573 static const IFolderVtbl foldervtbl
= {
574 folder_QueryInterface
,
577 folder_GetTypeInfoCount
,
579 folder_GetIDsOfNames
,
584 folder_get_ShortPath
,
585 folder_get_ShortName
,
587 folder_get_ParentFolder
,
588 folder_get_Attributes
,
589 folder_put_Attributes
,
590 folder_get_DateCreated
,
591 folder_get_DateLastModified
,
592 folder_get_DateLastAccessed
,
597 folder_get_IsRootFolder
,
599 folder_get_SubFolders
,
601 folder_CreateTextFile
604 static HRESULT
create_folder(IFolder
**folder
)
608 This
= heap_alloc(sizeof(struct folder
));
609 if (!This
) return E_OUTOFMEMORY
;
611 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
614 *folder
= &This
->IFolder_iface
;
619 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
621 struct file
*This
= impl_from_IFile(iface
);
623 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
625 if (IsEqualIID(riid
, &IID_IFile
) ||
626 IsEqualIID(riid
, &IID_IDispatch
) ||
627 IsEqualIID(riid
, &IID_IUnknown
))
635 return E_NOINTERFACE
;
638 static ULONG WINAPI
file_AddRef(IFile
*iface
)
640 struct file
*This
= impl_from_IFile(iface
);
641 LONG ref
= InterlockedIncrement(&This
->ref
);
643 TRACE("(%p) ref=%d\n", This
, ref
);
648 static ULONG WINAPI
file_Release(IFile
*iface
)
650 struct file
*This
= impl_from_IFile(iface
);
651 LONG ref
= InterlockedDecrement(&This
->ref
);
653 TRACE("(%p) ref=%d\n", This
, ref
);
656 heap_free(This
->path
);
661 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
663 struct file
*This
= impl_from_IFile(iface
);
665 TRACE("(%p)->(%p)\n", This
, pctinfo
);
671 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
672 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
674 struct file
*This
= impl_from_IFile(iface
);
676 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
678 return get_typeinfo(IFile_tid
, ppTInfo
);
681 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
682 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
684 struct file
*This
= impl_from_IFile(iface
);
688 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
689 rgszNames
, cNames
, lcid
, rgDispId
);
691 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
693 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
694 ITypeInfo_Release(typeinfo
);
699 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
701 struct file
*This
= impl_from_IFile(iface
);
705 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
706 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
708 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
711 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
712 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
713 ITypeInfo_Release(typeinfo
);
718 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
720 struct file
*This
= impl_from_IFile(iface
);
721 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
725 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*pbstrName
)
727 struct file
*This
= impl_from_IFile(iface
);
728 FIXME("(%p)->(%p)\n", This
, pbstrName
);
732 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
734 struct file
*This
= impl_from_IFile(iface
);
735 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
739 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
741 struct file
*This
= impl_from_IFile(iface
);
742 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
746 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
748 struct file
*This
= impl_from_IFile(iface
);
749 FIXME("(%p)->(%p)\n", This
, pbstrName
);
753 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
755 struct file
*This
= impl_from_IFile(iface
);
756 FIXME("(%p)->(%p)\n", This
, ppdrive
);
760 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
762 struct file
*This
= impl_from_IFile(iface
);
763 FIXME("(%p)->(%p)\n", This
, ppfolder
);
767 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
769 struct file
*This
= impl_from_IFile(iface
);
772 TRACE("(%p)->(%p)\n", This
, pfa
);
777 fa
= GetFileAttributesW(This
->path
);
778 if(fa
== INVALID_FILE_ATTRIBUTES
)
779 return create_error(GetLastError());
781 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
782 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
783 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
787 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
789 struct file
*This
= impl_from_IFile(iface
);
790 FIXME("(%p)->(%x)\n", This
, pfa
);
794 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
796 struct file
*This
= impl_from_IFile(iface
);
797 FIXME("(%p)->(%p)\n", This
, pdate
);
801 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
803 struct file
*This
= impl_from_IFile(iface
);
804 FIXME("(%p)->(%p)\n", This
, pdate
);
808 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
810 struct file
*This
= impl_from_IFile(iface
);
811 FIXME("(%p)->(%p)\n", This
, pdate
);
815 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
817 struct file
*This
= impl_from_IFile(iface
);
821 TRACE("(%p)->(%p)\n", This
, pvarSize
);
826 f
= FindFirstFileW(This
->path
, &fd
);
827 if(f
== INVALID_HANDLE_VALUE
)
828 return create_error(GetLastError());
831 if(fd
.nFileSizeHigh
|| fd
.nFileSizeLow
>INT_MAX
) {
832 V_VT(pvarSize
) = VT_R8
;
833 V_R8(pvarSize
) = ((ULONGLONG
)fd
.nFileSizeHigh
<<32) + fd
.nFileSizeLow
;
835 V_VT(pvarSize
) = VT_I4
;
836 V_I4(pvarSize
) = fd
.nFileSizeLow
;
841 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
843 struct file
*This
= impl_from_IFile(iface
);
844 FIXME("(%p)->(%p)\n", This
, pbstrType
);
848 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
850 struct file
*This
= impl_from_IFile(iface
);
851 FIXME("(%p)->(%x)\n", This
, Force
);
855 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
857 struct file
*This
= impl_from_IFile(iface
);
858 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
862 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
864 struct file
*This
= impl_from_IFile(iface
);
865 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
869 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode IOMode
, Tristate Format
, ITextStream
**ppts
)
871 struct file
*This
= impl_from_IFile(iface
);
872 FIXME("(%p)->(%x %x %p)\n", This
, IOMode
, Format
, ppts
);
876 static const IFileVtbl file_vtbl
= {
880 file_GetTypeInfoCount
,
890 file_get_ParentFolder
,
893 file_get_DateCreated
,
894 file_get_DateLastModified
,
895 file_get_DateLastAccessed
,
901 file_OpenAsTextStream
904 static HRESULT
create_file(BSTR path
, IFile
**file
)
911 f
= heap_alloc(sizeof(struct file
));
913 return E_OUTOFMEMORY
;
915 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
918 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
924 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
927 return E_OUTOFMEMORY
;
930 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
936 if(path
[len
-1]=='/' || path
[len
-1]=='\\')
939 attrs
= GetFileAttributesW(f
->path
);
940 if(attrs
==INVALID_FILE_ATTRIBUTES
||
941 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
944 return create_error(GetLastError());
947 *file
= &f
->IFile_iface
;
951 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
953 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
955 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
956 IsEqualGUID( riid
, &IID_IFileSystem
) ||
957 IsEqualGUID( riid
, &IID_IDispatch
) ||
958 IsEqualGUID( riid
, &IID_IUnknown
) )
962 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
964 TRACE("Interface IDispatchEx not supported - returning NULL\n");
966 return E_NOINTERFACE
;
968 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
970 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
972 return E_NOINTERFACE
;
976 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
977 return E_NOINTERFACE
;
980 IFileSystem3_AddRef(iface
);
985 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
987 TRACE("%p\n", iface
);
992 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
994 TRACE("%p\n", iface
);
999 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
1001 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
1007 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
1008 LCID lcid
, ITypeInfo
**ppTInfo
)
1010 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
1011 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
1014 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
1015 LPOLESTR
*rgszNames
, UINT cNames
,
1016 LCID lcid
, DISPID
*rgDispId
)
1018 ITypeInfo
*typeinfo
;
1021 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1023 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
1026 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1027 ITypeInfo_Release(typeinfo
);
1033 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
1034 REFIID riid
, LCID lcid
, WORD wFlags
,
1035 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1036 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1038 ITypeInfo
*typeinfo
;
1041 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
1042 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1044 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
1047 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1048 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1049 ITypeInfo_Release(typeinfo
);
1055 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
1057 FIXME("%p %p\n", iface
, ppdrives
);
1062 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
1063 BSTR Name
, BSTR
*pbstrResult
)
1065 FIXME("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), pbstrResult
);
1070 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR Path
,
1073 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1078 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
1085 for(i
=len
-1; i
>=0; i
--)
1086 if(path
[i
]!='/' && path
[i
]!='\\')
1090 if(path
[i
]=='/' || path
[i
]=='\\')
1094 if(path
[i
]!='/' && path
[i
]!='\\')
1100 if(path
[i
]==':' && i
==1)
1105 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
1110 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1115 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
1117 *pbstrResult
= NULL
;
1121 *pbstrResult
= SysAllocStringLen(Path
, len
);
1123 return E_OUTOFMEMORY
;
1127 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
1132 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1138 *pbstrResult
= NULL
;
1142 for(end
=strlenW(Path
)-1; end
>=0; end
--)
1143 if(Path
[end
]!='/' && Path
[end
]!='\\')
1146 for(i
=end
; i
>=0; i
--)
1147 if(Path
[i
]=='/' || Path
[i
]=='\\')
1151 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
1152 *pbstrResult
= NULL
;
1156 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
1158 return E_OUTOFMEMORY
;
1162 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
1167 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1173 *pbstrResult
= NULL
;
1177 for(end
=strlenW(Path
)-1; end
>=0; end
--)
1178 if(Path
[end
]!='/' && Path
[end
]!='\\')
1181 for(i
=end
; i
>=0; i
--) {
1182 if(Path
[i
]=='.' && Path
[end
+1]!='.')
1184 if(Path
[i
]=='/' || Path
[i
]=='\\')
1189 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
1190 *pbstrResult
= NULL
;
1194 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
1196 return E_OUTOFMEMORY
;
1200 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
1203 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1208 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
1211 static const WCHAR cur_path
[] = {'.',0};
1213 WCHAR buf
[MAX_PATH
], ch
;
1215 DWORD i
, beg
, len
, exp_len
;
1216 WIN32_FIND_DATAW fdata
;
1219 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
1229 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
1233 buf
[0] = toupperW(buf
[0]);
1234 if(len
>3 && buf
[len
-1] == '\\')
1237 for(beg
=3, i
=3; i
<=len
; i
++) {
1238 if(buf
[i
]!='\\' && buf
[i
])
1243 fh
= FindFirstFileW(buf
, &fdata
);
1244 if(fh
== INVALID_HANDLE_VALUE
)
1247 exp_len
= strlenW(fdata
.cFileName
);
1248 if(exp_len
== i
-beg
)
1249 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
1255 *pbstrResult
= SysAllocString(buf
);
1257 return E_OUTOFMEMORY
;
1261 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
1263 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
1267 TRACE("%p %p\n", iface
, pbstrResult
);
1272 *pbstrResult
= SysAllocStringLen(NULL
, 12);
1274 return E_OUTOFMEMORY
;
1276 if(!RtlGenRandom(&random
, sizeof(random
)))
1278 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
1282 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
1283 VARIANT_BOOL
*pfExists
)
1285 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
1290 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
1293 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
1295 if (!ret
) return E_POINTER
;
1297 attrs
= GetFileAttributesW(path
);
1298 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
1302 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
1305 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
1307 if (!ret
) return E_POINTER
;
1309 attrs
= GetFileAttributesW(path
);
1310 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
1315 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
1318 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
1323 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
1326 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
1331 return E_INVALIDARG
;
1333 return create_file(FilePath
, ppfile
);
1336 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
1339 FIXME("%p %s %p\n", iface
, debugstr_w(FolderPath
), ppfolder
);
1344 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
1345 SpecialFolderConst SpecialFolder
,
1348 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
1353 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
1355 WCHAR path
[MAX_PATH
];
1356 DWORD len
, name_len
;
1357 WIN32_FIND_DATAW ffd
;
1360 f
= FindFirstFileW(file
, &ffd
);
1361 if(f
== INVALID_HANDLE_VALUE
)
1362 return create_error(GetLastError());
1364 len
= get_parent_folder_name(file
, file_len
);
1365 if(len
+1 >= MAX_PATH
) {
1370 memcpy(path
, file
, len
*sizeof(WCHAR
));
1375 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
1378 name_len
= strlenW(ffd
.cFileName
);
1379 if(len
+name_len
+1 >= MAX_PATH
) {
1383 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
1385 TRACE("deleting %s\n", debugstr_w(path
));
1387 if(!DeleteFileW(path
)) {
1388 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
1389 || !DeleteFileW(path
)) {
1391 return create_error(GetLastError());
1394 } while(FindNextFileW(f
, &ffd
));
1400 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
1403 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
1408 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
1411 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
1413 WCHAR path
[MAX_PATH
];
1414 DWORD len
, name_len
;
1415 WIN32_FIND_DATAW ffd
;
1419 f
= FindFirstFileW(folder
, &ffd
);
1420 if(f
== INVALID_HANDLE_VALUE
)
1421 return create_error(GetLastError());
1423 len
= get_parent_folder_name(folder
, folder_len
);
1424 if(len
+1 >= MAX_PATH
) {
1429 memcpy(path
, folder
, len
*sizeof(WCHAR
));
1434 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
1436 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
1437 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
1440 name_len
= strlenW(ffd
.cFileName
);
1441 if(len
+name_len
+3 >= MAX_PATH
) {
1445 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
1446 path
[len
+name_len
] = '\\';
1447 path
[len
+name_len
+1] = '*';
1448 path
[len
+name_len
+2] = 0;
1450 hr
= delete_file(path
, len
+name_len
+2, force
);
1456 hr
= delete_folder(path
, len
+name_len
+2, force
);
1462 path
[len
+name_len
] = 0;
1463 TRACE("deleting %s\n", debugstr_w(path
));
1465 if(!RemoveDirectoryW(path
)) {
1467 return create_error(GetLastError());
1469 } while(FindNextFileW(f
, &ffd
));
1475 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
1478 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
1483 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
1486 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
1489 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
1494 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
1497 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
1502 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
1503 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
1506 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
1507 DWORD src_len
, dst_len
, name_len
;
1508 WIN32_FIND_DATAW ffd
;
1512 if(!source
[0] || !destination
[0])
1513 return E_INVALIDARG
;
1515 attrs
= GetFileAttributesW(destination
);
1516 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
1517 attrs
= GetFileAttributesW(source
);
1518 if(attrs
== INVALID_FILE_ATTRIBUTES
)
1519 return create_error(GetLastError());
1520 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
1521 return CTL_E_FILENOTFOUND
;
1523 if(!CopyFileW(source
, destination
, !overwrite
))
1524 return create_error(GetLastError());
1528 f
= FindFirstFileW(source
, &ffd
);
1529 if(f
== INVALID_HANDLE_VALUE
)
1530 return CTL_E_FILENOTFOUND
;
1532 src_len
= get_parent_folder_name(source
, source_len
);
1533 if(src_len
+1 >= MAX_PATH
)
1536 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
1537 src_path
[src_len
++] = '\\';
1540 dst_len
= destination_len
;
1541 if(dst_len
+1 >= MAX_PATH
) {
1545 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
1546 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
1547 dst_path
[dst_len
++] = '\\';
1549 hr
= CTL_E_FILENOTFOUND
;
1551 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
1554 name_len
= strlenW(ffd
.cFileName
);
1555 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
1559 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
1560 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
1562 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
1564 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
1566 return create_error(GetLastError());
1570 } while(FindNextFileW(f
, &ffd
));
1576 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
1577 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
1579 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
1581 if(!Source
|| !Destination
)
1584 return copy_file(Source
, SysStringLen(Source
), Destination
,
1585 SysStringLen(Destination
), OverWriteFiles
);
1588 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
1589 DWORD destination_len
, VARIANT_BOOL overwrite
)
1591 DWORD tmp
, src_len
, dst_len
, name_len
;
1592 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
1593 WIN32_FIND_DATAW ffd
;
1596 BOOL copied
= FALSE
;
1598 if(!source
[0] || !destination
[0])
1599 return E_INVALIDARG
;
1601 dst_len
= destination_len
;
1602 if(dst_len
+1 >= MAX_PATH
)
1604 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
1606 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
1607 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
1608 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
1609 if(!CreateDirectoryW(dst
, NULL
)) {
1610 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
1611 tmp
= GetFileAttributesW(dst
);
1612 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
1613 return CTL_E_FILEALREADYEXISTS
;
1615 return create_error(GetLastError());
1620 src_len
= source_len
;
1621 if(src_len
+2 >= MAX_PATH
)
1623 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
1624 src
[src_len
++] = '\\';
1628 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
1629 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
1630 return create_error(GetLastError());
1632 f
= FindFirstFileW(src
, &ffd
);
1634 src_len
= get_parent_folder_name(source
, source_len
);
1635 if(src_len
+2 >= MAX_PATH
)
1637 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
1639 src
[src_len
++] = '\\';
1641 f
= FindFirstFileW(source
, &ffd
);
1643 if(f
== INVALID_HANDLE_VALUE
)
1644 return CTL_E_PATHNOTFOUND
;
1646 dst
[dst_len
++] = '\\';
1650 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
1652 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
1653 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
1656 name_len
= strlenW(ffd
.cFileName
);
1657 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
1661 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
1662 dst
[dst_len
+name_len
] = 0;
1663 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
1664 src
[src_len
+name_len
] = '\\';
1665 src
[src_len
+name_len
+1] = '*';
1666 src
[src_len
+name_len
+2] = 0;
1668 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
1670 if(!CreateDirectoryW(dst
, NULL
)) {
1671 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
1672 tmp
= GetFileAttributesW(dst
);
1673 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
1675 return CTL_E_FILEALREADYEXISTS
;
1679 return create_error(GetLastError());
1681 return create_error(GetLastError());
1685 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
1686 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
1691 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
1692 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
1696 } while(FindNextFileW(f
, &ffd
));
1699 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
1702 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
1703 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
1705 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
1707 if(!Source
|| !Destination
)
1710 return copy_folder(Source
, SysStringLen(Source
), Destination
,
1711 SysStringLen(Destination
), OverWriteFiles
);
1714 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
1719 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
1721 ret
= CreateDirectoryW(path
, NULL
);
1725 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
1726 return HRESULT_FROM_WIN32(GetLastError());
1729 return create_folder(folder
);
1732 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR FileName
,
1733 VARIANT_BOOL Overwrite
, VARIANT_BOOL Unicode
,
1736 FIXME("%p %s %d %d %p\n", iface
, debugstr_w(FileName
), Overwrite
, Unicode
, ppts
);
1741 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
1742 IOMode mode
, VARIANT_BOOL create
,
1743 Tristate format
, ITextStream
**stream
)
1745 FIXME("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
1746 return create_textstream(mode
, stream
);
1749 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
1750 StandardStreamTypes StandardStreamType
,
1751 VARIANT_BOOL Unicode
,
1754 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
1759 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
1761 static WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
1765 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
1766 a
= (WORD
)( version
>> 48);
1767 b
= (WORD
)((version
>> 32) & 0xffff);
1768 c
= (WORD
)((version
>> 16) & 0xffff);
1769 d
= (WORD
)( version
& 0xffff);
1771 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
1774 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
1776 static const WCHAR rootW
[] = {'\\',0};
1777 VS_FIXEDFILEINFO
*info
;
1783 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
1785 len
= GetFileVersionInfoSizeW(name
, NULL
);
1787 return HRESULT_FROM_WIN32(GetLastError());
1789 ptr
= heap_alloc(len
);
1790 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
1793 return HRESULT_FROM_WIN32(GetLastError());
1796 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
1799 return HRESULT_FROM_WIN32(GetLastError());
1801 get_versionstring(info
, ver
);
1802 *version
= SysAllocString(ver
);
1803 TRACE("version=%s\n", debugstr_w(ver
));
1808 static const struct IFileSystem3Vtbl filesys_vtbl
=
1810 filesys_QueryInterface
,
1813 filesys_GetTypeInfoCount
,
1814 filesys_GetTypeInfo
,
1815 filesys_GetIDsOfNames
,
1819 filesys_GetDriveName
,
1820 filesys_GetParentFolderName
,
1821 filesys_GetFileName
,
1822 filesys_GetBaseName
,
1823 filesys_GetExtensionName
,
1824 filesys_GetAbsolutePathName
,
1825 filesys_GetTempName
,
1826 filesys_DriveExists
,
1828 filesys_FolderExists
,
1832 filesys_GetSpecialFolder
,
1834 filesys_DeleteFolder
,
1839 filesys_CreateFolder
,
1840 filesys_CreateTextFile
,
1841 filesys_OpenTextFile
,
1842 filesys_GetStandardStream
,
1843 filesys_GetFileVersion
1846 static IFileSystem3 filesystem
= { &filesys_vtbl
};
1848 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
1850 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
1852 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);