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