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 395 FIXME("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName), 396 pstgPriority, grfMode, snbExclude, reserved, ppstg); 397 return E_NOTIMPL; 398 } 399 400 static HRESULT WINAPI ITSS_IStorageImpl_CopyTo( 401 IStorage* iface, 402 DWORD ciidExclude, 403 const IID* rgiidExclude, 404 SNB snbExclude, 405 IStorage* pstgDest) 406 { 407 FIXME("\n"); 408 return E_NOTIMPL; 409 } 410 411 static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo( 412 IStorage* iface, 413 LPCOLESTR pwcsName, 414 IStorage* pstgDest, 415 LPCOLESTR pwcsNewName, 416 DWORD grfFlags) 417 { 418 FIXME("\n"); 419 return E_NOTIMPL; 420 } 421 422 static HRESULT WINAPI ITSS_IStorageImpl_Commit( 423 IStorage* iface, 424 DWORD grfCommitFlags) 425 { 426 FIXME("\n"); 427 return E_NOTIMPL; 428 } 429 430 static HRESULT WINAPI ITSS_IStorageImpl_Revert( 431 IStorage* iface) 432 { 433 FIXME("\n"); 434 return E_NOTIMPL; 435 } 436 437 static int ITSS_chm_enumerator( 438 struct chmFile *h, 439 struct chmUnitInfo *ui, 440 void *context) 441 { 442 struct enum_info *info; 443 IEnumSTATSTG_Impl* stgenum = context; 444 445 TRACE("adding %s to enumeration\n", debugstr_w(ui->path) ); 446 447 info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) ); 448 info->ui = *ui; 449 450 info->next = NULL; 451 info->prev = stgenum->last; 452 if( stgenum->last ) 453 stgenum->last->next = info; 454 else 455 stgenum->first = info; 456 stgenum->last = info; 457 458 return CHM_ENUMERATOR_CONTINUE; 459 } 460 461 static HRESULT WINAPI ITSS_IStorageImpl_EnumElements( 462 IStorage* iface, 463 DWORD reserved1, 464 void* reserved2, 465 DWORD reserved3, 466 IEnumSTATSTG** ppenum) 467 { 468 ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; 469 IEnumSTATSTG_Impl* stgenum; 470 471 TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum ); 472 473 stgenum = ITSS_create_enum(); 474 if( !stgenum ) 475 return E_FAIL; 476 477 chm_enumerate_dir(This->chmfile, 478 This->dir, 479 CHM_ENUMERATE_ALL, 480 ITSS_chm_enumerator, 481 stgenum ); 482 483 stgenum->current = stgenum->first; 484 485 *ppenum = (IEnumSTATSTG*) stgenum; 486 487 return S_OK; 488 } 489 490 static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement( 491 IStorage* iface, 492 LPCOLESTR pwcsName) 493 { 494 FIXME("\n"); 495 return E_NOTIMPL; 496 } 497 498 static HRESULT WINAPI ITSS_IStorageImpl_RenameElement( 499 IStorage* iface, 500 LPCOLESTR pwcsOldName, 501 LPCOLESTR pwcsNewName) 502 { 503 FIXME("\n"); 504 return E_NOTIMPL; 505 } 506 507 static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes( 508 IStorage* iface, 509 LPCOLESTR pwcsName, 510 const FILETIME* pctime, 511 const FILETIME* patime, 512 const FILETIME* pmtime) 513 { 514 FIXME("\n"); 515 return E_NOTIMPL; 516 } 517 518 static HRESULT WINAPI ITSS_IStorageImpl_SetClass( 519 IStorage* iface, 520 REFCLSID clsid) 521 { 522 FIXME("\n"); 523 return E_NOTIMPL; 524 } 525 526 static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits( 527 IStorage* iface, 528 DWORD grfStateBits, 529 DWORD grfMask) 530 { 531 FIXME("\n"); 532 return E_NOTIMPL; 533 } 534 535 static HRESULT WINAPI ITSS_IStorageImpl_Stat( 536 IStorage* iface, 537 STATSTG* pstatstg, 538 DWORD grfStatFlag) 539 { 540 FIXME("\n"); 541 return E_NOTIMPL; 542 } 543 544 static const IStorageVtbl ITSS_IStorageImpl_Vtbl = 545 { 546 ITSS_IStorageImpl_QueryInterface, 547 ITSS_IStorageImpl_AddRef, 548 ITSS_IStorageImpl_Release, 549 ITSS_IStorageImpl_CreateStream, 550 ITSS_IStorageImpl_OpenStream, 551 ITSS_IStorageImpl_CreateStorage, 552 ITSS_IStorageImpl_OpenStorage, 553 ITSS_IStorageImpl_CopyTo, 554 ITSS_IStorageImpl_MoveElementTo, 555 ITSS_IStorageImpl_Commit, 556 ITSS_IStorageImpl_Revert, 557 ITSS_IStorageImpl_EnumElements, 558 ITSS_IStorageImpl_DestroyElement, 559 ITSS_IStorageImpl_RenameElement, 560 ITSS_IStorageImpl_SetElementTimes, 561 ITSS_IStorageImpl_SetClass, 562 ITSS_IStorageImpl_SetStateBits, 563 ITSS_IStorageImpl_Stat, 564 }; 565 566 static HRESULT ITSS_create_chm_storage( 567 struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen ) 568 { 569 ITSS_IStorageImpl *stg; 570 DWORD len; 571 572 TRACE("%p %s\n", chmfile, debugstr_w( dir ) ); 573 574 len = strlenW( dir ) + 1; 575 stg = HeapAlloc( GetProcessHeap(), 0, 576 sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) ); 577 stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl; 578 stg->ref = 1; 579 stg->chmfile = chmfile; 580 strcpyW( stg->dir, dir ); 581 582 *ppstgOpen = (IStorage*) stg; 583 584 ITSS_LockModule(); 585 return S_OK; 586 } 587 588 HRESULT ITSS_StgOpenStorage( 589 const WCHAR* pwcsName, 590 IStorage* pstgPriority, 591 DWORD grfMode, 592 SNB snbExclude, 593 DWORD reserved, 594 IStorage** ppstgOpen) 595 { 596 struct chmFile *chmfile; 597 static const WCHAR szRoot[] = { '/', 0 }; 598 599 TRACE("%s\n", debugstr_w(pwcsName) ); 600 601 chmfile = chm_openW( pwcsName ); 602 if( !chmfile ) 603 return E_FAIL; 604 605 return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen ); 606 } 607 608 /************************************************************************/ 609 610 static HRESULT WINAPI ITSS_IStream_QueryInterface( 611 IStream* iface, 612 REFIID riid, 613 void** ppvObject) 614 { 615 IStream_Impl *This = (IStream_Impl *)iface; 616 617 if (IsEqualGUID(riid, &IID_IUnknown) 618 || IsEqualGUID(riid, &IID_ISequentialStream) 619 || IsEqualGUID(riid, &IID_IStream)) 620 { 621 IStream_AddRef(iface); 622 *ppvObject = This; 623 return S_OK; 624 } 625 626 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); 627 return E_NOINTERFACE; 628 } 629 630 static ULONG WINAPI ITSS_IStream_AddRef( 631 IStream* iface) 632 { 633 IStream_Impl *This = (IStream_Impl *)iface; 634 return InterlockedIncrement(&This->ref); 635 } 636 637 static ULONG WINAPI ITSS_IStream_Release( 638 IStream* iface) 639 { 640 IStream_Impl *This = (IStream_Impl *)iface; 641 642 ULONG ref = InterlockedDecrement(&This->ref); 643 644 if (ref == 0) 645 { 646 IStorage_Release( (IStorage*) This->stg ); 647 HeapFree(GetProcessHeap(), 0, This); 648 ITSS_UnlockModule(); 649 } 650 651 return ref; 652 } 653 654 static HRESULT WINAPI ITSS_IStream_Read( 655 IStream* iface, 656 void* pv, 657 ULONG cb, 658 ULONG* pcbRead) 659 { 660 IStream_Impl *This = (IStream_Impl *)iface; 661 ULONG count; 662 663 TRACE("%p %p %u %p\n", This, pv, cb, pcbRead); 664 665 count = chm_retrieve_object(This->stg->chmfile, 666 &This->ui, pv, This->addr, cb); 667 This->addr += count; 668 if( pcbRead ) 669 *pcbRead = count; 670 671 return count ? S_OK : S_FALSE; 672 } 673 674 static HRESULT WINAPI ITSS_IStream_Write( 675 IStream* iface, 676 const void* pv, 677 ULONG cb, 678 ULONG* pcbWritten) 679 { 680 FIXME("\n"); 681 return E_NOTIMPL; 682 } 683 684 static HRESULT WINAPI ITSS_IStream_Seek( 685 IStream* iface, 686 LARGE_INTEGER dlibMove, 687 DWORD dwOrigin, 688 ULARGE_INTEGER* plibNewPosition) 689 { 690 IStream_Impl *This = (IStream_Impl *)iface; 691 LONGLONG newpos; 692 693 TRACE("%p %s %u %p\n", This, 694 wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition ); 695 696 newpos = This->addr; 697 switch( dwOrigin ) 698 { 699 case STREAM_SEEK_CUR: 700 newpos = This->addr + dlibMove.QuadPart; 701 break; 702 case STREAM_SEEK_SET: 703 newpos = dlibMove.QuadPart; 704 break; 705 case STREAM_SEEK_END: 706 newpos = This->ui.length + dlibMove.QuadPart; 707 break; 708 } 709 710 if( ( newpos < 0 ) || ( newpos > This->ui.length ) ) 711 return STG_E_INVALIDPOINTER; 712 713 This->addr = newpos; 714 if( plibNewPosition ) 715 plibNewPosition->QuadPart = This->addr; 716 717 return S_OK; 718 } 719 720 static HRESULT WINAPI ITSS_IStream_SetSize( 721 IStream* iface, 722 ULARGE_INTEGER libNewSize) 723 { 724 FIXME("\n"); 725 return E_NOTIMPL; 726 } 727 728 static HRESULT WINAPI ITSS_IStream_CopyTo( 729 IStream* iface, 730 IStream* pstm, 731 ULARGE_INTEGER cb, 732 ULARGE_INTEGER* pcbRead, 733 ULARGE_INTEGER* pcbWritten) 734 { 735 FIXME("\n"); 736 return E_NOTIMPL; 737 } 738 739 static HRESULT WINAPI ITSS_IStream_Commit( 740 IStream* iface, 741 DWORD grfCommitFlags) 742 { 743 FIXME("\n"); 744 return E_NOTIMPL; 745 } 746 747 static HRESULT WINAPI ITSS_IStream_Revert( 748 IStream* iface) 749 { 750 FIXME("\n"); 751 return E_NOTIMPL; 752 } 753 754 static HRESULT WINAPI ITSS_IStream_LockRegion( 755 IStream* iface, 756 ULARGE_INTEGER libOffset, 757 ULARGE_INTEGER cb, 758 DWORD dwLockType) 759 { 760 FIXME("\n"); 761 return E_NOTIMPL; 762 } 763 764 static HRESULT WINAPI ITSS_IStream_UnlockRegion( 765 IStream* iface, 766 ULARGE_INTEGER libOffset, 767 ULARGE_INTEGER cb, 768 DWORD dwLockType) 769 { 770 FIXME("\n"); 771 return E_NOTIMPL; 772 } 773 774 static HRESULT WINAPI ITSS_IStream_Stat( 775 IStream* iface, 776 STATSTG* pstatstg, 777 DWORD grfStatFlag) 778 { 779 IStream_Impl *This = (IStream_Impl *)iface; 780 781 TRACE("%p %p %d\n", This, pstatstg, grfStatFlag); 782 783 memset( pstatstg, 0, sizeof *pstatstg ); 784 if( !( grfStatFlag & STATFLAG_NONAME ) ) 785 { 786 FIXME("copy the name\n"); 787 } 788 pstatstg->type = STGTY_STREAM; 789 pstatstg->cbSize.QuadPart = This->ui.length; 790 pstatstg->grfMode = STGM_READ; 791 pstatstg->clsid = CLSID_ITStorage; 792 793 return S_OK; 794 } 795 796 static HRESULT WINAPI ITSS_IStream_Clone( 797 IStream* iface, 798 IStream** ppstm) 799 { 800 FIXME("\n"); 801 return E_NOTIMPL; 802 } 803 804 static const IStreamVtbl ITSS_IStream_vtbl = 805 { 806 ITSS_IStream_QueryInterface, 807 ITSS_IStream_AddRef, 808 ITSS_IStream_Release, 809 ITSS_IStream_Read, 810 ITSS_IStream_Write, 811 ITSS_IStream_Seek, 812 ITSS_IStream_SetSize, 813 ITSS_IStream_CopyTo, 814 ITSS_IStream_Commit, 815 ITSS_IStream_Revert, 816 ITSS_IStream_LockRegion, 817 ITSS_IStream_UnlockRegion, 818 ITSS_IStream_Stat, 819 ITSS_IStream_Clone, 820 }; 821 822 static IStream_Impl *ITSS_create_stream( 823 ITSS_IStorageImpl *stg, struct chmUnitInfo *ui ) 824 { 825 IStream_Impl *stm; 826 827 stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) ); 828 stm->vtbl_IStream = &ITSS_IStream_vtbl; 829 stm->ref = 1; 830 stm->addr = 0; 831 stm->ui = *ui; 832 stm->stg = stg; 833 IStorage_AddRef( (IStorage*) stg ); 834 835 ITSS_LockModule(); 836 837 TRACE(" -> %p\n", stm ); 838 839 return stm; 840 } 841