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
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(itss
);
46 /************************************************************************/
48 typedef struct _ITSS_IStorageImpl
50 IStorageVtbl
*vtbl_IStorage
;
52 struct chmFile
*chmfile
;
58 struct enum_info
*next
, *prev
;
59 struct chmUnitInfo ui
;
62 typedef struct _IEnumSTATSTG_Impl
64 IEnumSTATSTGVtbl
*vtbl_IEnumSTATSTG
;
66 struct enum_info
*first
, *last
, *current
;
69 typedef struct _IStream_Impl
71 IStreamVtbl
*vtbl_IStream
;
73 ITSS_IStorageImpl
*stg
;
75 struct chmUnitInfo ui
;
78 static HRESULT
ITSS_create_chm_storage(
79 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
);
80 static IStream_Impl
* ITSS_create_stream(
81 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
);
83 /************************************************************************/
85 static HRESULT WINAPI
ITSS_IEnumSTATSTG_QueryInterface(
90 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
92 if (IsEqualGUID(riid
, &IID_IUnknown
)
93 || IsEqualGUID(riid
, &IID_IEnumSTATSTG
))
95 IEnumSTATSTG_AddRef(iface
);
100 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
101 return E_NOINTERFACE
;
104 static ULONG WINAPI
ITSS_IEnumSTATSTG_AddRef(
107 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
108 return ++(This
->ref
);
111 static ULONG WINAPI
ITSS_IEnumSTATSTG_Release(
114 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
116 ULONG ref
= --This
->ref
;
122 struct enum_info
*t
= This
->first
->next
;
123 HeapFree( GetProcessHeap(), 0, This
->first
);
126 HeapFree(GetProcessHeap(), 0, This
);
132 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Next(
138 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
140 struct enum_info
*cur
;
142 TRACE("%p %lu %p %p\n", This
, celt
, rgelt
, pceltFetched
);
146 while( (n
<celt
) && cur
)
150 memset( rgelt
, 0, sizeof *rgelt
);
156 len
= strlenW( str
) + 1;
157 rgelt
->pwcsName
= CoTaskMemAlloc( len
*sizeof(WCHAR
) );
158 strcpyW( rgelt
->pwcsName
, str
);
160 /* determine the type */
161 if( rgelt
->pwcsName
[len
-2] == '/' )
163 rgelt
->pwcsName
[len
-2] = 0;
164 rgelt
->type
= STGTY_STORAGE
;
167 rgelt
->type
= STGTY_STREAM
;
170 rgelt
->cbSize
.QuadPart
= cur
->ui
.length
;
172 /* advance to the next item if it exists */
186 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Skip(
190 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
192 struct enum_info
*cur
;
194 TRACE("%p %lu\n", This
, celt
);
198 while( (n
<celt
) && cur
)
211 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Reset(
214 IEnumSTATSTG_Impl
*This
= (IEnumSTATSTG_Impl
*)iface
;
216 TRACE("%p\n", This
);
218 This
->current
= This
->first
;
223 static HRESULT WINAPI
ITSS_IEnumSTATSTG_Clone(
225 IEnumSTATSTG
** ppenum
)
231 struct IEnumSTATSTGVtbl IEnumSTATSTG_vtbl
=
233 ITSS_IEnumSTATSTG_QueryInterface
,
234 ITSS_IEnumSTATSTG_AddRef
,
235 ITSS_IEnumSTATSTG_Release
,
236 ITSS_IEnumSTATSTG_Next
,
237 ITSS_IEnumSTATSTG_Skip
,
238 ITSS_IEnumSTATSTG_Reset
,
239 ITSS_IEnumSTATSTG_Clone
242 static IEnumSTATSTG_Impl
*ITSS_create_enum( void )
244 IEnumSTATSTG_Impl
*stgenum
;
246 stgenum
= HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl
) );
247 stgenum
->vtbl_IEnumSTATSTG
= &IEnumSTATSTG_vtbl
;
249 stgenum
->first
= NULL
;
250 stgenum
->last
= NULL
;
251 stgenum
->current
= NULL
;
253 TRACE(" -> %p\n", stgenum
);
258 /************************************************************************/
260 HRESULT WINAPI
ITSS_IStorageImpl_QueryInterface(
265 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
267 if (IsEqualGUID(riid
, &IID_IUnknown
)
268 || IsEqualGUID(riid
, &IID_IStorage
))
270 IStorage_AddRef(iface
);
275 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
276 return E_NOINTERFACE
;
279 ULONG WINAPI
ITSS_IStorageImpl_AddRef(
282 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
283 return ++(This
->ref
);
286 ULONG WINAPI
ITSS_IStorageImpl_Release(
289 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
291 ULONG ref
= --This
->ref
;
295 HeapFree(GetProcessHeap(), 0, This
);
301 HRESULT WINAPI
ITSS_IStorageImpl_CreateStream(
313 HRESULT WINAPI
ITSS_IStorageImpl_OpenStream(
321 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
324 struct chmUnitInfo ui
;
328 TRACE("%p %s %p %lu %lu %p\n", This
, debugstr_w(pwcsName
),
329 reserved1
, grfMode
, reserved2
, ppstm
);
331 len
= strlenW( This
->dir
) + strlenW( pwcsName
) + 1;
332 path
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
333 strcpyW( path
, This
->dir
);
334 if( pwcsName
[0] == '/' )
336 WCHAR
*p
= &path
[strlenW( path
) - 1];
337 while( ( path
<= p
) && ( *p
= '/' ) )
340 strcatW( path
, pwcsName
);
342 TRACE("Resolving %s\n", debugstr_w(path
));
344 r
= chm_resolve_object(This
->chmfile
, path
, &ui
);
345 HeapFree( GetProcessHeap(), 0, path
);
347 if( r
!= CHM_RESOLVE_SUCCESS
)
348 return STG_E_FILENOTFOUND
;
350 stm
= ITSS_create_stream( This
, &ui
);
354 *ppstm
= (IStream
*) stm
;
359 HRESULT WINAPI
ITSS_IStorageImpl_CreateStorage(
371 HRESULT WINAPI
ITSS_IStorageImpl_OpenStorage(
374 IStorage
* pstgPriority
,
380 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
382 FIXME("%p %s %p %lu %p %lu %p\n", This
, debugstr_w(pwcsName
),
383 pstgPriority
, grfMode
, snbExclude
, reserved
, ppstg
);
387 HRESULT WINAPI
ITSS_IStorageImpl_CopyTo(
390 const IID
* rgiidExclude
,
398 HRESULT WINAPI
ITSS_IStorageImpl_MoveElementTo(
402 LPCOLESTR pwcsNewName
,
409 HRESULT WINAPI
ITSS_IStorageImpl_Commit(
411 DWORD grfCommitFlags
)
417 HRESULT WINAPI
ITSS_IStorageImpl_Revert(
424 static int ITSS_chm_enumerator(
426 struct chmUnitInfo
*ui
,
429 struct enum_info
*info
;
430 IEnumSTATSTG_Impl
* stgenum
= context
;
432 TRACE("adding %s to enumeration\n", debugstr_w(ui
->path
) );
434 info
= HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info
) );
435 memcpy( &info
->ui
, ui
, sizeof info
->ui
);
438 info
->prev
= stgenum
->last
;
440 stgenum
->last
->next
= info
;
442 stgenum
->first
= info
;
443 stgenum
->last
= info
;
445 return CHM_ENUMERATOR_CONTINUE
;
448 HRESULT WINAPI
ITSS_IStorageImpl_EnumElements(
453 IEnumSTATSTG
** ppenum
)
455 ITSS_IStorageImpl
*This
= (ITSS_IStorageImpl
*)iface
;
456 IEnumSTATSTG_Impl
* stgenum
;
458 TRACE("%p %ld %p %ld %p\n", This
, reserved1
, reserved2
, reserved3
, ppenum
);
460 stgenum
= ITSS_create_enum();
464 chm_enumerate_dir(This
->chmfile
,
470 stgenum
->current
= stgenum
->first
;
472 *ppenum
= (IEnumSTATSTG
*) stgenum
;
477 HRESULT WINAPI
ITSS_IStorageImpl_DestroyElement(
485 HRESULT WINAPI
ITSS_IStorageImpl_RenameElement(
487 LPCOLESTR pwcsOldName
,
488 LPCOLESTR pwcsNewName
)
494 HRESULT WINAPI
ITSS_IStorageImpl_SetElementTimes(
497 const FILETIME
* pctime
,
498 const FILETIME
* patime
,
499 const FILETIME
* pmtime
)
505 HRESULT WINAPI
ITSS_IStorageImpl_SetClass(
513 HRESULT WINAPI
ITSS_IStorageImpl_SetStateBits(
522 HRESULT WINAPI
ITSS_IStorageImpl_Stat(
531 static IStorageVtbl ITSS_IStorageImpl_Vtbl
=
533 ITSS_IStorageImpl_QueryInterface
,
534 ITSS_IStorageImpl_AddRef
,
535 ITSS_IStorageImpl_Release
,
536 ITSS_IStorageImpl_CreateStream
,
537 ITSS_IStorageImpl_OpenStream
,
538 ITSS_IStorageImpl_CreateStorage
,
539 ITSS_IStorageImpl_OpenStorage
,
540 ITSS_IStorageImpl_CopyTo
,
541 ITSS_IStorageImpl_MoveElementTo
,
542 ITSS_IStorageImpl_Commit
,
543 ITSS_IStorageImpl_Revert
,
544 ITSS_IStorageImpl_EnumElements
,
545 ITSS_IStorageImpl_DestroyElement
,
546 ITSS_IStorageImpl_RenameElement
,
547 ITSS_IStorageImpl_SetElementTimes
,
548 ITSS_IStorageImpl_SetClass
,
549 ITSS_IStorageImpl_SetStateBits
,
550 ITSS_IStorageImpl_Stat
,
553 static HRESULT
ITSS_create_chm_storage(
554 struct chmFile
*chmfile
, const WCHAR
*dir
, IStorage
** ppstgOpen
)
556 ITSS_IStorageImpl
*stg
;
559 TRACE("%p %s\n", chmfile
, debugstr_w( dir
) );
561 len
= strlenW( dir
) + 1;
562 stg
= HeapAlloc( GetProcessHeap(), 0,
563 sizeof (ITSS_IStorageImpl
) + len
*sizeof(WCHAR
) );
564 stg
->vtbl_IStorage
= &ITSS_IStorageImpl_Vtbl
;
566 stg
->chmfile
= chmfile
;
567 strcpyW( stg
->dir
, dir
);
569 *ppstgOpen
= (IStorage
*) stg
;
574 HRESULT
ITSS_StgOpenStorage(
575 const WCHAR
* pwcsName
,
576 IStorage
* pstgPriority
,
580 IStorage
** ppstgOpen
)
582 struct chmFile
*chmfile
;
583 static const WCHAR szRoot
[] = { '/', 0 };
585 TRACE("%s\n", debugstr_w(pwcsName
) );
587 chmfile
= chm_openW( pwcsName
);
591 return ITSS_create_chm_storage( chmfile
, szRoot
, ppstgOpen
);
594 /************************************************************************/
596 static HRESULT WINAPI
ITSS_IStream_QueryInterface(
601 IStream_Impl
*This
= (IStream_Impl
*)iface
;
603 if (IsEqualGUID(riid
, &IID_IUnknown
)
604 || IsEqualGUID(riid
, &IID_ISequentialStream
)
605 || IsEqualGUID(riid
, &IID_IStream
))
607 IStream_AddRef(iface
);
612 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppvObject
);
613 return E_NOINTERFACE
;
616 static ULONG WINAPI
ITSS_IStream_AddRef(
619 IStream_Impl
*This
= (IStream_Impl
*)iface
;
620 return ++(This
->ref
);
623 static ULONG WINAPI
ITSS_IStream_Release(
626 IStream_Impl
*This
= (IStream_Impl
*)iface
;
628 ULONG ref
= --This
->ref
;
632 IStorage_Release( (IStorage
*) This
->stg
);
633 HeapFree(GetProcessHeap(), 0, This
);
639 static HRESULT WINAPI
ITSS_IStream_Read(
645 IStream_Impl
*This
= (IStream_Impl
*)iface
;
648 TRACE("%p %p %lu %p\n", This
, pv
, cb
, pcbRead
);
650 count
= chm_retrieve_object(This
->stg
->chmfile
,
651 &This
->ui
, pv
, This
->addr
, cb
);
659 static HRESULT WINAPI
ITSS_IStream_Write(
669 static HRESULT WINAPI
ITSS_IStream_Seek(
671 LARGE_INTEGER dlibMove
,
673 ULARGE_INTEGER
* plibNewPosition
)
675 IStream_Impl
*This
= (IStream_Impl
*)iface
;
678 TRACE("%p %s %lu %p\n", This
,
679 wine_dbgstr_longlong( dlibMove
.QuadPart
), dwOrigin
, plibNewPosition
);
684 case STREAM_SEEK_CUR
:
685 newpos
= This
->addr
+ dlibMove
.QuadPart
;
687 case STREAM_SEEK_SET
:
688 newpos
= dlibMove
.QuadPart
;
690 case STREAM_SEEK_END
:
691 newpos
= This
->ui
.length
+ dlibMove
.QuadPart
;
695 if( ( newpos
< 0 ) || ( newpos
> This
->ui
.length
) )
696 return STG_E_INVALIDPOINTER
;
699 if( plibNewPosition
)
700 plibNewPosition
->QuadPart
= This
->addr
;
705 static HRESULT WINAPI
ITSS_IStream_SetSize(
707 ULARGE_INTEGER libNewSize
)
713 static HRESULT WINAPI
ITSS_IStream_CopyTo(
717 ULARGE_INTEGER
* pcbRead
,
718 ULARGE_INTEGER
* pcbWritten
)
724 static HRESULT WINAPI
ITSS_IStream_Commit(
726 DWORD grfCommitFlags
)
732 static HRESULT WINAPI
ITSS_IStream_Revert(
739 static HRESULT WINAPI
ITSS_IStream_LockRegion(
741 ULARGE_INTEGER libOffset
,
749 static HRESULT WINAPI
ITSS_IStream_UnlockRegion(
751 ULARGE_INTEGER libOffset
,
759 static HRESULT WINAPI
ITSS_IStream_Stat(
764 IStream_Impl
*This
= (IStream_Impl
*)iface
;
766 TRACE("%p %p %ld\n", This
, pstatstg
, grfStatFlag
);
768 memset( pstatstg
, 0, sizeof *pstatstg
);
769 if( !( grfStatFlag
& STATFLAG_NONAME
) )
771 FIXME("copy the name\n");
773 pstatstg
->type
= STGTY_STREAM
;
774 pstatstg
->cbSize
.QuadPart
= This
->ui
.length
;
775 pstatstg
->grfMode
= STGM_READ
;
776 memcpy( &pstatstg
->clsid
, &CLSID_ITStorage
, sizeof (CLSID
) );
781 static HRESULT WINAPI
ITSS_IStream_Clone(
789 struct IStreamVtbl ITSS_IStream_vtbl
=
791 ITSS_IStream_QueryInterface
,
793 ITSS_IStream_Release
,
797 ITSS_IStream_SetSize
,
801 ITSS_IStream_LockRegion
,
802 ITSS_IStream_UnlockRegion
,
807 static IStream_Impl
*ITSS_create_stream(
808 ITSS_IStorageImpl
*stg
, struct chmUnitInfo
*ui
)
812 stm
= HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl
) );
813 stm
->vtbl_IStream
= &ITSS_IStream_vtbl
;
816 memcpy( &stm
->ui
, ui
, sizeof stm
->ui
);
818 IStorage_AddRef( (IStorage
*) stg
);
820 TRACE(" -> %p\n", stm
);