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