| | 358 | |
|---|
| | 359 | class MemoryIStream: DflComObject, dfl.internal.wincom.IStream |
|---|
| | 360 | { |
|---|
| | 361 | this(void[] memory) |
|---|
| | 362 | { |
|---|
| | 363 | this.mem = memory; |
|---|
| | 364 | } |
|---|
| | 365 | |
|---|
| | 366 | |
|---|
| | 367 | extern(Windows): |
|---|
| | 368 | |
|---|
| | 369 | override HRESULT QueryInterface(IID* riid, void** ppv) |
|---|
| | 370 | { |
|---|
| | 371 | if(*riid == _IID_IStream) |
|---|
| | 372 | { |
|---|
| | 373 | *ppv = cast(void*)cast(dfl.internal.wincom.IStream)this; |
|---|
| | 374 | AddRef(); |
|---|
| | 375 | return S_OK; |
|---|
| | 376 | } |
|---|
| | 377 | else if(*riid == _IID_ISequentialStream) |
|---|
| | 378 | { |
|---|
| | 379 | *ppv = cast(void*)cast(dfl.internal.wincom.ISequentialStream)this; |
|---|
| | 380 | AddRef(); |
|---|
| | 381 | return S_OK; |
|---|
| | 382 | } |
|---|
| | 383 | else if(*riid == _IID_IUnknown) |
|---|
| | 384 | { |
|---|
| | 385 | *ppv = cast(void*)cast(IUnknown)this; |
|---|
| | 386 | AddRef(); |
|---|
| | 387 | return S_OK; |
|---|
| | 388 | } |
|---|
| | 389 | else |
|---|
| | 390 | { |
|---|
| | 391 | *ppv = null; |
|---|
| | 392 | return E_NOINTERFACE; |
|---|
| | 393 | } |
|---|
| | 394 | } |
|---|
| | 395 | |
|---|
| | 396 | |
|---|
| | 397 | HRESULT Read(void* pv, ULONG cb, ULONG* pcbRead) |
|---|
| | 398 | { |
|---|
| | 399 | // Shouldn't happen unless the mem changes, which doesn't happen yet. |
|---|
| | 400 | if(seekpos > mem.length) |
|---|
| | 401 | return S_FALSE; // ? |
|---|
| | 402 | |
|---|
| | 403 | size_t count = mem.length - seekpos; |
|---|
| | 404 | if(count > cb) |
|---|
| | 405 | count = cb; |
|---|
| | 406 | |
|---|
| | 407 | pv[0 .. count] = mem[seekpos .. seekpos + count]; |
|---|
| | 408 | seekpos += count; |
|---|
| | 409 | |
|---|
| | 410 | if(pcbRead) |
|---|
| | 411 | *pcbRead = count; |
|---|
| | 412 | return S_OK; |
|---|
| | 413 | } |
|---|
| | 414 | |
|---|
| | 415 | |
|---|
| | 416 | HRESULT Write(void* pv, ULONG cb, ULONG* pcbWritten) |
|---|
| | 417 | { |
|---|
| | 418 | //return STG_E_ACCESSDENIED; |
|---|
| | 419 | return E_NOTIMPL; |
|---|
| | 420 | } |
|---|
| | 421 | |
|---|
| | 422 | |
|---|
| | 423 | HRESULT Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) |
|---|
| | 424 | { |
|---|
| | 425 | //printf("seek move=%u, origin=0x%x\n", cast(uint)dlibMove.QuadPart, dwOrigin); |
|---|
| | 426 | |
|---|
| | 427 | auto toPos = cast(long)dlibMove.QuadPart; |
|---|
| | 428 | switch(dwOrigin) |
|---|
| | 429 | { |
|---|
| | 430 | case STREAM_SEEK_SET: |
|---|
| | 431 | break; |
|---|
| | 432 | |
|---|
| | 433 | case STREAM_SEEK_CUR: |
|---|
| | 434 | toPos = cast(long)seekpos + toPos; |
|---|
| | 435 | break; |
|---|
| | 436 | |
|---|
| | 437 | case STREAM_SEEK_END: |
|---|
| | 438 | toPos = cast(long)mem.length - toPos; |
|---|
| | 439 | break; |
|---|
| | 440 | |
|---|
| | 441 | default: |
|---|
| | 442 | return STG_E_INVALIDFUNCTION; |
|---|
| | 443 | } |
|---|
| | 444 | |
|---|
| | 445 | if(withinbounds(toPos)) |
|---|
| | 446 | { |
|---|
| | 447 | seekpos = cast(size_t)toPos; |
|---|
| | 448 | if(plibNewPosition) |
|---|
| | 449 | plibNewPosition.QuadPart = seekpos; |
|---|
| | 450 | return S_OK; |
|---|
| | 451 | } |
|---|
| | 452 | else |
|---|
| | 453 | { |
|---|
| | 454 | return 0x80030005; //STG_E_ACCESSDENIED; // Seeking past end needs write access. |
|---|
| | 455 | } |
|---|
| | 456 | } |
|---|
| | 457 | |
|---|
| | 458 | |
|---|
| | 459 | HRESULT SetSize(ULARGE_INTEGER libNewSize) |
|---|
| | 460 | { |
|---|
| | 461 | return E_NOTIMPL; |
|---|
| | 462 | } |
|---|
| | 463 | |
|---|
| | 464 | |
|---|
| | 465 | HRESULT CopyTo(IStream pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) |
|---|
| | 466 | { |
|---|
| | 467 | // TODO: implement. |
|---|
| | 468 | return E_NOTIMPL; |
|---|
| | 469 | } |
|---|
| | 470 | |
|---|
| | 471 | |
|---|
| | 472 | HRESULT Commit(DWORD grfCommitFlags) |
|---|
| | 473 | { |
|---|
| | 474 | return S_OK; // ? |
|---|
| | 475 | } |
|---|
| | 476 | |
|---|
| | 477 | |
|---|
| | 478 | HRESULT Revert() |
|---|
| | 479 | { |
|---|
| | 480 | return E_NOTIMPL; // ? S_FALSE ? |
|---|
| | 481 | } |
|---|
| | 482 | |
|---|
| | 483 | |
|---|
| | 484 | HRESULT LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) |
|---|
| | 485 | { |
|---|
| | 486 | return E_NOTIMPL; |
|---|
| | 487 | } |
|---|
| | 488 | |
|---|
| | 489 | |
|---|
| | 490 | HRESULT UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) |
|---|
| | 491 | { |
|---|
| | 492 | return E_NOTIMPL; |
|---|
| | 493 | } |
|---|
| | 494 | |
|---|
| | 495 | |
|---|
| | 496 | HRESULT Stat(STATSTG* pstatstg, DWORD grfStatFlag) |
|---|
| | 497 | { |
|---|
| | 498 | return E_NOTIMPL; // ? |
|---|
| | 499 | } |
|---|
| | 500 | |
|---|
| | 501 | |
|---|
| | 502 | HRESULT Clone(IStream* ppstm) |
|---|
| | 503 | { |
|---|
| | 504 | // Cloned stream needs its own seek position. |
|---|
| | 505 | return E_NOTIMPL; // ? |
|---|
| | 506 | } |
|---|
| | 507 | |
|---|
| | 508 | |
|---|
| | 509 | extern(D): |
|---|
| | 510 | |
|---|
| | 511 | private: |
|---|
| | 512 | void[] mem; |
|---|
| | 513 | size_t seekpos = 0; |
|---|
| | 514 | |
|---|
| | 515 | |
|---|
| | 516 | bool withinbounds(long pos) |
|---|
| | 517 | { |
|---|
| | 518 | if(pos < seekpos.min || pos > seekpos.max) |
|---|
| | 519 | return false; |
|---|
| | 520 | // Note: it IS within bounds if it's AT the end, it just can't read there. |
|---|
| | 521 | return cast(size_t)pos <= mem.length; |
|---|
| | 522 | } |
|---|
| | 523 | } |
|---|
| | 524 | |
|---|