Removed some uses of the non-standard ICOM_THIS macro.
[wine/multimedia.git] / dlls / itss / storage.c
blob3c7e706182a3725397bdf1de3847390d8eb7b94b
1 /*
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
23 #include "config.h"
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
32 #include "winreg.h"
33 #include "ole2.h"
35 #include "uuids.h"
37 #include "itss.h"
38 #include "chm_lib.h"
39 #include "itsstor.h"
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;
51 DWORD ref;
52 struct chmFile *chmfile;
53 WCHAR dir[1];
54 } ITSS_IStorageImpl;
56 struct enum_info
58 struct enum_info *next, *prev;
59 struct chmUnitInfo ui;
62 typedef struct _IEnumSTATSTG_Impl
64 IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG;
65 DWORD ref;
66 struct enum_info *first, *last, *current;
67 } IEnumSTATSTG_Impl;
69 typedef struct _IStream_Impl
71 IStreamVtbl *vtbl_IStream;
72 DWORD ref;
73 ITSS_IStorageImpl *stg;
74 ULONGLONG addr;
75 struct chmUnitInfo ui;
76 } IStream_Impl;
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(
86 IEnumSTATSTG* iface,
87 REFIID riid,
88 void** ppvObject)
90 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
92 if (IsEqualGUID(riid, &IID_IUnknown)
93 || IsEqualGUID(riid, &IID_IEnumSTATSTG))
95 IEnumSTATSTG_AddRef(iface);
96 *ppvObject = This;
97 return S_OK;
100 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
101 return E_NOINTERFACE;
104 static ULONG WINAPI ITSS_IEnumSTATSTG_AddRef(
105 IEnumSTATSTG* iface)
107 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
108 return ++(This->ref);
111 static ULONG WINAPI ITSS_IEnumSTATSTG_Release(
112 IEnumSTATSTG* iface)
114 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
116 ULONG ref = --This->ref;
118 if (ref == 0)
120 while( This->first )
122 struct enum_info *t = This->first->next;
123 HeapFree( GetProcessHeap(), 0, This->first );
124 This->first = t;
126 HeapFree(GetProcessHeap(), 0, This);
129 return ref;
132 static HRESULT WINAPI ITSS_IEnumSTATSTG_Next(
133 IEnumSTATSTG* iface,
134 ULONG celt,
135 STATSTG* rgelt,
136 ULONG* pceltFetched)
138 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
139 DWORD len, n;
140 struct enum_info *cur;
142 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched );
144 cur = This->current;
145 n = 0;
146 while( (n<celt) && cur)
148 WCHAR *str;
150 memset( rgelt, 0, sizeof *rgelt );
152 /* copy the name */
153 str = cur->ui.path;
154 if( *str == '/' )
155 str++;
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;
166 else
167 rgelt->type = STGTY_STREAM;
169 /* copy the size */
170 rgelt->cbSize.QuadPart = cur->ui.length;
172 /* advance to the next item if it exists */
173 n++;
174 cur = cur->next;
177 This->current = cur;
178 *pceltFetched = n;
180 if( n < celt )
181 return S_FALSE;
183 return S_OK;
186 static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip(
187 IEnumSTATSTG* iface,
188 ULONG celt)
190 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
191 DWORD n;
192 struct enum_info *cur;
194 TRACE("%p %lu\n", This, celt );
196 cur = This->current;
197 n = 0;
198 while( (n<celt) && cur)
200 n++;
201 cur = cur->next;
203 This->current = cur;
205 if( n < celt )
206 return S_FALSE;
208 return S_OK;
211 static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset(
212 IEnumSTATSTG* iface)
214 IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface;
216 TRACE("%p\n", This );
218 This->current = This->first;
220 return S_OK;
223 static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone(
224 IEnumSTATSTG* iface,
225 IEnumSTATSTG** ppenum)
227 FIXME("\n");
228 return E_NOTIMPL;
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;
248 stgenum->ref = 1;
249 stgenum->first = NULL;
250 stgenum->last = NULL;
251 stgenum->current = NULL;
253 TRACE(" -> %p\n", stgenum );
255 return stgenum;
258 /************************************************************************/
260 HRESULT WINAPI ITSS_IStorageImpl_QueryInterface(
261 IStorage* iface,
262 REFIID riid,
263 void** ppvObject)
265 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
267 if (IsEqualGUID(riid, &IID_IUnknown)
268 || IsEqualGUID(riid, &IID_IStorage))
270 IStorage_AddRef(iface);
271 *ppvObject = This;
272 return S_OK;
275 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
276 return E_NOINTERFACE;
279 ULONG WINAPI ITSS_IStorageImpl_AddRef(
280 IStorage* iface)
282 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
283 return ++(This->ref);
286 ULONG WINAPI ITSS_IStorageImpl_Release(
287 IStorage* iface)
289 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
291 ULONG ref = --This->ref;
293 if (ref == 0)
295 HeapFree(GetProcessHeap(), 0, This);
298 return ref;
301 HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
302 IStorage* iface,
303 LPCOLESTR pwcsName,
304 DWORD grfMode,
305 DWORD reserved1,
306 DWORD reserved2,
307 IStream** ppstm)
309 FIXME("\n");
310 return E_NOTIMPL;
313 HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
314 IStorage* iface,
315 LPCOLESTR pwcsName,
316 void* reserved1,
317 DWORD grfMode,
318 DWORD reserved2,
319 IStream** ppstm)
321 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface;
322 IStream_Impl *stm;
323 DWORD len;
324 struct chmUnitInfo ui;
325 int r;
326 WCHAR *path;
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 = '/' ) )
338 *p-- = 0;
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 );
351 if( !stm )
352 return E_FAIL;
354 *ppstm = (IStream*) stm;
356 return S_OK;
359 HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
360 IStorage* iface,
361 LPCOLESTR pwcsName,
362 DWORD grfMode,
363 DWORD dwStgFmt,
364 DWORD reserved2,
365 IStorage** ppstg)
367 FIXME("\n");
368 return E_NOTIMPL;
371 HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
372 IStorage* iface,
373 LPCOLESTR pwcsName,
374 IStorage* pstgPriority,
375 DWORD grfMode,
376 SNB snbExclude,
377 DWORD reserved,
378 IStorage** ppstg)
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);
384 return E_NOTIMPL;
387 HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
388 IStorage* iface,
389 DWORD ciidExclude,
390 const IID* rgiidExclude,
391 SNB snbExclude,
392 IStorage* pstgDest)
394 FIXME("\n");
395 return E_NOTIMPL;
398 HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
399 IStorage* iface,
400 LPCOLESTR pwcsName,
401 IStorage* pstgDest,
402 LPCOLESTR pwcsNewName,
403 DWORD grfFlags)
405 FIXME("\n");
406 return E_NOTIMPL;
409 HRESULT WINAPI ITSS_IStorageImpl_Commit(
410 IStorage* iface,
411 DWORD grfCommitFlags)
413 FIXME("\n");
414 return E_NOTIMPL;
417 HRESULT WINAPI ITSS_IStorageImpl_Revert(
418 IStorage* iface)
420 FIXME("\n");
421 return E_NOTIMPL;
424 static int ITSS_chm_enumerator(
425 struct chmFile *h,
426 struct chmUnitInfo *ui,
427 void *context)
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 );
437 info->next = NULL;
438 info->prev = stgenum->last;
439 if( stgenum->last )
440 stgenum->last->next = info;
441 else
442 stgenum->first = info;
443 stgenum->last = info;
445 return CHM_ENUMERATOR_CONTINUE;
448 HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
449 IStorage* iface,
450 DWORD reserved1,
451 void* reserved2,
452 DWORD reserved3,
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();
461 if( !stgenum )
462 return E_FAIL;
464 chm_enumerate_dir(This->chmfile,
465 This->dir,
466 CHM_ENUMERATE_ALL,
467 ITSS_chm_enumerator,
468 stgenum );
470 stgenum->current = stgenum->first;
472 *ppenum = (IEnumSTATSTG*) stgenum;
474 return S_OK;
477 HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
478 IStorage* iface,
479 LPCOLESTR pwcsName)
481 FIXME("\n");
482 return E_NOTIMPL;
485 HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
486 IStorage* iface,
487 LPCOLESTR pwcsOldName,
488 LPCOLESTR pwcsNewName)
490 FIXME("\n");
491 return E_NOTIMPL;
494 HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
495 IStorage* iface,
496 LPCOLESTR pwcsName,
497 const FILETIME* pctime,
498 const FILETIME* patime,
499 const FILETIME* pmtime)
501 FIXME("\n");
502 return E_NOTIMPL;
505 HRESULT WINAPI ITSS_IStorageImpl_SetClass(
506 IStorage* iface,
507 REFCLSID clsid)
509 FIXME("\n");
510 return E_NOTIMPL;
513 HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
514 IStorage* iface,
515 DWORD grfStateBits,
516 DWORD grfMask)
518 FIXME("\n");
519 return E_NOTIMPL;
522 HRESULT WINAPI ITSS_IStorageImpl_Stat(
523 IStorage* iface,
524 STATSTG* pstatstg,
525 DWORD grfStatFlag)
527 FIXME("\n");
528 return E_NOTIMPL;
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;
557 DWORD len;
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;
565 stg->ref = 1;
566 stg->chmfile = chmfile;
567 strcpyW( stg->dir, dir );
569 *ppstgOpen = (IStorage*) stg;
571 return S_OK;
574 HRESULT ITSS_StgOpenStorage(
575 const WCHAR* pwcsName,
576 IStorage* pstgPriority,
577 DWORD grfMode,
578 SNB snbExclude,
579 DWORD reserved,
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 );
588 if( !chmfile )
589 return E_FAIL;
591 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
594 /************************************************************************/
596 static HRESULT WINAPI ITSS_IStream_QueryInterface(
597 IStream* iface,
598 REFIID riid,
599 void** ppvObject)
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);
608 *ppvObject = This;
609 return S_OK;
612 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
613 return E_NOINTERFACE;
616 static ULONG WINAPI ITSS_IStream_AddRef(
617 IStream* iface)
619 IStream_Impl *This = (IStream_Impl *)iface;
620 return ++(This->ref);
623 static ULONG WINAPI ITSS_IStream_Release(
624 IStream* iface)
626 IStream_Impl *This = (IStream_Impl *)iface;
628 ULONG ref = --This->ref;
630 if (ref == 0)
632 IStorage_Release( (IStorage*) This->stg );
633 HeapFree(GetProcessHeap(), 0, This);
636 return ref;
639 static HRESULT WINAPI ITSS_IStream_Read(
640 IStream* iface,
641 void* pv,
642 ULONG cb,
643 ULONG* pcbRead)
645 IStream_Impl *This = (IStream_Impl *)iface;
646 ULONG count;
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);
652 This->addr += count;
653 if( pcbRead )
654 *pcbRead = count;
656 return S_OK;
659 static HRESULT WINAPI ITSS_IStream_Write(
660 IStream* iface,
661 const void* pv,
662 ULONG cb,
663 ULONG* pcbWritten)
665 FIXME("\n");
666 return E_NOTIMPL;
669 static HRESULT WINAPI ITSS_IStream_Seek(
670 IStream* iface,
671 LARGE_INTEGER dlibMove,
672 DWORD dwOrigin,
673 ULARGE_INTEGER* plibNewPosition)
675 IStream_Impl *This = (IStream_Impl *)iface;
676 LONGLONG newpos;
678 TRACE("%p %s %lu %p\n", This,
679 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
681 newpos = This->addr;
682 switch( dwOrigin )
684 case STREAM_SEEK_CUR:
685 newpos = This->addr + dlibMove.QuadPart;
686 break;
687 case STREAM_SEEK_SET:
688 newpos = dlibMove.QuadPart;
689 break;
690 case STREAM_SEEK_END:
691 newpos = This->ui.length + dlibMove.QuadPart;
692 break;
695 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
696 return STG_E_INVALIDPOINTER;
698 This->addr = newpos;
699 if( plibNewPosition )
700 plibNewPosition->QuadPart = This->addr;
702 return S_OK;
705 static HRESULT WINAPI ITSS_IStream_SetSize(
706 IStream* iface,
707 ULARGE_INTEGER libNewSize)
709 FIXME("\n");
710 return E_NOTIMPL;
713 static HRESULT WINAPI ITSS_IStream_CopyTo(
714 IStream* iface,
715 IStream* pstm,
716 ULARGE_INTEGER cb,
717 ULARGE_INTEGER* pcbRead,
718 ULARGE_INTEGER* pcbWritten)
720 FIXME("\n");
721 return E_NOTIMPL;
724 static HRESULT WINAPI ITSS_IStream_Commit(
725 IStream* iface,
726 DWORD grfCommitFlags)
728 FIXME("\n");
729 return E_NOTIMPL;
732 static HRESULT WINAPI ITSS_IStream_Revert(
733 IStream* iface)
735 FIXME("\n");
736 return E_NOTIMPL;
739 static HRESULT WINAPI ITSS_IStream_LockRegion(
740 IStream* iface,
741 ULARGE_INTEGER libOffset,
742 ULARGE_INTEGER cb,
743 DWORD dwLockType)
745 FIXME("\n");
746 return E_NOTIMPL;
749 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
750 IStream* iface,
751 ULARGE_INTEGER libOffset,
752 ULARGE_INTEGER cb,
753 DWORD dwLockType)
755 FIXME("\n");
756 return E_NOTIMPL;
759 static HRESULT WINAPI ITSS_IStream_Stat(
760 IStream* iface,
761 STATSTG* pstatstg,
762 DWORD grfStatFlag)
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) );
778 return S_OK;
781 static HRESULT WINAPI ITSS_IStream_Clone(
782 IStream* iface,
783 IStream** ppstm)
785 FIXME("\n");
786 return E_NOTIMPL;
789 struct IStreamVtbl ITSS_IStream_vtbl =
791 ITSS_IStream_QueryInterface,
792 ITSS_IStream_AddRef,
793 ITSS_IStream_Release,
794 ITSS_IStream_Read,
795 ITSS_IStream_Write,
796 ITSS_IStream_Seek,
797 ITSS_IStream_SetSize,
798 ITSS_IStream_CopyTo,
799 ITSS_IStream_Commit,
800 ITSS_IStream_Revert,
801 ITSS_IStream_LockRegion,
802 ITSS_IStream_UnlockRegion,
803 ITSS_IStream_Stat,
804 ITSS_IStream_Clone,
807 static IStream_Impl *ITSS_create_stream(
808 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
810 IStream_Impl *stm;
812 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
813 stm->vtbl_IStream = &ITSS_IStream_vtbl;
814 stm->ref = 1;
815 stm->addr = 0;
816 memcpy( &stm->ui, ui, sizeof stm->ui );
817 stm->stg = stg;
818 IStorage_AddRef( (IStorage*) stg );
820 TRACE(" -> %p\n", stm );
822 return stm;