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 */ 19SkBaseIStream::SkBaseIStream() : _refcount(1) { } 20SkBaseIStream::~SkBaseIStream() { } 21 22HRESULT 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 41ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) { 42 return (ULONG)InterlockedIncrement(&_refcount); 43} 44 45ULONG 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 54HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv 55 , ULONG cb 56 , ULONG* pcbRead) 57{ return E_NOTIMPL; } 58 59HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv 60 , ULONG cb 61 , ULONG* pcbWritten) 62{ return E_NOTIMPL; } 63 64// IStream Interface 65HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER) 66{ return E_NOTIMPL; } 67 68HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream* 69 , ULARGE_INTEGER 70 , ULARGE_INTEGER* 71 , ULARGE_INTEGER*) 72{ return E_NOTIMPL; } 73 74HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD) 75{ return E_NOTIMPL; } 76 77HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void) 78{ return E_NOTIMPL; } 79 80HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER 81 , ULARGE_INTEGER 82 , DWORD) 83{ return E_NOTIMPL; } 84 85HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER 86 , ULARGE_INTEGER 87 , DWORD) 88{ return E_NOTIMPL; } 89 90HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **) 91{ return E_NOTIMPL; } 92 93HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove 94 , DWORD dwOrigin 95 , ULARGE_INTEGER* lpNewFilePointer) 96{ return E_NOTIMPL; } 97 98HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg 99 , DWORD grfStatFlag) 100{ return E_NOTIMPL; } 101 102 103/** 104 * SkIStream 105 */ 106SkIStream::SkIStream(SkStream* stream, bool unrefOnRelease) 107 : SkBaseIStream() 108 , fSkStream(stream) 109 , fUnrefOnRelease(unrefOnRelease) 110 , fLocation() 111{ 112 this->fSkStream->rewind(); 113} 114 115SkIStream::~SkIStream() { 116 if (NULL != this->fSkStream && fUnrefOnRelease) { 117 this->fSkStream->unref(); 118 } 119} 120 121HRESULT 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 130HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) { 131 *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb)); 132 this->fLocation.QuadPart += *pcbRead; 133 return (*pcbRead == cb) ? S_OK : S_FALSE; 134} 135 136HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv 137 , ULONG cb 138 , ULONG* pcbWritten) 139{ 140 return STG_E_CANTSAVE; 141} 142 143// IStream Interface 144HRESULT 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 200HRESULT 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 */ 218SkWIStream::SkWIStream(SkWStream* stream) 219 : SkBaseIStream() 220 , fSkWStream(stream) 221{ } 222 223SkWIStream::~SkWIStream() { 224 if (NULL != this->fSkWStream) { 225 this->fSkWStream->flush(); 226 } 227} 228 229HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream 230 , IStream ** ppStream) 231{ 232 *ppStream = new SkWIStream(stream); 233 return S_OK; 234} 235 236// ISequentialStream Interface 237HRESULT 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 253HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) { 254 this->fSkWStream->flush(); 255 return S_OK; 256} 257 258HRESULT 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