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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
42 #include "wine/itss.h"
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(itss
);
48 extern LONG dll_count
;
50 /************************************************************************/
52 typedef struct _ITSS_IStorageImpl
54 const IStorageVtbl
*vtbl_IStorage
;
56 struct chmFile
*chmfile
;
62 struct enum_info
*next
, *prev
;
63 struct chmUnitInfo ui
;
66 typedef struct _IEnumSTATSTG_Impl
68 const IEnumSTATSTGVtbl
*vtbl_IEnumSTATSTG
;
70 struct enum_info
*first
, *last
, *current
;
73 typedef struct _IStream_Impl
75 const IStreamVtbl
*vtbl_IStream
;
77 ITSS_IStorageImpl
*stg
;
79 struct chmUnitInfo ui
;
82 static HRESULT
ITSS_create_chm_storage(
83 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
);
84 static IStream_Impl
* ITSS_create_stream(
85 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
);
87 /************************************************************************/
89 static HRESULT WINAPI
ITSS_IEnumSTATSTG_QueryInterface(
94 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
96 if (IsEqualGUID(riid
, &IID_IUnknown
)
97 || IsEqualGUID(riid
, &IID_IEnumSTATSTG
))
99 IEnumSTATSTG_AddRef(iface
);
104 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
105 return E_NOINTERFACE
;
108 static ULONG WINAPI
ITSS_IEnumSTATSTG_AddRef(
111 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
112 return InterlockedIncrement(&This
->ref
);
115 static ULONG WINAPI
ITSS_IEnumSTATSTG_Release(
118 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
120 ULONG ref
= InterlockedDecrement(&This
->ref
);
126 struct enum_info
*t
= This
->first
->next
;
127 HeapFree( GetProcessHeap(), 0, This
->first
);
130 HeapFree(GetProcessHeap(), 0, This
);
131 InterlockedDecrement(&dll_count
);
137 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Next(
143 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
145 struct enum_info
*cur
;
147 TRACE("%p %lu %p %p\n", This
, celt
, rgelt
, pceltFetched
);
151 while( (n
<celt
) && cur
)
155 memset( rgelt
, 0, sizeof *rgelt
);
161 len
= strlenW( str
) + 1;
162 rgelt
->pwcsName
= CoTaskMemAlloc( len
*sizeof(WCHAR
) );
163 strcpyW( rgelt
->pwcsName
, str
);
165 /* determine the type */
166 if( rgelt
->pwcsName
[len
-2] == '/' )
168 rgelt
->pwcsName
[len
-2] = 0;
169 rgelt
->type
= STGTY_STORAGE
;
172 rgelt
->type
= STGTY_STREAM
;
175 rgelt
->cbSize
.QuadPart
= cur
->ui
.length
;
177 /* advance to the next item if it exists */
191 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Skip(
195 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
197 struct enum_info
*cur
;
199 TRACE("%p %lu\n", This
, celt
);
203 while( (n
<celt
) && cur
)
216 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Reset(
219 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
221 TRACE("%p\n", This
);
223 This
->current
= This
->first
;
228 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Clone(
230 IEnumSTATSTG
** ppenum
)
236 static const IEnumSTATSTGVtbl IEnumSTATSTG_vtbl
=
238 ITSS_IEnumSTATSTG_QueryInterface
,
239 ITSS_IEnumSTATSTG_AddRef
,
240 ITSS_IEnumSTATSTG_Release
,
241 ITSS_IEnumSTATSTG_Next
,
242 ITSS_IEnumSTATSTG_Skip
,
243 ITSS_IEnumSTATSTG_Reset
,
244 ITSS_IEnumSTATSTG_Clone
247 static IEnumSTATSTG_Impl
*ITSS_create_enum( void )
249 IEnumSTATSTG_Impl
*stgenum
;
251 stgenum
= HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl
) );
252 stgenum
->vtbl_IEnumSTATSTG
= &IEnumSTATSTG_vtbl
;
254 stgenum
->first
= NULL
;
255 stgenum
->last
= NULL
;
256 stgenum
->current
= NULL
;
257 InterlockedIncrement(&dll_count
);
259 TRACE(" -> %p\n", stgenum
);
264 /************************************************************************/
266 static HRESULT WINAPI
ITSS_IStorageImpl_QueryInterface(
271 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
273 if (IsEqualGUID(riid
, &IID_IUnknown
)
274 || IsEqualGUID(riid
, &IID_IStorage
))
276 IStorage_AddRef(iface
);
281 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
282 return E_NOINTERFACE
;
285 static ULONG WINAPI
ITSS_IStorageImpl_AddRef(
288 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
289 return InterlockedIncrement(&This
->ref
);
292 static ULONG WINAPI
ITSS_IStorageImpl_Release(
295 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
297 ULONG ref
= InterlockedDecrement(&This
->ref
);
301 HeapFree(GetProcessHeap(), 0, This
);
302 InterlockedDecrement(&dll_count
);
308 static HRESULT WINAPI
ITSS_IStorageImpl_CreateStream(
320 static HRESULT WINAPI
ITSS_IStorageImpl_OpenStream(
328 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
331 struct chmUnitInfo ui
;
335 TRACE("%p %s %p %lu %lu %p\n", This
, debugstr_w(pwcsName
),
336 reserved1
, grfMode
, reserved2
, ppstm
);
338 len
= strlenW( This
->dir
) + strlenW( pwcsName
) + 1;
339 path
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
340 strcpyW( path
, This
->dir
);
341 if( pwcsName
[0] == '/' )
343 WCHAR
*p
= &path
[strlenW( path
) - 1];
344 while( ( path
<= p
) && ( *p
== '/' ) )
347 strcatW( path
, pwcsName
);
349 TRACE("Resolving %s\n", debugstr_w(path
));
351 r
= chm_resolve_object(This
->chmfile
, path
, &ui
);
352 HeapFree( GetProcessHeap(), 0, path
);
354 if( r
!= CHM_RESOLVE_SUCCESS
)
355 return STG_E_FILENOTFOUND
;
357 stm
= ITSS_create_stream( This
, &ui
);
361 *ppstm
= (IStream
*) stm
;
366 static HRESULT WINAPI
ITSS_IStorageImpl_CreateStorage(
378 static HRESULT WINAPI
ITSS_IStorageImpl_OpenStorage(
381 IStorage
* pstgPriority
,
387 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
389 FIXME("%p %s %p %lu %p %lu %p\n", This
, debugstr_w(pwcsName
),
390 pstgPriority
, grfMode
, snbExclude
, reserved
, ppstg
);
394 static HRESULT WINAPI
ITSS_IStorageImpl_CopyTo(
397 const IID
* rgiidExclude
,
405 static HRESULT WINAPI
ITSS_IStorageImpl_MoveElementTo(
409 LPCOLESTR pwcsNewName
,
416 static HRESULT WINAPI
ITSS_IStorageImpl_Commit(
418 DWORD grfCommitFlags
)
424 static HRESULT WINAPI
ITSS_IStorageImpl_Revert(
431 static int ITSS_chm_enumerator(
433 struct chmUnitInfo
*ui
,
436 struct enum_info
*info
;
437 IEnumSTATSTG_Impl
* stgenum
= context
;
439 TRACE("adding %s to enumeration\n", debugstr_w(ui
->path
) );
441 info
= HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info
) );
442 memcpy( &info
->ui
, ui
, sizeof info
->ui
);
445 info
->prev
= stgenum
->last
;
447 stgenum
->last
->next
= info
;
449 stgenum
->first
= info
;
450 stgenum
->last
= info
;
452 return CHM_ENUMERATOR_CONTINUE
;
455 static HRESULT WINAPI
ITSS_IStorageImpl_EnumElements(
460 IEnumSTATSTG
** ppenum
)
462 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
463 IEnumSTATSTG_Impl
* stgenum
;
465 TRACE("%p %ld %p %ld %p\n", This
, reserved1
, reserved2
, reserved3
, ppenum
);
467 stgenum
= ITSS_create_enum();
471 chm_enumerate_dir(This
->chmfile
,
477 stgenum
->current
= stgenum
->first
;
479 *ppenum
= (IEnumSTATSTG
*) stgenum
;
484 static HRESULT WINAPI
ITSS_IStorageImpl_DestroyElement(
492 static HRESULT WINAPI
ITSS_IStorageImpl_RenameElement(
494 LPCOLESTR pwcsOldName
,
495 LPCOLESTR pwcsNewName
)
501 static HRESULT WINAPI
ITSS_IStorageImpl_SetElementTimes(
504 const FILETIME
* pctime
,
505 const FILETIME
* patime
,
506 const FILETIME
* pmtime
)
512 static HRESULT WINAPI
ITSS_IStorageImpl_SetClass(
520 static HRESULT WINAPI
ITSS_IStorageImpl_SetStateBits(
529 static HRESULT WINAPI
ITSS_IStorageImpl_Stat(
538 static const IStorageVtbl ITSS_IStorageImpl_Vtbl
=
540 ITSS_IStorageImpl_QueryInterface
,
541 ITSS_IStorageImpl_AddRef
,
542 ITSS_IStorageImpl_Release
,
543 ITSS_IStorageImpl_CreateStream
,
544 ITSS_IStorageImpl_OpenStream
,
545 ITSS_IStorageImpl_CreateStorage
,
546 ITSS_IStorageImpl_OpenStorage
,
547 ITSS_IStorageImpl_CopyTo
,
548 ITSS_IStorageImpl_MoveElementTo
,
549 ITSS_IStorageImpl_Commit
,
550 ITSS_IStorageImpl_Revert
,
551 ITSS_IStorageImpl_EnumElements
,
552 ITSS_IStorageImpl_DestroyElement
,
553 ITSS_IStorageImpl_RenameElement
,
554 ITSS_IStorageImpl_SetElementTimes
,
555 ITSS_IStorageImpl_SetClass
,
556 ITSS_IStorageImpl_SetStateBits
,
557 ITSS_IStorageImpl_Stat
,
560 static HRESULT
ITSS_create_chm_storage(
561 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
)
563 ITSS_IStorageImpl
*stg
;
566 TRACE("%p %s\n", chmfile
, debugstr_w( dir
) );
568 len
= strlenW( dir
) + 1;
569 stg
= HeapAlloc( GetProcessHeap(), 0,
570 sizeof (ITSS_IStorageImpl
) + len
*sizeof(WCHAR
) );
571 stg
->vtbl_IStorage
= &ITSS_IStorageImpl_Vtbl
;
573 stg
->chmfile
= chmfile
;
574 strcpyW( stg
->dir
, dir
);
576 *ppstgOpen
= (IStorage
*) stg
;
577 InterlockedIncrement(&dll_count
);
582 HRESULT
ITSS_StgOpenStorage(
583 const WCHAR
* pwcsName
,
584 IStorage
* pstgPriority
,
588 IStorage
** ppstgOpen
)
590 struct chmFile
*chmfile
;
591 static const WCHAR szRoot
[] = { '/', 0 };
593 TRACE("%s\n", debugstr_w(pwcsName
) );
595 chmfile
= chm_openW( pwcsName
);
599 return ITSS_create_chm_storage( chmfile
, szRoot
, ppstgOpen
);
602 /************************************************************************/
604 static HRESULT WINAPI
ITSS_IStream_QueryInterface(
609 IStream_Impl
*This
= (IStream_Impl
*)iface
;
611 if (IsEqualGUID(riid
, &IID_IUnknown
)
612 || IsEqualGUID(riid
, &IID_ISequentialStream
)
613 || IsEqualGUID(riid
, &IID_IStream
))
615 IStream_AddRef(iface
);
620 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
621 return E_NOINTERFACE
;
624 static ULONG WINAPI
ITSS_IStream_AddRef(
627 IStream_Impl
*This
= (IStream_Impl
*)iface
;
628 return InterlockedIncrement(&This
->ref
);
631 static ULONG WINAPI
ITSS_IStream_Release(
634 IStream_Impl
*This
= (IStream_Impl
*)iface
;
636 ULONG ref
= InterlockedDecrement(&This
->ref
);
640 IStorage_Release( (IStorage
*) This
->stg
);
641 HeapFree(GetProcessHeap(), 0, This
);
642 InterlockedDecrement(&dll_count
);
648 static HRESULT WINAPI
ITSS_IStream_Read(
654 IStream_Impl
*This
= (IStream_Impl
*)iface
;
657 TRACE("%p %p %lu %p\n", This
, pv
, cb
, pcbRead
);
659 count
= chm_retrieve_object(This
->stg
->chmfile
,
660 &This
->ui
, pv
, This
->addr
, cb
);
668 static HRESULT WINAPI
ITSS_IStream_Write(
678 static HRESULT WINAPI
ITSS_IStream_Seek(
680 LARGE_INTEGER dlibMove
,
682 ULARGE_INTEGER
* plibNewPosition
)
684 IStream_Impl
*This
= (IStream_Impl
*)iface
;
687 TRACE("%p %s %lu %p\n", This
,
688 wine_dbgstr_longlong( dlibMove
.QuadPart
), dwOrigin
, plibNewPosition
);
693 case STREAM_SEEK_CUR
:
694 newpos
= This
->addr
+ dlibMove
.QuadPart
;
696 case STREAM_SEEK_SET
:
697 newpos
= dlibMove
.QuadPart
;
699 case STREAM_SEEK_END
:
700 newpos
= This
->ui
.length
+ dlibMove
.QuadPart
;
704 if( ( newpos
< 0 ) || ( newpos
> This
->ui
.length
) )
705 return STG_E_INVALIDPOINTER
;
708 if( plibNewPosition
)
709 plibNewPosition
->QuadPart
= This
->addr
;
714 static HRESULT WINAPI
ITSS_IStream_SetSize(
716 ULARGE_INTEGER libNewSize
)
722 static HRESULT WINAPI
ITSS_IStream_CopyTo(
726 ULARGE_INTEGER
* pcbRead
,
727 ULARGE_INTEGER
* pcbWritten
)
733 static HRESULT WINAPI
ITSS_IStream_Commit(
735 DWORD grfCommitFlags
)
741 static HRESULT WINAPI
ITSS_IStream_Revert(
748 static HRESULT WINAPI
ITSS_IStream_LockRegion(
750 ULARGE_INTEGER libOffset
,
758 static HRESULT WINAPI
ITSS_IStream_UnlockRegion(
760 ULARGE_INTEGER libOffset
,
768 static HRESULT WINAPI
ITSS_IStream_Stat(
773 IStream_Impl
*This
= (IStream_Impl
*)iface
;
775 TRACE("%p %p %ld\n", This
, pstatstg
, grfStatFlag
);
777 memset( pstatstg
, 0, sizeof *pstatstg
);
778 if( !( grfStatFlag
& STATFLAG_NONAME
) )
780 FIXME("copy the name\n");
782 pstatstg
->type
= STGTY_STREAM
;
783 pstatstg
->cbSize
.QuadPart
= This
->ui
.length
;
784 pstatstg
->grfMode
= STGM_READ
;
785 memcpy( &pstatstg
->clsid
, &CLSID_ITStorage
, sizeof (CLSID
) );
790 static HRESULT WINAPI
ITSS_IStream_Clone(
798 static const IStreamVtbl ITSS_IStream_vtbl
=
800 ITSS_IStream_QueryInterface
,
802 ITSS_IStream_Release
,
806 ITSS_IStream_SetSize
,
810 ITSS_IStream_LockRegion
,
811 ITSS_IStream_UnlockRegion
,
816 static IStream_Impl
*ITSS_create_stream(
817 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
)
821 stm
= HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl
) );
822 stm
->vtbl_IStream
= &ITSS_IStream_vtbl
;
825 memcpy( &stm
->ui
, ui
, sizeof stm
->ui
);
827 IStorage_AddRef( (IStorage
*) stg
);
828 InterlockedIncrement(&dll_count
);
830 TRACE(" -> %p\n", stm
);