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