scrrun: Block stream reading calls if it's not in ForReading mode.
[wine] / dlls / scrrun / filesystem.c
1 /*
2  * Copyright 2012 Alistair Leslie-Hughes
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #define COBJMACROS
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ole2.h"
27 #include "olectl.h"
28 #include "dispex.h"
29 #include "scrrun.h"
30 #include "scrrun_private.h"
31
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(scrrun);
35
36 struct folder {
37     IFolder IFolder_iface;
38     LONG ref;
39 };
40
41 struct textstream {
42     ITextStream ITextStream_iface;
43     LONG ref;
44
45     IOMode mode;
46 };
47
48 enum iotype {
49     IORead,
50     IOWrite
51 };
52
53 static inline struct folder *impl_from_IFolder(IFolder *iface)
54 {
55     return CONTAINING_RECORD(iface, struct folder, IFolder_iface);
56 }
57
58 static inline struct textstream *impl_from_ITextStream(ITextStream *iface)
59 {
60     return CONTAINING_RECORD(iface, struct textstream, ITextStream_iface);
61 }
62
63 static int textstream_check_iomode(struct textstream *This, enum iotype type)
64 {
65     if (type == IORead)
66         return This->mode == ForWriting || This->mode == ForAppending;
67     else
68         return 1;
69 }
70
71 static HRESULT WINAPI textstream_QueryInterface(ITextStream *iface, REFIID riid, void **obj)
72 {
73     struct textstream *This = impl_from_ITextStream(iface);
74
75     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
76
77     if (IsEqualIID(riid, &IID_ITextStream) ||
78         IsEqualIID(riid, &IID_IDispatch) ||
79         IsEqualIID(riid, &IID_IUnknown))
80     {
81         *obj = iface;
82         ITextStream_AddRef(iface);
83         return S_OK;
84     }
85
86     *obj = NULL;
87     return E_NOINTERFACE;
88 }
89
90 static ULONG WINAPI textstream_AddRef(ITextStream *iface)
91 {
92     struct textstream *This = impl_from_ITextStream(iface);
93     ULONG ref = InterlockedIncrement(&This->ref);
94     TRACE("(%p)->(%d)\n", This, ref);
95     return ref;
96 }
97
98 static ULONG WINAPI textstream_Release(ITextStream *iface)
99 {
100     struct textstream *This = impl_from_ITextStream(iface);
101     ULONG ref = InterlockedDecrement(&This->ref);
102     TRACE("(%p)->(%d)\n", This, ref);
103
104     if (!ref)
105         heap_free(This);
106
107     return ref;
108 }
109
110 static HRESULT WINAPI textstream_GetTypeInfoCount(ITextStream *iface, UINT *pctinfo)
111 {
112     struct textstream *This = impl_from_ITextStream(iface);
113     TRACE("(%p)->(%p)\n", This, pctinfo);
114     *pctinfo = 1;
115     return S_OK;
116 }
117
118 static HRESULT WINAPI textstream_GetTypeInfo(ITextStream *iface, UINT iTInfo,
119                                         LCID lcid, ITypeInfo **ppTInfo)
120 {
121     struct textstream *This = impl_from_ITextStream(iface);
122     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
123     return get_typeinfo(ITextStream_tid, ppTInfo);
124 }
125
126 static HRESULT WINAPI textstream_GetIDsOfNames(ITextStream *iface, REFIID riid,
127                                         LPOLESTR *rgszNames, UINT cNames,
128                                         LCID lcid, DISPID *rgDispId)
129 {
130     struct textstream *This = impl_from_ITextStream(iface);
131     ITypeInfo *typeinfo;
132     HRESULT hr;
133
134     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
135
136     hr = get_typeinfo(ITextStream_tid, &typeinfo);
137     if(SUCCEEDED(hr))
138     {
139         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
140         ITypeInfo_Release(typeinfo);
141     }
142
143     return hr;
144 }
145
146 static HRESULT WINAPI textstream_Invoke(ITextStream *iface, DISPID dispIdMember,
147                                       REFIID riid, LCID lcid, WORD wFlags,
148                                       DISPPARAMS *pDispParams, VARIANT *pVarResult,
149                                       EXCEPINFO *pExcepInfo, UINT *puArgErr)
150 {
151     struct textstream *This = impl_from_ITextStream(iface);
152     ITypeInfo *typeinfo;
153     HRESULT hr;
154
155     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
156            lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
157
158     hr = get_typeinfo(ITextStream_tid, &typeinfo);
159     if(SUCCEEDED(hr))
160     {
161         hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
162                 pDispParams, pVarResult, pExcepInfo, puArgErr);
163         ITypeInfo_Release(typeinfo);
164     }
165
166     return hr;
167 }
168
169 static HRESULT WINAPI textstream_get_Line(ITextStream *iface, LONG *line)
170 {
171     struct textstream *This = impl_from_ITextStream(iface);
172     FIXME("(%p)->(%p): stub\n", This, line);
173     return E_NOTIMPL;
174 }
175
176 static HRESULT WINAPI textstream_get_Column(ITextStream *iface, LONG *column)
177 {
178     struct textstream *This = impl_from_ITextStream(iface);
179     FIXME("(%p)->(%p): stub\n", This, column);
180     return E_NOTIMPL;
181 }
182
183 static HRESULT WINAPI textstream_get_AtEndOfStream(ITextStream *iface, VARIANT_BOOL *eos)
184 {
185     struct textstream *This = impl_from_ITextStream(iface);
186     FIXME("(%p)->(%p): stub\n", This, eos);
187     return E_NOTIMPL;
188 }
189
190 static HRESULT WINAPI textstream_get_AtEndOfLine(ITextStream *iface, VARIANT_BOOL *eol)
191 {
192     struct textstream *This = impl_from_ITextStream(iface);
193     FIXME("(%p)->(%p): stub\n", This, eol);
194     return E_NOTIMPL;
195 }
196
197 static HRESULT WINAPI textstream_Read(ITextStream *iface, LONG len, BSTR *text)
198 {
199     struct textstream *This = impl_from_ITextStream(iface);
200     FIXME("(%p)->(%p): stub\n", This, text);
201
202     if (textstream_check_iomode(This, IORead))
203         return CTL_E_BADFILEMODE;
204
205     return E_NOTIMPL;
206 }
207
208 static HRESULT WINAPI textstream_ReadLine(ITextStream *iface, BSTR *text)
209 {
210     struct textstream *This = impl_from_ITextStream(iface);
211     FIXME("(%p)->(%p): stub\n", This, text);
212
213     if (textstream_check_iomode(This, IORead))
214         return CTL_E_BADFILEMODE;
215
216     return E_NOTIMPL;
217 }
218
219 static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
220 {
221     struct textstream *This = impl_from_ITextStream(iface);
222     FIXME("(%p)->(%p): stub\n", This, text);
223
224     if (textstream_check_iomode(This, IORead))
225         return CTL_E_BADFILEMODE;
226
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI textstream_Write(ITextStream *iface, BSTR text)
231 {
232     struct textstream *This = impl_from_ITextStream(iface);
233     FIXME("(%p)->(%s): stub\n", This, debugstr_w(text));
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI textstream_WriteLine(ITextStream *iface, BSTR text)
238 {
239     struct textstream *This = impl_from_ITextStream(iface);
240     FIXME("(%p)->(%s): stub\n", This, debugstr_w(text));
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI textstream_WriteBlankLines(ITextStream *iface, LONG lines)
245 {
246     struct textstream *This = impl_from_ITextStream(iface);
247     FIXME("(%p)->(%d): stub\n", This, lines);
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI textstream_Skip(ITextStream *iface, LONG count)
252 {
253     struct textstream *This = impl_from_ITextStream(iface);
254     FIXME("(%p)->(%d): stub\n", This, count);
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI textstream_SkipLine(ITextStream *iface)
259 {
260     struct textstream *This = impl_from_ITextStream(iface);
261     FIXME("(%p): stub\n", This);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI textstream_Close(ITextStream *iface)
266 {
267     struct textstream *This = impl_from_ITextStream(iface);
268     FIXME("(%p): stub\n", This);
269     return E_NOTIMPL;
270 }
271
272 static const ITextStreamVtbl textstreamvtbl = {
273     textstream_QueryInterface,
274     textstream_AddRef,
275     textstream_Release,
276     textstream_GetTypeInfoCount,
277     textstream_GetTypeInfo,
278     textstream_GetIDsOfNames,
279     textstream_Invoke,
280     textstream_get_Line,
281     textstream_get_Column,
282     textstream_get_AtEndOfStream,
283     textstream_get_AtEndOfLine,
284     textstream_Read,
285     textstream_ReadLine,
286     textstream_ReadAll,
287     textstream_Write,
288     textstream_WriteLine,
289     textstream_WriteBlankLines,
290     textstream_Skip,
291     textstream_SkipLine,
292     textstream_Close
293 };
294
295 static HRESULT create_textstream(IOMode mode, ITextStream **ret)
296 {
297     struct textstream *stream;
298
299     stream = heap_alloc(sizeof(struct textstream));
300     if (!stream) return E_OUTOFMEMORY;
301
302     stream->ITextStream_iface.lpVtbl = &textstreamvtbl;
303     stream->ref = 1;
304     stream->mode = mode;
305
306     *ret = &stream->ITextStream_iface;
307     return S_OK;
308 }
309
310 static HRESULT WINAPI folder_QueryInterface(IFolder *iface, REFIID riid, void **obj)
311 {
312     struct folder *This = impl_from_IFolder(iface);
313
314     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
315
316     *obj = NULL;
317
318     if (IsEqualGUID( riid, &IID_IFolder ) ||
319         IsEqualGUID( riid, &IID_IUnknown))
320     {
321         *obj = iface;
322         IFolder_AddRef(iface);
323     }
324     else
325         return E_NOINTERFACE;
326
327     return S_OK;
328 }
329
330 static ULONG WINAPI folder_AddRef(IFolder *iface)
331 {
332     struct folder *This = impl_from_IFolder(iface);
333     ULONG ref = InterlockedIncrement(&This->ref);
334     TRACE("(%p)->(%d)\n", This, ref);
335     return ref;
336 }
337
338 static ULONG WINAPI folder_Release(IFolder *iface)
339 {
340     struct folder *This = impl_from_IFolder(iface);
341     ULONG ref = InterlockedDecrement(&This->ref);
342     TRACE("(%p)->(%d)\n", This, ref);
343
344     if (!ref)
345         heap_free(This);
346
347     return ref;
348 }
349
350 static HRESULT WINAPI folder_GetTypeInfoCount(IFolder *iface, UINT *pctinfo)
351 {
352     struct folder *This = impl_from_IFolder(iface);
353     TRACE("(%p)->(%p)\n", This, pctinfo);
354     *pctinfo = 1;
355     return S_OK;
356 }
357
358 static HRESULT WINAPI folder_GetTypeInfo(IFolder *iface, UINT iTInfo,
359                                         LCID lcid, ITypeInfo **ppTInfo)
360 {
361     struct folder *This = impl_from_IFolder(iface);
362     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
363     return get_typeinfo(IFolder_tid, ppTInfo);
364 }
365
366 static HRESULT WINAPI folder_GetIDsOfNames(IFolder *iface, REFIID riid,
367                                         LPOLESTR *rgszNames, UINT cNames,
368                                         LCID lcid, DISPID *rgDispId)
369 {
370     struct folder *This = impl_from_IFolder(iface);
371     ITypeInfo *typeinfo;
372     HRESULT hr;
373
374     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
375
376     hr = get_typeinfo(IFolder_tid, &typeinfo);
377     if(SUCCEEDED(hr))
378     {
379         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
380         ITypeInfo_Release(typeinfo);
381     }
382
383     return hr;
384 }
385
386 static HRESULT WINAPI folder_Invoke(IFolder *iface, DISPID dispIdMember,
387                                       REFIID riid, LCID lcid, WORD wFlags,
388                                       DISPPARAMS *pDispParams, VARIANT *pVarResult,
389                                       EXCEPINFO *pExcepInfo, UINT *puArgErr)
390 {
391     struct folder *This = impl_from_IFolder(iface);
392     ITypeInfo *typeinfo;
393     HRESULT hr;
394
395     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
396            lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
397
398     hr = get_typeinfo(IFolder_tid, &typeinfo);
399     if(SUCCEEDED(hr))
400     {
401         hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
402                 pDispParams, pVarResult, pExcepInfo, puArgErr);
403         ITypeInfo_Release(typeinfo);
404     }
405
406     return hr;
407 }
408
409 static HRESULT WINAPI folder_get_Path(IFolder *iface, BSTR *path)
410 {
411     struct folder *This = impl_from_IFolder(iface);
412     FIXME("(%p)->(%p): stub\n", This, path);
413     return E_NOTIMPL;
414 }
415
416 static HRESULT WINAPI folder_get_Name(IFolder *iface, BSTR *name)
417 {
418     struct folder *This = impl_from_IFolder(iface);
419     FIXME("(%p)->(%p): stub\n", This, name);
420     return E_NOTIMPL;
421 }
422
423 static HRESULT WINAPI folder_put_Name(IFolder *iface, BSTR name)
424 {
425     struct folder *This = impl_from_IFolder(iface);
426     FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
427     return E_NOTIMPL;
428 }
429
430 static HRESULT WINAPI folder_get_ShortPath(IFolder *iface, BSTR *path)
431 {
432     struct folder *This = impl_from_IFolder(iface);
433     FIXME("(%p)->(%p): stub\n", This, path);
434     return E_NOTIMPL;
435 }
436
437 static HRESULT WINAPI folder_get_ShortName(IFolder *iface, BSTR *name)
438 {
439     struct folder *This = impl_from_IFolder(iface);
440     FIXME("(%p)->(%p): stub\n", This, name);
441     return E_NOTIMPL;
442 }
443
444 static HRESULT WINAPI folder_get_Drive(IFolder *iface, IDrive **drive)
445 {
446     struct folder *This = impl_from_IFolder(iface);
447     FIXME("(%p)->(%p): stub\n", This, drive);
448     return E_NOTIMPL;
449 }
450
451 static HRESULT WINAPI folder_get_ParentFolder(IFolder *iface, IFolder **parent)
452 {
453     struct folder *This = impl_from_IFolder(iface);
454     FIXME("(%p)->(%p): stub\n", This, parent);
455     return E_NOTIMPL;
456 }
457
458 static HRESULT WINAPI folder_get_Attributes(IFolder *iface, FileAttribute *attr)
459 {
460     struct folder *This = impl_from_IFolder(iface);
461     FIXME("(%p)->(%p): stub\n", This, attr);
462     return E_NOTIMPL;
463 }
464
465 static HRESULT WINAPI folder_put_Attributes(IFolder *iface, FileAttribute attr)
466 {
467     struct folder *This = impl_from_IFolder(iface);
468     FIXME("(%p)->(0x%x): stub\n", This, attr);
469     return E_NOTIMPL;
470 }
471
472 static HRESULT WINAPI folder_get_DateCreated(IFolder *iface, DATE *date)
473 {
474     struct folder *This = impl_from_IFolder(iface);
475     FIXME("(%p)->(%p): stub\n", This, date);
476     return E_NOTIMPL;
477 }
478
479 static HRESULT WINAPI folder_get_DateLastModified(IFolder *iface, DATE *date)
480 {
481     struct folder *This = impl_from_IFolder(iface);
482     FIXME("(%p)->(%p): stub\n", This, date);
483     return E_NOTIMPL;
484 }
485
486 static HRESULT WINAPI folder_get_DateLastAccessed(IFolder *iface, DATE *date)
487 {
488     struct folder *This = impl_from_IFolder(iface);
489     FIXME("(%p)->(%p): stub\n", This, date);
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI folder_get_Type(IFolder *iface, BSTR *type)
494 {
495     struct folder *This = impl_from_IFolder(iface);
496     FIXME("(%p)->(%p): stub\n", This, type);
497     return E_NOTIMPL;
498 }
499
500 static HRESULT WINAPI folder_Delete(IFolder *iface, VARIANT_BOOL force)
501 {
502     struct folder *This = impl_from_IFolder(iface);
503     FIXME("(%p)->(%x): stub\n", This, force);
504     return E_NOTIMPL;
505 }
506
507 static HRESULT WINAPI folder_Copy(IFolder *iface, BSTR dest, VARIANT_BOOL overwrite)
508 {
509     struct folder *This = impl_from_IFolder(iface);
510     FIXME("(%p)->(%s %x): stub\n", This, debugstr_w(dest), overwrite);
511     return E_NOTIMPL;
512 }
513
514 static HRESULT WINAPI folder_Move(IFolder *iface, BSTR dest)
515 {
516     struct folder *This = impl_from_IFolder(iface);
517     FIXME("(%p)->(%s): stub\n", This, debugstr_w(dest));
518     return E_NOTIMPL;
519 }
520
521 static HRESULT WINAPI folder_get_IsRootFolder(IFolder *iface, VARIANT_BOOL *isroot)
522 {
523     struct folder *This = impl_from_IFolder(iface);
524     FIXME("(%p)->(%p): stub\n", This, isroot);
525     return E_NOTIMPL;
526 }
527
528 static HRESULT WINAPI folder_get_Size(IFolder *iface, VARIANT *size)
529 {
530     struct folder *This = impl_from_IFolder(iface);
531     FIXME("(%p)->(%p): stub\n", This, size);
532     return E_NOTIMPL;
533 }
534
535 static HRESULT WINAPI folder_get_SubFolders(IFolder *iface, IFolderCollection **folders)
536 {
537     struct folder *This = impl_from_IFolder(iface);
538     FIXME("(%p)->(%p): stub\n", This, folders);
539     return E_NOTIMPL;
540 }
541
542 static HRESULT WINAPI folder_get_Files(IFolder *iface, IFileCollection **files)
543 {
544     struct folder *This = impl_from_IFolder(iface);
545     FIXME("(%p)->(%p): stub\n", This, files);
546     return E_NOTIMPL;
547 }
548
549 static HRESULT WINAPI folder_CreateTextFile(IFolder *iface, BSTR filename, VARIANT_BOOL overwrite,
550     VARIANT_BOOL unicode, ITextStream **stream)
551 {
552     struct folder *This = impl_from_IFolder(iface);
553     FIXME("(%p)->(%s %x %x %p): stub\n", This, debugstr_w(filename), overwrite, unicode, stream);
554     return E_NOTIMPL;
555 }
556
557 static const IFolderVtbl foldervtbl = {
558     folder_QueryInterface,
559     folder_AddRef,
560     folder_Release,
561     folder_GetTypeInfoCount,
562     folder_GetTypeInfo,
563     folder_GetIDsOfNames,
564     folder_Invoke,
565     folder_get_Path,
566     folder_get_Name,
567     folder_put_Name,
568     folder_get_ShortPath,
569     folder_get_ShortName,
570     folder_get_Drive,
571     folder_get_ParentFolder,
572     folder_get_Attributes,
573     folder_put_Attributes,
574     folder_get_DateCreated,
575     folder_get_DateLastModified,
576     folder_get_DateLastAccessed,
577     folder_get_Type,
578     folder_Delete,
579     folder_Copy,
580     folder_Move,
581     folder_get_IsRootFolder,
582     folder_get_Size,
583     folder_get_SubFolders,
584     folder_get_Files,
585     folder_CreateTextFile
586 };
587
588 static HRESULT create_folder(IFolder **folder)
589 {
590     struct folder *This;
591
592     This = heap_alloc(sizeof(struct folder));
593     if (!This) return E_OUTOFMEMORY;
594
595     This->IFolder_iface.lpVtbl = &foldervtbl;
596     This->ref = 1;
597
598     *folder = &This->IFolder_iface;
599
600     return S_OK;
601 }
602
603 static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, void **ppvObject)
604 {
605     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
606
607     if ( IsEqualGUID( riid, &IID_IFileSystem3 ) ||
608          IsEqualGUID( riid, &IID_IFileSystem ) ||
609          IsEqualGUID( riid, &IID_IDispatch ) ||
610          IsEqualGUID( riid, &IID_IUnknown ) )
611     {
612         *ppvObject = iface;
613     }
614     else if ( IsEqualGUID( riid, &IID_IDispatchEx ))
615     {
616         TRACE("Interface IDispatchEx not supported - returning NULL\n");
617         *ppvObject = NULL;
618         return E_NOINTERFACE;
619     }
620     else if ( IsEqualGUID( riid, &IID_IObjectWithSite ))
621     {
622         TRACE("Interface IObjectWithSite not supported - returning NULL\n");
623         *ppvObject = NULL;
624         return E_NOINTERFACE;
625     }
626     else
627     {
628         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
629         return E_NOINTERFACE;
630     }
631
632     IFileSystem3_AddRef(iface);
633
634     return S_OK;
635 }
636
637 static ULONG WINAPI filesys_AddRef(IFileSystem3 *iface)
638 {
639     TRACE("%p\n", iface);
640
641     return 2;
642 }
643
644 static ULONG WINAPI filesys_Release(IFileSystem3 *iface)
645 {
646     TRACE("%p\n", iface);
647
648     return 1;
649 }
650
651 static HRESULT WINAPI filesys_GetTypeInfoCount(IFileSystem3 *iface, UINT *pctinfo)
652 {
653     TRACE("(%p)->(%p)\n", iface, pctinfo);
654
655     *pctinfo = 1;
656     return S_OK;
657 }
658
659 static HRESULT WINAPI filesys_GetTypeInfo(IFileSystem3 *iface, UINT iTInfo,
660                                         LCID lcid, ITypeInfo **ppTInfo)
661 {
662     TRACE("(%p)->(%u %u %p)\n", iface, iTInfo, lcid, ppTInfo);
663     return get_typeinfo(IFileSystem3_tid, ppTInfo);
664 }
665
666 static HRESULT WINAPI filesys_GetIDsOfNames(IFileSystem3 *iface, REFIID riid,
667                                         LPOLESTR *rgszNames, UINT cNames,
668                                         LCID lcid, DISPID *rgDispId)
669 {
670     ITypeInfo *typeinfo;
671     HRESULT hr;
672
673     TRACE("(%p)->(%s %p %u %u %p)\n", iface, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
674
675     hr = get_typeinfo(IFileSystem3_tid, &typeinfo);
676     if(SUCCEEDED(hr))
677     {
678         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
679         ITypeInfo_Release(typeinfo);
680     }
681
682     return hr;
683 }
684
685 static HRESULT WINAPI filesys_Invoke(IFileSystem3 *iface, DISPID dispIdMember,
686                                       REFIID riid, LCID lcid, WORD wFlags,
687                                       DISPPARAMS *pDispParams, VARIANT *pVarResult,
688                                       EXCEPINFO *pExcepInfo, UINT *puArgErr)
689 {
690     ITypeInfo *typeinfo;
691     HRESULT hr;
692
693     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface, dispIdMember, debugstr_guid(riid),
694            lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
695
696     hr = get_typeinfo(IFileSystem3_tid, &typeinfo);
697     if(SUCCEEDED(hr))
698     {
699         hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
700                 pDispParams, pVarResult, pExcepInfo, puArgErr);
701         ITypeInfo_Release(typeinfo);
702     }
703
704     return hr;
705 }
706
707 static HRESULT WINAPI filesys_get_Drives(IFileSystem3 *iface, IDriveCollection **ppdrives)
708 {
709     FIXME("%p %p\n", iface, ppdrives);
710
711     return E_NOTIMPL;
712 }
713
714 static HRESULT WINAPI filesys_BuildPath(IFileSystem3 *iface, BSTR Path,
715                                             BSTR Name, BSTR *pbstrResult)
716 {
717     FIXME("%p %s %s %p\n", iface, debugstr_w(Path), debugstr_w(Name), pbstrResult);
718
719     return E_NOTIMPL;
720 }
721
722 static HRESULT WINAPI filesys_GetDriveName(IFileSystem3 *iface, BSTR Path,
723                                             BSTR *pbstrResult)
724 {
725     FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
726
727     return E_NOTIMPL;
728 }
729
730 static HRESULT WINAPI filesys_GetParentFolderName(IFileSystem3 *iface, BSTR Path,
731                                             BSTR *pbstrResult)
732 {
733     FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
734
735     return E_NOTIMPL;
736 }
737
738 static HRESULT WINAPI filesys_GetFileName(IFileSystem3 *iface, BSTR Path,
739                                             BSTR *pbstrResult)
740 {
741     FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
742
743     return E_NOTIMPL;
744 }
745
746 static HRESULT WINAPI filesys_GetBaseName(IFileSystem3 *iface, BSTR Path,
747                                             BSTR *pbstrResult)
748 {
749     FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
750
751     return E_NOTIMPL;
752 }
753
754 static HRESULT WINAPI filesys_GetExtensionName(IFileSystem3 *iface, BSTR Path,
755                                             BSTR *pbstrResult)
756 {
757     FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
758
759     return E_NOTIMPL;
760 }
761
762 static HRESULT WINAPI filesys_GetAbsolutePathName(IFileSystem3 *iface, BSTR Path,
763                                             BSTR *pbstrResult)
764 {
765     FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
766
767     return E_NOTIMPL;
768 }
769
770 static HRESULT WINAPI filesys_GetTempName(IFileSystem3 *iface, BSTR *pbstrResult)
771 {
772     FIXME("%p %p\n", iface, pbstrResult);
773
774     return E_NOTIMPL;
775 }
776
777 static HRESULT WINAPI filesys_DriveExists(IFileSystem3 *iface, BSTR DriveSpec,
778                                             VARIANT_BOOL *pfExists)
779 {
780     FIXME("%p %s %p\n", iface, debugstr_w(DriveSpec), pfExists);
781
782     return E_NOTIMPL;
783 }
784
785 static HRESULT WINAPI filesys_FileExists(IFileSystem3 *iface, BSTR path, VARIANT_BOOL *ret)
786 {
787     DWORD attrs;
788     TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
789
790     if (!ret) return E_POINTER;
791
792     attrs = GetFileAttributesW(path);
793     *ret = attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
794     return S_OK;
795 }
796
797 static HRESULT WINAPI filesys_FolderExists(IFileSystem3 *iface, BSTR path, VARIANT_BOOL *ret)
798 {
799     DWORD attrs;
800     TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
801
802     if (!ret) return E_POINTER;
803
804     attrs = GetFileAttributesW(path);
805     *ret = attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
806
807     return S_OK;
808 }
809
810 static HRESULT WINAPI filesys_GetDrive(IFileSystem3 *iface, BSTR DriveSpec,
811                                             IDrive **ppdrive)
812 {
813     FIXME("%p %s %p\n", iface, debugstr_w(DriveSpec), ppdrive);
814
815     return E_NOTIMPL;
816 }
817
818 static HRESULT WINAPI filesys_GetFile(IFileSystem3 *iface, BSTR FilePath,
819                                             IFile **ppfile)
820 {
821     FIXME("%p %s %p\n", iface, debugstr_w(FilePath), ppfile);
822
823     return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI filesys_GetFolder(IFileSystem3 *iface, BSTR FolderPath,
827                                             IFolder **ppfolder)
828 {
829     FIXME("%p %s %p\n", iface, debugstr_w(FolderPath), ppfolder);
830
831     return E_NOTIMPL;
832 }
833
834 static HRESULT WINAPI filesys_GetSpecialFolder(IFileSystem3 *iface,
835                                             SpecialFolderConst SpecialFolder,
836                                             IFolder **ppfolder)
837 {
838     FIXME("%p %d %p\n", iface, SpecialFolder, ppfolder);
839
840     return E_NOTIMPL;
841 }
842
843 static HRESULT WINAPI filesys_DeleteFile(IFileSystem3 *iface, BSTR FileSpec,
844                                             VARIANT_BOOL Force)
845 {
846     FIXME("%p %s %d\n", iface, debugstr_w(FileSpec), Force);
847
848     return E_NOTIMPL;
849 }
850
851 static HRESULT WINAPI filesys_DeleteFolder(IFileSystem3 *iface, BSTR FolderSpec,
852                                             VARIANT_BOOL Force)
853 {
854     FIXME("%p %s %d\n", iface, debugstr_w(FolderSpec), Force);
855
856     return E_NOTIMPL;
857 }
858
859 static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR Source,
860                                             BSTR Destination)
861 {
862     FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
863
864     return E_NOTIMPL;
865 }
866
867 static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface,BSTR Source,
868                                             BSTR Destination)
869 {
870     FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
871
872     return E_NOTIMPL;
873 }
874
875 static HRESULT WINAPI filesys_CopyFile(IFileSystem3 *iface, BSTR Source,
876                                             BSTR Destination, VARIANT_BOOL OverWriteFiles)
877 {
878     FIXME("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
879
880     return E_NOTIMPL;
881 }
882
883 static HRESULT WINAPI filesys_CopyFolder(IFileSystem3 *iface, BSTR Source,
884                                             BSTR Destination, VARIANT_BOOL OverWriteFiles)
885 {
886     FIXME("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
887
888     return E_NOTIMPL;
889 }
890
891 static HRESULT WINAPI filesys_CreateFolder(IFileSystem3 *iface, BSTR path,
892                                             IFolder **folder)
893 {
894     BOOL ret;
895
896     TRACE("(%p)->(%s %p)\n", iface, debugstr_w(path), folder);
897
898     ret = CreateDirectoryW(path, NULL);
899     if (!ret)
900     {
901         *folder = NULL;
902         if (GetLastError() == ERROR_ALREADY_EXISTS) return CTL_E_FILEALREADYEXISTS;
903         return HRESULT_FROM_WIN32(GetLastError());
904     }
905
906     return create_folder(folder);
907 }
908
909 static HRESULT WINAPI filesys_CreateTextFile(IFileSystem3 *iface, BSTR FileName,
910                                             VARIANT_BOOL Overwrite, VARIANT_BOOL Unicode,
911                                             ITextStream **ppts)
912 {
913     FIXME("%p %s %d %d %p\n", iface, debugstr_w(FileName), Overwrite, Unicode, ppts);
914
915     return E_NOTIMPL;
916 }
917
918 static HRESULT WINAPI filesys_OpenTextFile(IFileSystem3 *iface, BSTR filename,
919                                             IOMode mode, VARIANT_BOOL create,
920                                             Tristate format, ITextStream **stream)
921 {
922     FIXME("(%p)->(%s %d %d %d %p)\n", iface, debugstr_w(filename), mode, create, format, stream);
923     return create_textstream(mode, stream);
924 }
925
926 static HRESULT WINAPI filesys_GetStandardStream(IFileSystem3 *iface,
927                                             StandardStreamTypes StandardStreamType,
928                                             VARIANT_BOOL Unicode,
929                                             ITextStream **ppts)
930 {
931     FIXME("%p %d %d %p\n", iface, StandardStreamType, Unicode, ppts);
932
933     return E_NOTIMPL;
934 }
935
936 static HRESULT WINAPI filesys_GetFileVersion(IFileSystem3 *iface, BSTR FileName,
937                                             BSTR *FileVersion)
938 {
939     FIXME("%p %s %p\n", iface, debugstr_w(FileName), FileVersion);
940
941     return E_NOTIMPL;
942 }
943
944 static const struct IFileSystem3Vtbl filesys_vtbl =
945 {
946     filesys_QueryInterface,
947     filesys_AddRef,
948     filesys_Release,
949     filesys_GetTypeInfoCount,
950     filesys_GetTypeInfo,
951     filesys_GetIDsOfNames,
952     filesys_Invoke,
953     filesys_get_Drives,
954     filesys_BuildPath,
955     filesys_GetDriveName,
956     filesys_GetParentFolderName,
957     filesys_GetFileName,
958     filesys_GetBaseName,
959     filesys_GetExtensionName,
960     filesys_GetAbsolutePathName,
961     filesys_GetTempName,
962     filesys_DriveExists,
963     filesys_FileExists,
964     filesys_FolderExists,
965     filesys_GetDrive,
966     filesys_GetFile,
967     filesys_GetFolder,
968     filesys_GetSpecialFolder,
969     filesys_DeleteFile,
970     filesys_DeleteFolder,
971     filesys_MoveFile,
972     filesys_MoveFolder,
973     filesys_CopyFile,
974     filesys_CopyFolder,
975     filesys_CreateFolder,
976     filesys_CreateTextFile,
977     filesys_OpenTextFile,
978     filesys_GetStandardStream,
979     filesys_GetFileVersion
980 };
981
982 static IFileSystem3 filesystem = { &filesys_vtbl };
983
984 HRESULT WINAPI FileSystem_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
985 {
986     TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
987
988     return IFileSystem3_QueryInterface(&filesystem, riid, ppv);
989 }