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
32 #include "scrrun_private.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(scrrun
);
39 static const WCHAR bsW
[] = {'\\',0};
40 static const WCHAR utf16bom
= 0xfeff;
42 struct foldercollection
{
43 IFolderCollection IFolderCollection_iface
;
48 struct filecollection
{
49 IFileCollection IFileCollection_iface
;
54 struct drivecollection
{
55 IDriveCollection IDriveCollection_iface
;
66 struct foldercollection
*coll
;
71 struct filecollection
*coll
;
76 struct drivecollection
*coll
;
83 IEnumVARIANT IEnumVARIANT_iface
;
96 IFolder IFolder_iface
;
109 ITextStream ITextStream_iface
;
124 static inline struct drive
*impl_from_IDrive(IDrive
*iface
)
126 return CONTAINING_RECORD(iface
, struct drive
, IDrive_iface
);
129 static inline struct folder
*impl_from_IFolder(IFolder
*iface
)
131 return CONTAINING_RECORD(iface
, struct folder
, IFolder_iface
);
134 static inline struct file
*impl_from_IFile(IFile
*iface
)
136 return CONTAINING_RECORD(iface
, struct file
, IFile_iface
);
139 static inline struct textstream
*impl_from_ITextStream(ITextStream
*iface
)
141 return CONTAINING_RECORD(iface
, struct textstream
, ITextStream_iface
);
144 static inline struct foldercollection
*impl_from_IFolderCollection(IFolderCollection
*iface
)
146 return CONTAINING_RECORD(iface
, struct foldercollection
, IFolderCollection_iface
);
149 static inline struct filecollection
*impl_from_IFileCollection(IFileCollection
*iface
)
151 return CONTAINING_RECORD(iface
, struct filecollection
, IFileCollection_iface
);
154 static inline struct drivecollection
*impl_from_IDriveCollection(IDriveCollection
*iface
)
156 return CONTAINING_RECORD(iface
, struct drivecollection
, IDriveCollection_iface
);
159 static inline struct enumvariant
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
161 return CONTAINING_RECORD(iface
, struct enumvariant
, IEnumVARIANT_iface
);
164 static inline HRESULT
create_error(DWORD err
)
167 case ERROR_FILE_NOT_FOUND
: return CTL_E_FILENOTFOUND
;
168 case ERROR_PATH_NOT_FOUND
: return CTL_E_PATHNOTFOUND
;
169 case ERROR_ACCESS_DENIED
: return CTL_E_PERMISSIONDENIED
;
170 case ERROR_FILE_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
171 case ERROR_ALREADY_EXISTS
: return CTL_E_FILEALREADYEXISTS
;
173 FIXME("Unsupported error code: %d\n", err
);
178 static HRESULT
create_folder(const WCHAR
*, IFolder
**);
179 static HRESULT
create_file(BSTR
, IFile
**);
180 static HRESULT
create_foldercoll_enum(struct foldercollection
*, IUnknown
**);
181 static HRESULT
create_filecoll_enum(struct filecollection
*, IUnknown
**);
183 static inline BOOL
is_dir_data(const WIN32_FIND_DATAW
*data
)
185 static const WCHAR dotdotW
[] = {'.','.',0};
186 static const WCHAR dotW
[] = {'.',0};
188 return (data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
189 strcmpW(data
->cFileName
, dotdotW
) &&
190 strcmpW(data
->cFileName
, dotW
);
193 static inline BOOL
is_file_data(const WIN32_FIND_DATAW
*data
)
195 return !(data
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
198 static BSTR
get_full_path(BSTR path
, const WIN32_FIND_DATAW
*data
)
200 int len
= SysStringLen(path
);
201 WCHAR buffW
[MAX_PATH
];
203 strcpyW(buffW
, path
);
204 if (path
[len
-1] != '\\')
206 strcatW(buffW
, data
->cFileName
);
208 return SysAllocString(buffW
);
211 static BOOL
textstream_check_iomode(struct textstream
*This
, enum iotype type
)
214 return This
->mode
== ForWriting
|| This
->mode
== ForAppending
;
216 return This
->mode
== ForReading
;
219 static HRESULT WINAPI
textstream_QueryInterface(ITextStream
*iface
, REFIID riid
, void **obj
)
221 struct textstream
*This
= impl_from_ITextStream(iface
);
223 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
225 if (IsEqualIID(riid
, &IID_ITextStream
) ||
226 IsEqualIID(riid
, &IID_IDispatch
) ||
227 IsEqualIID(riid
, &IID_IUnknown
))
230 ITextStream_AddRef(iface
);
235 return E_NOINTERFACE
;
238 static ULONG WINAPI
textstream_AddRef(ITextStream
*iface
)
240 struct textstream
*This
= impl_from_ITextStream(iface
);
241 ULONG ref
= InterlockedIncrement(&This
->ref
);
242 TRACE("(%p)->(%d)\n", This
, ref
);
246 static ULONG WINAPI
textstream_Release(ITextStream
*iface
)
248 struct textstream
*This
= impl_from_ITextStream(iface
);
249 ULONG ref
= InterlockedDecrement(&This
->ref
);
250 TRACE("(%p)->(%d)\n", This
, ref
);
254 CloseHandle(This
->file
);
261 static HRESULT WINAPI
textstream_GetTypeInfoCount(ITextStream
*iface
, UINT
*pctinfo
)
263 struct textstream
*This
= impl_from_ITextStream(iface
);
264 TRACE("(%p)->(%p)\n", This
, pctinfo
);
269 static HRESULT WINAPI
textstream_GetTypeInfo(ITextStream
*iface
, UINT iTInfo
,
270 LCID lcid
, ITypeInfo
**ppTInfo
)
272 struct textstream
*This
= impl_from_ITextStream(iface
);
273 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
274 return get_typeinfo(ITextStream_tid
, ppTInfo
);
277 static HRESULT WINAPI
textstream_GetIDsOfNames(ITextStream
*iface
, REFIID riid
,
278 LPOLESTR
*rgszNames
, UINT cNames
,
279 LCID lcid
, DISPID
*rgDispId
)
281 struct textstream
*This
= impl_from_ITextStream(iface
);
285 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
287 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
290 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
291 ITypeInfo_Release(typeinfo
);
297 static HRESULT WINAPI
textstream_Invoke(ITextStream
*iface
, DISPID dispIdMember
,
298 REFIID riid
, LCID lcid
, WORD wFlags
,
299 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
300 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
302 struct textstream
*This
= impl_from_ITextStream(iface
);
306 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
307 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
309 hr
= get_typeinfo(ITextStream_tid
, &typeinfo
);
312 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
313 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
314 ITypeInfo_Release(typeinfo
);
320 static HRESULT WINAPI
textstream_get_Line(ITextStream
*iface
, LONG
*line
)
322 struct textstream
*This
= impl_from_ITextStream(iface
);
323 FIXME("(%p)->(%p): stub\n", This
, line
);
327 static HRESULT WINAPI
textstream_get_Column(ITextStream
*iface
, LONG
*column
)
329 struct textstream
*This
= impl_from_ITextStream(iface
);
330 FIXME("(%p)->(%p): stub\n", This
, column
);
334 static HRESULT WINAPI
textstream_get_AtEndOfStream(ITextStream
*iface
, VARIANT_BOOL
*eos
)
336 struct textstream
*This
= impl_from_ITextStream(iface
);
337 LARGE_INTEGER pos
, dist
;
339 TRACE("(%p)->(%p)\n", This
, eos
);
344 if (textstream_check_iomode(This
, IORead
)) {
346 return CTL_E_BADFILEMODE
;
350 if (!SetFilePointerEx(This
->file
, dist
, &pos
, FILE_CURRENT
))
353 *eos
= This
->size
.QuadPart
== pos
.QuadPart
? VARIANT_TRUE
: VARIANT_FALSE
;
357 static HRESULT WINAPI
textstream_get_AtEndOfLine(ITextStream
*iface
, VARIANT_BOOL
*eol
)
359 struct textstream
*This
= impl_from_ITextStream(iface
);
360 FIXME("(%p)->(%p): stub\n", This
, eol
);
365 Reads 'toread' bytes from a file, converts if needed
366 BOM is skipped if 'bof' is set.
368 static HRESULT
textstream_read(struct textstream
*stream
, LONG toread
, BOOL bof
, BSTR
*text
)
376 *text
= SysAllocStringLen(NULL
, 0);
377 return *text
? S_FALSE
: E_OUTOFMEMORY
;
380 if (toread
< sizeof(WCHAR
))
381 return CTL_E_ENDOFFILE
;
383 buff
= heap_alloc(toread
);
385 return E_OUTOFMEMORY
;
387 ret
= ReadFile(stream
->file
, buff
, toread
, &read
, NULL
);
388 if (!ret
|| toread
!= read
) {
389 WARN("failed to read from file %d, %d, error %d\n", read
, toread
, GetLastError());
394 if (stream
->unicode
) {
398 if (bof
&& *(WCHAR
*)buff
== utf16bom
) {
399 read
-= sizeof(WCHAR
);
403 *text
= SysAllocStringLen(read
? (WCHAR
*)&buff
[i
] : NULL
, read
/sizeof(WCHAR
));
404 if (!*text
) hr
= E_OUTOFMEMORY
;
407 INT len
= MultiByteToWideChar(CP_ACP
, 0, buff
, read
, NULL
, 0);
408 *text
= SysAllocStringLen(NULL
, len
);
410 MultiByteToWideChar(CP_ACP
, 0, buff
, read
, *text
, len
);
419 static HRESULT WINAPI
textstream_Read(ITextStream
*iface
, LONG len
, BSTR
*text
)
421 struct textstream
*This
= impl_from_ITextStream(iface
);
422 LARGE_INTEGER start
, end
, dist
;
426 TRACE("(%p)->(%d %p)\n", This
, len
, text
);
433 return len
== 0 ? S_OK
: E_INVALIDARG
;
435 if (textstream_check_iomode(This
, IORead
))
436 return CTL_E_BADFILEMODE
;
438 if (!This
->first_read
) {
442 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
446 if (eos
== VARIANT_TRUE
)
447 return CTL_E_ENDOFFILE
;
450 /* read everything from current position */
452 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
453 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
454 toread
= end
.QuadPart
- start
.QuadPart
;
456 dist
.QuadPart
= start
.QuadPart
;
457 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
459 This
->first_read
= FALSE
;
460 if (This
->unicode
) len
*= sizeof(WCHAR
);
462 hr
= textstream_read(This
, min(toread
, len
), start
.QuadPart
== 0, text
);
466 return toread
<= len
? S_FALSE
: S_OK
;
469 static HRESULT WINAPI
textstream_ReadLine(ITextStream
*iface
, BSTR
*text
)
471 struct textstream
*This
= impl_from_ITextStream(iface
);
475 FIXME("(%p)->(%p): stub\n", This
, text
);
481 if (textstream_check_iomode(This
, IORead
))
482 return CTL_E_BADFILEMODE
;
485 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
489 if (eos
== VARIANT_TRUE
)
490 return CTL_E_ENDOFFILE
;
495 static HRESULT WINAPI
textstream_ReadAll(ITextStream
*iface
, BSTR
*text
)
497 struct textstream
*This
= impl_from_ITextStream(iface
);
498 LARGE_INTEGER start
, end
, dist
;
502 TRACE("(%p)->(%p)\n", This
, text
);
508 if (textstream_check_iomode(This
, IORead
))
509 return CTL_E_BADFILEMODE
;
511 if (!This
->first_read
) {
515 hr
= ITextStream_get_AtEndOfStream(iface
, &eos
);
519 if (eos
== VARIANT_TRUE
)
520 return CTL_E_ENDOFFILE
;
523 /* read everything from current position */
525 SetFilePointerEx(This
->file
, dist
, &start
, FILE_CURRENT
);
526 SetFilePointerEx(This
->file
, dist
, &end
, FILE_END
);
527 toread
= end
.QuadPart
- start
.QuadPart
;
529 dist
.QuadPart
= start
.QuadPart
;
530 SetFilePointerEx(This
->file
, dist
, NULL
, FILE_BEGIN
);
532 This
->first_read
= FALSE
;
534 hr
= textstream_read(This
, toread
, start
.QuadPart
== 0, text
);
535 return FAILED(hr
) ? hr
: S_FALSE
;
538 static HRESULT
textstream_writestr(struct textstream
*stream
, BSTR text
)
543 if (stream
->unicode
) {
544 ret
= WriteFile(stream
->file
, text
, SysStringByteLen(text
), &written
, NULL
);
545 return (ret
&& written
== SysStringByteLen(text
)) ? S_OK
: create_error(GetLastError());
547 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), NULL
, 0, NULL
, NULL
);
551 buffA
= heap_alloc(len
);
553 return E_OUTOFMEMORY
;
555 WideCharToMultiByte(CP_ACP
, 0, text
, SysStringLen(text
), buffA
, len
, NULL
, NULL
);
556 ret
= WriteFile(stream
->file
, buffA
, len
, &written
, NULL
);
557 hr
= (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
563 static HRESULT WINAPI
textstream_Write(ITextStream
*iface
, BSTR text
)
565 struct textstream
*This
= impl_from_ITextStream(iface
);
567 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
569 if (textstream_check_iomode(This
, IOWrite
))
570 return CTL_E_BADFILEMODE
;
572 return textstream_writestr(This
, text
);
575 static HRESULT
textstream_writecrlf(struct textstream
*stream
)
577 static const WCHAR crlfW
[] = {'\r','\n'};
578 static const char crlfA
[] = {'\r','\n'};
579 DWORD written
= 0, len
;
583 if (stream
->unicode
) {
592 ret
= WriteFile(stream
->file
, ptr
, len
, &written
, NULL
);
593 return (ret
&& written
== len
) ? S_OK
: create_error(GetLastError());
596 static HRESULT WINAPI
textstream_WriteLine(ITextStream
*iface
, BSTR text
)
598 struct textstream
*This
= impl_from_ITextStream(iface
);
601 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
603 if (textstream_check_iomode(This
, IOWrite
))
604 return CTL_E_BADFILEMODE
;
606 hr
= textstream_writestr(This
, text
);
608 hr
= textstream_writecrlf(This
);
612 static HRESULT WINAPI
textstream_WriteBlankLines(ITextStream
*iface
, LONG lines
)
614 struct textstream
*This
= impl_from_ITextStream(iface
);
615 FIXME("(%p)->(%d): stub\n", This
, lines
);
619 static HRESULT WINAPI
textstream_Skip(ITextStream
*iface
, LONG count
)
621 struct textstream
*This
= impl_from_ITextStream(iface
);
622 FIXME("(%p)->(%d): stub\n", This
, count
);
626 static HRESULT WINAPI
textstream_SkipLine(ITextStream
*iface
)
628 struct textstream
*This
= impl_from_ITextStream(iface
);
629 FIXME("(%p): stub\n", This
);
633 static HRESULT WINAPI
textstream_Close(ITextStream
*iface
)
635 struct textstream
*This
= impl_from_ITextStream(iface
);
636 FIXME("(%p): stub\n", This
);
640 static const ITextStreamVtbl textstreamvtbl
= {
641 textstream_QueryInterface
,
644 textstream_GetTypeInfoCount
,
645 textstream_GetTypeInfo
,
646 textstream_GetIDsOfNames
,
649 textstream_get_Column
,
650 textstream_get_AtEndOfStream
,
651 textstream_get_AtEndOfLine
,
656 textstream_WriteLine
,
657 textstream_WriteBlankLines
,
663 static HRESULT
create_textstream(const WCHAR
*filename
, DWORD disposition
, IOMode mode
, BOOL unicode
, ITextStream
**ret
)
665 struct textstream
*stream
;
668 /* map access mode */
672 access
= GENERIC_READ
;
675 access
= GENERIC_WRITE
;
678 access
= FILE_APPEND_DATA
;
684 stream
= heap_alloc(sizeof(struct textstream
));
685 if (!stream
) return E_OUTOFMEMORY
;
687 stream
->ITextStream_iface
.lpVtbl
= &textstreamvtbl
;
690 stream
->unicode
= unicode
;
691 stream
->first_read
= TRUE
;
693 stream
->file
= CreateFileW(filename
, access
, 0, NULL
, disposition
, FILE_ATTRIBUTE_NORMAL
, NULL
);
694 if (stream
->file
== INVALID_HANDLE_VALUE
)
696 HRESULT hr
= create_error(GetLastError());
701 if (mode
== ForReading
)
702 GetFileSizeEx(stream
->file
, &stream
->size
);
704 stream
->size
.QuadPart
= 0;
706 /* Write Unicode BOM */
707 if (unicode
&& mode
== ForWriting
&& (disposition
== CREATE_ALWAYS
|| disposition
== CREATE_NEW
)) {
709 BOOL ret
= WriteFile(stream
->file
, &utf16bom
, sizeof(utf16bom
), &written
, NULL
);
710 if (!ret
|| written
!= sizeof(utf16bom
)) {
711 ITextStream_Release(&stream
->ITextStream_iface
);
712 return create_error(GetLastError());
716 *ret
= &stream
->ITextStream_iface
;
720 static HRESULT WINAPI
drive_QueryInterface(IDrive
*iface
, REFIID riid
, void **obj
)
722 struct drive
*This
= impl_from_IDrive(iface
);
724 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
728 if (IsEqualIID( riid
, &IID_IDrive
) ||
729 IsEqualIID( riid
, &IID_IDispatch
) ||
730 IsEqualIID( riid
, &IID_IUnknown
))
733 IDrive_AddRef(iface
);
736 return E_NOINTERFACE
;
741 static ULONG WINAPI
drive_AddRef(IDrive
*iface
)
743 struct drive
*This
= impl_from_IDrive(iface
);
744 ULONG ref
= InterlockedIncrement(&This
->ref
);
745 TRACE("(%p)->(%d)\n", This
, ref
);
749 static ULONG WINAPI
drive_Release(IDrive
*iface
)
751 struct drive
*This
= impl_from_IDrive(iface
);
752 ULONG ref
= InterlockedDecrement(&This
->ref
);
753 TRACE("(%p)->(%d)\n", This
, ref
);
757 SysFreeString(This
->root
);
764 static HRESULT WINAPI
drive_GetTypeInfoCount(IDrive
*iface
, UINT
*pctinfo
)
766 struct drive
*This
= impl_from_IDrive(iface
);
767 TRACE("(%p)->(%p)\n", This
, pctinfo
);
772 static HRESULT WINAPI
drive_GetTypeInfo(IDrive
*iface
, UINT iTInfo
,
773 LCID lcid
, ITypeInfo
**ppTInfo
)
775 struct drive
*This
= impl_from_IDrive(iface
);
776 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
777 return get_typeinfo(IDrive_tid
, ppTInfo
);
780 static HRESULT WINAPI
drive_GetIDsOfNames(IDrive
*iface
, REFIID riid
,
781 LPOLESTR
*rgszNames
, UINT cNames
,
782 LCID lcid
, DISPID
*rgDispId
)
784 struct drive
*This
= impl_from_IDrive(iface
);
788 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
790 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
793 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
794 ITypeInfo_Release(typeinfo
);
800 static HRESULT WINAPI
drive_Invoke(IDrive
*iface
, DISPID dispIdMember
,
801 REFIID riid
, LCID lcid
, WORD wFlags
,
802 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
803 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
805 struct drive
*This
= impl_from_IDrive(iface
);
809 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
810 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
812 hr
= get_typeinfo(IDrive_tid
, &typeinfo
);
815 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
816 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
817 ITypeInfo_Release(typeinfo
);
823 static HRESULT WINAPI
drive_get_Path(IDrive
*iface
, BSTR
*path
)
825 struct drive
*This
= impl_from_IDrive(iface
);
826 FIXME("(%p)->(%p): stub\n", This
, path
);
830 static HRESULT WINAPI
drive_get_DriveLetter(IDrive
*iface
, BSTR
*letter
)
832 struct drive
*This
= impl_from_IDrive(iface
);
834 TRACE("(%p)->(%p)\n", This
, letter
);
839 *letter
= SysAllocStringLen(This
->root
, 1);
841 return E_OUTOFMEMORY
;
846 static HRESULT WINAPI
drive_get_ShareName(IDrive
*iface
, BSTR
*share_name
)
848 struct drive
*This
= impl_from_IDrive(iface
);
849 FIXME("(%p)->(%p): stub\n", This
, share_name
);
853 static HRESULT WINAPI
drive_get_DriveType(IDrive
*iface
, DriveTypeConst
*type
)
855 struct drive
*This
= impl_from_IDrive(iface
);
857 TRACE("(%p)->(%p)\n", This
, type
);
859 switch (GetDriveTypeW(This
->root
))
861 case DRIVE_REMOVABLE
:
884 static HRESULT WINAPI
drive_get_RootFolder(IDrive
*iface
, IFolder
**folder
)
886 struct drive
*This
= impl_from_IDrive(iface
);
887 FIXME("(%p)->(%p): stub\n", This
, folder
);
891 static HRESULT
variant_from_largeint(const ULARGE_INTEGER
*src
, VARIANT
*v
)
895 if (src
->HighPart
|| src
->LowPart
> INT_MAX
)
898 hr
= VarR8FromUI8(src
->QuadPart
, &V_R8(v
));
903 V_I4(v
) = src
->LowPart
;
909 static HRESULT WINAPI
drive_get_AvailableSpace(IDrive
*iface
, VARIANT
*v
)
911 struct drive
*This
= impl_from_IDrive(iface
);
912 ULARGE_INTEGER avail
;
914 TRACE("(%p)->(%p)\n", This
, v
);
919 if (!GetDiskFreeSpaceExW(This
->root
, &avail
, NULL
, NULL
))
922 return variant_from_largeint(&avail
, v
);
925 static HRESULT WINAPI
drive_get_FreeSpace(IDrive
*iface
, VARIANT
*v
)
927 struct drive
*This
= impl_from_IDrive(iface
);
928 ULARGE_INTEGER freespace
;
930 TRACE("(%p)->(%p)\n", This
, v
);
935 if (!GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
))
938 return variant_from_largeint(&freespace
, v
);
941 static HRESULT WINAPI
drive_get_TotalSize(IDrive
*iface
, VARIANT
*v
)
943 struct drive
*This
= impl_from_IDrive(iface
);
944 ULARGE_INTEGER total
;
946 TRACE("(%p)->(%p)\n", This
, v
);
951 if (!GetDiskFreeSpaceExW(This
->root
, NULL
, &total
, NULL
))
954 return variant_from_largeint(&total
, v
);
957 static HRESULT WINAPI
drive_get_VolumeName(IDrive
*iface
, BSTR
*name
)
959 struct drive
*This
= impl_from_IDrive(iface
);
960 FIXME("(%p)->(%p): stub\n", This
, name
);
964 static HRESULT WINAPI
drive_put_VolumeName(IDrive
*iface
, BSTR name
)
966 struct drive
*This
= impl_from_IDrive(iface
);
967 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
971 static HRESULT WINAPI
drive_get_FileSystem(IDrive
*iface
, BSTR
*fs
)
973 struct drive
*This
= impl_from_IDrive(iface
);
974 FIXME("(%p)->(%p): stub\n", This
, fs
);
978 static HRESULT WINAPI
drive_get_SerialNumber(IDrive
*iface
, LONG
*serial
)
980 struct drive
*This
= impl_from_IDrive(iface
);
981 FIXME("(%p)->(%p): stub\n", This
, serial
);
985 static HRESULT WINAPI
drive_get_IsReady(IDrive
*iface
, VARIANT_BOOL
*ready
)
987 struct drive
*This
= impl_from_IDrive(iface
);
988 ULARGE_INTEGER freespace
;
991 TRACE("(%p)->(%p)\n", This
, ready
);
996 ret
= GetDiskFreeSpaceExW(This
->root
, &freespace
, NULL
, NULL
);
997 *ready
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
1001 static const IDriveVtbl drivevtbl
= {
1002 drive_QueryInterface
,
1005 drive_GetTypeInfoCount
,
1007 drive_GetIDsOfNames
,
1010 drive_get_DriveLetter
,
1011 drive_get_ShareName
,
1012 drive_get_DriveType
,
1013 drive_get_RootFolder
,
1014 drive_get_AvailableSpace
,
1015 drive_get_FreeSpace
,
1016 drive_get_TotalSize
,
1017 drive_get_VolumeName
,
1018 drive_put_VolumeName
,
1019 drive_get_FileSystem
,
1020 drive_get_SerialNumber
,
1024 static HRESULT
create_drive(WCHAR letter
, IDrive
**drive
)
1030 This
= heap_alloc(sizeof(*This
));
1031 if (!This
) return E_OUTOFMEMORY
;
1033 This
->IDrive_iface
.lpVtbl
= &drivevtbl
;
1035 This
->root
= SysAllocStringLen(NULL
, 3);
1039 return E_OUTOFMEMORY
;
1041 This
->root
[0] = letter
;
1042 This
->root
[1] = ':';
1043 This
->root
[2] = '\\';
1046 *drive
= &This
->IDrive_iface
;
1050 static HRESULT WINAPI
enumvariant_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
1052 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1054 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1058 if (IsEqualIID( riid
, &IID_IEnumVARIANT
) ||
1059 IsEqualIID( riid
, &IID_IUnknown
))
1062 IEnumVARIANT_AddRef(iface
);
1065 return E_NOINTERFACE
;
1070 static ULONG WINAPI
enumvariant_AddRef(IEnumVARIANT
*iface
)
1072 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1073 ULONG ref
= InterlockedIncrement(&This
->ref
);
1074 TRACE("(%p)->(%d)\n", This
, ref
);
1078 static ULONG WINAPI
foldercoll_enumvariant_Release(IEnumVARIANT
*iface
)
1080 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1081 ULONG ref
= InterlockedDecrement(&This
->ref
);
1083 TRACE("(%p)->(%d)\n", This
, ref
);
1087 IFolderCollection_Release(&This
->data
.u
.foldercoll
.coll
->IFolderCollection_iface
);
1088 FindClose(This
->data
.u
.foldercoll
.find
);
1095 static HANDLE
start_enumeration(const WCHAR
*path
, WIN32_FIND_DATAW
*data
, BOOL file
)
1097 static const WCHAR allW
[] = {'*',0};
1098 WCHAR pathW
[MAX_PATH
];
1102 strcpyW(pathW
, path
);
1103 len
= strlenW(pathW
);
1104 if (pathW
[len
-1] != '\\')
1105 strcatW(pathW
, bsW
);
1106 strcatW(pathW
, allW
);
1107 handle
= FindFirstFileW(pathW
, data
);
1108 if (handle
== INVALID_HANDLE_VALUE
) return 0;
1110 /* find first dir/file */
1113 if (file
? is_file_data(data
) : is_dir_data(data
))
1116 if (!FindNextFileW(handle
, data
))
1125 static HRESULT WINAPI
foldercoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1127 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1128 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1129 WIN32_FIND_DATAW data
;
1132 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1137 if (!celt
) return S_OK
;
1141 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1142 if (!handle
) return S_FALSE
;
1144 This
->data
.u
.foldercoll
.find
= handle
;
1148 if (!FindNextFileW(handle
, &data
))
1154 if (is_dir_data(&data
))
1160 str
= get_full_path(This
->data
.u
.foldercoll
.coll
->path
, &data
);
1161 hr
= create_folder(str
, &folder
);
1163 if (FAILED(hr
)) return hr
;
1165 V_VT(&var
[count
]) = VT_DISPATCH
;
1166 V_DISPATCH(&var
[count
]) = (IDispatch
*)folder
;
1169 if (count
>= celt
) break;
1171 } while (FindNextFileW(handle
, &data
));
1176 return (count
< celt
) ? S_FALSE
: S_OK
;
1179 static HRESULT WINAPI
foldercoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1181 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1182 HANDLE handle
= This
->data
.u
.foldercoll
.find
;
1183 WIN32_FIND_DATAW data
;
1185 TRACE("(%p)->(%d)\n", This
, celt
);
1187 if (!celt
) return S_OK
;
1191 handle
= start_enumeration(This
->data
.u
.foldercoll
.coll
->path
, &data
, FALSE
);
1192 if (!handle
) return S_FALSE
;
1194 This
->data
.u
.foldercoll
.find
= handle
;
1198 if (!FindNextFileW(handle
, &data
))
1204 if (is_dir_data(&data
))
1208 } while (FindNextFileW(handle
, &data
));
1210 return celt
? S_FALSE
: S_OK
;
1213 static HRESULT WINAPI
foldercoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1215 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1217 TRACE("(%p)\n", This
);
1219 FindClose(This
->data
.u
.foldercoll
.find
);
1220 This
->data
.u
.foldercoll
.find
= NULL
;
1225 static HRESULT WINAPI
foldercoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1227 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1228 TRACE("(%p)->(%p)\n", This
, pclone
);
1229 return create_foldercoll_enum(This
->data
.u
.foldercoll
.coll
, (IUnknown
**)pclone
);
1232 static const IEnumVARIANTVtbl foldercollenumvariantvtbl
= {
1233 enumvariant_QueryInterface
,
1235 foldercoll_enumvariant_Release
,
1236 foldercoll_enumvariant_Next
,
1237 foldercoll_enumvariant_Skip
,
1238 foldercoll_enumvariant_Reset
,
1239 foldercoll_enumvariant_Clone
1242 static HRESULT
create_foldercoll_enum(struct foldercollection
*collection
, IUnknown
**newenum
)
1244 struct enumvariant
*This
;
1248 This
= heap_alloc(sizeof(*This
));
1249 if (!This
) return E_OUTOFMEMORY
;
1251 This
->IEnumVARIANT_iface
.lpVtbl
= &foldercollenumvariantvtbl
;
1253 This
->data
.u
.foldercoll
.find
= NULL
;
1254 This
->data
.u
.foldercoll
.coll
= collection
;
1255 IFolderCollection_AddRef(&collection
->IFolderCollection_iface
);
1257 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1262 static ULONG WINAPI
filecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1264 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1265 ULONG ref
= InterlockedDecrement(&This
->ref
);
1267 TRACE("(%p)->(%d)\n", This
, ref
);
1271 IFileCollection_Release(&This
->data
.u
.filecoll
.coll
->IFileCollection_iface
);
1272 FindClose(This
->data
.u
.filecoll
.find
);
1279 static HRESULT WINAPI
filecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1281 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1282 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1283 WIN32_FIND_DATAW data
;
1286 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1291 if (!celt
) return S_OK
;
1295 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1296 if (!handle
) return S_FALSE
;
1297 This
->data
.u
.filecoll
.find
= handle
;
1299 else if (!FindNextFileW(handle
, &data
))
1304 if (is_file_data(&data
))
1310 str
= get_full_path(This
->data
.u
.filecoll
.coll
->path
, &data
);
1311 hr
= create_file(str
, &file
);
1313 if (FAILED(hr
)) return hr
;
1315 V_VT(&var
[count
]) = VT_DISPATCH
;
1316 V_DISPATCH(&var
[count
]) = (IDispatch
*)file
;
1317 if (++count
>= celt
) break;
1319 } while (FindNextFileW(handle
, &data
));
1324 return (count
< celt
) ? S_FALSE
: S_OK
;
1327 static HRESULT WINAPI
filecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1329 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1330 HANDLE handle
= This
->data
.u
.filecoll
.find
;
1331 WIN32_FIND_DATAW data
;
1333 TRACE("(%p)->(%d)\n", This
, celt
);
1335 if (!celt
) return S_OK
;
1339 handle
= start_enumeration(This
->data
.u
.filecoll
.coll
->path
, &data
, TRUE
);
1340 if (!handle
) return S_FALSE
;
1341 This
->data
.u
.filecoll
.find
= handle
;
1343 else if (!FindNextFileW(handle
, &data
))
1348 if (is_file_data(&data
))
1350 } while (celt
&& FindNextFileW(handle
, &data
));
1352 return celt
? S_FALSE
: S_OK
;
1355 static HRESULT WINAPI
filecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1357 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1359 TRACE("(%p)\n", This
);
1361 FindClose(This
->data
.u
.filecoll
.find
);
1362 This
->data
.u
.filecoll
.find
= NULL
;
1367 static HRESULT WINAPI
filecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1369 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1370 TRACE("(%p)->(%p)\n", This
, pclone
);
1371 return create_filecoll_enum(This
->data
.u
.filecoll
.coll
, (IUnknown
**)pclone
);
1374 static const IEnumVARIANTVtbl filecollenumvariantvtbl
= {
1375 enumvariant_QueryInterface
,
1377 filecoll_enumvariant_Release
,
1378 filecoll_enumvariant_Next
,
1379 filecoll_enumvariant_Skip
,
1380 filecoll_enumvariant_Reset
,
1381 filecoll_enumvariant_Clone
1384 static HRESULT
create_filecoll_enum(struct filecollection
*collection
, IUnknown
**newenum
)
1386 struct enumvariant
*This
;
1390 This
= heap_alloc(sizeof(*This
));
1391 if (!This
) return E_OUTOFMEMORY
;
1393 This
->IEnumVARIANT_iface
.lpVtbl
= &filecollenumvariantvtbl
;
1395 This
->data
.u
.filecoll
.find
= NULL
;
1396 This
->data
.u
.filecoll
.coll
= collection
;
1397 IFileCollection_AddRef(&collection
->IFileCollection_iface
);
1399 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1404 static ULONG WINAPI
drivecoll_enumvariant_Release(IEnumVARIANT
*iface
)
1406 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1407 ULONG ref
= InterlockedDecrement(&This
->ref
);
1409 TRACE("(%p)->(%d)\n", This
, ref
);
1413 IDriveCollection_Release(&This
->data
.u
.drivecoll
.coll
->IDriveCollection_iface
);
1420 static HRESULT
find_next_drive(struct enumvariant
*penum
)
1422 int i
= penum
->data
.u
.drivecoll
.cur
== -1 ? 0 : penum
->data
.u
.drivecoll
.cur
+ 1;
1425 if (penum
->data
.u
.drivecoll
.coll
->drives
& (1 << i
))
1427 penum
->data
.u
.drivecoll
.cur
= i
;
1434 static HRESULT WINAPI
drivecoll_enumvariant_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
1436 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1439 TRACE("(%p)->(%d %p %p)\n", This
, celt
, var
, fetched
);
1444 if (!celt
) return S_OK
;
1446 while (find_next_drive(This
) == S_OK
)
1451 hr
= create_drive('A' + This
->data
.u
.drivecoll
.cur
, &drive
);
1452 if (FAILED(hr
)) return hr
;
1454 V_VT(&var
[count
]) = VT_DISPATCH
;
1455 V_DISPATCH(&var
[count
]) = (IDispatch
*)drive
;
1457 if (++count
>= celt
) break;
1463 return (count
< celt
) ? S_FALSE
: S_OK
;
1466 static HRESULT WINAPI
drivecoll_enumvariant_Skip(IEnumVARIANT
*iface
, ULONG celt
)
1468 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1470 TRACE("(%p)->(%d)\n", This
, celt
);
1472 if (!celt
) return S_OK
;
1474 while (celt
&& find_next_drive(This
) == S_OK
)
1477 return celt
? S_FALSE
: S_OK
;
1480 static HRESULT WINAPI
drivecoll_enumvariant_Reset(IEnumVARIANT
*iface
)
1482 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1484 TRACE("(%p)\n", This
);
1486 This
->data
.u
.drivecoll
.cur
= -1;
1490 static HRESULT WINAPI
drivecoll_enumvariant_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**pclone
)
1492 struct enumvariant
*This
= impl_from_IEnumVARIANT(iface
);
1493 FIXME("(%p)->(%p): stub\n", This
, pclone
);
1497 static const IEnumVARIANTVtbl drivecollenumvariantvtbl
= {
1498 enumvariant_QueryInterface
,
1500 drivecoll_enumvariant_Release
,
1501 drivecoll_enumvariant_Next
,
1502 drivecoll_enumvariant_Skip
,
1503 drivecoll_enumvariant_Reset
,
1504 drivecoll_enumvariant_Clone
1507 static HRESULT
create_drivecoll_enum(struct drivecollection
*collection
, IUnknown
**newenum
)
1509 struct enumvariant
*This
;
1513 This
= heap_alloc(sizeof(*This
));
1514 if (!This
) return E_OUTOFMEMORY
;
1516 This
->IEnumVARIANT_iface
.lpVtbl
= &drivecollenumvariantvtbl
;
1518 This
->data
.u
.drivecoll
.coll
= collection
;
1519 This
->data
.u
.drivecoll
.cur
= -1;
1520 IDriveCollection_AddRef(&collection
->IDriveCollection_iface
);
1522 *newenum
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
1527 static HRESULT WINAPI
foldercoll_QueryInterface(IFolderCollection
*iface
, REFIID riid
, void **obj
)
1529 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1531 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1535 if (IsEqualIID( riid
, &IID_IFolderCollection
) ||
1536 IsEqualIID( riid
, &IID_IDispatch
) ||
1537 IsEqualIID( riid
, &IID_IUnknown
))
1540 IFolderCollection_AddRef(iface
);
1543 return E_NOINTERFACE
;
1548 static ULONG WINAPI
foldercoll_AddRef(IFolderCollection
*iface
)
1550 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1551 ULONG ref
= InterlockedIncrement(&This
->ref
);
1552 TRACE("(%p)->(%d)\n", This
, ref
);
1556 static ULONG WINAPI
foldercoll_Release(IFolderCollection
*iface
)
1558 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1559 ULONG ref
= InterlockedDecrement(&This
->ref
);
1560 TRACE("(%p)->(%d)\n", This
, ref
);
1564 SysFreeString(This
->path
);
1571 static HRESULT WINAPI
foldercoll_GetTypeInfoCount(IFolderCollection
*iface
, UINT
*pctinfo
)
1573 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1574 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1579 static HRESULT WINAPI
foldercoll_GetTypeInfo(IFolderCollection
*iface
, UINT iTInfo
,
1580 LCID lcid
, ITypeInfo
**ppTInfo
)
1582 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1583 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1584 return get_typeinfo(IFolderCollection_tid
, ppTInfo
);
1587 static HRESULT WINAPI
foldercoll_GetIDsOfNames(IFolderCollection
*iface
, REFIID riid
,
1588 LPOLESTR
*rgszNames
, UINT cNames
,
1589 LCID lcid
, DISPID
*rgDispId
)
1591 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1592 ITypeInfo
*typeinfo
;
1595 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1597 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1600 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1601 ITypeInfo_Release(typeinfo
);
1607 static HRESULT WINAPI
foldercoll_Invoke(IFolderCollection
*iface
, DISPID dispIdMember
,
1608 REFIID riid
, LCID lcid
, WORD wFlags
,
1609 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1610 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1612 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1613 ITypeInfo
*typeinfo
;
1616 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1617 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1619 hr
= get_typeinfo(IFolderCollection_tid
, &typeinfo
);
1622 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1623 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1624 ITypeInfo_Release(typeinfo
);
1630 static HRESULT WINAPI
foldercoll_Add(IFolderCollection
*iface
, BSTR name
, IFolder
**folder
)
1632 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1633 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(name
), folder
);
1637 static HRESULT WINAPI
foldercoll_get_Item(IFolderCollection
*iface
, VARIANT key
, IFolder
**folder
)
1639 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1640 FIXME("(%p)->(%p): stub\n", This
, folder
);
1644 static HRESULT WINAPI
foldercoll_get__NewEnum(IFolderCollection
*iface
, IUnknown
**newenum
)
1646 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1648 TRACE("(%p)->(%p)\n", This
, newenum
);
1653 return create_foldercoll_enum(This
, newenum
);
1656 static HRESULT WINAPI
foldercoll_get_Count(IFolderCollection
*iface
, LONG
*count
)
1658 struct foldercollection
*This
= impl_from_IFolderCollection(iface
);
1659 static const WCHAR allW
[] = {'\\','*',0};
1660 WIN32_FIND_DATAW data
;
1661 WCHAR pathW
[MAX_PATH
];
1664 TRACE("(%p)->(%p)\n", This
, count
);
1671 strcpyW(pathW
, This
->path
);
1672 strcatW(pathW
, allW
);
1673 handle
= FindFirstFileW(pathW
, &data
);
1674 if (handle
== INVALID_HANDLE_VALUE
)
1675 return HRESULT_FROM_WIN32(GetLastError());
1679 if (is_dir_data(&data
))
1681 } while (FindNextFileW(handle
, &data
));
1687 static const IFolderCollectionVtbl foldercollvtbl
= {
1688 foldercoll_QueryInterface
,
1691 foldercoll_GetTypeInfoCount
,
1692 foldercoll_GetTypeInfo
,
1693 foldercoll_GetIDsOfNames
,
1696 foldercoll_get_Item
,
1697 foldercoll_get__NewEnum
,
1698 foldercoll_get_Count
1701 static HRESULT
create_foldercoll(BSTR path
, IFolderCollection
**folders
)
1703 struct foldercollection
*This
;
1707 This
= heap_alloc(sizeof(struct foldercollection
));
1708 if (!This
) return E_OUTOFMEMORY
;
1710 This
->IFolderCollection_iface
.lpVtbl
= &foldercollvtbl
;
1712 This
->path
= SysAllocString(path
);
1716 return E_OUTOFMEMORY
;
1719 *folders
= &This
->IFolderCollection_iface
;
1724 static HRESULT WINAPI
filecoll_QueryInterface(IFileCollection
*iface
, REFIID riid
, void **obj
)
1726 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1728 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1732 if (IsEqualIID( riid
, &IID_IFileCollection
) ||
1733 IsEqualIID( riid
, &IID_IDispatch
) ||
1734 IsEqualIID( riid
, &IID_IUnknown
))
1737 IFileCollection_AddRef(iface
);
1740 return E_NOINTERFACE
;
1745 static ULONG WINAPI
filecoll_AddRef(IFileCollection
*iface
)
1747 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1748 ULONG ref
= InterlockedIncrement(&This
->ref
);
1749 TRACE("(%p)->(%d)\n", This
, ref
);
1753 static ULONG WINAPI
filecoll_Release(IFileCollection
*iface
)
1755 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1756 ULONG ref
= InterlockedDecrement(&This
->ref
);
1757 TRACE("(%p)->(%d)\n", This
, ref
);
1761 SysFreeString(This
->path
);
1768 static HRESULT WINAPI
filecoll_GetTypeInfoCount(IFileCollection
*iface
, UINT
*pctinfo
)
1770 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1771 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1776 static HRESULT WINAPI
filecoll_GetTypeInfo(IFileCollection
*iface
, UINT iTInfo
,
1777 LCID lcid
, ITypeInfo
**ppTInfo
)
1779 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1780 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1781 return get_typeinfo(IFileCollection_tid
, ppTInfo
);
1784 static HRESULT WINAPI
filecoll_GetIDsOfNames(IFileCollection
*iface
, REFIID riid
,
1785 LPOLESTR
*rgszNames
, UINT cNames
,
1786 LCID lcid
, DISPID
*rgDispId
)
1788 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1789 ITypeInfo
*typeinfo
;
1792 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1794 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1797 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1798 ITypeInfo_Release(typeinfo
);
1804 static HRESULT WINAPI
filecoll_Invoke(IFileCollection
*iface
, DISPID dispIdMember
,
1805 REFIID riid
, LCID lcid
, WORD wFlags
,
1806 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1807 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1809 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1810 ITypeInfo
*typeinfo
;
1813 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1814 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1816 hr
= get_typeinfo(IFileCollection_tid
, &typeinfo
);
1819 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
1820 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1821 ITypeInfo_Release(typeinfo
);
1827 static HRESULT WINAPI
filecoll_get_Item(IFileCollection
*iface
, VARIANT Key
, IFile
**file
)
1829 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1830 FIXME("(%p)->(%p)\n", This
, file
);
1834 static HRESULT WINAPI
filecoll_get__NewEnum(IFileCollection
*iface
, IUnknown
**ppenum
)
1836 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1838 TRACE("(%p)->(%p)\n", This
, ppenum
);
1843 return create_filecoll_enum(This
, ppenum
);
1846 static HRESULT WINAPI
filecoll_get_Count(IFileCollection
*iface
, LONG
*count
)
1848 struct filecollection
*This
= impl_from_IFileCollection(iface
);
1849 static const WCHAR allW
[] = {'\\','*',0};
1850 WIN32_FIND_DATAW data
;
1851 WCHAR pathW
[MAX_PATH
];
1854 TRACE("(%p)->(%p)\n", This
, count
);
1861 strcpyW(pathW
, This
->path
);
1862 strcatW(pathW
, allW
);
1863 handle
= FindFirstFileW(pathW
, &data
);
1864 if (handle
== INVALID_HANDLE_VALUE
)
1865 return HRESULT_FROM_WIN32(GetLastError());
1869 if (is_file_data(&data
))
1871 } while (FindNextFileW(handle
, &data
));
1877 static const IFileCollectionVtbl filecollectionvtbl
= {
1878 filecoll_QueryInterface
,
1881 filecoll_GetTypeInfoCount
,
1882 filecoll_GetTypeInfo
,
1883 filecoll_GetIDsOfNames
,
1886 filecoll_get__NewEnum
,
1890 static HRESULT
create_filecoll(BSTR path
, IFileCollection
**files
)
1892 struct filecollection
*This
;
1896 This
= heap_alloc(sizeof(*This
));
1897 if (!This
) return E_OUTOFMEMORY
;
1899 This
->IFileCollection_iface
.lpVtbl
= &filecollectionvtbl
;
1901 This
->path
= SysAllocString(path
);
1905 return E_OUTOFMEMORY
;
1908 *files
= &This
->IFileCollection_iface
;
1912 static HRESULT WINAPI
drivecoll_QueryInterface(IDriveCollection
*iface
, REFIID riid
, void **obj
)
1914 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1916 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1920 if (IsEqualIID( riid
, &IID_IDriveCollection
) ||
1921 IsEqualIID( riid
, &IID_IDispatch
) ||
1922 IsEqualIID( riid
, &IID_IUnknown
))
1925 IDriveCollection_AddRef(iface
);
1928 return E_NOINTERFACE
;
1933 static ULONG WINAPI
drivecoll_AddRef(IDriveCollection
*iface
)
1935 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1936 ULONG ref
= InterlockedIncrement(&This
->ref
);
1937 TRACE("(%p)->(%d)\n", This
, ref
);
1941 static ULONG WINAPI
drivecoll_Release(IDriveCollection
*iface
)
1943 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1944 ULONG ref
= InterlockedDecrement(&This
->ref
);
1945 TRACE("(%p)->(%d)\n", This
, ref
);
1953 static HRESULT WINAPI
drivecoll_GetTypeInfoCount(IDriveCollection
*iface
, UINT
*pctinfo
)
1955 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1956 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1961 static HRESULT WINAPI
drivecoll_GetTypeInfo(IDriveCollection
*iface
, UINT iTInfo
,
1962 LCID lcid
, ITypeInfo
**ppTInfo
)
1964 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1965 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1966 return get_typeinfo(IDriveCollection_tid
, ppTInfo
);
1969 static HRESULT WINAPI
drivecoll_GetIDsOfNames(IDriveCollection
*iface
, REFIID riid
,
1970 LPOLESTR
*rgszNames
, UINT cNames
,
1971 LCID lcid
, DISPID
*rgDispId
)
1973 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1974 ITypeInfo
*typeinfo
;
1977 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1979 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
1982 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1983 ITypeInfo_Release(typeinfo
);
1989 static HRESULT WINAPI
drivecoll_Invoke(IDriveCollection
*iface
, DISPID dispIdMember
,
1990 REFIID riid
, LCID lcid
, WORD wFlags
,
1991 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1992 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1994 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
1995 ITypeInfo
*typeinfo
;
1998 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1999 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2001 hr
= get_typeinfo(IDriveCollection_tid
, &typeinfo
);
2004 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2005 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2006 ITypeInfo_Release(typeinfo
);
2012 static HRESULT WINAPI
drivecoll_get_Item(IDriveCollection
*iface
, VARIANT key
, IDrive
**drive
)
2014 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2015 FIXME("(%p)->(%p): stub\n", This
, drive
);
2019 static HRESULT WINAPI
drivecoll_get__NewEnum(IDriveCollection
*iface
, IUnknown
**ppenum
)
2021 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2023 TRACE("(%p)->(%p)\n", This
, ppenum
);
2028 return create_drivecoll_enum(This
, ppenum
);
2031 static HRESULT WINAPI
drivecoll_get_Count(IDriveCollection
*iface
, LONG
*count
)
2033 struct drivecollection
*This
= impl_from_IDriveCollection(iface
);
2035 TRACE("(%p)->(%p)\n", This
, count
);
2037 if (!count
) return E_POINTER
;
2039 *count
= This
->count
;
2043 static const IDriveCollectionVtbl drivecollectionvtbl
= {
2044 drivecoll_QueryInterface
,
2047 drivecoll_GetTypeInfoCount
,
2048 drivecoll_GetTypeInfo
,
2049 drivecoll_GetIDsOfNames
,
2052 drivecoll_get__NewEnum
,
2056 static HRESULT
create_drivecoll(IDriveCollection
**drives
)
2058 struct drivecollection
*This
;
2063 This
= heap_alloc(sizeof(*This
));
2064 if (!This
) return E_OUTOFMEMORY
;
2066 This
->IDriveCollection_iface
.lpVtbl
= &drivecollectionvtbl
;
2068 This
->drives
= mask
= GetLogicalDrives();
2069 /* count set bits */
2070 for (This
->count
= 0; mask
; This
->count
++)
2073 *drives
= &This
->IDriveCollection_iface
;
2077 static HRESULT WINAPI
folder_QueryInterface(IFolder
*iface
, REFIID riid
, void **obj
)
2079 struct folder
*This
= impl_from_IFolder(iface
);
2081 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2085 if (IsEqualIID( riid
, &IID_IFolder
) ||
2086 IsEqualIID( riid
, &IID_IDispatch
) ||
2087 IsEqualIID( riid
, &IID_IUnknown
))
2090 IFolder_AddRef(iface
);
2093 return E_NOINTERFACE
;
2098 static ULONG WINAPI
folder_AddRef(IFolder
*iface
)
2100 struct folder
*This
= impl_from_IFolder(iface
);
2101 ULONG ref
= InterlockedIncrement(&This
->ref
);
2102 TRACE("(%p)->(%d)\n", This
, ref
);
2106 static ULONG WINAPI
folder_Release(IFolder
*iface
)
2108 struct folder
*This
= impl_from_IFolder(iface
);
2109 ULONG ref
= InterlockedDecrement(&This
->ref
);
2110 TRACE("(%p)->(%d)\n", This
, ref
);
2114 SysFreeString(This
->path
);
2121 static HRESULT WINAPI
folder_GetTypeInfoCount(IFolder
*iface
, UINT
*pctinfo
)
2123 struct folder
*This
= impl_from_IFolder(iface
);
2124 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2129 static HRESULT WINAPI
folder_GetTypeInfo(IFolder
*iface
, UINT iTInfo
,
2130 LCID lcid
, ITypeInfo
**ppTInfo
)
2132 struct folder
*This
= impl_from_IFolder(iface
);
2133 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2134 return get_typeinfo(IFolder_tid
, ppTInfo
);
2137 static HRESULT WINAPI
folder_GetIDsOfNames(IFolder
*iface
, REFIID riid
,
2138 LPOLESTR
*rgszNames
, UINT cNames
,
2139 LCID lcid
, DISPID
*rgDispId
)
2141 struct folder
*This
= impl_from_IFolder(iface
);
2142 ITypeInfo
*typeinfo
;
2145 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2147 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2150 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2151 ITypeInfo_Release(typeinfo
);
2157 static HRESULT WINAPI
folder_Invoke(IFolder
*iface
, DISPID dispIdMember
,
2158 REFIID riid
, LCID lcid
, WORD wFlags
,
2159 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2160 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2162 struct folder
*This
= impl_from_IFolder(iface
);
2163 ITypeInfo
*typeinfo
;
2166 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2167 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2169 hr
= get_typeinfo(IFolder_tid
, &typeinfo
);
2172 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2173 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2174 ITypeInfo_Release(typeinfo
);
2180 static HRESULT WINAPI
folder_get_Path(IFolder
*iface
, BSTR
*path
)
2182 struct folder
*This
= impl_from_IFolder(iface
);
2184 TRACE("(%p)->(%p)\n", This
, path
);
2189 *path
= SysAllocString(This
->path
);
2190 return *path
? S_OK
: E_OUTOFMEMORY
;
2193 static HRESULT WINAPI
folder_get_Name(IFolder
*iface
, BSTR
*name
)
2195 struct folder
*This
= impl_from_IFolder(iface
);
2198 TRACE("(%p)->(%p)\n", This
, name
);
2205 ptr
= strrchrW(This
->path
, '\\');
2208 *name
= SysAllocString(ptr
+1);
2209 TRACE("%s\n", debugstr_w(*name
));
2210 if (!*name
) return E_OUTOFMEMORY
;
2218 static HRESULT WINAPI
folder_put_Name(IFolder
*iface
, BSTR name
)
2220 struct folder
*This
= impl_from_IFolder(iface
);
2221 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
2225 static HRESULT WINAPI
folder_get_ShortPath(IFolder
*iface
, BSTR
*path
)
2227 struct folder
*This
= impl_from_IFolder(iface
);
2228 FIXME("(%p)->(%p): stub\n", This
, path
);
2232 static HRESULT WINAPI
folder_get_ShortName(IFolder
*iface
, BSTR
*name
)
2234 struct folder
*This
= impl_from_IFolder(iface
);
2235 FIXME("(%p)->(%p): stub\n", This
, name
);
2239 static HRESULT WINAPI
folder_get_Drive(IFolder
*iface
, IDrive
**drive
)
2241 struct folder
*This
= impl_from_IFolder(iface
);
2242 FIXME("(%p)->(%p): stub\n", This
, drive
);
2246 static HRESULT WINAPI
folder_get_ParentFolder(IFolder
*iface
, IFolder
**parent
)
2248 struct folder
*This
= impl_from_IFolder(iface
);
2249 FIXME("(%p)->(%p): stub\n", This
, parent
);
2253 static HRESULT WINAPI
folder_get_Attributes(IFolder
*iface
, FileAttribute
*attr
)
2255 struct folder
*This
= impl_from_IFolder(iface
);
2256 FIXME("(%p)->(%p): stub\n", This
, attr
);
2260 static HRESULT WINAPI
folder_put_Attributes(IFolder
*iface
, FileAttribute attr
)
2262 struct folder
*This
= impl_from_IFolder(iface
);
2263 FIXME("(%p)->(0x%x): stub\n", This
, attr
);
2267 static HRESULT WINAPI
folder_get_DateCreated(IFolder
*iface
, DATE
*date
)
2269 struct folder
*This
= impl_from_IFolder(iface
);
2270 FIXME("(%p)->(%p): stub\n", This
, date
);
2274 static HRESULT WINAPI
folder_get_DateLastModified(IFolder
*iface
, DATE
*date
)
2276 struct folder
*This
= impl_from_IFolder(iface
);
2277 FIXME("(%p)->(%p): stub\n", This
, date
);
2281 static HRESULT WINAPI
folder_get_DateLastAccessed(IFolder
*iface
, DATE
*date
)
2283 struct folder
*This
= impl_from_IFolder(iface
);
2284 FIXME("(%p)->(%p): stub\n", This
, date
);
2288 static HRESULT WINAPI
folder_get_Type(IFolder
*iface
, BSTR
*type
)
2290 struct folder
*This
= impl_from_IFolder(iface
);
2291 FIXME("(%p)->(%p): stub\n", This
, type
);
2295 static HRESULT WINAPI
folder_Delete(IFolder
*iface
, VARIANT_BOOL force
)
2297 struct folder
*This
= impl_from_IFolder(iface
);
2298 FIXME("(%p)->(%x): stub\n", This
, force
);
2302 static HRESULT WINAPI
folder_Copy(IFolder
*iface
, BSTR dest
, VARIANT_BOOL overwrite
)
2304 struct folder
*This
= impl_from_IFolder(iface
);
2305 FIXME("(%p)->(%s %x): stub\n", This
, debugstr_w(dest
), overwrite
);
2309 static HRESULT WINAPI
folder_Move(IFolder
*iface
, BSTR dest
)
2311 struct folder
*This
= impl_from_IFolder(iface
);
2312 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(dest
));
2316 static HRESULT WINAPI
folder_get_IsRootFolder(IFolder
*iface
, VARIANT_BOOL
*isroot
)
2318 struct folder
*This
= impl_from_IFolder(iface
);
2319 FIXME("(%p)->(%p): stub\n", This
, isroot
);
2323 static HRESULT WINAPI
folder_get_Size(IFolder
*iface
, VARIANT
*size
)
2325 struct folder
*This
= impl_from_IFolder(iface
);
2326 FIXME("(%p)->(%p): stub\n", This
, size
);
2330 static HRESULT WINAPI
folder_get_SubFolders(IFolder
*iface
, IFolderCollection
**folders
)
2332 struct folder
*This
= impl_from_IFolder(iface
);
2334 TRACE("(%p)->(%p)\n", This
, folders
);
2339 return create_foldercoll(This
->path
, folders
);
2342 static HRESULT WINAPI
folder_get_Files(IFolder
*iface
, IFileCollection
**files
)
2344 struct folder
*This
= impl_from_IFolder(iface
);
2346 TRACE("(%p)->(%p)\n", This
, files
);
2351 return create_filecoll(This
->path
, files
);
2354 static HRESULT WINAPI
folder_CreateTextFile(IFolder
*iface
, BSTR filename
, VARIANT_BOOL overwrite
,
2355 VARIANT_BOOL unicode
, ITextStream
**stream
)
2357 struct folder
*This
= impl_from_IFolder(iface
);
2358 FIXME("(%p)->(%s %x %x %p): stub\n", This
, debugstr_w(filename
), overwrite
, unicode
, stream
);
2362 static const IFolderVtbl foldervtbl
= {
2363 folder_QueryInterface
,
2366 folder_GetTypeInfoCount
,
2368 folder_GetIDsOfNames
,
2373 folder_get_ShortPath
,
2374 folder_get_ShortName
,
2376 folder_get_ParentFolder
,
2377 folder_get_Attributes
,
2378 folder_put_Attributes
,
2379 folder_get_DateCreated
,
2380 folder_get_DateLastModified
,
2381 folder_get_DateLastAccessed
,
2386 folder_get_IsRootFolder
,
2388 folder_get_SubFolders
,
2390 folder_CreateTextFile
2393 HRESULT
create_folder(const WCHAR
*path
, IFolder
**folder
)
2395 struct folder
*This
;
2399 TRACE("%s\n", debugstr_w(path
));
2401 This
= heap_alloc(sizeof(struct folder
));
2402 if (!This
) return E_OUTOFMEMORY
;
2404 This
->IFolder_iface
.lpVtbl
= &foldervtbl
;
2406 This
->path
= SysAllocString(path
);
2410 return E_OUTOFMEMORY
;
2413 *folder
= &This
->IFolder_iface
;
2418 static HRESULT WINAPI
file_QueryInterface(IFile
*iface
, REFIID riid
, void **obj
)
2420 struct file
*This
= impl_from_IFile(iface
);
2422 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2424 if (IsEqualIID(riid
, &IID_IFile
) ||
2425 IsEqualIID(riid
, &IID_IDispatch
) ||
2426 IsEqualIID(riid
, &IID_IUnknown
))
2429 IFile_AddRef(iface
);
2434 return E_NOINTERFACE
;
2437 static ULONG WINAPI
file_AddRef(IFile
*iface
)
2439 struct file
*This
= impl_from_IFile(iface
);
2440 LONG ref
= InterlockedIncrement(&This
->ref
);
2442 TRACE("(%p) ref=%d\n", This
, ref
);
2447 static ULONG WINAPI
file_Release(IFile
*iface
)
2449 struct file
*This
= impl_from_IFile(iface
);
2450 LONG ref
= InterlockedDecrement(&This
->ref
);
2452 TRACE("(%p) ref=%d\n", This
, ref
);
2456 heap_free(This
->path
);
2463 static HRESULT WINAPI
file_GetTypeInfoCount(IFile
*iface
, UINT
*pctinfo
)
2465 struct file
*This
= impl_from_IFile(iface
);
2467 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2473 static HRESULT WINAPI
file_GetTypeInfo(IFile
*iface
,
2474 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
2476 struct file
*This
= impl_from_IFile(iface
);
2478 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2480 return get_typeinfo(IFile_tid
, ppTInfo
);
2483 static HRESULT WINAPI
file_GetIDsOfNames(IFile
*iface
, REFIID riid
,
2484 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2486 struct file
*This
= impl_from_IFile(iface
);
2487 ITypeInfo
*typeinfo
;
2490 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
2491 rgszNames
, cNames
, lcid
, rgDispId
);
2493 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2495 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2496 ITypeInfo_Release(typeinfo
);
2501 static HRESULT WINAPI
file_Invoke(IFile
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2503 struct file
*This
= impl_from_IFile(iface
);
2504 ITypeInfo
*typeinfo
;
2507 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2508 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2510 hr
= get_typeinfo(IFile_tid
, &typeinfo
);
2513 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2514 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2515 ITypeInfo_Release(typeinfo
);
2520 static HRESULT WINAPI
file_get_Path(IFile
*iface
, BSTR
*pbstrPath
)
2522 struct file
*This
= impl_from_IFile(iface
);
2523 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2527 static HRESULT WINAPI
file_get_Name(IFile
*iface
, BSTR
*name
)
2529 struct file
*This
= impl_from_IFile(iface
);
2532 TRACE("(%p)->(%p)\n", This
, name
);
2539 ptr
= strrchrW(This
->path
, '\\');
2542 *name
= SysAllocString(ptr
+1);
2543 TRACE("%s\n", debugstr_w(*name
));
2544 if (!*name
) return E_OUTOFMEMORY
;
2552 static HRESULT WINAPI
file_put_Name(IFile
*iface
, BSTR pbstrName
)
2554 struct file
*This
= impl_from_IFile(iface
);
2555 FIXME("(%p)->(%s)\n", This
, debugstr_w(pbstrName
));
2559 static HRESULT WINAPI
file_get_ShortPath(IFile
*iface
, BSTR
*pbstrPath
)
2561 struct file
*This
= impl_from_IFile(iface
);
2562 FIXME("(%p)->(%p)\n", This
, pbstrPath
);
2566 static HRESULT WINAPI
file_get_ShortName(IFile
*iface
, BSTR
*pbstrName
)
2568 struct file
*This
= impl_from_IFile(iface
);
2569 FIXME("(%p)->(%p)\n", This
, pbstrName
);
2573 static HRESULT WINAPI
file_get_Drive(IFile
*iface
, IDrive
**ppdrive
)
2575 struct file
*This
= impl_from_IFile(iface
);
2576 FIXME("(%p)->(%p)\n", This
, ppdrive
);
2580 static HRESULT WINAPI
file_get_ParentFolder(IFile
*iface
, IFolder
**ppfolder
)
2582 struct file
*This
= impl_from_IFile(iface
);
2583 FIXME("(%p)->(%p)\n", This
, ppfolder
);
2587 static HRESULT WINAPI
file_get_Attributes(IFile
*iface
, FileAttribute
*pfa
)
2589 struct file
*This
= impl_from_IFile(iface
);
2592 TRACE("(%p)->(%p)\n", This
, pfa
);
2597 fa
= GetFileAttributesW(This
->path
);
2598 if(fa
== INVALID_FILE_ATTRIBUTES
)
2599 return create_error(GetLastError());
2601 *pfa
= fa
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
|
2602 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_ARCHIVE
|
2603 FILE_ATTRIBUTE_REPARSE_POINT
| FILE_ATTRIBUTE_COMPRESSED
);
2607 static HRESULT WINAPI
file_put_Attributes(IFile
*iface
, FileAttribute pfa
)
2609 struct file
*This
= impl_from_IFile(iface
);
2610 FIXME("(%p)->(%x)\n", This
, pfa
);
2614 static HRESULT WINAPI
file_get_DateCreated(IFile
*iface
, DATE
*pdate
)
2616 struct file
*This
= impl_from_IFile(iface
);
2617 FIXME("(%p)->(%p)\n", This
, pdate
);
2621 static HRESULT WINAPI
file_get_DateLastModified(IFile
*iface
, DATE
*pdate
)
2623 struct file
*This
= impl_from_IFile(iface
);
2624 FIXME("(%p)->(%p)\n", This
, pdate
);
2628 static HRESULT WINAPI
file_get_DateLastAccessed(IFile
*iface
, DATE
*pdate
)
2630 struct file
*This
= impl_from_IFile(iface
);
2631 FIXME("(%p)->(%p)\n", This
, pdate
);
2635 static HRESULT WINAPI
file_get_Size(IFile
*iface
, VARIANT
*pvarSize
)
2637 struct file
*This
= impl_from_IFile(iface
);
2638 ULARGE_INTEGER size
;
2639 WIN32_FIND_DATAW fd
;
2642 TRACE("(%p)->(%p)\n", This
, pvarSize
);
2647 f
= FindFirstFileW(This
->path
, &fd
);
2648 if(f
== INVALID_HANDLE_VALUE
)
2649 return create_error(GetLastError());
2652 size
.LowPart
= fd
.nFileSizeLow
;
2653 size
.HighPart
= fd
.nFileSizeHigh
;
2655 return variant_from_largeint(&size
, pvarSize
);
2658 static HRESULT WINAPI
file_get_Type(IFile
*iface
, BSTR
*pbstrType
)
2660 struct file
*This
= impl_from_IFile(iface
);
2661 FIXME("(%p)->(%p)\n", This
, pbstrType
);
2665 static HRESULT WINAPI
file_Delete(IFile
*iface
, VARIANT_BOOL Force
)
2667 struct file
*This
= impl_from_IFile(iface
);
2668 FIXME("(%p)->(%x)\n", This
, Force
);
2672 static HRESULT WINAPI
file_Copy(IFile
*iface
, BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
2674 struct file
*This
= impl_from_IFile(iface
);
2675 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(Destination
), OverWriteFiles
);
2679 static HRESULT WINAPI
file_Move(IFile
*iface
, BSTR Destination
)
2681 struct file
*This
= impl_from_IFile(iface
);
2682 FIXME("(%p)->(%s)\n", This
, debugstr_w(Destination
));
2686 static HRESULT WINAPI
file_OpenAsTextStream(IFile
*iface
, IOMode mode
, Tristate format
, ITextStream
**stream
)
2688 struct file
*This
= impl_from_IFile(iface
);
2690 TRACE("(%p)->(%d %d %p)\n", This
, mode
, format
, stream
);
2692 if (format
== TristateUseDefault
) {
2693 FIXME("default format not handled, defaulting to unicode\n");
2694 format
= TristateTrue
;
2697 return create_textstream(This
->path
, OPEN_EXISTING
, mode
, format
== TristateTrue
, stream
);
2700 static const IFileVtbl file_vtbl
= {
2701 file_QueryInterface
,
2704 file_GetTypeInfoCount
,
2714 file_get_ParentFolder
,
2715 file_get_Attributes
,
2716 file_put_Attributes
,
2717 file_get_DateCreated
,
2718 file_get_DateLastModified
,
2719 file_get_DateLastAccessed
,
2725 file_OpenAsTextStream
2728 static HRESULT
create_file(BSTR path
, IFile
**file
)
2735 f
= heap_alloc(sizeof(struct file
));
2737 return E_OUTOFMEMORY
;
2739 f
->IFile_iface
.lpVtbl
= &file_vtbl
;
2742 len
= GetFullPathNameW(path
, 0, NULL
, NULL
);
2748 f
->path
= heap_alloc(len
*sizeof(WCHAR
));
2751 return E_OUTOFMEMORY
;
2754 if(!GetFullPathNameW(path
, len
, f
->path
, NULL
)) {
2760 attrs
= GetFileAttributesW(f
->path
);
2761 if(attrs
==INVALID_FILE_ATTRIBUTES
||
2762 (attrs
&(FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))) {
2765 return create_error(GetLastError());
2768 *file
= &f
->IFile_iface
;
2772 static HRESULT WINAPI
filesys_QueryInterface(IFileSystem3
*iface
, REFIID riid
, void **ppvObject
)
2774 TRACE("%p %s %p\n", iface
, debugstr_guid(riid
), ppvObject
);
2776 if ( IsEqualGUID( riid
, &IID_IFileSystem3
) ||
2777 IsEqualGUID( riid
, &IID_IFileSystem
) ||
2778 IsEqualGUID( riid
, &IID_IDispatch
) ||
2779 IsEqualGUID( riid
, &IID_IUnknown
) )
2783 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
2785 TRACE("Interface IDispatchEx not supported - returning NULL\n");
2787 return E_NOINTERFACE
;
2789 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
2791 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
2793 return E_NOINTERFACE
;
2797 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
2798 return E_NOINTERFACE
;
2801 IFileSystem3_AddRef(iface
);
2806 static ULONG WINAPI
filesys_AddRef(IFileSystem3
*iface
)
2808 TRACE("%p\n", iface
);
2813 static ULONG WINAPI
filesys_Release(IFileSystem3
*iface
)
2815 TRACE("%p\n", iface
);
2820 static HRESULT WINAPI
filesys_GetTypeInfoCount(IFileSystem3
*iface
, UINT
*pctinfo
)
2822 TRACE("(%p)->(%p)\n", iface
, pctinfo
);
2828 static HRESULT WINAPI
filesys_GetTypeInfo(IFileSystem3
*iface
, UINT iTInfo
,
2829 LCID lcid
, ITypeInfo
**ppTInfo
)
2831 TRACE("(%p)->(%u %u %p)\n", iface
, iTInfo
, lcid
, ppTInfo
);
2832 return get_typeinfo(IFileSystem3_tid
, ppTInfo
);
2835 static HRESULT WINAPI
filesys_GetIDsOfNames(IFileSystem3
*iface
, REFIID riid
,
2836 LPOLESTR
*rgszNames
, UINT cNames
,
2837 LCID lcid
, DISPID
*rgDispId
)
2839 ITypeInfo
*typeinfo
;
2842 TRACE("(%p)->(%s %p %u %u %p)\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2844 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2847 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2848 ITypeInfo_Release(typeinfo
);
2854 static HRESULT WINAPI
filesys_Invoke(IFileSystem3
*iface
, DISPID dispIdMember
,
2855 REFIID riid
, LCID lcid
, WORD wFlags
,
2856 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2857 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2859 ITypeInfo
*typeinfo
;
2862 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", iface
, dispIdMember
, debugstr_guid(riid
),
2863 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2865 hr
= get_typeinfo(IFileSystem3_tid
, &typeinfo
);
2868 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
,
2869 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2870 ITypeInfo_Release(typeinfo
);
2876 static HRESULT WINAPI
filesys_get_Drives(IFileSystem3
*iface
, IDriveCollection
**ppdrives
)
2878 TRACE("%p %p\n", iface
, ppdrives
);
2879 return create_drivecoll(ppdrives
);
2882 static HRESULT WINAPI
filesys_BuildPath(IFileSystem3
*iface
, BSTR Path
,
2883 BSTR Name
, BSTR
*Result
)
2887 TRACE("%p %s %s %p\n", iface
, debugstr_w(Path
), debugstr_w(Name
), Result
);
2889 if (!Result
) return E_POINTER
;
2893 int path_len
= SysStringLen(Path
), name_len
= SysStringLen(Name
);
2895 /* if both parts have backslashes strip one from Path */
2896 if (Path
[path_len
-1] == '\\' && Name
[0] == '\\')
2900 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2908 else if (Path
[path_len
-1] != '\\' && Name
[0] != '\\')
2910 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
+ 1);
2914 if (Path
[path_len
-1] != ':')
2921 ret
= SysAllocStringLen(NULL
, path_len
+ name_len
);
2929 else if (Path
|| Name
)
2930 ret
= SysAllocString(Path
? Path
: Name
);
2932 ret
= SysAllocStringLen(NULL
, 0);
2934 if (!ret
) return E_OUTOFMEMORY
;
2940 static HRESULT WINAPI
filesys_GetDriveName(IFileSystem3
*iface
, BSTR Path
,
2943 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2948 static inline DWORD
get_parent_folder_name(const WCHAR
*path
, DWORD len
)
2955 for(i
=len
-1; i
>=0; i
--)
2956 if(path
[i
]!='/' && path
[i
]!='\\')
2960 if(path
[i
]=='/' || path
[i
]=='\\')
2964 if(path
[i
]!='/' && path
[i
]!='\\')
2970 if(path
[i
]==':' && i
==1)
2975 static HRESULT WINAPI
filesys_GetParentFolderName(IFileSystem3
*iface
, BSTR Path
,
2980 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
2985 len
= get_parent_folder_name(Path
, SysStringLen(Path
));
2987 *pbstrResult
= NULL
;
2991 *pbstrResult
= SysAllocStringLen(Path
, len
);
2993 return E_OUTOFMEMORY
;
2997 static HRESULT WINAPI
filesys_GetFileName(IFileSystem3
*iface
, BSTR Path
,
3002 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3008 *pbstrResult
= NULL
;
3012 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3013 if(Path
[end
]!='/' && Path
[end
]!='\\')
3016 for(i
=end
; i
>=0; i
--)
3017 if(Path
[i
]=='/' || Path
[i
]=='\\')
3021 if(i
>end
|| (i
==0 && end
==1 && Path
[1]==':')) {
3022 *pbstrResult
= NULL
;
3026 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3028 return E_OUTOFMEMORY
;
3032 static HRESULT WINAPI
filesys_GetBaseName(IFileSystem3
*iface
, BSTR Path
,
3037 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3043 *pbstrResult
= NULL
;
3047 for(end
=strlenW(Path
)-1; end
>=0; end
--)
3048 if(Path
[end
]!='/' && Path
[end
]!='\\')
3051 for(i
=end
; i
>=0; i
--) {
3052 if(Path
[i
]=='.' && Path
[end
+1]!='.')
3054 if(Path
[i
]=='/' || Path
[i
]=='\\')
3059 if((i
>end
&& Path
[end
+1]!='.') || (i
==0 && end
==1 && Path
[1]==':')) {
3060 *pbstrResult
= NULL
;
3064 *pbstrResult
= SysAllocStringLen(Path
+i
, end
-i
+1);
3066 return E_OUTOFMEMORY
;
3070 static HRESULT WINAPI
filesys_GetExtensionName(IFileSystem3
*iface
, BSTR Path
,
3073 FIXME("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3078 static HRESULT WINAPI
filesys_GetAbsolutePathName(IFileSystem3
*iface
, BSTR Path
,
3081 static const WCHAR cur_path
[] = {'.',0};
3083 WCHAR buf
[MAX_PATH
], ch
;
3085 DWORD i
, beg
, len
, exp_len
;
3086 WIN32_FIND_DATAW fdata
;
3089 TRACE("%p %s %p\n", iface
, debugstr_w(Path
), pbstrResult
);
3099 len
= GetFullPathNameW(path
, MAX_PATH
, buf
, NULL
);
3103 buf
[0] = toupperW(buf
[0]);
3104 if(len
>3 && buf
[len
-1] == '\\')
3107 for(beg
=3, i
=3; i
<=len
; i
++) {
3108 if(buf
[i
]!='\\' && buf
[i
])
3113 fh
= FindFirstFileW(buf
, &fdata
);
3114 if(fh
== INVALID_HANDLE_VALUE
)
3117 exp_len
= strlenW(fdata
.cFileName
);
3118 if(exp_len
== i
-beg
)
3119 memcpy(buf
+beg
, fdata
.cFileName
, exp_len
*sizeof(WCHAR
));
3125 *pbstrResult
= SysAllocString(buf
);
3127 return E_OUTOFMEMORY
;
3131 static HRESULT WINAPI
filesys_GetTempName(IFileSystem3
*iface
, BSTR
*pbstrResult
)
3133 static const WCHAR fmt
[] = {'r','a','d','%','0','5','X','.','t','x','t',0};
3137 TRACE("%p %p\n", iface
, pbstrResult
);
3142 *pbstrResult
= SysAllocStringLen(NULL
, 12);
3144 return E_OUTOFMEMORY
;
3146 if(!RtlGenRandom(&random
, sizeof(random
)))
3148 sprintfW(*pbstrResult
, fmt
, random
& 0xfffff);
3152 static HRESULT WINAPI
filesys_DriveExists(IFileSystem3
*iface
, BSTR DriveSpec
,
3153 VARIANT_BOOL
*pfExists
)
3155 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), pfExists
);
3160 static HRESULT WINAPI
filesys_FileExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3163 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3165 if (!ret
) return E_POINTER
;
3167 attrs
= GetFileAttributesW(path
);
3168 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3172 static HRESULT WINAPI
filesys_FolderExists(IFileSystem3
*iface
, BSTR path
, VARIANT_BOOL
*ret
)
3175 TRACE("%p %s %p\n", iface
, debugstr_w(path
), ret
);
3177 if (!ret
) return E_POINTER
;
3179 attrs
= GetFileAttributesW(path
);
3180 *ret
= attrs
!= INVALID_FILE_ATTRIBUTES
&& (attrs
& FILE_ATTRIBUTE_DIRECTORY
) ? VARIANT_TRUE
: VARIANT_FALSE
;
3185 static HRESULT WINAPI
filesys_GetDrive(IFileSystem3
*iface
, BSTR DriveSpec
,
3188 FIXME("%p %s %p\n", iface
, debugstr_w(DriveSpec
), ppdrive
);
3193 static HRESULT WINAPI
filesys_GetFile(IFileSystem3
*iface
, BSTR FilePath
,
3196 TRACE("%p %s %p\n", iface
, debugstr_w(FilePath
), ppfile
);
3201 return E_INVALIDARG
;
3203 return create_file(FilePath
, ppfile
);
3206 static HRESULT WINAPI
filesys_GetFolder(IFileSystem3
*iface
, BSTR FolderPath
,
3211 TRACE("%p %s %p\n", iface
, debugstr_w(FolderPath
), folder
);
3218 return E_INVALIDARG
;
3220 attrs
= GetFileAttributesW(FolderPath
);
3221 if((attrs
== INVALID_FILE_ATTRIBUTES
) || !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
3222 return CTL_E_PATHNOTFOUND
;
3224 return create_folder(FolderPath
, folder
);
3227 static HRESULT WINAPI
filesys_GetSpecialFolder(IFileSystem3
*iface
,
3228 SpecialFolderConst SpecialFolder
,
3231 FIXME("%p %d %p\n", iface
, SpecialFolder
, ppfolder
);
3236 static inline HRESULT
delete_file(const WCHAR
*file
, DWORD file_len
, VARIANT_BOOL force
)
3238 WCHAR path
[MAX_PATH
];
3239 DWORD len
, name_len
;
3240 WIN32_FIND_DATAW ffd
;
3243 f
= FindFirstFileW(file
, &ffd
);
3244 if(f
== INVALID_HANDLE_VALUE
)
3245 return create_error(GetLastError());
3247 len
= get_parent_folder_name(file
, file_len
);
3248 if(len
+1 >= MAX_PATH
) {
3253 memcpy(path
, file
, len
*sizeof(WCHAR
));
3258 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3261 name_len
= strlenW(ffd
.cFileName
);
3262 if(len
+name_len
+1 >= MAX_PATH
) {
3266 memcpy(path
+len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3268 TRACE("deleting %s\n", debugstr_w(path
));
3270 if(!DeleteFileW(path
)) {
3271 if(!force
|| !SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
)
3272 || !DeleteFileW(path
)) {
3274 return create_error(GetLastError());
3277 } while(FindNextFileW(f
, &ffd
));
3283 static HRESULT WINAPI
filesys_DeleteFile(IFileSystem3
*iface
, BSTR FileSpec
,
3286 TRACE("%p %s %d\n", iface
, debugstr_w(FileSpec
), Force
);
3291 return delete_file(FileSpec
, SysStringLen(FileSpec
), Force
);
3294 static HRESULT
delete_folder(const WCHAR
*folder
, DWORD folder_len
, VARIANT_BOOL force
)
3296 WCHAR path
[MAX_PATH
];
3297 DWORD len
, name_len
;
3298 WIN32_FIND_DATAW ffd
;
3302 f
= FindFirstFileW(folder
, &ffd
);
3303 if(f
== INVALID_HANDLE_VALUE
)
3304 return create_error(GetLastError());
3306 len
= get_parent_folder_name(folder
, folder_len
);
3307 if(len
+1 >= MAX_PATH
) {
3312 memcpy(path
, folder
, len
*sizeof(WCHAR
));
3317 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3319 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3320 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3323 name_len
= strlenW(ffd
.cFileName
);
3324 if(len
+name_len
+3 >= MAX_PATH
) {
3328 memcpy(path
+len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3329 path
[len
+name_len
] = '\\';
3330 path
[len
+name_len
+1] = '*';
3331 path
[len
+name_len
+2] = 0;
3333 hr
= delete_file(path
, len
+name_len
+2, force
);
3339 hr
= delete_folder(path
, len
+name_len
+2, force
);
3345 path
[len
+name_len
] = 0;
3346 TRACE("deleting %s\n", debugstr_w(path
));
3348 if(!RemoveDirectoryW(path
)) {
3350 return create_error(GetLastError());
3352 } while(FindNextFileW(f
, &ffd
));
3358 static HRESULT WINAPI
filesys_DeleteFolder(IFileSystem3
*iface
, BSTR FolderSpec
,
3361 TRACE("%p %s %d\n", iface
, debugstr_w(FolderSpec
), Force
);
3366 return delete_folder(FolderSpec
, SysStringLen(FolderSpec
), Force
);
3369 static HRESULT WINAPI
filesys_MoveFile(IFileSystem3
*iface
, BSTR Source
,
3372 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3377 static HRESULT WINAPI
filesys_MoveFolder(IFileSystem3
*iface
,BSTR Source
,
3380 FIXME("%p %s %s\n", iface
, debugstr_w(Source
), debugstr_w(Destination
));
3385 static inline HRESULT
copy_file(const WCHAR
*source
, DWORD source_len
,
3386 const WCHAR
*destination
, DWORD destination_len
, VARIANT_BOOL overwrite
)
3389 WCHAR src_path
[MAX_PATH
], dst_path
[MAX_PATH
];
3390 DWORD src_len
, dst_len
, name_len
;
3391 WIN32_FIND_DATAW ffd
;
3395 if(!source
[0] || !destination
[0])
3396 return E_INVALIDARG
;
3398 attrs
= GetFileAttributesW(destination
);
3399 if(attrs
==INVALID_FILE_ATTRIBUTES
|| !(attrs
& FILE_ATTRIBUTE_DIRECTORY
)) {
3400 attrs
= GetFileAttributesW(source
);
3401 if(attrs
== INVALID_FILE_ATTRIBUTES
)
3402 return create_error(GetLastError());
3403 else if(attrs
& FILE_ATTRIBUTE_DIRECTORY
)
3404 return CTL_E_FILENOTFOUND
;
3406 if(!CopyFileW(source
, destination
, !overwrite
))
3407 return create_error(GetLastError());
3411 f
= FindFirstFileW(source
, &ffd
);
3412 if(f
== INVALID_HANDLE_VALUE
)
3413 return CTL_E_FILENOTFOUND
;
3415 src_len
= get_parent_folder_name(source
, source_len
);
3416 if(src_len
+1 >= MAX_PATH
) {
3421 memcpy(src_path
, source
, src_len
*sizeof(WCHAR
));
3422 src_path
[src_len
++] = '\\';
3425 dst_len
= destination_len
;
3426 if(dst_len
+1 >= MAX_PATH
) {
3430 memcpy(dst_path
, destination
, dst_len
*sizeof(WCHAR
));
3431 if(dst_path
[dst_len
-1]!= '\\' && dst_path
[dst_len
-1]!='/')
3432 dst_path
[dst_len
++] = '\\';
3434 hr
= CTL_E_FILENOTFOUND
;
3436 if(ffd
.dwFileAttributes
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_DEVICE
))
3439 name_len
= strlenW(ffd
.cFileName
);
3440 if(src_len
+name_len
+1>=MAX_PATH
|| dst_len
+name_len
+1>=MAX_PATH
) {
3444 memcpy(src_path
+src_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3445 memcpy(dst_path
+dst_len
, ffd
.cFileName
, (name_len
+1)*sizeof(WCHAR
));
3447 TRACE("copying %s to %s\n", debugstr_w(src_path
), debugstr_w(dst_path
));
3449 if(!CopyFileW(src_path
, dst_path
, !overwrite
)) {
3451 return create_error(GetLastError());
3455 } while(FindNextFileW(f
, &ffd
));
3461 static HRESULT WINAPI
filesys_CopyFile(IFileSystem3
*iface
, BSTR Source
,
3462 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3464 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3466 if(!Source
|| !Destination
)
3469 return copy_file(Source
, SysStringLen(Source
), Destination
,
3470 SysStringLen(Destination
), OverWriteFiles
);
3473 static HRESULT
copy_folder(const WCHAR
*source
, DWORD source_len
, const WCHAR
*destination
,
3474 DWORD destination_len
, VARIANT_BOOL overwrite
)
3476 DWORD tmp
, src_len
, dst_len
, name_len
;
3477 WCHAR src
[MAX_PATH
], dst
[MAX_PATH
];
3478 WIN32_FIND_DATAW ffd
;
3481 BOOL copied
= FALSE
;
3483 if(!source
[0] || !destination
[0])
3484 return E_INVALIDARG
;
3486 dst_len
= destination_len
;
3487 if(dst_len
+1 >= MAX_PATH
)
3489 memcpy(dst
, destination
, (dst_len
+1)*sizeof(WCHAR
));
3491 if(dst
[dst_len
-1]!='\\' && dst
[dst_len
-1]!='/' &&
3492 (tmp
= GetFileAttributesW(source
))!=INVALID_FILE_ATTRIBUTES
&&
3493 tmp
&FILE_ATTRIBUTE_DIRECTORY
) {
3494 if(!CreateDirectoryW(dst
, NULL
)) {
3495 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3496 tmp
= GetFileAttributesW(dst
);
3497 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
))
3498 return CTL_E_FILEALREADYEXISTS
;
3500 return create_error(GetLastError());
3505 src_len
= source_len
;
3506 if(src_len
+2 >= MAX_PATH
)
3508 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3509 src
[src_len
++] = '\\';
3513 hr
= copy_file(src
, src_len
+1, dst
, dst_len
, overwrite
);
3514 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
)
3515 return create_error(GetLastError());
3517 f
= FindFirstFileW(src
, &ffd
);
3519 src_len
= get_parent_folder_name(source
, source_len
);
3520 if(src_len
+2 >= MAX_PATH
)
3522 memcpy(src
, source
, src_len
*sizeof(WCHAR
));
3524 src
[src_len
++] = '\\';
3526 f
= FindFirstFileW(source
, &ffd
);
3528 if(f
== INVALID_HANDLE_VALUE
)
3529 return CTL_E_PATHNOTFOUND
;
3531 dst
[dst_len
++] = '\\';
3535 if(!(ffd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
3537 if(ffd
.cFileName
[0]=='.' && (ffd
.cFileName
[1]==0 ||
3538 (ffd
.cFileName
[1]=='.' && ffd
.cFileName
[2]==0)))
3541 name_len
= strlenW(ffd
.cFileName
);
3542 if(dst_len
+name_len
>=MAX_PATH
|| src_len
+name_len
+2>=MAX_PATH
) {
3546 memcpy(dst
+dst_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3547 dst
[dst_len
+name_len
] = 0;
3548 memcpy(src
+src_len
, ffd
.cFileName
, name_len
*sizeof(WCHAR
));
3549 src
[src_len
+name_len
] = '\\';
3550 src
[src_len
+name_len
+1] = '*';
3551 src
[src_len
+name_len
+2] = 0;
3553 TRACE("copying %s to %s\n", debugstr_w(src
), debugstr_w(dst
));
3555 if(!CreateDirectoryW(dst
, NULL
)) {
3556 if(overwrite
&& GetLastError()==ERROR_ALREADY_EXISTS
) {
3557 tmp
= GetFileAttributesW(dst
);
3558 if(tmp
==INVALID_FILE_ATTRIBUTES
|| !(tmp
&FILE_ATTRIBUTE_DIRECTORY
)) {
3560 return CTL_E_FILEALREADYEXISTS
;
3565 return create_error(GetLastError());
3569 hr
= copy_file(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3570 if(FAILED(hr
) && hr
!=CTL_E_FILENOTFOUND
) {
3575 hr
= copy_folder(src
, src_len
+name_len
+2, dst
, dst_len
+name_len
, overwrite
);
3576 if(FAILED(hr
) && hr
!=CTL_E_PATHNOTFOUND
) {
3580 } while(FindNextFileW(f
, &ffd
));
3583 return copied
? S_OK
: CTL_E_PATHNOTFOUND
;
3586 static HRESULT WINAPI
filesys_CopyFolder(IFileSystem3
*iface
, BSTR Source
,
3587 BSTR Destination
, VARIANT_BOOL OverWriteFiles
)
3589 TRACE("%p %s %s %d\n", iface
, debugstr_w(Source
), debugstr_w(Destination
), OverWriteFiles
);
3591 if(!Source
|| !Destination
)
3594 return copy_folder(Source
, SysStringLen(Source
), Destination
,
3595 SysStringLen(Destination
), OverWriteFiles
);
3598 static HRESULT WINAPI
filesys_CreateFolder(IFileSystem3
*iface
, BSTR path
,
3603 TRACE("(%p)->(%s %p)\n", iface
, debugstr_w(path
), folder
);
3605 ret
= CreateDirectoryW(path
, NULL
);
3609 if (GetLastError() == ERROR_ALREADY_EXISTS
) return CTL_E_FILEALREADYEXISTS
;
3610 return HRESULT_FROM_WIN32(GetLastError());
3613 return create_folder(path
, folder
);
3616 static HRESULT WINAPI
filesys_CreateTextFile(IFileSystem3
*iface
, BSTR filename
,
3617 VARIANT_BOOL overwrite
, VARIANT_BOOL unicode
,
3618 ITextStream
**stream
)
3622 TRACE("%p %s %d %d %p\n", iface
, debugstr_w(filename
), overwrite
, unicode
, stream
);
3624 disposition
= overwrite
== VARIANT_TRUE
? CREATE_ALWAYS
: CREATE_NEW
;
3625 return create_textstream(filename
, disposition
, ForWriting
, !!unicode
, stream
);
3628 static HRESULT WINAPI
filesys_OpenTextFile(IFileSystem3
*iface
, BSTR filename
,
3629 IOMode mode
, VARIANT_BOOL create
,
3630 Tristate format
, ITextStream
**stream
)
3634 TRACE("(%p)->(%s %d %d %d %p)\n", iface
, debugstr_w(filename
), mode
, create
, format
, stream
);
3635 disposition
= create
== VARIANT_TRUE
? OPEN_ALWAYS
: OPEN_EXISTING
;
3637 if (format
== TristateUseDefault
) {
3638 FIXME("default format not handled, defaulting to unicode\n");
3639 format
= TristateTrue
;
3642 return create_textstream(filename
, disposition
, mode
, format
== TristateTrue
, stream
);
3645 static HRESULT WINAPI
filesys_GetStandardStream(IFileSystem3
*iface
,
3646 StandardStreamTypes StandardStreamType
,
3647 VARIANT_BOOL Unicode
,
3650 FIXME("%p %d %d %p\n", iface
, StandardStreamType
, Unicode
, ppts
);
3655 static void get_versionstring(VS_FIXEDFILEINFO
*info
, WCHAR
*ver
)
3657 static const WCHAR fmtW
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3661 version
= (((DWORDLONG
)info
->dwFileVersionMS
) << 32) + info
->dwFileVersionLS
;
3662 a
= (WORD
)( version
>> 48);
3663 b
= (WORD
)((version
>> 32) & 0xffff);
3664 c
= (WORD
)((version
>> 16) & 0xffff);
3665 d
= (WORD
)( version
& 0xffff);
3667 sprintfW(ver
, fmtW
, a
, b
, c
, d
);
3670 static HRESULT WINAPI
filesys_GetFileVersion(IFileSystem3
*iface
, BSTR name
, BSTR
*version
)
3672 static const WCHAR rootW
[] = {'\\',0};
3673 VS_FIXEDFILEINFO
*info
;
3679 TRACE("%p %s %p\n", iface
, debugstr_w(name
), version
);
3681 len
= GetFileVersionInfoSizeW(name
, NULL
);
3683 return HRESULT_FROM_WIN32(GetLastError());
3685 ptr
= heap_alloc(len
);
3686 if (!GetFileVersionInfoW(name
, 0, len
, ptr
))
3689 return HRESULT_FROM_WIN32(GetLastError());
3692 ret
= VerQueryValueW(ptr
, rootW
, (void**)&info
, &len
);
3696 return HRESULT_FROM_WIN32(GetLastError());
3699 get_versionstring(info
, ver
);
3702 *version
= SysAllocString(ver
);
3703 TRACE("version=%s\n", debugstr_w(ver
));
3708 static const struct IFileSystem3Vtbl filesys_vtbl
=
3710 filesys_QueryInterface
,
3713 filesys_GetTypeInfoCount
,
3714 filesys_GetTypeInfo
,
3715 filesys_GetIDsOfNames
,
3719 filesys_GetDriveName
,
3720 filesys_GetParentFolderName
,
3721 filesys_GetFileName
,
3722 filesys_GetBaseName
,
3723 filesys_GetExtensionName
,
3724 filesys_GetAbsolutePathName
,
3725 filesys_GetTempName
,
3726 filesys_DriveExists
,
3728 filesys_FolderExists
,
3732 filesys_GetSpecialFolder
,
3734 filesys_DeleteFolder
,
3739 filesys_CreateFolder
,
3740 filesys_CreateTextFile
,
3741 filesys_OpenTextFile
,
3742 filesys_GetStandardStream
,
3743 filesys_GetFileVersion
3746 static IFileSystem3 filesystem
= { &filesys_vtbl
};
3748 HRESULT WINAPI
FileSystem_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
3750 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
3752 return IFileSystem3_QueryInterface(&filesystem
, riid
, ppv
);