Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "WebKitDLL.h"
     28 #include "MemoryStream.h"
     29 
     30 using std::min;
     31 using namespace WebCore;
     32 
     33 // MemoryStream ---------------------------------------------------------------
     34 
     35 MemoryStream::MemoryStream(PassRefPtr<SharedBuffer> buffer)
     36 : m_refCount(0)
     37 , m_buffer(buffer)
     38 , m_pos(0)
     39 {
     40     gClassCount++;
     41     gClassNameCount.add("MemoryStream");
     42 }
     43 
     44 MemoryStream::~MemoryStream()
     45 {
     46     gClassCount--;
     47     gClassNameCount.remove("MemoryStream");
     48 }
     49 
     50 COMPtr<MemoryStream> MemoryStream::createInstance(PassRefPtr<SharedBuffer> buffer)
     51 {
     52     return new MemoryStream(buffer);
     53 }
     54 
     55 // IUnknown -------------------------------------------------------------------
     56 
     57 HRESULT STDMETHODCALLTYPE MemoryStream::QueryInterface(REFIID riid, void** ppvObject)
     58 {
     59     *ppvObject = 0;
     60     if (IsEqualGUID(riid, IID_IUnknown))
     61         *ppvObject = static_cast<IUnknown*>(this);
     62     else if (IsEqualGUID(riid, IID_ISequentialStream))
     63         *ppvObject = static_cast<ISequentialStream*>(this);
     64     else if (IsEqualGUID(riid, IID_IStream))
     65         *ppvObject = static_cast<IStream*>(this);
     66     else
     67         return E_NOINTERFACE;
     68 
     69     AddRef();
     70     return S_OK;
     71 }
     72 
     73 ULONG STDMETHODCALLTYPE MemoryStream::AddRef(void)
     74 {
     75     return ++m_refCount;
     76 }
     77 
     78 ULONG STDMETHODCALLTYPE MemoryStream::Release(void)
     79 {
     80     ULONG newRef = --m_refCount;
     81     if (!newRef)
     82         delete(this);
     83 
     84     return newRef;
     85 }
     86 
     87 // ISequentialStream ----------------------------------------------------------
     88 
     89 HRESULT STDMETHODCALLTYPE MemoryStream::Read(
     90     /* [length_is][size_is][out] */ void* pv,
     91     /* [in] */ ULONG cb,
     92     /* [out] */ ULONG* pcbRead)
     93 {
     94     *pcbRead = 0;
     95 
     96     if (!m_buffer)
     97         return E_FAIL;
     98 
     99     if (m_pos >= m_buffer->size())
    100         return S_FALSE;
    101 
    102     if (m_pos + cb < m_buffer->size())
    103         *pcbRead = cb;
    104     else
    105         *pcbRead = (ULONG) (m_buffer->size() - m_pos);
    106 
    107     memcpy(pv, m_buffer->data() + m_pos, *pcbRead);
    108     m_pos += *pcbRead;
    109 
    110     return S_OK;
    111 }
    112 
    113 HRESULT STDMETHODCALLTYPE MemoryStream::Write(
    114     /* [size_is][in] */ const void* /*pv*/,
    115     /* [in] */ ULONG /*cb*/,
    116     /* [out] */ ULONG* /*pcbWritten*/)
    117 {
    118     // we use this for read-only streams
    119     return STG_E_ACCESSDENIED;
    120 }
    121 
    122 // IStream --------------------------------------------------------------------
    123 
    124 HRESULT STDMETHODCALLTYPE MemoryStream::Seek(
    125     /* [in] */ LARGE_INTEGER dlibMove,
    126     /* [in] */ DWORD dwOrigin,
    127     /* [out] */ ULARGE_INTEGER* plibNewPosition)
    128 {
    129     if (!m_buffer)
    130         return E_FAIL;
    131 
    132     size_t proposedPos = m_pos;
    133     size_t lowPartNeg;
    134     switch (dwOrigin) {
    135         case STREAM_SEEK_SET:
    136             proposedPos = dlibMove.LowPart;
    137             if (dlibMove.HighPart)
    138                 return E_FAIL;
    139             break;
    140         case STREAM_SEEK_CUR:
    141             if (!dlibMove.HighPart) {
    142                 if (dlibMove.LowPart > (m_buffer->size() - m_pos))
    143                     return E_FAIL;
    144                 proposedPos += dlibMove.LowPart;
    145             } else if (dlibMove.HighPart == -1) {
    146                 lowPartNeg = (~dlibMove.LowPart)+1;
    147                 if (lowPartNeg > m_pos)
    148                     return E_FAIL;
    149                 proposedPos = m_pos - lowPartNeg;
    150             } else
    151                 return E_FAIL;
    152             break;
    153         case STREAM_SEEK_END:
    154             if (dlibMove.HighPart != -1)
    155                 return E_FAIL;
    156             lowPartNeg = (~dlibMove.LowPart)+1;
    157             if (lowPartNeg > m_buffer->size())
    158                 return E_FAIL;
    159             proposedPos = m_buffer->size() - lowPartNeg;
    160             break;
    161         default:
    162             return E_FAIL;
    163     }
    164 
    165     if (proposedPos >= m_buffer->size())
    166         return E_FAIL;
    167 
    168     if (plibNewPosition) {
    169         plibNewPosition->HighPart = 0;
    170         plibNewPosition->LowPart = (DWORD) m_pos;
    171     }
    172 
    173     return S_OK;
    174 }
    175 
    176 HRESULT STDMETHODCALLTYPE MemoryStream::SetSize(
    177     /* [in] */ ULARGE_INTEGER /*libNewSize*/)
    178 {
    179     return STG_E_INVALIDFUNCTION;
    180 }
    181 
    182 HRESULT STDMETHODCALLTYPE MemoryStream::CopyTo(
    183     /* [unique][in] */ IStream* pstm,
    184     /* [in] */ ULARGE_INTEGER cb,
    185     /* [out] */ ULARGE_INTEGER* pcbRead,
    186     /* [out] */ ULARGE_INTEGER* pcbWritten)
    187 {
    188     if (!m_buffer)
    189         return E_FAIL;
    190     if (cb.HighPart) {
    191         cb.HighPart = 0;
    192         cb.LowPart = (DWORD)-1;
    193     }
    194 
    195     ULONG written;
    196     ULONG read = min(cb.LowPart, (ULONG)(m_buffer->size()-m_pos));
    197     HRESULT hr = pstm->Write(m_buffer->data()+m_pos, read, &written);
    198     if (pcbWritten) {
    199         pcbWritten->HighPart = 0;
    200         pcbWritten->LowPart = written;
    201     }
    202     if (pcbRead) {
    203         pcbRead->HighPart = 0;
    204         pcbRead->LowPart = read;
    205     }
    206 
    207     return hr;
    208 }
    209 
    210 HRESULT STDMETHODCALLTYPE MemoryStream::Commit(
    211     /* [in] */ DWORD /*grfCommitFlags*/)
    212 {
    213     return S_OK;
    214 }
    215 
    216 HRESULT STDMETHODCALLTYPE MemoryStream::Revert( void)
    217 {
    218     return S_OK;
    219 }
    220 
    221 HRESULT STDMETHODCALLTYPE MemoryStream::LockRegion(
    222     /* [in] */ ULARGE_INTEGER /*libOffset*/,
    223     /* [in] */ ULARGE_INTEGER /*cb*/,
    224     /* [in] */ DWORD /*dwLockType*/)
    225 {
    226     return STG_E_INVALIDFUNCTION;
    227 }
    228 
    229 HRESULT STDMETHODCALLTYPE MemoryStream::UnlockRegion(
    230     /* [in] */ ULARGE_INTEGER /*libOffset*/,
    231     /* [in] */ ULARGE_INTEGER /*cb*/,
    232     /* [in] */ DWORD /*dwLockType*/)
    233 {
    234     return STG_E_INVALIDFUNCTION;
    235 }
    236 
    237 HRESULT STDMETHODCALLTYPE MemoryStream::Stat(
    238     /* [out] */ STATSTG* pstatstg,
    239     /* [in] */ DWORD /*grfStatFlag*/)
    240 {
    241     if (!pstatstg)
    242         return E_POINTER;
    243 
    244     if (!m_buffer)
    245         return E_FAIL;
    246 
    247     memset(pstatstg, 0, sizeof(STATSTG));
    248     pstatstg->type = STGTY_STREAM;
    249     pstatstg->cbSize.LowPart = (DWORD) m_buffer->size();
    250     return S_OK;
    251 }
    252 
    253 HRESULT STDMETHODCALLTYPE MemoryStream::Clone(
    254     /* [out] */ IStream** ppstm)
    255 {
    256     MemoryStream::createInstance(m_buffer).copyRefTo(ppstm);
    257     // FIXME: MSDN says we should be returning STG_E_INSUFFICIENT_MEMORY instead of E_OUTOFMEMORY here.
    258     return (*ppstm) ? S_OK : E_OUTOFMEMORY;
    259 }
    260