[ITSS]
[reactos.git] / reactos / dll / win32 / itss / storage.c
1 /*
2 * ITSS Storage implementation
3 *
4 * Copyright 2004 Mike McCormack
5 *
6 * see http://bonedaddy.net/pabs3/hhm/#chmspec
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "precomp.h"
24
25 /************************************************************************/
26
27 typedef struct _ITSS_IStorageImpl
28 {
29 IStorage IStorage_iface;
30 LONG ref;
31 struct chmFile *chmfile;
32 WCHAR dir[1];
33 } ITSS_IStorageImpl;
34
35 struct enum_info
36 {
37 struct enum_info *next, *prev;
38 struct chmUnitInfo ui;
39 };
40
41 typedef struct _IEnumSTATSTG_Impl
42 {
43 IEnumSTATSTG IEnumSTATSTG_iface;
44 LONG ref;
45 struct enum_info *first, *last, *current;
46 } IEnumSTATSTG_Impl;
47
48 typedef struct _IStream_Impl
49 {
50 IStream IStream_iface;
51 LONG ref;
52 ITSS_IStorageImpl *stg;
53 ULONGLONG addr;
54 struct chmUnitInfo ui;
55 } IStream_Impl;
56
57 static inline ITSS_IStorageImpl *impl_from_IStorage(IStorage *iface)
58 {
59 return CONTAINING_RECORD(iface, ITSS_IStorageImpl, IStorage_iface);
60 }
61
62 static inline IEnumSTATSTG_Impl *impl_from_IEnumSTATSTG(IEnumSTATSTG *iface)
63 {
64 return CONTAINING_RECORD(iface, IEnumSTATSTG_Impl, IEnumSTATSTG_iface);
65 }
66
67 static inline IStream_Impl *impl_from_IStream(IStream *iface)
68 {
69 return CONTAINING_RECORD(iface, IStream_Impl, IStream_iface);
70 }
71
72 static HRESULT ITSS_create_chm_storage(
73 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen );
74 static IStream_Impl* ITSS_create_stream(
75 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui );
76
77 /************************************************************************/
78
79 static HRESULT WINAPI ITSS_IEnumSTATSTG_QueryInterface(
80 IEnumSTATSTG* iface,
81 REFIID riid,
82 void** ppvObject)
83 {
84 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
85
86 if (IsEqualGUID(riid, &IID_IUnknown)
87 || IsEqualGUID(riid, &IID_IEnumSTATSTG))
88 {
89 IEnumSTATSTG_AddRef(iface);
90 *ppvObject = This;
91 return S_OK;
92 }
93
94 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
95 return E_NOINTERFACE;
96 }
97
98 static ULONG WINAPI ITSS_IEnumSTATSTG_AddRef(
99 IEnumSTATSTG* iface)
100 {
101 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
102 return InterlockedIncrement(&This->ref);
103 }
104
105 static ULONG WINAPI ITSS_IEnumSTATSTG_Release(
106 IEnumSTATSTG* iface)
107 {
108 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
109
110 ULONG ref = InterlockedDecrement(&This->ref);
111
112 if (ref == 0)
113 {
114 while( This->first )
115 {
116 struct enum_info *t = This->first->next;
117 HeapFree( GetProcessHeap(), 0, This->first );
118 This->first = t;
119 }
120 HeapFree(GetProcessHeap(), 0, This);
121 ITSS_UnlockModule();
122 }
123
124 return ref;
125 }
126
127 static HRESULT WINAPI ITSS_IEnumSTATSTG_Next(
128 IEnumSTATSTG* iface,
129 ULONG celt,
130 STATSTG* rgelt,
131 ULONG* pceltFetched)
132 {
133 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
134 DWORD len, n;
135 struct enum_info *cur;
136
137 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched );
138
139 cur = This->current;
140 n = 0;
141 while( (n<celt) && cur)
142 {
143 WCHAR *str;
144
145 memset( rgelt, 0, sizeof *rgelt );
146
147 /* copy the name */
148 str = cur->ui.path;
149 if( *str == '/' )
150 str++;
151 len = strlenW( str ) + 1;
152 rgelt->pwcsName = CoTaskMemAlloc( len*sizeof(WCHAR) );
153 strcpyW( rgelt->pwcsName, str );
154
155 /* determine the type */
156 if( rgelt->pwcsName[len-2] == '/' )
157 {
158 rgelt->pwcsName[len-2] = 0;
159 rgelt->type = STGTY_STORAGE;
160 }
161 else
162 rgelt->type = STGTY_STREAM;
163
164 /* copy the size */
165 rgelt->cbSize.QuadPart = cur->ui.length;
166
167 /* advance to the next item if it exists */
168 n++;
169 cur = cur->next;
170 }
171
172 This->current = cur;
173 *pceltFetched = n;
174
175 if( n < celt )
176 return S_FALSE;
177
178 return S_OK;
179 }
180
181 static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip(
182 IEnumSTATSTG* iface,
183 ULONG celt)
184 {
185 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
186 DWORD n;
187 struct enum_info *cur;
188
189 TRACE("%p %u\n", This, celt );
190
191 cur = This->current;
192 n = 0;
193 while( (n<celt) && cur)
194 {
195 n++;
196 cur = cur->next;
197 }
198 This->current = cur;
199
200 if( n < celt )
201 return S_FALSE;
202
203 return S_OK;
204 }
205
206 static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset(
207 IEnumSTATSTG* iface)
208 {
209 IEnumSTATSTG_Impl *This = impl_from_IEnumSTATSTG(iface);
210
211 TRACE("%p\n", This );
212
213 This->current = This->first;
214
215 return S_OK;
216 }
217
218 static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone(
219 IEnumSTATSTG* iface,
220 IEnumSTATSTG** ppenum)
221 {
222 FIXME("\n");
223 return E_NOTIMPL;
224 }
225
226 static const IEnumSTATSTGVtbl IEnumSTATSTG_vtbl =
227 {
228 ITSS_IEnumSTATSTG_QueryInterface,
229 ITSS_IEnumSTATSTG_AddRef,
230 ITSS_IEnumSTATSTG_Release,
231 ITSS_IEnumSTATSTG_Next,
232 ITSS_IEnumSTATSTG_Skip,
233 ITSS_IEnumSTATSTG_Reset,
234 ITSS_IEnumSTATSTG_Clone
235 };
236
237 static IEnumSTATSTG_Impl *ITSS_create_enum( void )
238 {
239 IEnumSTATSTG_Impl *stgenum;
240
241 stgenum = HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl) );
242 stgenum->IEnumSTATSTG_iface.lpVtbl = &IEnumSTATSTG_vtbl;
243 stgenum->ref = 1;
244 stgenum->first = NULL;
245 stgenum->last = NULL;
246 stgenum->current = NULL;
247
248 ITSS_LockModule();
249 TRACE(" -> %p\n", stgenum );
250
251 return stgenum;
252 }
253
254 /************************************************************************/
255
256 static HRESULT WINAPI ITSS_IStorageImpl_QueryInterface(
257 IStorage* iface,
258 REFIID riid,
259 void** ppvObject)
260 {
261 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
262
263 if (IsEqualGUID(riid, &IID_IUnknown)
264 || IsEqualGUID(riid, &IID_IStorage))
265 {
266 IStorage_AddRef(iface);
267 *ppvObject = This;
268 return S_OK;
269 }
270
271 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
272 return E_NOINTERFACE;
273 }
274
275 static ULONG WINAPI ITSS_IStorageImpl_AddRef(
276 IStorage* iface)
277 {
278 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
279 return InterlockedIncrement(&This->ref);
280 }
281
282 static ULONG WINAPI ITSS_IStorageImpl_Release(
283 IStorage* iface)
284 {
285 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
286
287 ULONG ref = InterlockedDecrement(&This->ref);
288
289 if (ref == 0)
290 {
291 chm_close(This->chmfile);
292 HeapFree(GetProcessHeap(), 0, This);
293 ITSS_UnlockModule();
294 }
295
296 return ref;
297 }
298
299 static HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
300 IStorage* iface,
301 LPCOLESTR pwcsName,
302 DWORD grfMode,
303 DWORD reserved1,
304 DWORD reserved2,
305 IStream** ppstm)
306 {
307 FIXME("\n");
308 return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
312 IStorage* iface,
313 LPCOLESTR pwcsName,
314 void* reserved1,
315 DWORD grfMode,
316 DWORD reserved2,
317 IStream** ppstm)
318 {
319 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
320 IStream_Impl *stm;
321 DWORD len;
322 struct chmUnitInfo ui;
323 int r;
324 WCHAR *path, *p;
325
326 TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName),
327 reserved1, grfMode, reserved2, ppstm );
328
329 len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
330 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
331 strcpyW( path, This->dir );
332
333 if( pwcsName[0] == '/' || pwcsName[0] == '\\' )
334 {
335 p = &path[strlenW( path ) - 1];
336 while( ( path <= p ) && ( *p == '/' ) )
337 *p-- = 0;
338 }
339 strcatW( path, pwcsName );
340
341 for(p=path; *p; p++) {
342 if(*p == '\\')
343 *p = '/';
344 }
345
346 if(*--p == '/')
347 *p = 0;
348
349 TRACE("Resolving %s\n", debugstr_w(path));
350
351 r = chm_resolve_object(This->chmfile, path, &ui);
352 HeapFree( GetProcessHeap(), 0, path );
353
354 if( r != CHM_RESOLVE_SUCCESS ) {
355 WARN("Could not resolve object\n");
356 return STG_E_FILENOTFOUND;
357 }
358
359 stm = ITSS_create_stream( This, &ui );
360 if( !stm )
361 return E_FAIL;
362
363 *ppstm = &stm->IStream_iface;
364
365 return S_OK;
366 }
367
368 static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
369 IStorage* iface,
370 LPCOLESTR pwcsName,
371 DWORD grfMode,
372 DWORD dwStgFmt,
373 DWORD reserved2,
374 IStorage** ppstg)
375 {
376 FIXME("\n");
377 return E_NOTIMPL;
378 }
379
380 static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
381 IStorage* iface,
382 LPCOLESTR pwcsName,
383 IStorage* pstgPriority,
384 DWORD grfMode,
385 SNB snbExclude,
386 DWORD reserved,
387 IStorage** ppstg)
388 {
389 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
390 struct chmFile *chmfile;
391 WCHAR *path, *p;
392 DWORD len;
393
394 TRACE("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName),
395 pstgPriority, grfMode, snbExclude, reserved, ppstg);
396
397 chmfile = chm_dup( This->chmfile );
398 if( !chmfile )
399 return E_FAIL;
400
401 len = strlenW( This->dir ) + strlenW( pwcsName ) + 2; /* need room for a terminating slash */
402 path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
403 strcpyW( path, This->dir );
404
405 if( pwcsName[0] == '/' || pwcsName[0] == '\\' )
406 {
407 p = &path[strlenW( path ) - 1];
408 while( ( path <= p ) && ( *p == '/' ) )
409 *p-- = 0;
410 }
411 strcatW( path, pwcsName );
412
413 for(p=path; *p; p++) {
414 if(*p == '\\')
415 *p = '/';
416 }
417
418 /* add a terminating slash if one does not already exist */
419 if(*(p-1) != '/')
420 {
421 *p++ = '/';
422 *p = 0;
423 }
424
425 TRACE("Resolving %s\n", debugstr_w(path));
426
427 return ITSS_create_chm_storage(chmfile, path, ppstg);
428 }
429
430 static HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
431 IStorage* iface,
432 DWORD ciidExclude,
433 const IID* rgiidExclude,
434 SNB snbExclude,
435 IStorage* pstgDest)
436 {
437 FIXME("\n");
438 return E_NOTIMPL;
439 }
440
441 static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
442 IStorage* iface,
443 LPCOLESTR pwcsName,
444 IStorage* pstgDest,
445 LPCOLESTR pwcsNewName,
446 DWORD grfFlags)
447 {
448 FIXME("\n");
449 return E_NOTIMPL;
450 }
451
452 static HRESULT WINAPI ITSS_IStorageImpl_Commit(
453 IStorage* iface,
454 DWORD grfCommitFlags)
455 {
456 FIXME("\n");
457 return E_NOTIMPL;
458 }
459
460 static HRESULT WINAPI ITSS_IStorageImpl_Revert(
461 IStorage* iface)
462 {
463 FIXME("\n");
464 return E_NOTIMPL;
465 }
466
467 static int ITSS_chm_enumerator(
468 struct chmFile *h,
469 struct chmUnitInfo *ui,
470 void *context)
471 {
472 struct enum_info *info;
473 IEnumSTATSTG_Impl* stgenum = context;
474
475 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) );
476
477 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) );
478 info->ui = *ui;
479
480 info->next = NULL;
481 info->prev = stgenum->last;
482 if( stgenum->last )
483 stgenum->last->next = info;
484 else
485 stgenum->first = info;
486 stgenum->last = info;
487
488 return CHM_ENUMERATOR_CONTINUE;
489 }
490
491 static HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
492 IStorage* iface,
493 DWORD reserved1,
494 void* reserved2,
495 DWORD reserved3,
496 IEnumSTATSTG** ppenum)
497 {
498 ITSS_IStorageImpl *This = impl_from_IStorage(iface);
499 IEnumSTATSTG_Impl* stgenum;
500
501 TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum );
502
503 stgenum = ITSS_create_enum();
504 if( !stgenum )
505 return E_FAIL;
506
507 chm_enumerate_dir(This->chmfile,
508 This->dir,
509 CHM_ENUMERATE_ALL,
510 ITSS_chm_enumerator,
511 stgenum );
512
513 stgenum->current = stgenum->first;
514
515 *ppenum = &stgenum->IEnumSTATSTG_iface;
516
517 return S_OK;
518 }
519
520 static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
521 IStorage* iface,
522 LPCOLESTR pwcsName)
523 {
524 FIXME("\n");
525 return E_NOTIMPL;
526 }
527
528 static HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
529 IStorage* iface,
530 LPCOLESTR pwcsOldName,
531 LPCOLESTR pwcsNewName)
532 {
533 FIXME("\n");
534 return E_NOTIMPL;
535 }
536
537 static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
538 IStorage* iface,
539 LPCOLESTR pwcsName,
540 const FILETIME* pctime,
541 const FILETIME* patime,
542 const FILETIME* pmtime)
543 {
544 FIXME("\n");
545 return E_NOTIMPL;
546 }
547
548 static HRESULT WINAPI ITSS_IStorageImpl_SetClass(
549 IStorage* iface,
550 REFCLSID clsid)
551 {
552 FIXME("\n");
553 return E_NOTIMPL;
554 }
555
556 static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
557 IStorage* iface,
558 DWORD grfStateBits,
559 DWORD grfMask)
560 {
561 FIXME("\n");
562 return E_NOTIMPL;
563 }
564
565 static HRESULT WINAPI ITSS_IStorageImpl_Stat(
566 IStorage* iface,
567 STATSTG* pstatstg,
568 DWORD grfStatFlag)
569 {
570 FIXME("\n");
571 return E_NOTIMPL;
572 }
573
574 static const IStorageVtbl ITSS_IStorageImpl_Vtbl =
575 {
576 ITSS_IStorageImpl_QueryInterface,
577 ITSS_IStorageImpl_AddRef,
578 ITSS_IStorageImpl_Release,
579 ITSS_IStorageImpl_CreateStream,
580 ITSS_IStorageImpl_OpenStream,
581 ITSS_IStorageImpl_CreateStorage,
582 ITSS_IStorageImpl_OpenStorage,
583 ITSS_IStorageImpl_CopyTo,
584 ITSS_IStorageImpl_MoveElementTo,
585 ITSS_IStorageImpl_Commit,
586 ITSS_IStorageImpl_Revert,
587 ITSS_IStorageImpl_EnumElements,
588 ITSS_IStorageImpl_DestroyElement,
589 ITSS_IStorageImpl_RenameElement,
590 ITSS_IStorageImpl_SetElementTimes,
591 ITSS_IStorageImpl_SetClass,
592 ITSS_IStorageImpl_SetStateBits,
593 ITSS_IStorageImpl_Stat,
594 };
595
596 static HRESULT ITSS_create_chm_storage(
597 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen )
598 {
599 ITSS_IStorageImpl *stg;
600
601 TRACE("%p %s\n", chmfile, debugstr_w( dir ) );
602
603 stg = HeapAlloc( GetProcessHeap(), 0,
604 FIELD_OFFSET( ITSS_IStorageImpl, dir[strlenW( dir ) + 1] ));
605 stg->IStorage_iface.lpVtbl = &ITSS_IStorageImpl_Vtbl;
606 stg->ref = 1;
607 stg->chmfile = chmfile;
608 strcpyW( stg->dir, dir );
609
610 *ppstgOpen = &stg->IStorage_iface;
611
612 ITSS_LockModule();
613 return S_OK;
614 }
615
616 HRESULT ITSS_StgOpenStorage(
617 const WCHAR* pwcsName,
618 IStorage* pstgPriority,
619 DWORD grfMode,
620 SNB snbExclude,
621 DWORD reserved,
622 IStorage** ppstgOpen)
623 {
624 struct chmFile *chmfile;
625 static const WCHAR szRoot[] = { '/', 0 };
626
627 TRACE("%s\n", debugstr_w(pwcsName) );
628
629 chmfile = chm_openW( pwcsName );
630 if( !chmfile )
631 return E_FAIL;
632
633 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen );
634 }
635
636 /************************************************************************/
637
638 static HRESULT WINAPI ITSS_IStream_QueryInterface(
639 IStream* iface,
640 REFIID riid,
641 void** ppvObject)
642 {
643 IStream_Impl *This = impl_from_IStream(iface);
644
645 if (IsEqualGUID(riid, &IID_IUnknown)
646 || IsEqualGUID(riid, &IID_ISequentialStream)
647 || IsEqualGUID(riid, &IID_IStream))
648 {
649 IStream_AddRef(iface);
650 *ppvObject = This;
651 return S_OK;
652 }
653
654 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
655 return E_NOINTERFACE;
656 }
657
658 static ULONG WINAPI ITSS_IStream_AddRef(
659 IStream* iface)
660 {
661 IStream_Impl *This = impl_from_IStream(iface);
662 return InterlockedIncrement(&This->ref);
663 }
664
665 static ULONG WINAPI ITSS_IStream_Release(
666 IStream* iface)
667 {
668 IStream_Impl *This = impl_from_IStream(iface);
669
670 ULONG ref = InterlockedDecrement(&This->ref);
671
672 if (ref == 0)
673 {
674 IStorage_Release( &This->stg->IStorage_iface );
675 HeapFree(GetProcessHeap(), 0, This);
676 ITSS_UnlockModule();
677 }
678
679 return ref;
680 }
681
682 static HRESULT WINAPI ITSS_IStream_Read(
683 IStream* iface,
684 void* pv,
685 ULONG cb,
686 ULONG* pcbRead)
687 {
688 IStream_Impl *This = impl_from_IStream(iface);
689 ULONG count;
690
691 TRACE("%p %p %u %p\n", This, pv, cb, pcbRead);
692
693 count = chm_retrieve_object(This->stg->chmfile,
694 &This->ui, pv, This->addr, cb);
695 This->addr += count;
696 if( pcbRead )
697 *pcbRead = count;
698
699 return count ? S_OK : S_FALSE;
700 }
701
702 static HRESULT WINAPI ITSS_IStream_Write(
703 IStream* iface,
704 const void* pv,
705 ULONG cb,
706 ULONG* pcbWritten)
707 {
708 FIXME("\n");
709 return E_NOTIMPL;
710 }
711
712 static HRESULT WINAPI ITSS_IStream_Seek(
713 IStream* iface,
714 LARGE_INTEGER dlibMove,
715 DWORD dwOrigin,
716 ULARGE_INTEGER* plibNewPosition)
717 {
718 IStream_Impl *This = impl_from_IStream(iface);
719 LONGLONG newpos;
720
721 TRACE("%p %s %u %p\n", This,
722 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition );
723
724 newpos = This->addr;
725 switch( dwOrigin )
726 {
727 case STREAM_SEEK_CUR:
728 newpos = This->addr + dlibMove.QuadPart;
729 break;
730 case STREAM_SEEK_SET:
731 newpos = dlibMove.QuadPart;
732 break;
733 case STREAM_SEEK_END:
734 newpos = This->ui.length + dlibMove.QuadPart;
735 break;
736 }
737
738 if( ( newpos < 0 ) || ( newpos > This->ui.length ) )
739 return STG_E_INVALIDPOINTER;
740
741 This->addr = newpos;
742 if( plibNewPosition )
743 plibNewPosition->QuadPart = This->addr;
744
745 return S_OK;
746 }
747
748 static HRESULT WINAPI ITSS_IStream_SetSize(
749 IStream* iface,
750 ULARGE_INTEGER libNewSize)
751 {
752 FIXME("\n");
753 return E_NOTIMPL;
754 }
755
756 static HRESULT WINAPI ITSS_IStream_CopyTo(
757 IStream* iface,
758 IStream* pstm,
759 ULARGE_INTEGER cb,
760 ULARGE_INTEGER* pcbRead,
761 ULARGE_INTEGER* pcbWritten)
762 {
763 FIXME("\n");
764 return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI ITSS_IStream_Commit(
768 IStream* iface,
769 DWORD grfCommitFlags)
770 {
771 FIXME("\n");
772 return E_NOTIMPL;
773 }
774
775 static HRESULT WINAPI ITSS_IStream_Revert(
776 IStream* iface)
777 {
778 FIXME("\n");
779 return E_NOTIMPL;
780 }
781
782 static HRESULT WINAPI ITSS_IStream_LockRegion(
783 IStream* iface,
784 ULARGE_INTEGER libOffset,
785 ULARGE_INTEGER cb,
786 DWORD dwLockType)
787 {
788 FIXME("\n");
789 return E_NOTIMPL;
790 }
791
792 static HRESULT WINAPI ITSS_IStream_UnlockRegion(
793 IStream* iface,
794 ULARGE_INTEGER libOffset,
795 ULARGE_INTEGER cb,
796 DWORD dwLockType)
797 {
798 FIXME("\n");
799 return E_NOTIMPL;
800 }
801
802 static HRESULT WINAPI ITSS_IStream_Stat(
803 IStream* iface,
804 STATSTG* pstatstg,
805 DWORD grfStatFlag)
806 {
807 IStream_Impl *This = impl_from_IStream(iface);
808
809 TRACE("%p %p %d\n", This, pstatstg, grfStatFlag);
810
811 memset( pstatstg, 0, sizeof *pstatstg );
812 if( !( grfStatFlag & STATFLAG_NONAME ) )
813 {
814 FIXME("copy the name\n");
815 }
816 pstatstg->type = STGTY_STREAM;
817 pstatstg->cbSize.QuadPart = This->ui.length;
818 pstatstg->grfMode = STGM_READ;
819 pstatstg->clsid = CLSID_ITStorage;
820
821 return S_OK;
822 }
823
824 static HRESULT WINAPI ITSS_IStream_Clone(
825 IStream* iface,
826 IStream** ppstm)
827 {
828 FIXME("\n");
829 return E_NOTIMPL;
830 }
831
832 static const IStreamVtbl ITSS_IStream_vtbl =
833 {
834 ITSS_IStream_QueryInterface,
835 ITSS_IStream_AddRef,
836 ITSS_IStream_Release,
837 ITSS_IStream_Read,
838 ITSS_IStream_Write,
839 ITSS_IStream_Seek,
840 ITSS_IStream_SetSize,
841 ITSS_IStream_CopyTo,
842 ITSS_IStream_Commit,
843 ITSS_IStream_Revert,
844 ITSS_IStream_LockRegion,
845 ITSS_IStream_UnlockRegion,
846 ITSS_IStream_Stat,
847 ITSS_IStream_Clone,
848 };
849
850 static IStream_Impl *ITSS_create_stream(
851 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui )
852 {
853 IStream_Impl *stm;
854
855 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) );
856 stm->IStream_iface.lpVtbl = &ITSS_IStream_vtbl;
857 stm->ref = 1;
858 stm->addr = 0;
859 stm->ui = *ui;
860 stm->stg = stg;
861 IStorage_AddRef( &stg->IStorage_iface );
862
863 ITSS_LockModule();
864
865 TRACE(" -> %p\n", stm );
866
867 return stm;
868 }