blob: 6274e717a2065dd7e7e87102a355c632982ab9f8 [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
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bungeman@google.com9df621d2011-06-23 21:43:52 +000010#define WIN32_LEAN_AND_MEAN
bungeman@google.com0d9e3da2013-12-03 15:23:37 +000011#include <windows.h>
bungeman@google.com9df621d2011-06-23 21:43:52 +000012#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;
rmistry@google.comd6176b02012-08-23 18:14:13 +000037 return E_NOINTERFACE;
bungeman@google.com9df621d2011-06-23 21:43:52 +000038 }
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
rmistry@google.comd6176b02012-08-23 18:14:13 +000065HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
bungeman@google.com9df621d2011-06-23 21:43:52 +000066{ 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)
bungeman@google.com60157922011-08-13 00:06:17 +0000110 , fLocation()
111{
112 this->fSkStream->rewind();
113}
bungeman@google.com9df621d2011-06-23 21:43:52 +0000114
115SkIStream::~SkIStream() {
bsalomon49f085d2014-09-05 13:34:00 -0700116 if (this->fSkStream && fUnrefOnRelease) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000117 this->fSkStream->unref();
118 }
119}
120
121HRESULT SkIStream::CreateFromSkStream(SkStream* stream
122 , bool unrefOnRelease
123 , IStream ** ppStream)
124{
bungeman@google.com635091f2013-10-01 15:03:18 +0000125 if (NULL == stream) {
126 return E_INVALIDARG;
127 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000128 *ppStream = new SkIStream(stream, unrefOnRelease);
129 return S_OK;
130}
131
132// ISequentialStream Interface
133HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
bungeman@google.com4b18f572013-07-22 15:21:23 +0000134 *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
bungeman@google.com60157922011-08-13 00:06:17 +0000135 this->fLocation.QuadPart += *pcbRead;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000136 return (*pcbRead == cb) ? S_OK : S_FALSE;
137}
138
139HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
140 , ULONG cb
141 , ULONG* pcbWritten)
142{
143 return STG_E_CANTSAVE;
144}
145
146// IStream Interface
147HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
148 , DWORD dwOrigin
149 , ULARGE_INTEGER* lpNewFilePointer)
150{
bungeman@google.com9df621d2011-06-23 21:43:52 +0000151 HRESULT hr = S_OK;
bungeman@google.com60157922011-08-13 00:06:17 +0000152
bungeman@google.com9df621d2011-06-23 21:43:52 +0000153 switch(dwOrigin) {
154 case STREAM_SEEK_SET: {
155 if (!this->fSkStream->rewind()) {
156 hr = E_FAIL;
157 } else {
158 size_t skipped = this->fSkStream->skip(
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000159 static_cast<size_t>(liDistanceToMove.QuadPart)
bungeman@google.com9df621d2011-06-23 21:43:52 +0000160 );
bungeman@google.com60157922011-08-13 00:06:17 +0000161 this->fLocation.QuadPart = skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000162 if (skipped != liDistanceToMove.QuadPart) {
163 hr = E_FAIL;
164 }
165 }
166 break;
167 }
168 case STREAM_SEEK_CUR: {
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000169 size_t skipped = this->fSkStream->skip(
170 static_cast<size_t>(liDistanceToMove.QuadPart)
171 );
bungeman@google.com60157922011-08-13 00:06:17 +0000172 this->fLocation.QuadPart += skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000173 if (skipped != liDistanceToMove.QuadPart) {
174 hr = E_FAIL;
175 }
176 break;
177 }
178 case STREAM_SEEK_END: {
179 if (!this->fSkStream->rewind()) {
180 hr = E_FAIL;
181 } else {
scroggo@google.comb5571b32013-09-25 21:34:24 +0000182 // FIXME: Should not depend on getLength.
183 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com60157922011-08-13 00:06:17 +0000184 LONGLONG skip = this->fSkStream->getLength()
185 + liDistanceToMove.QuadPart;
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000186 size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
bungeman@google.com60157922011-08-13 00:06:17 +0000187 this->fLocation.QuadPart = skipped;
188 if (skipped != skip) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000189 hr = E_FAIL;
190 }
191 }
192 break;
193 }
194 default:
195 hr = STG_E_INVALIDFUNCTION;
196 break;
197 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000198
bsalomon49f085d2014-09-05 13:34:00 -0700199 if (lpNewFilePointer) {
bungeman@google.come25c6842011-08-17 14:53:54 +0000200 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
bungeman@google.com60157922011-08-13 00:06:17 +0000201 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000202 return hr;
203}
204
205HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
206 , DWORD grfStatFlag)
207{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000208 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000209 return STG_E_INVALIDFLAG;
210 }
211 pStatstg->pwcsName = NULL;
scroggo@google.comb5571b32013-09-25 21:34:24 +0000212 // FIXME: Should not depend on getLength
213 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com9df621d2011-06-23 21:43:52 +0000214 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
215 pStatstg->clsid = CLSID_NULL;
216 pStatstg->type = STGTY_STREAM;
217 pStatstg->grfMode = STGM_READ;
218 return S_OK;
219}
220
221
222/**
223 * SkIWStream
224 */
225SkWIStream::SkWIStream(SkWStream* stream)
226 : SkBaseIStream()
227 , fSkWStream(stream)
228{ }
229
230SkWIStream::~SkWIStream() {
bsalomon49f085d2014-09-05 13:34:00 -0700231 if (this->fSkWStream) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000232 this->fSkWStream->flush();
233 }
234}
235
236HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
237 , IStream ** ppStream)
238{
239 *ppStream = new SkWIStream(stream);
240 return S_OK;
241}
242
243// ISequentialStream Interface
244HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
245 , ULONG cb
246 , ULONG* pcbWritten)
247{
248 HRESULT hr = S_OK;
249 bool wrote = this->fSkWStream->write(pv, cb);
250 if (wrote) {
251 *pcbWritten = cb;
252 } else {
253 *pcbWritten = 0;
254 hr = S_FALSE;
255 }
256 return hr;
257}
258
259// IStream Interface
bungeman@google.com14fc3212011-08-01 20:41:53 +0000260HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
261 this->fSkWStream->flush();
262 return S_OK;
263}
264
bungeman@google.com9df621d2011-06-23 21:43:52 +0000265HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
266 , DWORD grfStatFlag)
267{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000268 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000269 return STG_E_INVALIDFLAG;
270 }
271 pStatstg->pwcsName = NULL;
272 pStatstg->cbSize.QuadPart = 0;
273 pStatstg->clsid = CLSID_NULL;
274 pStatstg->type = STGTY_STREAM;
275 pStatstg->grfMode = STGM_WRITE;
276 return S_OK;
277}