blob: fdb6ce6eff26d737593a44d73bc519df364022fe [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bungeman@google.com9df621d2011-06-23 21:43:52 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
bungeman@google.com9df621d2011-06-23 21:43:52 +00007 */
8
mtklein1ee76512015-11-02 10:20:27 -08009#include "SkTypes.h"
10#if defined(SK_BUILD_FOR_WIN32)
epoger@google.comec3ed6a2011-07-28 14:26:00 +000011
bungeman@google.com9df621d2011-06-23 21:43:52 +000012#define WIN32_LEAN_AND_MEAN
bungeman@google.com0d9e3da2013-12-03 15:23:37 +000013#include <windows.h>
bungeman@google.com9df621d2011-06-23 21:43:52 +000014#include <ole2.h>
15#include "SkIStream.h"
16#include "SkStream.h"
17
18/**
19 * SkBaseIStream
20 */
21SkBaseIStream::SkBaseIStream() : _refcount(1) { }
22SkBaseIStream::~SkBaseIStream() { }
23
24HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
25 , void ** ppvObject)
26{
halcanary96fcdcc2015-08-27 07:41:13 -070027 if (nullptr == ppvObject) {
bungeman@google.com9df621d2011-06-23 21:43:52 +000028 return E_INVALIDARG;
29 }
30 if (iid == __uuidof(IUnknown)
31 || iid == __uuidof(IStream)
32 || iid == __uuidof(ISequentialStream))
33 {
34 *ppvObject = static_cast<IStream*>(this);
35 AddRef();
36 return S_OK;
37 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070038 *ppvObject = nullptr;
rmistry@google.comd6176b02012-08-23 18:14:13 +000039 return E_NOINTERFACE;
bungeman@google.com9df621d2011-06-23 21:43:52 +000040 }
41}
42
43ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
44 return (ULONG)InterlockedIncrement(&_refcount);
45}
46
47ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) {
48 ULONG res = (ULONG) InterlockedDecrement(&_refcount);
49 if (0 == res) {
50 delete this;
51 }
52 return res;
53}
54
55// ISequentialStream Interface
56HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
57 , ULONG cb
58 , ULONG* pcbRead)
59{ return E_NOTIMPL; }
60
61HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
62 , ULONG cb
63 , ULONG* pcbWritten)
64{ return E_NOTIMPL; }
65
66// IStream Interface
rmistry@google.comd6176b02012-08-23 18:14:13 +000067HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
bungeman@google.com9df621d2011-06-23 21:43:52 +000068{ return E_NOTIMPL; }
69
70HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
71 , ULARGE_INTEGER
72 , ULARGE_INTEGER*
73 , ULARGE_INTEGER*)
74{ return E_NOTIMPL; }
75
76HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
77{ return E_NOTIMPL; }
78
79HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
80{ return E_NOTIMPL; }
81
82HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
83 , ULARGE_INTEGER
84 , DWORD)
85{ return E_NOTIMPL; }
86
87HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
88 , ULARGE_INTEGER
89 , DWORD)
90{ return E_NOTIMPL; }
91
92HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
93{ return E_NOTIMPL; }
94
95HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
96 , DWORD dwOrigin
97 , ULARGE_INTEGER* lpNewFilePointer)
98{ return E_NOTIMPL; }
99
100HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
101 , DWORD grfStatFlag)
102{ return E_NOTIMPL; }
103
104
105/**
106 * SkIStream
107 */
bungeman2dca8172015-01-22 06:08:31 -0800108SkIStream::SkIStream(SkStream* stream, bool deleteOnRelease)
bungeman@google.com9df621d2011-06-23 21:43:52 +0000109 : SkBaseIStream()
110 , fSkStream(stream)
bungeman2dca8172015-01-22 06:08:31 -0800111 , fDeleteOnRelease(deleteOnRelease)
bungeman@google.com60157922011-08-13 00:06:17 +0000112 , fLocation()
113{
114 this->fSkStream->rewind();
115}
bungeman@google.com9df621d2011-06-23 21:43:52 +0000116
117SkIStream::~SkIStream() {
bungeman44af7ba2015-01-22 07:33:51 -0800118 if (fDeleteOnRelease) {
bungeman2dca8172015-01-22 06:08:31 -0800119 delete this->fSkStream;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000120 }
121}
122
123HRESULT SkIStream::CreateFromSkStream(SkStream* stream
bungeman2dca8172015-01-22 06:08:31 -0800124 , bool deleteOnRelease
bungeman@google.com9df621d2011-06-23 21:43:52 +0000125 , IStream ** ppStream)
126{
halcanary96fcdcc2015-08-27 07:41:13 -0700127 if (nullptr == stream) {
bungeman@google.com635091f2013-10-01 15:03:18 +0000128 return E_INVALIDARG;
129 }
bungeman2dca8172015-01-22 06:08:31 -0800130 *ppStream = new SkIStream(stream, deleteOnRelease);
bungeman@google.com9df621d2011-06-23 21:43:52 +0000131 return S_OK;
132}
133
134// ISequentialStream Interface
135HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
bungeman@google.com4b18f572013-07-22 15:21:23 +0000136 *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
bungeman@google.com60157922011-08-13 00:06:17 +0000137 this->fLocation.QuadPart += *pcbRead;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000138 return (*pcbRead == cb) ? S_OK : S_FALSE;
139}
140
141HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
142 , ULONG cb
143 , ULONG* pcbWritten)
144{
145 return STG_E_CANTSAVE;
146}
147
148// IStream Interface
149HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
150 , DWORD dwOrigin
151 , ULARGE_INTEGER* lpNewFilePointer)
152{
bungeman@google.com9df621d2011-06-23 21:43:52 +0000153 HRESULT hr = S_OK;
bungeman@google.com60157922011-08-13 00:06:17 +0000154
bungeman@google.com9df621d2011-06-23 21:43:52 +0000155 switch(dwOrigin) {
156 case STREAM_SEEK_SET: {
157 if (!this->fSkStream->rewind()) {
158 hr = E_FAIL;
159 } else {
160 size_t skipped = this->fSkStream->skip(
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000161 static_cast<size_t>(liDistanceToMove.QuadPart)
bungeman@google.com9df621d2011-06-23 21:43:52 +0000162 );
bungeman@google.com60157922011-08-13 00:06:17 +0000163 this->fLocation.QuadPart = skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000164 if (skipped != liDistanceToMove.QuadPart) {
165 hr = E_FAIL;
166 }
167 }
168 break;
169 }
170 case STREAM_SEEK_CUR: {
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000171 size_t skipped = this->fSkStream->skip(
172 static_cast<size_t>(liDistanceToMove.QuadPart)
173 );
bungeman@google.com60157922011-08-13 00:06:17 +0000174 this->fLocation.QuadPart += skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000175 if (skipped != liDistanceToMove.QuadPart) {
176 hr = E_FAIL;
177 }
178 break;
179 }
180 case STREAM_SEEK_END: {
181 if (!this->fSkStream->rewind()) {
182 hr = E_FAIL;
183 } else {
scroggo@google.comb5571b32013-09-25 21:34:24 +0000184 // FIXME: Should not depend on getLength.
185 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com60157922011-08-13 00:06:17 +0000186 LONGLONG skip = this->fSkStream->getLength()
187 + liDistanceToMove.QuadPart;
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000188 size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
bungeman@google.com60157922011-08-13 00:06:17 +0000189 this->fLocation.QuadPart = skipped;
190 if (skipped != skip) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000191 hr = E_FAIL;
192 }
193 }
194 break;
195 }
196 default:
197 hr = STG_E_INVALIDFUNCTION;
198 break;
199 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000200
bsalomon49f085d2014-09-05 13:34:00 -0700201 if (lpNewFilePointer) {
bungeman@google.come25c6842011-08-17 14:53:54 +0000202 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
bungeman@google.com60157922011-08-13 00:06:17 +0000203 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000204 return hr;
205}
206
207HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
208 , DWORD grfStatFlag)
209{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000210 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000211 return STG_E_INVALIDFLAG;
212 }
halcanary96fcdcc2015-08-27 07:41:13 -0700213 pStatstg->pwcsName = nullptr;
scroggo@google.comb5571b32013-09-25 21:34:24 +0000214 // FIXME: Should not depend on getLength
215 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com9df621d2011-06-23 21:43:52 +0000216 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
217 pStatstg->clsid = CLSID_NULL;
218 pStatstg->type = STGTY_STREAM;
219 pStatstg->grfMode = STGM_READ;
220 return S_OK;
221}
222
223
224/**
225 * SkIWStream
226 */
227SkWIStream::SkWIStream(SkWStream* stream)
228 : SkBaseIStream()
229 , fSkWStream(stream)
230{ }
231
232SkWIStream::~SkWIStream() {
bsalomon49f085d2014-09-05 13:34:00 -0700233 if (this->fSkWStream) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000234 this->fSkWStream->flush();
235 }
236}
237
238HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
239 , IStream ** ppStream)
240{
241 *ppStream = new SkWIStream(stream);
242 return S_OK;
243}
244
245// ISequentialStream Interface
246HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
247 , ULONG cb
248 , ULONG* pcbWritten)
249{
250 HRESULT hr = S_OK;
251 bool wrote = this->fSkWStream->write(pv, cb);
252 if (wrote) {
253 *pcbWritten = cb;
254 } else {
255 *pcbWritten = 0;
256 hr = S_FALSE;
257 }
258 return hr;
259}
260
261// IStream Interface
bungeman@google.com14fc3212011-08-01 20:41:53 +0000262HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
263 this->fSkWStream->flush();
264 return S_OK;
265}
266
bungeman@google.com9df621d2011-06-23 21:43:52 +0000267HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
268 , DWORD grfStatFlag)
269{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000270 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000271 return STG_E_INVALIDFLAG;
272 }
halcanary96fcdcc2015-08-27 07:41:13 -0700273 pStatstg->pwcsName = nullptr;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000274 pStatstg->cbSize.QuadPart = 0;
275 pStatstg->clsid = CLSID_NULL;
276 pStatstg->type = STGTY_STREAM;
277 pStatstg->grfMode = STGM_WRITE;
278 return S_OK;
279}
mtklein1ee76512015-11-02 10:20:27 -0800280#endif//defined(SK_BUILD_FOR_WIN32)