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