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
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(itss
);
48 /************************************************************************/
50 typedef struct _ITSS_IStorageImpl
52 IStorageVtbl
*vtbl_IStorage
;
54 struct chmFile
*chmfile
;
60 struct enum_info
*next
, *prev
;
61 struct chmUnitInfo ui
;
64 typedef struct _IEnumSTATSTG_Impl
66 IEnumSTATSTGVtbl
*vtbl_IEnumSTATSTG
;
68 struct enum_info
*first
, *last
, *current
;
71 typedef struct _IStream_Impl
73 IStreamVtbl
*vtbl_IStream
;
75 ITSS_IStorageImpl
*stg
;
77 struct chmUnitInfo ui
;
80 static HRESULT
ITSS_create_chm_storage(
81 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
);
82 static IStream_Impl
* ITSS_create_stream(
83 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
);
85 /************************************************************************/
87 static HRESULT WINAPI
ITSS_IEnumSTATSTG_QueryInterface(
92 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
94 if (IsEqualGUID(riid
, &IID_IUnknown
)
95 || IsEqualGUID(riid
, &IID_IEnumSTATSTG
))
97 IEnumSTATSTG_AddRef(iface
);
102 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
103 return E_NOINTERFACE
;
106 static ULONG WINAPI
ITSS_IEnumSTATSTG_AddRef(
109 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
110 return ++(This
->ref
);
113 static ULONG WINAPI
ITSS_IEnumSTATSTG_Release(
116 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
118 ULONG ref
= --This
->ref
;
124 struct enum_info
*t
= This
->first
->next
;
125 HeapFree( GetProcessHeap(), 0, This
->first
);
128 HeapFree(GetProcessHeap(), 0, This
);
134 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Next(
140 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
142 struct enum_info
*cur
;
144 TRACE("%p %lu %p %p\n", This
, celt
, rgelt
, pceltFetched
);
148 while( (n
<celt
) && cur
)
152 memset( rgelt
, 0, sizeof *rgelt
);
158 len
= strlenW( str
) + 1;
159 rgelt
->pwcsName
= CoTaskMemAlloc( len
*sizeof(WCHAR
) );
160 strcpyW( rgelt
->pwcsName
, str
);
162 /* determine the type */
163 if( rgelt
->pwcsName
[len
-2] == '/' )
165 rgelt
->pwcsName
[len
-2] = 0;
166 rgelt
->type
= STGTY_STORAGE
;
169 rgelt
->type
= STGTY_STREAM
;
172 rgelt
->cbSize
.QuadPart
= cur
->ui
.length
;
174 /* advance to the next item if it exists */
188 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Skip(
192 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
194 struct enum_info
*cur
;
196 TRACE("%p %lu\n", This
, celt
);
200 while( (n
<celt
) && cur
)
213 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Reset(
216 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
218 TRACE("%p\n", This
);
220 This
->current
= This
->first
;
225 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Clone(
227 IEnumSTATSTG
** ppenum
)
233 struct IEnumSTATSTGVtbl IEnumSTATSTG_vtbl
=
235 ITSS_IEnumSTATSTG_QueryInterface
,
236 ITSS_IEnumSTATSTG_AddRef
,
237 ITSS_IEnumSTATSTG_Release
,
238 ITSS_IEnumSTATSTG_Next
,
239 ITSS_IEnumSTATSTG_Skip
,
240 ITSS_IEnumSTATSTG_Reset
,
241 ITSS_IEnumSTATSTG_Clone
244 static IEnumSTATSTG_Impl
*ITSS_create_enum( void )
246 IEnumSTATSTG_Impl
*stgenum
;
248 stgenum
= HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl
) );
249 stgenum
->vtbl_IEnumSTATSTG
= &IEnumSTATSTG_vtbl
;
251 stgenum
->first
= NULL
;
252 stgenum
->last
= NULL
;
253 stgenum
->current
= NULL
;
255 TRACE(" -> %p\n", stgenum
);
260 /************************************************************************/
262 HRESULT WINAPI
ITSS_IStorageImpl_QueryInterface(
267 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
269 if (IsEqualGUID(riid
, &IID_IUnknown
)
270 || IsEqualGUID(riid
, &IID_IStorage
))
272 IStorage_AddRef(iface
);
277 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
278 return E_NOINTERFACE
;
281 ULONG WINAPI
ITSS_IStorageImpl_AddRef(
284 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
285 return ++(This
->ref
);
288 ULONG WINAPI
ITSS_IStorageImpl_Release(
291 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
293 ULONG ref
= --This
->ref
;
297 HeapFree(GetProcessHeap(), 0, This
);
303 HRESULT WINAPI
ITSS_IStorageImpl_CreateStream(
315 HRESULT WINAPI
ITSS_IStorageImpl_OpenStream(
323 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
326 struct chmUnitInfo ui
;
330 TRACE("%p %s %p %lu %lu %p\n", This
, debugstr_w(pwcsName
),
331 reserved1
, grfMode
, reserved2
, ppstm
);
333 len
= strlenW( This
->dir
) + strlenW( pwcsName
) + 1;
334 path
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
335 strcpyW( path
, This
->dir
);
336 if( pwcsName
[0] == '/' )
338 WCHAR
*p
= &path
[strlenW( path
) - 1];
339 while( ( path
<= p
) && ( *p
== '/' ) )
342 strcatW( path
, pwcsName
);
344 TRACE("Resolving %s\n", debugstr_w(path
));
346 r
= chm_resolve_object(This
->chmfile
, path
, &ui
);
347 HeapFree( GetProcessHeap(), 0, path
);
349 if( r
!= CHM_RESOLVE_SUCCESS
)
350 return STG_E_FILENOTFOUND
;
352 stm
= ITSS_create_stream( This
, &ui
);
356 *ppstm
= (IStream
*) stm
;
361 HRESULT WINAPI
ITSS_IStorageImpl_CreateStorage(
373 HRESULT WINAPI
ITSS_IStorageImpl_OpenStorage(
376 IStorage
* pstgPriority
,
382 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
384 FIXME("%p %s %p %lu %p %lu %p\n", This
, debugstr_w(pwcsName
),
385 pstgPriority
, grfMode
, snbExclude
, reserved
, ppstg
);
389 HRESULT WINAPI
ITSS_IStorageImpl_CopyTo(
392 const IID
* rgiidExclude
,
400 HRESULT WINAPI
ITSS_IStorageImpl_MoveElementTo(
404 LPCOLESTR pwcsNewName
,
411 HRESULT WINAPI
ITSS_IStorageImpl_Commit(
413 DWORD grfCommitFlags
)
419 HRESULT WINAPI
ITSS_IStorageImpl_Revert(
426 static int ITSS_chm_enumerator(
428 struct chmUnitInfo
*ui
,
431 struct enum_info
*info
;
432 IEnumSTATSTG_Impl
* stgenum
= context
;
434 TRACE("adding %s to enumeration\n", debugstr_w(ui
->path
) );
436 info
= HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info
) );
437 memcpy( &info
->ui
, ui
, sizeof info
->ui
);
440 info
->prev
= stgenum
->last
;
442 stgenum
->last
->next
= info
;
444 stgenum
->first
= info
;
445 stgenum
->last
= info
;
447 return CHM_ENUMERATOR_CONTINUE
;
450 HRESULT WINAPI
ITSS_IStorageImpl_EnumElements(
455 IEnumSTATSTG
** ppenum
)
457 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
458 IEnumSTATSTG_Impl
* stgenum
;
460 TRACE("%p %ld %p %ld %p\n", This
, reserved1
, reserved2
, reserved3
, ppenum
);
462 stgenum
= ITSS_create_enum();
466 chm_enumerate_dir(This
->chmfile
,
472 stgenum
->current
= stgenum
->first
;
474 *ppenum
= (IEnumSTATSTG
*) stgenum
;
479 HRESULT WINAPI
ITSS_IStorageImpl_DestroyElement(
487 HRESULT WINAPI
ITSS_IStorageImpl_RenameElement(
489 LPCOLESTR pwcsOldName
,
490 LPCOLESTR pwcsNewName
)
496 HRESULT WINAPI
ITSS_IStorageImpl_SetElementTimes(
499 const FILETIME
* pctime
,
500 const FILETIME
* patime
,
501 const FILETIME
* pmtime
)
507 HRESULT WINAPI
ITSS_IStorageImpl_SetClass(
515 HRESULT WINAPI
ITSS_IStorageImpl_SetStateBits(
524 HRESULT WINAPI
ITSS_IStorageImpl_Stat(
533 static IStorageVtbl ITSS_IStorageImpl_Vtbl
=
535 ITSS_IStorageImpl_QueryInterface
,
536 ITSS_IStorageImpl_AddRef
,
537 ITSS_IStorageImpl_Release
,
538 ITSS_IStorageImpl_CreateStream
,
539 ITSS_IStorageImpl_OpenStream
,
540 ITSS_IStorageImpl_CreateStorage
,
541 ITSS_IStorageImpl_OpenStorage
,
542 ITSS_IStorageImpl_CopyTo
,
543 ITSS_IStorageImpl_MoveElementTo
,
544 ITSS_IStorageImpl_Commit
,
545 ITSS_IStorageImpl_Revert
,
546 ITSS_IStorageImpl_EnumElements
,
547 ITSS_IStorageImpl_DestroyElement
,
548 ITSS_IStorageImpl_RenameElement
,
549 ITSS_IStorageImpl_SetElementTimes
,
550 ITSS_IStorageImpl_SetClass
,
551 ITSS_IStorageImpl_SetStateBits
,
552 ITSS_IStorageImpl_Stat
,
555 static HRESULT
ITSS_create_chm_storage(
556 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
)
558 ITSS_IStorageImpl
*stg
;
561 TRACE("%p %s\n", chmfile
, debugstr_w( dir
) );
563 len
= strlenW( dir
) + 1;
564 stg
= HeapAlloc( GetProcessHeap(), 0,
565 sizeof (ITSS_IStorageImpl
) + len
*sizeof(WCHAR
) );
566 stg
->vtbl_IStorage
= &ITSS_IStorageImpl_Vtbl
;
568 stg
->chmfile
= chmfile
;
569 strcpyW( stg
->dir
, dir
);
571 *ppstgOpen
= (IStorage
*) stg
;
576 HRESULT
ITSS_StgOpenStorage(
577 const WCHAR
* pwcsName
,
578 IStorage
* pstgPriority
,
582 IStorage
** ppstgOpen
)
584 struct chmFile
*chmfile
;
585 static const WCHAR szRoot
[] = { '/', 0 };
587 TRACE("%s\n", debugstr_w(pwcsName
) );
589 chmfile
= chm_openW( pwcsName
);
593 return ITSS_create_chm_storage( chmfile
, szRoot
, ppstgOpen
);
596 /************************************************************************/
598 static HRESULT WINAPI
ITSS_IStream_QueryInterface(
603 IStream_Impl
*This
= (IStream_Impl
*)iface
;
605 if (IsEqualGUID(riid
, &IID_IUnknown
)
606 || IsEqualGUID(riid
, &IID_ISequentialStream
)
607 || IsEqualGUID(riid
, &IID_IStream
))
609 IStream_AddRef(iface
);
614 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
615 return E_NOINTERFACE
;
618 static ULONG WINAPI
ITSS_IStream_AddRef(
621 IStream_Impl
*This
= (IStream_Impl
*)iface
;
622 return ++(This
->ref
);
625 static ULONG WINAPI
ITSS_IStream_Release(
628 IStream_Impl
*This
= (IStream_Impl
*)iface
;
630 ULONG ref
= --This
->ref
;
634 IStorage_Release( (IStorage
*) This
->stg
);
635 HeapFree(GetProcessHeap(), 0, This
);
641 static HRESULT WINAPI
ITSS_IStream_Read(
647 IStream_Impl
*This
= (IStream_Impl
*)iface
;
650 TRACE("%p %p %lu %p\n", This
, pv
, cb
, pcbRead
);
652 count
= chm_retrieve_object(This
->stg
->chmfile
,
653 &This
->ui
, pv
, This
->addr
, cb
);
661 static HRESULT WINAPI
ITSS_IStream_Write(
671 static HRESULT WINAPI
ITSS_IStream_Seek(
673 LARGE_INTEGER dlibMove
,
675 ULARGE_INTEGER
* plibNewPosition
)
677 IStream_Impl
*This
= (IStream_Impl
*)iface
;
680 TRACE("%p %s %lu %p\n", This
,
681 wine_dbgstr_longlong( dlibMove
.QuadPart
), dwOrigin
, plibNewPosition
);
686 case STREAM_SEEK_CUR
:
687 newpos
= This
->addr
+ dlibMove
.QuadPart
;
689 case STREAM_SEEK_SET
:
690 newpos
= dlibMove
.QuadPart
;
692 case STREAM_SEEK_END
:
693 newpos
= This
->ui
.length
+ dlibMove
.QuadPart
;
697 if( ( newpos
< 0 ) || ( newpos
> This
->ui
.length
) )
698 return STG_E_INVALIDPOINTER
;
701 if( plibNewPosition
)
702 plibNewPosition
->QuadPart
= This
->addr
;
707 static HRESULT WINAPI
ITSS_IStream_SetSize(
709 ULARGE_INTEGER libNewSize
)
715 static HRESULT WINAPI
ITSS_IStream_CopyTo(
719 ULARGE_INTEGER
* pcbRead
,
720 ULARGE_INTEGER
* pcbWritten
)
726 static HRESULT WINAPI
ITSS_IStream_Commit(
728 DWORD grfCommitFlags
)
734 static HRESULT WINAPI
ITSS_IStream_Revert(
741 static HRESULT WINAPI
ITSS_IStream_LockRegion(
743 ULARGE_INTEGER libOffset
,
751 static HRESULT WINAPI
ITSS_IStream_UnlockRegion(
753 ULARGE_INTEGER libOffset
,
761 static HRESULT WINAPI
ITSS_IStream_Stat(
766 IStream_Impl
*This
= (IStream_Impl
*)iface
;
768 TRACE("%p %p %ld\n", This
, pstatstg
, grfStatFlag
);
770 memset( pstatstg
, 0, sizeof *pstatstg
);
771 if( !( grfStatFlag
& STATFLAG_NONAME
) )
773 FIXME("copy the name\n");
775 pstatstg
->type
= STGTY_STREAM
;
776 pstatstg
->cbSize
.QuadPart
= This
->ui
.length
;
777 pstatstg
->grfMode
= STGM_READ
;
778 memcpy( &pstatstg
->clsid
, &CLSID_ITStorage
, sizeof (CLSID
) );
783 static HRESULT WINAPI
ITSS_IStream_Clone(
791 struct IStreamVtbl ITSS_IStream_vtbl
=
793 ITSS_IStream_QueryInterface
,
795 ITSS_IStream_Release
,
799 ITSS_IStream_SetSize
,
803 ITSS_IStream_LockRegion
,
804 ITSS_IStream_UnlockRegion
,
809 static IStream_Impl
*ITSS_create_stream(
810 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
)
814 stm
= HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl
) );
815 stm
->vtbl_IStream
= &ITSS_IStream_vtbl
;
818 memcpy( &stm
->ui
, ui
, sizeof stm
->ui
);
820 IStorage_AddRef( (IStorage
*) stg
);
822 TRACE(" -> %p\n", stm
);