2 * ITSS Storage implementation
4 * Copyright 2004 Mike McCormack
6 * see http://bonedaddy.net/pabs3/hhm/#chmspec
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(itss
);
45 /************************************************************************/
47 typedef struct _ITSS_IStorageImpl
49 IStorageVtbl
*vtbl_IStorage
;
51 struct chmFile
*chmfile
;
57 struct enum_info
*next
, *prev
;
58 struct chmUnitInfo ui
;
61 typedef struct _IEnumSTATSTG_Impl
63 IEnumSTATSTGVtbl
*vtbl_IEnumSTATSTG
;
65 struct enum_info
*first
, *last
, *current
;
68 typedef struct _IStream_Impl
70 IStreamVtbl
*vtbl_IStream
;
72 ITSS_IStorageImpl
*stg
;
74 struct chmUnitInfo ui
;
77 static HRESULT
ITSS_create_chm_storage(
78 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
);
79 static IStream_Impl
* ITSS_create_stream(
80 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
);
82 /************************************************************************/
84 static HRESULT WINAPI
ITSS_IEnumSTATSTG_QueryInterface(
89 ICOM_THIS(IEnumSTATSTG_Impl
,iface
);
91 if (IsEqualGUID(riid
, &IID_IUnknown
)
92 || IsEqualGUID(riid
, &IID_IEnumSTATSTG
))
94 IEnumSTATSTG_AddRef(iface
);
99 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
100 return E_NOINTERFACE
;
103 static ULONG WINAPI
ITSS_IEnumSTATSTG_AddRef(
106 ICOM_THIS(IEnumSTATSTG_Impl
,iface
);
107 return ++(This
->ref
);
110 static ULONG WINAPI
ITSS_IEnumSTATSTG_Release(
113 ICOM_THIS(IEnumSTATSTG_Impl
,iface
);
115 ULONG ref
= --This
->ref
;
121 struct enum_info
*t
= This
->first
->next
;
122 HeapFree( GetProcessHeap(), 0, This
->first
);
125 HeapFree(GetProcessHeap(), 0, This
);
131 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Next(
137 ICOM_THIS(IEnumSTATSTG_Impl
,iface
);
139 struct enum_info
*cur
;
141 TRACE("%p %lu %p %p\n", This
, celt
, rgelt
, pceltFetched
);
145 while( (n
<celt
) && cur
)
149 memset( rgelt
, 0, sizeof *rgelt
);
155 len
= strlenW( str
) + 1;
156 rgelt
->pwcsName
= CoTaskMemAlloc( len
*sizeof(WCHAR
) );
157 strcpyW( rgelt
->pwcsName
, str
);
159 /* determine the type */
160 if( rgelt
->pwcsName
[len
-2] == '/' )
162 rgelt
->pwcsName
[len
-2] = 0;
163 rgelt
->type
= STGTY_STORAGE
;
166 rgelt
->type
= STGTY_STREAM
;
169 rgelt
->cbSize
.QuadPart
= cur
->ui
.length
;
171 /* advance to the next item if it exists */
185 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Skip(
189 ICOM_THIS(IEnumSTATSTG_Impl
,iface
);
191 struct enum_info
*cur
;
193 TRACE("%p %lu\n", This
, celt
);
197 while( (n
<celt
) && cur
)
210 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Reset(
213 ICOM_THIS(IEnumSTATSTG_Impl
,iface
);
215 TRACE("%p\n", This
);
217 This
->current
= This
->first
;
222 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Clone(
224 IEnumSTATSTG
** ppenum
)
230 struct IEnumSTATSTGVtbl IEnumSTATSTG_vtbl
=
232 ITSS_IEnumSTATSTG_QueryInterface
,
233 ITSS_IEnumSTATSTG_AddRef
,
234 ITSS_IEnumSTATSTG_Release
,
235 ITSS_IEnumSTATSTG_Next
,
236 ITSS_IEnumSTATSTG_Skip
,
237 ITSS_IEnumSTATSTG_Reset
,
238 ITSS_IEnumSTATSTG_Clone
241 static IEnumSTATSTG_Impl
*ITSS_create_enum( void )
243 IEnumSTATSTG_Impl
*stgenum
;
245 stgenum
= HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl
) );
246 stgenum
->vtbl_IEnumSTATSTG
= &IEnumSTATSTG_vtbl
;
248 stgenum
->first
= NULL
;
249 stgenum
->last
= NULL
;
250 stgenum
->current
= NULL
;
252 TRACE(" -> %p\n", stgenum
);
257 /************************************************************************/
259 HRESULT WINAPI
ITSS_IStorageImpl_QueryInterface(
264 ICOM_THIS(ITSS_IStorageImpl
,iface
);
266 if (IsEqualGUID(riid
, &IID_IUnknown
)
267 || IsEqualGUID(riid
, &IID_IStorage
))
269 IStorage_AddRef(iface
);
274 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
275 return E_NOINTERFACE
;
278 ULONG WINAPI
ITSS_IStorageImpl_AddRef(
281 ICOM_THIS(ITSS_IStorageImpl
,iface
);
282 return ++(This
->ref
);
285 ULONG WINAPI
ITSS_IStorageImpl_Release(
288 ICOM_THIS(ITSS_IStorageImpl
,iface
);
290 ULONG ref
= --This
->ref
;
294 HeapFree(GetProcessHeap(), 0, This
);
300 HRESULT WINAPI
ITSS_IStorageImpl_CreateStream(
312 HRESULT WINAPI
ITSS_IStorageImpl_OpenStream(
320 ICOM_THIS(ITSS_IStorageImpl
,iface
);
323 struct chmUnitInfo ui
;
327 TRACE("%p %s %p %lu %lu %p\n", This
, debugstr_w(pwcsName
),
328 reserved1
, grfMode
, reserved2
, ppstm
);
330 len
= strlenW( This
->dir
) + strlenW( pwcsName
) + 1;
331 path
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
332 strcpyW( path
, This
->dir
);
333 strcatW( path
, pwcsName
);
335 r
= chm_resolve_object(This
->chmfile
, path
, &ui
);
336 HeapFree( GetProcessHeap(), 0, path
);
338 if( r
!= CHM_RESOLVE_SUCCESS
)
339 return STG_E_FILENOTFOUND
;
341 stm
= ITSS_create_stream( This
, &ui
);
345 *ppstm
= (IStream
*) stm
;
350 HRESULT WINAPI
ITSS_IStorageImpl_CreateStorage(
362 HRESULT WINAPI
ITSS_IStorageImpl_OpenStorage(
365 IStorage
* pstgPriority
,
375 HRESULT WINAPI
ITSS_IStorageImpl_CopyTo(
378 const IID
* rgiidExclude
,
386 HRESULT WINAPI
ITSS_IStorageImpl_MoveElementTo(
390 LPCOLESTR pwcsNewName
,
397 HRESULT WINAPI
ITSS_IStorageImpl_Commit(
399 DWORD grfCommitFlags
)
405 HRESULT WINAPI
ITSS_IStorageImpl_Revert(
412 static int ITSS_chm_enumerator(
414 struct chmUnitInfo
*ui
,
417 struct enum_info
*info
;
418 IEnumSTATSTG_Impl
* stgenum
= context
;
420 TRACE("adding %s to enumeration\n", debugstr_w(ui
->path
) );
422 info
= HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info
) );
423 memcpy( &info
->ui
, ui
, sizeof info
->ui
);
426 info
->prev
= stgenum
->last
;
428 stgenum
->last
->next
= info
;
430 stgenum
->first
= info
;
431 stgenum
->last
= info
;
433 return CHM_ENUMERATOR_CONTINUE
;
436 HRESULT WINAPI
ITSS_IStorageImpl_EnumElements(
441 IEnumSTATSTG
** ppenum
)
443 ICOM_THIS(ITSS_IStorageImpl
,iface
);
444 IEnumSTATSTG_Impl
* stgenum
;
446 TRACE("%p %ld %p %ld %p\n", This
, reserved1
, reserved2
, reserved3
, ppenum
);
448 stgenum
= ITSS_create_enum();
452 chm_enumerate_dir(This
->chmfile
,
458 stgenum
->current
= stgenum
->first
;
460 *ppenum
= (IEnumSTATSTG
*) stgenum
;
465 HRESULT WINAPI
ITSS_IStorageImpl_DestroyElement(
473 HRESULT WINAPI
ITSS_IStorageImpl_RenameElement(
475 LPCOLESTR pwcsOldName
,
476 LPCOLESTR pwcsNewName
)
482 HRESULT WINAPI
ITSS_IStorageImpl_SetElementTimes(
485 const FILETIME
* pctime
,
486 const FILETIME
* patime
,
487 const FILETIME
* pmtime
)
493 HRESULT WINAPI
ITSS_IStorageImpl_SetClass(
501 HRESULT WINAPI
ITSS_IStorageImpl_SetStateBits(
510 HRESULT WINAPI
ITSS_IStorageImpl_Stat(
519 static IStorageVtbl ITSS_IStorageImpl_Vtbl
=
521 ITSS_IStorageImpl_QueryInterface
,
522 ITSS_IStorageImpl_AddRef
,
523 ITSS_IStorageImpl_Release
,
524 ITSS_IStorageImpl_CreateStream
,
525 ITSS_IStorageImpl_OpenStream
,
526 ITSS_IStorageImpl_CreateStorage
,
527 ITSS_IStorageImpl_OpenStorage
,
528 ITSS_IStorageImpl_CopyTo
,
529 ITSS_IStorageImpl_MoveElementTo
,
530 ITSS_IStorageImpl_Commit
,
531 ITSS_IStorageImpl_Revert
,
532 ITSS_IStorageImpl_EnumElements
,
533 ITSS_IStorageImpl_DestroyElement
,
534 ITSS_IStorageImpl_RenameElement
,
535 ITSS_IStorageImpl_SetElementTimes
,
536 ITSS_IStorageImpl_SetClass
,
537 ITSS_IStorageImpl_SetStateBits
,
538 ITSS_IStorageImpl_Stat
,
541 static HRESULT
ITSS_create_chm_storage(
542 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
)
544 ITSS_IStorageImpl
*stg
;
547 TRACE("%p %s\n", chmfile
, debugstr_w( dir
) );
549 len
= strlenW( dir
) + 1;
550 stg
= HeapAlloc( GetProcessHeap(), 0,
551 sizeof (ITSS_IStorageImpl
) + len
*sizeof(WCHAR
) );
552 stg
->vtbl_IStorage
= &ITSS_IStorageImpl_Vtbl
;
554 stg
->chmfile
= chmfile
;
555 strcpyW( stg
->dir
, dir
);
557 *ppstgOpen
= (IStorage
*) stg
;
562 HRESULT
ITSS_StgOpenStorage(
563 const WCHAR
* pwcsName
,
564 IStorage
* pstgPriority
,
568 IStorage
** ppstgOpen
)
570 struct chmFile
*chmfile
;
571 static const WCHAR szRoot
[] = { '/', 0 };
573 TRACE("%s\n", debugstr_w(pwcsName
) );
575 chmfile
= chm_openW( pwcsName
);
579 return ITSS_create_chm_storage( chmfile
, szRoot
, ppstgOpen
);
582 /************************************************************************/
584 static HRESULT WINAPI
ITSS_IStream_QueryInterface(
589 ICOM_THIS(IStream_Impl
,iface
);
591 if (IsEqualGUID(riid
, &IID_IUnknown
)
592 || IsEqualGUID(riid
, &IID_ISequentialStream
)
593 || IsEqualGUID(riid
, &IID_IStream
))
595 IStream_AddRef(iface
);
600 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
601 return E_NOINTERFACE
;
604 static ULONG WINAPI
ITSS_IStream_AddRef(
607 ICOM_THIS(IStream_Impl
,iface
);
608 return ++(This
->ref
);
611 static ULONG WINAPI
ITSS_IStream_Release(
614 ICOM_THIS(IStream_Impl
,iface
);
616 ULONG ref
= --This
->ref
;
620 IStorage_Release( (IStorage
*) This
->stg
);
621 HeapFree(GetProcessHeap(), 0, This
);
627 static HRESULT WINAPI
ITSS_IStream_Read(
633 ICOM_THIS(IStream_Impl
,iface
);
636 TRACE("%p %p %lu %p\n", This
, pv
, cb
, pcbRead
);
638 count
= chm_retrieve_object(This
->stg
->chmfile
,
639 &This
->ui
, pv
, This
->addr
, cb
);
647 static HRESULT WINAPI
ITSS_IStream_Write(
657 static HRESULT WINAPI
ITSS_IStream_Seek(
659 LARGE_INTEGER dlibMove
,
661 ULARGE_INTEGER
* plibNewPosition
)
663 ICOM_THIS(IStream_Impl
,iface
);
666 TRACE("%p %s %lu %p\n", This
,
667 wine_dbgstr_longlong( dlibMove
.QuadPart
), dwOrigin
, plibNewPosition
);
672 case STREAM_SEEK_CUR
:
673 newpos
= This
->addr
+ dlibMove
.QuadPart
;
675 case STREAM_SEEK_SET
:
676 newpos
= dlibMove
.QuadPart
;
678 case STREAM_SEEK_END
:
679 newpos
= This
->ui
.length
+ dlibMove
.QuadPart
;
683 if( ( newpos
< 0 ) || ( newpos
> This
->ui
.length
) )
684 return STG_E_INVALIDPOINTER
;
687 if( plibNewPosition
)
688 plibNewPosition
->QuadPart
= This
->addr
;
693 static HRESULT WINAPI
ITSS_IStream_SetSize(
695 ULARGE_INTEGER libNewSize
)
701 static HRESULT WINAPI
ITSS_IStream_CopyTo(
705 ULARGE_INTEGER
* pcbRead
,
706 ULARGE_INTEGER
* pcbWritten
)
712 static HRESULT WINAPI
ITSS_IStream_Commit(
714 DWORD grfCommitFlags
)
720 static HRESULT WINAPI
ITSS_IStream_Revert(
727 static HRESULT WINAPI
ITSS_IStream_LockRegion(
729 ULARGE_INTEGER libOffset
,
737 static HRESULT WINAPI
ITSS_IStream_UnlockRegion(
739 ULARGE_INTEGER libOffset
,
747 static HRESULT WINAPI
ITSS_IStream_Stat(
756 static HRESULT WINAPI
ITSS_IStream_Clone(
764 struct IStreamVtbl ITSS_IStream_vtbl
=
766 ITSS_IStream_QueryInterface
,
768 ITSS_IStream_Release
,
772 ITSS_IStream_SetSize
,
776 ITSS_IStream_LockRegion
,
777 ITSS_IStream_UnlockRegion
,
782 static IStream_Impl
*ITSS_create_stream(
783 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
)
787 stm
= HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl
) );
788 stm
->vtbl_IStream
= &ITSS_IStream_vtbl
;
791 memcpy( &stm
->ui
, ui
, sizeof stm
->ui
);
793 IStorage_AddRef( (IStorage
*) stg
);
795 TRACE(" -> %p\n", stm
);