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 extern ULONG dll_count;
50 /************************************************************************/
52 typedef struct _ITSS_IStorageImpl
54 IStorageVtbl *vtbl_IStorage;
56 struct chmFile *chmfile;
62 struct enum_info *next, *prev;
63 struct chmUnitInfo ui;
66 typedef struct _IEnumSTATSTG_Impl
68 IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG;
70 struct enum_info *first, *last, *current;
73 typedef struct _IStream_Impl
75 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 struct 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 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 ULONG WINAPI ITSS_IStorageImpl_AddRef(
288 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
289 return InterlockedIncrement(&This->ref);
292 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 HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
320 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 HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
378 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 HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
397 const IID* rgiidExclude,
405 HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
409 LPCOLESTR pwcsNewName,
416 HRESULT WINAPI ITSS_IStorageImpl_Commit(
418 DWORD grfCommitFlags)
424 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 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 HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
492 HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
494 LPCOLESTR pwcsOldName,
495 LPCOLESTR pwcsNewName)
501 HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
504 const FILETIME* pctime,
505 const FILETIME* patime,
506 const FILETIME* pmtime)
512 HRESULT WINAPI ITSS_IStorageImpl_SetClass(
520 HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
529 HRESULT WINAPI ITSS_IStorageImpl_Stat(
538 static 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 struct 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 );