Authors: Stewart Caie<kyz@uklinux.net>, Jed Wing <jedwin@ugcs.caltech.edu>, Mike...
[wine/multimedia.git] / dlls / itss / storage.c
blobec8bbfb7fac9a0ceea161e095be8a1dd802f65de
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"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(itss);
45 /************************************************************************/
47 typedef struct _ITSS_IStorageImpl
49 IStorageVtbl *vtbl_IStorage;
50 DWORD ref;
51 struct chmFile *chmfile;
52 WCHAR dir[1];
53 } ITSS_IStorageImpl;
55 struct enum_info
57 struct enum_info *next, *prev;
58 struct chmUnitInfo ui;
61 typedef struct _IEnumSTATSTG_Impl
63 IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG;
64 DWORD ref;
65 struct enum_info *first, *last, *current;
66 } IEnumSTATSTG_Impl;
68 typedef struct _IStream_Impl
70 IStreamVtbl *vtbl_IStream;
71 DWORD ref;
72 ITSS_IStorageImpl *stg;
73 ULONGLONG addr;
74 struct chmUnitInfo ui;
75 } IStream_Impl;
77 static HRESULT ITSS_create_chm_storage(
78 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen );
79 static IStream_Impl* ITSS_create_stream(
80 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui );
82 /************************************************************************/
84 static HRESULT WINAPI ITSS_IEnumSTATSTG_QueryInterface(
85 IEnumSTATSTG* iface,
86 REFIID riid,
87 void** ppvObject)
89 ICOM_THIS(IEnumSTATSTG_Impl,iface);
91 if (IsEqualGUID(riid, &IID_IUnknown)
92 || IsEqualGUID(riid, &IID_IEnumSTATSTG))
94 IEnumSTATSTG_AddRef(iface);
95 *ppvObject = This;
96 return S_OK;
99 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
100 return E_NOINTERFACE;
103 static ULONG WINAPI ITSS_IEnumSTATSTG_AddRef(
104 IEnumSTATSTG* iface)
106 ICOM_THIS(IEnumSTATSTG_Impl,iface);
107 return ++(This->ref);
110 static ULONG WINAPI ITSS_IEnumSTATSTG_Release(
111 IEnumSTATSTG* iface)
113 ICOM_THIS(IEnumSTATSTG_Impl,iface);
115 ULONG ref = --This->ref;
117 if (ref == 0)
119 while( This->first )
121 struct enum_info *t = This->first->next;
122 HeapFree( GetProcessHeap(), 0, This->first );
123 This->first = t;
125 HeapFree(GetProcessHeap(), 0, This);
128 return ref;
131 static HRESULT WINAPI ITSS_IEnumSTATSTG_Next(
132 IEnumSTATSTG* iface,
133 ULONG celt,
134 STATSTG* rgelt,
135 ULONG* pceltFetched)
137 ICOM_THIS(IEnumSTATSTG_Impl,iface);
138 DWORD len, n;
139 struct enum_info *cur;
141 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched );
143 cur = This->current;
144 n = 0;
145 while( (n<celt) && cur)
147 WCHAR *str;
149 memset( rgelt, 0, sizeof *rgelt );
151 /* copy the name */
152 str = cur->ui.path;
153 if( *str == '/' )
154 str++;
155 len = strlenW( str ) + 1;
156 rgelt->pwcsName = CoTaskMemAlloc( len*sizeof(WCHAR) );
157 strcpyW( rgelt->pwcsName, str );
159 /* determine the type */
160 if( rgelt->pwcsName[len-2] == '/' )
162 rgelt->pwcsName[len-2] = 0;
163 rgelt->type = STGTY_STORAGE;
165 else
166 rgelt->type = STGTY_STREAM;
168 /* copy the size */
169 rgelt->cbSize.QuadPart = cur->ui.length;
171 /* advance to the next item if it exists */
172 n++;
173 cur = cur->next;
176 This->current = cur;
177 *pceltFetched = n;
179 if( n < celt )
180 return S_FALSE;
182 return S_OK;
185 static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip(
186 IEnumSTATSTG* iface,
187 ULONG celt)
189 ICOM_THIS(IEnumSTATSTG_Impl,iface);
190 DWORD n;
191 struct enum_info *cur;
193 TRACE("%p %lu\n", This, celt );
195 cur = This->current;
196 n = 0;
197 while( (n<celt) && cur)
199 n++;
200 cur = cur->next;
202 This->current = cur;
204 if( n < celt )
205 return S_FALSE;
207 return S_OK;
210 static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset(
211 IEnumSTATSTG* iface)
213 ICOM_THIS(IEnumSTATSTG_Impl,iface);
215 TRACE("%p\n", This );
217 This->current = This->first;
219 return S_OK;
222 static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone(
223 IEnumSTATSTG* iface,
224 IEnumSTATSTG** ppenum)
226 FIXME("\n");
227 return E_NOTIMPL;
230 struct IEnumSTATSTGVtbl IEnumSTATSTG_vtbl =
232 ITSS_IEnumSTATSTG_QueryInterface,
233 ITSS_IEnumSTATSTG_AddRef,
234 ITSS_IEnumSTATSTG_Release,
235 ITSS_IEnumSTATSTG_Next,
236 ITSS_IEnumSTATSTG_Skip,
237 ITSS_IEnumSTATSTG_Reset,
238 ITSS_IEnumSTATSTG_Clone
241 static IEnumSTATSTG_Impl *ITSS_create_enum( void )
243 IEnumSTATSTG_Impl *stgenum;
245 stgenum = HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl) );
246 stgenum->vtbl_IEnumSTATSTG = &IEnumSTATSTG_vtbl;
247 stgenum->ref = 1;
248 stgenum->first = NULL;
249 stgenum->last = NULL;
250 stgenum->current = NULL;
252 TRACE(" -> %p\n", stgenum );
254 return stgenum;
257 /************************************************************************/
259 HRESULT WINAPI ITSS_IStorageImpl_QueryInterface(
260 IStorage* iface,
261 REFIID riid,
262 void** ppvObject)
264 ICOM_THIS(ITSS_IStorageImpl,iface);
266 if (IsEqualGUID(riid, &IID_IUnknown)
267 || IsEqualGUID(riid, &IID_IStorage))
269 IStorage_AddRef(iface);
270 *ppvObject = This;
271 return S_OK;
274 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
275 return E_NOINTERFACE;
278 ULONG WINAPI ITSS_IStorageImpl_AddRef(
279 IStorage* iface)
281 ICOM_THIS(ITSS_IStorageImpl,iface);
282 return ++(This->ref);
285 ULONG WINAPI ITSS_IStorageImpl_Release(
286 IStorage* iface)
288 ICOM_THIS(ITSS_IStorageImpl,iface);
290 ULONG ref = --This->ref;
292 if (ref == 0)
294 HeapFree(GetProcessHeap(), 0, This);
297 return ref;
300 HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
301 IStorage* iface,
302 LPCOLESTR pwcsName,
303 DWORD grfMode,
304 DWORD reserved1,
305 DWORD reserved2,
306 IStream** ppstm)
308 FIXME("\n");
309 return E_NOTIMPL;
312 HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
313 IStorage* iface,
314 LPCOLESTR pwcsName,
315 void* reserved1,
316 DWORD grfMode,
317 DWORD reserved2,
318 IStream** ppstm)
320 ICOM_THIS(ITSS_IStorageImpl,iface);
321 IStream_Impl *stm;
322 DWORD len;
323 struct chmUnitInfo ui;
324 int r;
325 WCHAR *path;
327 TRACE("%p %s %p %lu %lu %p\n", This, debugstr_w(pwcsName),
328 reserved1, grfMode, reserved2, ppstm );
330 len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
331 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
332 strcpyW( path, This->dir );
333 strcatW( path, pwcsName );
335 r = chm_resolve_object(This->chmfile, path, &ui);
336 HeapFree( GetProcessHeap(), 0, path );
338 if( r != CHM_RESOLVE_SUCCESS )
339 return STG_E_FILENOTFOUND;
341 stm = ITSS_create_stream( This, &ui );
342 if( !stm )
343 return E_FAIL;
345 *ppstm = (IStream*) stm;
347 return S_OK;
350 HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
351 IStorage* iface,
352 LPCOLESTR pwcsName,
353 DWORD grfMode,
354 DWORD dwStgFmt,
355 DWORD reserved2,
356 IStorage** ppstg)
358 FIXME("\n");
359 return E_NOTIMPL;
362 HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
363 IStorage* iface,
364 LPCOLESTR pwcsName,
365 IStorage* pstgPriority,
366 DWORD grfMode,
367 SNB snbExclude,
368 DWORD reserved,
369 IStorage** ppstg)
371 FIXME("\n");
372 return E_NOTIMPL;
375 HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
376 IStorage* iface,
377 DWORD ciidExclude,
378 const IID* rgiidExclude,
379 SNB snbExclude,
380 IStorage* pstgDest)
382 FIXME("\n");
383 return E_NOTIMPL;
386 HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
387 IStorage* iface,
388 LPCOLESTR pwcsName,
389 IStorage* pstgDest,
390 LPCOLESTR pwcsNewName,
391 DWORD grfFlags)
393 FIXME("\n");
394 return E_NOTIMPL;
397 HRESULT WINAPI ITSS_IStorageImpl_Commit(
398 IStorage* iface,
399 DWORD grfCommitFlags)
401 FIXME("\n");
402 return E_NOTIMPL;
405 HRESULT WINAPI ITSS_IStorageImpl_Revert(
406 IStorage* iface)
408 FIXME("\n");
409 return E_NOTIMPL;
412 static int ITSS_chm_enumerator(
413 struct chmFile *h,
414 struct chmUnitInfo *ui,
415 void *context)
417 struct enum_info *info;
418 IEnumSTATSTG_Impl* stgenum = context;
420 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) );
422 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) );
423 memcpy( &info->ui, ui, sizeof info->ui );
425 info->next = NULL;
426 info->prev = stgenum->last;
427 if( stgenum->last )
428 stgenum->last->next = info;
429 else
430 stgenum->first = info;
431 stgenum->last = info;
433 return CHM_ENUMERATOR_CONTINUE;
436 HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
437 IStorage* iface,
438 DWORD reserved1,
439 void* reserved2,
440 DWORD reserved3,
441 IEnumSTATSTG** ppenum)
443 ICOM_THIS(ITSS_IStorageImpl,iface);
444 IEnumSTATSTG_Impl* stgenum;
446 TRACE("%p %ld %p %ld %p\n", This, reserved1, reserved2, reserved3, ppenum );
448 stgenum = ITSS_create_enum();
449 if( !stgenum )
450 return E_FAIL;
452 chm_enumerate_dir(This->chmfile,
453 This->dir,
454 CHM_ENUMERATE_ALL,
455 ITSS_chm_enumerator,
456 stgenum );
458 stgenum->current = stgenum->first;
460 *ppenum = (IEnumSTATSTG*) stgenum;
462 return S_OK;
465 HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
466 IStorage* iface,
467 LPCOLESTR pwcsName)
469 FIXME("\n");
470 return E_NOTIMPL;
473 HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
474 IStorage* iface,
475 LPCOLESTR pwcsOldName,
476 LPCOLESTR pwcsNewName)
478 FIXME("\n");
479 return E_NOTIMPL;
482 HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
483 IStorage* iface,
484 LPCOLESTR pwcsName,
485 const FILETIME* pctime,
486 const FILETIME* patime,
487 const FILETIME* pmtime)
489 FIXME("\n");
490 return E_NOTIMPL;
493 HRESULT WINAPI ITSS_IStorageImpl_SetClass(
494 IStorage* iface,
495 REFCLSID clsid)
497 FIXME("\n");
498 return E_NOTIMPL;
501 HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
502 IStorage* iface,
503 DWORD grfStateBits,
504 DWORD grfMask)
506 FIXME("\n");
507 return E_NOTIMPL;
510 HRESULT WINAPI ITSS_IStorageImpl_Stat(
511 IStorage* iface,
512 STATSTG* pstatstg,
513 DWORD grfStatFlag)
515 FIXME("\n");
516 return E_NOTIMPL;
519 static IStorageVtbl ITSS_IStorageImpl_Vtbl =
521 ITSS_IStorageImpl_QueryInterface,
522 ITSS_IStorageImpl_AddRef,
523 ITSS_IStorageImpl_Release,
524 ITSS_IStorageImpl_CreateStream,
525 ITSS_IStorageImpl_OpenStream,
526 ITSS_IStorageImpl_CreateStorage,
527 ITSS_IStorageImpl_OpenStorage,
528 ITSS_IStorageImpl_CopyTo,
529 ITSS_IStorageImpl_MoveElementTo,
530 ITSS_IStorageImpl_Commit,
531 ITSS_IStorageImpl_Revert,
532 ITSS_IStorageImpl_EnumElements,
533 ITSS_IStorageImpl_DestroyElement,
534 ITSS_IStorageImpl_RenameElement,
535 ITSS_IStorageImpl_SetElementTimes,
536 ITSS_IStorageImpl_SetClass,
537 ITSS_IStorageImpl_SetStateBits,
538 ITSS_IStorageImpl_Stat,
541 static HRESULT ITSS_create_chm_storage(
542 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen )
544 ITSS_IStorageImpl *stg;
545 DWORD len;
547 TRACE("%p %s\n", chmfile, debugstr_w( dir ) );
549 len = strlenW( dir ) + 1;
550 stg = HeapAlloc( GetProcessHeap(), 0,
551 sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) );
552 stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl;
553 stg->ref = 1;
554 stg->chmfile = chmfile;
555 strcpyW( stg->dir, dir );
557 *ppstgOpen = (IStorage*) stg;
559 return S_OK;
562 HRESULT ITSS_StgOpenStorage(
563 const WCHAR* pwcsName,
564 IStorage* pstgPriority,
565 DWORD grfMode,
566 SNB snbExclude,
567 DWORD reserved,
568 IStorage** ppstgOpen)
570 struct chmFile *chmfile;
571 static const WCHAR szRoot[] = { '/', 0 };
573 TRACE("%s\n", debugstr_w(pwcsName) );
575 chmfile = chm_openW( pwcsName );
576 if( !chmfile )
577 return E_FAIL;
579 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
582 /************************************************************************/
584 static HRESULT WINAPI ITSS_IStream_QueryInterface(
585 IStream* iface,
586 REFIID riid,
587 void** ppvObject)
589 ICOM_THIS(IStream_Impl,iface);
591 if (IsEqualGUID(riid, &IID_IUnknown)
592 || IsEqualGUID(riid, &IID_ISequentialStream)
593 || IsEqualGUID(riid, &IID_IStream))
595 IStream_AddRef(iface);
596 *ppvObject = This;
597 return S_OK;
600 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
601 return E_NOINTERFACE;
604 static ULONG WINAPI ITSS_IStream_AddRef(
605 IStream* iface)
607 ICOM_THIS(IStream_Impl,iface);
608 return ++(This->ref);
611 static ULONG WINAPI ITSS_IStream_Release(
612 IStream* iface)
614 ICOM_THIS(IStream_Impl,iface);
616 ULONG ref = --This->ref;
618 if (ref == 0)
620 IStorage_Release( (IStorage*) This->stg );
621 HeapFree(GetProcessHeap(), 0, This);
624 return ref;
627 static HRESULT WINAPI ITSS_IStream_Read(
628 IStream* iface,
629 void* pv,
630 ULONG cb,
631 ULONG* pcbRead)
633 ICOM_THIS(IStream_Impl,iface);
634 ULONG count;
636 TRACE("%p %p %lu %p\n", This, pv, cb, pcbRead);
638 count = chm_retrieve_object(This->stg->chmfile,
639 &This->ui, pv, This->addr, cb);
640 This->addr += count;
641 if( pcbRead )
642 *pcbRead = count;
644 return S_OK;
647 static HRESULT WINAPI ITSS_IStream_Write(
648 IStream* iface,
649 const void* pv,
650 ULONG cb,
651 ULONG* pcbWritten)
653 FIXME("\n");
654 return E_NOTIMPL;
657 static HRESULT WINAPI ITSS_IStream_Seek(
658 IStream* iface,
659 LARGE_INTEGER dlibMove,
660 DWORD dwOrigin,
661 ULARGE_INTEGER* plibNewPosition)
663 ICOM_THIS(IStream_Impl,iface);
664 LONGLONG newpos;
666 TRACE("%p %s %lu %p\n", This,
667 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
669 newpos = This->addr;
670 switch( dwOrigin )
672 case STREAM_SEEK_CUR:
673 newpos = This->addr + dlibMove.QuadPart;
674 break;
675 case STREAM_SEEK_SET:
676 newpos = dlibMove.QuadPart;
677 break;
678 case STREAM_SEEK_END:
679 newpos = This->ui.length + dlibMove.QuadPart;
680 break;
683 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
684 return STG_E_INVALIDPOINTER;
686 This->addr = newpos;
687 if( plibNewPosition )
688 plibNewPosition->QuadPart = This->addr;
690 return S_OK;
693 static HRESULT WINAPI ITSS_IStream_SetSize(
694 IStream* iface,
695 ULARGE_INTEGER libNewSize)
697 FIXME("\n");
698 return E_NOTIMPL;
701 static HRESULT WINAPI ITSS_IStream_CopyTo(
702 IStream* iface,
703 IStream* pstm,
704 ULARGE_INTEGER cb,
705 ULARGE_INTEGER* pcbRead,
706 ULARGE_INTEGER* pcbWritten)
708 FIXME("\n");
709 return E_NOTIMPL;
712 static HRESULT WINAPI ITSS_IStream_Commit(
713 IStream* iface,
714 DWORD grfCommitFlags)
716 FIXME("\n");
717 return E_NOTIMPL;
720 static HRESULT WINAPI ITSS_IStream_Revert(
721 IStream* iface)
723 FIXME("\n");
724 return E_NOTIMPL;
727 static HRESULT WINAPI ITSS_IStream_LockRegion(
728 IStream* iface,
729 ULARGE_INTEGER libOffset,
730 ULARGE_INTEGER cb,
731 DWORD dwLockType)
733 FIXME("\n");
734 return E_NOTIMPL;
737 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
738 IStream* iface,
739 ULARGE_INTEGER libOffset,
740 ULARGE_INTEGER cb,
741 DWORD dwLockType)
743 FIXME("\n");
744 return E_NOTIMPL;
747 static HRESULT WINAPI ITSS_IStream_Stat(
748 IStream* iface,
749 STATSTG* pstatstg,
750 DWORD grfStatFlag)
752 FIXME("\n");
753 return E_NOTIMPL;
756 static HRESULT WINAPI ITSS_IStream_Clone(
757 IStream* iface,
758 IStream** ppstm)
760 FIXME("\n");
761 return E_NOTIMPL;
764 struct IStreamVtbl ITSS_IStream_vtbl =
766 ITSS_IStream_QueryInterface,
767 ITSS_IStream_AddRef,
768 ITSS_IStream_Release,
769 ITSS_IStream_Read,
770 ITSS_IStream_Write,
771 ITSS_IStream_Seek,
772 ITSS_IStream_SetSize,
773 ITSS_IStream_CopyTo,
774 ITSS_IStream_Commit,
775 ITSS_IStream_Revert,
776 ITSS_IStream_LockRegion,
777 ITSS_IStream_UnlockRegion,
778 ITSS_IStream_Stat,
779 ITSS_IStream_Clone,
782 static IStream_Impl *ITSS_create_stream(
783 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
785 IStream_Impl *stm;
787 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
788 stm->vtbl_IStream = &ITSS_IStream_vtbl;
789 stm->ref = 1;
790 stm->addr = 0;
791 memcpy( &stm->ui, ui, sizeof stm->ui );
792 stm->stg = stg;
793 IStorage_AddRef( (IStorage*) stg );
795 TRACE(" -> %p\n", stm );
797 return stm;