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 } 888