Home | History | Annotate | Download | only in win
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #define WIN32_LEAN_AND_MEAN
     11 #include <Windows.h>
     12 #include <ole2.h>
     13 #include "SkIStream.h"
     14 #include "SkStream.h"
     15 
     16 /**
     17  * SkBaseIStream
     18  */
     19 SkBaseIStream::SkBaseIStream() : _refcount(1) { }
     20 SkBaseIStream::~SkBaseIStream() { }
     21 
     22 HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
     23                                                       , void ** ppvObject)
     24 {
     25     if (NULL == ppvObject) {
     26         return E_INVALIDARG;
     27     }
     28     if (iid == __uuidof(IUnknown)
     29         || iid == __uuidof(IStream)
     30         || iid == __uuidof(ISequentialStream))
     31     {
     32         *ppvObject = static_cast<IStream*>(this);
     33         AddRef();
     34         return S_OK;
     35     } else {
     36         *ppvObject = NULL;
     37         return E_NOINTERFACE;
     38     }
     39 }
     40 
     41 ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
     42     return (ULONG)InterlockedIncrement(&_refcount);
     43 }
     44 
     45 ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) {
     46     ULONG res = (ULONG) InterlockedDecrement(&_refcount);
     47     if (0 == res) {
     48         delete this;
     49     }
     50     return res;
     51 }
     52 
     53 // ISequentialStream Interface
     54 HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
     55                                             , ULONG cb
     56                                             , ULONG* pcbRead)
     57 { return E_NOTIMPL; }
     58 
     59 HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
     60                                              , ULONG cb
     61                                              , ULONG* pcbWritten)
     62 { return E_NOTIMPL; }
     63 
     64 // IStream Interface
     65 HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
     66 { return E_NOTIMPL; }
     67 
     68 HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
     69                                               , ULARGE_INTEGER
     70                                               , ULARGE_INTEGER*
     71                                               , ULARGE_INTEGER*)
     72 { return E_NOTIMPL; }
     73 
     74 HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
     75 { return E_NOTIMPL; }
     76 
     77 HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
     78 { return E_NOTIMPL; }
     79 
     80 HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
     81                                                   , ULARGE_INTEGER
     82                                                   , DWORD)
     83 { return E_NOTIMPL; }
     84 
     85 HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
     86                                                     , ULARGE_INTEGER
     87                                                     , DWORD)
     88 { return E_NOTIMPL; }
     89 
     90 HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
     91 { return E_NOTIMPL; }
     92 
     93 HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
     94                                             , DWORD dwOrigin
     95                                             , ULARGE_INTEGER* lpNewFilePointer)
     96 { return E_NOTIMPL; }
     97 
     98 HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
     99                                             , DWORD grfStatFlag)
    100 { return E_NOTIMPL; }
    101 
    102 
    103 /**
    104  * SkIStream
    105  */
    106 SkIStream::SkIStream(SkStream* stream, bool unrefOnRelease)
    107     : SkBaseIStream()
    108     , fSkStream(stream)
    109     , fUnrefOnRelease(unrefOnRelease)
    110     , fLocation()
    111 {
    112     this->fSkStream->rewind();
    113 }
    114 
    115 SkIStream::~SkIStream() {
    116     if (NULL != this->fSkStream && fUnrefOnRelease) {
    117         this->fSkStream->unref();
    118     }
    119 }
    120 
    121 HRESULT SkIStream::CreateFromSkStream(SkStream* stream
    122                                     , bool unrefOnRelease
    123                                     , IStream ** ppStream)
    124 {
    125     *ppStream = new SkIStream(stream, unrefOnRelease);
    126     return S_OK;
    127 }
    128 
    129 // ISequentialStream Interface
    130 HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
    131     *pcbRead = this->fSkStream->read(pv, cb);
    132     this->fLocation.QuadPart += *pcbRead;
    133     return (*pcbRead == cb) ? S_OK : S_FALSE;
    134 }
    135 
    136 HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
    137                                          , ULONG cb
    138                                          , ULONG* pcbWritten)
    139 {
    140     return STG_E_CANTSAVE;
    141 }
    142 
    143 // IStream Interface
    144 HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
    145                                         , DWORD dwOrigin
    146                                         , ULARGE_INTEGER* lpNewFilePointer)
    147 {
    148     HRESULT hr = S_OK;
    149 
    150     switch(dwOrigin) {
    151     case STREAM_SEEK_SET: {
    152         if (!this->fSkStream->rewind()) {
    153             hr = E_FAIL;
    154         } else {
    155             size_t skipped = this->fSkStream->skip(
    156                 static_cast<size_t>(liDistanceToMove.QuadPart)
    157             );
    158             this->fLocation.QuadPart = skipped;
    159             if (skipped != liDistanceToMove.QuadPart) {
    160                 hr = E_FAIL;
    161             }
    162         }
    163         break;
    164     }
    165     case STREAM_SEEK_CUR: {
    166         size_t skipped = this->fSkStream->skip(
    167             static_cast<size_t>(liDistanceToMove.QuadPart)
    168         );
    169         this->fLocation.QuadPart += skipped;
    170         if (skipped != liDistanceToMove.QuadPart) {
    171             hr = E_FAIL;
    172         }
    173         break;
    174     }
    175     case STREAM_SEEK_END: {
    176         if (!this->fSkStream->rewind()) {
    177             hr = E_FAIL;
    178         } else {
    179             LONGLONG skip = this->fSkStream->getLength()
    180                           + liDistanceToMove.QuadPart;
    181             size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
    182             this->fLocation.QuadPart = skipped;
    183             if (skipped != skip) {
    184                 hr = E_FAIL;
    185             }
    186         }
    187         break;
    188     }
    189     default:
    190         hr = STG_E_INVALIDFUNCTION;
    191         break;
    192     }
    193 
    194     if (NULL != lpNewFilePointer) {
    195         lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
    196     }
    197     return hr;
    198 }
    199 
    200 HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
    201                                         , DWORD grfStatFlag)
    202 {
    203     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
    204         return STG_E_INVALIDFLAG;
    205     }
    206     pStatstg->pwcsName = NULL;
    207     pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
    208     pStatstg->clsid = CLSID_NULL;
    209     pStatstg->type = STGTY_STREAM;
    210     pStatstg->grfMode = STGM_READ;
    211     return S_OK;
    212 }
    213 
    214 
    215 /**
    216  * SkIWStream
    217  */
    218 SkWIStream::SkWIStream(SkWStream* stream)
    219     : SkBaseIStream()
    220     , fSkWStream(stream)
    221 { }
    222 
    223 SkWIStream::~SkWIStream() {
    224     if (NULL != this->fSkWStream) {
    225         this->fSkWStream->flush();
    226     }
    227 }
    228 
    229 HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
    230                                       , IStream ** ppStream)
    231 {
    232     *ppStream = new SkWIStream(stream);
    233     return S_OK;
    234 }
    235 
    236 // ISequentialStream Interface
    237 HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
    238                                           , ULONG cb
    239                                           , ULONG* pcbWritten)
    240 {
    241     HRESULT hr = S_OK;
    242     bool wrote = this->fSkWStream->write(pv, cb);
    243     if (wrote) {
    244         *pcbWritten = cb;
    245     } else {
    246         *pcbWritten = 0;
    247         hr = S_FALSE;
    248     }
    249     return hr;
    250 }
    251 
    252 // IStream Interface
    253 HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
    254     this->fSkWStream->flush();
    255     return S_OK;
    256 }
    257 
    258 HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
    259                                          , DWORD grfStatFlag)
    260 {
    261     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
    262         return STG_E_INVALIDFLAG;
    263     }
    264     pStatstg->pwcsName = NULL;
    265     pStatstg->cbSize.QuadPart = 0;
    266     pStatstg->clsid = CLSID_NULL;
    267     pStatstg->type = STGTY_STREAM;
    268     pStatstg->grfMode = STGM_WRITE;
    269     return S_OK;
    270 }
    271