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 /************************************************************************/
50 typedef struct _ITSS_IStorageImpl
52 const IStorageVtbl *vtbl_IStorage;
54 struct chmFile *chmfile;
60 struct enum_info *next, *prev;
61 struct chmUnitInfo ui;
64 typedef struct _IEnumSTATSTG_Impl
66 const IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG;
68 struct enum_info *first, *last, *current;
71 typedef struct _IStream_Impl
73 const 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 InterlockedIncrement(&This->ref);
113 static ULONG WINAPI ITSS_IEnumSTATSTG_Release(
116 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
118 ULONG ref = InterlockedDecrement(&This->ref);
124 struct enum_info *t = This->first->next;
125 HeapFree( GetProcessHeap(), 0, This->first );
128 HeapFree(GetProcessHeap(), 0, This);
135 static HRESULT WINAPI ITSS_IEnumSTATSTG_Next(
141 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
143 struct enum_info *cur;
145 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched );
149 while( (n<celt) && cur)
153 memset( rgelt, 0, sizeof *rgelt );
159 len = strlenW( str ) + 1;
160 rgelt->pwcsName = CoTaskMemAlloc( len*sizeof(WCHAR) );
161 strcpyW( rgelt->pwcsName, str );
163 /* determine the type */
164 if( rgelt->pwcsName[len-2] == '/' )
166 rgelt->pwcsName[len-2] = 0;
167 rgelt->type = STGTY_STORAGE;
170 rgelt->type = STGTY_STREAM;
173 rgelt->cbSize.QuadPart = cur->ui.length;
175 /* advance to the next item if it exists */
189 static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip(
193 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
195 struct enum_info *cur;
197 TRACE("%p %u\n", This, celt );
201 while( (n<celt) && cur)
214 static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset(
217 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
219 TRACE("%p\n", This );
221 This->current = This->first;
226 static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone(
228 IEnumSTATSTG** ppenum)
234 static const IEnumSTATSTGVtbl IEnumSTATSTG_vtbl =
236 ITSS_IEnumSTATSTG_QueryInterface,
237 ITSS_IEnumSTATSTG_AddRef,
238 ITSS_IEnumSTATSTG_Release,
239 ITSS_IEnumSTATSTG_Next,
240 ITSS_IEnumSTATSTG_Skip,
241 ITSS_IEnumSTATSTG_Reset,
242 ITSS_IEnumSTATSTG_Clone
245 static IEnumSTATSTG_Impl *ITSS_create_enum( void )
247 IEnumSTATSTG_Impl *stgenum;
249 stgenum = HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl) );
250 stgenum->vtbl_IEnumSTATSTG = &IEnumSTATSTG_vtbl;
252 stgenum->first = NULL;
253 stgenum->last = NULL;
254 stgenum->current = NULL;
257 TRACE(" -> %p\n", stgenum );
262 /************************************************************************/
264 static HRESULT WINAPI ITSS_IStorageImpl_QueryInterface(
269 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
271 if (IsEqualGUID(riid, &IID_IUnknown)
272 || IsEqualGUID(riid, &IID_IStorage))
274 IStorage_AddRef(iface);
279 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
280 return E_NOINTERFACE;
283 static ULONG WINAPI ITSS_IStorageImpl_AddRef(
286 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
287 return InterlockedIncrement(&This->ref);
290 static ULONG WINAPI ITSS_IStorageImpl_Release(
293 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
295 ULONG ref = InterlockedDecrement(&This->ref);
299 HeapFree(GetProcessHeap(), 0, This);
306 static HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
318 static HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
326 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
329 struct chmUnitInfo ui;
333 TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName),
334 reserved1, grfMode, reserved2, ppstm );
336 len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
337 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
338 strcpyW( path, This->dir );
339 if( pwcsName[0] == '/' )
341 WCHAR *p = &path[strlenW( path ) - 1];
342 while( ( path <= p ) && ( *p == '/' ) )
345 strcatW( path, pwcsName );
347 TRACE("Resolving %s\n", debugstr_w(path));
349 r = chm_resolve_object(This->chmfile, path, &ui);
350 HeapFree( GetProcessHeap(), 0, path );
352 if( r != CHM_RESOLVE_SUCCESS )
353 return STG_E_FILENOTFOUND;
355 stm = ITSS_create_stream( This, &ui );
359 *ppstm = (IStream*) stm;
364 static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
376 static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
379 IStorage* pstgPriority,
385 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
387 FIXME("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName),
388 pstgPriority, grfMode, snbExclude, reserved, ppstg);
392 static HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
395 const IID* rgiidExclude,
403 static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
407 LPCOLESTR pwcsNewName,
414 static HRESULT WINAPI ITSS_IStorageImpl_Commit(
416 DWORD grfCommitFlags)
422 static HRESULT WINAPI ITSS_IStorageImpl_Revert(
429 static int ITSS_chm_enumerator(
431 struct chmUnitInfo *ui,
434 struct enum_info *info;
435 IEnumSTATSTG_Impl* stgenum = context;
437 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) );
439 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) );
440 memcpy( &info->ui, ui, sizeof info->ui );
443 info->prev = stgenum->last;
445 stgenum->last->next = info;
447 stgenum->first = info;
448 stgenum->last = info;
450 return CHM_ENUMERATOR_CONTINUE;
453 static HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
458 IEnumSTATSTG** ppenum)
460 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
461 IEnumSTATSTG_Impl* stgenum;
463 TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum );
465 stgenum = ITSS_create_enum();
469 chm_enumerate_dir(This->chmfile,
475 stgenum->current = stgenum->first;
477 *ppenum = (IEnumSTATSTG*) stgenum;
482 static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
490 static HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
492 LPCOLESTR pwcsOldName,
493 LPCOLESTR pwcsNewName)
499 static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
502 const FILETIME* pctime,
503 const FILETIME* patime,
504 const FILETIME* pmtime)
510 static HRESULT WINAPI ITSS_IStorageImpl_SetClass(
518 static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
527 static HRESULT WINAPI ITSS_IStorageImpl_Stat(
536 static const IStorageVtbl ITSS_IStorageImpl_Vtbl =
538 ITSS_IStorageImpl_QueryInterface,
539 ITSS_IStorageImpl_AddRef,
540 ITSS_IStorageImpl_Release,
541 ITSS_IStorageImpl_CreateStream,
542 ITSS_IStorageImpl_OpenStream,
543 ITSS_IStorageImpl_CreateStorage,
544 ITSS_IStorageImpl_OpenStorage,
545 ITSS_IStorageImpl_CopyTo,
546 ITSS_IStorageImpl_MoveElementTo,
547 ITSS_IStorageImpl_Commit,
548 ITSS_IStorageImpl_Revert,
549 ITSS_IStorageImpl_EnumElements,
550 ITSS_IStorageImpl_DestroyElement,
551 ITSS_IStorageImpl_RenameElement,
552 ITSS_IStorageImpl_SetElementTimes,
553 ITSS_IStorageImpl_SetClass,
554 ITSS_IStorageImpl_SetStateBits,
555 ITSS_IStorageImpl_Stat,
558 static HRESULT ITSS_create_chm_storage(
559 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen )
561 ITSS_IStorageImpl *stg;
564 TRACE("%p %s\n", chmfile, debugstr_w( dir ) );
566 len = strlenW( dir ) + 1;
567 stg = HeapAlloc( GetProcessHeap(), 0,
568 sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) );
569 stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl;
571 stg->chmfile = chmfile;
572 strcpyW( stg->dir, dir );
574 *ppstgOpen = (IStorage*) stg;
580 HRESULT ITSS_StgOpenStorage(
581 const WCHAR* pwcsName,
582 IStorage* pstgPriority,
586 IStorage** ppstgOpen)
588 struct chmFile *chmfile;
589 static const WCHAR szRoot[] = { '/', 0 };
591 TRACE("%s\n", debugstr_w(pwcsName) );
593 chmfile = chm_openW( pwcsName );
597 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
600 /************************************************************************/
602 static HRESULT WINAPI ITSS_IStream_QueryInterface(
607 IStream_Impl *This = (IStream_Impl *)iface;
609 if (IsEqualGUID(riid, &IID_IUnknown)
610 || IsEqualGUID(riid, &IID_ISequentialStream)
611 || IsEqualGUID(riid, &IID_IStream))
613 IStream_AddRef(iface);
618 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
619 return E_NOINTERFACE;
622 static ULONG WINAPI ITSS_IStream_AddRef(
625 IStream_Impl *This = (IStream_Impl *)iface;
626 return InterlockedIncrement(&This->ref);
629 static ULONG WINAPI ITSS_IStream_Release(
632 IStream_Impl *This = (IStream_Impl *)iface;
634 ULONG ref = InterlockedDecrement(&This->ref);
638 IStorage_Release( (IStorage*) This->stg );
639 HeapFree(GetProcessHeap(), 0, This);
646 static HRESULT WINAPI ITSS_IStream_Read(
652 IStream_Impl *This = (IStream_Impl *)iface;
655 TRACE("%p %p %u %p\n", This, pv, cb, pcbRead);
657 count = chm_retrieve_object(This->stg->chmfile,
658 &This->ui, pv, This->addr, cb);
666 static HRESULT WINAPI ITSS_IStream_Write(
676 static HRESULT WINAPI ITSS_IStream_Seek(
678 LARGE_INTEGER dlibMove,
680 ULARGE_INTEGER* plibNewPosition)
682 IStream_Impl *This = (IStream_Impl *)iface;
685 TRACE("%p %s %u %p\n", This,
686 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
691 case STREAM_SEEK_CUR:
692 newpos = This->addr + dlibMove.QuadPart;
694 case STREAM_SEEK_SET:
695 newpos = dlibMove.QuadPart;
697 case STREAM_SEEK_END:
698 newpos = This->ui.length + dlibMove.QuadPart;
702 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
703 return STG_E_INVALIDPOINTER;
706 if( plibNewPosition )
707 plibNewPosition->QuadPart = This->addr;
712 static HRESULT WINAPI ITSS_IStream_SetSize(
714 ULARGE_INTEGER libNewSize)
720 static HRESULT WINAPI ITSS_IStream_CopyTo(
724 ULARGE_INTEGER* pcbRead,
725 ULARGE_INTEGER* pcbWritten)
731 static HRESULT WINAPI ITSS_IStream_Commit(
733 DWORD grfCommitFlags)
739 static HRESULT WINAPI ITSS_IStream_Revert(
746 static HRESULT WINAPI ITSS_IStream_LockRegion(
748 ULARGE_INTEGER libOffset,
756 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
758 ULARGE_INTEGER libOffset,
766 static HRESULT WINAPI ITSS_IStream_Stat(
771 IStream_Impl *This = (IStream_Impl *)iface;
773 TRACE("%p %p %d\n", This, pstatstg, grfStatFlag);
775 memset( pstatstg, 0, sizeof *pstatstg );
776 if( !( grfStatFlag & STATFLAG_NONAME ) )
778 FIXME("copy the name\n");
780 pstatstg->type = STGTY_STREAM;
781 pstatstg->cbSize.QuadPart = This->ui.length;
782 pstatstg->grfMode = STGM_READ;
783 memcpy( &pstatstg->clsid, &CLSID_ITStorage, sizeof (CLSID) );
788 static HRESULT WINAPI ITSS_IStream_Clone(
796 static const IStreamVtbl ITSS_IStream_vtbl =
798 ITSS_IStream_QueryInterface,
800 ITSS_IStream_Release,
804 ITSS_IStream_SetSize,
808 ITSS_IStream_LockRegion,
809 ITSS_IStream_UnlockRegion,
814 static IStream_Impl *ITSS_create_stream(
815 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
819 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
820 stm->vtbl_IStream = &ITSS_IStream_vtbl;
823 memcpy( &stm->ui, ui, sizeof stm->ui );
825 IStorage_AddRef( (IStorage*) stg );
829 TRACE(" -> %p\n", stm );