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