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