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 chm_close(This->chmfile);
300 HeapFree(GetProcessHeap(), 0, This);
307 static HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
319 static HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
327 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
330 struct chmUnitInfo ui;
334 TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName),
335 reserved1, grfMode, reserved2, ppstm );
337 len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
338 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
339 strcpyW( path, This->dir );
341 if( pwcsName[0] == '/' || pwcsName[0] == '\\' )
343 p = &path[strlenW( path ) - 1];
344 while( ( path <= p ) && ( *p == '/' ) )
347 strcatW( path, pwcsName );
349 for(p=path; *p; p++) {
354 TRACE("Resolving %s\n", debugstr_w(path));
356 r = chm_resolve_object(This->chmfile, path, &ui);
357 HeapFree( GetProcessHeap(), 0, path );
359 if( r != CHM_RESOLVE_SUCCESS ) {
360 WARN("Could not resolve object\n");
361 return STG_E_FILENOTFOUND;
364 stm = ITSS_create_stream( This, &ui );
368 *ppstm = (IStream*) stm;
373 static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
385 static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
388 IStorage* pstgPriority,
394 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
396 FIXME("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName),
397 pstgPriority, grfMode, snbExclude, reserved, ppstg);
401 static HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
404 const IID* rgiidExclude,
412 static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
416 LPCOLESTR pwcsNewName,
423 static HRESULT WINAPI ITSS_IStorageImpl_Commit(
425 DWORD grfCommitFlags)
431 static HRESULT WINAPI ITSS_IStorageImpl_Revert(
438 static int ITSS_chm_enumerator(
440 struct chmUnitInfo *ui,
443 struct enum_info *info;
444 IEnumSTATSTG_Impl* stgenum = context;
446 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) );
448 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) );
449 memcpy( &info->ui, ui, sizeof info->ui );
452 info->prev = stgenum->last;
454 stgenum->last->next = info;
456 stgenum->first = info;
457 stgenum->last = info;
459 return CHM_ENUMERATOR_CONTINUE;
462 static HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
467 IEnumSTATSTG** ppenum)
469 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
470 IEnumSTATSTG_Impl* stgenum;
472 TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum );
474 stgenum = ITSS_create_enum();
478 chm_enumerate_dir(This->chmfile,
484 stgenum->current = stgenum->first;
486 *ppenum = (IEnumSTATSTG*) stgenum;
491 static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
499 static HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
501 LPCOLESTR pwcsOldName,
502 LPCOLESTR pwcsNewName)
508 static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
511 const FILETIME* pctime,
512 const FILETIME* patime,
513 const FILETIME* pmtime)
519 static HRESULT WINAPI ITSS_IStorageImpl_SetClass(
527 static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
536 static HRESULT WINAPI ITSS_IStorageImpl_Stat(
545 static const IStorageVtbl ITSS_IStorageImpl_Vtbl =
547 ITSS_IStorageImpl_QueryInterface,
548 ITSS_IStorageImpl_AddRef,
549 ITSS_IStorageImpl_Release,
550 ITSS_IStorageImpl_CreateStream,
551 ITSS_IStorageImpl_OpenStream,
552 ITSS_IStorageImpl_CreateStorage,
553 ITSS_IStorageImpl_OpenStorage,
554 ITSS_IStorageImpl_CopyTo,
555 ITSS_IStorageImpl_MoveElementTo,
556 ITSS_IStorageImpl_Commit,
557 ITSS_IStorageImpl_Revert,
558 ITSS_IStorageImpl_EnumElements,
559 ITSS_IStorageImpl_DestroyElement,
560 ITSS_IStorageImpl_RenameElement,
561 ITSS_IStorageImpl_SetElementTimes,
562 ITSS_IStorageImpl_SetClass,
563 ITSS_IStorageImpl_SetStateBits,
564 ITSS_IStorageImpl_Stat,
567 static HRESULT ITSS_create_chm_storage(
568 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen )
570 ITSS_IStorageImpl *stg;
573 TRACE("%p %s\n", chmfile, debugstr_w( dir ) );
575 len = strlenW( dir ) + 1;
576 stg = HeapAlloc( GetProcessHeap(), 0,
577 sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) );
578 stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl;
580 stg->chmfile = chmfile;
581 strcpyW( stg->dir, dir );
583 *ppstgOpen = (IStorage*) stg;
589 HRESULT ITSS_StgOpenStorage(
590 const WCHAR* pwcsName,
591 IStorage* pstgPriority,
595 IStorage** ppstgOpen)
597 struct chmFile *chmfile;
598 static const WCHAR szRoot[] = { '/', 0 };
600 TRACE("%s\n", debugstr_w(pwcsName) );
602 chmfile = chm_openW( pwcsName );
606 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
609 /************************************************************************/
611 static HRESULT WINAPI ITSS_IStream_QueryInterface(
616 IStream_Impl *This = (IStream_Impl *)iface;
618 if (IsEqualGUID(riid, &IID_IUnknown)
619 || IsEqualGUID(riid, &IID_ISequentialStream)
620 || IsEqualGUID(riid, &IID_IStream))
622 IStream_AddRef(iface);
627 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
628 return E_NOINTERFACE;
631 static ULONG WINAPI ITSS_IStream_AddRef(
634 IStream_Impl *This = (IStream_Impl *)iface;
635 return InterlockedIncrement(&This->ref);
638 static ULONG WINAPI ITSS_IStream_Release(
641 IStream_Impl *This = (IStream_Impl *)iface;
643 ULONG ref = InterlockedDecrement(&This->ref);
647 IStorage_Release( (IStorage*) This->stg );
648 HeapFree(GetProcessHeap(), 0, This);
655 static HRESULT WINAPI ITSS_IStream_Read(
661 IStream_Impl *This = (IStream_Impl *)iface;
664 TRACE("%p %p %u %p\n", This, pv, cb, pcbRead);
666 count = chm_retrieve_object(This->stg->chmfile,
667 &This->ui, pv, This->addr, cb);
672 return count ? S_OK : S_FALSE;
675 static HRESULT WINAPI ITSS_IStream_Write(
685 static HRESULT WINAPI ITSS_IStream_Seek(
687 LARGE_INTEGER dlibMove,
689 ULARGE_INTEGER* plibNewPosition)
691 IStream_Impl *This = (IStream_Impl *)iface;
694 TRACE("%p %s %u %p\n", This,
695 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
700 case STREAM_SEEK_CUR:
701 newpos = This->addr + dlibMove.QuadPart;
703 case STREAM_SEEK_SET:
704 newpos = dlibMove.QuadPart;
706 case STREAM_SEEK_END:
707 newpos = This->ui.length + dlibMove.QuadPart;
711 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
712 return STG_E_INVALIDPOINTER;
715 if( plibNewPosition )
716 plibNewPosition->QuadPart = This->addr;
721 static HRESULT WINAPI ITSS_IStream_SetSize(
723 ULARGE_INTEGER libNewSize)
729 static HRESULT WINAPI ITSS_IStream_CopyTo(
733 ULARGE_INTEGER* pcbRead,
734 ULARGE_INTEGER* pcbWritten)
740 static HRESULT WINAPI ITSS_IStream_Commit(
742 DWORD grfCommitFlags)
748 static HRESULT WINAPI ITSS_IStream_Revert(
755 static HRESULT WINAPI ITSS_IStream_LockRegion(
757 ULARGE_INTEGER libOffset,
765 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
767 ULARGE_INTEGER libOffset,
775 static HRESULT WINAPI ITSS_IStream_Stat(
780 IStream_Impl *This = (IStream_Impl *)iface;
782 TRACE("%p %p %d\n", This, pstatstg, grfStatFlag);
784 memset( pstatstg, 0, sizeof *pstatstg );
785 if( !( grfStatFlag & STATFLAG_NONAME ) )
787 FIXME("copy the name\n");
789 pstatstg->type = STGTY_STREAM;
790 pstatstg->cbSize.QuadPart = This->ui.length;
791 pstatstg->grfMode = STGM_READ;
792 memcpy( &pstatstg->clsid, &CLSID_ITStorage, sizeof (CLSID) );
797 static HRESULT WINAPI ITSS_IStream_Clone(
805 static const IStreamVtbl ITSS_IStream_vtbl =
807 ITSS_IStream_QueryInterface,
809 ITSS_IStream_Release,
813 ITSS_IStream_SetSize,
817 ITSS_IStream_LockRegion,
818 ITSS_IStream_UnlockRegion,
823 static IStream_Impl *ITSS_create_stream(
824 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
828 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
829 stm->vtbl_IStream = &ITSS_IStream_vtbl;
832 memcpy( &stm->ui, ui, sizeof stm->ui );
834 IStorage_AddRef( (IStorage*) stg );
838 TRACE(" -> %p\n", stm );