advapi32: Don't shadow keychain_item in mac_write_credential.
[wine/multimedia.git] / dlls / scrrun / filesystem.c
blobbfb201cfa572082ab45742ba5dc37bafd4a3b1fc
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 HRESULT WINAPI foldercoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched)
472 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
473 HANDLE handle = This->data.u.foldercoll.find;
474 WIN32_FIND_DATAW data;
475 ULONG count = 0;
477 TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
479 if (fetched)
480 *fetched = 0;
482 if (!handle)
484 static const WCHAR allW[] = {'*',0};
485 WCHAR pathW[MAX_PATH];
486 BSTR parent = This->data.u.foldercoll.coll->path;
487 int len;
489 strcpyW(pathW, parent);
490 len = SysStringLen(parent);
491 if (parent[len-1] != '\\')
492 strcatW(pathW, bsW);
493 strcatW(pathW, allW);
494 handle = FindFirstFileW(pathW, &data);
495 if (handle == INVALID_HANDLE_VALUE)
496 return S_FALSE;
498 /* find first dir */
499 while (1)
501 if (is_dir_data(&data))
502 break;
503 else
504 if (!FindNextFileW(handle, &data))
506 FindClose(handle);
507 return S_FALSE;
511 This->data.u.foldercoll.find = handle;
513 else if (celt)
514 FindNextFileW(handle, &data);
518 if (count >= celt) break;
520 if (is_dir_data(&data))
522 IFolder *folder;
523 HRESULT hr;
524 BSTR str;
526 str = get_full_path(This->data.u.foldercoll.coll->path, &data);
527 hr = create_folder(str, &folder);
528 SysFreeString(str);
529 if (FAILED(hr)) return hr;
531 V_VT(&var[count]) = VT_DISPATCH;
532 V_DISPATCH(&var[count]) = (IDispatch*)folder;
533 count++;
535 } while (FindNextFileW(handle, &data));
537 if (count < celt)
538 return S_FALSE;
540 if (fetched)
541 *fetched = count;
543 return S_OK;
546 static HRESULT WINAPI foldercoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt)
548 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
549 HANDLE handle = This->data.u.foldercoll.find;
550 WIN32_FIND_DATAW data;
552 TRACE("(%p)->(%d)\n", This, celt);
554 while (FindNextFileW(handle, &data) && celt)
555 if (is_dir_data(&data))
556 --celt;
558 return celt ? S_FALSE : S_OK;
561 static HRESULT WINAPI foldercoll_enumvariant_Reset(IEnumVARIANT *iface)
563 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
565 TRACE("(%p)\n", This);
567 FindClose(This->data.u.foldercoll.find);
568 This->data.u.foldercoll.find = NULL;
570 return S_OK;
573 static HRESULT WINAPI foldercoll_enumvariant_Clone(IEnumVARIANT *iface, IEnumVARIANT **pclone)
575 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
576 TRACE("(%p)->(%p)\n", This, pclone);
577 return create_foldercoll_enum(This->data.u.foldercoll.coll, (IUnknown**)pclone);
580 static const IEnumVARIANTVtbl foldercollenumvariantvtbl = {
581 enumvariant_QueryInterface,
582 enumvariant_AddRef,
583 foldercoll_enumvariant_Release,
584 foldercoll_enumvariant_Next,
585 foldercoll_enumvariant_Skip,
586 foldercoll_enumvariant_Reset,
587 foldercoll_enumvariant_Clone
590 HRESULT create_foldercoll_enum(struct foldercollection *collection, IUnknown **newenum)
592 struct enumvariant *This;
594 *newenum = NULL;
596 This = heap_alloc(sizeof(*This));
597 if (!This) return E_OUTOFMEMORY;
599 This->IEnumVARIANT_iface.lpVtbl = &foldercollenumvariantvtbl;
600 This->ref = 1;
601 This->data.u.foldercoll.find = NULL;
602 This->data.u.foldercoll.coll = collection;
603 IFolderCollection_AddRef(&collection->IFolderCollection_iface);
605 *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
607 return S_OK;
610 static ULONG WINAPI filecoll_enumvariant_Release(IEnumVARIANT *iface)
612 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
613 ULONG ref = InterlockedDecrement(&This->ref);
615 TRACE("(%p)->(%d)\n", This, ref);
617 if (!ref)
619 IFileCollection_Release(&This->data.u.filecoll.coll->IFileCollection_iface);
620 heap_free(This);
623 return ref;
626 static HRESULT WINAPI filecoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched)
628 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
629 HANDLE handle = This->data.u.filecoll.find;
630 WIN32_FIND_DATAW data;
631 ULONG count = 0;
633 TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
635 if (fetched)
636 *fetched = 0;
638 if (!handle)
640 static const WCHAR allW[] = {'*',0};
641 WCHAR pathW[MAX_PATH];
642 BSTR parent = This->data.u.filecoll.coll->path;
643 int len;
645 strcpyW(pathW, parent);
646 len = SysStringLen(parent);
647 if (parent[len-1] != '\\')
648 strcatW(pathW, bsW);
649 strcatW(pathW, allW);
650 handle = FindFirstFileW(pathW, &data);
651 if (handle == INVALID_HANDLE_VALUE)
652 return S_FALSE;
654 while (1)
656 if (is_file_data(&data))
657 break;
658 else
659 if (!FindNextFileW(handle, &data))
661 FindClose(handle);
662 return S_FALSE;
666 This->data.u.filecoll.find = handle;
668 else if (celt)
669 FindNextFileW(handle, &data);
673 if (count >= celt) break;
675 if (is_file_data(&data))
677 IFile *file;
678 HRESULT hr;
679 BSTR str;
681 str = get_full_path(This->data.u.filecoll.coll->path, &data);
682 hr = create_file(str, &file);
683 SysFreeString(str);
684 if (FAILED(hr)) return hr;
686 V_VT(&var[count]) = VT_DISPATCH;
687 V_DISPATCH(&var[count]) = (IDispatch*)file;
688 count++;
690 } while (FindNextFileW(handle, &data));
692 if (count < celt)
693 return S_FALSE;
695 if (fetched)
696 *fetched = count;
698 return S_OK;
701 static HRESULT WINAPI filecoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt)
703 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
704 HANDLE handle = This->data.u.filecoll.find;
705 WIN32_FIND_DATAW data;
707 TRACE("(%p)->(%d)\n", This, celt);
709 while (FindNextFileW(handle, &data) && celt)
710 if (is_file_data(&data))
711 --celt;
713 return celt ? S_FALSE : S_OK;
716 static HRESULT WINAPI filecoll_enumvariant_Reset(IEnumVARIANT *iface)
718 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
720 TRACE("(%p)\n", This);
722 FindClose(This->data.u.filecoll.find);
723 This->data.u.filecoll.find = NULL;
725 return S_OK;
728 static HRESULT WINAPI filecoll_enumvariant_Clone(IEnumVARIANT *iface, IEnumVARIANT **pclone)
730 struct enumvariant *This = impl_from_IEnumVARIANT(iface);
731 TRACE("(%p)->(%p)\n", This, pclone);
732 return create_filecoll_enum(This->data.u.filecoll.coll, (IUnknown**)pclone);
735 static const IEnumVARIANTVtbl filecollenumvariantvtbl = {
736 enumvariant_QueryInterface,
737 enumvariant_AddRef,
738 filecoll_enumvariant_Release,
739 filecoll_enumvariant_Next,
740 filecoll_enumvariant_Skip,
741 filecoll_enumvariant_Reset,
742 filecoll_enumvariant_Clone
745 HRESULT create_filecoll_enum(struct filecollection *collection, IUnknown **newenum)
747 struct enumvariant *This;
749 *newenum = NULL;
751 This = heap_alloc(sizeof(*This));
752 if (!This) return E_OUTOFMEMORY;
754 This->IEnumVARIANT_iface.lpVtbl = &filecollenumvariantvtbl;
755 This->ref = 1;
756 This->data.u.filecoll.coll = collection;
757 IFileCollection_AddRef(&collection->IFileCollection_iface);
759 *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
761 return S_OK;
764 static HRESULT WINAPI foldercoll_QueryInterface(IFolderCollection *iface, REFIID riid, void **obj)
766 struct foldercollection *This = impl_from_IFolderCollection(iface);
768 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
770 *obj = NULL;
772 if (IsEqualIID( riid, &IID_IFolderCollection ) ||
773 IsEqualIID( riid, &IID_IDispatch ) ||
774 IsEqualIID( riid, &IID_IUnknown ))
776 *obj = iface;
777 IFolderCollection_AddRef(iface);
779 else
780 return E_NOINTERFACE;
782 return S_OK;
785 static ULONG WINAPI foldercoll_AddRef(IFolderCollection *iface)
787 struct foldercollection *This = impl_from_IFolderCollection(iface);
788 ULONG ref = InterlockedIncrement(&This->ref);
789 TRACE("(%p)->(%d)\n", This, ref);
790 return ref;
793 static ULONG WINAPI foldercoll_Release(IFolderCollection *iface)
795 struct foldercollection *This = impl_from_IFolderCollection(iface);
796 ULONG ref = InterlockedDecrement(&This->ref);
797 TRACE("(%p)->(%d)\n", This, ref);
799 if (!ref)
801 SysFreeString(This->path);
802 heap_free(This);
805 return ref;
808 static HRESULT WINAPI foldercoll_GetTypeInfoCount(IFolderCollection *iface, UINT *pctinfo)
810 struct foldercollection *This = impl_from_IFolderCollection(iface);
811 TRACE("(%p)->(%p)\n", This, pctinfo);
812 *pctinfo = 1;
813 return S_OK;
816 static HRESULT WINAPI foldercoll_GetTypeInfo(IFolderCollection *iface, UINT iTInfo,
817 LCID lcid, ITypeInfo **ppTInfo)
819 struct foldercollection *This = impl_from_IFolderCollection(iface);
820 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
821 return get_typeinfo(IFolderCollection_tid, ppTInfo);
824 static HRESULT WINAPI foldercoll_GetIDsOfNames(IFolderCollection *iface, REFIID riid,
825 LPOLESTR *rgszNames, UINT cNames,
826 LCID lcid, DISPID *rgDispId)
828 struct foldercollection *This = impl_from_IFolderCollection(iface);
829 ITypeInfo *typeinfo;
830 HRESULT hr;
832 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
834 hr = get_typeinfo(IFolderCollection_tid, &typeinfo);
835 if(SUCCEEDED(hr))
837 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
838 ITypeInfo_Release(typeinfo);
841 return hr;
844 static HRESULT WINAPI foldercoll_Invoke(IFolderCollection *iface, DISPID dispIdMember,
845 REFIID riid, LCID lcid, WORD wFlags,
846 DISPPARAMS *pDispParams, VARIANT *pVarResult,
847 EXCEPINFO *pExcepInfo, UINT *puArgErr)
849 struct foldercollection *This = impl_from_IFolderCollection(iface);
850 ITypeInfo *typeinfo;
851 HRESULT hr;
853 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
854 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
856 hr = get_typeinfo(IFolderCollection_tid, &typeinfo);
857 if(SUCCEEDED(hr))
859 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
860 pDispParams, pVarResult, pExcepInfo, puArgErr);
861 ITypeInfo_Release(typeinfo);
864 return hr;
867 static HRESULT WINAPI foldercoll_Add(IFolderCollection *iface, BSTR name, IFolder **folder)
869 struct foldercollection *This = impl_from_IFolderCollection(iface);
870 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(name), folder);
871 return E_NOTIMPL;
874 static HRESULT WINAPI foldercoll_get_Item(IFolderCollection *iface, VARIANT key, IFolder **folder)
876 struct foldercollection *This = impl_from_IFolderCollection(iface);
877 FIXME("(%p)->(%p): stub\n", This, folder);
878 return E_NOTIMPL;
881 static HRESULT WINAPI foldercoll_get__NewEnum(IFolderCollection *iface, IUnknown **newenum)
883 struct foldercollection *This = impl_from_IFolderCollection(iface);
885 TRACE("(%p)->(%p)\n", This, newenum);
887 if(!newenum)
888 return E_POINTER;
890 return create_foldercoll_enum(This, newenum);
893 static HRESULT WINAPI foldercoll_get_Count(IFolderCollection *iface, LONG *count)
895 struct foldercollection *This = impl_from_IFolderCollection(iface);
896 static const WCHAR allW[] = {'\\','*',0};
897 WIN32_FIND_DATAW data;
898 WCHAR pathW[MAX_PATH];
899 HANDLE handle;
901 TRACE("(%p)->(%p)\n", This, count);
903 if(!count)
904 return E_POINTER;
906 *count = 0;
908 strcpyW(pathW, This->path);
909 strcatW(pathW, allW);
910 handle = FindFirstFileW(pathW, &data);
911 if (handle == INVALID_HANDLE_VALUE)
912 return HRESULT_FROM_WIN32(GetLastError());
916 if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
917 *count += 1;
918 } while (FindNextFileW(handle, &data));
919 FindClose(handle);
921 return S_OK;
924 static const IFolderCollectionVtbl foldercollvtbl = {
925 foldercoll_QueryInterface,
926 foldercoll_AddRef,
927 foldercoll_Release,
928 foldercoll_GetTypeInfoCount,
929 foldercoll_GetTypeInfo,
930 foldercoll_GetIDsOfNames,
931 foldercoll_Invoke,
932 foldercoll_Add,
933 foldercoll_get_Item,
934 foldercoll_get__NewEnum,
935 foldercoll_get_Count
938 static HRESULT create_foldercoll(BSTR path, IFolderCollection **folders)
940 struct foldercollection *This;
942 *folders = NULL;
944 This = heap_alloc(sizeof(struct foldercollection));
945 if (!This) return E_OUTOFMEMORY;
947 This->IFolderCollection_iface.lpVtbl = &foldercollvtbl;
948 This->ref = 1;
949 This->path = SysAllocString(path);
950 if (!This->path)
952 heap_free(This);
953 return E_OUTOFMEMORY;
956 *folders = &This->IFolderCollection_iface;
958 return S_OK;
961 static HRESULT WINAPI filecoll_QueryInterface(IFileCollection *iface, REFIID riid, void **obj)
963 struct filecollection *This = impl_from_IFileCollection(iface);
965 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
967 *obj = NULL;
969 if (IsEqualIID( riid, &IID_IFileCollection ) ||
970 IsEqualIID( riid, &IID_IDispatch ) ||
971 IsEqualIID( riid, &IID_IUnknown ))
973 *obj = iface;
974 IFileCollection_AddRef(iface);
976 else
977 return E_NOINTERFACE;
979 return S_OK;
982 static ULONG WINAPI filecoll_AddRef(IFileCollection *iface)
984 struct filecollection *This = impl_from_IFileCollection(iface);
985 ULONG ref = InterlockedIncrement(&This->ref);
986 TRACE("(%p)->(%d)\n", This, ref);
987 return ref;
990 static ULONG WINAPI filecoll_Release(IFileCollection *iface)
992 struct filecollection *This = impl_from_IFileCollection(iface);
993 ULONG ref = InterlockedDecrement(&This->ref);
994 TRACE("(%p)->(%d)\n", This, ref);
996 if (!ref)
998 SysFreeString(This->path);
999 heap_free(This);
1002 return ref;
1005 static HRESULT WINAPI filecoll_GetTypeInfoCount(IFileCollection *iface, UINT *pctinfo)
1007 struct filecollection *This = impl_from_IFileCollection(iface);
1008 TRACE("(%p)->(%p)\n", This, pctinfo);
1009 *pctinfo = 1;
1010 return S_OK;
1013 static HRESULT WINAPI filecoll_GetTypeInfo(IFileCollection *iface, UINT iTInfo,
1014 LCID lcid, ITypeInfo **ppTInfo)
1016 struct filecollection *This = impl_from_IFileCollection(iface);
1017 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1018 return get_typeinfo(IFileCollection_tid, ppTInfo);
1021 static HRESULT WINAPI filecoll_GetIDsOfNames(IFileCollection *iface, REFIID riid,
1022 LPOLESTR *rgszNames, UINT cNames,
1023 LCID lcid, DISPID *rgDispId)
1025 struct filecollection *This = impl_from_IFileCollection(iface);
1026 ITypeInfo *typeinfo;
1027 HRESULT hr;
1029 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1031 hr = get_typeinfo(IFileCollection_tid, &typeinfo);
1032 if(SUCCEEDED(hr))
1034 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1035 ITypeInfo_Release(typeinfo);
1038 return hr;
1041 static HRESULT WINAPI filecoll_Invoke(IFileCollection *iface, DISPID dispIdMember,
1042 REFIID riid, LCID lcid, WORD wFlags,
1043 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1044 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1046 struct filecollection *This = impl_from_IFileCollection(iface);
1047 ITypeInfo *typeinfo;
1048 HRESULT hr;
1050 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1051 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1053 hr = get_typeinfo(IFileCollection_tid, &typeinfo);
1054 if(SUCCEEDED(hr))
1056 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1057 pDispParams, pVarResult, pExcepInfo, puArgErr);
1058 ITypeInfo_Release(typeinfo);
1061 return hr;
1064 static HRESULT WINAPI filecoll_get_Item(IFileCollection *iface, VARIANT Key, IFile **file)
1066 struct filecollection *This = impl_from_IFileCollection(iface);
1067 FIXME("(%p)->(%p)\n", This, file);
1068 return E_NOTIMPL;
1071 static HRESULT WINAPI filecoll_get__NewEnum(IFileCollection *iface, IUnknown **ppenum)
1073 struct filecollection *This = impl_from_IFileCollection(iface);
1075 TRACE("(%p)->(%p)\n", This, ppenum);
1077 if(!ppenum)
1078 return E_POINTER;
1080 return create_filecoll_enum(This, ppenum);
1083 static HRESULT WINAPI filecoll_get_Count(IFileCollection *iface, LONG *count)
1085 struct filecollection *This = impl_from_IFileCollection(iface);
1086 FIXME("(%p)->(%p)\n", This, count);
1087 return E_NOTIMPL;
1090 static const IFileCollectionVtbl filecollectionvtbl = {
1091 filecoll_QueryInterface,
1092 filecoll_AddRef,
1093 filecoll_Release,
1094 filecoll_GetTypeInfoCount,
1095 filecoll_GetTypeInfo,
1096 filecoll_GetIDsOfNames,
1097 filecoll_Invoke,
1098 filecoll_get_Item,
1099 filecoll_get__NewEnum,
1100 filecoll_get_Count
1103 static HRESULT create_filecoll(BSTR path, IFileCollection **files)
1105 struct filecollection *This;
1107 *files = NULL;
1109 This = heap_alloc(sizeof(*This));
1110 if (!This) return E_OUTOFMEMORY;
1112 This->IFileCollection_iface.lpVtbl = &filecollectionvtbl;
1113 This->ref = 1;
1114 This->path = SysAllocString(path);
1115 if (!This->path)
1117 heap_free(This);
1118 return E_OUTOFMEMORY;
1121 *files = &This->IFileCollection_iface;
1122 return S_OK;
1125 static HRESULT WINAPI folder_QueryInterface(IFolder *iface, REFIID riid, void **obj)
1127 struct folder *This = impl_from_IFolder(iface);
1129 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1131 *obj = NULL;
1133 if (IsEqualIID( riid, &IID_IFolder ) ||
1134 IsEqualIID( riid, &IID_IDispatch ) ||
1135 IsEqualIID( riid, &IID_IUnknown))
1137 *obj = iface;
1138 IFolder_AddRef(iface);
1140 else
1141 return E_NOINTERFACE;
1143 return S_OK;
1146 static ULONG WINAPI folder_AddRef(IFolder *iface)
1148 struct folder *This = impl_from_IFolder(iface);
1149 ULONG ref = InterlockedIncrement(&This->ref);
1150 TRACE("(%p)->(%d)\n", This, ref);
1151 return ref;
1154 static ULONG WINAPI folder_Release(IFolder *iface)
1156 struct folder *This = impl_from_IFolder(iface);
1157 ULONG ref = InterlockedDecrement(&This->ref);
1158 TRACE("(%p)->(%d)\n", This, ref);
1160 if (!ref)
1162 SysFreeString(This->path);
1163 heap_free(This);
1166 return ref;
1169 static HRESULT WINAPI folder_GetTypeInfoCount(IFolder *iface, UINT *pctinfo)
1171 struct folder *This = impl_from_IFolder(iface);
1172 TRACE("(%p)->(%p)\n", This, pctinfo);
1173 *pctinfo = 1;
1174 return S_OK;
1177 static HRESULT WINAPI folder_GetTypeInfo(IFolder *iface, UINT iTInfo,
1178 LCID lcid, ITypeInfo **ppTInfo)
1180 struct folder *This = impl_from_IFolder(iface);
1181 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1182 return get_typeinfo(IFolder_tid, ppTInfo);
1185 static HRESULT WINAPI folder_GetIDsOfNames(IFolder *iface, REFIID riid,
1186 LPOLESTR *rgszNames, UINT cNames,
1187 LCID lcid, DISPID *rgDispId)
1189 struct folder *This = impl_from_IFolder(iface);
1190 ITypeInfo *typeinfo;
1191 HRESULT hr;
1193 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1195 hr = get_typeinfo(IFolder_tid, &typeinfo);
1196 if(SUCCEEDED(hr))
1198 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1199 ITypeInfo_Release(typeinfo);
1202 return hr;
1205 static HRESULT WINAPI folder_Invoke(IFolder *iface, DISPID dispIdMember,
1206 REFIID riid, LCID lcid, WORD wFlags,
1207 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1208 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1210 struct folder *This = impl_from_IFolder(iface);
1211 ITypeInfo *typeinfo;
1212 HRESULT hr;
1214 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1215 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1217 hr = get_typeinfo(IFolder_tid, &typeinfo);
1218 if(SUCCEEDED(hr))
1220 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1221 pDispParams, pVarResult, pExcepInfo, puArgErr);
1222 ITypeInfo_Release(typeinfo);
1225 return hr;
1228 static HRESULT WINAPI folder_get_Path(IFolder *iface, BSTR *path)
1230 struct folder *This = impl_from_IFolder(iface);
1231 FIXME("(%p)->(%p): stub\n", This, path);
1232 return E_NOTIMPL;
1235 static HRESULT WINAPI folder_get_Name(IFolder *iface, BSTR *name)
1237 struct folder *This = impl_from_IFolder(iface);
1238 WCHAR *ptr;
1240 TRACE("(%p)->(%p)\n", This, name);
1242 if(!name)
1243 return E_POINTER;
1245 *name = NULL;
1247 ptr = strrchrW(This->path, '\\');
1248 if (ptr)
1250 *name = SysAllocString(ptr+1);
1251 TRACE("%s\n", debugstr_w(*name));
1252 if (!*name) return E_OUTOFMEMORY;
1254 else
1255 return E_FAIL;
1257 return S_OK;
1260 static HRESULT WINAPI folder_put_Name(IFolder *iface, BSTR name)
1262 struct folder *This = impl_from_IFolder(iface);
1263 FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
1264 return E_NOTIMPL;
1267 static HRESULT WINAPI folder_get_ShortPath(IFolder *iface, BSTR *path)
1269 struct folder *This = impl_from_IFolder(iface);
1270 FIXME("(%p)->(%p): stub\n", This, path);
1271 return E_NOTIMPL;
1274 static HRESULT WINAPI folder_get_ShortName(IFolder *iface, BSTR *name)
1276 struct folder *This = impl_from_IFolder(iface);
1277 FIXME("(%p)->(%p): stub\n", This, name);
1278 return E_NOTIMPL;
1281 static HRESULT WINAPI folder_get_Drive(IFolder *iface, IDrive **drive)
1283 struct folder *This = impl_from_IFolder(iface);
1284 FIXME("(%p)->(%p): stub\n", This, drive);
1285 return E_NOTIMPL;
1288 static HRESULT WINAPI folder_get_ParentFolder(IFolder *iface, IFolder **parent)
1290 struct folder *This = impl_from_IFolder(iface);
1291 FIXME("(%p)->(%p): stub\n", This, parent);
1292 return E_NOTIMPL;
1295 static HRESULT WINAPI folder_get_Attributes(IFolder *iface, FileAttribute *attr)
1297 struct folder *This = impl_from_IFolder(iface);
1298 FIXME("(%p)->(%p): stub\n", This, attr);
1299 return E_NOTIMPL;
1302 static HRESULT WINAPI folder_put_Attributes(IFolder *iface, FileAttribute attr)
1304 struct folder *This = impl_from_IFolder(iface);
1305 FIXME("(%p)->(0x%x): stub\n", This, attr);
1306 return E_NOTIMPL;
1309 static HRESULT WINAPI folder_get_DateCreated(IFolder *iface, DATE *date)
1311 struct folder *This = impl_from_IFolder(iface);
1312 FIXME("(%p)->(%p): stub\n", This, date);
1313 return E_NOTIMPL;
1316 static HRESULT WINAPI folder_get_DateLastModified(IFolder *iface, DATE *date)
1318 struct folder *This = impl_from_IFolder(iface);
1319 FIXME("(%p)->(%p): stub\n", This, date);
1320 return E_NOTIMPL;
1323 static HRESULT WINAPI folder_get_DateLastAccessed(IFolder *iface, DATE *date)
1325 struct folder *This = impl_from_IFolder(iface);
1326 FIXME("(%p)->(%p): stub\n", This, date);
1327 return E_NOTIMPL;
1330 static HRESULT WINAPI folder_get_Type(IFolder *iface, BSTR *type)
1332 struct folder *This = impl_from_IFolder(iface);
1333 FIXME("(%p)->(%p): stub\n", This, type);
1334 return E_NOTIMPL;
1337 static HRESULT WINAPI folder_Delete(IFolder *iface, VARIANT_BOOL force)
1339 struct folder *This = impl_from_IFolder(iface);
1340 FIXME("(%p)->(%x): stub\n", This, force);
1341 return E_NOTIMPL;
1344 static HRESULT WINAPI folder_Copy(IFolder *iface, BSTR dest, VARIANT_BOOL overwrite)
1346 struct folder *This = impl_from_IFolder(iface);
1347 FIXME("(%p)->(%s %x): stub\n", This, debugstr_w(dest), overwrite);
1348 return E_NOTIMPL;
1351 static HRESULT WINAPI folder_Move(IFolder *iface, BSTR dest)
1353 struct folder *This = impl_from_IFolder(iface);
1354 FIXME("(%p)->(%s): stub\n", This, debugstr_w(dest));
1355 return E_NOTIMPL;
1358 static HRESULT WINAPI folder_get_IsRootFolder(IFolder *iface, VARIANT_BOOL *isroot)
1360 struct folder *This = impl_from_IFolder(iface);
1361 FIXME("(%p)->(%p): stub\n", This, isroot);
1362 return E_NOTIMPL;
1365 static HRESULT WINAPI folder_get_Size(IFolder *iface, VARIANT *size)
1367 struct folder *This = impl_from_IFolder(iface);
1368 FIXME("(%p)->(%p): stub\n", This, size);
1369 return E_NOTIMPL;
1372 static HRESULT WINAPI folder_get_SubFolders(IFolder *iface, IFolderCollection **folders)
1374 struct folder *This = impl_from_IFolder(iface);
1376 TRACE("(%p)->(%p)\n", This, folders);
1378 if(!folders)
1379 return E_POINTER;
1381 return create_foldercoll(This->path, folders);
1384 static HRESULT WINAPI folder_get_Files(IFolder *iface, IFileCollection **files)
1386 struct folder *This = impl_from_IFolder(iface);
1388 TRACE("(%p)->(%p)\n", This, files);
1390 if(!files)
1391 return E_POINTER;
1393 return create_filecoll(This->path, files);
1396 static HRESULT WINAPI folder_CreateTextFile(IFolder *iface, BSTR filename, VARIANT_BOOL overwrite,
1397 VARIANT_BOOL unicode, ITextStream **stream)
1399 struct folder *This = impl_from_IFolder(iface);
1400 FIXME("(%p)->(%s %x %x %p): stub\n", This, debugstr_w(filename), overwrite, unicode, stream);
1401 return E_NOTIMPL;
1404 static const IFolderVtbl foldervtbl = {
1405 folder_QueryInterface,
1406 folder_AddRef,
1407 folder_Release,
1408 folder_GetTypeInfoCount,
1409 folder_GetTypeInfo,
1410 folder_GetIDsOfNames,
1411 folder_Invoke,
1412 folder_get_Path,
1413 folder_get_Name,
1414 folder_put_Name,
1415 folder_get_ShortPath,
1416 folder_get_ShortName,
1417 folder_get_Drive,
1418 folder_get_ParentFolder,
1419 folder_get_Attributes,
1420 folder_put_Attributes,
1421 folder_get_DateCreated,
1422 folder_get_DateLastModified,
1423 folder_get_DateLastAccessed,
1424 folder_get_Type,
1425 folder_Delete,
1426 folder_Copy,
1427 folder_Move,
1428 folder_get_IsRootFolder,
1429 folder_get_Size,
1430 folder_get_SubFolders,
1431 folder_get_Files,
1432 folder_CreateTextFile
1435 HRESULT create_folder(const WCHAR *path, IFolder **folder)
1437 struct folder *This;
1439 *folder = NULL;
1441 TRACE("%s\n", debugstr_w(path));
1443 This = heap_alloc(sizeof(struct folder));
1444 if (!This) return E_OUTOFMEMORY;
1446 This->IFolder_iface.lpVtbl = &foldervtbl;
1447 This->ref = 1;
1448 This->path = SysAllocString(path);
1449 if (!This->path)
1451 heap_free(This);
1452 return E_OUTOFMEMORY;
1455 *folder = &This->IFolder_iface;
1457 return S_OK;
1460 static HRESULT WINAPI file_QueryInterface(IFile *iface, REFIID riid, void **obj)
1462 struct file *This = impl_from_IFile(iface);
1464 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1466 if (IsEqualIID(riid, &IID_IFile) ||
1467 IsEqualIID(riid, &IID_IDispatch) ||
1468 IsEqualIID(riid, &IID_IUnknown))
1470 *obj = iface;
1471 IFile_AddRef(iface);
1472 return S_OK;
1475 *obj = NULL;
1476 return E_NOINTERFACE;
1479 static ULONG WINAPI file_AddRef(IFile *iface)
1481 struct file *This = impl_from_IFile(iface);
1482 LONG ref = InterlockedIncrement(&This->ref);
1484 TRACE("(%p) ref=%d\n", This, ref);
1486 return ref;
1489 static ULONG WINAPI file_Release(IFile *iface)
1491 struct file *This = impl_from_IFile(iface);
1492 LONG ref = InterlockedDecrement(&This->ref);
1494 TRACE("(%p) ref=%d\n", This, ref);
1496 if(!ref)
1497 heap_free(This->path);
1499 return ref;
1502 static HRESULT WINAPI file_GetTypeInfoCount(IFile *iface, UINT *pctinfo)
1504 struct file *This = impl_from_IFile(iface);
1506 TRACE("(%p)->(%p)\n", This, pctinfo);
1508 *pctinfo = 1;
1509 return S_OK;
1512 static HRESULT WINAPI file_GetTypeInfo(IFile *iface,
1513 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1515 struct file *This = impl_from_IFile(iface);
1517 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1519 return get_typeinfo(IFile_tid, ppTInfo);
1522 static HRESULT WINAPI file_GetIDsOfNames(IFile *iface, REFIID riid,
1523 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1525 struct file *This = impl_from_IFile(iface);
1526 ITypeInfo *typeinfo;
1527 HRESULT hr;
1529 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
1530 rgszNames, cNames, lcid, rgDispId);
1532 hr = get_typeinfo(IFile_tid, &typeinfo);
1533 if(SUCCEEDED(hr)) {
1534 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1535 ITypeInfo_Release(typeinfo);
1537 return hr;
1540 static HRESULT WINAPI file_Invoke(IFile *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1542 struct file *This = impl_from_IFile(iface);
1543 ITypeInfo *typeinfo;
1544 HRESULT hr;
1546 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1547 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1549 hr = get_typeinfo(IFile_tid, &typeinfo);
1550 if(SUCCEEDED(hr))
1552 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1553 pDispParams, pVarResult, pExcepInfo, puArgErr);
1554 ITypeInfo_Release(typeinfo);
1556 return hr;
1559 static HRESULT WINAPI file_get_Path(IFile *iface, BSTR *pbstrPath)
1561 struct file *This = impl_from_IFile(iface);
1562 FIXME("(%p)->(%p)\n", This, pbstrPath);
1563 return E_NOTIMPL;
1566 static HRESULT WINAPI file_get_Name(IFile *iface, BSTR *name)
1568 struct file *This = impl_from_IFile(iface);
1569 WCHAR *ptr;
1571 TRACE("(%p)->(%p)\n", This, name);
1573 if(!name)
1574 return E_POINTER;
1576 *name = NULL;
1578 ptr = strrchrW(This->path, '\\');
1579 if (ptr)
1581 *name = SysAllocString(ptr+1);
1582 TRACE("%s\n", debugstr_w(*name));
1583 if (!*name) return E_OUTOFMEMORY;
1585 else
1586 return E_FAIL;
1588 return S_OK;
1591 static HRESULT WINAPI file_put_Name(IFile *iface, BSTR pbstrName)
1593 struct file *This = impl_from_IFile(iface);
1594 FIXME("(%p)->(%s)\n", This, debugstr_w(pbstrName));
1595 return E_NOTIMPL;
1598 static HRESULT WINAPI file_get_ShortPath(IFile *iface, BSTR *pbstrPath)
1600 struct file *This = impl_from_IFile(iface);
1601 FIXME("(%p)->(%p)\n", This, pbstrPath);
1602 return E_NOTIMPL;
1605 static HRESULT WINAPI file_get_ShortName(IFile *iface, BSTR *pbstrName)
1607 struct file *This = impl_from_IFile(iface);
1608 FIXME("(%p)->(%p)\n", This, pbstrName);
1609 return E_NOTIMPL;
1612 static HRESULT WINAPI file_get_Drive(IFile *iface, IDrive **ppdrive)
1614 struct file *This = impl_from_IFile(iface);
1615 FIXME("(%p)->(%p)\n", This, ppdrive);
1616 return E_NOTIMPL;
1619 static HRESULT WINAPI file_get_ParentFolder(IFile *iface, IFolder **ppfolder)
1621 struct file *This = impl_from_IFile(iface);
1622 FIXME("(%p)->(%p)\n", This, ppfolder);
1623 return E_NOTIMPL;
1626 static HRESULT WINAPI file_get_Attributes(IFile *iface, FileAttribute *pfa)
1628 struct file *This = impl_from_IFile(iface);
1629 DWORD fa;
1631 TRACE("(%p)->(%p)\n", This, pfa);
1633 if(!pfa)
1634 return E_POINTER;
1636 fa = GetFileAttributesW(This->path);
1637 if(fa == INVALID_FILE_ATTRIBUTES)
1638 return create_error(GetLastError());
1640 *pfa = fa & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
1641 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE |
1642 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED);
1643 return S_OK;
1646 static HRESULT WINAPI file_put_Attributes(IFile *iface, FileAttribute pfa)
1648 struct file *This = impl_from_IFile(iface);
1649 FIXME("(%p)->(%x)\n", This, pfa);
1650 return E_NOTIMPL;
1653 static HRESULT WINAPI file_get_DateCreated(IFile *iface, DATE *pdate)
1655 struct file *This = impl_from_IFile(iface);
1656 FIXME("(%p)->(%p)\n", This, pdate);
1657 return E_NOTIMPL;
1660 static HRESULT WINAPI file_get_DateLastModified(IFile *iface, DATE *pdate)
1662 struct file *This = impl_from_IFile(iface);
1663 FIXME("(%p)->(%p)\n", This, pdate);
1664 return E_NOTIMPL;
1667 static HRESULT WINAPI file_get_DateLastAccessed(IFile *iface, DATE *pdate)
1669 struct file *This = impl_from_IFile(iface);
1670 FIXME("(%p)->(%p)\n", This, pdate);
1671 return E_NOTIMPL;
1674 static HRESULT WINAPI file_get_Size(IFile *iface, VARIANT *pvarSize)
1676 struct file *This = impl_from_IFile(iface);
1677 WIN32_FIND_DATAW fd;
1678 HANDLE f;
1680 TRACE("(%p)->(%p)\n", This, pvarSize);
1682 if(!pvarSize)
1683 return E_POINTER;
1685 f = FindFirstFileW(This->path, &fd);
1686 if(f == INVALID_HANDLE_VALUE)
1687 return create_error(GetLastError());
1688 FindClose(f);
1690 if(fd.nFileSizeHigh || fd.nFileSizeLow>INT_MAX) {
1691 V_VT(pvarSize) = VT_R8;
1692 V_R8(pvarSize) = ((ULONGLONG)fd.nFileSizeHigh<<32) + fd.nFileSizeLow;
1693 }else {
1694 V_VT(pvarSize) = VT_I4;
1695 V_I4(pvarSize) = fd.nFileSizeLow;
1697 return S_OK;
1700 static HRESULT WINAPI file_get_Type(IFile *iface, BSTR *pbstrType)
1702 struct file *This = impl_from_IFile(iface);
1703 FIXME("(%p)->(%p)\n", This, pbstrType);
1704 return E_NOTIMPL;
1707 static HRESULT WINAPI file_Delete(IFile *iface, VARIANT_BOOL Force)
1709 struct file *This = impl_from_IFile(iface);
1710 FIXME("(%p)->(%x)\n", This, Force);
1711 return E_NOTIMPL;
1714 static HRESULT WINAPI file_Copy(IFile *iface, BSTR Destination, VARIANT_BOOL OverWriteFiles)
1716 struct file *This = impl_from_IFile(iface);
1717 FIXME("(%p)->(%s %x)\n", This, debugstr_w(Destination), OverWriteFiles);
1718 return E_NOTIMPL;
1721 static HRESULT WINAPI file_Move(IFile *iface, BSTR Destination)
1723 struct file *This = impl_from_IFile(iface);
1724 FIXME("(%p)->(%s)\n", This, debugstr_w(Destination));
1725 return E_NOTIMPL;
1728 static HRESULT WINAPI file_OpenAsTextStream(IFile *iface, IOMode IOMode, Tristate Format, ITextStream **ppts)
1730 struct file *This = impl_from_IFile(iface);
1731 FIXME("(%p)->(%x %x %p)\n", This, IOMode, Format, ppts);
1732 return E_NOTIMPL;
1735 static const IFileVtbl file_vtbl = {
1736 file_QueryInterface,
1737 file_AddRef,
1738 file_Release,
1739 file_GetTypeInfoCount,
1740 file_GetTypeInfo,
1741 file_GetIDsOfNames,
1742 file_Invoke,
1743 file_get_Path,
1744 file_get_Name,
1745 file_put_Name,
1746 file_get_ShortPath,
1747 file_get_ShortName,
1748 file_get_Drive,
1749 file_get_ParentFolder,
1750 file_get_Attributes,
1751 file_put_Attributes,
1752 file_get_DateCreated,
1753 file_get_DateLastModified,
1754 file_get_DateLastAccessed,
1755 file_get_Size,
1756 file_get_Type,
1757 file_Delete,
1758 file_Copy,
1759 file_Move,
1760 file_OpenAsTextStream
1763 static HRESULT create_file(BSTR path, IFile **file)
1765 struct file *f;
1766 DWORD len, attrs;
1768 *file = NULL;
1770 f = heap_alloc(sizeof(struct file));
1771 if(!f)
1772 return E_OUTOFMEMORY;
1774 f->IFile_iface.lpVtbl = &file_vtbl;
1775 f->ref = 1;
1777 len = GetFullPathNameW(path, 0, NULL, NULL);
1778 if(!len) {
1779 heap_free(f);
1780 return E_FAIL;
1783 f->path = heap_alloc(len*sizeof(WCHAR));
1784 if(!f->path) {
1785 heap_free(f);
1786 return E_OUTOFMEMORY;
1789 if(!GetFullPathNameW(path, len, f->path, NULL)) {
1790 heap_free(f->path);
1791 heap_free(f);
1792 return E_FAIL;
1795 if(path[len-1]=='/' || path[len-1]=='\\')
1796 path[len-1] = 0;
1798 attrs = GetFileAttributesW(f->path);
1799 if(attrs==INVALID_FILE_ATTRIBUTES ||
1800 (attrs&(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))) {
1801 heap_free(f->path);
1802 heap_free(f);
1803 return create_error(GetLastError());
1806 *file = &f->IFile_iface;
1807 return S_OK;
1810 static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, void **ppvObject)
1812 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
1814 if ( IsEqualGUID( riid, &IID_IFileSystem3 ) ||
1815 IsEqualGUID( riid, &IID_IFileSystem ) ||
1816 IsEqualGUID( riid, &IID_IDispatch ) ||
1817 IsEqualGUID( riid, &IID_IUnknown ) )
1819 *ppvObject = iface;
1821 else if ( IsEqualGUID( riid, &IID_IDispatchEx ))
1823 TRACE("Interface IDispatchEx not supported - returning NULL\n");
1824 *ppvObject = NULL;
1825 return E_NOINTERFACE;
1827 else if ( IsEqualGUID( riid, &IID_IObjectWithSite ))
1829 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
1830 *ppvObject = NULL;
1831 return E_NOINTERFACE;
1833 else
1835 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
1836 return E_NOINTERFACE;
1839 IFileSystem3_AddRef(iface);
1841 return S_OK;
1844 static ULONG WINAPI filesys_AddRef(IFileSystem3 *iface)
1846 TRACE("%p\n", iface);
1848 return 2;
1851 static ULONG WINAPI filesys_Release(IFileSystem3 *iface)
1853 TRACE("%p\n", iface);
1855 return 1;
1858 static HRESULT WINAPI filesys_GetTypeInfoCount(IFileSystem3 *iface, UINT *pctinfo)
1860 TRACE("(%p)->(%p)\n", iface, pctinfo);
1862 *pctinfo = 1;
1863 return S_OK;
1866 static HRESULT WINAPI filesys_GetTypeInfo(IFileSystem3 *iface, UINT iTInfo,
1867 LCID lcid, ITypeInfo **ppTInfo)
1869 TRACE("(%p)->(%u %u %p)\n", iface, iTInfo, lcid, ppTInfo);
1870 return get_typeinfo(IFileSystem3_tid, ppTInfo);
1873 static HRESULT WINAPI filesys_GetIDsOfNames(IFileSystem3 *iface, REFIID riid,
1874 LPOLESTR *rgszNames, UINT cNames,
1875 LCID lcid, DISPID *rgDispId)
1877 ITypeInfo *typeinfo;
1878 HRESULT hr;
1880 TRACE("(%p)->(%s %p %u %u %p)\n", iface, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1882 hr = get_typeinfo(IFileSystem3_tid, &typeinfo);
1883 if(SUCCEEDED(hr))
1885 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1886 ITypeInfo_Release(typeinfo);
1889 return hr;
1892 static HRESULT WINAPI filesys_Invoke(IFileSystem3 *iface, DISPID dispIdMember,
1893 REFIID riid, LCID lcid, WORD wFlags,
1894 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1895 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1897 ITypeInfo *typeinfo;
1898 HRESULT hr;
1900 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface, dispIdMember, debugstr_guid(riid),
1901 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1903 hr = get_typeinfo(IFileSystem3_tid, &typeinfo);
1904 if(SUCCEEDED(hr))
1906 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1907 pDispParams, pVarResult, pExcepInfo, puArgErr);
1908 ITypeInfo_Release(typeinfo);
1911 return hr;
1914 static HRESULT WINAPI filesys_get_Drives(IFileSystem3 *iface, IDriveCollection **ppdrives)
1916 FIXME("%p %p\n", iface, ppdrives);
1918 return E_NOTIMPL;
1921 static HRESULT WINAPI filesys_BuildPath(IFileSystem3 *iface, BSTR Path,
1922 BSTR Name, BSTR *Result)
1924 BSTR ret;
1926 TRACE("%p %s %s %p\n", iface, debugstr_w(Path), debugstr_w(Name), Result);
1928 if (!Result) return E_POINTER;
1930 if (Path && Name)
1932 int path_len = SysStringLen(Path), name_len = SysStringLen(Name);
1934 /* if both parts have backslashes strip one from Path */
1935 if (Path[path_len-1] == '\\' && Name[0] == '\\')
1937 path_len -= 1;
1939 ret = SysAllocStringLen(NULL, path_len + name_len);
1940 if (ret)
1942 strcpyW(ret, Path);
1943 ret[path_len] = 0;
1944 strcatW(ret, Name);
1947 else if (Path[path_len-1] != '\\' && Name[0] != '\\')
1949 ret = SysAllocStringLen(NULL, path_len + name_len + 1);
1950 if (ret)
1952 strcpyW(ret, Path);
1953 if (Path[path_len-1] != ':')
1954 strcatW(ret, bsW);
1955 strcatW(ret, Name);
1958 else
1960 ret = SysAllocStringLen(NULL, path_len + name_len);
1961 if (ret)
1963 strcpyW(ret, Path);
1964 strcatW(ret, Name);
1968 else if (Path || Name)
1969 ret = SysAllocString(Path ? Path : Name);
1970 else
1971 ret = SysAllocStringLen(NULL, 0);
1973 if (!ret) return E_OUTOFMEMORY;
1974 *Result = ret;
1976 return S_OK;
1979 static HRESULT WINAPI filesys_GetDriveName(IFileSystem3 *iface, BSTR Path,
1980 BSTR *pbstrResult)
1982 FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
1984 return E_NOTIMPL;
1987 static inline DWORD get_parent_folder_name(const WCHAR *path, DWORD len)
1989 int i;
1991 if(!path)
1992 return 0;
1994 for(i=len-1; i>=0; i--)
1995 if(path[i]!='/' && path[i]!='\\')
1996 break;
1998 for(; i>=0; i--)
1999 if(path[i]=='/' || path[i]=='\\')
2000 break;
2002 for(; i>=0; i--)
2003 if(path[i]!='/' && path[i]!='\\')
2004 break;
2006 if(i < 0)
2007 return 0;
2009 if(path[i]==':' && i==1)
2010 i++;
2011 return i+1;
2014 static HRESULT WINAPI filesys_GetParentFolderName(IFileSystem3 *iface, BSTR Path,
2015 BSTR *pbstrResult)
2017 DWORD len;
2019 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2021 if(!pbstrResult)
2022 return E_POINTER;
2024 len = get_parent_folder_name(Path, SysStringLen(Path));
2025 if(!len) {
2026 *pbstrResult = NULL;
2027 return S_OK;
2030 *pbstrResult = SysAllocStringLen(Path, len);
2031 if(!*pbstrResult)
2032 return E_OUTOFMEMORY;
2033 return S_OK;
2036 static HRESULT WINAPI filesys_GetFileName(IFileSystem3 *iface, BSTR Path,
2037 BSTR *pbstrResult)
2039 int i, end;
2041 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2043 if(!pbstrResult)
2044 return E_POINTER;
2046 if(!Path) {
2047 *pbstrResult = NULL;
2048 return S_OK;
2051 for(end=strlenW(Path)-1; end>=0; end--)
2052 if(Path[end]!='/' && Path[end]!='\\')
2053 break;
2055 for(i=end; i>=0; i--)
2056 if(Path[i]=='/' || Path[i]=='\\')
2057 break;
2058 i++;
2060 if(i>end || (i==0 && end==1 && Path[1]==':')) {
2061 *pbstrResult = NULL;
2062 return S_OK;
2065 *pbstrResult = SysAllocStringLen(Path+i, end-i+1);
2066 if(!*pbstrResult)
2067 return E_OUTOFMEMORY;
2068 return S_OK;
2071 static HRESULT WINAPI filesys_GetBaseName(IFileSystem3 *iface, BSTR Path,
2072 BSTR *pbstrResult)
2074 int i, end;
2076 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2078 if(!pbstrResult)
2079 return E_POINTER;
2081 if(!Path) {
2082 *pbstrResult = NULL;
2083 return S_OK;
2086 for(end=strlenW(Path)-1; end>=0; end--)
2087 if(Path[end]!='/' && Path[end]!='\\')
2088 break;
2090 for(i=end; i>=0; i--) {
2091 if(Path[i]=='.' && Path[end+1]!='.')
2092 end = i-1;
2093 if(Path[i]=='/' || Path[i]=='\\')
2094 break;
2096 i++;
2098 if((i>end && Path[end+1]!='.') || (i==0 && end==1 && Path[1]==':')) {
2099 *pbstrResult = NULL;
2100 return S_OK;
2103 *pbstrResult = SysAllocStringLen(Path+i, end-i+1);
2104 if(!*pbstrResult)
2105 return E_OUTOFMEMORY;
2106 return S_OK;
2109 static HRESULT WINAPI filesys_GetExtensionName(IFileSystem3 *iface, BSTR Path,
2110 BSTR *pbstrResult)
2112 FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2114 return E_NOTIMPL;
2117 static HRESULT WINAPI filesys_GetAbsolutePathName(IFileSystem3 *iface, BSTR Path,
2118 BSTR *pbstrResult)
2120 static const WCHAR cur_path[] = {'.',0};
2122 WCHAR buf[MAX_PATH], ch;
2123 const WCHAR *path;
2124 DWORD i, beg, len, exp_len;
2125 WIN32_FIND_DATAW fdata;
2126 HANDLE fh;
2128 TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
2130 if(!pbstrResult)
2131 return E_POINTER;
2133 if(!Path)
2134 path = cur_path;
2135 else
2136 path = Path;
2138 len = GetFullPathNameW(path, MAX_PATH, buf, NULL);
2139 if(!len)
2140 return E_FAIL;
2142 buf[0] = toupperW(buf[0]);
2143 if(len>3 && buf[len-1] == '\\')
2144 buf[--len] = 0;
2146 for(beg=3, i=3; i<=len; i++) {
2147 if(buf[i]!='\\' && buf[i])
2148 continue;
2150 ch = buf[i];
2151 buf[i] = 0;
2152 fh = FindFirstFileW(buf, &fdata);
2153 if(fh == INVALID_HANDLE_VALUE)
2154 break;
2156 exp_len = strlenW(fdata.cFileName);
2157 if(exp_len == i-beg)
2158 memcpy(buf+beg, fdata.cFileName, exp_len*sizeof(WCHAR));
2159 FindClose(fh);
2160 buf[i] = ch;
2161 beg = i+1;
2164 *pbstrResult = SysAllocString(buf);
2165 if(!*pbstrResult)
2166 return E_OUTOFMEMORY;
2167 return S_OK;
2170 static HRESULT WINAPI filesys_GetTempName(IFileSystem3 *iface, BSTR *pbstrResult)
2172 static const WCHAR fmt[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
2174 DWORD random;
2176 TRACE("%p %p\n", iface, pbstrResult);
2178 if(!pbstrResult)
2179 return E_POINTER;
2181 *pbstrResult = SysAllocStringLen(NULL, 12);
2182 if(!*pbstrResult)
2183 return E_OUTOFMEMORY;
2185 if(!RtlGenRandom(&random, sizeof(random)))
2186 return E_FAIL;
2187 sprintfW(*pbstrResult, fmt, random & 0xfffff);
2188 return S_OK;
2191 static HRESULT WINAPI filesys_DriveExists(IFileSystem3 *iface, BSTR DriveSpec,
2192 VARIANT_BOOL *pfExists)
2194 FIXME("%p %s %p\n", iface, debugstr_w(DriveSpec), pfExists);
2196 return E_NOTIMPL;
2199 static HRESULT WINAPI filesys_FileExists(IFileSystem3 *iface, BSTR path, VARIANT_BOOL *ret)
2201 DWORD attrs;
2202 TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
2204 if (!ret) return E_POINTER;
2206 attrs = GetFileAttributesW(path);
2207 *ret = attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
2208 return S_OK;
2211 static HRESULT WINAPI filesys_FolderExists(IFileSystem3 *iface, BSTR path, VARIANT_BOOL *ret)
2213 DWORD attrs;
2214 TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
2216 if (!ret) return E_POINTER;
2218 attrs = GetFileAttributesW(path);
2219 *ret = attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
2221 return S_OK;
2224 static HRESULT WINAPI filesys_GetDrive(IFileSystem3 *iface, BSTR DriveSpec,
2225 IDrive **ppdrive)
2227 FIXME("%p %s %p\n", iface, debugstr_w(DriveSpec), ppdrive);
2229 return E_NOTIMPL;
2232 static HRESULT WINAPI filesys_GetFile(IFileSystem3 *iface, BSTR FilePath,
2233 IFile **ppfile)
2235 TRACE("%p %s %p\n", iface, debugstr_w(FilePath), ppfile);
2237 if(!ppfile)
2238 return E_POINTER;
2239 if(!FilePath)
2240 return E_INVALIDARG;
2242 return create_file(FilePath, ppfile);
2245 static HRESULT WINAPI filesys_GetFolder(IFileSystem3 *iface, BSTR FolderPath,
2246 IFolder **folder)
2248 DWORD attrs;
2250 TRACE("%p %s %p\n", iface, debugstr_w(FolderPath), folder);
2252 if(!folder)
2253 return E_POINTER;
2255 *folder = NULL;
2256 if(!FolderPath)
2257 return E_INVALIDARG;
2259 attrs = GetFileAttributesW(FolderPath);
2260 if((attrs == INVALID_FILE_ATTRIBUTES) || !(attrs & FILE_ATTRIBUTE_DIRECTORY))
2261 return CTL_E_PATHNOTFOUND;
2263 return create_folder(FolderPath, folder);
2266 static HRESULT WINAPI filesys_GetSpecialFolder(IFileSystem3 *iface,
2267 SpecialFolderConst SpecialFolder,
2268 IFolder **ppfolder)
2270 FIXME("%p %d %p\n", iface, SpecialFolder, ppfolder);
2272 return E_NOTIMPL;
2275 static inline HRESULT delete_file(const WCHAR *file, DWORD file_len, VARIANT_BOOL force)
2277 WCHAR path[MAX_PATH];
2278 DWORD len, name_len;
2279 WIN32_FIND_DATAW ffd;
2280 HANDLE f;
2282 f = FindFirstFileW(file, &ffd);
2283 if(f == INVALID_HANDLE_VALUE)
2284 return create_error(GetLastError());
2286 len = get_parent_folder_name(file, file_len);
2287 if(len+1 >= MAX_PATH) {
2288 FindClose(f);
2289 return E_FAIL;
2291 if(len) {
2292 memcpy(path, file, len*sizeof(WCHAR));
2293 path[len++] = '\\';
2296 do {
2297 if(ffd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
2298 continue;
2300 name_len = strlenW(ffd.cFileName);
2301 if(len+name_len+1 >= MAX_PATH) {
2302 FindClose(f);
2303 return E_FAIL;
2305 memcpy(path+len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
2307 TRACE("deleting %s\n", debugstr_w(path));
2309 if(!DeleteFileW(path)) {
2310 if(!force || !SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL)
2311 || !DeleteFileW(path)) {
2312 FindClose(f);
2313 return create_error(GetLastError());
2316 } while(FindNextFileW(f, &ffd));
2317 FindClose(f);
2319 return S_OK;
2322 static HRESULT WINAPI filesys_DeleteFile(IFileSystem3 *iface, BSTR FileSpec,
2323 VARIANT_BOOL Force)
2325 TRACE("%p %s %d\n", iface, debugstr_w(FileSpec), Force);
2327 if(!FileSpec)
2328 return E_POINTER;
2330 return delete_file(FileSpec, SysStringLen(FileSpec), Force);
2333 static HRESULT delete_folder(const WCHAR *folder, DWORD folder_len, VARIANT_BOOL force)
2335 WCHAR path[MAX_PATH];
2336 DWORD len, name_len;
2337 WIN32_FIND_DATAW ffd;
2338 HANDLE f;
2339 HRESULT hr;
2341 f = FindFirstFileW(folder, &ffd);
2342 if(f == INVALID_HANDLE_VALUE)
2343 return create_error(GetLastError());
2345 len = get_parent_folder_name(folder, folder_len);
2346 if(len+1 >= MAX_PATH) {
2347 FindClose(f);
2348 return E_FAIL;
2350 if(len) {
2351 memcpy(path, folder, len*sizeof(WCHAR));
2352 path[len++] = '\\';
2355 do {
2356 if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
2357 continue;
2358 if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 ||
2359 (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0)))
2360 continue;
2362 name_len = strlenW(ffd.cFileName);
2363 if(len+name_len+3 >= MAX_PATH) {
2364 FindClose(f);
2365 return E_FAIL;
2367 memcpy(path+len, ffd.cFileName, name_len*sizeof(WCHAR));
2368 path[len+name_len] = '\\';
2369 path[len+name_len+1] = '*';
2370 path[len+name_len+2] = 0;
2372 hr = delete_file(path, len+name_len+2, force);
2373 if(FAILED(hr)) {
2374 FindClose(f);
2375 return hr;
2378 hr = delete_folder(path, len+name_len+2, force);
2379 if(FAILED(hr)) {
2380 FindClose(f);
2381 return hr;
2384 path[len+name_len] = 0;
2385 TRACE("deleting %s\n", debugstr_w(path));
2387 if(!RemoveDirectoryW(path)) {
2388 FindClose(f);
2389 return create_error(GetLastError());
2391 } while(FindNextFileW(f, &ffd));
2392 FindClose(f);
2394 return S_OK;
2397 static HRESULT WINAPI filesys_DeleteFolder(IFileSystem3 *iface, BSTR FolderSpec,
2398 VARIANT_BOOL Force)
2400 TRACE("%p %s %d\n", iface, debugstr_w(FolderSpec), Force);
2402 if(!FolderSpec)
2403 return E_POINTER;
2405 return delete_folder(FolderSpec, SysStringLen(FolderSpec), Force);
2408 static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR Source,
2409 BSTR Destination)
2411 FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
2413 return E_NOTIMPL;
2416 static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface,BSTR Source,
2417 BSTR Destination)
2419 FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
2421 return E_NOTIMPL;
2424 static inline HRESULT copy_file(const WCHAR *source, DWORD source_len,
2425 const WCHAR *destination, DWORD destination_len, VARIANT_BOOL overwrite)
2427 DWORD attrs;
2428 WCHAR src_path[MAX_PATH], dst_path[MAX_PATH];
2429 DWORD src_len, dst_len, name_len;
2430 WIN32_FIND_DATAW ffd;
2431 HANDLE f;
2432 HRESULT hr;
2434 if(!source[0] || !destination[0])
2435 return E_INVALIDARG;
2437 attrs = GetFileAttributesW(destination);
2438 if(attrs==INVALID_FILE_ATTRIBUTES || !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
2439 attrs = GetFileAttributesW(source);
2440 if(attrs == INVALID_FILE_ATTRIBUTES)
2441 return create_error(GetLastError());
2442 else if(attrs & FILE_ATTRIBUTE_DIRECTORY)
2443 return CTL_E_FILENOTFOUND;
2445 if(!CopyFileW(source, destination, !overwrite))
2446 return create_error(GetLastError());
2447 return S_OK;
2450 f = FindFirstFileW(source, &ffd);
2451 if(f == INVALID_HANDLE_VALUE)
2452 return CTL_E_FILENOTFOUND;
2454 src_len = get_parent_folder_name(source, source_len);
2455 if(src_len+1 >= MAX_PATH)
2456 return E_FAIL;
2457 if(src_len) {
2458 memcpy(src_path, source, src_len*sizeof(WCHAR));
2459 src_path[src_len++] = '\\';
2462 dst_len = destination_len;
2463 if(dst_len+1 >= MAX_PATH) {
2464 FindClose(f);
2465 return E_FAIL;
2467 memcpy(dst_path, destination, dst_len*sizeof(WCHAR));
2468 if(dst_path[dst_len-1]!= '\\' && dst_path[dst_len-1]!='/')
2469 dst_path[dst_len++] = '\\';
2471 hr = CTL_E_FILENOTFOUND;
2472 do {
2473 if(ffd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
2474 continue;
2476 name_len = strlenW(ffd.cFileName);
2477 if(src_len+name_len+1>=MAX_PATH || dst_len+name_len+1>=MAX_PATH) {
2478 FindClose(f);
2479 return E_FAIL;
2481 memcpy(src_path+src_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
2482 memcpy(dst_path+dst_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
2484 TRACE("copying %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path));
2486 if(!CopyFileW(src_path, dst_path, !overwrite)) {
2487 FindClose(f);
2488 return create_error(GetLastError());
2489 }else {
2490 hr = S_OK;
2492 } while(FindNextFileW(f, &ffd));
2493 FindClose(f);
2495 return hr;
2498 static HRESULT WINAPI filesys_CopyFile(IFileSystem3 *iface, BSTR Source,
2499 BSTR Destination, VARIANT_BOOL OverWriteFiles)
2501 TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
2503 if(!Source || !Destination)
2504 return E_POINTER;
2506 return copy_file(Source, SysStringLen(Source), Destination,
2507 SysStringLen(Destination), OverWriteFiles);
2510 static HRESULT copy_folder(const WCHAR *source, DWORD source_len, const WCHAR *destination,
2511 DWORD destination_len, VARIANT_BOOL overwrite)
2513 DWORD tmp, src_len, dst_len, name_len;
2514 WCHAR src[MAX_PATH], dst[MAX_PATH];
2515 WIN32_FIND_DATAW ffd;
2516 HANDLE f;
2517 HRESULT hr;
2518 BOOL copied = FALSE;
2520 if(!source[0] || !destination[0])
2521 return E_INVALIDARG;
2523 dst_len = destination_len;
2524 if(dst_len+1 >= MAX_PATH)
2525 return E_FAIL;
2526 memcpy(dst, destination, (dst_len+1)*sizeof(WCHAR));
2528 if(dst[dst_len-1]!='\\' && dst[dst_len-1]!='/' &&
2529 (tmp = GetFileAttributesW(source))!=INVALID_FILE_ATTRIBUTES &&
2530 tmp&FILE_ATTRIBUTE_DIRECTORY) {
2531 if(!CreateDirectoryW(dst, NULL)) {
2532 if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) {
2533 tmp = GetFileAttributesW(dst);
2534 if(tmp==INVALID_FILE_ATTRIBUTES || !(tmp&FILE_ATTRIBUTE_DIRECTORY))
2535 return CTL_E_FILEALREADYEXISTS;
2536 }else {
2537 return create_error(GetLastError());
2540 copied = TRUE;
2542 src_len = source_len;
2543 if(src_len+2 >= MAX_PATH)
2544 return E_FAIL;
2545 memcpy(src, source, src_len*sizeof(WCHAR));
2546 src[src_len++] = '\\';
2547 src[src_len] = '*';
2548 src[src_len+1] = 0;
2550 hr = copy_file(src, src_len+1, dst, dst_len, overwrite);
2551 if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND)
2552 return create_error(GetLastError());
2554 f = FindFirstFileW(src, &ffd);
2555 }else {
2556 src_len = get_parent_folder_name(source, source_len);
2557 if(src_len+2 >= MAX_PATH)
2558 return E_FAIL;
2559 memcpy(src, source, src_len*sizeof(WCHAR));
2560 if(src_len)
2561 src[src_len++] = '\\';
2563 f = FindFirstFileW(source, &ffd);
2565 if(f == INVALID_HANDLE_VALUE)
2566 return CTL_E_PATHNOTFOUND;
2568 dst[dst_len++] = '\\';
2569 dst[dst_len] = 0;
2571 do {
2572 if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
2573 continue;
2574 if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 ||
2575 (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0)))
2576 continue;
2578 name_len = strlenW(ffd.cFileName);
2579 if(dst_len+name_len>=MAX_PATH || src_len+name_len+2>=MAX_PATH) {
2580 FindClose(f);
2581 return E_FAIL;
2583 memcpy(dst+dst_len, ffd.cFileName, name_len*sizeof(WCHAR));
2584 dst[dst_len+name_len] = 0;
2585 memcpy(src+src_len, ffd.cFileName, name_len*sizeof(WCHAR));
2586 src[src_len+name_len] = '\\';
2587 src[src_len+name_len+1] = '*';
2588 src[src_len+name_len+2] = 0;
2590 TRACE("copying %s to %s\n", debugstr_w(src), debugstr_w(dst));
2592 if(!CreateDirectoryW(dst, NULL)) {
2593 if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) {
2594 tmp = GetFileAttributesW(dst);
2595 if(tmp==INVALID_FILE_ATTRIBUTES || !(tmp&FILE_ATTRIBUTE_DIRECTORY)) {
2596 FindClose(f);
2597 return CTL_E_FILEALREADYEXISTS;
2599 }else {
2600 FindClose(f);
2601 return create_error(GetLastError());
2603 return create_error(GetLastError());
2605 copied = TRUE;
2607 hr = copy_file(src, src_len+name_len+2, dst, dst_len+name_len, overwrite);
2608 if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND) {
2609 FindClose(f);
2610 return hr;
2613 hr = copy_folder(src, src_len+name_len+2, dst, dst_len+name_len, overwrite);
2614 if(FAILED(hr) && hr!=CTL_E_PATHNOTFOUND) {
2615 FindClose(f);
2616 return hr;
2618 } while(FindNextFileW(f, &ffd));
2619 FindClose(f);
2621 return copied ? S_OK : CTL_E_PATHNOTFOUND;
2624 static HRESULT WINAPI filesys_CopyFolder(IFileSystem3 *iface, BSTR Source,
2625 BSTR Destination, VARIANT_BOOL OverWriteFiles)
2627 TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
2629 if(!Source || !Destination)
2630 return E_POINTER;
2632 return copy_folder(Source, SysStringLen(Source), Destination,
2633 SysStringLen(Destination), OverWriteFiles);
2636 static HRESULT WINAPI filesys_CreateFolder(IFileSystem3 *iface, BSTR path,
2637 IFolder **folder)
2639 BOOL ret;
2641 TRACE("(%p)->(%s %p)\n", iface, debugstr_w(path), folder);
2643 ret = CreateDirectoryW(path, NULL);
2644 if (!ret)
2646 *folder = NULL;
2647 if (GetLastError() == ERROR_ALREADY_EXISTS) return CTL_E_FILEALREADYEXISTS;
2648 return HRESULT_FROM_WIN32(GetLastError());
2651 return create_folder(path, folder);
2654 static HRESULT WINAPI filesys_CreateTextFile(IFileSystem3 *iface, BSTR FileName,
2655 VARIANT_BOOL Overwrite, VARIANT_BOOL Unicode,
2656 ITextStream **ppts)
2658 FIXME("%p %s %d %d %p\n", iface, debugstr_w(FileName), Overwrite, Unicode, ppts);
2660 return E_NOTIMPL;
2663 static HRESULT WINAPI filesys_OpenTextFile(IFileSystem3 *iface, BSTR filename,
2664 IOMode mode, VARIANT_BOOL create,
2665 Tristate format, ITextStream **stream)
2667 FIXME("(%p)->(%s %d %d %d %p)\n", iface, debugstr_w(filename), mode, create, format, stream);
2668 return create_textstream(mode, stream);
2671 static HRESULT WINAPI filesys_GetStandardStream(IFileSystem3 *iface,
2672 StandardStreamTypes StandardStreamType,
2673 VARIANT_BOOL Unicode,
2674 ITextStream **ppts)
2676 FIXME("%p %d %d %p\n", iface, StandardStreamType, Unicode, ppts);
2678 return E_NOTIMPL;
2681 static void get_versionstring(VS_FIXEDFILEINFO *info, WCHAR *ver)
2683 static const WCHAR fmtW[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
2684 DWORDLONG version;
2685 WORD a, b, c, d;
2687 version = (((DWORDLONG)info->dwFileVersionMS) << 32) + info->dwFileVersionLS;
2688 a = (WORD)( version >> 48);
2689 b = (WORD)((version >> 32) & 0xffff);
2690 c = (WORD)((version >> 16) & 0xffff);
2691 d = (WORD)( version & 0xffff);
2693 sprintfW(ver, fmtW, a, b, c, d);
2696 static HRESULT WINAPI filesys_GetFileVersion(IFileSystem3 *iface, BSTR name, BSTR *version)
2698 static const WCHAR rootW[] = {'\\',0};
2699 VS_FIXEDFILEINFO *info;
2700 WCHAR ver[30];
2701 void *ptr;
2702 DWORD len;
2703 BOOL ret;
2705 TRACE("%p %s %p\n", iface, debugstr_w(name), version);
2707 len = GetFileVersionInfoSizeW(name, NULL);
2708 if (!len)
2709 return HRESULT_FROM_WIN32(GetLastError());
2711 ptr = heap_alloc(len);
2712 if (!GetFileVersionInfoW(name, 0, len, ptr))
2714 heap_free(ptr);
2715 return HRESULT_FROM_WIN32(GetLastError());
2718 ret = VerQueryValueW(ptr, rootW, (void**)&info, &len);
2719 heap_free(ptr);
2720 if (!ret)
2721 return HRESULT_FROM_WIN32(GetLastError());
2723 get_versionstring(info, ver);
2724 *version = SysAllocString(ver);
2725 TRACE("version=%s\n", debugstr_w(ver));
2727 return S_OK;
2730 static const struct IFileSystem3Vtbl filesys_vtbl =
2732 filesys_QueryInterface,
2733 filesys_AddRef,
2734 filesys_Release,
2735 filesys_GetTypeInfoCount,
2736 filesys_GetTypeInfo,
2737 filesys_GetIDsOfNames,
2738 filesys_Invoke,
2739 filesys_get_Drives,
2740 filesys_BuildPath,
2741 filesys_GetDriveName,
2742 filesys_GetParentFolderName,
2743 filesys_GetFileName,
2744 filesys_GetBaseName,
2745 filesys_GetExtensionName,
2746 filesys_GetAbsolutePathName,
2747 filesys_GetTempName,
2748 filesys_DriveExists,
2749 filesys_FileExists,
2750 filesys_FolderExists,
2751 filesys_GetDrive,
2752 filesys_GetFile,
2753 filesys_GetFolder,
2754 filesys_GetSpecialFolder,
2755 filesys_DeleteFile,
2756 filesys_DeleteFolder,
2757 filesys_MoveFile,
2758 filesys_MoveFolder,
2759 filesys_CopyFile,
2760 filesys_CopyFolder,
2761 filesys_CreateFolder,
2762 filesys_CreateTextFile,
2763 filesys_OpenTextFile,
2764 filesys_GetStandardStream,
2765 filesys_GetFileVersion
2768 static IFileSystem3 filesystem = { &filesys_vtbl };
2770 HRESULT WINAPI FileSystem_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2772 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
2774 return IFileSystem3_QueryInterface(&filesystem, riid, ppv);