d3d10core: Implement ID3D10Multithread.
[wine/multimedia.git] / dlls / scrrun / filesystem.c
blob21aaf700d1e5b1e926259d52b2cf5f1063f8954c
1 /*
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 #define COBJMACROS
21 #include "config.h"
22 #include <stdarg.h>
23 #include <limits.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "ole2.h"
28 #include "olectl.h"
29 #include "dispex.h"
30 #include "ntsecapi.h"
31 #include "scrrun.h"
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;
43 LONG ref;
44 BSTR path;
47 struct filecollection {
48 IFileCollection IFileCollection_iface;
49 LONG ref;
50 BSTR path;
53 struct enumdata {
54 union
56 struct
58 struct foldercollection *coll;
59 HANDLE find;
60 } foldercoll;
61 struct
63 struct filecollection *coll;
64 HANDLE find;
65 } filecoll;
66 } u;
69 struct enumvariant {
70 IEnumVARIANT IEnumVARIANT_iface;
71 LONG ref;
73 struct enumdata data;
76 struct folder {
77 IFolder IFolder_iface;
78 LONG ref;
79 BSTR path;
82 struct file {
83 IFile IFile_iface;
84 LONG ref;
86 WCHAR *path;
89 struct textstream {
90 ITextStream ITextStream_iface;
91 LONG ref;
93 IOMode mode;
96 enum iotype {
97 IORead,
98 IOWrite
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)
133 switch(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;
139 default:
140 FIXME("Unsupported error code: %d\n", err);
141 return E_FAIL;
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] != '\\')
172 strcatW(buffW, bsW);
173 strcatW(buffW, data->cFileName);
175 return SysAllocString(buffW);
178 static BOOL textstream_check_iomode(struct textstream *This, enum iotype type)
180 if (type == IORead)
181 return This->mode == ForWriting || This->mode == ForAppending;
182 else
183 return TRUE;
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))
196 *obj = iface;
197 ITextStream_AddRef(iface);
198 return S_OK;
201 *obj = NULL;
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);
210 return 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);
219 if (!ref)
220 heap_free(This);
222 return 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);
229 *pctinfo = 1;
230 return S_OK;
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);
246 ITypeInfo *typeinfo;
247 HRESULT hr;
249 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
251 hr = get_typeinfo(ITextStream_tid, &typeinfo);
252 if(SUCCEEDED(hr))
254 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
255 ITypeInfo_Release(typeinfo);
258 return hr;
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);
267 ITypeInfo *typeinfo;
268 HRESULT hr;
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);
274 if(SUCCEEDED(hr))
276 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
277 pDispParams, pVarResult, pExcepInfo, puArgErr);
278 ITypeInfo_Release(typeinfo);
281 return hr;
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);
288 return E_NOTIMPL;
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);
295 return E_NOTIMPL;
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);
302 return E_NOTIMPL;
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);
309 return E_NOTIMPL;
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;
320 return E_NOTIMPL;
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;
331 return E_NOTIMPL;
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;
342 return E_NOTIMPL;
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));
349 return E_NOTIMPL;
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));
356 return E_NOTIMPL;
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);
363 return E_NOTIMPL;
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);
370 return E_NOTIMPL;
373 static HRESULT WINAPI textstream_SkipLine(ITextStream *iface)
375 struct textstream *This = impl_from_ITextStream(iface);
376 FIXME("(%p): stub\n", This);
377 return E_NOTIMPL;
380 static HRESULT WINAPI textstream_Close(ITextStream *iface)
382 struct textstream *This = impl_from_ITextStream(iface);
383 FIXME("(%p): stub\n", This);
384 return E_NOTIMPL;
387 static const ITextStreamVtbl textstreamvtbl = {
388 textstream_QueryInterface,
389 textstream_AddRef,
390 textstream_Release,
391 textstream_GetTypeInfoCount,
392 textstream_GetTypeInfo,
393 textstream_GetIDsOfNames,
394 textstream_Invoke,
395 textstream_get_Line,
396 textstream_get_Column,
397 textstream_get_AtEndOfStream,
398 textstream_get_AtEndOfLine,
399 textstream_Read,
400 textstream_ReadLine,
401 textstream_ReadAll,
402 textstream_Write,
403 textstream_WriteLine,
404 textstream_WriteBlankLines,
405 textstream_Skip,
406 textstream_SkipLine,
407 textstream_Close
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;
418 stream->ref = 1;
419 stream->mode = mode;
421 *ret = &stream->ITextStream_iface;
422 return S_OK;
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);
431 *obj = NULL;
433 if (IsEqualIID( riid, &IID_IEnumVARIANT ) ||
434 IsEqualIID( riid, &IID_IUnknown ))
436 *obj = iface;
437 IEnumVARIANT_AddRef(iface);
439 else
440 return E_NOINTERFACE;
442 return S_OK;
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);
450 return 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);
460 if (!ref)
462 IFolderCollection_Release(&This->data.u.foldercoll.coll->IFolderCollection_iface);
463 FindClose(This->data.u.foldercoll.find);
464 heap_free(This);
467 return ref;
470 static HANDLE start_enumeration(const WCHAR *path, WIN32_FIND_DATAW *data)
472 static const WCHAR allW[] = {'*',0};
473 WCHAR pathW[MAX_PATH];
474 int len;
475 HANDLE handle;
477 strcpyW(pathW, path);
478 len = strlenW(pathW);
479 if (pathW[len-1] != '\\')
480 strcatW(pathW, bsW);
481 strcatW(pathW, allW);
482 handle = FindFirstFileW(pathW, data);
483 if (handle == INVALID_HANDLE_VALUE) return 0;
485 /* find first dir */
486 while (1)
488 if (is_dir_data(data))
489 break;
491 if (!FindNextFileW(handle, data))
493 FindClose(handle);
494 return 0;
497 return handle;
500 static HRESULT WINAPI foldercoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched)
502 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
503 HANDLE handle = This->data.u.foldercoll.find;
504 WIN32_FIND_DATAW data;
505 ULONG count = 0;
507 TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
509 if (fetched)
510 *fetched = 0;
512 if (!celt) return S_OK;
514 if (!handle)
516 handle = start_enumeration(This->data.u.foldercoll.coll->path, &data);
517 if (!handle) return S_FALSE;
519 This->data.u.foldercoll.find = handle;
521 else
523 if (!FindNextFileW(handle, &data))
524 return S_FALSE;
529 if (is_dir_data(&data))
531 IFolder *folder;
532 HRESULT hr;
533 BSTR str;
535 str = get_full_path(This->data.u.foldercoll.coll->path, &data);
536 hr = create_folder(str, &folder);
537 SysFreeString(str);
538 if (FAILED(hr)) return hr;
540 V_VT(&var[count]) = VT_DISPATCH;
541 V_DISPATCH(&var[count]) = (IDispatch*)folder;
542 count++;
544 if (count >= celt) break;
546 } while (FindNextFileW(handle, &data));
548 if (fetched)
549 *fetched = count;
551 return (count < celt) ? S_FALSE : S_OK;
554 static HRESULT WINAPI foldercoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt)
556 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
557 HANDLE handle = This->data.u.foldercoll.find;
558 WIN32_FIND_DATAW data;
560 TRACE("(%p)->(%d)\n", This, celt);
562 if (!celt) return S_OK;
564 if (!handle)
566 handle = start_enumeration(This->data.u.foldercoll.coll->path, &data);
567 if (!handle) return S_FALSE;
569 This->data.u.foldercoll.find = handle;
571 else
573 if (!FindNextFileW(handle, &data))
574 return S_FALSE;
579 if (is_dir_data(&data))
580 --celt;
582 if (!celt) break;
583 } while (FindNextFileW(handle, &data));
585 return celt ? S_FALSE : S_OK;
588 static HRESULT WINAPI foldercoll_enumvariant_Reset(IEnumVARIANT *iface)
590 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
592 TRACE("(%p)\n", This);
594 FindClose(This->data.u.foldercoll.find);
595 This->data.u.foldercoll.find = NULL;
597 return S_OK;
600 static HRESULT WINAPI foldercoll_enumvariant_Clone(IEnumVARIANT *iface, IEnumVARIANT **pclone)
602 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
603 TRACE("(%p)->(%p)\n", This, pclone);
604 return create_foldercoll_enum(This->data.u.foldercoll.coll, (IUnknown**)pclone);
607 static const IEnumVARIANTVtbl foldercollenumvariantvtbl = {
608 enumvariant_QueryInterface,
609 enumvariant_AddRef,
610 foldercoll_enumvariant_Release,
611 foldercoll_enumvariant_Next,
612 foldercoll_enumvariant_Skip,
613 foldercoll_enumvariant_Reset,
614 foldercoll_enumvariant_Clone
617 static HRESULT create_foldercoll_enum(struct foldercollection *collection, IUnknown **newenum)
619 struct enumvariant *This;
621 *newenum = NULL;
623 This = heap_alloc(sizeof(*This));
624 if (!This) return E_OUTOFMEMORY;
626 This->IEnumVARIANT_iface.lpVtbl = &foldercollenumvariantvtbl;
627 This->ref = 1;
628 This->data.u.foldercoll.find = NULL;
629 This->data.u.foldercoll.coll = collection;
630 IFolderCollection_AddRef(&collection->IFolderCollection_iface);
632 *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
634 return S_OK;
637 static ULONG WINAPI filecoll_enumvariant_Release(IEnumVARIANT *iface)
639 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
640 ULONG ref = InterlockedDecrement(&This->ref);
642 TRACE("(%p)->(%d)\n", This, ref);
644 if (!ref)
646 IFileCollection_Release(&This->data.u.filecoll.coll->IFileCollection_iface);
647 FindClose(This->data.u.filecoll.find);
648 heap_free(This);
651 return ref;
654 static HRESULT WINAPI filecoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched)
656 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
657 HANDLE handle = This->data.u.filecoll.find;
658 WIN32_FIND_DATAW data;
659 ULONG count = 0;
661 TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
663 if (fetched)
664 *fetched = 0;
666 if (!handle)
668 static const WCHAR allW[] = {'*',0};
669 WCHAR pathW[MAX_PATH];
670 BSTR parent = This->data.u.filecoll.coll->path;
671 int len;
673 strcpyW(pathW, parent);
674 len = SysStringLen(parent);
675 if (parent[len-1] != '\\')
676 strcatW(pathW, bsW);
677 strcatW(pathW, allW);
678 handle = FindFirstFileW(pathW, &data);
679 if (handle == INVALID_HANDLE_VALUE)
680 return S_FALSE;
682 while (1)
684 if (is_file_data(&data))
685 break;
686 else
687 if (!FindNextFileW(handle, &data))
689 FindClose(handle);
690 return S_FALSE;
694 This->data.u.filecoll.find = handle;
696 else if (celt)
697 FindNextFileW(handle, &data);
701 if (count >= celt) break;
703 if (is_file_data(&data))
705 IFile *file;
706 HRESULT hr;
707 BSTR str;
709 str = get_full_path(This->data.u.filecoll.coll->path, &data);
710 hr = create_file(str, &file);
711 SysFreeString(str);
712 if (FAILED(hr)) return hr;
714 V_VT(&var[count]) = VT_DISPATCH;
715 V_DISPATCH(&var[count]) = (IDispatch*)file;
716 count++;
718 } while (FindNextFileW(handle, &data));
720 if (count < celt)
721 return S_FALSE;
723 if (fetched)
724 *fetched = count;
726 return S_OK;
729 static HRESULT WINAPI filecoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt)
731 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
732 HANDLE handle = This->data.u.filecoll.find;
733 WIN32_FIND_DATAW data;
735 TRACE("(%p)->(%d)\n", This, celt);
737 while (FindNextFileW(handle, &data) && celt)
738 if (is_file_data(&data))
739 --celt;
741 return celt ? S_FALSE : S_OK;
744 static HRESULT WINAPI filecoll_enumvariant_Reset(IEnumVARIANT *iface)
746 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
748 TRACE("(%p)\n", This);
750 FindClose(This->data.u.filecoll.find);
751 This->data.u.filecoll.find = NULL;
753 return S_OK;
756 static HRESULT WINAPI filecoll_enumvariant_Clone(IEnumVARIANT *iface, IEnumVARIANT **pclone)
758 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
759 TRACE("(%p)->(%p)\n", This, pclone);
760 return create_filecoll_enum(This->data.u.filecoll.coll, (IUnknown**)pclone);
763 static const IEnumVARIANTVtbl filecollenumvariantvtbl = {
764 enumvariant_QueryInterface,
765 enumvariant_AddRef,
766 filecoll_enumvariant_Release,
767 filecoll_enumvariant_Next,
768 filecoll_enumvariant_Skip,
769 filecoll_enumvariant_Reset,
770 filecoll_enumvariant_Clone
773 static HRESULT create_filecoll_enum(struct filecollection *collection, IUnknown **newenum)
775 struct enumvariant *This;
777 *newenum = NULL;
779 This = heap_alloc(sizeof(*This));
780 if (!This) return E_OUTOFMEMORY;
782 This->IEnumVARIANT_iface.lpVtbl = &filecollenumvariantvtbl;
783 This->ref = 1;
784 This->data.u.filecoll.coll = collection;
785 IFileCollection_AddRef(&collection->IFileCollection_iface);
787 *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
789 return S_OK;
792 static HRESULT WINAPI foldercoll_QueryInterface(IFolderCollection *iface, REFIID riid, void **obj)
794 struct foldercollection *This = impl_from_IFolderCollection(iface);
796 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
798 *obj = NULL;
800 if (IsEqualIID( riid, &IID_IFolderCollection ) ||
801 IsEqualIID( riid, &IID_IDispatch ) ||
802 IsEqualIID( riid, &IID_IUnknown ))
804 *obj = iface;
805 IFolderCollection_AddRef(iface);
807 else
808 return E_NOINTERFACE;
810 return S_OK;
813 static ULONG WINAPI foldercoll_AddRef(IFolderCollection *iface)
815 struct foldercollection *This = impl_from_IFolderCollection(iface);
816 ULONG ref = InterlockedIncrement(&This->ref);
817 TRACE("(%p)->(%d)\n", This, ref);
818 return ref;
821 static ULONG WINAPI foldercoll_Release(IFolderCollection *iface)
823 struct foldercollection *This = impl_from_IFolderCollection(iface);
824 ULONG ref = InterlockedDecrement(&This->ref);
825 TRACE("(%p)->(%d)\n", This, ref);
827 if (!ref)
829 SysFreeString(This->path);
830 heap_free(This);
833 return ref;
836 static HRESULT WINAPI foldercoll_GetTypeInfoCount(IFolderCollection *iface, UINT *pctinfo)
838 struct foldercollection *This = impl_from_IFolderCollection(iface);
839 TRACE("(%p)->(%p)\n", This, pctinfo);
840 *pctinfo = 1;
841 return S_OK;
844 static HRESULT WINAPI foldercoll_GetTypeInfo(IFolderCollection *iface, UINT iTInfo,
845 LCID lcid, ITypeInfo **ppTInfo)
847 struct foldercollection *This = impl_from_IFolderCollection(iface);
848 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
849 return get_typeinfo(IFolderCollection_tid, ppTInfo);
852 static HRESULT WINAPI foldercoll_GetIDsOfNames(IFolderCollection *iface, REFIID riid,
853 LPOLESTR *rgszNames, UINT cNames,
854 LCID lcid, DISPID *rgDispId)
856 struct foldercollection *This = impl_from_IFolderCollection(iface);
857 ITypeInfo *typeinfo;
858 HRESULT hr;
860 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
862 hr = get_typeinfo(IFolderCollection_tid, &typeinfo);
863 if(SUCCEEDED(hr))
865 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
866 ITypeInfo_Release(typeinfo);
869 return hr;
872 static HRESULT WINAPI foldercoll_Invoke(IFolderCollection *iface, DISPID dispIdMember,
873 REFIID riid, LCID lcid, WORD wFlags,
874 DISPPARAMS *pDispParams, VARIANT *pVarResult,
875 EXCEPINFO *pExcepInfo, UINT *puArgErr)
877 struct foldercollection *This = impl_from_IFolderCollection(iface);
878 ITypeInfo *typeinfo;
879 HRESULT hr;
881 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
882 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
884 hr = get_typeinfo(IFolderCollection_tid, &typeinfo);
885 if(SUCCEEDED(hr))
887 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
888 pDispParams, pVarResult, pExcepInfo, puArgErr);
889 ITypeInfo_Release(typeinfo);
892 return hr;
895 static HRESULT WINAPI foldercoll_Add(IFolderCollection *iface, BSTR name, IFolder **folder)
897 struct foldercollection *This = impl_from_IFolderCollection(iface);
898 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(name), folder);
899 return E_NOTIMPL;
902 static HRESULT WINAPI foldercoll_get_Item(IFolderCollection *iface, VARIANT key, IFolder **folder)
904 struct foldercollection *This = impl_from_IFolderCollection(iface);
905 FIXME("(%p)->(%p): stub\n", This, folder);
906 return E_NOTIMPL;
909 static HRESULT WINAPI foldercoll_get__NewEnum(IFolderCollection *iface, IUnknown **newenum)
911 struct foldercollection *This = impl_from_IFolderCollection(iface);
913 TRACE("(%p)->(%p)\n", This, newenum);
915 if(!newenum)
916 return E_POINTER;
918 return create_foldercoll_enum(This, newenum);
921 static HRESULT WINAPI foldercoll_get_Count(IFolderCollection *iface, LONG *count)
923 struct foldercollection *This = impl_from_IFolderCollection(iface);
924 static const WCHAR allW[] = {'\\','*',0};
925 WIN32_FIND_DATAW data;
926 WCHAR pathW[MAX_PATH];
927 HANDLE handle;
929 TRACE("(%p)->(%p)\n", This, count);
931 if(!count)
932 return E_POINTER;
934 *count = 0;
936 strcpyW(pathW, This->path);
937 strcatW(pathW, allW);
938 handle = FindFirstFileW(pathW, &data);
939 if (handle == INVALID_HANDLE_VALUE)
940 return HRESULT_FROM_WIN32(GetLastError());
944 if (is_dir_data(&data))
945 *count += 1;
946 } while (FindNextFileW(handle, &data));
947 FindClose(handle);
949 return S_OK;
952 static const IFolderCollectionVtbl foldercollvtbl = {
953 foldercoll_QueryInterface,
954 foldercoll_AddRef,
955 foldercoll_Release,
956 foldercoll_GetTypeInfoCount,
957 foldercoll_GetTypeInfo,
958 foldercoll_GetIDsOfNames,
959 foldercoll_Invoke,
960 foldercoll_Add,
961 foldercoll_get_Item,
962 foldercoll_get__NewEnum,
963 foldercoll_get_Count
966 static HRESULT create_foldercoll(BSTR path, IFolderCollection **folders)
968 struct foldercollection *This;
970 *folders = NULL;
972 This = heap_alloc(sizeof(struct foldercollection));
973 if (!This) return E_OUTOFMEMORY;
975 This->IFolderCollection_iface.lpVtbl = &foldercollvtbl;
976 This->ref = 1;
977 This->path = SysAllocString(path);
978 if (!This->path)
980 heap_free(This);
981 return E_OUTOFMEMORY;
984 *folders = &This->IFolderCollection_iface;
986 return S_OK;
989 static HRESULT WINAPI filecoll_QueryInterface(IFileCollection *iface, REFIID riid, void **obj)
991 struct filecollection *This = impl_from_IFileCollection(iface);
993 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
995 *obj = NULL;
997 if (IsEqualIID( riid, &IID_IFileCollection ) ||
998 IsEqualIID( riid, &IID_IDispatch ) ||
999 IsEqualIID( riid, &IID_IUnknown ))
1001 *obj = iface;
1002 IFileCollection_AddRef(iface);
1004 else
1005 return E_NOINTERFACE;
1007 return S_OK;
1010 static ULONG WINAPI filecoll_AddRef(IFileCollection *iface)
1012 struct filecollection *This = impl_from_IFileCollection(iface);
1013 ULONG ref = InterlockedIncrement(&This->ref);
1014 TRACE("(%p)->(%d)\n", This, ref);
1015 return ref;
1018 static ULONG WINAPI filecoll_Release(IFileCollection *iface)
1020 struct filecollection *This = impl_from_IFileCollection(iface);
1021 ULONG ref = InterlockedDecrement(&This->ref);
1022 TRACE("(%p)->(%d)\n", This, ref);
1024 if (!ref)
1026 SysFreeString(This->path);
1027 heap_free(This);
1030 return ref;
1033 static HRESULT WINAPI filecoll_GetTypeInfoCount(IFileCollection *iface, UINT *pctinfo)
1035 struct filecollection *This = impl_from_IFileCollection(iface);
1036 TRACE("(%p)->(%p)\n", This, pctinfo);
1037 *pctinfo = 1;
1038 return S_OK;
1041 static HRESULT WINAPI filecoll_GetTypeInfo(IFileCollection *iface, UINT iTInfo,
1042 LCID lcid, ITypeInfo **ppTInfo)
1044 struct filecollection *This = impl_from_IFileCollection(iface);
1045 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1046 return get_typeinfo(IFileCollection_tid, ppTInfo);
1049 static HRESULT WINAPI filecoll_GetIDsOfNames(IFileCollection *iface, REFIID riid,
1050 LPOLESTR *rgszNames, UINT cNames,
1051 LCID lcid, DISPID *rgDispId)
1053 struct filecollection *This = impl_from_IFileCollection(iface);
1054 ITypeInfo *typeinfo;
1055 HRESULT hr;
1057 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1059 hr = get_typeinfo(IFileCollection_tid, &typeinfo);
1060 if(SUCCEEDED(hr))
1062 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1063 ITypeInfo_Release(typeinfo);
1066 return hr;
1069 static HRESULT WINAPI filecoll_Invoke(IFileCollection *iface, DISPID dispIdMember,
1070 REFIID riid, LCID lcid, WORD wFlags,
1071 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1072 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1074 struct filecollection *This = impl_from_IFileCollection(iface);
1075 ITypeInfo *typeinfo;
1076 HRESULT hr;
1078 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1079 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1081 hr = get_typeinfo(IFileCollection_tid, &typeinfo);
1082 if(SUCCEEDED(hr))
1084 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1085 pDispParams, pVarResult, pExcepInfo, puArgErr);
1086 ITypeInfo_Release(typeinfo);
1089 return hr;
1092 static HRESULT WINAPI filecoll_get_Item(IFileCollection *iface, VARIANT Key, IFile **file)
1094 struct filecollection *This = impl_from_IFileCollection(iface);
1095 FIXME("(%p)->(%p)\n", This, file);
1096 return E_NOTIMPL;
1099 static HRESULT WINAPI filecoll_get__NewEnum(IFileCollection *iface, IUnknown **ppenum)
1101 struct filecollection *This = impl_from_IFileCollection(iface);
1103 TRACE("(%p)->(%p)\n", This, ppenum);
1105 if(!ppenum)
1106 return E_POINTER;
1108 return create_filecoll_enum(This, ppenum);
1111 static HRESULT WINAPI filecoll_get_Count(IFileCollection *iface, LONG *count)
1113 struct filecollection *This = impl_from_IFileCollection(iface);
1114 FIXME("(%p)->(%p)\n", This, count);
1115 return E_NOTIMPL;
1118 static const IFileCollectionVtbl filecollectionvtbl = {
1119 filecoll_QueryInterface,
1120 filecoll_AddRef,
1121 filecoll_Release,
1122 filecoll_GetTypeInfoCount,
1123 filecoll_GetTypeInfo,
1124 filecoll_GetIDsOfNames,
1125 filecoll_Invoke,
1126 filecoll_get_Item,
1127 filecoll_get__NewEnum,
1128 filecoll_get_Count
1131 static HRESULT create_filecoll(BSTR path, IFileCollection **files)
1133 struct filecollection *This;
1135 *files = NULL;
1137 This = heap_alloc(sizeof(*This));
1138 if (!This) return E_OUTOFMEMORY;
1140 This->IFileCollection_iface.lpVtbl = &filecollectionvtbl;
1141 This->ref = 1;
1142 This->path = SysAllocString(path);
1143 if (!This->path)
1145 heap_free(This);
1146 return E_OUTOFMEMORY;
1149 *files = &This->IFileCollection_iface;
1150 return S_OK;
1153 static HRESULT WINAPI folder_QueryInterface(IFolder *iface, REFIID riid, void **obj)
1155 struct folder *This = impl_from_IFolder(iface);
1157 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1159 *obj = NULL;
1161 if (IsEqualIID( riid, &IID_IFolder ) ||
1162 IsEqualIID( riid, &IID_IDispatch ) ||
1163 IsEqualIID( riid, &IID_IUnknown))
1165 *obj = iface;
1166 IFolder_AddRef(iface);
1168 else
1169 return E_NOINTERFACE;
1171 return S_OK;
1174 static ULONG WINAPI folder_AddRef(IFolder *iface)
1176 struct folder *This = impl_from_IFolder(iface);
1177 ULONG ref = InterlockedIncrement(&This->ref);
1178 TRACE("(%p)->(%d)\n", This, ref);
1179 return ref;
1182 static ULONG WINAPI folder_Release(IFolder *iface)
1184 struct folder *This = impl_from_IFolder(iface);
1185 ULONG ref = InterlockedDecrement(&This->ref);
1186 TRACE("(%p)->(%d)\n", This, ref);
1188 if (!ref)
1190 SysFreeString(This->path);
1191 heap_free(This);
1194 return ref;
1197 static HRESULT WINAPI folder_GetTypeInfoCount(IFolder *iface, UINT *pctinfo)
1199 struct folder *This = impl_from_IFolder(iface);
1200 TRACE("(%p)->(%p)\n", This, pctinfo);
1201 *pctinfo = 1;
1202 return S_OK;
1205 static HRESULT WINAPI folder_GetTypeInfo(IFolder *iface, UINT iTInfo,
1206 LCID lcid, ITypeInfo **ppTInfo)
1208 struct folder *This = impl_from_IFolder(iface);
1209 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1210 return get_typeinfo(IFolder_tid, ppTInfo);
1213 static HRESULT WINAPI folder_GetIDsOfNames(IFolder *iface, REFIID riid,
1214 LPOLESTR *rgszNames, UINT cNames,
1215 LCID lcid, DISPID *rgDispId)
1217 struct folder *This = impl_from_IFolder(iface);
1218 ITypeInfo *typeinfo;
1219 HRESULT hr;
1221 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1223 hr = get_typeinfo(IFolder_tid, &typeinfo);
1224 if(SUCCEEDED(hr))
1226 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1227 ITypeInfo_Release(typeinfo);
1230 return hr;
1233 static HRESULT WINAPI folder_Invoke(IFolder *iface, DISPID dispIdMember,
1234 REFIID riid, LCID lcid, WORD wFlags,
1235 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1236 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1238 struct folder *This = impl_from_IFolder(iface);
1239 ITypeInfo *typeinfo;
1240 HRESULT hr;
1242 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1243 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1245 hr = get_typeinfo(IFolder_tid, &typeinfo);
1246 if(SUCCEEDED(hr))
1248 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1249 pDispParams, pVarResult, pExcepInfo, puArgErr);
1250 ITypeInfo_Release(typeinfo);
1253 return hr;
1256 static HRESULT WINAPI folder_get_Path(IFolder *iface, BSTR *path)
1258 struct folder *This = impl_from_IFolder(iface);
1259 FIXME("(%p)->(%p): stub\n", This, path);
1260 return E_NOTIMPL;
1263 static HRESULT WINAPI folder_get_Name(IFolder *iface, BSTR *name)
1265 struct folder *This = impl_from_IFolder(iface);
1266 WCHAR *ptr;
1268 TRACE("(%p)->(%p)\n", This, name);
1270 if(!name)
1271 return E_POINTER;
1273 *name = NULL;
1275 ptr = strrchrW(This->path, '\\');
1276 if (ptr)
1278 *name = SysAllocString(ptr+1);
1279 TRACE("%s\n", debugstr_w(*name));
1280 if (!*name) return E_OUTOFMEMORY;
1282 else
1283 return E_FAIL;
1285 return S_OK;
1288 static HRESULT WINAPI folder_put_Name(IFolder *iface, BSTR name)
1290 struct folder *This = impl_from_IFolder(iface);
1291 FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
1292 return E_NOTIMPL;
1295 static HRESULT WINAPI folder_get_ShortPath(IFolder *iface, BSTR *path)
1297 struct folder *This = impl_from_IFolder(iface);
1298 FIXME("(%p)->(%p): stub\n", This, path);
1299 return E_NOTIMPL;
1302 static HRESULT WINAPI folder_get_ShortName(IFolder *iface, BSTR *name)
1304 struct folder *This = impl_from_IFolder(iface);
1305 FIXME("(%p)->(%p): stub\n", This, name);
1306 return E_NOTIMPL;
1309 static HRESULT WINAPI folder_get_Drive(IFolder *iface, IDrive **drive)
1311 struct folder *This = impl_from_IFolder(iface);
1312 FIXME("(%p)->(%p): stub\n", This, drive);
1313 return E_NOTIMPL;
1316 static HRESULT WINAPI folder_get_ParentFolder(IFolder *iface, IFolder **parent)
1318 struct folder *This = impl_from_IFolder(iface);
1319 FIXME("(%p)->(%p): stub\n", This, parent);
1320 return E_NOTIMPL;
1323 static HRESULT WINAPI folder_get_Attributes(IFolder *iface, FileAttribute *attr)
1325 struct folder *This = impl_from_IFolder(iface);
1326 FIXME("(%p)->(%p): stub\n", This, attr);
1327 return E_NOTIMPL;
1330 static HRESULT WINAPI folder_put_Attributes(IFolder *iface, FileAttribute attr)
1332 struct folder *This = impl_from_IFolder(iface);
1333 FIXME("(%p)->(0x%x): stub\n", This, attr);
1334 return E_NOTIMPL;
1337 static HRESULT WINAPI folder_get_DateCreated(IFolder *iface, DATE *date)
1339 struct folder *This = impl_from_IFolder(iface);
1340 FIXME("(%p)->(%p): stub\n", This, date);
1341 return E_NOTIMPL;
1344 static HRESULT WINAPI folder_get_DateLastModified(IFolder *iface, DATE *date)
1346 struct folder *This = impl_from_IFolder(iface);
1347 FIXME("(%p)->(%p): stub\n", This, date);
1348 return E_NOTIMPL;
1351 static HRESULT WINAPI folder_get_DateLastAccessed(IFolder *iface, DATE *date)
1353 struct folder *This = impl_from_IFolder(iface);
1354 FIXME("(%p)->(%p): stub\n", This, date);
1355 return E_NOTIMPL;
1358 static HRESULT WINAPI folder_get_Type(IFolder *iface, BSTR *type)
1360 struct folder *This = impl_from_IFolder(iface);
1361 FIXME("(%p)->(%p): stub\n", This, type);
1362 return E_NOTIMPL;
1365 static HRESULT WINAPI folder_Delete(IFolder *iface, VARIANT_BOOL force)
1367 struct folder *This = impl_from_IFolder(iface);
1368 FIXME("(%p)->(%x): stub\n", This, force);
1369 return E_NOTIMPL;
1372 static HRESULT WINAPI folder_Copy(IFolder *iface, BSTR dest, VARIANT_BOOL overwrite)
1374 struct folder *This = impl_from_IFolder(iface);
1375 FIXME("(%p)->(%s %x): stub\n", This, debugstr_w(dest), overwrite);
1376 return E_NOTIMPL;
1379 static HRESULT WINAPI folder_Move(IFolder *iface, BSTR dest)
1381 struct folder *This = impl_from_IFolder(iface);
1382 FIXME("(%p)->(%s): stub\n", This, debugstr_w(dest));
1383 return E_NOTIMPL;
1386 static HRESULT WINAPI folder_get_IsRootFolder(IFolder *iface, VARIANT_BOOL *isroot)
1388 struct folder *This = impl_from_IFolder(iface);
1389 FIXME("(%p)->(%p): stub\n", This, isroot);
1390 return E_NOTIMPL;
1393 static HRESULT WINAPI folder_get_Size(IFolder *iface, VARIANT *size)
1395 struct folder *This = impl_from_IFolder(iface);
1396 FIXME("(%p)->(%p): stub\n", This, size);
1397 return E_NOTIMPL;
1400 static HRESULT WINAPI folder_get_SubFolders(IFolder *iface, IFolderCollection **folders)
1402 struct folder *This = impl_from_IFolder(iface);
1404 TRACE("(%p)->(%p)\n", This, folders);
1406 if(!folders)
1407 return E_POINTER;
1409 return create_foldercoll(This->path, folders);
1412 static HRESULT WINAPI folder_get_Files(IFolder *iface, IFileCollection **files)
1414 struct folder *This = impl_from_IFolder(iface);
1416 TRACE("(%p)->(%p)\n", This, files);
1418 if(!files)
1419 return E_POINTER;
1421 return create_filecoll(This->path, files);
1424 static HRESULT WINAPI folder_CreateTextFile(IFolder *iface, BSTR filename, VARIANT_BOOL overwrite,
1425 VARIANT_BOOL unicode, ITextStream **stream)
1427 struct folder *This = impl_from_IFolder(iface);
1428 FIXME("(%p)->(%s %x %x %p): stub\n", This, debugstr_w(filename), overwrite, unicode, stream);
1429 return E_NOTIMPL;
1432 static const IFolderVtbl foldervtbl = {
1433 folder_QueryInterface,
1434 folder_AddRef,
1435 folder_Release,
1436 folder_GetTypeInfoCount,
1437 folder_GetTypeInfo,
1438 folder_GetIDsOfNames,
1439 folder_Invoke,
1440 folder_get_Path,
1441 folder_get_Name,
1442 folder_put_Name,
1443 folder_get_ShortPath,
1444 folder_get_ShortName,
1445 folder_get_Drive,
1446 folder_get_ParentFolder,
1447 folder_get_Attributes,
1448 folder_put_Attributes,
1449 folder_get_DateCreated,
1450 folder_get_DateLastModified,
1451 folder_get_DateLastAccessed,
1452 folder_get_Type,
1453 folder_Delete,
1454 folder_Copy,
1455 folder_Move,
1456 folder_get_IsRootFolder,
1457 folder_get_Size,
1458 folder_get_SubFolders,
1459 folder_get_Files,
1460 folder_CreateTextFile
1463 HRESULT create_folder(const WCHAR *path, IFolder **folder)
1465 struct folder *This;
1467 *folder = NULL;
1469 TRACE("%s\n", debugstr_w(path));
1471 This = heap_alloc(sizeof(struct folder));
1472 if (!This) return E_OUTOFMEMORY;
1474 This->IFolder_iface.lpVtbl = &foldervtbl;
1475 This->ref = 1;
1476 This->path = SysAllocString(path);
1477 if (!This->path)
1479 heap_free(This);
1480 return E_OUTOFMEMORY;
1483 *folder = &This->IFolder_iface;
1485 return S_OK;
1488 static HRESULT WINAPI file_QueryInterface(IFile *iface, REFIID riid, void **obj)
1490 struct file *This = impl_from_IFile(iface);
1492 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1494 if (IsEqualIID(riid, &IID_IFile) ||
1495 IsEqualIID(riid, &IID_IDispatch) ||
1496 IsEqualIID(riid, &IID_IUnknown))
1498 *obj = iface;
1499 IFile_AddRef(iface);
1500 return S_OK;
1503 *obj = NULL;
1504 return E_NOINTERFACE;
1507 static ULONG WINAPI file_AddRef(IFile *iface)
1509 struct file *This = impl_from_IFile(iface);
1510 LONG ref = InterlockedIncrement(&This->ref);
1512 TRACE("(%p) ref=%d\n", This, ref);
1514 return ref;
1517 static ULONG WINAPI file_Release(IFile *iface)
1519 struct file *This = impl_from_IFile(iface);
1520 LONG ref = InterlockedDecrement(&This->ref);
1522 TRACE("(%p) ref=%d\n", This, ref);
1524 if(!ref)
1526 heap_free(This->path);
1527 heap_free(This);
1530 return ref;
1533 static HRESULT WINAPI file_GetTypeInfoCount(IFile *iface, UINT *pctinfo)
1535 struct file *This = impl_from_IFile(iface);
1537 TRACE("(%p)->(%p)\n", This, pctinfo);
1539 *pctinfo = 1;
1540 return S_OK;
1543 static HRESULT WINAPI file_GetTypeInfo(IFile *iface,
1544 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1546 struct file *This = impl_from_IFile(iface);
1548 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1550 return get_typeinfo(IFile_tid, ppTInfo);
1553 static HRESULT WINAPI file_GetIDsOfNames(IFile *iface, REFIID riid,
1554 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1556 struct file *This = impl_from_IFile(iface);
1557 ITypeInfo *typeinfo;
1558 HRESULT hr;
1560 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
1561 rgszNames, cNames, lcid, rgDispId);
1563 hr = get_typeinfo(IFile_tid, &typeinfo);
1564 if(SUCCEEDED(hr)) {
1565 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1566 ITypeInfo_Release(typeinfo);
1568 return hr;
1571 static HRESULT WINAPI file_Invoke(IFile *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1573 struct file *This = impl_from_IFile(iface);
1574 ITypeInfo *typeinfo;
1575 HRESULT hr;
1577 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1578 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1580 hr = get_typeinfo(IFile_tid, &typeinfo);
1581 if(SUCCEEDED(hr))
1583 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1584 pDispParams, pVarResult, pExcepInfo, puArgErr);
1585 ITypeInfo_Release(typeinfo);
1587 return hr;
1590 static HRESULT WINAPI file_get_Path(IFile *iface, BSTR *pbstrPath)
1592 struct file *This = impl_from_IFile(iface);
1593 FIXME("(%p)->(%p)\n", This, pbstrPath);
1594 return E_NOTIMPL;
1597 static HRESULT WINAPI file_get_Name(IFile *iface, BSTR *name)
1599 struct file *This = impl_from_IFile(iface);
1600 WCHAR *ptr;
1602 TRACE("(%p)->(%p)\n", This, name);
1604 if(!name)
1605 return E_POINTER;
1607 *name = NULL;
1609 ptr = strrchrW(This->path, '\\');
1610 if (ptr)
1612 *name = SysAllocString(ptr+1);
1613 TRACE("%s\n", debugstr_w(*name));
1614 if (!*name) return E_OUTOFMEMORY;
1616 else
1617 return E_FAIL;
1619 return S_OK;
1622 static HRESULT WINAPI file_put_Name(IFile *iface, BSTR pbstrName)
1624 struct file *This = impl_from_IFile(iface);
1625 FIXME("(%p)->(%s)\n", This, debugstr_w(pbstrName));
1626 return E_NOTIMPL;
1629 static HRESULT WINAPI file_get_ShortPath(IFile *iface, BSTR *pbstrPath)
1631 struct file *This = impl_from_IFile(iface);
1632 FIXME("(%p)->(%p)\n", This, pbstrPath);
1633 return E_NOTIMPL;
1636 static HRESULT WINAPI file_get_ShortName(IFile *iface, BSTR *pbstrName)
1638 struct file *This = impl_from_IFile(iface);
1639 FIXME("(%p)->(%p)\n", This, pbstrName);
1640 return E_NOTIMPL;
1643 static HRESULT WINAPI file_get_Drive(IFile *iface, IDrive **ppdrive)
1645 struct file *This = impl_from_IFile(iface);
1646 FIXME("(%p)->(%p)\n", This, ppdrive);
1647 return E_NOTIMPL;
1650 static HRESULT WINAPI file_get_ParentFolder(IFile *iface, IFolder **ppfolder)
1652 struct file *This = impl_from_IFile(iface);
1653 FIXME("(%p)->(%p)\n", This, ppfolder);
1654 return E_NOTIMPL;
1657 static HRESULT WINAPI file_get_Attributes(IFile *iface, FileAttribute *pfa)
1659 struct file *This = impl_from_IFile(iface);
1660 DWORD fa;
1662 TRACE("(%p)->(%p)\n", This, pfa);
1664 if(!pfa)
1665 return E_POINTER;
1667 fa = GetFileAttributesW(This->path);
1668 if(fa == INVALID_FILE_ATTRIBUTES)
1669 return create_error(GetLastError());
1671 *pfa = fa & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
1672 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE |
1673 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED);
1674 return S_OK;
1677 static HRESULT WINAPI file_put_Attributes(IFile *iface, FileAttribute pfa)
1679 struct file *This = impl_from_IFile(iface);
1680 FIXME("(%p)->(%x)\n", This, pfa);
1681 return E_NOTIMPL;
1684 static HRESULT WINAPI file_get_DateCreated(IFile *iface, DATE *pdate)
1686 struct file *This = impl_from_IFile(iface);
1687 FIXME("(%p)->(%p)\n", This, pdate);
1688 return E_NOTIMPL;
1691 static HRESULT WINAPI file_get_DateLastModified(IFile *iface, DATE *pdate)
1693 struct file *This = impl_from_IFile(iface);
1694 FIXME("(%p)->(%p)\n", This, pdate);
1695 return E_NOTIMPL;
1698 static HRESULT WINAPI file_get_DateLastAccessed(IFile *iface, DATE *pdate)
1700 struct file *This = impl_from_IFile(iface);
1701 FIXME("(%p)->(%p)\n", This, pdate);
1702 return E_NOTIMPL;
1705 static HRESULT WINAPI file_get_Size(IFile *iface, VARIANT *pvarSize)
1707 struct file *This = impl_from_IFile(iface);
1708 WIN32_FIND_DATAW fd;
1709 HANDLE f;
1711 TRACE("(%p)->(%p)\n", This, pvarSize);
1713 if(!pvarSize)
1714 return E_POINTER;
1716 f = FindFirstFileW(This->path, &fd);
1717 if(f == INVALID_HANDLE_VALUE)
1718 return create_error(GetLastError());
1719 FindClose(f);
1721 if(fd.nFileSizeHigh || fd.nFileSizeLow>INT_MAX) {
1722 V_VT(pvarSize) = VT_R8;
1723 V_R8(pvarSize) = ((ULONGLONG)fd.nFileSizeHigh<<32) + fd.nFileSizeLow;
1724 }else {
1725 V_VT(pvarSize) = VT_I4;
1726 V_I4(pvarSize) = fd.nFileSizeLow;
1728 return S_OK;
1731 static HRESULT WINAPI file_get_Type(IFile *iface, BSTR *pbstrType)
1733 struct file *This = impl_from_IFile(iface);
1734 FIXME("(%p)->(%p)\n", This, pbstrType);
1735 return E_NOTIMPL;
1738 static HRESULT WINAPI file_Delete(IFile *iface, VARIANT_BOOL Force)
1740 struct file *This = impl_from_IFile(iface);
1741 FIXME("(%p)->(%x)\n", This, Force);
1742 return E_NOTIMPL;
1745 static HRESULT WINAPI file_Copy(IFile *iface, BSTR Destination, VARIANT_BOOL OverWriteFiles)
1747 struct file *This = impl_from_IFile(iface);
1748 FIXME("(%p)->(%s %x)\n", This, debugstr_w(Destination), OverWriteFiles);
1749 return E_NOTIMPL;
1752 static HRESULT WINAPI file_Move(IFile *iface, BSTR Destination)
1754 struct file *This = impl_from_IFile(iface);
1755 FIXME("(%p)->(%s)\n", This, debugstr_w(Destination));
1756 return E_NOTIMPL;
1759 static HRESULT WINAPI file_OpenAsTextStream(IFile *iface, IOMode IOMode, Tristate Format, ITextStream **ppts)
1761 struct file *This = impl_from_IFile(iface);
1762 FIXME("(%p)->(%x %x %p)\n", This, IOMode, Format, ppts);
1763 return E_NOTIMPL;
1766 static const IFileVtbl file_vtbl = {
1767 file_QueryInterface,
1768 file_AddRef,
1769 file_Release,
1770 file_GetTypeInfoCount,
1771 file_GetTypeInfo,
1772 file_GetIDsOfNames,
1773 file_Invoke,
1774 file_get_Path,
1775 file_get_Name,
1776 file_put_Name,
1777 file_get_ShortPath,
1778 file_get_ShortName,
1779 file_get_Drive,
1780 file_get_ParentFolder,
1781 file_get_Attributes,
1782 file_put_Attributes,
1783 file_get_DateCreated,
1784 file_get_DateLastModified,
1785 file_get_DateLastAccessed,
1786 file_get_Size,
1787 file_get_Type,
1788 file_Delete,
1789 file_Copy,
1790 file_Move,
1791 file_OpenAsTextStream
1794 static HRESULT create_file(BSTR path, IFile **file)
1796 struct file *f;
1797 DWORD len, attrs;
1799 *file = NULL;
1801 f = heap_alloc(sizeof(struct file));
1802 if(!f)
1803 return E_OUTOFMEMORY;
1805 f->IFile_iface.lpVtbl = &file_vtbl;
1806 f->ref = 1;
1808 len = GetFullPathNameW(path, 0, NULL, NULL);
1809 if(!len) {
1810 heap_free(f);
1811 return E_FAIL;
1814 f->path = heap_alloc(len*sizeof(WCHAR));
1815 if(!f->path) {
1816 heap_free(f);
1817 return E_OUTOFMEMORY;
1820 if(!GetFullPathNameW(path, len, f->path, NULL)) {
1821 heap_free(f->path);
1822 heap_free(f);
1823 return E_FAIL;
1826 if(path[len-1]=='/' || path[len-1]=='\\')
1827 path[len-1] = 0;
1829 attrs = GetFileAttributesW(f->path);
1830 if(attrs==INVALID_FILE_ATTRIBUTES ||
1831 (attrs&(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))) {
1832 heap_free(f->path);
1833 heap_free(f);
1834 return create_error(GetLastError());
1837 *file = &f->IFile_iface;
1838 return S_OK;
1841 static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, void **ppvObject)
1843 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
1845 if ( IsEqualGUID( riid, &IID_IFileSystem3 ) ||
1846 IsEqualGUID( riid, &IID_IFileSystem ) ||
1847 IsEqualGUID( riid, &IID_IDispatch ) ||
1848 IsEqualGUID( riid, &IID_IUnknown ) )
1850 *ppvObject = iface;
1852 else if ( IsEqualGUID( riid, &IID_IDispatchEx ))
1854 TRACE("Interface IDispatchEx not supported - returning NULL\n");
1855 *ppvObject = NULL;
1856 return E_NOINTERFACE;
1858 else if ( IsEqualGUID( riid, &IID_IObjectWithSite ))
1860 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
1861 *ppvObject = NULL;
1862 return E_NOINTERFACE;
1864 else
1866 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
1867 return E_NOINTERFACE;
1870 IFileSystem3_AddRef(iface);
1872 return S_OK;
1875 static ULONG WINAPI filesys_AddRef(IFileSystem3 *iface)
1877 TRACE("%p\n", iface);
1879 return 2;
1882 static ULONG WINAPI filesys_Release(IFileSystem3 *iface)
1884 TRACE("%p\n", iface);
1886 return 1;
1889 static HRESULT WINAPI filesys_GetTypeInfoCount(IFileSystem3 *iface, UINT *pctinfo)
1891 TRACE("(%p)->(%p)\n", iface, pctinfo);
1893 *pctinfo = 1;
1894 return S_OK;
1897 static HRESULT WINAPI filesys_GetTypeInfo(IFileSystem3 *iface, UINT iTInfo,
1898 LCID lcid, ITypeInfo **ppTInfo)
1900 TRACE("(%p)->(%u %u %p)\n", iface, iTInfo, lcid, ppTInfo);
1901 return get_typeinfo(IFileSystem3_tid, ppTInfo);
1904 static HRESULT WINAPI filesys_GetIDsOfNames(IFileSystem3 *iface, REFIID riid,
1905 LPOLESTR *rgszNames, UINT cNames,
1906 LCID lcid, DISPID *rgDispId)
1908 ITypeInfo *typeinfo;
1909 HRESULT hr;
1911 TRACE("(%p)->(%s %p %u %u %p)\n", iface, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1913 hr = get_typeinfo(IFileSystem3_tid, &typeinfo);
1914 if(SUCCEEDED(hr))
1916 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1917 ITypeInfo_Release(typeinfo);
1920 return hr;
1923 static HRESULT WINAPI filesys_Invoke(IFileSystem3 *iface, DISPID dispIdMember,
1924 REFIID riid, LCID lcid, WORD wFlags,
1925 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1926 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1928 ITypeInfo *typeinfo;
1929 HRESULT hr;
1931 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface, dispIdMember, debugstr_guid(riid),
1932 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1934 hr = get_typeinfo(IFileSystem3_tid, &typeinfo);
1935 if(SUCCEEDED(hr))
1937 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1938 pDispParams, pVarResult, pExcepInfo, puArgErr);
1939 ITypeInfo_Release(typeinfo);
1942 return hr;
1945 static HRESULT WINAPI filesys_get_Drives(IFileSystem3 *iface, IDriveCollection **ppdrives)
1947 FIXME("%p %p\n", iface, ppdrives);
1949 return E_NOTIMPL;
1952 static HRESULT WINAPI filesys_BuildPath(IFileSystem3 *iface, BSTR Path,
1953 BSTR Name, BSTR *Result)
1955 BSTR ret;
1957 TRACE("%p %s %s %p\n", iface, debugstr_w(Path), debugstr_w(Name), Result);
1959 if (!Result) return E_POINTER;
1961 if (Path && Name)
1963 int path_len = SysStringLen(Path), name_len = SysStringLen(Name);
1965 /* if both parts have backslashes strip one from Path */
1966 if (Path[path_len-1] == '\\' && Name[0] == '\\')
1968 path_len -= 1;
1970 ret = SysAllocStringLen(NULL, path_len + name_len);
1971 if (ret)
1973 strcpyW(ret, Path);
1974 ret[path_len] = 0;
1975 strcatW(ret, Name);
1978 else if (Path[path_len-1] != '\\' && Name[0] != '\\')
1980 ret = SysAllocStringLen(NULL, path_len + name_len + 1);
1981 if (ret)
1983 strcpyW(ret, Path);
1984 if (Path[path_len-1] != ':')
1985 strcatW(ret, bsW);
1986 strcatW(ret, Name);
1989 else
1991 ret = SysAllocStringLen(NULL, path_len + name_len);
1992 if (ret)
1994 strcpyW(ret, Path);
1995 strcatW(ret, Name);
1999 else if (Path || Name)
2000 ret = SysAllocString(Path ? Path : Name);
2001 else
2002 ret = SysAllocStringLen(NULL, 0);
2004 if (!ret) return E_OUTOFMEMORY;
2005 *Result = ret;
2007 return S_OK;
2010 static HRESULT WINAPI filesys_GetDriveName(IFileSystem3 *iface, BSTR Path,
2011 BSTR *pbstrResult)
2013 FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2015 return E_NOTIMPL;
2018 static inline DWORD get_parent_folder_name(const WCHAR *path, DWORD len)
2020 int i;
2022 if(!path)
2023 return 0;
2025 for(i=len-1; i>=0; i--)
2026 if(path[i]!='/' && path[i]!='\\')
2027 break;
2029 for(; i>=0; i--)
2030 if(path[i]=='/' || path[i]=='\\')
2031 break;
2033 for(; i>=0; i--)
2034 if(path[i]!='/' && path[i]!='\\')
2035 break;
2037 if(i < 0)
2038 return 0;
2040 if(path[i]==':' && i==1)
2041 i++;
2042 return i+1;
2045 static HRESULT WINAPI filesys_GetParentFolderName(IFileSystem3 *iface, BSTR Path,
2046 BSTR *pbstrResult)
2048 DWORD len;
2050 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2052 if(!pbstrResult)
2053 return E_POINTER;
2055 len = get_parent_folder_name(Path, SysStringLen(Path));
2056 if(!len) {
2057 *pbstrResult = NULL;
2058 return S_OK;
2061 *pbstrResult = SysAllocStringLen(Path, len);
2062 if(!*pbstrResult)
2063 return E_OUTOFMEMORY;
2064 return S_OK;
2067 static HRESULT WINAPI filesys_GetFileName(IFileSystem3 *iface, BSTR Path,
2068 BSTR *pbstrResult)
2070 int i, end;
2072 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2074 if(!pbstrResult)
2075 return E_POINTER;
2077 if(!Path) {
2078 *pbstrResult = NULL;
2079 return S_OK;
2082 for(end=strlenW(Path)-1; end>=0; end--)
2083 if(Path[end]!='/' && Path[end]!='\\')
2084 break;
2086 for(i=end; i>=0; i--)
2087 if(Path[i]=='/' || Path[i]=='\\')
2088 break;
2089 i++;
2091 if(i>end || (i==0 && end==1 && Path[1]==':')) {
2092 *pbstrResult = NULL;
2093 return S_OK;
2096 *pbstrResult = SysAllocStringLen(Path+i, end-i+1);
2097 if(!*pbstrResult)
2098 return E_OUTOFMEMORY;
2099 return S_OK;
2102 static HRESULT WINAPI filesys_GetBaseName(IFileSystem3 *iface, BSTR Path,
2103 BSTR *pbstrResult)
2105 int i, end;
2107 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2109 if(!pbstrResult)
2110 return E_POINTER;
2112 if(!Path) {
2113 *pbstrResult = NULL;
2114 return S_OK;
2117 for(end=strlenW(Path)-1; end>=0; end--)
2118 if(Path[end]!='/' && Path[end]!='\\')
2119 break;
2121 for(i=end; i>=0; i--) {
2122 if(Path[i]=='.' && Path[end+1]!='.')
2123 end = i-1;
2124 if(Path[i]=='/' || Path[i]=='\\')
2125 break;
2127 i++;
2129 if((i>end && Path[end+1]!='.') || (i==0 && end==1 && Path[1]==':')) {
2130 *pbstrResult = NULL;
2131 return S_OK;
2134 *pbstrResult = SysAllocStringLen(Path+i, end-i+1);
2135 if(!*pbstrResult)
2136 return E_OUTOFMEMORY;
2137 return S_OK;
2140 static HRESULT WINAPI filesys_GetExtensionName(IFileSystem3 *iface, BSTR Path,
2141 BSTR *pbstrResult)
2143 FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2145 return E_NOTIMPL;
2148 static HRESULT WINAPI filesys_GetAbsolutePathName(IFileSystem3 *iface, BSTR Path,
2149 BSTR *pbstrResult)
2151 static const WCHAR cur_path[] = {'.',0};
2153 WCHAR buf[MAX_PATH], ch;
2154 const WCHAR *path;
2155 DWORD i, beg, len, exp_len;
2156 WIN32_FIND_DATAW fdata;
2157 HANDLE fh;
2159 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2161 if(!pbstrResult)
2162 return E_POINTER;
2164 if(!Path)
2165 path = cur_path;
2166 else
2167 path = Path;
2169 len = GetFullPathNameW(path, MAX_PATH, buf, NULL);
2170 if(!len)
2171 return E_FAIL;
2173 buf[0] = toupperW(buf[0]);
2174 if(len>3 && buf[len-1] == '\\')
2175 buf[--len] = 0;
2177 for(beg=3, i=3; i<=len; i++) {
2178 if(buf[i]!='\\' && buf[i])
2179 continue;
2181 ch = buf[i];
2182 buf[i] = 0;
2183 fh = FindFirstFileW(buf, &fdata);
2184 if(fh == INVALID_HANDLE_VALUE)
2185 break;
2187 exp_len = strlenW(fdata.cFileName);
2188 if(exp_len == i-beg)
2189 memcpy(buf+beg, fdata.cFileName, exp_len*sizeof(WCHAR));
2190 FindClose(fh);
2191 buf[i] = ch;
2192 beg = i+1;
2195 *pbstrResult = SysAllocString(buf);
2196 if(!*pbstrResult)
2197 return E_OUTOFMEMORY;
2198 return S_OK;
2201 static HRESULT WINAPI filesys_GetTempName(IFileSystem3 *iface, BSTR *pbstrResult)
2203 static const WCHAR fmt[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
2205 DWORD random;
2207 TRACE("%p %p\n", iface, pbstrResult);
2209 if(!pbstrResult)
2210 return E_POINTER;
2212 *pbstrResult = SysAllocStringLen(NULL, 12);
2213 if(!*pbstrResult)
2214 return E_OUTOFMEMORY;
2216 if(!RtlGenRandom(&random, sizeof(random)))
2217 return E_FAIL;
2218 sprintfW(*pbstrResult, fmt, random & 0xfffff);
2219 return S_OK;
2222 static HRESULT WINAPI filesys_DriveExists(IFileSystem3 *iface, BSTR DriveSpec,
2223 VARIANT_BOOL *pfExists)
2225 FIXME("%p %s %p\n", iface, debugstr_w(DriveSpec), pfExists);
2227 return E_NOTIMPL;
2230 static HRESULT WINAPI filesys_FileExists(IFileSystem3 *iface, BSTR path, VARIANT_BOOL *ret)
2232 DWORD attrs;
2233 TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
2235 if (!ret) return E_POINTER;
2237 attrs = GetFileAttributesW(path);
2238 *ret = attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
2239 return S_OK;
2242 static HRESULT WINAPI filesys_FolderExists(IFileSystem3 *iface, BSTR path, VARIANT_BOOL *ret)
2244 DWORD attrs;
2245 TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
2247 if (!ret) return E_POINTER;
2249 attrs = GetFileAttributesW(path);
2250 *ret = attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
2252 return S_OK;
2255 static HRESULT WINAPI filesys_GetDrive(IFileSystem3 *iface, BSTR DriveSpec,
2256 IDrive **ppdrive)
2258 FIXME("%p %s %p\n", iface, debugstr_w(DriveSpec), ppdrive);
2260 return E_NOTIMPL;
2263 static HRESULT WINAPI filesys_GetFile(IFileSystem3 *iface, BSTR FilePath,
2264 IFile **ppfile)
2266 TRACE("%p %s %p\n", iface, debugstr_w(FilePath), ppfile);
2268 if(!ppfile)
2269 return E_POINTER;
2270 if(!FilePath)
2271 return E_INVALIDARG;
2273 return create_file(FilePath, ppfile);
2276 static HRESULT WINAPI filesys_GetFolder(IFileSystem3 *iface, BSTR FolderPath,
2277 IFolder **folder)
2279 DWORD attrs;
2281 TRACE("%p %s %p\n", iface, debugstr_w(FolderPath), folder);
2283 if(!folder)
2284 return E_POINTER;
2286 *folder = NULL;
2287 if(!FolderPath)
2288 return E_INVALIDARG;
2290 attrs = GetFileAttributesW(FolderPath);
2291 if((attrs == INVALID_FILE_ATTRIBUTES) || !(attrs & FILE_ATTRIBUTE_DIRECTORY))
2292 return CTL_E_PATHNOTFOUND;
2294 return create_folder(FolderPath, folder);
2297 static HRESULT WINAPI filesys_GetSpecialFolder(IFileSystem3 *iface,
2298 SpecialFolderConst SpecialFolder,
2299 IFolder **ppfolder)
2301 FIXME("%p %d %p\n", iface, SpecialFolder, ppfolder);
2303 return E_NOTIMPL;
2306 static inline HRESULT delete_file(const WCHAR *file, DWORD file_len, VARIANT_BOOL force)
2308 WCHAR path[MAX_PATH];
2309 DWORD len, name_len;
2310 WIN32_FIND_DATAW ffd;
2311 HANDLE f;
2313 f = FindFirstFileW(file, &ffd);
2314 if(f == INVALID_HANDLE_VALUE)
2315 return create_error(GetLastError());
2317 len = get_parent_folder_name(file, file_len);
2318 if(len+1 >= MAX_PATH) {
2319 FindClose(f);
2320 return E_FAIL;
2322 if(len) {
2323 memcpy(path, file, len*sizeof(WCHAR));
2324 path[len++] = '\\';
2327 do {
2328 if(ffd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
2329 continue;
2331 name_len = strlenW(ffd.cFileName);
2332 if(len+name_len+1 >= MAX_PATH) {
2333 FindClose(f);
2334 return E_FAIL;
2336 memcpy(path+len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
2338 TRACE("deleting %s\n", debugstr_w(path));
2340 if(!DeleteFileW(path)) {
2341 if(!force || !SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL)
2342 || !DeleteFileW(path)) {
2343 FindClose(f);
2344 return create_error(GetLastError());
2347 } while(FindNextFileW(f, &ffd));
2348 FindClose(f);
2350 return S_OK;
2353 static HRESULT WINAPI filesys_DeleteFile(IFileSystem3 *iface, BSTR FileSpec,
2354 VARIANT_BOOL Force)
2356 TRACE("%p %s %d\n", iface, debugstr_w(FileSpec), Force);
2358 if(!FileSpec)
2359 return E_POINTER;
2361 return delete_file(FileSpec, SysStringLen(FileSpec), Force);
2364 static HRESULT delete_folder(const WCHAR *folder, DWORD folder_len, VARIANT_BOOL force)
2366 WCHAR path[MAX_PATH];
2367 DWORD len, name_len;
2368 WIN32_FIND_DATAW ffd;
2369 HANDLE f;
2370 HRESULT hr;
2372 f = FindFirstFileW(folder, &ffd);
2373 if(f == INVALID_HANDLE_VALUE)
2374 return create_error(GetLastError());
2376 len = get_parent_folder_name(folder, folder_len);
2377 if(len+1 >= MAX_PATH) {
2378 FindClose(f);
2379 return E_FAIL;
2381 if(len) {
2382 memcpy(path, folder, len*sizeof(WCHAR));
2383 path[len++] = '\\';
2386 do {
2387 if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
2388 continue;
2389 if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 ||
2390 (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0)))
2391 continue;
2393 name_len = strlenW(ffd.cFileName);
2394 if(len+name_len+3 >= MAX_PATH) {
2395 FindClose(f);
2396 return E_FAIL;
2398 memcpy(path+len, ffd.cFileName, name_len*sizeof(WCHAR));
2399 path[len+name_len] = '\\';
2400 path[len+name_len+1] = '*';
2401 path[len+name_len+2] = 0;
2403 hr = delete_file(path, len+name_len+2, force);
2404 if(FAILED(hr)) {
2405 FindClose(f);
2406 return hr;
2409 hr = delete_folder(path, len+name_len+2, force);
2410 if(FAILED(hr)) {
2411 FindClose(f);
2412 return hr;
2415 path[len+name_len] = 0;
2416 TRACE("deleting %s\n", debugstr_w(path));
2418 if(!RemoveDirectoryW(path)) {
2419 FindClose(f);
2420 return create_error(GetLastError());
2422 } while(FindNextFileW(f, &ffd));
2423 FindClose(f);
2425 return S_OK;
2428 static HRESULT WINAPI filesys_DeleteFolder(IFileSystem3 *iface, BSTR FolderSpec,
2429 VARIANT_BOOL Force)
2431 TRACE("%p %s %d\n", iface, debugstr_w(FolderSpec), Force);
2433 if(!FolderSpec)
2434 return E_POINTER;
2436 return delete_folder(FolderSpec, SysStringLen(FolderSpec), Force);
2439 static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR Source,
2440 BSTR Destination)
2442 FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
2444 return E_NOTIMPL;
2447 static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface,BSTR Source,
2448 BSTR Destination)
2450 FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
2452 return E_NOTIMPL;
2455 static inline HRESULT copy_file(const WCHAR *source, DWORD source_len,
2456 const WCHAR *destination, DWORD destination_len, VARIANT_BOOL overwrite)
2458 DWORD attrs;
2459 WCHAR src_path[MAX_PATH], dst_path[MAX_PATH];
2460 DWORD src_len, dst_len, name_len;
2461 WIN32_FIND_DATAW ffd;
2462 HANDLE f;
2463 HRESULT hr;
2465 if(!source[0] || !destination[0])
2466 return E_INVALIDARG;
2468 attrs = GetFileAttributesW(destination);
2469 if(attrs==INVALID_FILE_ATTRIBUTES || !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
2470 attrs = GetFileAttributesW(source);
2471 if(attrs == INVALID_FILE_ATTRIBUTES)
2472 return create_error(GetLastError());
2473 else if(attrs & FILE_ATTRIBUTE_DIRECTORY)
2474 return CTL_E_FILENOTFOUND;
2476 if(!CopyFileW(source, destination, !overwrite))
2477 return create_error(GetLastError());
2478 return S_OK;
2481 f = FindFirstFileW(source, &ffd);
2482 if(f == INVALID_HANDLE_VALUE)
2483 return CTL_E_FILENOTFOUND;
2485 src_len = get_parent_folder_name(source, source_len);
2486 if(src_len+1 >= MAX_PATH)
2487 return E_FAIL;
2488 if(src_len) {
2489 memcpy(src_path, source, src_len*sizeof(WCHAR));
2490 src_path[src_len++] = '\\';
2493 dst_len = destination_len;
2494 if(dst_len+1 >= MAX_PATH) {
2495 FindClose(f);
2496 return E_FAIL;
2498 memcpy(dst_path, destination, dst_len*sizeof(WCHAR));
2499 if(dst_path[dst_len-1]!= '\\' && dst_path[dst_len-1]!='/')
2500 dst_path[dst_len++] = '\\';
2502 hr = CTL_E_FILENOTFOUND;
2503 do {
2504 if(ffd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
2505 continue;
2507 name_len = strlenW(ffd.cFileName);
2508 if(src_len+name_len+1>=MAX_PATH || dst_len+name_len+1>=MAX_PATH) {
2509 FindClose(f);
2510 return E_FAIL;
2512 memcpy(src_path+src_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
2513 memcpy(dst_path+dst_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
2515 TRACE("copying %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path));
2517 if(!CopyFileW(src_path, dst_path, !overwrite)) {
2518 FindClose(f);
2519 return create_error(GetLastError());
2520 }else {
2521 hr = S_OK;
2523 } while(FindNextFileW(f, &ffd));
2524 FindClose(f);
2526 return hr;
2529 static HRESULT WINAPI filesys_CopyFile(IFileSystem3 *iface, BSTR Source,
2530 BSTR Destination, VARIANT_BOOL OverWriteFiles)
2532 TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
2534 if(!Source || !Destination)
2535 return E_POINTER;
2537 return copy_file(Source, SysStringLen(Source), Destination,
2538 SysStringLen(Destination), OverWriteFiles);
2541 static HRESULT copy_folder(const WCHAR *source, DWORD source_len, const WCHAR *destination,
2542 DWORD destination_len, VARIANT_BOOL overwrite)
2544 DWORD tmp, src_len, dst_len, name_len;
2545 WCHAR src[MAX_PATH], dst[MAX_PATH];
2546 WIN32_FIND_DATAW ffd;
2547 HANDLE f;
2548 HRESULT hr;
2549 BOOL copied = FALSE;
2551 if(!source[0] || !destination[0])
2552 return E_INVALIDARG;
2554 dst_len = destination_len;
2555 if(dst_len+1 >= MAX_PATH)
2556 return E_FAIL;
2557 memcpy(dst, destination, (dst_len+1)*sizeof(WCHAR));
2559 if(dst[dst_len-1]!='\\' && dst[dst_len-1]!='/' &&
2560 (tmp = GetFileAttributesW(source))!=INVALID_FILE_ATTRIBUTES &&
2561 tmp&FILE_ATTRIBUTE_DIRECTORY) {
2562 if(!CreateDirectoryW(dst, NULL)) {
2563 if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) {
2564 tmp = GetFileAttributesW(dst);
2565 if(tmp==INVALID_FILE_ATTRIBUTES || !(tmp&FILE_ATTRIBUTE_DIRECTORY))
2566 return CTL_E_FILEALREADYEXISTS;
2567 }else {
2568 return create_error(GetLastError());
2571 copied = TRUE;
2573 src_len = source_len;
2574 if(src_len+2 >= MAX_PATH)
2575 return E_FAIL;
2576 memcpy(src, source, src_len*sizeof(WCHAR));
2577 src[src_len++] = '\\';
2578 src[src_len] = '*';
2579 src[src_len+1] = 0;
2581 hr = copy_file(src, src_len+1, dst, dst_len, overwrite);
2582 if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND)
2583 return create_error(GetLastError());
2585 f = FindFirstFileW(src, &ffd);
2586 }else {
2587 src_len = get_parent_folder_name(source, source_len);
2588 if(src_len+2 >= MAX_PATH)
2589 return E_FAIL;
2590 memcpy(src, source, src_len*sizeof(WCHAR));
2591 if(src_len)
2592 src[src_len++] = '\\';
2594 f = FindFirstFileW(source, &ffd);
2596 if(f == INVALID_HANDLE_VALUE)
2597 return CTL_E_PATHNOTFOUND;
2599 dst[dst_len++] = '\\';
2600 dst[dst_len] = 0;
2602 do {
2603 if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
2604 continue;
2605 if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 ||
2606 (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0)))
2607 continue;
2609 name_len = strlenW(ffd.cFileName);
2610 if(dst_len+name_len>=MAX_PATH || src_len+name_len+2>=MAX_PATH) {
2611 FindClose(f);
2612 return E_FAIL;
2614 memcpy(dst+dst_len, ffd.cFileName, name_len*sizeof(WCHAR));
2615 dst[dst_len+name_len] = 0;
2616 memcpy(src+src_len, ffd.cFileName, name_len*sizeof(WCHAR));
2617 src[src_len+name_len] = '\\';
2618 src[src_len+name_len+1] = '*';
2619 src[src_len+name_len+2] = 0;
2621 TRACE("copying %s to %s\n", debugstr_w(src), debugstr_w(dst));
2623 if(!CreateDirectoryW(dst, NULL)) {
2624 if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) {
2625 tmp = GetFileAttributesW(dst);
2626 if(tmp==INVALID_FILE_ATTRIBUTES || !(tmp&FILE_ATTRIBUTE_DIRECTORY)) {
2627 FindClose(f);
2628 return CTL_E_FILEALREADYEXISTS;
2630 }else {
2631 FindClose(f);
2632 return create_error(GetLastError());
2634 return create_error(GetLastError());
2636 copied = TRUE;
2638 hr = copy_file(src, src_len+name_len+2, dst, dst_len+name_len, overwrite);
2639 if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND) {
2640 FindClose(f);
2641 return hr;
2644 hr = copy_folder(src, src_len+name_len+2, dst, dst_len+name_len, overwrite);
2645 if(FAILED(hr) && hr!=CTL_E_PATHNOTFOUND) {
2646 FindClose(f);
2647 return hr;
2649 } while(FindNextFileW(f, &ffd));
2650 FindClose(f);
2652 return copied ? S_OK : CTL_E_PATHNOTFOUND;
2655 static HRESULT WINAPI filesys_CopyFolder(IFileSystem3 *iface, BSTR Source,
2656 BSTR Destination, VARIANT_BOOL OverWriteFiles)
2658 TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
2660 if(!Source || !Destination)
2661 return E_POINTER;
2663 return copy_folder(Source, SysStringLen(Source), Destination,
2664 SysStringLen(Destination), OverWriteFiles);
2667 static HRESULT WINAPI filesys_CreateFolder(IFileSystem3 *iface, BSTR path,
2668 IFolder **folder)
2670 BOOL ret;
2672 TRACE("(%p)->(%s %p)\n", iface, debugstr_w(path), folder);
2674 ret = CreateDirectoryW(path, NULL);
2675 if (!ret)
2677 *folder = NULL;
2678 if (GetLastError() == ERROR_ALREADY_EXISTS) return CTL_E_FILEALREADYEXISTS;
2679 return HRESULT_FROM_WIN32(GetLastError());
2682 return create_folder(path, folder);
2685 static HRESULT WINAPI filesys_CreateTextFile(IFileSystem3 *iface, BSTR FileName,
2686 VARIANT_BOOL Overwrite, VARIANT_BOOL Unicode,
2687 ITextStream **ppts)
2689 FIXME("%p %s %d %d %p\n", iface, debugstr_w(FileName), Overwrite, Unicode, ppts);
2691 return E_NOTIMPL;
2694 static HRESULT WINAPI filesys_OpenTextFile(IFileSystem3 *iface, BSTR filename,
2695 IOMode mode, VARIANT_BOOL create,
2696 Tristate format, ITextStream **stream)
2698 FIXME("(%p)->(%s %d %d %d %p)\n", iface, debugstr_w(filename), mode, create, format, stream);
2699 return create_textstream(mode, stream);
2702 static HRESULT WINAPI filesys_GetStandardStream(IFileSystem3 *iface,
2703 StandardStreamTypes StandardStreamType,
2704 VARIANT_BOOL Unicode,
2705 ITextStream **ppts)
2707 FIXME("%p %d %d %p\n", iface, StandardStreamType, Unicode, ppts);
2709 return E_NOTIMPL;
2712 static void get_versionstring(VS_FIXEDFILEINFO *info, WCHAR *ver)
2714 static const WCHAR fmtW[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
2715 DWORDLONG version;
2716 WORD a, b, c, d;
2718 version = (((DWORDLONG)info->dwFileVersionMS) << 32) + info->dwFileVersionLS;
2719 a = (WORD)( version >> 48);
2720 b = (WORD)((version >> 32) & 0xffff);
2721 c = (WORD)((version >> 16) & 0xffff);
2722 d = (WORD)( version & 0xffff);
2724 sprintfW(ver, fmtW, a, b, c, d);
2727 static HRESULT WINAPI filesys_GetFileVersion(IFileSystem3 *iface, BSTR name, BSTR *version)
2729 static const WCHAR rootW[] = {'\\',0};
2730 VS_FIXEDFILEINFO *info;
2731 WCHAR ver[30];
2732 void *ptr;
2733 DWORD len;
2734 BOOL ret;
2736 TRACE("%p %s %p\n", iface, debugstr_w(name), version);
2738 len = GetFileVersionInfoSizeW(name, NULL);
2739 if (!len)
2740 return HRESULT_FROM_WIN32(GetLastError());
2742 ptr = heap_alloc(len);
2743 if (!GetFileVersionInfoW(name, 0, len, ptr))
2745 heap_free(ptr);
2746 return HRESULT_FROM_WIN32(GetLastError());
2749 ret = VerQueryValueW(ptr, rootW, (void**)&info, &len);
2750 heap_free(ptr);
2751 if (!ret)
2752 return HRESULT_FROM_WIN32(GetLastError());
2754 get_versionstring(info, ver);
2755 *version = SysAllocString(ver);
2756 TRACE("version=%s\n", debugstr_w(ver));
2758 return S_OK;
2761 static const struct IFileSystem3Vtbl filesys_vtbl =
2763 filesys_QueryInterface,
2764 filesys_AddRef,
2765 filesys_Release,
2766 filesys_GetTypeInfoCount,
2767 filesys_GetTypeInfo,
2768 filesys_GetIDsOfNames,
2769 filesys_Invoke,
2770 filesys_get_Drives,
2771 filesys_BuildPath,
2772 filesys_GetDriveName,
2773 filesys_GetParentFolderName,
2774 filesys_GetFileName,
2775 filesys_GetBaseName,
2776 filesys_GetExtensionName,
2777 filesys_GetAbsolutePathName,
2778 filesys_GetTempName,
2779 filesys_DriveExists,
2780 filesys_FileExists,
2781 filesys_FolderExists,
2782 filesys_GetDrive,
2783 filesys_GetFile,
2784 filesys_GetFolder,
2785 filesys_GetSpecialFolder,
2786 filesys_DeleteFile,
2787 filesys_DeleteFolder,
2788 filesys_MoveFile,
2789 filesys_MoveFolder,
2790 filesys_CopyFile,
2791 filesys_CopyFolder,
2792 filesys_CreateFolder,
2793 filesys_CreateTextFile,
2794 filesys_OpenTextFile,
2795 filesys_GetStandardStream,
2796 filesys_GetFileVersion
2799 static IFileSystem3 filesystem = { &filesys_vtbl };
2801 HRESULT WINAPI FileSystem_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2803 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
2805 return IFileSystem3_QueryInterface(&filesystem, riid, ppv);