shell32: Merge ShellView menu implementations into a single file.
[wine/multimedia.git] / dlls / itss / storage.c
blob4f687c6c7b4a012e35130ecfc8722c1754f51df8
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define COBJMACROS
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "ole2.h"
35 #include "chm_lib.h"
36 #include "itsstor.h"
38 #include "wine/itss.h"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(itss);
44 /************************************************************************/
46 typedef struct _ITSS_IStorageImpl
48 IStorage IStorage_iface;
49 LONG ref;
50 struct chmFile *chmfile;
51 WCHAR dir[1];
52 } ITSS_IStorageImpl;
54 struct enum_info
56 struct enum_info *next, *prev;
57 struct chmUnitInfo ui;
60 typedef struct _IEnumSTATSTG_Impl
62 IEnumSTATSTG IEnumSTATSTG_iface;
63 LONG ref;
64 struct enum_info *first, *last, *current;
65 } IEnumSTATSTG_Impl;
67 typedef struct _IStream_Impl
69 IStream IStream_iface;
70 LONG ref;
71 ITSS_IStorageImpl *stg;
72 ULONGLONG addr;
73 struct chmUnitInfo ui;
74 } IStream_Impl;
76 static inline ITSS_IStorageImpl *impl_from_IStorage(IStorage *iface)
78 return CONTAINING_RECORD(iface, ITSS_IStorageImpl, IStorage_iface);
81 static inline IEnumSTATSTG_Impl *impl_from_IEnumSTATSTG(IEnumSTATSTG *iface)
83 return CONTAINING_RECORD(iface, IEnumSTATSTG_Impl, IEnumSTATSTG_iface);
86 static inline IStream_Impl *impl_from_IStream(IStream *iface)
88 return CONTAINING_RECORD(iface, IStream_Impl, IStream_iface);
91 static HRESULT ITSS_create_chm_storage(
92 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen );
93 static IStream_Impl* ITSS_create_stream(
94 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui );
96 /************************************************************************/
98 static HRESULT WINAPI ITSS_IEnumSTATSTG_QueryInterface(
99 IEnumSTATSTG* iface,
100 REFIID riid,
101 void** ppvObject)
103 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
105 if (IsEqualGUID(riid, &IID_IUnknown)
106 || IsEqualGUID(riid, &IID_IEnumSTATSTG))
108 IEnumSTATSTG_AddRef(iface);
109 *ppvObject = This;
110 return S_OK;
113 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
114 return E_NOINTERFACE;
117 static ULONG WINAPI ITSS_IEnumSTATSTG_AddRef(
118 IEnumSTATSTG* iface)
120 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
121 return InterlockedIncrement(&This->ref);
124 static ULONG WINAPI ITSS_IEnumSTATSTG_Release(
125 IEnumSTATSTG* iface)
127 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
129 ULONG ref = InterlockedDecrement(&This->ref);
131 if (ref == 0)
133 while( This->first )
135 struct enum_info *t = This->first->next;
136 HeapFree( GetProcessHeap(), 0, This->first );
137 This->first = t;
139 HeapFree(GetProcessHeap(), 0, This);
140 ITSS_UnlockModule();
143 return ref;
146 static HRESULT WINAPI ITSS_IEnumSTATSTG_Next(
147 IEnumSTATSTG* iface,
148 ULONG celt,
149 STATSTG* rgelt,
150 ULONG* pceltFetched)
152 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
153 DWORD len, n;
154 struct enum_info *cur;
156 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched );
158 cur = This->current;
159 n = 0;
160 while( (n<celt) && cur)
162 WCHAR *str;
164 memset( rgelt, 0, sizeof *rgelt );
166 /* copy the name */
167 str = cur->ui.path;
168 if( *str == '/' )
169 str++;
170 len = strlenW( str ) + 1;
171 rgelt->pwcsName = CoTaskMemAlloc( len*sizeof(WCHAR) );
172 strcpyW( rgelt->pwcsName, str );
174 /* determine the type */
175 if( rgelt->pwcsName[len-2] == '/' )
177 rgelt->pwcsName[len-2] = 0;
178 rgelt->type = STGTY_STORAGE;
180 else
181 rgelt->type = STGTY_STREAM;
183 /* copy the size */
184 rgelt->cbSize.QuadPart = cur->ui.length;
186 /* advance to the next item if it exists */
187 n++;
188 cur = cur->next;
191 This->current = cur;
192 *pceltFetched = n;
194 if( n < celt )
195 return S_FALSE;
197 return S_OK;
200 static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip(
201 IEnumSTATSTG* iface,
202 ULONG celt)
204 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
205 DWORD n;
206 struct enum_info *cur;
208 TRACE("%p %u\n", This, celt );
210 cur = This->current;
211 n = 0;
212 while( (n<celt) && cur)
214 n++;
215 cur = cur->next;
217 This->current = cur;
219 if( n < celt )
220 return S_FALSE;
222 return S_OK;
225 static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset(
226 IEnumSTATSTG* iface)
228 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
230 TRACE("%p\n", This );
232 This->current = This->first;
234 return S_OK;
237 static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone(
238 IEnumSTATSTG* iface,
239 IEnumSTATSTG** ppenum)
241 FIXME("\n");
242 return E_NOTIMPL;
245 static const IEnumSTATSTGVtbl IEnumSTATSTG_vtbl =
247 ITSS_IEnumSTATSTG_QueryInterface,
248 ITSS_IEnumSTATSTG_AddRef,
249 ITSS_IEnumSTATSTG_Release,
250 ITSS_IEnumSTATSTG_Next,
251 ITSS_IEnumSTATSTG_Skip,
252 ITSS_IEnumSTATSTG_Reset,
253 ITSS_IEnumSTATSTG_Clone
256 static IEnumSTATSTG_Impl *ITSS_create_enum( void )
258 IEnumSTATSTG_Impl *stgenum;
260 stgenum = HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl) );
261 stgenum->IEnumSTATSTG_iface.lpVtbl = &IEnumSTATSTG_vtbl;
262 stgenum->ref = 1;
263 stgenum->first = NULL;
264 stgenum->last = NULL;
265 stgenum->current = NULL;
267 ITSS_LockModule();
268 TRACE(" -> %p\n", stgenum );
270 return stgenum;
273 /************************************************************************/
275 static HRESULT WINAPI ITSS_IStorageImpl_QueryInterface(
276 IStorage* iface,
277 REFIID riid,
278 void** ppvObject)
280 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
282 if (IsEqualGUID(riid, &IID_IUnknown)
283 || IsEqualGUID(riid, &IID_IStorage))
285 IStorage_AddRef(iface);
286 *ppvObject = This;
287 return S_OK;
290 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
291 return E_NOINTERFACE;
294 static ULONG WINAPI ITSS_IStorageImpl_AddRef(
295 IStorage* iface)
297 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
298 return InterlockedIncrement(&This->ref);
301 static ULONG WINAPI ITSS_IStorageImpl_Release(
302 IStorage* iface)
304 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
306 ULONG ref = InterlockedDecrement(&This->ref);
308 if (ref == 0)
310 chm_close(This->chmfile);
311 HeapFree(GetProcessHeap(), 0, This);
312 ITSS_UnlockModule();
315 return ref;
318 static HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
319 IStorage* iface,
320 LPCOLESTR pwcsName,
321 DWORD grfMode,
322 DWORD reserved1,
323 DWORD reserved2,
324 IStream** ppstm)
326 FIXME("\n");
327 return E_NOTIMPL;
330 static HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
331 IStorage* iface,
332 LPCOLESTR pwcsName,
333 void* reserved1,
334 DWORD grfMode,
335 DWORD reserved2,
336 IStream** ppstm)
338 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
339 IStream_Impl *stm;
340 DWORD len;
341 struct chmUnitInfo ui;
342 int r;
343 WCHAR *path, *p;
345 TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName),
346 reserved1, grfMode, reserved2, ppstm );
348 len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
349 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
350 strcpyW( path, This->dir );
352 if( pwcsName[0] == '/' || pwcsName[0] == '\\' )
354 p = &path[strlenW( path ) - 1];
355 while( ( path <= p ) && ( *p == '/' ) )
356 *p-- = 0;
358 strcatW( path, pwcsName );
360 for(p=path; *p; p++) {
361 if(*p == '\\')
362 *p = '/';
365 if(*--p == '/')
366 *p = 0;
368 TRACE("Resolving %s\n", debugstr_w(path));
370 r = chm_resolve_object(This->chmfile, path, &ui);
371 HeapFree( GetProcessHeap(), 0, path );
373 if( r != CHM_RESOLVE_SUCCESS ) {
374 WARN("Could not resolve object\n");
375 return STG_E_FILENOTFOUND;
378 stm = ITSS_create_stream( This, &ui );
379 if( !stm )
380 return E_FAIL;
382 *ppstm = &stm->IStream_iface;
384 return S_OK;
387 static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
388 IStorage* iface,
389 LPCOLESTR pwcsName,
390 DWORD grfMode,
391 DWORD dwStgFmt,
392 DWORD reserved2,
393 IStorage** ppstg)
395 FIXME("\n");
396 return E_NOTIMPL;
399 static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
400 IStorage* iface,
401 LPCOLESTR pwcsName,
402 IStorage* pstgPriority,
403 DWORD grfMode,
404 SNB snbExclude,
405 DWORD reserved,
406 IStorage** ppstg)
408 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
409 static const WCHAR szRoot[] = { '/', 0 };
410 struct chmFile *chmfile;
411 WCHAR *path, *p;
412 DWORD len;
414 TRACE("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName),
415 pstgPriority, grfMode, snbExclude, reserved, ppstg);
417 chmfile = chm_dup( This->chmfile );
418 if( !chmfile )
419 return E_FAIL;
421 len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
422 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
423 strcpyW( path, This->dir );
425 if( pwcsName[0] == '/' || pwcsName[0] == '\\' )
427 p = &path[strlenW( path ) - 1];
428 while( ( path <= p ) && ( *p == '/' ) )
429 *p-- = 0;
431 strcatW( path, pwcsName );
433 for(p=path; *p; p++) {
434 if(*p == '\\')
435 *p = '/';
438 if(*--p == '/')
439 *p = 0;
441 strcatW( path, szRoot );
443 TRACE("Resolving %s\n", debugstr_w(path));
445 return ITSS_create_chm_storage(chmfile, path, ppstg);
448 static HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
449 IStorage* iface,
450 DWORD ciidExclude,
451 const IID* rgiidExclude,
452 SNB snbExclude,
453 IStorage* pstgDest)
455 FIXME("\n");
456 return E_NOTIMPL;
459 static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
460 IStorage* iface,
461 LPCOLESTR pwcsName,
462 IStorage* pstgDest,
463 LPCOLESTR pwcsNewName,
464 DWORD grfFlags)
466 FIXME("\n");
467 return E_NOTIMPL;
470 static HRESULT WINAPI ITSS_IStorageImpl_Commit(
471 IStorage* iface,
472 DWORD grfCommitFlags)
474 FIXME("\n");
475 return E_NOTIMPL;
478 static HRESULT WINAPI ITSS_IStorageImpl_Revert(
479 IStorage* iface)
481 FIXME("\n");
482 return E_NOTIMPL;
485 static int ITSS_chm_enumerator(
486 struct chmFile *h,
487 struct chmUnitInfo *ui,
488 void *context)
490 struct enum_info *info;
491 IEnumSTATSTG_Impl* stgenum = context;
493 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) );
495 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) );
496 info->ui = *ui;
498 info->next = NULL;
499 info->prev = stgenum->last;
500 if( stgenum->last )
501 stgenum->last->next = info;
502 else
503 stgenum->first = info;
504 stgenum->last = info;
506 return CHM_ENUMERATOR_CONTINUE;
509 static HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
510 IStorage* iface,
511 DWORD reserved1,
512 void* reserved2,
513 DWORD reserved3,
514 IEnumSTATSTG** ppenum)
516 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
517 IEnumSTATSTG_Impl* stgenum;
519 TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum );
521 stgenum = ITSS_create_enum();
522 if( !stgenum )
523 return E_FAIL;
525 chm_enumerate_dir(This->chmfile,
526 This->dir,
527 CHM_ENUMERATE_ALL,
528 ITSS_chm_enumerator,
529 stgenum );
531 stgenum->current = stgenum->first;
533 *ppenum = &stgenum->IEnumSTATSTG_iface;
535 return S_OK;
538 static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
539 IStorage* iface,
540 LPCOLESTR pwcsName)
542 FIXME("\n");
543 return E_NOTIMPL;
546 static HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
547 IStorage* iface,
548 LPCOLESTR pwcsOldName,
549 LPCOLESTR pwcsNewName)
551 FIXME("\n");
552 return E_NOTIMPL;
555 static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
556 IStorage* iface,
557 LPCOLESTR pwcsName,
558 const FILETIME* pctime,
559 const FILETIME* patime,
560 const FILETIME* pmtime)
562 FIXME("\n");
563 return E_NOTIMPL;
566 static HRESULT WINAPI ITSS_IStorageImpl_SetClass(
567 IStorage* iface,
568 REFCLSID clsid)
570 FIXME("\n");
571 return E_NOTIMPL;
574 static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
575 IStorage* iface,
576 DWORD grfStateBits,
577 DWORD grfMask)
579 FIXME("\n");
580 return E_NOTIMPL;
583 static HRESULT WINAPI ITSS_IStorageImpl_Stat(
584 IStorage* iface,
585 STATSTG* pstatstg,
586 DWORD grfStatFlag)
588 FIXME("\n");
589 return E_NOTIMPL;
592 static const IStorageVtbl ITSS_IStorageImpl_Vtbl =
594 ITSS_IStorageImpl_QueryInterface,
595 ITSS_IStorageImpl_AddRef,
596 ITSS_IStorageImpl_Release,
597 ITSS_IStorageImpl_CreateStream,
598 ITSS_IStorageImpl_OpenStream,
599 ITSS_IStorageImpl_CreateStorage,
600 ITSS_IStorageImpl_OpenStorage,
601 ITSS_IStorageImpl_CopyTo,
602 ITSS_IStorageImpl_MoveElementTo,
603 ITSS_IStorageImpl_Commit,
604 ITSS_IStorageImpl_Revert,
605 ITSS_IStorageImpl_EnumElements,
606 ITSS_IStorageImpl_DestroyElement,
607 ITSS_IStorageImpl_RenameElement,
608 ITSS_IStorageImpl_SetElementTimes,
609 ITSS_IStorageImpl_SetClass,
610 ITSS_IStorageImpl_SetStateBits,
611 ITSS_IStorageImpl_Stat,
614 static HRESULT ITSS_create_chm_storage(
615 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen )
617 ITSS_IStorageImpl *stg;
618 DWORD len;
620 TRACE("%p %s\n", chmfile, debugstr_w( dir ) );
622 len = strlenW( dir ) + 1;
623 stg = HeapAlloc( GetProcessHeap(), 0,
624 sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) );
625 stg->IStorage_iface.lpVtbl = &ITSS_IStorageImpl_Vtbl;
626 stg->ref = 1;
627 stg->chmfile = chmfile;
628 strcpyW( stg->dir, dir );
630 *ppstgOpen = &stg->IStorage_iface;
632 ITSS_LockModule();
633 return S_OK;
636 HRESULT ITSS_StgOpenStorage(
637 const WCHAR* pwcsName,
638 IStorage* pstgPriority,
639 DWORD grfMode,
640 SNB snbExclude,
641 DWORD reserved,
642 IStorage** ppstgOpen)
644 struct chmFile *chmfile;
645 static const WCHAR szRoot[] = { '/', 0 };
647 TRACE("%s\n", debugstr_w(pwcsName) );
649 chmfile = chm_openW( pwcsName );
650 if( !chmfile )
651 return E_FAIL;
653 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
656 /************************************************************************/
658 static HRESULT WINAPI ITSS_IStream_QueryInterface(
659 IStream* iface,
660 REFIID riid,
661 void** ppvObject)
663 IStream_Impl *This = impl_from_IStream(iface);
665 if (IsEqualGUID(riid, &IID_IUnknown)
666 || IsEqualGUID(riid, &IID_ISequentialStream)
667 || IsEqualGUID(riid, &IID_IStream))
669 IStream_AddRef(iface);
670 *ppvObject = This;
671 return S_OK;
674 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
675 return E_NOINTERFACE;
678 static ULONG WINAPI ITSS_IStream_AddRef(
679 IStream* iface)
681 IStream_Impl *This = impl_from_IStream(iface);
682 return InterlockedIncrement(&This->ref);
685 static ULONG WINAPI ITSS_IStream_Release(
686 IStream* iface)
688 IStream_Impl *This = impl_from_IStream(iface);
690 ULONG ref = InterlockedDecrement(&This->ref);
692 if (ref == 0)
694 IStorage_Release( &This->stg->IStorage_iface );
695 HeapFree(GetProcessHeap(), 0, This);
696 ITSS_UnlockModule();
699 return ref;
702 static HRESULT WINAPI ITSS_IStream_Read(
703 IStream* iface,
704 void* pv,
705 ULONG cb,
706 ULONG* pcbRead)
708 IStream_Impl *This = impl_from_IStream(iface);
709 ULONG count;
711 TRACE("%p %p %u %p\n", This, pv, cb, pcbRead);
713 count = chm_retrieve_object(This->stg->chmfile,
714 &This->ui, pv, This->addr, cb);
715 This->addr += count;
716 if( pcbRead )
717 *pcbRead = count;
719 return count ? S_OK : S_FALSE;
722 static HRESULT WINAPI ITSS_IStream_Write(
723 IStream* iface,
724 const void* pv,
725 ULONG cb,
726 ULONG* pcbWritten)
728 FIXME("\n");
729 return E_NOTIMPL;
732 static HRESULT WINAPI ITSS_IStream_Seek(
733 IStream* iface,
734 LARGE_INTEGER dlibMove,
735 DWORD dwOrigin,
736 ULARGE_INTEGER* plibNewPosition)
738 IStream_Impl *This = impl_from_IStream(iface);
739 LONGLONG newpos;
741 TRACE("%p %s %u %p\n", This,
742 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
744 newpos = This->addr;
745 switch( dwOrigin )
747 case STREAM_SEEK_CUR:
748 newpos = This->addr + dlibMove.QuadPart;
749 break;
750 case STREAM_SEEK_SET:
751 newpos = dlibMove.QuadPart;
752 break;
753 case STREAM_SEEK_END:
754 newpos = This->ui.length + dlibMove.QuadPart;
755 break;
758 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
759 return STG_E_INVALIDPOINTER;
761 This->addr = newpos;
762 if( plibNewPosition )
763 plibNewPosition->QuadPart = This->addr;
765 return S_OK;
768 static HRESULT WINAPI ITSS_IStream_SetSize(
769 IStream* iface,
770 ULARGE_INTEGER libNewSize)
772 FIXME("\n");
773 return E_NOTIMPL;
776 static HRESULT WINAPI ITSS_IStream_CopyTo(
777 IStream* iface,
778 IStream* pstm,
779 ULARGE_INTEGER cb,
780 ULARGE_INTEGER* pcbRead,
781 ULARGE_INTEGER* pcbWritten)
783 FIXME("\n");
784 return E_NOTIMPL;
787 static HRESULT WINAPI ITSS_IStream_Commit(
788 IStream* iface,
789 DWORD grfCommitFlags)
791 FIXME("\n");
792 return E_NOTIMPL;
795 static HRESULT WINAPI ITSS_IStream_Revert(
796 IStream* iface)
798 FIXME("\n");
799 return E_NOTIMPL;
802 static HRESULT WINAPI ITSS_IStream_LockRegion(
803 IStream* iface,
804 ULARGE_INTEGER libOffset,
805 ULARGE_INTEGER cb,
806 DWORD dwLockType)
808 FIXME("\n");
809 return E_NOTIMPL;
812 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
813 IStream* iface,
814 ULARGE_INTEGER libOffset,
815 ULARGE_INTEGER cb,
816 DWORD dwLockType)
818 FIXME("\n");
819 return E_NOTIMPL;
822 static HRESULT WINAPI ITSS_IStream_Stat(
823 IStream* iface,
824 STATSTG* pstatstg,
825 DWORD grfStatFlag)
827 IStream_Impl *This = impl_from_IStream(iface);
829 TRACE("%p %p %d\n", This, pstatstg, grfStatFlag);
831 memset( pstatstg, 0, sizeof *pstatstg );
832 if( !( grfStatFlag & STATFLAG_NONAME ) )
834 FIXME("copy the name\n");
836 pstatstg->type = STGTY_STREAM;
837 pstatstg->cbSize.QuadPart = This->ui.length;
838 pstatstg->grfMode = STGM_READ;
839 pstatstg->clsid = CLSID_ITStorage;
841 return S_OK;
844 static HRESULT WINAPI ITSS_IStream_Clone(
845 IStream* iface,
846 IStream** ppstm)
848 FIXME("\n");
849 return E_NOTIMPL;
852 static const IStreamVtbl ITSS_IStream_vtbl =
854 ITSS_IStream_QueryInterface,
855 ITSS_IStream_AddRef,
856 ITSS_IStream_Release,
857 ITSS_IStream_Read,
858 ITSS_IStream_Write,
859 ITSS_IStream_Seek,
860 ITSS_IStream_SetSize,
861 ITSS_IStream_CopyTo,
862 ITSS_IStream_Commit,
863 ITSS_IStream_Revert,
864 ITSS_IStream_LockRegion,
865 ITSS_IStream_UnlockRegion,
866 ITSS_IStream_Stat,
867 ITSS_IStream_Clone,
870 static IStream_Impl *ITSS_create_stream(
871 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
873 IStream_Impl *stm;
875 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
876 stm->IStream_iface.lpVtbl = &ITSS_IStream_vtbl;
877 stm->ref = 1;
878 stm->addr = 0;
879 stm->ui = *ui;
880 stm->stg = stg;
881 IStorage_AddRef( &stg->IStorage_iface );
883 ITSS_LockModule();
885 TRACE(" -> %p\n", stm );
887 return stm;