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++) {
357 TRACE("Resolving %s\n", debugstr_w(path));
359 r = chm_resolve_object(This->chmfile, path, &ui);
360 HeapFree( GetProcessHeap(), 0, path );
362 if( r != CHM_RESOLVE_SUCCESS ) {
363 WARN("Could not resolve object\n");
364 return STG_E_FILENOTFOUND;
367 stm = ITSS_create_stream( This, &ui );
371 *ppstm = (IStream*) stm;
376 static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
388 static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
391 IStorage* pstgPriority,
397 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
399 FIXME("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName),
400 pstgPriority, grfMode, snbExclude, reserved, ppstg);
404 static HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
407 const IID* rgiidExclude,
415 static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
419 LPCOLESTR pwcsNewName,
426 static HRESULT WINAPI ITSS_IStorageImpl_Commit(
428 DWORD grfCommitFlags)
434 static HRESULT WINAPI ITSS_IStorageImpl_Revert(
441 static int ITSS_chm_enumerator(
443 struct chmUnitInfo *ui,
446 struct enum_info *info;
447 IEnumSTATSTG_Impl* stgenum = context;
449 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) );
451 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) );
452 memcpy( &info->ui, ui, sizeof info->ui );
455 info->prev = stgenum->last;
457 stgenum->last->next = info;
459 stgenum->first = info;
460 stgenum->last = info;
462 return CHM_ENUMERATOR_CONTINUE;
465 static HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
470 IEnumSTATSTG** ppenum)
472 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
473 IEnumSTATSTG_Impl* stgenum;
475 TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum );
477 stgenum = ITSS_create_enum();
481 chm_enumerate_dir(This->chmfile,
487 stgenum->current = stgenum->first;
489 *ppenum = (IEnumSTATSTG*) stgenum;
494 static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
502 static HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
504 LPCOLESTR pwcsOldName,
505 LPCOLESTR pwcsNewName)
511 static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
514 const FILETIME* pctime,
515 const FILETIME* patime,
516 const FILETIME* pmtime)
522 static HRESULT WINAPI ITSS_IStorageImpl_SetClass(
530 static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
539 static HRESULT WINAPI ITSS_IStorageImpl_Stat(
548 static const IStorageVtbl ITSS_IStorageImpl_Vtbl =
550 ITSS_IStorageImpl_QueryInterface,
551 ITSS_IStorageImpl_AddRef,
552 ITSS_IStorageImpl_Release,
553 ITSS_IStorageImpl_CreateStream,
554 ITSS_IStorageImpl_OpenStream,
555 ITSS_IStorageImpl_CreateStorage,
556 ITSS_IStorageImpl_OpenStorage,
557 ITSS_IStorageImpl_CopyTo,
558 ITSS_IStorageImpl_MoveElementTo,
559 ITSS_IStorageImpl_Commit,
560 ITSS_IStorageImpl_Revert,
561 ITSS_IStorageImpl_EnumElements,
562 ITSS_IStorageImpl_DestroyElement,
563 ITSS_IStorageImpl_RenameElement,
564 ITSS_IStorageImpl_SetElementTimes,
565 ITSS_IStorageImpl_SetClass,
566 ITSS_IStorageImpl_SetStateBits,
567 ITSS_IStorageImpl_Stat,
570 static HRESULT ITSS_create_chm_storage(
571 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen )
573 ITSS_IStorageImpl *stg;
576 TRACE("%p %s\n", chmfile, debugstr_w( dir ) );
578 len = strlenW( dir ) + 1;
579 stg = HeapAlloc( GetProcessHeap(), 0,
580 sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) );
581 stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl;
583 stg->chmfile = chmfile;
584 strcpyW( stg->dir, dir );
586 *ppstgOpen = (IStorage*) stg;
592 HRESULT ITSS_StgOpenStorage(
593 const WCHAR* pwcsName,
594 IStorage* pstgPriority,
598 IStorage** ppstgOpen)
600 struct chmFile *chmfile;
601 static const WCHAR szRoot[] = { '/', 0 };
603 TRACE("%s\n", debugstr_w(pwcsName) );
605 chmfile = chm_openW( pwcsName );
609 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
612 /************************************************************************/
614 static HRESULT WINAPI ITSS_IStream_QueryInterface(
619 IStream_Impl *This = (IStream_Impl *)iface;
621 if (IsEqualGUID(riid, &IID_IUnknown)
622 || IsEqualGUID(riid, &IID_ISequentialStream)
623 || IsEqualGUID(riid, &IID_IStream))
625 IStream_AddRef(iface);
630 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
631 return E_NOINTERFACE;
634 static ULONG WINAPI ITSS_IStream_AddRef(
637 IStream_Impl *This = (IStream_Impl *)iface;
638 return InterlockedIncrement(&This->ref);
641 static ULONG WINAPI ITSS_IStream_Release(
644 IStream_Impl *This = (IStream_Impl *)iface;
646 ULONG ref = InterlockedDecrement(&This->ref);
650 IStorage_Release( (IStorage*) This->stg );
651 HeapFree(GetProcessHeap(), 0, This);
658 static HRESULT WINAPI ITSS_IStream_Read(
664 IStream_Impl *This = (IStream_Impl *)iface;
667 TRACE("%p %p %u %p\n", This, pv, cb, pcbRead);
669 count = chm_retrieve_object(This->stg->chmfile,
670 &This->ui, pv, This->addr, cb);
675 return count ? S_OK : S_FALSE;
678 static HRESULT WINAPI ITSS_IStream_Write(
688 static HRESULT WINAPI ITSS_IStream_Seek(
690 LARGE_INTEGER dlibMove,
692 ULARGE_INTEGER* plibNewPosition)
694 IStream_Impl *This = (IStream_Impl *)iface;
697 TRACE("%p %s %u %p\n", This,
698 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
703 case STREAM_SEEK_CUR:
704 newpos = This->addr + dlibMove.QuadPart;
706 case STREAM_SEEK_SET:
707 newpos = dlibMove.QuadPart;
709 case STREAM_SEEK_END:
710 newpos = This->ui.length + dlibMove.QuadPart;
714 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
715 return STG_E_INVALIDPOINTER;
718 if( plibNewPosition )
719 plibNewPosition->QuadPart = This->addr;
724 static HRESULT WINAPI ITSS_IStream_SetSize(
726 ULARGE_INTEGER libNewSize)
732 static HRESULT WINAPI ITSS_IStream_CopyTo(
736 ULARGE_INTEGER* pcbRead,
737 ULARGE_INTEGER* pcbWritten)
743 static HRESULT WINAPI ITSS_IStream_Commit(
745 DWORD grfCommitFlags)
751 static HRESULT WINAPI ITSS_IStream_Revert(
758 static HRESULT WINAPI ITSS_IStream_LockRegion(
760 ULARGE_INTEGER libOffset,
768 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
770 ULARGE_INTEGER libOffset,
778 static HRESULT WINAPI ITSS_IStream_Stat(
783 IStream_Impl *This = (IStream_Impl *)iface;
785 TRACE("%p %p %d\n", This, pstatstg, grfStatFlag);
787 memset( pstatstg, 0, sizeof *pstatstg );
788 if( !( grfStatFlag & STATFLAG_NONAME ) )
790 FIXME("copy the name\n");
792 pstatstg->type = STGTY_STREAM;
793 pstatstg->cbSize.QuadPart = This->ui.length;
794 pstatstg->grfMode = STGM_READ;
795 memcpy( &pstatstg->clsid, &CLSID_ITStorage, sizeof (CLSID) );
800 static HRESULT WINAPI ITSS_IStream_Clone(
808 static const IStreamVtbl ITSS_IStream_vtbl =
810 ITSS_IStream_QueryInterface,
812 ITSS_IStream_Release,
816 ITSS_IStream_SetSize,
820 ITSS_IStream_LockRegion,
821 ITSS_IStream_UnlockRegion,
826 static IStream_Impl *ITSS_create_stream(
827 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
831 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
832 stm->vtbl_IStream = &ITSS_IStream_vtbl;
835 memcpy( &stm->ui, ui, sizeof stm->ui );
837 IStorage_AddRef( (IStorage*) stg );
841 TRACE(" -> %p\n", stm );