ReactOS  0.4.14-dev-583-g2a1ba2c
filesystem.c
Go to the documentation of this file.
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 <stdarg.h>
22 #include <limits.h>
23 #ifdef __REACTOS__
24 #include <wchar.h>
25 #endif
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "ole2.h"
30 #include "olectl.h"
31 #include "dispex.h"
32 #include "ntsecapi.h"
33 #include "scrrun.h"
34 #include "scrrun_private.h"
35 
36 #include "wine/debug.h"
37 #include "wine/heap.h"
38 
39 #ifdef __REACTOS__
40 #include <winver.h>
41 #endif
42 
44 
45 static const WCHAR bsW[] = {'\\',0};
46 static const WCHAR utf16bom = 0xfeff;
47 
48 struct filesystem {
50  IFileSystem3 IFileSystem3_iface;
51 };
52 
55  IFolderCollection IFolderCollection_iface;
58 };
59 
62  IFileCollection IFileCollection_iface;
65 };
66 
69  IDriveCollection IDriveCollection_iface;
73 };
74 
75 struct enumdata {
76  union
77  {
78  struct
79  {
82  } foldercoll;
83  struct
84  {
86  HANDLE find;
87  } filecoll;
88  struct
89  {
92  } drivecoll;
93  } u;
94 };
95 
96 struct enumvariant {
99 
100  struct enumdata data;
101 };
102 
103 struct drive {
105  IDrive IDrive_iface;
108 };
109 
110 struct folder {
112  IFolder IFolder_iface;
115 };
116 
117 struct file {
119  IFile IFile_iface;
121 
123 };
124 
125 struct textstream {
127  ITextStream ITextStream_iface;
129 
135 };
136 
137 enum iotype {
140 };
141 
142 static inline struct filesystem *impl_from_IFileSystem3(IFileSystem3 *iface)
143 {
144  return CONTAINING_RECORD(iface, struct filesystem, IFileSystem3_iface);
145 }
146 
147 static inline struct drive *impl_from_IDrive(IDrive *iface)
148 {
149  return CONTAINING_RECORD(iface, struct drive, IDrive_iface);
150 }
151 
152 static inline struct folder *impl_from_IFolder(IFolder *iface)
153 {
154  return CONTAINING_RECORD(iface, struct folder, IFolder_iface);
155 }
156 
157 static inline struct file *impl_from_IFile(IFile *iface)
158 {
159  return CONTAINING_RECORD(iface, struct file, IFile_iface);
160 }
161 
162 static inline struct textstream *impl_from_ITextStream(ITextStream *iface)
163 {
164  return CONTAINING_RECORD(iface, struct textstream, ITextStream_iface);
165 }
166 
167 static inline struct foldercollection *impl_from_IFolderCollection(IFolderCollection *iface)
168 {
170 }
171 
172 static inline struct filecollection *impl_from_IFileCollection(IFileCollection *iface)
173 {
175 }
176 
177 static inline struct drivecollection *impl_from_IDriveCollection(IDriveCollection *iface)
178 {
180 }
181 
182 static inline struct enumvariant *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
183 {
184  return CONTAINING_RECORD(iface, struct enumvariant, IEnumVARIANT_iface);
185 }
186 
188 {
189  switch(err) {
195  default:
196  FIXME("Unsupported error code: %d\n", err);
197  return E_FAIL;
198  }
199 }
200 
201 static HRESULT create_folder(const WCHAR*, IFolder**);
202 static HRESULT create_file(BSTR, IFile**);
206 
207 static inline BOOL is_dir_data(const WIN32_FIND_DATAW *data)
208 {
209  static const WCHAR dotdotW[] = {'.','.',0};
210  static const WCHAR dotW[] = {'.',0};
211 
212  return (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
213  wcscmp(data->cFileName, dotdotW) &&
214  wcscmp(data->cFileName, dotW);
215 }
216 
217 static inline BOOL is_file_data(const WIN32_FIND_DATAW *data)
218 {
219  return !(data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
220 }
221 
223 {
224  int len = SysStringLen(path);
225  WCHAR buffW[MAX_PATH];
226 
227  lstrcpyW(buffW, path);
228  if (path[len-1] != '\\')
229  lstrcatW(buffW, bsW);
230  lstrcatW(buffW, data->cFileName);
231 
232  return SysAllocString(buffW);
233 }
234 
236 {
237  if (type == IORead)
238  return This->mode == ForWriting || This->mode == ForAppending;
239  else
240  return This->mode == ForReading;
241 }
242 
243 static HRESULT WINAPI textstream_QueryInterface(ITextStream *iface, REFIID riid, void **obj)
244 {
245  struct textstream *This = impl_from_ITextStream(iface);
246 
247  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
248 
249  if (IsEqualIID(riid, &IID_ITextStream) ||
252  {
253  *obj = &This->ITextStream_iface;
254  }
256  {
257  *obj = &This->classinfo.IProvideClassInfo_iface;
258  }
259  else
260  return E_NOINTERFACE;
261 
262  IUnknown_AddRef((IUnknown*)*obj);
263  return S_OK;
264 }
265 
266 static ULONG WINAPI textstream_AddRef(ITextStream *iface)
267 {
268  struct textstream *This = impl_from_ITextStream(iface);
270  TRACE("(%p)->(%d)\n", This, ref);
271  return ref;
272 }
273 
274 static ULONG WINAPI textstream_Release(ITextStream *iface)
275 {
276  struct textstream *This = impl_from_ITextStream(iface);
278  TRACE("(%p)->(%d)\n", This, ref);
279 
280  if (!ref)
281  {
282  CloseHandle(This->file);
283  heap_free(This);
284  }
285 
286  return ref;
287 }
288 
289 static HRESULT WINAPI textstream_GetTypeInfoCount(ITextStream *iface, UINT *pctinfo)
290 {
291  struct textstream *This = impl_from_ITextStream(iface);
292  TRACE("(%p)->(%p)\n", This, pctinfo);
293  *pctinfo = 1;
294  return S_OK;
295 }
296 
297 static HRESULT WINAPI textstream_GetTypeInfo(ITextStream *iface, UINT iTInfo,
298  LCID lcid, ITypeInfo **ppTInfo)
299 {
300  struct textstream *This = impl_from_ITextStream(iface);
301  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
302  return get_typeinfo(ITextStream_tid, ppTInfo);
303 }
304 
305 static HRESULT WINAPI textstream_GetIDsOfNames(ITextStream *iface, REFIID riid,
306  LPOLESTR *rgszNames, UINT cNames,
307  LCID lcid, DISPID *rgDispId)
308 {
309  struct textstream *This = impl_from_ITextStream(iface);
311  HRESULT hr;
312 
313  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
314 
316  if(SUCCEEDED(hr))
317  {
318  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
319  ITypeInfo_Release(typeinfo);
320  }
321 
322  return hr;
323 }
324 
325 static HRESULT WINAPI textstream_Invoke(ITextStream *iface, DISPID dispIdMember,
326  REFIID riid, LCID lcid, WORD wFlags,
327  DISPPARAMS *pDispParams, VARIANT *pVarResult,
328  EXCEPINFO *pExcepInfo, UINT *puArgErr)
329 {
330  struct textstream *This = impl_from_ITextStream(iface);
332  HRESULT hr;
333 
334  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
335  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
336 
338  if(SUCCEEDED(hr))
339  {
340  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
341  pDispParams, pVarResult, pExcepInfo, puArgErr);
342  ITypeInfo_Release(typeinfo);
343  }
344 
345  return hr;
346 }
347 
348 static HRESULT WINAPI textstream_get_Line(ITextStream *iface, LONG *line)
349 {
350  struct textstream *This = impl_from_ITextStream(iface);
351  FIXME("(%p)->(%p): stub\n", This, line);
352  return E_NOTIMPL;
353 }
354 
355 static HRESULT WINAPI textstream_get_Column(ITextStream *iface, LONG *column)
356 {
357  struct textstream *This = impl_from_ITextStream(iface);
358  FIXME("(%p)->(%p): stub\n", This, column);
359  return E_NOTIMPL;
360 }
361 
362 static HRESULT WINAPI textstream_get_AtEndOfStream(ITextStream *iface, VARIANT_BOOL *eos)
363 {
364  struct textstream *This = impl_from_ITextStream(iface);
365  LARGE_INTEGER pos, dist;
366 
367  TRACE("(%p)->(%p)\n", This, eos);
368 
369  if (!eos)
370  return E_POINTER;
371 
373  *eos = VARIANT_TRUE;
374  return CTL_E_BADFILEMODE;
375  }
376 
377  dist.QuadPart = 0;
378  if (!SetFilePointerEx(This->file, dist, &pos, FILE_CURRENT))
379  return E_FAIL;
380 
381  *eos = This->size.QuadPart == pos.QuadPart ? VARIANT_TRUE : VARIANT_FALSE;
382  return S_OK;
383 }
384 
385 static HRESULT WINAPI textstream_get_AtEndOfLine(ITextStream *iface, VARIANT_BOOL *eol)
386 {
387  struct textstream *This = impl_from_ITextStream(iface);
388  FIXME("(%p)->(%p): stub\n", This, eol);
389  return E_NOTIMPL;
390 }
391 
392 /*
393  Reads 'toread' bytes from a file, converts if needed
394  BOM is skipped if 'bof' is set.
395  */
396 static HRESULT textstream_read(struct textstream *stream, LONG toread, BOOL bof, BSTR *text)
397 {
398  HRESULT hr = S_OK;
399  DWORD read;
400  char *buff;
401  BOOL ret;
402 
403  if (toread == 0) {
404  *text = SysAllocStringLen(NULL, 0);
405  return *text ? S_FALSE : E_OUTOFMEMORY;
406  }
407 
408  if (toread < sizeof(WCHAR))
409  return CTL_E_ENDOFFILE;
410 
411  buff = heap_alloc(toread);
412  if (!buff)
413  return E_OUTOFMEMORY;
414 
415  ret = ReadFile(stream->file, buff, toread, &read, NULL);
416  if (!ret || toread != read) {
417  WARN("failed to read from file %d, %d, error %d\n", read, toread, GetLastError());
418  heap_free(buff);
419  return E_FAIL;
420  }
421 
422  if (stream->unicode) {
423  int i = 0;
424 
425  /* skip BOM */
426  if (bof && *(WCHAR*)buff == utf16bom) {
427  read -= sizeof(WCHAR);
428  i += sizeof(WCHAR);
429  }
430 
431  *text = SysAllocStringLen(read ? (WCHAR*)&buff[i] : NULL, read/sizeof(WCHAR));
432  if (!*text) hr = E_OUTOFMEMORY;
433  }
434  else {
437  if (*text)
439  else
440  hr = E_OUTOFMEMORY;
441  }
442  heap_free(buff);
443 
444  return hr;
445 }
446 
447 static HRESULT WINAPI textstream_Read(ITextStream *iface, LONG len, BSTR *text)
448 {
449  struct textstream *This = impl_from_ITextStream(iface);
450  LARGE_INTEGER start, end, dist;
451  DWORD toread;
452  HRESULT hr;
453 
454  TRACE("(%p)->(%d %p)\n", This, len, text);
455 
456  if (!text)
457  return E_POINTER;
458 
459  *text = NULL;
460  if (len <= 0)
461  return len == 0 ? S_OK : E_INVALIDARG;
462 
464  return CTL_E_BADFILEMODE;
465 
466  if (!This->first_read) {
467  VARIANT_BOOL eos;
468 
469  /* check for EOF */
470  hr = ITextStream_get_AtEndOfStream(iface, &eos);
471  if (FAILED(hr))
472  return hr;
473 
474  if (eos == VARIANT_TRUE)
475  return CTL_E_ENDOFFILE;
476  }
477 
478  /* read everything from current position */
479  dist.QuadPart = 0;
480  SetFilePointerEx(This->file, dist, &start, FILE_CURRENT);
481  SetFilePointerEx(This->file, dist, &end, FILE_END);
482  toread = end.QuadPart - start.QuadPart;
483  /* rewind back */
484  dist.QuadPart = start.QuadPart;
485  SetFilePointerEx(This->file, dist, NULL, FILE_BEGIN);
486 
487  This->first_read = FALSE;
488  if (This->unicode) len *= sizeof(WCHAR);
489 
490  hr = textstream_read(This, min(toread, len), start.QuadPart == 0, text);
491  if (FAILED(hr))
492  return hr;
493  else
494  return toread <= len ? S_FALSE : S_OK;
495 }
496 
497 static HRESULT WINAPI textstream_ReadLine(ITextStream *iface, BSTR *text)
498 {
499  struct textstream *This = impl_from_ITextStream(iface);
500  VARIANT_BOOL eos;
501  HRESULT hr;
502 
503  FIXME("(%p)->(%p): stub\n", This, text);
504 
505  if (!text)
506  return E_POINTER;
507 
508  *text = NULL;
510  return CTL_E_BADFILEMODE;
511 
512  /* check for EOF */
513  hr = ITextStream_get_AtEndOfStream(iface, &eos);
514  if (FAILED(hr))
515  return hr;
516 
517  if (eos == VARIANT_TRUE)
518  return CTL_E_ENDOFFILE;
519 
520  return E_NOTIMPL;
521 }
522 
523 static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
524 {
525  struct textstream *This = impl_from_ITextStream(iface);
526  LARGE_INTEGER start, end, dist;
527  DWORD toread;
528  HRESULT hr;
529 
530  TRACE("(%p)->(%p)\n", This, text);
531 
532  if (!text)
533  return E_POINTER;
534 
535  *text = NULL;
537  return CTL_E_BADFILEMODE;
538 
539  if (!This->first_read) {
540  VARIANT_BOOL eos;
541 
542  /* check for EOF */
543  hr = ITextStream_get_AtEndOfStream(iface, &eos);
544  if (FAILED(hr))
545  return hr;
546 
547  if (eos == VARIANT_TRUE)
548  return CTL_E_ENDOFFILE;
549  }
550 
551  /* read everything from current position */
552  dist.QuadPart = 0;
553  SetFilePointerEx(This->file, dist, &start, FILE_CURRENT);
554  SetFilePointerEx(This->file, dist, &end, FILE_END);
555  toread = end.QuadPart - start.QuadPart;
556  /* rewind back */
557  dist.QuadPart = start.QuadPart;
558  SetFilePointerEx(This->file, dist, NULL, FILE_BEGIN);
559 
560  This->first_read = FALSE;
561 
562  hr = textstream_read(This, toread, start.QuadPart == 0, text);
563  return FAILED(hr) ? hr : S_FALSE;
564 }
565 
567 {
568  DWORD written = 0;
569  BOOL ret;
570 
571  if (stream->unicode) {
572  ret = WriteFile(stream->file, text, SysStringByteLen(text), &written, NULL);
573  return (ret && written == SysStringByteLen(text)) ? S_OK : create_error(GetLastError());
574  } else {
576  char *buffA;
577  HRESULT hr;
578 
579  buffA = heap_alloc(len);
580  if (!buffA)
581  return E_OUTOFMEMORY;
582 
584  ret = WriteFile(stream->file, buffA, len, &written, NULL);
585  hr = (ret && written == len) ? S_OK : create_error(GetLastError());
586  heap_free(buffA);
587  return hr;
588  }
589 }
590 
591 static HRESULT WINAPI textstream_Write(ITextStream *iface, BSTR text)
592 {
593  struct textstream *This = impl_from_ITextStream(iface);
594 
595  TRACE("(%p)->(%s)\n", This, debugstr_w(text));
596 
598  return CTL_E_BADFILEMODE;
599 
600  return textstream_writestr(This, text);
601 }
602 
604 {
605  static const WCHAR crlfW[] = {'\r','\n'};
606  static const char crlfA[] = {'\r','\n'};
607  DWORD written = 0, len;
608  const void *ptr;
609  BOOL ret;
610 
611  if (stream->unicode) {
612  ptr = crlfW;
613  len = sizeof(crlfW);
614  }
615  else {
616  ptr = crlfA;
617  len = sizeof(crlfA);
618  }
619 
620  ret = WriteFile(stream->file, ptr, len, &written, NULL);
621  return (ret && written == len) ? S_OK : create_error(GetLastError());
622 }
623 
624 static HRESULT WINAPI textstream_WriteLine(ITextStream *iface, BSTR text)
625 {
626  struct textstream *This = impl_from_ITextStream(iface);
627  HRESULT hr;
628 
629  TRACE("(%p)->(%s)\n", This, debugstr_w(text));
630 
632  return CTL_E_BADFILEMODE;
633 
635  if (SUCCEEDED(hr))
637  return hr;
638 }
639 
641 {
642  struct textstream *This = impl_from_ITextStream(iface);
643  FIXME("(%p)->(%d): stub\n", This, lines);
644  return E_NOTIMPL;
645 }
646 
647 static HRESULT WINAPI textstream_Skip(ITextStream *iface, LONG count)
648 {
649  struct textstream *This = impl_from_ITextStream(iface);
650  FIXME("(%p)->(%d): stub\n", This, count);
651  return E_NOTIMPL;
652 }
653 
654 static HRESULT WINAPI textstream_SkipLine(ITextStream *iface)
655 {
656  struct textstream *This = impl_from_ITextStream(iface);
657  FIXME("(%p): stub\n", This);
658  return E_NOTIMPL;
659 }
660 
661 static HRESULT WINAPI textstream_Close(ITextStream *iface)
662 {
663  struct textstream *This = impl_from_ITextStream(iface);
664  HRESULT hr = S_OK;
665 
666  TRACE("(%p)\n", This);
667 
668  if(!CloseHandle(This->file))
669  hr = S_FALSE;
670 
671  This->file = NULL;
672 
673  return hr;
674 }
675 
676 static const ITextStreamVtbl textstreamvtbl = {
697 };
698 
699 static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMode mode, Tristate format, ITextStream **ret)
700 {
701  struct textstream *stream;
702  DWORD access = 0;
703 
704  /* map access mode */
705  switch (mode)
706  {
707  case ForReading:
709  break;
710  case ForWriting:
712  break;
713  case ForAppending:
715  break;
716  default:
717  return E_INVALIDARG;
718  }
719 
720  stream = heap_alloc(sizeof(struct textstream));
721  if (!stream) return E_OUTOFMEMORY;
722 
723  stream->ITextStream_iface.lpVtbl = &textstreamvtbl;
724  stream->ref = 1;
725  stream->mode = mode;
726  stream->first_read = TRUE;
727 
728  stream->file = CreateFileW(filename, access, 0, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
729  if (stream->file == INVALID_HANDLE_VALUE)
730  {
732  heap_free(stream);
733  return hr;
734  }
735 
736  if (mode == ForReading)
737  GetFileSizeEx(stream->file, &stream->size);
738  else
739  stream->size.QuadPart = 0;
740 
741  if (mode == ForWriting)
742  {
743  stream->unicode = format == TristateTrue;
744  /* Write Unicode BOM */
745  if (stream->unicode && (disposition == CREATE_ALWAYS || disposition == CREATE_NEW)) {
746  DWORD written = 0;
747  BOOL ret = WriteFile(stream->file, &utf16bom, sizeof(utf16bom), &written, NULL);
748  if (!ret || written != sizeof(utf16bom)) {
749  ITextStream_Release(&stream->ITextStream_iface);
750  return create_error(GetLastError());
751  }
752  }
753  }
754  else
755  {
756  if (format == TristateUseDefault)
757  {
758  BYTE buf[64];
759  DWORD read;
760  BOOL ret;
761 
762  ret = ReadFile(stream->file, buf, sizeof(buf), &read, NULL);
763  if (!ret) {
764  ITextStream_Release(&stream->ITextStream_iface);
765  return create_error(GetLastError());
766  }
767 
768  stream->unicode = IsTextUnicode(buf, read, NULL);
769  if (mode == ForReading) SetFilePointer(stream->file, 0, 0, FILE_BEGIN);
770  }
771  else stream->unicode = format != TristateFalse;
772 
773  if (mode == ForAppending) SetFilePointer(stream->file, 0, 0, FILE_END);
774  }
775 
776  init_classinfo(&CLSID_TextStream, (IUnknown *)&stream->ITextStream_iface, &stream->classinfo);
777  *ret = &stream->ITextStream_iface;
778  return S_OK;
779 }
780 
781 static HRESULT WINAPI drive_QueryInterface(IDrive *iface, REFIID riid, void **obj)
782 {
783  struct drive *This = impl_from_IDrive(iface);
784 
785  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
786 
787  *obj = NULL;
788 
789  if (IsEqualIID( riid, &IID_IDrive ) ||
792  {
793  *obj = &This->IDrive_iface;
794  }
795  else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
796  {
797  *obj = &This->classinfo.IProvideClassInfo_iface;
798  }
799  else
800  return E_NOINTERFACE;
801 
802  IUnknown_AddRef((IUnknown*)*obj);
803  return S_OK;
804 }
805 
806 static ULONG WINAPI drive_AddRef(IDrive *iface)
807 {
808  struct drive *This = impl_from_IDrive(iface);
810  TRACE("(%p)->(%d)\n", This, ref);
811  return ref;
812 }
813 
814 static ULONG WINAPI drive_Release(IDrive *iface)
815 {
816  struct drive *This = impl_from_IDrive(iface);
818  TRACE("(%p)->(%d)\n", This, ref);
819 
820  if (!ref)
821  {
822  SysFreeString(This->root);
823  heap_free(This);
824  }
825 
826  return ref;
827 }
828 
829 static HRESULT WINAPI drive_GetTypeInfoCount(IDrive *iface, UINT *pctinfo)
830 {
831  struct drive *This = impl_from_IDrive(iface);
832  TRACE("(%p)->(%p)\n", This, pctinfo);
833  *pctinfo = 1;
834  return S_OK;
835 }
836 
837 static HRESULT WINAPI drive_GetTypeInfo(IDrive *iface, UINT iTInfo,
838  LCID lcid, ITypeInfo **ppTInfo)
839 {
840  struct drive *This = impl_from_IDrive(iface);
841  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
842  return get_typeinfo(IDrive_tid, ppTInfo);
843 }
844 
846  LPOLESTR *rgszNames, UINT cNames,
847  LCID lcid, DISPID *rgDispId)
848 {
849  struct drive *This = impl_from_IDrive(iface);
851  HRESULT hr;
852 
853  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
854 
856  if(SUCCEEDED(hr))
857  {
858  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
859  ITypeInfo_Release(typeinfo);
860  }
861 
862  return hr;
863 }
864 
865 static HRESULT WINAPI drive_Invoke(IDrive *iface, DISPID dispIdMember,
866  REFIID riid, LCID lcid, WORD wFlags,
867  DISPPARAMS *pDispParams, VARIANT *pVarResult,
868  EXCEPINFO *pExcepInfo, UINT *puArgErr)
869 {
870  struct drive *This = impl_from_IDrive(iface);
872  HRESULT hr;
873 
874  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
875  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
876 
878  if(SUCCEEDED(hr))
879  {
880  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
881  pDispParams, pVarResult, pExcepInfo, puArgErr);
882  ITypeInfo_Release(typeinfo);
883  }
884 
885  return hr;
886 }
887 
888 static HRESULT WINAPI drive_get_Path(IDrive *iface, BSTR *path)
889 {
890  struct drive *This = impl_from_IDrive(iface);
891  FIXME("(%p)->(%p): stub\n", This, path);
892  return E_NOTIMPL;
893 }
894 
895 static HRESULT WINAPI drive_get_DriveLetter(IDrive *iface, BSTR *letter)
896 {
897  struct drive *This = impl_from_IDrive(iface);
898 
899  TRACE("(%p)->(%p)\n", This, letter);
900 
901  if (!letter)
902  return E_POINTER;
903 
904  *letter = SysAllocStringLen(This->root, 1);
905  if (!*letter)
906  return E_OUTOFMEMORY;
907 
908  return S_OK;
909 }
910 
911 static HRESULT WINAPI drive_get_ShareName(IDrive *iface, BSTR *share_name)
912 {
913  struct drive *This = impl_from_IDrive(iface);
914  FIXME("(%p)->(%p): stub\n", This, share_name);
915  return E_NOTIMPL;
916 }
917 
919 {
920  struct drive *This = impl_from_IDrive(iface);
921 
922  TRACE("(%p)->(%p)\n", This, type);
923 
924  switch (GetDriveTypeW(This->root))
925  {
926  case DRIVE_REMOVABLE:
927  *type = Removable;
928  break;
929  case DRIVE_FIXED:
930  *type = Fixed;
931  break;
932  case DRIVE_REMOTE:
933  *type = Remote;
934  break;
935  case DRIVE_CDROM:
936  *type = CDRom;
937  break;
938  case DRIVE_RAMDISK:
939  *type = RamDisk;
940  break;
941  default:
942  *type = UnknownType;
943  break;
944  }
945 
946  return S_OK;
947 }
948 
949 static HRESULT WINAPI drive_get_RootFolder(IDrive *iface, IFolder **folder)
950 {
951  struct drive *This = impl_from_IDrive(iface);
952  FIXME("(%p)->(%p): stub\n", This, folder);
953  return E_NOTIMPL;
954 }
955 
957 {
958  HRESULT hr = S_OK;
959 
960  if (src->u.HighPart || src->u.LowPart > INT_MAX)
961  {
962  V_VT(v) = VT_R8;
963  hr = VarR8FromUI8(src->QuadPart, &V_R8(v));
964  }
965  else
966  {
967  V_VT(v) = VT_I4;
968  V_I4(v) = src->u.LowPart;
969  }
970 
971  return hr;
972 }
973 
975 {
976  struct drive *This = impl_from_IDrive(iface);
978 
979  TRACE("(%p)->(%p)\n", This, v);
980 
981  if (!v)
982  return E_POINTER;
983 
984  if (!GetDiskFreeSpaceExW(This->root, &avail, NULL, NULL))
985  return E_FAIL;
986 
987  return variant_from_largeint(&avail, v);
988 }
989 
990 static HRESULT WINAPI drive_get_FreeSpace(IDrive *iface, VARIANT *v)
991 {
992  struct drive *This = impl_from_IDrive(iface);
994 
995  TRACE("(%p)->(%p)\n", This, v);
996 
997  if (!v)
998  return E_POINTER;
999 
1000  if (!GetDiskFreeSpaceExW(This->root, &freespace, NULL, NULL))
1001  return E_FAIL;
1002 
1003  return variant_from_largeint(&freespace, v);
1004 }
1005 
1006 static HRESULT WINAPI drive_get_TotalSize(IDrive *iface, VARIANT *v)
1007 {
1008  struct drive *This = impl_from_IDrive(iface);
1009  ULARGE_INTEGER total;
1010 
1011  TRACE("(%p)->(%p)\n", This, v);
1012 
1013  if (!v)
1014  return E_POINTER;
1015 
1016  if (!GetDiskFreeSpaceExW(This->root, NULL, &total, NULL))
1017  return E_FAIL;
1018 
1019  return variant_from_largeint(&total, v);
1020 }
1021 
1023 {
1024  struct drive *This = impl_from_IDrive(iface);
1025  WCHAR nameW[MAX_PATH+1];
1026  BOOL ret;
1027 
1028  TRACE("(%p)->(%p)\n", This, name);
1029 
1030  if (!name)
1031  return E_POINTER;
1032 
1033  *name = NULL;
1035  if (ret)
1037  return ret ? S_OK : E_FAIL;
1038 }
1039 
1041 {
1042  struct drive *This = impl_from_IDrive(iface);
1043  FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
1044  return E_NOTIMPL;
1045 }
1046 
1047 static HRESULT WINAPI drive_get_FileSystem(IDrive *iface, BSTR *fs)
1048 {
1049  struct drive *This = impl_from_IDrive(iface);
1050  WCHAR nameW[MAX_PATH+1];
1051  BOOL ret;
1052 
1053  TRACE("(%p)->(%p)\n", This, fs);
1054 
1055  if (!fs)
1056  return E_POINTER;
1057 
1058  *fs = NULL;
1060  if (ret)
1061  *fs = SysAllocString(nameW);
1062  return ret ? S_OK : E_FAIL;
1063 }
1064 
1066 {
1067  struct drive *This = impl_from_IDrive(iface);
1068  BOOL ret;
1069 
1070  TRACE("(%p)->(%p)\n", This, serial);
1071 
1072  if (!serial)
1073  return E_POINTER;
1074 
1075  ret = GetVolumeInformationW(This->root, NULL, 0, (DWORD*)serial, NULL, NULL, NULL, 0);
1076  return ret ? S_OK : E_FAIL;
1077 }
1078 
1079 static HRESULT WINAPI drive_get_IsReady(IDrive *iface, VARIANT_BOOL *ready)
1080 {
1081  struct drive *This = impl_from_IDrive(iface);
1083  BOOL ret;
1084 
1085  TRACE("(%p)->(%p)\n", This, ready);
1086 
1087  if (!ready)
1088  return E_POINTER;
1089 
1091  *ready = ret ? VARIANT_TRUE : VARIANT_FALSE;
1092  return S_OK;
1093 }
1094 
1095 static const IDriveVtbl drivevtbl = {
1097  drive_AddRef,
1098  drive_Release,
1102  drive_Invoke,
1116 };
1117 
1118 static HRESULT create_drive(WCHAR letter, IDrive **drive)
1119 {
1120  struct drive *This;
1121 
1122  *drive = NULL;
1123 
1124  This = heap_alloc(sizeof(*This));
1125  if (!This) return E_OUTOFMEMORY;
1126 
1127  This->IDrive_iface.lpVtbl = &drivevtbl;
1128  This->ref = 1;
1129  This->root = SysAllocStringLen(NULL, 3);
1130  if (!This->root)
1131  {
1132  heap_free(This);
1133  return E_OUTOFMEMORY;
1134  }
1135  This->root[0] = letter;
1136  This->root[1] = ':';
1137  This->root[2] = '\\';
1138  This->root[3] = 0;
1139 
1140  init_classinfo(&CLSID_Drive, (IUnknown *)&This->IDrive_iface, &This->classinfo);
1141  *drive = &This->IDrive_iface;
1142  return S_OK;
1143 }
1144 
1146 {
1147  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1148 
1149  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1150 
1151  *obj = NULL;
1152 
1153  if (IsEqualIID( riid, &IID_IEnumVARIANT ) ||
1155  {
1156  *obj = iface;
1157  IEnumVARIANT_AddRef(iface);
1158  }
1159  else
1160  return E_NOINTERFACE;
1161 
1162  return S_OK;
1163 }
1164 
1166 {
1167  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1169  TRACE("(%p)->(%d)\n", This, ref);
1170  return ref;
1171 }
1172 
1174 {
1175  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1177 
1178  TRACE("(%p)->(%d)\n", This, ref);
1179 
1180  if (!ref)
1181  {
1182  IFolderCollection_Release(&This->data.u.foldercoll.coll->IFolderCollection_iface);
1183  FindClose(This->data.u.foldercoll.find);
1184  heap_free(This);
1185  }
1186 
1187  return ref;
1188 }
1189 
1191 {
1192  static const WCHAR allW[] = {'*',0};
1193  WCHAR pathW[MAX_PATH];
1194  int len;
1195  HANDLE handle;
1196 
1197  lstrcpyW(pathW, path);
1198  len = lstrlenW(pathW);
1199  if (len && pathW[len-1] != '\\')
1200  lstrcatW(pathW, bsW);
1201  lstrcatW(pathW, allW);
1202  handle = FindFirstFileW(pathW, data);
1203  if (handle == INVALID_HANDLE_VALUE) return 0;
1204 
1205  /* find first dir/file */
1206  while (1)
1207  {
1209  break;
1210 
1211  if (!FindNextFileW(handle, data))
1212  {
1213  FindClose(handle);
1214  return 0;
1215  }
1216  }
1217  return handle;
1218 }
1219 
1221 {
1222  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1223  HANDLE handle = This->data.u.foldercoll.find;
1225  ULONG count = 0;
1226 
1227  TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
1228 
1229  if (fetched)
1230  *fetched = 0;
1231 
1232  if (!celt) return S_OK;
1233 
1234  if (!handle)
1235  {
1236  handle = start_enumeration(This->data.u.foldercoll.coll->path, &data, FALSE);
1237  if (!handle) return S_FALSE;
1238 
1239  This->data.u.foldercoll.find = handle;
1240  }
1241  else
1242  {
1243  if (!FindNextFileW(handle, &data))
1244  return S_FALSE;
1245  }
1246 
1247  do
1248  {
1249  if (is_dir_data(&data))
1250  {
1251  IFolder *folder;
1252  HRESULT hr;
1253  BSTR str;
1254 
1255  str = get_full_path(This->data.u.foldercoll.coll->path, &data);
1256  hr = create_folder(str, &folder);
1257  SysFreeString(str);
1258  if (FAILED(hr)) return hr;
1259 
1260  V_VT(&var[count]) = VT_DISPATCH;
1261  V_DISPATCH(&var[count]) = (IDispatch*)folder;
1262  count++;
1263 
1264  if (count >= celt) break;
1265  }
1266  } while (FindNextFileW(handle, &data));
1267 
1268  if (fetched)
1269  *fetched = count;
1270 
1271  return (count < celt) ? S_FALSE : S_OK;
1272 }
1273 
1275 {
1276  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1277  HANDLE handle = This->data.u.foldercoll.find;
1279 
1280  TRACE("(%p)->(%d)\n", This, celt);
1281 
1282  if (!celt) return S_OK;
1283 
1284  if (!handle)
1285  {
1286  handle = start_enumeration(This->data.u.foldercoll.coll->path, &data, FALSE);
1287  if (!handle) return S_FALSE;
1288 
1289  This->data.u.foldercoll.find = handle;
1290  }
1291  else
1292  {
1293  if (!FindNextFileW(handle, &data))
1294  return S_FALSE;
1295  }
1296 
1297  do
1298  {
1299  if (is_dir_data(&data))
1300  --celt;
1301 
1302  if (!celt) break;
1303  } while (FindNextFileW(handle, &data));
1304 
1305  return celt ? S_FALSE : S_OK;
1306 }
1307 
1309 {
1310  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1311 
1312  TRACE("(%p)\n", This);
1313 
1314  FindClose(This->data.u.foldercoll.find);
1315  This->data.u.foldercoll.find = NULL;
1316 
1317  return S_OK;
1318 }
1319 
1321 {
1322  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1323  TRACE("(%p)->(%p)\n", This, pclone);
1324  return create_foldercoll_enum(This->data.u.foldercoll.coll, (IUnknown**)pclone);
1325 }
1326 
1327 static const IEnumVARIANTVtbl foldercollenumvariantvtbl = {
1335 };
1336 
1338 {
1339  struct enumvariant *This;
1340 
1341  *newenum = NULL;
1342 
1343  This = heap_alloc(sizeof(*This));
1344  if (!This) return E_OUTOFMEMORY;
1345 
1346  This->IEnumVARIANT_iface.lpVtbl = &foldercollenumvariantvtbl;
1347  This->ref = 1;
1348  This->data.u.foldercoll.find = NULL;
1349  This->data.u.foldercoll.coll = collection;
1350  IFolderCollection_AddRef(&collection->IFolderCollection_iface);
1351 
1352  *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
1353 
1354  return S_OK;
1355 }
1356 
1358 {
1359  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1361 
1362  TRACE("(%p)->(%d)\n", This, ref);
1363 
1364  if (!ref)
1365  {
1366  IFileCollection_Release(&This->data.u.filecoll.coll->IFileCollection_iface);
1367  FindClose(This->data.u.filecoll.find);
1368  heap_free(This);
1369  }
1370 
1371  return ref;
1372 }
1373 
1375 {
1376  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1377  HANDLE handle = This->data.u.filecoll.find;
1379  ULONG count = 0;
1380 
1381  TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
1382 
1383  if (fetched)
1384  *fetched = 0;
1385 
1386  if (!celt) return S_OK;
1387 
1388  if (!handle)
1389  {
1390  handle = start_enumeration(This->data.u.filecoll.coll->path, &data, TRUE);
1391  if (!handle) return S_FALSE;
1392  This->data.u.filecoll.find = handle;
1393  }
1394  else if (!FindNextFileW(handle, &data))
1395  return S_FALSE;
1396 
1397  do
1398  {
1399  if (is_file_data(&data))
1400  {
1401  IFile *file;
1402  HRESULT hr;
1403  BSTR str;
1404 
1405  str = get_full_path(This->data.u.filecoll.coll->path, &data);
1406  hr = create_file(str, &file);
1407  SysFreeString(str);
1408  if (FAILED(hr)) return hr;
1409 
1410  V_VT(&var[count]) = VT_DISPATCH;
1411  V_DISPATCH(&var[count]) = (IDispatch*)file;
1412  if (++count >= celt) break;
1413  }
1414  } while (FindNextFileW(handle, &data));
1415 
1416  if (fetched)
1417  *fetched = count;
1418 
1419  return (count < celt) ? S_FALSE : S_OK;
1420 }
1421 
1423 {
1424  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1425  HANDLE handle = This->data.u.filecoll.find;
1427 
1428  TRACE("(%p)->(%d)\n", This, celt);
1429 
1430  if (!celt) return S_OK;
1431 
1432  if (!handle)
1433  {
1434  handle = start_enumeration(This->data.u.filecoll.coll->path, &data, TRUE);
1435  if (!handle) return S_FALSE;
1436  This->data.u.filecoll.find = handle;
1437  }
1438  else if (!FindNextFileW(handle, &data))
1439  return S_FALSE;
1440 
1441  do
1442  {
1443  if (is_file_data(&data))
1444  --celt;
1445  } while (celt && FindNextFileW(handle, &data));
1446 
1447  return celt ? S_FALSE : S_OK;
1448 }
1449 
1451 {
1452  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1453 
1454  TRACE("(%p)\n", This);
1455 
1456  FindClose(This->data.u.filecoll.find);
1457  This->data.u.filecoll.find = NULL;
1458 
1459  return S_OK;
1460 }
1461 
1463 {
1464  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1465  TRACE("(%p)->(%p)\n", This, pclone);
1466  return create_filecoll_enum(This->data.u.filecoll.coll, (IUnknown**)pclone);
1467 }
1468 
1469 static const IEnumVARIANTVtbl filecollenumvariantvtbl = {
1477 };
1478 
1480 {
1481  struct enumvariant *This;
1482 
1483  *newenum = NULL;
1484 
1485  This = heap_alloc(sizeof(*This));
1486  if (!This) return E_OUTOFMEMORY;
1487 
1488  This->IEnumVARIANT_iface.lpVtbl = &filecollenumvariantvtbl;
1489  This->ref = 1;
1490  This->data.u.filecoll.find = NULL;
1491  This->data.u.filecoll.coll = collection;
1492  IFileCollection_AddRef(&collection->IFileCollection_iface);
1493 
1494  *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
1495 
1496  return S_OK;
1497 }
1498 
1500 {
1501  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1503 
1504  TRACE("(%p)->(%d)\n", This, ref);
1505 
1506  if (!ref)
1507  {
1508  IDriveCollection_Release(&This->data.u.drivecoll.coll->IDriveCollection_iface);
1509  heap_free(This);
1510  }
1511 
1512  return ref;
1513 }
1514 
1515 static HRESULT find_next_drive(struct enumvariant *penum)
1516 {
1517  int i = penum->data.u.drivecoll.cur == -1 ? 0 : penum->data.u.drivecoll.cur + 1;
1518 
1519  for (; i < 32; i++)
1520  if (penum->data.u.drivecoll.coll->drives & (1 << i))
1521  {
1522  penum->data.u.drivecoll.cur = i;
1523  return S_OK;
1524  }
1525 
1526  return S_FALSE;
1527 }
1528 
1530 {
1531  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1532  ULONG count = 0;
1533 
1534  TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
1535 
1536  if (fetched)
1537  *fetched = 0;
1538 
1539  if (!celt) return S_OK;
1540 
1541  while (find_next_drive(This) == S_OK)
1542  {
1543  IDrive *drive;
1544  HRESULT hr;
1545 
1546  hr = create_drive('A' + This->data.u.drivecoll.cur, &drive);
1547  if (FAILED(hr)) return hr;
1548 
1549  V_VT(&var[count]) = VT_DISPATCH;
1550  V_DISPATCH(&var[count]) = (IDispatch*)drive;
1551 
1552  if (++count >= celt) break;
1553  }
1554 
1555  if (fetched)
1556  *fetched = count;
1557 
1558  return (count < celt) ? S_FALSE : S_OK;
1559 }
1560 
1562 {
1563  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1564 
1565  TRACE("(%p)->(%d)\n", This, celt);
1566 
1567  if (!celt) return S_OK;
1568 
1569  while (celt && find_next_drive(This) == S_OK)
1570  celt--;
1571 
1572  return celt ? S_FALSE : S_OK;
1573 }
1574 
1576 {
1577  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1578 
1579  TRACE("(%p)\n", This);
1580 
1581  This->data.u.drivecoll.cur = -1;
1582  return S_OK;
1583 }
1584 
1586 {
1587  struct enumvariant *This = impl_from_IEnumVARIANT(iface);
1588  TRACE("(%p)->(%p)\n", This, pclone);
1589  return create_drivecoll_enum(This->data.u.drivecoll.coll, (IUnknown**)pclone);
1590 }
1591 
1592 static const IEnumVARIANTVtbl drivecollenumvariantvtbl = {
1600 };
1601 
1603 {
1604  struct enumvariant *This;
1605 
1606  *newenum = NULL;
1607 
1608  This = heap_alloc(sizeof(*This));
1609  if (!This) return E_OUTOFMEMORY;
1610 
1611  This->IEnumVARIANT_iface.lpVtbl = &drivecollenumvariantvtbl;
1612  This->ref = 1;
1613  This->data.u.drivecoll.coll = collection;
1614  This->data.u.drivecoll.cur = -1;
1615  IDriveCollection_AddRef(&collection->IDriveCollection_iface);
1616 
1617  *newenum = (IUnknown*)&This->IEnumVARIANT_iface;
1618 
1619  return S_OK;
1620 }
1621 
1622 static HRESULT WINAPI foldercoll_QueryInterface(IFolderCollection *iface, REFIID riid, void **obj)
1623 {
1625 
1626  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1627 
1628  *obj = NULL;
1629 
1630  if (IsEqualIID( riid, &IID_IFolderCollection ) ||
1631  IsEqualIID( riid, &IID_IDispatch ) ||
1633  {
1634  *obj = &This->IFolderCollection_iface;
1635  }
1636  else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
1637  {
1638  *obj = &This->classinfo.IProvideClassInfo_iface;
1639  }
1640  else
1641  return E_NOINTERFACE;
1642 
1643  IUnknown_AddRef((IUnknown*)*obj);
1644  return S_OK;
1645 }
1646 
1647 static ULONG WINAPI foldercoll_AddRef(IFolderCollection *iface)
1648 {
1651  TRACE("(%p)->(%d)\n", This, ref);
1652  return ref;
1653 }
1654 
1655 static ULONG WINAPI foldercoll_Release(IFolderCollection *iface)
1656 {
1659  TRACE("(%p)->(%d)\n", This, ref);
1660 
1661  if (!ref)
1662  {
1663  SysFreeString(This->path);
1664  heap_free(This);
1665  }
1666 
1667  return ref;
1668 }
1669 
1670 static HRESULT WINAPI foldercoll_GetTypeInfoCount(IFolderCollection *iface, UINT *pctinfo)
1671 {
1673  TRACE("(%p)->(%p)\n", This, pctinfo);
1674  *pctinfo = 1;
1675  return S_OK;
1676 }
1677 
1678 static HRESULT WINAPI foldercoll_GetTypeInfo(IFolderCollection *iface, UINT iTInfo,
1679  LCID lcid, ITypeInfo **ppTInfo)
1680 {
1682  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1683  return get_typeinfo(IFolderCollection_tid, ppTInfo);
1684 }
1685 
1686 static HRESULT WINAPI foldercoll_GetIDsOfNames(IFolderCollection *iface, REFIID riid,
1687  LPOLESTR *rgszNames, UINT cNames,
1688  LCID lcid, DISPID *rgDispId)
1689 {
1692  HRESULT hr;
1693 
1694  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1695 
1697  if(SUCCEEDED(hr))
1698  {
1699  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1700  ITypeInfo_Release(typeinfo);
1701  }
1702 
1703  return hr;
1704 }
1705 
1706 static HRESULT WINAPI foldercoll_Invoke(IFolderCollection *iface, DISPID dispIdMember,
1707  REFIID riid, LCID lcid, WORD wFlags,
1708  DISPPARAMS *pDispParams, VARIANT *pVarResult,
1709  EXCEPINFO *pExcepInfo, UINT *puArgErr)
1710 {
1713  HRESULT hr;
1714 
1715  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1716  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1717 
1719  if(SUCCEEDED(hr))
1720  {
1721  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1722  pDispParams, pVarResult, pExcepInfo, puArgErr);
1723  ITypeInfo_Release(typeinfo);
1724  }
1725 
1726  return hr;
1727 }
1728 
1729 static HRESULT WINAPI foldercoll_Add(IFolderCollection *iface, BSTR name, IFolder **folder)
1730 {
1732  FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(name), folder);
1733  return E_NOTIMPL;
1734 }
1735 
1736 static HRESULT WINAPI foldercoll_get_Item(IFolderCollection *iface, VARIANT key, IFolder **folder)
1737 {
1739  FIXME("(%p)->(%p): stub\n", This, folder);
1740  return E_NOTIMPL;
1741 }
1742 
1743 static HRESULT WINAPI foldercoll_get__NewEnum(IFolderCollection *iface, IUnknown **newenum)
1744 {
1746 
1747  TRACE("(%p)->(%p)\n", This, newenum);
1748 
1749  if(!newenum)
1750  return E_POINTER;
1751 
1752  return create_foldercoll_enum(This, newenum);
1753 }
1754 
1755 static HRESULT WINAPI foldercoll_get_Count(IFolderCollection *iface, LONG *count)
1756 {
1758  static const WCHAR allW[] = {'\\','*',0};
1760  WCHAR pathW[MAX_PATH];
1761  HANDLE handle;
1762 
1763  TRACE("(%p)->(%p)\n", This, count);
1764 
1765  if(!count)
1766  return E_POINTER;
1767 
1768  *count = 0;
1769 
1770  lstrcpyW(pathW, This->path);
1771  lstrcatW(pathW, allW);
1772  handle = FindFirstFileW(pathW, &data);
1774  return HRESULT_FROM_WIN32(GetLastError());
1775 
1776  do
1777  {
1778  if (is_dir_data(&data))
1779  *count += 1;
1780  } while (FindNextFileW(handle, &data));
1781  FindClose(handle);
1782 
1783  return S_OK;
1784 }
1785 
1786 static const IFolderCollectionVtbl foldercollvtbl = {
1798 };
1799 
1800 static HRESULT create_foldercoll(BSTR path, IFolderCollection **folders)
1801 {
1802  struct foldercollection *This;
1803 
1804  *folders = NULL;
1805 
1806  This = heap_alloc(sizeof(struct foldercollection));
1807  if (!This) return E_OUTOFMEMORY;
1808 
1809  This->IFolderCollection_iface.lpVtbl = &foldercollvtbl;
1810  This->ref = 1;
1811  This->path = SysAllocString(path);
1812  if (!This->path)
1813  {
1814  heap_free(This);
1815  return E_OUTOFMEMORY;
1816  }
1817 
1818  init_classinfo(&CLSID_Folders, (IUnknown *)&This->IFolderCollection_iface, &This->classinfo);
1819  *folders = &This->IFolderCollection_iface;
1820 
1821  return S_OK;
1822 }
1823 
1824 static HRESULT WINAPI filecoll_QueryInterface(IFileCollection *iface, REFIID riid, void **obj)
1825 {
1827 
1828  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1829 
1830  *obj = NULL;
1831 
1832  if (IsEqualIID( riid, &IID_IFileCollection ) ||
1833  IsEqualIID( riid, &IID_IDispatch ) ||
1835  {
1836  *obj = &This->IFileCollection_iface;
1837  }
1838  else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
1839  {
1840  *obj = &This->classinfo.IProvideClassInfo_iface;
1841  }
1842  else
1843  return E_NOINTERFACE;
1844 
1845  IUnknown_AddRef((IUnknown*)*obj);
1846  return S_OK;
1847 }
1848 
1849 static ULONG WINAPI filecoll_AddRef(IFileCollection *iface)
1850 {
1853  TRACE("(%p)->(%d)\n", This, ref);
1854  return ref;
1855 }
1856 
1857 static ULONG WINAPI filecoll_Release(IFileCollection *iface)
1858 {
1861  TRACE("(%p)->(%d)\n", This, ref);
1862 
1863  if (!ref)
1864  {
1865  SysFreeString(This->path);
1866  heap_free(This);
1867  }
1868 
1869  return ref;
1870 }
1871 
1872 static HRESULT WINAPI filecoll_GetTypeInfoCount(IFileCollection *iface, UINT *pctinfo)
1873 {
1875  TRACE("(%p)->(%p)\n", This, pctinfo);
1876  *pctinfo = 1;
1877  return S_OK;
1878 }
1879 
1880 static HRESULT WINAPI filecoll_GetTypeInfo(IFileCollection *iface, UINT iTInfo,
1881  LCID lcid, ITypeInfo **ppTInfo)
1882 {
1884  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1885  return get_typeinfo(IFileCollection_tid, ppTInfo);
1886 }
1887 
1888 static HRESULT WINAPI filecoll_GetIDsOfNames(IFileCollection *iface, REFIID riid,
1889  LPOLESTR *rgszNames, UINT cNames,
1890  LCID lcid, DISPID *rgDispId)
1891 {
1894  HRESULT hr;
1895 
1896  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1897 
1899  if(SUCCEEDED(hr))
1900  {
1901  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1902  ITypeInfo_Release(typeinfo);
1903  }
1904 
1905  return hr;
1906 }
1907 
1908 static HRESULT WINAPI filecoll_Invoke(IFileCollection *iface, DISPID dispIdMember,
1909  REFIID riid, LCID lcid, WORD wFlags,
1910  DISPPARAMS *pDispParams, VARIANT *pVarResult,
1911  EXCEPINFO *pExcepInfo, UINT *puArgErr)
1912 {
1915  HRESULT hr;
1916 
1917  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1918  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1919 
1921  if(SUCCEEDED(hr))
1922  {
1923  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1924  pDispParams, pVarResult, pExcepInfo, puArgErr);
1925  ITypeInfo_Release(typeinfo);
1926  }
1927 
1928  return hr;
1929 }
1930 
1931 static HRESULT WINAPI filecoll_get_Item(IFileCollection *iface, VARIANT Key, IFile **file)
1932 {
1934  FIXME("(%p)->(%p)\n", This, file);
1935  return E_NOTIMPL;
1936 }
1937 
1938 static HRESULT WINAPI filecoll_get__NewEnum(IFileCollection *iface, IUnknown **ppenum)
1939 {
1941 
1942  TRACE("(%p)->(%p)\n", This, ppenum);
1943 
1944  if(!ppenum)
1945  return E_POINTER;
1946 
1947  return create_filecoll_enum(This, ppenum);
1948 }
1949 
1950 static HRESULT WINAPI filecoll_get_Count(IFileCollection *iface, LONG *count)
1951 {
1953  static const WCHAR allW[] = {'\\','*',0};
1955  WCHAR pathW[MAX_PATH];
1956  HANDLE handle;
1957 
1958  TRACE("(%p)->(%p)\n", This, count);
1959 
1960  if(!count)
1961  return E_POINTER;
1962 
1963  *count = 0;
1964 
1965  lstrcpyW(pathW, This->path);
1966  lstrcatW(pathW, allW);
1967  handle = FindFirstFileW(pathW, &data);
1969  return HRESULT_FROM_WIN32(GetLastError());
1970 
1971  do
1972  {
1973  if (is_file_data(&data))
1974  *count += 1;
1975  } while (FindNextFileW(handle, &data));
1976  FindClose(handle);
1977 
1978  return S_OK;
1979 }
1980 
1981 static const IFileCollectionVtbl filecollectionvtbl = {
1992 };
1993 
1994 static HRESULT create_filecoll(BSTR path, IFileCollection **files)
1995 {
1996  struct filecollection *This;
1997 
1998  *files = NULL;
1999 
2000  This = heap_alloc(sizeof(*This));
2001  if (!This) return E_OUTOFMEMORY;
2002 
2003  This->IFileCollection_iface.lpVtbl = &filecollectionvtbl;
2004  This->ref = 1;
2005  This->path = SysAllocString(path);
2006  if (!This->path)
2007  {
2008  heap_free(This);
2009  return E_OUTOFMEMORY;
2010  }
2011 
2012  init_classinfo(&CLSID_Files, (IUnknown *)&This->IFileCollection_iface, &This->classinfo);
2013  *files = &This->IFileCollection_iface;
2014  return S_OK;
2015 }
2016 
2017 static HRESULT WINAPI drivecoll_QueryInterface(IDriveCollection *iface, REFIID riid, void **obj)
2018 {
2020 
2021  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2022 
2023  *obj = NULL;
2024 
2025  if (IsEqualIID( riid, &IID_IDriveCollection ) ||
2026  IsEqualIID( riid, &IID_IDispatch ) ||
2028  {
2029  *obj = &This->IDriveCollection_iface;
2030  }
2031  else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
2032  {
2033  *obj = &This->classinfo.IProvideClassInfo_iface;
2034  }
2035  else
2036  return E_NOINTERFACE;
2037 
2038  IUnknown_AddRef((IUnknown*)*obj);
2039  return S_OK;
2040 }
2041 
2042 static ULONG WINAPI drivecoll_AddRef(IDriveCollection *iface)
2043 {
2046  TRACE("(%p)->(%d)\n", This, ref);
2047  return ref;
2048 }
2049 
2050 static ULONG WINAPI drivecoll_Release(IDriveCollection *iface)
2051 {
2054  TRACE("(%p)->(%d)\n", This, ref);
2055 
2056  if (!ref)
2057  heap_free(This);
2058 
2059  return ref;
2060 }
2061 
2062 static HRESULT WINAPI drivecoll_GetTypeInfoCount(IDriveCollection *iface, UINT *pctinfo)
2063 {
2065  TRACE("(%p)->(%p)\n", This, pctinfo);
2066  *pctinfo = 1;
2067  return S_OK;
2068 }
2069 
2070 static HRESULT WINAPI drivecoll_GetTypeInfo(IDriveCollection *iface, UINT iTInfo,
2071  LCID lcid, ITypeInfo **ppTInfo)
2072 {
2074  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2075  return get_typeinfo(IDriveCollection_tid, ppTInfo);
2076 }
2077 
2078 static HRESULT WINAPI drivecoll_GetIDsOfNames(IDriveCollection *iface, REFIID riid,
2079  LPOLESTR *rgszNames, UINT cNames,
2080  LCID lcid, DISPID *rgDispId)
2081 {
2084  HRESULT hr;
2085 
2086  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
2087 
2089  if(SUCCEEDED(hr))
2090  {
2091  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2092  ITypeInfo_Release(typeinfo);
2093  }
2094 
2095  return hr;
2096 }
2097 
2098 static HRESULT WINAPI drivecoll_Invoke(IDriveCollection *iface, DISPID dispIdMember,
2099  REFIID riid, LCID lcid, WORD wFlags,
2100  DISPPARAMS *pDispParams, VARIANT *pVarResult,
2101  EXCEPINFO *pExcepInfo, UINT *puArgErr)
2102 {
2105  HRESULT hr;
2106 
2107  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2108  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2109 
2111  if(SUCCEEDED(hr))
2112  {
2113  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
2114  pDispParams, pVarResult, pExcepInfo, puArgErr);
2115  ITypeInfo_Release(typeinfo);
2116  }
2117 
2118  return hr;
2119 }
2120 
2121 static HRESULT WINAPI drivecoll_get_Item(IDriveCollection *iface, VARIANT key, IDrive **drive)
2122 {
2124  FIXME("(%p)->(%p): stub\n", This, drive);
2125  return E_NOTIMPL;
2126 }
2127 
2128 static HRESULT WINAPI drivecoll_get__NewEnum(IDriveCollection *iface, IUnknown **ppenum)
2129 {
2131 
2132  TRACE("(%p)->(%p)\n", This, ppenum);
2133 
2134  if(!ppenum)
2135  return E_POINTER;
2136 
2137  return create_drivecoll_enum(This, ppenum);
2138 }
2139 
2140 static HRESULT WINAPI drivecoll_get_Count(IDriveCollection *iface, LONG *count)
2141 {
2143 
2144  TRACE("(%p)->(%p)\n", This, count);
2145 
2146  if (!count) return E_POINTER;
2147 
2148  *count = This->count;
2149  return S_OK;
2150 }
2151 
2152 static const IDriveCollectionVtbl drivecollectionvtbl = {
2163 };
2164 
2165 static HRESULT create_drivecoll(IDriveCollection **drives)
2166 {
2167  struct drivecollection *This;
2168  DWORD mask;
2169 
2170  *drives = NULL;
2171 
2172  This = heap_alloc(sizeof(*This));
2173  if (!This) return E_OUTOFMEMORY;
2174 
2175  This->IDriveCollection_iface.lpVtbl = &drivecollectionvtbl;
2176  This->ref = 1;
2177  This->drives = mask = GetLogicalDrives();
2178  /* count set bits */
2179  for (This->count = 0; mask; This->count++)
2180  mask &= mask - 1;
2181 
2182  init_classinfo(&CLSID_Drives, (IUnknown *)&This->IDriveCollection_iface, &This->classinfo);
2183  *drives = &This->IDriveCollection_iface;
2184  return S_OK;
2185 }
2186 
2187 static HRESULT WINAPI folder_QueryInterface(IFolder *iface, REFIID riid, void **obj)
2188 {
2189  struct folder *This = impl_from_IFolder(iface);
2190 
2191  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2192 
2193  *obj = NULL;
2194 
2195  if (IsEqualIID( riid, &IID_IFolder ) ||
2196  IsEqualIID( riid, &IID_IDispatch ) ||
2198  {
2199  *obj = &This->IFolder_iface;
2200  }
2201  else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
2202  {
2203  *obj = &This->classinfo.IProvideClassInfo_iface;
2204  }
2205  else
2206  return E_NOINTERFACE;
2207 
2208  IUnknown_AddRef((IUnknown*)*obj);
2209  return S_OK;
2210 }
2211 
2212 static ULONG WINAPI folder_AddRef(IFolder *iface)
2213 {
2214  struct folder *This = impl_from_IFolder(iface);
2216  TRACE("(%p)->(%d)\n", This, ref);
2217  return ref;
2218 }
2219 
2220 static ULONG WINAPI folder_Release(IFolder *iface)
2221 {
2222  struct folder *This = impl_from_IFolder(iface);
2224  TRACE("(%p)->(%d)\n", This, ref);
2225 
2226  if (!ref)
2227  {
2228  SysFreeString(This->path);
2229  heap_free(This);
2230  }
2231 
2232  return ref;
2233 }
2234 
2235 static HRESULT WINAPI folder_GetTypeInfoCount(IFolder *iface, UINT *pctinfo)
2236 {
2237  struct folder *This = impl_from_IFolder(iface);
2238  TRACE("(%p)->(%p)\n", This, pctinfo);
2239  *pctinfo = 1;
2240  return S_OK;
2241 }
2242 
2243 static HRESULT WINAPI folder_GetTypeInfo(IFolder *iface, UINT iTInfo,
2244  LCID lcid, ITypeInfo **ppTInfo)
2245 {
2246  struct folder *This = impl_from_IFolder(iface);
2247  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2248  return get_typeinfo(IFolder_tid, ppTInfo);
2249 }
2250 
2252  LPOLESTR *rgszNames, UINT cNames,
2253  LCID lcid, DISPID *rgDispId)
2254 {
2255  struct folder *This = impl_from_IFolder(iface);
2257  HRESULT hr;
2258 
2259  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
2260 
2262  if(SUCCEEDED(hr))
2263  {
2264  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2265  ITypeInfo_Release(typeinfo);
2266  }
2267 
2268  return hr;
2269 }
2270 
2271 static HRESULT WINAPI folder_Invoke(IFolder *iface, DISPID dispIdMember,
2272  REFIID riid, LCID lcid, WORD wFlags,
2273  DISPPARAMS *pDispParams, VARIANT *pVarResult,
2274  EXCEPINFO *pExcepInfo, UINT *puArgErr)
2275 {
2276  struct folder *This = impl_from_IFolder(iface);
2278  HRESULT hr;
2279 
2280  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2281  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2282 
2284  if(SUCCEEDED(hr))
2285  {
2286  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
2287  pDispParams, pVarResult, pExcepInfo, puArgErr);
2288  ITypeInfo_Release(typeinfo);
2289  }
2290 
2291  return hr;
2292 }
2293 
2294 static HRESULT WINAPI folder_get_Path(IFolder *iface, BSTR *path)
2295 {
2296  struct folder *This = impl_from_IFolder(iface);
2297 
2298  TRACE("(%p)->(%p)\n", This, path);
2299 
2300  if(!path)
2301  return E_POINTER;
2302 
2303  *path = SysAllocString(This->path);
2304  return *path ? S_OK : E_OUTOFMEMORY;
2305 }
2306 
2307 static HRESULT WINAPI folder_get_Name(IFolder *iface, BSTR *name)
2308 {
2309  struct folder *This = impl_from_IFolder(iface);
2310  WCHAR *ptr;
2311 
2312  TRACE("(%p)->(%p)\n", This, name);
2313 
2314  if(!name)
2315  return E_POINTER;
2316 
2317  *name = NULL;
2318 
2319  ptr = wcsrchr(This->path, '\\');
2320  if (ptr)
2321  {
2322  *name = SysAllocString(ptr+1);
2323  TRACE("%s\n", debugstr_w(*name));
2324  if (!*name) return E_OUTOFMEMORY;
2325  }
2326  else
2327  return E_FAIL;
2328 
2329  return S_OK;
2330 }
2331 
2332 static HRESULT WINAPI folder_put_Name(IFolder *iface, BSTR name)
2333 {
2334  struct folder *This = impl_from_IFolder(iface);
2335  FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
2336  return E_NOTIMPL;
2337 }
2338 
2339 static HRESULT WINAPI folder_get_ShortPath(IFolder *iface, BSTR *path)
2340 {
2341  struct folder *This = impl_from_IFolder(iface);
2342  FIXME("(%p)->(%p): stub\n", This, path);
2343  return E_NOTIMPL;
2344 }
2345 
2346 static HRESULT WINAPI folder_get_ShortName(IFolder *iface, BSTR *name)
2347 {
2348  struct folder *This = impl_from_IFolder(iface);
2349  FIXME("(%p)->(%p): stub\n", This, name);
2350  return E_NOTIMPL;
2351 }
2352 
2353 static HRESULT WINAPI folder_get_Drive(IFolder *iface, IDrive **drive)
2354 {
2355  struct folder *This = impl_from_IFolder(iface);
2356  FIXME("(%p)->(%p): stub\n", This, drive);
2357  return E_NOTIMPL;
2358 }
2359 
2360 static HRESULT WINAPI folder_get_ParentFolder(IFolder *iface, IFolder **parent)
2361 {
2362  struct folder *This = impl_from_IFolder(iface);
2363  FIXME("(%p)->(%p): stub\n", This, parent);
2364  return E_NOTIMPL;
2365 }
2366 
2368 {
2369  struct folder *This = impl_from_IFolder(iface);
2370  FIXME("(%p)->(%p): stub\n", This, attr);
2371  return E_NOTIMPL;
2372 }
2373 
2375 {
2376  struct folder *This = impl_from_IFolder(iface);
2377  FIXME("(%p)->(0x%x): stub\n", This, attr);
2378  return E_NOTIMPL;
2379 }
2380 
2382 {
2383  struct folder *This = impl_from_IFolder(iface);
2384  FIXME("(%p)->(%p): stub\n", This, date);
2385  return E_NOTIMPL;
2386 }
2387 
2389 {
2390  struct folder *This = impl_from_IFolder(iface);
2391  FIXME("(%p)->(%p): stub\n", This, date);
2392  return E_NOTIMPL;
2393 }
2394 
2396 {
2397  struct folder *This = impl_from_IFolder(iface);
2398  FIXME("(%p)->(%p): stub\n", This, date);
2399  return E_NOTIMPL;
2400 }
2401 
2402 static HRESULT WINAPI folder_get_Type(IFolder *iface, BSTR *type)
2403 {
2404  struct folder *This = impl_from_IFolder(iface);
2405  FIXME("(%p)->(%p): stub\n", This, type);
2406  return E_NOTIMPL;
2407 }
2408 
2409 static HRESULT WINAPI folder_Delete(IFolder *iface, VARIANT_BOOL force)
2410 {
2411  struct folder *This = impl_from_IFolder(iface);
2412  FIXME("(%p)->(%x): stub\n", This, force);
2413  return E_NOTIMPL;
2414 }
2415 
2416 static HRESULT WINAPI folder_Copy(IFolder *iface, BSTR dest, VARIANT_BOOL overwrite)
2417 {
2418  struct folder *This = impl_from_IFolder(iface);
2419  FIXME("(%p)->(%s %x): stub\n", This, debugstr_w(dest), overwrite);
2420  return E_NOTIMPL;
2421 }
2422 
2423 static HRESULT WINAPI folder_Move(IFolder *iface, BSTR dest)
2424 {
2425  struct folder *This = impl_from_IFolder(iface);
2426  FIXME("(%p)->(%s): stub\n", This, debugstr_w(dest));
2427  return E_NOTIMPL;
2428 }
2429 
2430 static HRESULT WINAPI folder_get_IsRootFolder(IFolder *iface, VARIANT_BOOL *isroot)
2431 {
2432  struct folder *This = impl_from_IFolder(iface);
2433  FIXME("(%p)->(%p): stub\n", This, isroot);
2434  return E_NOTIMPL;
2435 }
2436 
2437 static HRESULT WINAPI folder_get_Size(IFolder *iface, VARIANT *size)
2438 {
2439  struct folder *This = impl_from_IFolder(iface);
2440  FIXME("(%p)->(%p): stub\n", This, size);
2441  return E_NOTIMPL;
2442 }
2443 
2444 static HRESULT WINAPI folder_get_SubFolders(IFolder *iface, IFolderCollection **folders)
2445 {
2446  struct folder *This = impl_from_IFolder(iface);
2447 
2448  TRACE("(%p)->(%p)\n", This, folders);
2449 
2450  if(!folders)
2451  return E_POINTER;
2452 
2453  return create_foldercoll(This->path, folders);
2454 }
2455 
2456 static HRESULT WINAPI folder_get_Files(IFolder *iface, IFileCollection **files)
2457 {
2458  struct folder *This = impl_from_IFolder(iface);
2459 
2460  TRACE("(%p)->(%p)\n", This, files);
2461 
2462  if(!files)
2463  return E_POINTER;
2464 
2465  return create_filecoll(This->path, files);
2466 }
2467 
2468 static HRESULT WINAPI folder_CreateTextFile(IFolder *iface, BSTR filename, VARIANT_BOOL overwrite,
2469  VARIANT_BOOL unicode, ITextStream **stream)
2470 {
2471  struct folder *This = impl_from_IFolder(iface);
2472  FIXME("(%p)->(%s %x %x %p): stub\n", This, debugstr_w(filename), overwrite, unicode, stream);
2473  return E_NOTIMPL;
2474 }
2475 
2476 static const IFolderVtbl foldervtbl = {
2478  folder_AddRef,
2483  folder_Invoke,
2497  folder_Delete,
2498  folder_Copy,
2499  folder_Move,
2505 };
2506 
2508 {
2509  struct folder *This;
2510 
2511  *folder = NULL;
2512 
2513  TRACE("%s\n", debugstr_w(path));
2514 
2515  This = heap_alloc(sizeof(struct folder));
2516  if (!This) return E_OUTOFMEMORY;
2517 
2518  This->IFolder_iface.lpVtbl = &foldervtbl;
2519  This->ref = 1;
2520  This->path = SysAllocString(path);
2521  if (!This->path)
2522  {
2523  heap_free(This);
2524  return E_OUTOFMEMORY;
2525  }
2526 
2527  init_classinfo(&CLSID_Folder, (IUnknown *)&This->IFolder_iface, &This->classinfo);
2528  *folder = &This->IFolder_iface;
2529 
2530  return S_OK;
2531 }
2532 
2533 static HRESULT WINAPI file_QueryInterface(IFile *iface, REFIID riid, void **obj)
2534 {
2535  struct file *This = impl_from_IFile(iface);
2536 
2537  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2538 
2539  *obj = NULL;
2540 
2541  if (IsEqualIID(riid, &IID_IFile) ||
2544  {
2545  *obj = &This->IFile_iface;
2546  }
2547  else if (IsEqualIID( riid, &IID_IProvideClassInfo ))
2548  {
2549  *obj = &This->classinfo.IProvideClassInfo_iface;
2550  }
2551  else
2552  return E_NOINTERFACE;
2553 
2554  IUnknown_AddRef((IUnknown*)*obj);
2555  return S_OK;
2556 }
2557 
2558 static ULONG WINAPI file_AddRef(IFile *iface)
2559 {
2560  struct file *This = impl_from_IFile(iface);
2561  LONG ref = InterlockedIncrement(&This->ref);
2562 
2563  TRACE("(%p) ref=%d\n", This, ref);
2564 
2565  return ref;
2566 }
2567 
2568 static ULONG WINAPI file_Release(IFile *iface)
2569 {
2570  struct file *This = impl_from_IFile(iface);
2571  LONG ref = InterlockedDecrement(&This->ref);
2572 
2573  TRACE("(%p) ref=%d\n", This, ref);
2574 
2575  if(!ref)
2576  {
2577  heap_free(This->path);
2578  heap_free(This);
2579  }
2580 
2581  return ref;
2582 }
2583 
2584 static HRESULT WINAPI file_GetTypeInfoCount(IFile *iface, UINT *pctinfo)
2585 {
2586  struct file *This = impl_from_IFile(iface);
2587 
2588  TRACE("(%p)->(%p)\n", This, pctinfo);
2589 
2590  *pctinfo = 1;
2591  return S_OK;
2592 }
2593 
2594 static HRESULT WINAPI file_GetTypeInfo(IFile *iface,
2595  UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
2596 {
2597  struct file *This = impl_from_IFile(iface);
2598 
2599  TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2600 
2601  return get_typeinfo(IFile_tid, ppTInfo);
2602 }
2603 
2605  LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2606 {
2607  struct file *This = impl_from_IFile(iface);
2609  HRESULT hr;
2610 
2611  TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
2612  rgszNames, cNames, lcid, rgDispId);
2613 
2615  if(SUCCEEDED(hr)) {
2616  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2617  ITypeInfo_Release(typeinfo);
2618  }
2619  return hr;
2620 }
2621 
2622 static HRESULT WINAPI file_Invoke(IFile *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2623 {
2624  struct file *This = impl_from_IFile(iface);
2626  HRESULT hr;
2627 
2628  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2629  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2630 
2632  if(SUCCEEDED(hr))
2633  {
2634  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
2635  pDispParams, pVarResult, pExcepInfo, puArgErr);
2636  ITypeInfo_Release(typeinfo);
2637  }
2638  return hr;
2639 }
2640 
2641 static HRESULT WINAPI file_get_Path(IFile *iface, BSTR *path)
2642 {
2643  struct file *This = impl_from_IFile(iface);
2644 
2645  TRACE("(%p)->(%p)\n", This, path);
2646 
2647  if (!path)
2648  return E_POINTER;
2649 
2650  *path = SysAllocString(This->path);
2651  if (!*path)
2652  return E_OUTOFMEMORY;
2653 
2654  return S_OK;
2655 }
2656 
2657 static HRESULT WINAPI file_get_Name(IFile *iface, BSTR *name)
2658 {
2659  struct file *This = impl_from_IFile(iface);
2660  WCHAR *ptr;
2661 
2662  TRACE("(%p)->(%p)\n", This, name);
2663 
2664  if(!name)
2665  return E_POINTER;
2666 
2667  *name = NULL;
2668 
2669  ptr = wcsrchr(This->path, '\\');
2670  if (ptr)
2671  {
2672  *name = SysAllocString(ptr+1);
2673  TRACE("%s\n", debugstr_w(*name));
2674  if (!*name) return E_OUTOFMEMORY;
2675  }
2676  else
2677  return E_FAIL;
2678 
2679  return S_OK;
2680 }
2681 
2682 static HRESULT WINAPI file_put_Name(IFile *iface, BSTR pbstrName)
2683 {
2684  struct file *This = impl_from_IFile(iface);
2685  FIXME("(%p)->(%s)\n", This, debugstr_w(pbstrName));
2686  return E_NOTIMPL;
2687 }
2688 
2689 static HRESULT WINAPI file_get_ShortPath(IFile *iface, BSTR *pbstrPath)
2690 {
2691  struct file *This = impl_from_IFile(iface);
2692  FIXME("(%p)->(%p)\n", This, pbstrPath);
2693  return E_NOTIMPL;
2694 }
2695 
2696 static HRESULT WINAPI file_get_ShortName(IFile *iface, BSTR *pbstrName)
2697 {
2698  struct file *This = impl_from_IFile(iface);
2699  FIXME("(%p)->(%p)\n", This, pbstrName);
2700  return E_NOTIMPL;
2701 }
2702 
2703 static HRESULT WINAPI file_get_Drive(IFile *iface, IDrive **ppdrive)
2704 {
2705  struct file *This = impl_from_IFile(iface);
2706  FIXME("(%p)->(%p)\n", This, ppdrive);
2707  return E_NOTIMPL;
2708 }
2709 
2710 static HRESULT WINAPI file_get_ParentFolder(IFile *iface, IFolder **ppfolder)
2711 {
2712  struct file *This = impl_from_IFile(iface);
2713  FIXME("(%p)->(%p)\n", This, ppfolder);
2714  return E_NOTIMPL;
2715 }
2716 
2718 {
2719  struct file *This = impl_from_IFile(iface);
2720  DWORD fa;
2721 
2722  TRACE("(%p)->(%p)\n", This, pfa);
2723 
2724  if(!pfa)
2725  return E_POINTER;
2726 
2727  fa = GetFileAttributesW(This->path);
2729  return create_error(GetLastError());
2730 
2734  return S_OK;
2735 }
2736 
2738 {
2739  struct file *This = impl_from_IFile(iface);
2740 
2741  TRACE("(%p)->(%x)\n", This, pfa);
2742 
2743  return SetFileAttributesW(This->path, pfa) ? S_OK : create_error(GetLastError());
2744 }
2745 
2747 {
2748  FILETIME ftlocal;
2749  SYSTEMTIME st;
2750 
2751  if (!date)
2752  return E_POINTER;
2753 
2754  FileTimeToLocalFileTime(ft, &ftlocal);
2755  FileTimeToSystemTime(&ftlocal, &st);
2757 
2758  return S_OK;
2759 }
2760 
2761 static HRESULT WINAPI file_get_DateCreated(IFile *iface, DATE *pdate)
2762 {
2763  struct file *This = impl_from_IFile(iface);
2764  FIXME("(%p)->(%p)\n", This, pdate);
2765  return E_NOTIMPL;
2766 }
2767 
2769 {
2770  struct file *This = impl_from_IFile(iface);
2772 
2773  TRACE("(%p)->(%p)\n", This, date);
2774 
2775  if (GetFileAttributesExW(This->path, GetFileExInfoStandard, &attrs))
2777 
2778  return E_FAIL;
2779 }
2780 
2781 static HRESULT WINAPI file_get_DateLastAccessed(IFile *iface, DATE *pdate)
2782 {
2783  struct file *This = impl_from_IFile(iface);
2784  FIXME("(%p)->(%p)\n", This, pdate);
2785  return E_NOTIMPL;
2786 }
2787 
2788 static HRESULT WINAPI file_get_Size(IFile *iface, VARIANT *pvarSize)
2789 {
2790  struct file *This = impl_from_IFile(iface);
2793  HANDLE f;
2794 
2795  TRACE("(%p)->(%p)\n", This, pvarSize);
2796 
2797  if(!pvarSize)
2798  return E_POINTER;
2799 
2800  f = FindFirstFileW(This->path, &fd);
2801  if(f == INVALID_HANDLE_VALUE)
2802  return create_error(GetLastError());
2803  FindClose(f);
2804 
2805  size.u.LowPart = fd.nFileSizeLow;
2806  size.u.HighPart = fd.nFileSizeHigh;
2807 
2808  return variant_from_largeint(&size, pvarSize);
2809 }
2810 
2811 static HRESULT WINAPI file_get_Type(IFile *iface, BSTR *pbstrType)
2812 {
2813  struct file *This = impl_from_IFile(iface);
2814  FIXME("(%p)->(%p)\n", This, pbstrType);
2815  return E_NOTIMPL;
2816 }
2817 
2819 {
2820  struct file *This = impl_from_IFile(iface);
2821  FIXME("(%p)->(%x)\n", This, Force);
2822  return E_NOTIMPL;
2823 }
2824 
2825 static HRESULT WINAPI file_Copy(IFile *iface, BSTR Destination, VARIANT_BOOL OverWriteFiles)
2826 {
2827  struct file *This = impl_from_IFile(iface);
2828  FIXME("(%p)->(%s %x)\n", This, debugstr_w(Destination), OverWriteFiles);
2829  return E_NOTIMPL;
2830 }
2831 
2832 static HRESULT WINAPI file_Move(IFile *iface, BSTR Destination)
2833 {
2834  struct file *This = impl_from_IFile(iface);
2835  FIXME("(%p)->(%s)\n", This, debugstr_w(Destination));
2836  return E_NOTIMPL;
2837 }
2838 
2839 static HRESULT WINAPI file_OpenAsTextStream(IFile *iface, IOMode mode, Tristate format, ITextStream **stream)
2840 {
2841  struct file *This = impl_from_IFile(iface);
2842 
2843  TRACE("(%p)->(%d %d %p)\n", This, mode, format, stream);
2844 
2846 }
2847 
2848 static const IFileVtbl file_vtbl = {
2850  file_AddRef,
2851  file_Release,
2855  file_Invoke,
2856  file_get_Path,
2857  file_get_Name,
2858  file_put_Name,
2868  file_get_Size,
2869  file_get_Type,
2870  file_Delete,
2871  file_Copy,
2872  file_Move,
2874 };
2875 
2877 {
2878  struct file *f;
2879  DWORD len, attrs;
2880 
2881  *file = NULL;
2882 
2883  f = heap_alloc(sizeof(struct file));
2884  if(!f)
2885  return E_OUTOFMEMORY;
2886 
2887  f->IFile_iface.lpVtbl = &file_vtbl;
2888  f->ref = 1;
2889 
2890  len = GetFullPathNameW(path, 0, NULL, NULL);
2891  if(!len) {
2892  heap_free(f);
2893  return E_FAIL;
2894  }
2895 
2896  f->path = heap_alloc(len*sizeof(WCHAR));
2897  if(!f->path) {
2898  heap_free(f);
2899  return E_OUTOFMEMORY;
2900  }
2901 
2902  if(!GetFullPathNameW(path, len, f->path, NULL)) {
2903  heap_free(f->path);
2904  heap_free(f);
2905  return E_FAIL;
2906  }
2907 
2908  attrs = GetFileAttributesW(f->path);
2909  if(attrs==INVALID_FILE_ATTRIBUTES ||
2911  heap_free(f->path);
2912  heap_free(f);
2913  return create_error(GetLastError());
2914  }
2915 
2916  init_classinfo(&CLSID_File, (IUnknown *)&f->IFile_iface, &f->classinfo);
2917  *file = &f->IFile_iface;
2918  return S_OK;
2919 }
2920 
2921 static HRESULT WINAPI filesys_QueryInterface(IFileSystem3 *iface, REFIID riid, void **ppvObject)
2922 {
2923  struct filesystem *This = impl_from_IFileSystem3(iface);
2924 
2925  TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
2926 
2927  if ( IsEqualGUID( riid, &IID_IFileSystem3 ) ||
2928  IsEqualGUID( riid, &IID_IFileSystem ) ||
2931  {
2932  *ppvObject = &This->IFileSystem3_iface;
2933  }
2934  else if (IsEqualGUID( riid, &IID_IProvideClassInfo ))
2935  {
2936  *ppvObject = &This->classinfo.IProvideClassInfo_iface;
2937  }
2938  else if ( IsEqualGUID( riid, &IID_IDispatchEx ))
2939  {
2940  TRACE("Interface IDispatchEx not supported - returning NULL\n");
2941  *ppvObject = NULL;
2942  return E_NOINTERFACE;
2943  }
2944  else if ( IsEqualGUID( riid, &IID_IObjectWithSite ))
2945  {
2946  TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2947  *ppvObject = NULL;
2948  return E_NOINTERFACE;
2949  }
2950  else
2951  {
2952  FIXME("Unsupported interface %s\n", debugstr_guid(riid));
2953  return E_NOINTERFACE;
2954  }
2955 
2956  IUnknown_AddRef((IUnknown*)*ppvObject);
2957 
2958  return S_OK;
2959 }
2960 
2961 static ULONG WINAPI filesys_AddRef(IFileSystem3 *iface)
2962 {
2963  TRACE("%p\n", iface);
2964 
2965  return 2;
2966 }
2967 
2968 static ULONG WINAPI filesys_Release(IFileSystem3 *iface)
2969 {
2970  TRACE("%p\n", iface);
2971 
2972  return 1;
2973 }
2974 
2975 static HRESULT WINAPI filesys_GetTypeInfoCount(IFileSystem3 *iface, UINT *pctinfo)
2976 {
2977  TRACE("(%p)->(%p)\n", iface, pctinfo);
2978 
2979  *pctinfo = 1;
2980  return S_OK;
2981 }
2982 
2983 static HRESULT WINAPI filesys_GetTypeInfo(IFileSystem3 *iface, UINT iTInfo,
2984  LCID lcid, ITypeInfo **ppTInfo)
2985 {
2986  TRACE("(%p)->(%u %u %p)\n", iface, iTInfo, lcid, ppTInfo);
2987  return get_typeinfo(IFileSystem3_tid, ppTInfo);
2988 }
2989 
2990 static HRESULT WINAPI filesys_GetIDsOfNames(IFileSystem3 *iface, REFIID riid,
2991  LPOLESTR *rgszNames, UINT cNames,
2992  LCID lcid, DISPID *rgDispId)
2993 {
2995  HRESULT hr;
2996 
2997  TRACE("(%p)->(%s %p %u %u %p)\n", iface, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
2998 
3000  if(SUCCEEDED(hr))
3001  {
3002  hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
3003  ITypeInfo_Release(typeinfo);
3004  }
3005 
3006  return hr;
3007 }
3008 
3009 static HRESULT WINAPI filesys_Invoke(IFileSystem3 *iface, DISPID dispIdMember,
3010  REFIID riid, LCID lcid, WORD wFlags,
3011  DISPPARAMS *pDispParams, VARIANT *pVarResult,
3012  EXCEPINFO *pExcepInfo, UINT *puArgErr)
3013 {
3015  HRESULT hr;
3016 
3017  TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface, dispIdMember, debugstr_guid(riid),
3018  lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3019 
3021  if(SUCCEEDED(hr))
3022  {
3023  hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
3024  pDispParams, pVarResult, pExcepInfo, puArgErr);
3025  ITypeInfo_Release(typeinfo);
3026  }
3027 
3028  return hr;
3029 }
3030 
3031 static HRESULT WINAPI filesys_get_Drives(IFileSystem3 *iface, IDriveCollection **ppdrives)
3032 {
3033  TRACE("%p %p\n", iface, ppdrives);
3034  return create_drivecoll(ppdrives);
3035 }
3036 
3037 static HRESULT WINAPI filesys_BuildPath(IFileSystem3 *iface, BSTR Path,
3038  BSTR Name, BSTR *Result)
3039 {
3040  BSTR ret;
3041 
3042  TRACE("%p %s %s %p\n", iface, debugstr_w(Path), debugstr_w(Name), Result);
3043 
3044  if (!Result) return E_POINTER;
3045 
3046  if (Path && Name)
3047  {
3048  int path_len = SysStringLen(Path), name_len = SysStringLen(Name);
3049 
3050  /* if both parts have backslashes strip one from Path */
3051  if (Path[path_len-1] == '\\' && Name[0] == '\\')
3052  {
3053  path_len -= 1;
3054 
3055  ret = SysAllocStringLen(NULL, path_len + name_len);
3056  if (ret)
3057  {
3058  lstrcpyW(ret, Path);
3059  ret[path_len] = 0;
3060  lstrcatW(ret, Name);
3061  }
3062  }
3063  else if (Path[path_len-1] != '\\' && Name[0] != '\\')
3064  {
3065  ret = SysAllocStringLen(NULL, path_len + name_len + 1);
3066  if (ret)
3067  {
3068  lstrcpyW(ret, Path);
3069  if (Path[path_len-1] != ':')
3070  lstrcatW(ret, bsW);
3071  lstrcatW(ret, Name);
3072  }
3073  }
3074  else
3075  {
3076  ret = SysAllocStringLen(NULL, path_len + name_len);
3077  if (ret)
3078  {
3079  lstrcpyW(ret, Path);
3080  lstrcatW(ret, Name);
3081  }
3082  }
3083  }
3084  else if (Path || Name)
3085  ret = SysAllocString(Path ? Path : Name);
3086  else
3087  ret = SysAllocStringLen(NULL, 0);
3088 
3089  if (!ret) return E_OUTOFMEMORY;
3090  *Result = ret;
3091 
3092  return S_OK;
3093 }
3094 
3095 static HRESULT WINAPI filesys_GetDriveName(IFileSystem3 *iface, BSTR path, BSTR *drive)
3096 {
3097  TRACE("(%p)->(%s %p)\n", iface, debugstr_w(path), drive);
3098 
3099  if (!drive)
3100  return E_POINTER;
3101 
3102  *drive = NULL;
3103 
3104  if (path && lstrlenW(path) > 1 && path[1] == ':')
3105  *drive = SysAllocStringLen(path, 2);
3106 
3107  return S_OK;
3108 }
3109 
3111 {
3112  int i;
3113 
3114  if(!path)
3115  return 0;
3116 
3117  for(i=len-1; i>=0; i--)
3118  if(path[i]!='/' && path[i]!='\\')
3119  break;
3120 
3121  for(; i>=0; i--)
3122  if(path[i]=='/' || path[i]=='\\')
3123  break;
3124 
3125  for(; i>=0; i--)
3126  if(path[i]!='/' && path[i]!='\\')
3127  break;
3128 
3129  if(i < 0)
3130  return 0;
3131 
3132  if(path[i]==':' && i==1)
3133  i++;
3134  return i+1;
3135 }
3136 
3138  BSTR *pbstrResult)
3139 {
3140  DWORD len;
3141 
3142  TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
3143 
3144  if(!pbstrResult)
3145  return E_POINTER;
3146 
3148  if(!len) {
3149  *pbstrResult = NULL;
3150  return S_OK;
3151  }
3152 
3153  *pbstrResult = SysAllocStringLen(Path, len);
3154  if(!*pbstrResult)
3155  return E_OUTOFMEMORY;
3156  return S_OK;
3157 }
3158 
3159 static HRESULT WINAPI filesys_GetFileName(IFileSystem3 *iface, BSTR Path,
3160  BSTR *pbstrResult)
3161 {
3162  int i, end;
3163 
3164  TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
3165 
3166  if(!pbstrResult)
3167  return E_POINTER;
3168 
3169  if(!Path) {
3170  *pbstrResult = NULL;
3171  return S_OK;
3172  }
3173 
3174  for(end=lstrlenW(Path)-1; end>=0; end--)
3175  if(Path[end]!='/' && Path[end]!='\\')
3176  break;
3177 
3178  for(i=end; i>=0; i--)
3179  if(Path[i]=='/' || Path[i]=='\\')
3180  break;
3181  i++;
3182 
3183  if(i>end || (i==0 && end==1 && Path[1]==':')) {
3184  *pbstrResult = NULL;
3185  return S_OK;
3186  }
3187 
3188  *pbstrResult = SysAllocStringLen(Path+i, end-i+1);
3189  if(!*pbstrResult)
3190  return E_OUTOFMEMORY;
3191  return S_OK;
3192 }
3193 
3194 static HRESULT WINAPI filesys_GetBaseName(IFileSystem3 *iface, BSTR Path,
3195  BSTR *pbstrResult)
3196 {
3197  int i, end;
3198 
3199  TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
3200 
3201  if(!pbstrResult)
3202  return E_POINTER;
3203 
3204  if(!Path) {
3205  *pbstrResult = NULL;
3206  return S_OK;
3207  }
3208 
3209  for(end=lstrlenW(Path)-1; end>=0; end--)
3210  if(Path[end]!='/' && Path[end]!='\\')
3211  break;
3212 
3213  for(i=end; i>=0; i--) {
3214  if(Path[i]=='.' && Path[end+1]!='.')
3215  end = i-1;
3216  if(Path[i]=='/' || Path[i]=='\\')
3217  break;
3218  }
3219  i++;
3220 
3221  if((i>end && Path[end+1]!='.') || (i==0 && end==1 && Path[1]==':')) {
3222  *pbstrResult = NULL;
3223  return S_OK;
3224  }
3225 
3226  *pbstrResult = SysAllocStringLen(Path+i, end-i+1);
3227  if(!*pbstrResult)
3228  return E_OUTOFMEMORY;
3229  return S_OK;
3230 }
3231 
3232 static HRESULT WINAPI filesys_GetExtensionName(IFileSystem3 *iface, BSTR path,
3233  BSTR *ext)
3234 {
3235  INT len;
3236 
3237  TRACE("%p %s %p\n", iface, debugstr_w(path), ext);
3238 
3239  *ext = NULL;
3240  len = SysStringLen(path);
3241  while (len) {
3242  if (path[len-1] == '.') {
3243  *ext = SysAllocString(&path[len]);
3244  if (!*ext)
3245  return E_OUTOFMEMORY;
3246  break;
3247  }
3248  len--;
3249  }
3250 
3251  return S_OK;
3252 }
3253 
3255  BSTR *pbstrResult)
3256 {
3257  static const WCHAR cur_path[] = {'.',0};
3258 
3259  WCHAR buf[MAX_PATH], ch;
3260  const WCHAR *path;
3261  DWORD i, beg, len, exp_len;
3262  WIN32_FIND_DATAW fdata;
3263  HANDLE fh;
3264 
3265  TRACE("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
3266 
3267  if(!pbstrResult)
3268  return E_POINTER;
3269 
3270  if(!Path)
3271  path = cur_path;
3272  else
3273  path = Path;
3274 
3276  if(!len)
3277  return E_FAIL;
3278 
3279  buf[0] = towupper(buf[0]);
3280  if(len>3 && buf[len-1] == '\\')
3281  buf[--len] = 0;
3282 
3283  for(beg=3, i=3; i<=len; i++) {
3284  if(buf[i]!='\\' && buf[i])
3285  continue;
3286 
3287  ch = buf[i];
3288  buf[i] = 0;
3289  fh = FindFirstFileW(buf, &fdata);
3290  if(fh == INVALID_HANDLE_VALUE)
3291  break;
3292 
3293  exp_len = lstrlenW(fdata.cFileName);
3294  if(exp_len == i-beg)
3295  memcpy(buf+beg, fdata.cFileName, exp_len*sizeof(WCHAR));
3296  FindClose(fh);
3297  buf[i] = ch;
3298  beg = i+1;
3299  }
3300 
3301  *pbstrResult = SysAllocString(buf);
3302  if(!*pbstrResult)
3303  return E_OUTOFMEMORY;
3304  return S_OK;
3305 }
3306 
3307 static HRESULT WINAPI filesys_GetTempName(IFileSystem3 *iface, BSTR *pbstrResult)
3308 {
3309  static const WCHAR fmt[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3310 
3311  DWORD random;
3312 
3313  TRACE("%p %p\n", iface, pbstrResult);
3314 
3315  if(!pbstrResult)
3316  return E_POINTER;
3317 
3318  *pbstrResult = SysAllocStringLen(NULL, 12);
3319  if(!*pbstrResult)
3320  return E_OUTOFMEMORY;
3321 
3322  if(!RtlGenRandom(&random, sizeof(random)))
3323  return E_FAIL;
3324  swprintf(*pbstrResult, fmt, random & 0xfffff);
3325  return S_OK;
3326 }
3327 
3328 static HRESULT WINAPI filesys_DriveExists(IFileSystem3 *iface, BSTR DriveSpec,
3329  VARIANT_BOOL *pfExists)
3330 {
3331  UINT len;
3332  WCHAR driveletter;
3333  TRACE("%p %s %p\n", iface, debugstr_w(DriveSpec), pfExists);
3334 
3335  if (!pfExists) return E_POINTER;
3336 
3337  *pfExists = VARIANT_FALSE;
3338  len = SysStringLen(DriveSpec);
3339 
3340  if (len >= 1) {
3341  driveletter = towupper(DriveSpec[0]);
3342  if (driveletter >= 'A' && driveletter <= 'Z'
3343  && (len < 2 || DriveSpec[1] == ':')
3344  && (len < 3 || DriveSpec[2] == '\\')) {
3345  const WCHAR root[] = {driveletter, ':', '\\', 0};
3346  UINT drivetype = GetDriveTypeW(root);
3347  *pfExists = drivetype != DRIVE_NO_ROOT_DIR && drivetype != DRIVE_UNKNOWN ? VARIANT_TRUE : VARIANT_FALSE;
3348  }
3349  }
3350 
3351  return S_OK;
3352 }
3353 
3355 {
3356  DWORD attrs;
3357  TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
3358 
3359  if (!ret) return E_POINTER;
3360 
3361  attrs = GetFileAttributesW(path);
3362  *ret = attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
3363  return S_OK;
3364 }
3365 
3367 {
3368  DWORD attrs;
3369  TRACE("%p %s %p\n", iface, debugstr_w(path), ret);
3370 
3371  if (!ret) return E_POINTER;
3372 
3373  attrs = GetFileAttributesW(path);
3374  *ret = attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) ? VARIANT_TRUE : VARIANT_FALSE;
3375 
3376  return S_OK;
3377 }
3378 
3379 static HRESULT WINAPI filesys_GetDrive(IFileSystem3 *iface, BSTR DriveSpec,
3380  IDrive **ppdrive)
3381 {
3382  UINT len;
3383  HRESULT hr;
3384  WCHAR driveletter;
3385  VARIANT_BOOL drive_exists;
3386 
3387  TRACE("%p %s %p\n", iface, debugstr_w(DriveSpec), ppdrive);
3388 
3389  if (!ppdrive)
3390  return E_POINTER;
3391 
3392  *ppdrive = NULL;
3393 
3394  /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3395  len = SysStringLen(DriveSpec);
3396  if (!len)
3397  return E_INVALIDARG;
3398  else if (len <= 3) {
3399  driveletter = towupper(DriveSpec[0]);
3400  if (driveletter < 'A' || driveletter > 'Z'
3401  || (len >= 2 && DriveSpec[1] != ':')
3402  || (len == 3 && DriveSpec[2] != '\\'))
3403  return E_INVALIDARG;
3404  hr = IFileSystem3_DriveExists(iface, DriveSpec, &drive_exists);
3405  if (FAILED(hr))
3406  return hr;
3407  if (drive_exists == VARIANT_FALSE)
3408  return CTL_E_DEVICEUNAVAILABLE;
3409  return create_drive(driveletter, ppdrive);
3410  } else {
3411  if (DriveSpec[0] != '\\' || DriveSpec[1] != '\\')
3412  return E_INVALIDARG;
3413  FIXME("%s not implemented yet\n", debugstr_w(DriveSpec));
3414  return E_NOTIMPL;
3415  }
3416 }
3417 
3418 static HRESULT WINAPI filesys_GetFile(IFileSystem3 *iface, BSTR FilePath,
3419  IFile **ppfile)
3420 {
3421  TRACE("%p %s %p\n", iface, debugstr_w(FilePath), ppfile);
3422 
3423  if(!ppfile)
3424  return E_POINTER;
3425  if(!FilePath)
3426  return E_INVALIDARG;
3427 
3428  return create_file(FilePath, ppfile);
3429 }
3430 
3431 static HRESULT WINAPI filesys_GetFolder(IFileSystem3 *iface, BSTR FolderPath,
3432  IFolder **folder)
3433 {
3434  DWORD attrs;
3435 
3436  TRACE("%p %s %p\n", iface, debugstr_w(FolderPath), folder);
3437 
3438  if(!folder)
3439  return E_POINTER;
3440 
3441  *folder = NULL;
3442  if(!FolderPath)
3443  return E_INVALIDARG;
3444 
3445  attrs = GetFileAttributesW(FolderPath);
3446  if((attrs == INVALID_FILE_ATTRIBUTES) || !(attrs & FILE_ATTRIBUTE_DIRECTORY))
3447  return CTL_E_PATHNOTFOUND;
3448 
3449  return create_folder(FolderPath, folder);
3450 }
3451 
3452 static HRESULT WINAPI filesys_GetSpecialFolder(IFileSystem3 *iface,
3454  IFolder **folder)
3455 {
3456  WCHAR pathW[MAX_PATH];
3457  DWORD ret;
3458 
3459  TRACE("%p %d %p\n", iface, SpecialFolder, folder);
3460 
3461  if (!folder)
3462  return E_POINTER;
3463 
3464  *folder = NULL;
3465 
3466  switch (SpecialFolder)
3467  {
3468  case WindowsFolder:
3469  ret = GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW));
3470  break;
3471  case SystemFolder:
3472  ret = GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
3473  break;
3474  case TemporaryFolder:
3475  ret = GetTempPathW(ARRAY_SIZE(pathW), pathW);
3476  /* we don't want trailing backslash */
3477  if (ret && pathW[ret-1] == '\\')
3478  pathW[ret-1] = 0;
3479  break;
3480  default:
3481  FIXME("unknown special folder type, %d\n", SpecialFolder);
3482  return E_INVALIDARG;
3483  }
3484 
3485  if (!ret)
3486  return HRESULT_FROM_WIN32(GetLastError());
3487 
3488  return create_folder(pathW, folder);
3489 }
3490 
3491 static inline HRESULT delete_file(const WCHAR *file, DWORD file_len, VARIANT_BOOL force)
3492 {
3493  WCHAR path[MAX_PATH];
3494  DWORD len, name_len;
3495  WIN32_FIND_DATAW ffd;
3496  HANDLE f;
3497 
3498  f = FindFirstFileW(file, &ffd);
3499  if(f == INVALID_HANDLE_VALUE)
3500  return create_error(GetLastError());
3501 
3502  len = get_parent_folder_name(file, file_len);
3503  if(len+1 >= MAX_PATH) {
3504  FindClose(f);
3505  return E_FAIL;
3506  }
3507  if(len) {
3508  memcpy(path, file, len*sizeof(WCHAR));
3509  path[len++] = '\\';
3510  }
3511 
3512  do {
3513  if(ffd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
3514  continue;
3515 
3516  name_len = lstrlenW(ffd.cFileName);
3517  if(len+name_len+1 >= MAX_PATH) {
3518  FindClose(f);
3519  return E_FAIL;
3520  }
3521  memcpy(path+len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
3522 
3523  TRACE("deleting %s\n", debugstr_w(path));
3524 
3525  if(!DeleteFileW(path)) {
3527  || !DeleteFileW(path)) {
3528  FindClose(f);
3529  return create_error(GetLastError());
3530  }
3531  }
3532  } while(FindNextFileW(f, &ffd));
3533  FindClose(f);
3534 
3535  return S_OK;
3536 }
3537 
3538 static HRESULT WINAPI filesys_DeleteFile(IFileSystem3 *iface, BSTR FileSpec,
3540 {
3541  TRACE("%p %s %d\n", iface, debugstr_w(FileSpec), Force);
3542 
3543  if(!FileSpec)
3544  return E_POINTER;
3545 
3546  return delete_file(FileSpec, SysStringLen(FileSpec), Force);
3547 }
3548 
3549 static HRESULT delete_folder(const WCHAR *folder, DWORD folder_len, VARIANT_BOOL force)
3550 {
3551  WCHAR path[MAX_PATH];
3552  DWORD len, name_len;
3553  WIN32_FIND_DATAW ffd;
3554  HANDLE f;
3555  HRESULT hr;
3556 
3557  f = FindFirstFileW(folder, &ffd);
3558  if(f == INVALID_HANDLE_VALUE)
3559  return create_error(GetLastError());
3560 
3561  len = get_parent_folder_name(folder, folder_len);
3562  if(len+1 >= MAX_PATH) {
3563  FindClose(f);
3564  return E_FAIL;
3565  }
3566  if(len) {
3567  memcpy(path, folder, len*sizeof(WCHAR));
3568  path[len++] = '\\';
3569  }
3570 
3571  do {
3572  if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
3573  continue;
3574  if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 ||
3575  (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0)))
3576  continue;
3577 
3578  name_len = lstrlenW(ffd.cFileName);
3579  if(len+name_len+3 >= MAX_PATH) {
3580  FindClose(f);
3581  return E_FAIL;
3582  }
3583  memcpy(path+len, ffd.cFileName, name_len*sizeof(WCHAR));
3584  path[len+name_len] = '\\';
3585  path[len+name_len+1] = '*';
3586  path[len+name_len+2] = 0;
3587 
3588  hr = delete_file(path, len+name_len+2, force);
3589  if(FAILED(hr)) {
3590  FindClose(f);
3591  return hr;
3592  }
3593 
3594  hr = delete_folder(path, len+name_len+2, force);
3595  if(FAILED(hr)) {
3596  FindClose(f);
3597  return hr;
3598  }
3599 
3600  path[len+name_len] = 0;
3601  TRACE("deleting %s\n", debugstr_w(path));
3602 
3603  if(!RemoveDirectoryW(path)) {
3604  FindClose(f);
3605  return create_error(GetLastError());
3606  }
3607  } while(FindNextFileW(f, &ffd));
3608  FindClose(f);
3609 
3610  return S_OK;
3611 }
3612 
3613 static HRESULT WINAPI filesys_DeleteFolder(IFileSystem3 *iface, BSTR FolderSpec,
3615 {
3616  TRACE("%p %s %d\n", iface, debugstr_w(FolderSpec), Force);
3617 
3618  if(!FolderSpec)
3619  return E_POINTER;
3620 
3621  return delete_folder(FolderSpec, SysStringLen(FolderSpec), Force);
3622 }
3623 
3624 static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR Source,
3625  BSTR Destination)
3626 {
3627  FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
3628 
3629  return E_NOTIMPL;
3630 }
3631 
3632 static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface,BSTR Source,
3633  BSTR Destination)
3634 {
3635  FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination));
3636 
3637  return E_NOTIMPL;
3638 }
3639 
3640 static inline HRESULT copy_file(const WCHAR *source, DWORD source_len,
3641  const WCHAR *destination, DWORD destination_len, VARIANT_BOOL overwrite)
3642 {
3643  DWORD attrs;
3644  WCHAR src_path[MAX_PATH], dst_path[MAX_PATH];
3645  DWORD src_len, dst_len, name_len;
3646  WIN32_FIND_DATAW ffd;
3647  HANDLE f;
3648  HRESULT hr;
3649 
3650  if(!source[0] || !destination[0])
3651  return E_INVALIDARG;
3652 
3653  attrs = GetFileAttributesW(destination);
3654  if(attrs==INVALID_FILE_ATTRIBUTES || !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
3655  attrs = GetFileAttributesW(source);
3656  if(attrs == INVALID_FILE_ATTRIBUTES)
3657  return create_error(GetLastError());
3658  else if(attrs & FILE_ATTRIBUTE_DIRECTORY)
3659  return CTL_E_FILENOTFOUND;
3660 
3661  if(!CopyFileW(source, destination, !overwrite))
3662  return create_error(GetLastError());
3663  return S_OK;
3664  }
3665 
3666  f = FindFirstFileW(source, &ffd);
3667  if(f == INVALID_HANDLE_VALUE)
3668  return CTL_E_FILENOTFOUND;
3669 
3670  src_len = get_parent_folder_name(source, source_len);
3671  if(src_len+1 >= MAX_PATH) {
3672  FindClose(f);
3673  return E_FAIL;
3674  }
3675  if(src_len) {
3676  memcpy(src_path, source, src_len*sizeof(WCHAR));
3677  src_path[src_len++] = '\\';
3678  }
3679 
3680  dst_len = destination_len;
3681  if(dst_len+1 >= MAX_PATH) {
3682  FindClose(f);
3683  return E_FAIL;
3684  }
3685  memcpy(dst_path, destination, dst_len*sizeof(WCHAR));
3686  if(dst_path[dst_len-1]!= '\\' && dst_path[dst_len-1]!='/')
3687  dst_path[dst_len++] = '\\';
3688 
3690  do {
3691  if(ffd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
3692  continue;
3693 
3694  name_len = lstrlenW(ffd.cFileName);
3695  if(src_len+name_len+1>=MAX_PATH || dst_len+name_len+1>=MAX_PATH) {
3696  FindClose(f);
3697  return E_FAIL;
3698  }
3699  memcpy(src_path+src_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
3700  memcpy(dst_path+dst_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR));
3701 
3702  TRACE("copying %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path));
3703 
3704  if(!CopyFileW(src_path, dst_path, !overwrite)) {
3705  FindClose(f);
3706  return create_error(GetLastError());
3707  }else {
3708  hr = S_OK;
3709  }
3710  } while(FindNextFileW(f, &ffd));
3711  FindClose(f);
3712 
3713  return hr;
3714 }
3715 
3716 static HRESULT WINAPI filesys_CopyFile(IFileSystem3 *iface, BSTR Source,
3717  BSTR Destination, VARIANT_BOOL OverWriteFiles)
3718 {
3719  TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
3720 
3721  if(!Source || !Destination)
3722  return E_POINTER;
3723 
3725  SysStringLen(Destination), OverWriteFiles);
3726 }
3727 
3728 static HRESULT copy_folder(const WCHAR *source, DWORD source_len, const WCHAR *destination,
3729  DWORD destination_len, VARIANT_BOOL overwrite)
3730 {
3731  DWORD tmp, src_len, dst_len, name_len;
3733  WIN32_FIND_DATAW ffd;
3734  HANDLE f;
3735  HRESULT hr;
3736  BOOL copied = FALSE;
3737 
3738  if(!source[0] || !destination[0])
3739  return E_INVALIDARG;
3740 
3741  dst_len = destination_len;
3742  if(dst_len+1 >= MAX_PATH)
3743  return E_FAIL;
3744  memcpy(dst, destination, (dst_len+1)*sizeof(WCHAR));
3745 
3746  if(dst[dst_len-1]!='\\' && dst[dst_len-1]!='/' &&
3749  if(!CreateDirectoryW(dst, NULL)) {
3750  if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) {
3751  tmp = GetFileAttributesW(dst);
3753  return CTL_E_FILEALREADYEXISTS;
3754  }else {
3755  return create_error(GetLastError());
3756  }
3757  }
3758  copied = TRUE;
3759 
3760  src_len = source_len;
3761  if(src_len+2 >= MAX_PATH)
3762  return E_FAIL;
3763  memcpy(src, source, src_len*sizeof(WCHAR));
3764  src[src_len++] = '\\';
3765  src[src_len] = '*';
3766  src[src_len+1] = 0;
3767 
3768  hr = copy_file(src, src_len+1, dst, dst_len, overwrite);
3769  if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND)
3770  return create_error(GetLastError());
3771 
3772  f = FindFirstFileW(src, &ffd);
3773  }else {
3774  src_len = get_parent_folder_name(source, source_len);
3775  if(src_len+2 >= MAX_PATH)
3776  return E_FAIL;
3777  memcpy(src, source, src_len*sizeof(WCHAR));
3778  if(src_len)
3779  src[src_len++] = '\\';
3780 
3781  f = FindFirstFileW(source, &ffd);
3782  }
3783  if(f == INVALID_HANDLE_VALUE)
3784  return CTL_E_PATHNOTFOUND;
3785 
3786  dst[dst_len++] = '\\';
3787  dst[dst_len] = 0;
3788 
3789  do {
3790  if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
3791  continue;
3792  if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 ||
3793  (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0)))
3794  continue;
3795 
3796  name_len = lstrlenW(ffd.cFileName);
3797  if(dst_len+name_len>=MAX_PATH || src_len+name_len+2>=MAX_PATH) {
3798  FindClose(f);
3799  return E_FAIL;
3800  }
3801  memcpy(dst+dst_len, ffd.cFileName, name_len*sizeof(WCHAR));
3802  dst[dst_len+name_len] = 0;
3803  memcpy(src+src_len, ffd.cFileName, name_len*sizeof(WCHAR));
3804  src[src_len+name_len] = '\\';
3805  src[src_len+name_len+1] = '*';
3806  src[src_len+name_len+2] = 0;
3807 
3808  TRACE("copying %s to %s\n", debugstr_w(src), debugstr_w(dst));
3809 
3810  if(!CreateDirectoryW(dst, NULL)) {
3811  if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) {
3812  tmp = GetFileAttributesW(dst);
3814  FindClose(f);
3815  return CTL_E_FILEALREADYEXISTS;
3816  }
3817  }
3818 
3819  FindClose(f);
3820  return create_error(GetLastError());
3821  }
3822  copied = TRUE;
3823 
3824  hr = copy_file(src, src_len+name_len+2, dst, dst_len+name_len, overwrite);
3825  if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND) {
3826  FindClose(f);
3827  return hr;
3828  }
3829 
3830  hr = copy_folder(src, src_len+name_len+2, dst, dst_len+name_len, overwrite);
3831  if(FAILED(hr) && hr!=CTL_E_PATHNOTFOUND) {
3832  FindClose(f);
3833  return hr;
3834  }
3835  } while(FindNextFileW(f, &ffd));
3836  FindClose(f);
3837 
3838  return copied ? S_OK : CTL_E_PATHNOTFOUND;
3839 }
3840 
3841 static HRESULT WINAPI filesys_CopyFolder(IFileSystem3 *iface, BSTR Source,
3842  BSTR Destination, VARIANT_BOOL OverWriteFiles)
3843 {
3844  TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
3845 
3846  if(!Source || !Destination)
3847  return E_POINTER;
3848 
3850  SysStringLen(Destination), OverWriteFiles);
3851 }
3852 
3853 static HRESULT WINAPI filesys_CreateFolder(IFileSystem3 *iface, BSTR path,
3854  IFolder **folder)
3855 {
3856  BOOL ret;
3857 
3858  TRACE("(%p)->(%s %p)\n", iface, debugstr_w(path), folder);
3859 
3861  if (!ret)
3862  {
3863  *folder = NULL;
3865  return HRESULT_FROM_WIN32(GetLastError());
3866  }
3867 
3868  return create_folder(path, folder);
3869 }
3870 
3871 static HRESULT WINAPI filesys_CreateTextFile(IFileSystem3 *iface, BSTR filename,
3872  VARIANT_BOOL overwrite, VARIANT_BOOL unicode,
3873  ITextStream **stream)
3874 {
3875  DWORD disposition;
3876 
3877  TRACE("%p %s %d %d %p\n", iface, debugstr_w(filename), overwrite, unicode, stream);
3878 
3879  disposition = overwrite == VARIANT_TRUE ? CREATE_ALWAYS : CREATE_NEW;
3880  return create_textstream(filename, disposition, ForWriting, unicode ? TristateTrue : TristateFalse, stream);
3881 }
3882 
3883 static HRESULT WINAPI filesys_OpenTextFile(IFileSystem3 *iface, BSTR filename,
3885  Tristate format, ITextStream **stream)
3886 {
3887  DWORD disposition;
3888 
3889  TRACE("(%p)->(%s %d %d %d %p)\n", iface, debugstr_w(filename), mode, create, format, stream);
3890 
3891  disposition = create == VARIANT_TRUE ? OPEN_ALWAYS : OPEN_EXISTING;
3892  return create_textstream(filename, disposition, mode, format, stream);
3893 }
3894 
3895 static HRESULT WINAPI filesys_GetStandardStream(IFileSystem3 *iface,
3896  StandardStreamTypes StandardStreamType,
3897  VARIANT_BOOL Unicode,
3898  ITextStream **ppts)
3899 {
3900  FIXME("%p %d %d %p\n", iface, StandardStreamType, Unicode, ppts);
3901 
3902  return E_NOTIMPL;
3903 }
3904 
3906 {
3907  static const WCHAR fmtW[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3909  WORD a, b, c, d;
3910 
3911  version = (((DWORDLONG)info->dwFileVersionMS) << 32) + info->dwFileVersionLS;
3912  a = (WORD)( version >> 48);
3913  b = (WORD)((version >> 32) & 0xffff);
3914  c = (WORD)((version >> 16) & 0xffff);
3915  d = (WORD)( version & 0xffff);
3916 
3917  swprintf(ver, fmtW, a, b, c, d);
3918 }
3919 
3921 {
3922  static const WCHAR rootW[] = {'\\',0};
3924  WCHAR ver[30];
3925  void *ptr;
3926  DWORD len;
3927  BOOL ret;
3928 
3929  TRACE("%p %s %p\n", iface, debugstr_w(name), version);
3930 
3932  if (!len)
3933  return HRESULT_FROM_WIN32(GetLastError());
3934 
3935  ptr = heap_alloc(len);
3936  if (!GetFileVersionInfoW(name, 0, len, ptr))
3937  {
3938  heap_free(ptr);
3939  return HRESULT_FROM_WIN32(GetLastError());
3940  }
3941 
3942  ret = VerQueryValueW(ptr, rootW, (void**)&info, &len);
3943  if (!ret)
3944  {
3945  heap_free(ptr);
3946  return HRESULT_FROM_WIN32(GetLastError());
3947  }
3948 
3949  get_versionstring(info, ver);
3950  heap_free(ptr);
3951 
3952  *version = SysAllocString(ver);
3953  TRACE("version=%s\n", debugstr_w(ver));
3954 
3955  return S_OK;
3956 }
3957 
3958 static const struct IFileSystem3Vtbl filesys_vtbl =
3959 {
3994 };
3995 
3996 static struct filesystem filesystem;
3997 
3999 {
4000  TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
4001 
4003  init_classinfo(&CLSID_FileSystemObject, (IUnknown *)&filesystem.IFileSystem3_iface, &filesystem.classinfo);
4004  return IFileSystem3_QueryInterface(&filesystem.IFileSystem3_iface, riid, ppv);
4005 }
static HRESULT WINAPI file_get_DateCreated(IFile *iface, DATE *pdate)
Definition: filesystem.c:2761
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:944
static ULONG WINAPI filesys_Release(IFileSystem3 *iface)
Definition: filesystem.c:2968
#define CTL_E_FILENOTFOUND
Definition: olectl.h:274
static HRESULT WINAPI foldercoll_Add(IFolderCollection *iface, BSTR name, IFolder **folder)
Definition: filesystem.c:1729
static HRESULT WINAPI folder_get_Type(IFolder *iface, BSTR *type)
Definition: filesystem.c:2402
static HRESULT WINAPI drive_get_Path(IDrive *iface, BSTR *path)
Definition: filesystem.c:888
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
static HRESULT textstream_writecrlf(struct textstream *stream)
Definition: filesystem.c:603
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Definition: fileinfo.c:327
static HANDLE start_enumeration(const WCHAR *path, WIN32_FIND_DATAW *data, BOOL file)
Definition: filesystem.c:1190
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static const IFileCollectionVtbl filecollectionvtbl
Definition: filesystem.c:1981
static HRESULT WINAPI filecoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched)
Definition: filesystem.c:1374
static HRESULT WINAPI filecoll_GetTypeInfo(IFileCollection *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
Definition: filesystem.c:1880
static HRESULT WINAPI textstream_ReadLine(ITextStream *iface, BSTR *text)
Definition: filesystem.c:497
static HRESULT WINAPI foldercoll_Invoke(IFolderCollection *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
Definition: filesystem.c:1706
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
static HRESULT WINAPI filesys_GetParentFolderName(IFileSystem3 *iface, BSTR Path, BSTR *pbstrResult)
Definition: filesystem.c:3137
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
static const WCHAR crlfW[]
Definition: filesystem.c:47
static HRESULT WINAPI drive_get_DriveLetter(IDrive *iface, BSTR *letter)
Definition: filesystem.c:895
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
#define E_NOINTERFACE
Definition: winerror.h:2364
struct provideclassinfo classinfo
Definition: filesystem.c:61
Definition: compat.h:1947
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
static const ITextStreamVtbl textstreamvtbl
Definition: filesystem.c:676
Definition: fci.c:115
DriveTypeConst
Definition: scrrun.idl:87
IFolderCollection IFolderCollection_iface
Definition: filesystem.c:55
#define WideCharToMultiByte
Definition: compat.h:101
static HRESULT WINAPI folder_get_DateCreated(IFolder *iface, DATE *date)
Definition: filesystem.c:2381
#define INT_MAX
Definition: limits.h:40