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