2 * Copyright 2012 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "scrrun_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(scrrun
);
40 struct provideclassinfo classinfo
;
41 IFileSystem3 IFileSystem3_iface
;
44 struct foldercollection
{
45 struct provideclassinfo classinfo
;
46 IFolderCollection IFolderCollection_iface
;
51 struct filecollection
{
52 struct provideclassinfo classinfo
;
53 IFileCollection IFileCollection_iface
;
58 struct drivecollection
{
59 struct provideclassinfo classinfo
;
60 IDriveCollection IDriveCollection_iface
;
71 struct foldercollection
*coll
;
76 struct filecollection
*coll
;
81 struct drivecollection
*coll
;
88 IEnumVARIANT IEnumVARIANT_iface
;
95 struct provideclassinfo classinfo
;
102 struct provideclassinfo classinfo
;
103 IFolder IFolder_iface
;
109 struct provideclassinfo classinfo
;
117 struct provideclassinfo classinfo
;
118 ITextStream ITextStream_iface
;
128 size_t read_buf_size
;
136 static inline struct filesystem
*impl_from_IFileSystem3(IFileSystem3
*iface
)
138 return CONTAINING_RECORD(iface
, struct filesystem
, IFileSystem3_iface
);
141 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
143 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
146 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
148 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
151 static inline struct file
*impl_from_IFile(IFile
*iface
)
153 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
156 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
158 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
161 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
163 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
166 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
168 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
171 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
173 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
176 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
178 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
181 static inline HRESULT
create_error(DWORD err
)
184 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
185 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
186 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
187 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
188 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
190 FIXME("Unsupported error code: %ld\n", err
);
195 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
196 static HRESULT
create_file(BSTR
, IFile
**);
197 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
198 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
199 static HRESULT
create_drivecoll_enum(struct drivecollection
*, IUnknown
**);
201 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
203 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
204 wcscmp(data
->cFileName
, L
"..") &&
205 wcscmp(data
->cFileName
, L
".");
208 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
210 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
213 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
215 int len
= SysStringLen(path
);
216 WCHAR buffW
[MAX_PATH
];
218 lstrcpyW(buffW
, path
);
219 if (path
[len
-1] != '\\') wcscat(buffW
, L
"\\");
220 lstrcatW(buffW
, data
->cFileName
);
222 return SysAllocString(buffW
);
225 static HRESULT
build_path( BSTR Path
, BSTR Name
, BSTR
*Result
)
231 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
233 /* if both parts have backslashes strip one from Path */
234 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
238 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
246 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
248 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
252 if (Path
[path_len
-1] != ':')
259 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
267 else if (Path
|| Name
)
268 ret
= SysAllocString(Path
? Path
: Name
);
270 ret
= SysAllocStringLen(NULL
, 0);
272 if (!ret
) return E_OUTOFMEMORY
;
278 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
281 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
283 return This
->mode
== ForReading
;
286 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
288 struct textstream
*This
= impl_from_ITextStream(iface
);
290 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
292 if (IsEqualIID(riid
, &IID_ITextStream
) ||
293 IsEqualIID(riid
, &IID_IDispatch
) ||
294 IsEqualIID(riid
, &IID_IUnknown
))
296 *obj
= &This
->ITextStream_iface
;
298 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
300 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
303 return E_NOINTERFACE
;
305 IUnknown_AddRef((IUnknown
*)*obj
);
309 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
311 struct textstream
*stream
= impl_from_ITextStream(iface
);
312 ULONG ref
= InterlockedIncrement(&stream
->ref
);
314 TRACE("%p, refcount %ld.\n", iface
, ref
);
319 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
321 struct textstream
*stream
= impl_from_ITextStream(iface
);
322 ULONG ref
= InterlockedDecrement(&stream
->ref
);
324 TRACE("%p, refcount %ld.\n", iface
, ref
);
328 if (stream
->read_buf_size
) free(stream
->read_buf
);
329 CloseHandle(stream
->file
);
336 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
338 struct textstream
*This
= impl_from_ITextStream(iface
);
339 TRACE("(%p)->(%p)\n", This
, pctinfo
);
344 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
345 LCID lcid
, ITypeInfo
**ppTInfo
)
347 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
349 return get_typeinfo(ITextStream_tid
, ppTInfo
);
352 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
353 LPOLESTR
*rgszNames
, UINT cNames
,
354 LCID lcid
, DISPID
*rgDispId
)
359 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
361 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
364 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
365 ITypeInfo_Release(typeinfo
);
371 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
372 REFIID riid
, LCID lcid
, WORD wFlags
,
373 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
374 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
379 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
380 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
382 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
385 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
386 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
387 ITypeInfo_Release(typeinfo
);
393 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
395 struct textstream
*This
= impl_from_ITextStream(iface
);
396 FIXME("(%p)->(%p): stub\n", This
, line
);
400 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
402 struct textstream
*This
= impl_from_ITextStream(iface
);
403 FIXME("(%p)->(%p): stub\n", This
, column
);
407 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
409 struct textstream
*This
= impl_from_ITextStream(iface
);
411 TRACE("(%p)->(%p)\n", This
, eos
);
416 if (textstream_check_iomode(This
, IORead
)) {
418 return CTL_E_BADFILEMODE
;
421 *eos
= (This
->eof
&& !This
->read_buf_size
) ? VARIANT_TRUE
: VARIANT_FALSE
;
425 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
427 struct textstream
*This
= impl_from_ITextStream(iface
);
428 FIXME("(%p)->(%p): stub\n", This
, eol
);
432 static HRESULT
append_read_data(struct textstream
*stream
, const char *buf
, size_t buf_size
)
434 LARGE_INTEGER revert
;
441 len
= buf_size
/ sizeof(WCHAR
);
442 if (buf_size
& 1) revert
.QuadPart
= -1;
446 for (len
= 0; len
< buf_size
; len
++)
448 if (!IsDBCSLeadByte(buf
[len
])) continue;
449 if (len
+ 1 == buf_size
)
451 revert
.QuadPart
= -1;
457 len
= MultiByteToWideChar(CP_ACP
, 0, buf
, buf_size
, NULL
, 0);
462 SetFilePointerEx(stream
->file
, revert
, NULL
, FILE_CURRENT
);
464 if (!stream
->read_buf_size
)
465 new_buf
= malloc(len
* sizeof(WCHAR
));
467 new_buf
= realloc(stream
->read_buf
, (len
+ stream
->read_buf_size
) * sizeof(WCHAR
));
468 if (!new_buf
) return E_OUTOFMEMORY
;
471 memcpy(new_buf
+ stream
->read_buf_size
, buf
, len
* sizeof(WCHAR
));
473 MultiByteToWideChar(CP_ACP
, 0, buf
, buf_size
, new_buf
+ stream
->read_buf_size
, len
);
474 stream
->read_buf
= new_buf
;
475 stream
->read_buf_size
+= len
;
479 static HRESULT
read_more_data(struct textstream
*stream
)
484 if (stream
->eof
) return S_OK
;
486 if (!ReadFile(stream
->file
, buf
, sizeof(buf
), &read
, NULL
))
488 ITextStream_Release(&stream
->ITextStream_iface
);
489 return create_error(GetLastError());
492 stream
->eof
= read
!= sizeof(buf
);
493 return append_read_data(stream
, buf
, read
);
496 static BOOL
read_from_buffer(struct textstream
*stream
, size_t len
, BSTR
*ret
, size_t skip
)
498 assert(len
+ skip
<= stream
->read_buf_size
);
500 if (!(*ret
= SysAllocStringLen(stream
->read_buf
, len
))) return FALSE
;
503 stream
->read_buf_size
-= len
;
504 if (stream
->read_buf_size
)
505 memmove(stream
->read_buf
, stream
->read_buf
+ len
, stream
->read_buf_size
* sizeof(WCHAR
));
507 free(stream
->read_buf
);
511 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
513 struct textstream
*This
= impl_from_ITextStream(iface
);
516 TRACE("%p, %ld, %p.\n", iface
, len
, text
);
523 return len
== 0 ? S_OK
: E_INVALIDARG
;
525 if (textstream_check_iomode(This
, IORead
))
526 return CTL_E_BADFILEMODE
;
528 while (!This
->eof
&& len
> This
->read_buf_size
)
530 if (FAILED(hr
= read_more_data(This
)))
534 if (This
->eof
&& !This
->read_buf_size
)
535 return CTL_E_ENDOFFILE
;
537 if (len
> This
->read_buf_size
)
539 len
= This
->read_buf_size
;
543 return read_from_buffer(This
, len
, text
, 0) ? hr
: E_OUTOFMEMORY
;
546 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
548 struct textstream
*This
= impl_from_ITextStream(iface
);
549 unsigned int skip
= 0;
553 TRACE("(%p)->(%p)\n", This
, text
);
559 if (textstream_check_iomode(This
, IORead
))
560 return CTL_E_BADFILEMODE
;
562 while (!(nl
= wmemchr(This
->read_buf
, '\n', This
->read_buf_size
)) && !This
->eof
)
564 if (FAILED(hr
= read_more_data(This
)))
568 if (This
->eof
&& !This
->read_buf_size
)
569 return CTL_E_ENDOFFILE
;
573 nl
= This
->read_buf
+ This
->read_buf_size
;
576 else if (nl
> This
->read_buf
&& nl
[-1] == '\r')
583 return read_from_buffer(This
, nl
- This
->read_buf
, text
, skip
) ? hr
: E_OUTOFMEMORY
;
586 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
588 struct textstream
*This
= impl_from_ITextStream(iface
);
591 TRACE("(%p)->(%p)\n", This
, text
);
597 if (textstream_check_iomode(This
, IORead
))
598 return CTL_E_BADFILEMODE
;
602 if (FAILED(hr
= read_more_data(This
)))
606 if (This
->eof
&& !This
->read_buf_size
)
607 return CTL_E_ENDOFFILE
;
609 return read_from_buffer(This
, This
->read_buf_size
, text
, 0) ? S_FALSE
: E_OUTOFMEMORY
;
612 static HRESULT
textstream_write(struct textstream
*stream
, BSTR text
)
617 if (textstream_check_iomode(stream
, IOWrite
))
618 return CTL_E_BADFILEMODE
;
620 if (stream
->unicode
) {
621 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
622 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
624 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
630 return E_OUTOFMEMORY
;
632 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
633 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
634 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
640 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
642 struct textstream
*stream
= impl_from_ITextStream(iface
);
644 TRACE("%p, %s.\n", iface
, debugstr_w(text
));
646 return textstream_write(stream
, text
);
649 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
651 static const WCHAR crlfW
[] = {'\r','\n'};
652 static const char crlfA
[] = {'\r','\n'};
653 DWORD written
= 0, len
;
657 if (stream
->unicode
) {
666 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
667 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
670 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
672 struct textstream
*stream
= impl_from_ITextStream(iface
);
675 TRACE("%p, %s.\n", iface
, debugstr_w(text
));
677 hr
= textstream_write(stream
, text
);
679 hr
= textstream_writecrlf(stream
);
683 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
685 FIXME("%p, %ld stub\n", iface
, lines
);
690 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
692 FIXME("%p, %ld stub\n", iface
, count
);
697 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
699 struct textstream
*This
= impl_from_ITextStream(iface
);
700 FIXME("(%p): stub\n", This
);
704 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
706 struct textstream
*stream
= impl_from_ITextStream(iface
);
709 TRACE("%p.\n", iface
);
711 if (!CloseHandle(stream
->file
))
719 static const ITextStreamVtbl textstreamvtbl
=
721 textstream_QueryInterface
,
724 textstream_GetTypeInfoCount
,
725 textstream_GetTypeInfo
,
726 textstream_GetIDsOfNames
,
729 textstream_get_Column
,
730 textstream_get_AtEndOfStream
,
731 textstream_get_AtEndOfLine
,
736 textstream_WriteLine
,
737 textstream_WriteBlankLines
,
743 static HRESULT WINAPI
pipestream_get_Line(ITextStream
*iface
, LONG
*line
)
745 FIXME("%p, %p.\n", iface
, line
);
750 static HRESULT WINAPI
pipestream_get_Column(ITextStream
*iface
, LONG
*column
)
752 FIXME("%p, %p.\n", iface
, column
);
757 static HRESULT WINAPI
pipestream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
759 FIXME("%p, %p.\n", iface
, eos
);
764 static HRESULT WINAPI
pipestream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
766 FIXME("%p, %p.\n", iface
, eol
);
771 static HRESULT WINAPI
pipestream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
773 FIXME("%p, %ld, %p.\n", iface
, len
, text
);
778 static HRESULT WINAPI
pipestream_ReadLine(ITextStream
*iface
, BSTR
*text
)
780 FIXME("%p, %p.\n", iface
, text
);
785 static HRESULT WINAPI
pipestream_ReadAll(ITextStream
*iface
, BSTR
*text
)
787 FIXME("%p, %p.\n", iface
, text
);
792 static HRESULT WINAPI
pipestream_Write(ITextStream
*iface
, BSTR text
)
794 struct textstream
*stream
= impl_from_ITextStream(iface
);
796 TRACE("%p, %s.\n", iface
, debugstr_w(text
));
798 return textstream_write(stream
, text
);
801 static HRESULT WINAPI
pipestream_WriteLine(ITextStream
*iface
, BSTR text
)
803 FIXME("%p, %s.\n", iface
, debugstr_w(text
));
808 static HRESULT WINAPI
pipestream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
810 FIXME("%p, %ld.\n", iface
, lines
);
815 static HRESULT WINAPI
pipestream_Skip(ITextStream
*iface
, LONG count
)
817 FIXME("%p, %ld.\n", iface
, count
);
822 static HRESULT WINAPI
pipestream_SkipLine(ITextStream
*iface
)
824 FIXME("%p.\n", iface
);
829 static const ITextStreamVtbl pipestreamvtbl
=
831 textstream_QueryInterface
,
834 textstream_GetTypeInfoCount
,
835 textstream_GetTypeInfo
,
836 textstream_GetIDsOfNames
,
839 pipestream_get_Column
,
840 pipestream_get_AtEndOfStream
,
841 pipestream_get_AtEndOfLine
,
846 pipestream_WriteLine
,
847 pipestream_WriteBlankLines
,
853 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, Tristate format
, ITextStream
**ret
)
855 static const unsigned short utf16bom
= 0xfeff;
856 struct textstream
*stream
;
860 /* map access mode */
864 access
= GENERIC_READ
;
867 access
= GENERIC_WRITE
;
870 access
= GENERIC_READ
| GENERIC_WRITE
;
876 if (!(stream
= calloc(1, sizeof(*stream
))))
877 return E_OUTOFMEMORY
;
879 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
883 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
884 if (stream
->file
== INVALID_HANDLE_VALUE
)
886 HRESULT hr
= create_error(GetLastError());
891 if (mode
== ForReading
)
892 GetFileSizeEx(stream
->file
, &stream
->size
);
894 stream
->size
.QuadPart
= 0;
896 if (mode
== ForWriting
)
898 stream
->unicode
= format
== TristateTrue
;
899 /* Write Unicode BOM */
900 if (stream
->unicode
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
|| disposition
== TRUNCATE_EXISTING
)) {
902 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
903 if (!ret
|| written
!= sizeof(utf16bom
)) {
904 ITextStream_Release(&stream
->ITextStream_iface
);
905 return create_error(GetLastError());
911 DWORD read
, buf_offset
= 0;
914 if (format
== TristateUseDefault
|| mode
== ForReading
)
916 if (!ReadFile(stream
->file
, buf
, sizeof(buf
), &read
, NULL
))
918 ITextStream_Release(&stream
->ITextStream_iface
);
919 return create_error(GetLastError());
923 if (format
== TristateUseDefault
)
924 stream
->unicode
= IsTextUnicode(buf
, read
, NULL
);
926 stream
->unicode
= format
!= TristateFalse
;
928 if (mode
== ForReading
)
930 if (stream
->unicode
&& read
>= 2 && buf
[0] == 0xff && buf
[1] == 0xfe)
931 buf_offset
+= 2; /* skip utf16 BOM */
933 hr
= append_read_data(stream
, (const char *)buf
+ buf_offset
, read
- buf_offset
);
936 ITextStream_Release(&stream
->ITextStream_iface
);
940 stream
->eof
= read
!= sizeof(buf
);
944 LONG filePosHigh
= 0;
945 DWORD filePosLow
= SetFilePointer(stream
->file
, 0, &filePosHigh
, FILE_END
);
946 if(stream
->unicode
&& filePosHigh
== 0 && filePosLow
== 0) {
947 /* unicode ForAppending to an empty file, write BOM */
949 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
950 if (!ret
|| written
!= sizeof(utf16bom
)) {
951 ITextStream_Release(&stream
->ITextStream_iface
);
952 return create_error(GetLastError());
958 init_classinfo(&CLSID_TextStream
, (IUnknown
*)&stream
->ITextStream_iface
, &stream
->classinfo
);
959 *ret
= &stream
->ITextStream_iface
;
963 HRESULT WINAPI
DoOpenPipeStream(HANDLE pipe
, IOMode mode
, ITextStream
**ret
)
965 struct textstream
*stream
;
967 TRACE("%p, %d, %p.\n", pipe
, mode
, ret
);
969 if (!(stream
= calloc(1, sizeof(*stream
))))
970 return E_OUTOFMEMORY
;
972 stream
->ITextStream_iface
.lpVtbl
= &pipestreamvtbl
;
977 init_classinfo(&CLSID_TextStream
, (IUnknown
*)&stream
->ITextStream_iface
, &stream
->classinfo
);
978 *ret
= &stream
->ITextStream_iface
;
983 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
985 struct drive
*This
= impl_from_IDrive(iface
);
987 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
991 if (IsEqualIID( riid
, &IID_IDrive
) ||
992 IsEqualIID( riid
, &IID_IDispatch
) ||
993 IsEqualIID( riid
, &IID_IUnknown
))
995 *obj
= &This
->IDrive_iface
;
997 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
999 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1002 return E_NOINTERFACE
;
1004 IUnknown_AddRef((IUnknown
*)*obj
);
1008 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
1010 struct drive
*drive
= impl_from_IDrive(iface
);
1011 ULONG ref
= InterlockedIncrement(&drive
->ref
);
1013 TRACE("%p, refcount %ld.\n", iface
, ref
);
1018 static ULONG WINAPI
drive_Release(IDrive
*iface
)
1020 struct drive
*drive
= impl_from_IDrive(iface
);
1021 ULONG ref
= InterlockedDecrement(&drive
->ref
);
1023 TRACE("%p, refcount %ld.\n", iface
, ref
);
1031 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
1033 struct drive
*This
= impl_from_IDrive(iface
);
1034 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1039 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
1040 LCID lcid
, ITypeInfo
**ppTInfo
)
1042 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1044 return get_typeinfo(IDrive_tid
, ppTInfo
);
1047 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
1048 LPOLESTR
*rgszNames
, UINT cNames
,
1049 LCID lcid
, DISPID
*rgDispId
)
1051 ITypeInfo
*typeinfo
;
1054 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1056 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
1059 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1060 ITypeInfo_Release(typeinfo
);
1066 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
1067 REFIID riid
, LCID lcid
, WORD wFlags
,
1068 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1069 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1071 ITypeInfo
*typeinfo
;
1074 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1075 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1077 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
1080 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1081 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1082 ITypeInfo_Release(typeinfo
);
1088 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
1090 struct drive
*This
= impl_from_IDrive(iface
);
1091 FIXME("(%p)->(%p): stub\n", This
, path
);
1095 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
1097 struct drive
*This
= impl_from_IDrive(iface
);
1099 TRACE("(%p)->(%p)\n", This
, letter
);
1104 *letter
= SysAllocStringLen(This
->root
, 1);
1106 return E_OUTOFMEMORY
;
1111 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
1113 struct drive
*This
= impl_from_IDrive(iface
);
1114 FIXME("(%p)->(%p): stub\n", This
, share_name
);
1118 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
1120 struct drive
*This
= impl_from_IDrive(iface
);
1122 TRACE("(%p)->(%p)\n", This
, type
);
1124 switch (GetDriveTypeW(This
->root
))
1126 case DRIVE_REMOVABLE
:
1142 *type
= UnknownType
;
1149 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
1151 struct drive
*This
= impl_from_IDrive(iface
);
1152 FIXME("(%p)->(%p): stub\n", This
, folder
);
1156 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
1160 if (src
->u
.HighPart
|| src
->u
.LowPart
> INT_MAX
)
1163 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
1168 V_I4(v
) = src
->u
.LowPart
;
1174 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
1176 struct drive
*This
= impl_from_IDrive(iface
);
1177 ULARGE_INTEGER avail
;
1179 TRACE("(%p)->(%p)\n", This
, v
);
1184 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
1187 return variant_from_largeint(&avail
, v
);
1190 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
1192 struct drive
*This
= impl_from_IDrive(iface
);
1193 ULARGE_INTEGER freespace
;
1195 TRACE("(%p)->(%p)\n", This
, v
);
1200 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
1203 return variant_from_largeint(&freespace
, v
);
1206 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
1208 struct drive
*This
= impl_from_IDrive(iface
);
1209 ULARGE_INTEGER total
;
1211 TRACE("(%p)->(%p)\n", This
, v
);
1216 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
1219 return variant_from_largeint(&total
, v
);
1222 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
1224 struct drive
*This
= impl_from_IDrive(iface
);
1225 WCHAR nameW
[MAX_PATH
+1];
1228 TRACE("(%p)->(%p)\n", This
, name
);
1234 ret
= GetVolumeInformationW(This
->root
, nameW
, ARRAY_SIZE(nameW
), NULL
, NULL
, NULL
, NULL
, 0);
1236 *name
= SysAllocString(nameW
);
1237 return ret
? S_OK
: E_FAIL
;
1240 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
1242 struct drive
*This
= impl_from_IDrive(iface
);
1243 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
1247 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
1249 struct drive
*This
= impl_from_IDrive(iface
);
1250 WCHAR nameW
[MAX_PATH
+1];
1253 TRACE("(%p)->(%p)\n", This
, fs
);
1259 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, NULL
, NULL
, NULL
, nameW
, ARRAY_SIZE(nameW
));
1261 *fs
= SysAllocString(nameW
);
1262 return ret
? S_OK
: E_FAIL
;
1265 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
1267 struct drive
*This
= impl_from_IDrive(iface
);
1270 TRACE("(%p)->(%p)\n", This
, serial
);
1275 ret
= GetVolumeInformationW(This
->root
, NULL
, 0, (DWORD
*)serial
, NULL
, NULL
, NULL
, 0);
1276 return ret
? S_OK
: E_FAIL
;
1279 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
1281 struct drive
*This
= impl_from_IDrive(iface
);
1282 ULARGE_INTEGER freespace
;
1285 TRACE("(%p)->(%p)\n", This
, ready
);
1290 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
1291 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1295 static const IDriveVtbl drivevtbl
= {
1296 drive_QueryInterface
,
1299 drive_GetTypeInfoCount
,
1301 drive_GetIDsOfNames
,
1304 drive_get_DriveLetter
,
1305 drive_get_ShareName
,
1306 drive_get_DriveType
,
1307 drive_get_RootFolder
,
1308 drive_get_AvailableSpace
,
1309 drive_get_FreeSpace
,
1310 drive_get_TotalSize
,
1311 drive_get_VolumeName
,
1312 drive_put_VolumeName
,
1313 drive_get_FileSystem
,
1314 drive_get_SerialNumber
,
1318 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1320 struct drive
*object
;
1324 object
= malloc(sizeof(*object
));
1325 if (!object
) return E_OUTOFMEMORY
;
1327 object
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1329 wcscpy(object
->root
, L
"A:\\");
1330 *object
->root
= letter
;
1332 init_classinfo(&CLSID_Drive
, (IUnknown
*)&object
->IDrive_iface
, &object
->classinfo
);
1333 *drive
= &object
->IDrive_iface
;
1338 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1340 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1342 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1346 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1347 IsEqualIID( riid
, &IID_IUnknown
))
1350 IEnumVARIANT_AddRef(iface
);
1353 return E_NOINTERFACE
;
1358 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1360 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1361 ULONG ref
= InterlockedIncrement(&This
->ref
);
1362 TRACE("%p, refcount %ld.\n", iface
, ref
);
1366 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1368 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1369 ULONG ref
= InterlockedDecrement(&This
->ref
);
1371 TRACE("%p, refcount %ld.\n", iface
, ref
);
1375 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1376 FindClose(This
->data
.u
.foldercoll
.find
);
1383 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1385 WCHAR pathW
[MAX_PATH
];
1389 lstrcpyW(pathW
, path
);
1390 len
= lstrlenW(pathW
);
1391 if (len
&& pathW
[len
-1] != '\\') wcscat(pathW
, L
"\\");
1392 wcscat(pathW
, L
"*");
1393 handle
= FindFirstFileW(pathW
, data
);
1394 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1396 /* find first dir/file */
1399 if (file
? is_file_data(data
) : is_dir_data(data
))
1402 if (!FindNextFileW(handle
, data
))
1411 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1413 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1414 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1415 WIN32_FIND_DATAW data
;
1418 TRACE("%p, %lu, %p, %p.\n", iface
, celt
, var
, fetched
);
1423 if (!celt
) return S_OK
;
1427 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1428 if (!handle
) return S_FALSE
;
1430 This
->data
.u
.foldercoll
.find
= handle
;
1434 if (!FindNextFileW(handle
, &data
))
1440 if (is_dir_data(&data
))
1446 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1447 hr
= create_folder(str
, &folder
);
1449 if (FAILED(hr
)) return hr
;
1451 V_VT(&var
[count
]) = VT_DISPATCH
;
1452 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1455 if (count
>= celt
) break;
1457 } while (FindNextFileW(handle
, &data
));
1462 return (count
< celt
) ? S_FALSE
: S_OK
;
1465 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1467 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1468 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1469 WIN32_FIND_DATAW data
;
1471 TRACE("%p, %lu.\n", iface
, celt
);
1473 if (!celt
) return S_OK
;
1477 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1478 if (!handle
) return S_FALSE
;
1480 This
->data
.u
.foldercoll
.find
= handle
;
1484 if (!FindNextFileW(handle
, &data
))
1490 if (is_dir_data(&data
))
1494 } while (FindNextFileW(handle
, &data
));
1496 return celt
? S_FALSE
: S_OK
;
1499 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1501 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1503 TRACE("(%p)\n", This
);
1505 FindClose(This
->data
.u
.foldercoll
.find
);
1506 This
->data
.u
.foldercoll
.find
= NULL
;
1511 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1513 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1514 TRACE("(%p)->(%p)\n", This
, pclone
);
1515 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1518 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1519 enumvariant_QueryInterface
,
1521 foldercoll_enumvariant_Release
,
1522 foldercoll_enumvariant_Next
,
1523 foldercoll_enumvariant_Skip
,
1524 foldercoll_enumvariant_Reset
,
1525 foldercoll_enumvariant_Clone
1528 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1530 struct enumvariant
*This
;
1534 This
= malloc(sizeof(*This
));
1535 if (!This
) return E_OUTOFMEMORY
;
1537 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1539 This
->data
.u
.foldercoll
.find
= NULL
;
1540 This
->data
.u
.foldercoll
.coll
= collection
;
1541 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1543 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1548 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1550 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1551 ULONG ref
= InterlockedDecrement(&This
->ref
);
1553 TRACE("%p, refcount %ld.\n", iface
, ref
);
1557 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1558 FindClose(This
->data
.u
.filecoll
.find
);
1565 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1567 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1568 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1569 WIN32_FIND_DATAW data
;
1572 TRACE("%p, %ld, %p, %p.\n", iface
, celt
, var
, fetched
);
1577 if (!celt
) return S_OK
;
1581 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1582 if (!handle
) return S_FALSE
;
1583 This
->data
.u
.filecoll
.find
= handle
;
1585 else if (!FindNextFileW(handle
, &data
))
1590 if (is_file_data(&data
))
1596 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1597 hr
= create_file(str
, &file
);
1599 if (FAILED(hr
)) return hr
;
1601 V_VT(&var
[count
]) = VT_DISPATCH
;
1602 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1603 if (++count
>= celt
) break;
1605 } while (FindNextFileW(handle
, &data
));
1610 return (count
< celt
) ? S_FALSE
: S_OK
;
1613 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1615 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1616 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1617 WIN32_FIND_DATAW data
;
1619 TRACE("%p, %lu.\n", iface
, celt
);
1621 if (!celt
) return S_OK
;
1625 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1626 if (!handle
) return S_FALSE
;
1627 This
->data
.u
.filecoll
.find
= handle
;
1629 else if (!FindNextFileW(handle
, &data
))
1634 if (is_file_data(&data
))
1636 } while (celt
&& FindNextFileW(handle
, &data
));
1638 return celt
? S_FALSE
: S_OK
;
1641 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1643 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1645 TRACE("(%p)\n", This
);
1647 FindClose(This
->data
.u
.filecoll
.find
);
1648 This
->data
.u
.filecoll
.find
= NULL
;
1653 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1655 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1656 TRACE("(%p)->(%p)\n", This
, pclone
);
1657 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1660 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1661 enumvariant_QueryInterface
,
1663 filecoll_enumvariant_Release
,
1664 filecoll_enumvariant_Next
,
1665 filecoll_enumvariant_Skip
,
1666 filecoll_enumvariant_Reset
,
1667 filecoll_enumvariant_Clone
1670 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1672 struct enumvariant
*This
;
1676 This
= malloc(sizeof(*This
));
1677 if (!This
) return E_OUTOFMEMORY
;
1679 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1681 This
->data
.u
.filecoll
.find
= NULL
;
1682 This
->data
.u
.filecoll
.coll
= collection
;
1683 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1685 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1690 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1692 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1693 ULONG ref
= InterlockedDecrement(&This
->ref
);
1695 TRACE("%p, refcount %ld.\n", iface
, ref
);
1699 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1706 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1708 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1711 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1713 penum
->data
.u
.drivecoll
.cur
= i
;
1720 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1722 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1725 TRACE("%p, %lu, %p, %p.\n", iface
, celt
, var
, fetched
);
1730 if (!celt
) return S_OK
;
1732 while (find_next_drive(This
) == S_OK
)
1737 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1738 if (FAILED(hr
)) return hr
;
1740 V_VT(&var
[count
]) = VT_DISPATCH
;
1741 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1743 if (++count
>= celt
) break;
1749 return (count
< celt
) ? S_FALSE
: S_OK
;
1752 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1754 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1756 TRACE("%p, %lu.\n", iface
, celt
);
1758 if (!celt
) return S_OK
;
1760 while (celt
&& find_next_drive(This
) == S_OK
)
1763 return celt
? S_FALSE
: S_OK
;
1766 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1768 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1770 TRACE("(%p)\n", This
);
1772 This
->data
.u
.drivecoll
.cur
= -1;
1776 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1778 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1779 TRACE("(%p)->(%p)\n", This
, pclone
);
1780 return create_drivecoll_enum(This
->data
.u
.drivecoll
.coll
, (IUnknown
**)pclone
);
1783 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1784 enumvariant_QueryInterface
,
1786 drivecoll_enumvariant_Release
,
1787 drivecoll_enumvariant_Next
,
1788 drivecoll_enumvariant_Skip
,
1789 drivecoll_enumvariant_Reset
,
1790 drivecoll_enumvariant_Clone
1793 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1795 struct enumvariant
*This
;
1799 This
= malloc(sizeof(*This
));
1800 if (!This
) return E_OUTOFMEMORY
;
1802 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1804 This
->data
.u
.drivecoll
.coll
= collection
;
1805 This
->data
.u
.drivecoll
.cur
= -1;
1806 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1808 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1813 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1815 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1817 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1821 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1822 IsEqualIID( riid
, &IID_IDispatch
) ||
1823 IsEqualIID( riid
, &IID_IUnknown
))
1825 *obj
= &This
->IFolderCollection_iface
;
1827 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
1829 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
1832 return E_NOINTERFACE
;
1834 IUnknown_AddRef((IUnknown
*)*obj
);
1838 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1840 struct foldercollection
*collection
= impl_from_IFolderCollection(iface
);
1841 ULONG ref
= InterlockedIncrement(&collection
->ref
);
1843 TRACE("%p, refcount %ld.\n", iface
, ref
);
1848 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1850 struct foldercollection
*collection
= impl_from_IFolderCollection(iface
);
1851 ULONG ref
= InterlockedDecrement(&collection
->ref
);
1853 TRACE("%p, refcount %ld.\n", iface
, ref
);
1857 SysFreeString(collection
->path
);
1864 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1866 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1867 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1872 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1873 LCID lcid
, ITypeInfo
**ppTInfo
)
1875 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1877 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1880 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1881 LPOLESTR
*rgszNames
, UINT cNames
,
1882 LCID lcid
, DISPID
*rgDispId
)
1884 ITypeInfo
*typeinfo
;
1887 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1889 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1892 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1893 ITypeInfo_Release(typeinfo
);
1899 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1900 REFIID riid
, LCID lcid
, WORD wFlags
,
1901 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1902 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1904 ITypeInfo
*typeinfo
;
1907 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1908 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1910 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1913 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1914 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1915 ITypeInfo_Release(typeinfo
);
1921 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1923 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1924 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1928 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1930 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1931 FIXME("(%p)->(%p): stub\n", This
, folder
);
1935 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1937 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1939 TRACE("(%p)->(%p)\n", This
, newenum
);
1944 return create_foldercoll_enum(This
, newenum
);
1947 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1949 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1950 WIN32_FIND_DATAW data
;
1951 WCHAR pathW
[MAX_PATH
];
1954 TRACE("(%p)->(%p)\n", This
, count
);
1961 wcscpy(pathW
, This
->path
);
1962 wcscat(pathW
, L
"\\*");
1963 handle
= FindFirstFileW(pathW
, &data
);
1964 if (handle
== INVALID_HANDLE_VALUE
)
1965 return HRESULT_FROM_WIN32(GetLastError());
1969 if (is_dir_data(&data
))
1971 } while (FindNextFileW(handle
, &data
));
1977 static const IFolderCollectionVtbl foldercollvtbl
= {
1978 foldercoll_QueryInterface
,
1981 foldercoll_GetTypeInfoCount
,
1982 foldercoll_GetTypeInfo
,
1983 foldercoll_GetIDsOfNames
,
1986 foldercoll_get_Item
,
1987 foldercoll_get__NewEnum
,
1988 foldercoll_get_Count
1991 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1993 struct foldercollection
*This
;
1997 This
= malloc(sizeof(*This
));
1998 if (!This
) return E_OUTOFMEMORY
;
2000 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
2002 This
->path
= SysAllocString(path
);
2006 return E_OUTOFMEMORY
;
2009 init_classinfo(&CLSID_Folders
, (IUnknown
*)&This
->IFolderCollection_iface
, &This
->classinfo
);
2010 *folders
= &This
->IFolderCollection_iface
;
2015 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
2017 struct filecollection
*This
= impl_from_IFileCollection(iface
);
2019 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2023 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
2024 IsEqualIID( riid
, &IID_IDispatch
) ||
2025 IsEqualIID( riid
, &IID_IUnknown
))
2027 *obj
= &This
->IFileCollection_iface
;
2029 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2031 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2034 return E_NOINTERFACE
;
2036 IUnknown_AddRef((IUnknown
*)*obj
);
2040 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
2042 struct filecollection
*collection
= impl_from_IFileCollection(iface
);
2043 ULONG ref
= InterlockedIncrement(&collection
->ref
);
2045 TRACE("%p, refcount %ld.\n", iface
, ref
);
2050 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
2052 struct filecollection
*collection
= impl_from_IFileCollection(iface
);
2053 ULONG ref
= InterlockedDecrement(&collection
->ref
);
2055 TRACE("%p, refcount %ld.\n", iface
, ref
);
2059 SysFreeString(collection
->path
);
2066 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
2068 struct filecollection
*This
= impl_from_IFileCollection(iface
);
2069 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2074 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
2075 LCID lcid
, ITypeInfo
**ppTInfo
)
2077 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
2079 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
2082 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
2083 LPOLESTR
*rgszNames
, UINT cNames
,
2084 LCID lcid
, DISPID
*rgDispId
)
2086 ITypeInfo
*typeinfo
;
2089 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2091 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
2094 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2095 ITypeInfo_Release(typeinfo
);
2101 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
2102 REFIID riid
, LCID lcid
, WORD wFlags
,
2103 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2104 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2106 ITypeInfo
*typeinfo
;
2109 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
2110 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2112 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
2115 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2116 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2117 ITypeInfo_Release(typeinfo
);
2123 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
2125 struct filecollection
*This
= impl_from_IFileCollection(iface
);
2126 FIXME("(%p)->(%p)\n", This
, file
);
2130 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
2132 struct filecollection
*This
= impl_from_IFileCollection(iface
);
2134 TRACE("(%p)->(%p)\n", This
, ppenum
);
2139 return create_filecoll_enum(This
, ppenum
);
2142 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
2144 struct filecollection
*This
= impl_from_IFileCollection(iface
);
2145 WIN32_FIND_DATAW data
;
2146 WCHAR pathW
[MAX_PATH
];
2149 TRACE("(%p)->(%p)\n", This
, count
);
2156 wcscpy(pathW
, This
->path
);
2157 wcscat(pathW
, L
"\\*");
2158 handle
= FindFirstFileW(pathW
, &data
);
2159 if (handle
== INVALID_HANDLE_VALUE
)
2160 return HRESULT_FROM_WIN32(GetLastError());
2164 if (is_file_data(&data
))
2166 } while (FindNextFileW(handle
, &data
));
2172 static const IFileCollectionVtbl filecollectionvtbl
= {
2173 filecoll_QueryInterface
,
2176 filecoll_GetTypeInfoCount
,
2177 filecoll_GetTypeInfo
,
2178 filecoll_GetIDsOfNames
,
2181 filecoll_get__NewEnum
,
2185 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
2187 struct filecollection
*This
;
2191 This
= malloc(sizeof(*This
));
2192 if (!This
) return E_OUTOFMEMORY
;
2194 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
2196 This
->path
= SysAllocString(path
);
2200 return E_OUTOFMEMORY
;
2203 init_classinfo(&CLSID_Files
, (IUnknown
*)&This
->IFileCollection_iface
, &This
->classinfo
);
2204 *files
= &This
->IFileCollection_iface
;
2208 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
2210 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2212 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2216 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
2217 IsEqualIID( riid
, &IID_IDispatch
) ||
2218 IsEqualIID( riid
, &IID_IUnknown
))
2220 *obj
= &This
->IDriveCollection_iface
;
2222 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2224 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2227 return E_NOINTERFACE
;
2229 IUnknown_AddRef((IUnknown
*)*obj
);
2233 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
2235 struct drivecollection
*collection
= impl_from_IDriveCollection(iface
);
2236 ULONG ref
= InterlockedIncrement(&collection
->ref
);
2238 TRACE("%p, refcount %ld.\n", iface
, ref
);
2243 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
2245 struct drivecollection
*collection
= impl_from_IDriveCollection(iface
);
2246 ULONG ref
= InterlockedDecrement(&collection
->ref
);
2248 TRACE("%p, refcount %ld.\n", iface
, ref
);
2256 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
2258 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2259 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2264 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
2265 LCID lcid
, ITypeInfo
**ppTInfo
)
2267 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
2269 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
2272 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
2273 LPOLESTR
*rgszNames
, UINT cNames
,
2274 LCID lcid
, DISPID
*rgDispId
)
2276 ITypeInfo
*typeinfo
;
2279 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2281 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2284 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2285 ITypeInfo_Release(typeinfo
);
2291 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
2292 REFIID riid
, LCID lcid
, WORD wFlags
,
2293 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2294 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2296 ITypeInfo
*typeinfo
;
2299 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
2300 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2302 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2305 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2306 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2307 ITypeInfo_Release(typeinfo
);
2313 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2315 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2316 FIXME("(%p)->(%p): stub\n", This
, drive
);
2320 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2322 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2324 TRACE("(%p)->(%p)\n", This
, ppenum
);
2329 return create_drivecoll_enum(This
, ppenum
);
2332 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2334 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2336 TRACE("(%p)->(%p)\n", This
, count
);
2338 if (!count
) return E_POINTER
;
2340 *count
= This
->count
;
2344 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2345 drivecoll_QueryInterface
,
2348 drivecoll_GetTypeInfoCount
,
2349 drivecoll_GetTypeInfo
,
2350 drivecoll_GetIDsOfNames
,
2353 drivecoll_get__NewEnum
,
2357 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2359 struct drivecollection
*This
;
2364 This
= malloc(sizeof(*This
));
2365 if (!This
) return E_OUTOFMEMORY
;
2367 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2369 This
->drives
= mask
= GetLogicalDrives();
2370 /* count set bits */
2371 for (This
->count
= 0; mask
; This
->count
++)
2374 init_classinfo(&CLSID_Drives
, (IUnknown
*)&This
->IDriveCollection_iface
, &This
->classinfo
);
2375 *drives
= &This
->IDriveCollection_iface
;
2379 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2381 struct folder
*This
= impl_from_IFolder(iface
);
2383 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2387 if (IsEqualIID( riid
, &IID_IFolder
) ||
2388 IsEqualIID( riid
, &IID_IDispatch
) ||
2389 IsEqualIID( riid
, &IID_IUnknown
))
2391 *obj
= &This
->IFolder_iface
;
2393 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2395 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2398 return E_NOINTERFACE
;
2400 IUnknown_AddRef((IUnknown
*)*obj
);
2404 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2406 struct folder
*folder
= impl_from_IFolder(iface
);
2407 ULONG ref
= InterlockedIncrement(&folder
->ref
);
2409 TRACE("%p, refcount %ld.\n", iface
, ref
);
2414 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2416 struct folder
*folder
= impl_from_IFolder(iface
);
2417 ULONG ref
= InterlockedDecrement(&folder
->ref
);
2419 TRACE("%p, refcount %ld.\n", iface
, ref
);
2423 SysFreeString(folder
->path
);
2430 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2432 struct folder
*This
= impl_from_IFolder(iface
);
2433 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2438 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2439 LCID lcid
, ITypeInfo
**ppTInfo
)
2441 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
2443 return get_typeinfo(IFolder_tid
, ppTInfo
);
2446 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2447 LPOLESTR
*rgszNames
, UINT cNames
,
2448 LCID lcid
, DISPID
*rgDispId
)
2450 ITypeInfo
*typeinfo
;
2453 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2455 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2458 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2459 ITypeInfo_Release(typeinfo
);
2465 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2466 REFIID riid
, LCID lcid
, WORD wFlags
,
2467 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2468 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2470 ITypeInfo
*typeinfo
;
2473 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
2474 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2476 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2479 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2480 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2481 ITypeInfo_Release(typeinfo
);
2487 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2489 struct folder
*This
= impl_from_IFolder(iface
);
2491 TRACE("(%p)->(%p)\n", This
, path
);
2496 *path
= SysAllocString(This
->path
);
2497 return *path
? S_OK
: E_OUTOFMEMORY
;
2500 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2502 struct folder
*This
= impl_from_IFolder(iface
);
2505 TRACE("(%p)->(%p)\n", This
, name
);
2512 ptr
= wcsrchr(This
->path
, '\\');
2515 *name
= SysAllocString(ptr
+1);
2516 TRACE("%s\n", debugstr_w(*name
));
2517 if (!*name
) return E_OUTOFMEMORY
;
2525 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2527 struct folder
*This
= impl_from_IFolder(iface
);
2528 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2532 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2534 struct folder
*This
= impl_from_IFolder(iface
);
2535 FIXME("(%p)->(%p): stub\n", This
, path
);
2539 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2541 struct folder
*This
= impl_from_IFolder(iface
);
2542 FIXME("(%p)->(%p): stub\n", This
, name
);
2546 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2548 struct folder
*This
= impl_from_IFolder(iface
);
2549 FIXME("(%p)->(%p): stub\n", This
, drive
);
2553 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2555 struct folder
*This
= impl_from_IFolder(iface
);
2556 FIXME("(%p)->(%p): stub\n", This
, parent
);
2560 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2562 struct folder
*This
= impl_from_IFolder(iface
);
2563 FIXME("(%p)->(%p): stub\n", This
, attr
);
2567 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2569 struct folder
*This
= impl_from_IFolder(iface
);
2570 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2574 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2576 struct folder
*This
= impl_from_IFolder(iface
);
2577 FIXME("(%p)->(%p): stub\n", This
, date
);
2581 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2583 struct folder
*This
= impl_from_IFolder(iface
);
2584 FIXME("(%p)->(%p): stub\n", This
, date
);
2588 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2590 struct folder
*This
= impl_from_IFolder(iface
);
2591 FIXME("(%p)->(%p): stub\n", This
, date
);
2595 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2597 struct folder
*This
= impl_from_IFolder(iface
);
2598 FIXME("(%p)->(%p): stub\n", This
, type
);
2602 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2604 struct folder
*This
= impl_from_IFolder(iface
);
2605 FIXME("(%p)->(%x): stub\n", This
, force
);
2609 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2611 struct folder
*This
= impl_from_IFolder(iface
);
2612 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2616 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2618 struct folder
*This
= impl_from_IFolder(iface
);
2619 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2623 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2625 struct folder
*This
= impl_from_IFolder(iface
);
2626 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2630 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2632 struct folder
*This
= impl_from_IFolder(iface
);
2633 FIXME("(%p)->(%p): stub\n", This
, size
);
2637 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2639 struct folder
*This
= impl_from_IFolder(iface
);
2641 TRACE("(%p)->(%p)\n", This
, folders
);
2646 return create_foldercoll(This
->path
, folders
);
2649 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2651 struct folder
*This
= impl_from_IFolder(iface
);
2653 TRACE("(%p)->(%p)\n", This
, files
);
2658 return create_filecoll(This
->path
, files
);
2661 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2662 VARIANT_BOOL unicode
, ITextStream
**stream
)
2668 struct folder
*This
= impl_from_IFolder(iface
);
2670 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2672 hres
= build_path(This
->path
, filename
, &path
);
2673 if (FAILED(hres
)) return hres
;
2675 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
2676 hres
= create_textstream(path
, disposition
, ForWriting
, unicode
? TristateTrue
: TristateFalse
, stream
);
2677 SysFreeString(path
);
2681 static const IFolderVtbl foldervtbl
= {
2682 folder_QueryInterface
,
2685 folder_GetTypeInfoCount
,
2687 folder_GetIDsOfNames
,
2692 folder_get_ShortPath
,
2693 folder_get_ShortName
,
2695 folder_get_ParentFolder
,
2696 folder_get_Attributes
,
2697 folder_put_Attributes
,
2698 folder_get_DateCreated
,
2699 folder_get_DateLastModified
,
2700 folder_get_DateLastAccessed
,
2705 folder_get_IsRootFolder
,
2707 folder_get_SubFolders
,
2709 folder_CreateTextFile
2712 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2714 struct folder
*object
;
2719 TRACE("%s\n", debugstr_w(path
));
2721 if (!(object
= malloc(sizeof(*object
))))
2722 return E_OUTOFMEMORY
;
2724 object
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2727 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2734 object
->path
= SysAllocStringLen(NULL
, len
);
2738 return E_OUTOFMEMORY
;
2741 if (!GetFullPathNameW(path
, len
, object
->path
, NULL
))
2743 SysFreeString(object
->path
);
2748 init_classinfo(&CLSID_Folder
, (IUnknown
*)&object
->IFolder_iface
, &object
->classinfo
);
2749 *folder
= &object
->IFolder_iface
;
2754 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2756 struct file
*This
= impl_from_IFile(iface
);
2758 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2762 if (IsEqualIID(riid
, &IID_IFile
) ||
2763 IsEqualIID(riid
, &IID_IDispatch
) ||
2764 IsEqualIID(riid
, &IID_IUnknown
))
2766 *obj
= &This
->IFile_iface
;
2768 else if (IsEqualIID( riid
, &IID_IProvideClassInfo
))
2770 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
2773 return E_NOINTERFACE
;
2775 IUnknown_AddRef((IUnknown
*)*obj
);
2779 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2781 struct file
*file
= impl_from_IFile(iface
);
2782 LONG ref
= InterlockedIncrement(&file
->ref
);
2784 TRACE("%p, refcount %ld.\n", iface
, ref
);
2789 static ULONG WINAPI
file_Release(IFile
*iface
)
2791 struct file
*file
= impl_from_IFile(iface
);
2792 LONG ref
= InterlockedDecrement(&file
->ref
);
2794 TRACE("%p, refcount %ld.\n", iface
, ref
);
2805 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2807 struct file
*This
= impl_from_IFile(iface
);
2809 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2815 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2816 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2818 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
2820 return get_typeinfo(IFile_tid
, ppTInfo
);
2823 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2824 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2826 ITypeInfo
*typeinfo
;
2829 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
),
2830 rgszNames
, cNames
, lcid
, rgDispId
);
2832 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2834 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2835 ITypeInfo_Release(typeinfo
);
2840 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
,
2841 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2843 ITypeInfo
*typeinfo
;
2846 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
2847 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2849 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2852 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2853 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2854 ITypeInfo_Release(typeinfo
);
2859 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*path
)
2861 struct file
*This
= impl_from_IFile(iface
);
2863 TRACE("(%p)->(%p)\n", This
, path
);
2868 *path
= SysAllocString(This
->path
);
2870 return E_OUTOFMEMORY
;
2875 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2877 struct file
*This
= impl_from_IFile(iface
);
2880 TRACE("(%p)->(%p)\n", This
, name
);
2887 ptr
= wcsrchr(This
->path
, '\\');
2890 *name
= SysAllocString(ptr
+1);
2891 TRACE("%s\n", debugstr_w(*name
));
2892 if (!*name
) return E_OUTOFMEMORY
;
2900 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2902 struct file
*This
= impl_from_IFile(iface
);
2903 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2907 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2909 struct file
*This
= impl_from_IFile(iface
);
2910 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2914 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2916 struct file
*This
= impl_from_IFile(iface
);
2917 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2921 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2923 struct file
*This
= impl_from_IFile(iface
);
2924 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2928 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2930 struct file
*This
= impl_from_IFile(iface
);
2931 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2935 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2937 struct file
*This
= impl_from_IFile(iface
);
2940 TRACE("(%p)->(%p)\n", This
, pfa
);
2945 fa
= GetFileAttributesW(This
->path
);
2946 if(fa
== INVALID_FILE_ATTRIBUTES
)
2947 return create_error(GetLastError());
2949 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2950 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2951 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2955 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2957 struct file
*This
= impl_from_IFile(iface
);
2959 TRACE("(%p)->(%x)\n", This
, pfa
);
2961 return SetFileAttributesW(This
->path
, pfa
) ? S_OK
: create_error(GetLastError());
2964 static HRESULT
get_date_from_filetime(const FILETIME
*ft
, DATE
*date
)
2972 FileTimeToLocalFileTime(ft
, &ftlocal
);
2973 FileTimeToSystemTime(&ftlocal
, &st
);
2974 SystemTimeToVariantTime(&st
, date
);
2979 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*date
)
2981 struct file
*This
= impl_from_IFile(iface
);
2982 WIN32_FILE_ATTRIBUTE_DATA attrs
;
2984 TRACE("(%p)->(%p)\n", This
, date
);
2986 if (GetFileAttributesExW(This
->path
, GetFileExInfoStandard
, &attrs
))
2987 return get_date_from_filetime(&attrs
.ftCreationTime
, date
);
2992 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*date
)
2994 struct file
*This
= impl_from_IFile(iface
);
2995 WIN32_FILE_ATTRIBUTE_DATA attrs
;
2997 TRACE("(%p)->(%p)\n", This
, date
);
2999 if (GetFileAttributesExW(This
->path
, GetFileExInfoStandard
, &attrs
))
3000 return get_date_from_filetime(&attrs
.ftLastWriteTime
, date
);
3005 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
3007 struct file
*This
= impl_from_IFile(iface
);
3008 FIXME("(%p)->(%p)\n", This
, pdate
);
3012 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
3014 struct file
*This
= impl_from_IFile(iface
);
3015 ULARGE_INTEGER size
;
3016 WIN32_FIND_DATAW fd
;
3019 TRACE("(%p)->(%p)\n", This
, pvarSize
);
3024 f
= FindFirstFileW(This
->path
, &fd
);
3025 if(f
== INVALID_HANDLE_VALUE
)
3026 return create_error(GetLastError());
3029 size
.u
.LowPart
= fd
.nFileSizeLow
;
3030 size
.u
.HighPart
= fd
.nFileSizeHigh
;
3032 return variant_from_largeint(&size
, pvarSize
);
3035 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
3037 struct file
*This
= impl_from_IFile(iface
);
3038 FIXME("(%p)->(%p)\n", This
, pbstrType
);
3042 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
3044 struct file
*This
= impl_from_IFile(iface
);
3045 FIXME("(%p)->(%x)\n", This
, Force
);
3049 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3051 struct file
*This
= impl_from_IFile(iface
);
3052 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
3056 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
3058 struct file
*This
= impl_from_IFile(iface
);
3059 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
3063 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
3065 struct file
*This
= impl_from_IFile(iface
);
3067 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
3069 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
, stream
);
3072 static const IFileVtbl file_vtbl
= {
3073 file_QueryInterface
,
3076 file_GetTypeInfoCount
,
3086 file_get_ParentFolder
,
3087 file_get_Attributes
,
3088 file_put_Attributes
,
3089 file_get_DateCreated
,
3090 file_get_DateLastModified
,
3091 file_get_DateLastAccessed
,
3097 file_OpenAsTextStream
3100 static HRESULT
create_file(BSTR path
, IFile
**file
)
3107 f
= malloc(sizeof(struct file
));
3109 return E_OUTOFMEMORY
;
3111 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
3114 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
3121 f
->path
= malloc(len
*sizeof(WCHAR
));
3125 return E_OUTOFMEMORY
;
3128 if (!GetFullPathNameW(path
, len
, f
->path
, NULL
))
3135 attrs
= GetFileAttributesW(f
->path
);
3136 if (attrs
== INVALID_FILE_ATTRIBUTES
|| (attrs
& (FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_DEVICE
)))
3140 return create_error(GetLastError());
3143 init_classinfo(&CLSID_File
, (IUnknown
*)&f
->IFile_iface
, &f
->classinfo
);
3144 *file
= &f
->IFile_iface
;
3148 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
3150 struct filesystem
*This
= impl_from_IFileSystem3(iface
);
3152 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
3154 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
3155 IsEqualGUID( riid
, &IID_IFileSystem
) ||
3156 IsEqualGUID( riid
, &IID_IDispatch
) ||
3157 IsEqualGUID( riid
, &IID_IUnknown
) )
3159 *ppvObject
= &This
->IFileSystem3_iface
;
3161 else if (IsEqualGUID( riid
, &IID_IProvideClassInfo
))
3163 *ppvObject
= &This
->classinfo
.IProvideClassInfo_iface
;
3165 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
3167 TRACE("Interface IDispatchEx not supported - returning NULL\n");
3169 return E_NOINTERFACE
;
3171 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
3173 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
3175 return E_NOINTERFACE
;
3179 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
3180 return E_NOINTERFACE
;
3183 IUnknown_AddRef((IUnknown
*)*ppvObject
);
3188 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
3190 TRACE("%p\n", iface
);
3195 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
3197 TRACE("%p\n", iface
);
3202 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
3204 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
3210 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
3211 LCID lcid
, ITypeInfo
**ppTInfo
)
3213 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
3215 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
3218 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
3219 LPOLESTR
*rgszNames
, UINT cNames
,
3220 LCID lcid
, DISPID
*rgDispId
)
3222 ITypeInfo
*typeinfo
;
3225 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
3227 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
3230 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
3231 ITypeInfo_Release(typeinfo
);
3237 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
3238 REFIID riid
, LCID lcid
, WORD wFlags
,
3239 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
3240 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
3242 ITypeInfo
*typeinfo
;
3245 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
3246 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
3248 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
3251 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
3252 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
3253 ITypeInfo_Release(typeinfo
);
3259 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
3261 TRACE("%p %p\n", iface
, ppdrives
);
3262 return create_drivecoll(ppdrives
);
3265 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
3266 BSTR Name
, BSTR
*Result
)
3268 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
3270 if (!Result
) return E_POINTER
;
3272 return build_path(Path
, Name
, Result
);
3275 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR path
, BSTR
*drive
)
3277 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), drive
);
3284 if (path
&& lstrlenW(path
) > 1 && path
[1] == ':')
3285 *drive
= SysAllocStringLen(path
, 2);
3290 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
3297 for(i
=len
-1; i
>=0; i
--)
3298 if(path
[i
]!='/' && path
[i
]!='\\')
3302 if(path
[i
]=='/' || path
[i
]=='\\')
3306 if(path
[i
]!='/' && path
[i
]!='\\')
3312 if(path
[i
]==':' && i
==1)
3317 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
3322 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3327 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
3329 *pbstrResult
= NULL
;
3333 *pbstrResult
= SysAllocStringLen(Path
, len
);
3335 return E_OUTOFMEMORY
;
3339 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3344 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3350 *pbstrResult
= NULL
;
3354 for(end
=lstrlenW(Path
)-1; end
>=0; end
--)
3355 if(Path
[end
]!='/' && Path
[end
]!='\\')
3358 for(i
=end
; i
>=0; i
--)
3359 if(Path
[i
]=='/' || Path
[i
]=='\\')
3363 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3364 *pbstrResult
= NULL
;
3368 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3370 return E_OUTOFMEMORY
;
3374 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3379 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3385 *pbstrResult
= NULL
;
3389 for(end
=lstrlenW(Path
)-1; end
>=0; end
--)
3390 if(Path
[end
]!='/' && Path
[end
]!='\\')
3393 for(i
=end
; i
>=0; i
--) {
3394 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3396 if(Path
[i
]=='/' || Path
[i
]=='\\')
3401 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3402 *pbstrResult
= NULL
;
3406 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3408 return E_OUTOFMEMORY
;
3412 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR path
,
3417 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ext
);
3420 len
= SysStringLen(path
);
3422 if (path
[len
-1] == '.') {
3423 *ext
= SysAllocString(&path
[len
]);
3425 return E_OUTOFMEMORY
;
3434 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR path
, BSTR
*pbstrResult
)
3436 WCHAR buf
[MAX_PATH
], ch
;
3437 DWORD i
, beg
, len
, exp_len
;
3438 WIN32_FIND_DATAW fdata
;
3441 TRACE("%p, %s, %p.\n", iface
, debugstr_w(path
), pbstrResult
);
3446 len
= GetFullPathNameW(path
? path
: L
".", MAX_PATH
, buf
, NULL
);
3450 buf
[0] = towupper(buf
[0]);
3451 if(len
>3 && buf
[len
-1] == '\\')
3454 for(beg
=3, i
=3; i
<=len
; i
++) {
3455 if(buf
[i
]!='\\' && buf
[i
])
3460 fh
= FindFirstFileW(buf
, &fdata
);
3461 if(fh
== INVALID_HANDLE_VALUE
)
3464 exp_len
= lstrlenW(fdata
.cFileName
);
3465 if(exp_len
== i
-beg
)
3466 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3472 *pbstrResult
= SysAllocString(buf
);
3474 return E_OUTOFMEMORY
;
3478 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*result
)
3482 TRACE("%p, %p.\n", iface
, result
);
3487 if (!(*result
= SysAllocStringLen(NULL
, 12)))
3488 return E_OUTOFMEMORY
;
3490 if(!RtlGenRandom(&random
, sizeof(random
)))
3492 SysFreeString(*result
);
3496 swprintf(*result
, 13, L
"rad%05X.tmp", random
& 0xfffff);
3500 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3501 VARIANT_BOOL
*pfExists
)
3505 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3507 if (!pfExists
) return E_POINTER
;
3509 *pfExists
= VARIANT_FALSE
;
3510 len
= SysStringLen(DriveSpec
);
3513 driveletter
= towupper(DriveSpec
[0]);
3514 if (driveletter
>= 'A' && driveletter
<= 'Z'
3515 && (len
< 2 || DriveSpec
[1] == ':')
3516 && (len
< 3 || DriveSpec
[2] == '\\')) {
3517 const WCHAR root
[] = {driveletter
, ':', '\\', 0};
3518 UINT drivetype
= GetDriveTypeW(root
);
3519 *pfExists
= drivetype
!= DRIVE_NO_ROOT_DIR
&& drivetype
!= DRIVE_UNKNOWN
? VARIANT_TRUE
: VARIANT_FALSE
;
3526 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3529 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3531 if (!ret
) return E_POINTER
;
3533 attrs
= GetFileAttributesW(path
);
3534 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3538 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3541 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3543 if (!ret
) return E_POINTER
;
3545 attrs
= GetFileAttributesW(path
);
3546 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3551 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3557 VARIANT_BOOL drive_exists
;
3559 TRACE("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3566 /* DriveSpec may be one of: 'x', 'x:', 'x:\', '\\computer\share' */
3567 len
= SysStringLen(DriveSpec
);
3569 return E_INVALIDARG
;
3570 else if (len
<= 3) {
3571 driveletter
= towupper(DriveSpec
[0]);
3572 if (driveletter
< 'A' || driveletter
> 'Z'
3573 || (len
>= 2 && DriveSpec
[1] != ':')
3574 || (len
== 3 && DriveSpec
[2] != '\\'))
3575 return E_INVALIDARG
;
3576 hr
= IFileSystem3_DriveExists(iface
, DriveSpec
, &drive_exists
);
3579 if (drive_exists
== VARIANT_FALSE
)
3580 return CTL_E_DEVICEUNAVAILABLE
;
3581 return create_drive(driveletter
, ppdrive
);
3583 if (DriveSpec
[0] != '\\' || DriveSpec
[1] != '\\')
3584 return E_INVALIDARG
;
3585 FIXME("%s not implemented yet\n", debugstr_w(DriveSpec
));
3590 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3593 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3598 return E_INVALIDARG
;
3600 return create_file(FilePath
, ppfile
);
3603 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3608 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3615 return E_INVALIDARG
;
3617 attrs
= GetFileAttributesW(FolderPath
);
3618 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3619 return CTL_E_PATHNOTFOUND
;
3621 return create_folder(FolderPath
, folder
);
3624 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3625 SpecialFolderConst SpecialFolder
,
3628 WCHAR pathW
[MAX_PATH
];
3631 TRACE("%p %d %p\n", iface
, SpecialFolder
, folder
);
3638 switch (SpecialFolder
)
3641 ret
= GetWindowsDirectoryW(pathW
, ARRAY_SIZE(pathW
));
3644 ret
= GetSystemDirectoryW(pathW
, ARRAY_SIZE(pathW
));
3646 case TemporaryFolder
:
3647 ret
= GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
3648 /* we don't want trailing backslash */
3649 if (ret
&& pathW
[ret
-1] == '\\')
3653 FIXME("unknown special folder type, %d\n", SpecialFolder
);
3654 return E_INVALIDARG
;
3658 return HRESULT_FROM_WIN32(GetLastError());
3660 return create_folder(pathW
, folder
);
3663 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3665 WCHAR path
[MAX_PATH
];
3666 DWORD len
, name_len
;
3667 WIN32_FIND_DATAW ffd
;
3670 f
= FindFirstFileW(file
, &ffd
);
3671 if(f
== INVALID_HANDLE_VALUE
)
3672 return create_error(GetLastError());
3674 len
= get_parent_folder_name(file
, file_len
);
3675 if(len
+1 >= MAX_PATH
) {
3680 memcpy(path
, file
, len
*sizeof(WCHAR
));
3685 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3688 name_len
= lstrlenW(ffd
.cFileName
);
3689 if(len
+name_len
+1 >= MAX_PATH
) {
3693 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3695 TRACE("deleting %s\n", debugstr_w(path
));
3697 if(!DeleteFileW(path
)) {
3698 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3699 || !DeleteFileW(path
)) {
3701 return create_error(GetLastError());
3704 } while(FindNextFileW(f
, &ffd
));
3710 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3713 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3718 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3721 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3723 WCHAR path
[MAX_PATH
];
3724 DWORD len
, name_len
;
3725 WIN32_FIND_DATAW ffd
;
3729 f
= FindFirstFileW(folder
, &ffd
);
3730 if(f
== INVALID_HANDLE_VALUE
)
3731 return create_error(GetLastError());
3733 len
= get_parent_folder_name(folder
, folder_len
);
3734 if(len
+1 >= MAX_PATH
) {
3739 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3744 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3746 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3747 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3750 name_len
= lstrlenW(ffd
.cFileName
);
3751 if(len
+name_len
+3 >= MAX_PATH
) {
3755 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3756 path
[len
+name_len
] = '\\';
3757 path
[len
+name_len
+1] = '*';
3758 path
[len
+name_len
+2] = 0;
3760 hr
= delete_file(path
, len
+name_len
+2, force
);
3766 hr
= delete_folder(path
, len
+name_len
+2, force
);
3772 path
[len
+name_len
] = 0;
3773 TRACE("deleting %s\n", debugstr_w(path
));
3775 if(!RemoveDirectoryW(path
)) {
3777 return create_error(GetLastError());
3779 } while(FindNextFileW(f
, &ffd
));
3785 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3788 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3793 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3796 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR source
, BSTR destination
)
3798 TRACE("%p %s %s\n", iface
, debugstr_w(source
), debugstr_w(destination
));
3800 if(!source
|| !destination
)
3801 return E_INVALIDARG
;
3803 return MoveFileW(source
, destination
) ? S_OK
: create_error(GetLastError());
3806 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3809 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3814 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3815 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3818 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3819 DWORD src_len
, dst_len
, name_len
;
3820 WIN32_FIND_DATAW ffd
;
3824 if(!source
[0] || !destination
[0])
3825 return E_INVALIDARG
;
3827 attrs
= GetFileAttributesW(destination
);
3828 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3829 attrs
= GetFileAttributesW(source
);
3830 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3831 return create_error(GetLastError());
3832 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3833 return CTL_E_FILENOTFOUND
;
3835 if(!CopyFileW(source
, destination
, !overwrite
))
3836 return create_error(GetLastError());
3840 f
= FindFirstFileW(source
, &ffd
);
3841 if(f
== INVALID_HANDLE_VALUE
)
3842 return CTL_E_FILENOTFOUND
;
3844 src_len
= get_parent_folder_name(source
, source_len
);
3845 if(src_len
+1 >= MAX_PATH
) {
3850 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3851 src_path
[src_len
++] = '\\';
3854 dst_len
= destination_len
;
3855 if(dst_len
+1 >= MAX_PATH
) {
3859 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3860 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3861 dst_path
[dst_len
++] = '\\';
3863 hr
= CTL_E_FILENOTFOUND
;
3865 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3868 name_len
= lstrlenW(ffd
.cFileName
);
3869 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3873 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3874 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3876 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3878 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3880 return create_error(GetLastError());
3884 } while(FindNextFileW(f
, &ffd
));
3890 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3891 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3893 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3895 if(!Source
|| !Destination
)
3898 return copy_file(Source
, SysStringLen(Source
), Destination
,
3899 SysStringLen(Destination
), OverWriteFiles
);
3902 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3903 DWORD destination_len
, VARIANT_BOOL overwrite
)
3905 DWORD tmp
, src_len
, dst_len
, name_len
;
3906 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3907 WIN32_FIND_DATAW ffd
;
3910 BOOL copied
= FALSE
;
3912 if(!source
[0] || !destination
[0])
3913 return E_INVALIDARG
;
3915 dst_len
= destination_len
;
3916 if(dst_len
+1 >= MAX_PATH
)
3918 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3920 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3921 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3922 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3923 if(!CreateDirectoryW(dst
, NULL
)) {
3924 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3925 tmp
= GetFileAttributesW(dst
);
3926 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3927 return CTL_E_FILEALREADYEXISTS
;
3929 return create_error(GetLastError());
3934 src_len
= source_len
;
3935 if(src_len
+2 >= MAX_PATH
)
3937 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3938 src
[src_len
++] = '\\';
3942 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3943 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3944 return create_error(GetLastError());
3946 f
= FindFirstFileW(src
, &ffd
);
3948 src_len
= get_parent_folder_name(source
, source_len
);
3949 if(src_len
+2 >= MAX_PATH
)
3951 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3953 src
[src_len
++] = '\\';
3955 f
= FindFirstFileW(source
, &ffd
);
3957 if(f
== INVALID_HANDLE_VALUE
)
3958 return CTL_E_PATHNOTFOUND
;
3960 dst
[dst_len
++] = '\\';
3964 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3966 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3967 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3970 name_len
= lstrlenW(ffd
.cFileName
);
3971 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3975 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3976 dst
[dst_len
+name_len
] = 0;
3977 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3978 src
[src_len
+name_len
] = '\\';
3979 src
[src_len
+name_len
+1] = '*';
3980 src
[src_len
+name_len
+2] = 0;
3982 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3984 if(!CreateDirectoryW(dst
, NULL
)) {
3985 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3986 tmp
= GetFileAttributesW(dst
);
3987 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3989 return CTL_E_FILEALREADYEXISTS
;
3994 return create_error(GetLastError());
3998 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3999 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
4004 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
4005 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
4009 } while(FindNextFileW(f
, &ffd
));
4012 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
4015 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
4016 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
4018 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
4020 if(!Source
|| !Destination
)
4023 return copy_folder(Source
, SysStringLen(Source
), Destination
,
4024 SysStringLen(Destination
), OverWriteFiles
);
4027 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
4032 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
4034 ret
= CreateDirectoryW(path
, NULL
);
4038 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
4039 return HRESULT_FROM_WIN32(GetLastError());
4042 return create_folder(path
, folder
);
4045 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
4046 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
4047 ITextStream
**stream
)
4051 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
4053 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
4054 return create_textstream(filename
, disposition
, ForWriting
, unicode
? TristateTrue
: TristateFalse
, stream
);
4057 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
4058 IOMode mode
, VARIANT_BOOL create
,
4059 Tristate format
, ITextStream
**stream
)
4063 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
4065 if(mode
== ForWriting
) {
4066 disposition
= create
== VARIANT_TRUE
? CREATE_ALWAYS
: TRUNCATE_EXISTING
;
4068 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
4070 return create_textstream(filename
, disposition
, mode
, format
, stream
);
4073 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
4074 StandardStreamTypes StandardStreamType
,
4075 VARIANT_BOOL Unicode
,
4078 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
4083 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
4088 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
4089 a
= (WORD
)( version
>> 48);
4090 b
= (WORD
)((version
>> 32) & 0xffff);
4091 c
= (WORD
)((version
>> 16) & 0xffff);
4092 d
= (WORD
)( version
& 0xffff);
4094 swprintf(ver
, 30, L
"%d.%d.%d.%d", a
, b
, c
, d
);
4097 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
4099 VS_FIXEDFILEINFO
*info
;
4105 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
4107 len
= GetFileVersionInfoSizeW(name
, NULL
);
4109 return HRESULT_FROM_WIN32(GetLastError());
4112 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
4115 return HRESULT_FROM_WIN32(GetLastError());
4118 ret
= VerQueryValueW(ptr
, L
"\\", (void **)&info
, NULL
);
4122 return HRESULT_FROM_WIN32(GetLastError());
4125 get_versionstring(info
, ver
);
4128 *version
= SysAllocString(ver
);
4129 TRACE("version=%s\n", debugstr_w(ver
));
4134 static const struct IFileSystem3Vtbl filesys_vtbl
=
4136 filesys_QueryInterface
,
4139 filesys_GetTypeInfoCount
,
4140 filesys_GetTypeInfo
,
4141 filesys_GetIDsOfNames
,
4145 filesys_GetDriveName
,
4146 filesys_GetParentFolderName
,
4147 filesys_GetFileName
,
4148 filesys_GetBaseName
,
4149 filesys_GetExtensionName
,
4150 filesys_GetAbsolutePathName
,
4151 filesys_GetTempName
,
4152 filesys_DriveExists
,
4154 filesys_FolderExists
,
4158 filesys_GetSpecialFolder
,
4160 filesys_DeleteFolder
,
4165 filesys_CreateFolder
,
4166 filesys_CreateTextFile
,
4167 filesys_OpenTextFile
,
4168 filesys_GetStandardStream
,
4169 filesys_GetFileVersion
4172 static struct filesystem filesystem
;
4174 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
4176 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
4178 filesystem
.IFileSystem3_iface
.lpVtbl
= &filesys_vtbl
;
4179 init_classinfo(&CLSID_FileSystemObject
, (IUnknown
*)&filesystem
.IFileSystem3_iface
, &filesystem
.classinfo
);
4180 return IFileSystem3_QueryInterface(&filesystem
.IFileSystem3_iface
, riid
, ppv
);