blob: 182d9a8caab1bd6594ef36727194e4b8db0b1739 [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
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;
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() {
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) {
bungeman@google.com4b18f572013-07-22 15:21:23 +0000131 *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
bungeman@google.com60157922011-08-13 00:06:17 +0000132 this->fLocation.QuadPart += *pcbRead;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000133 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{
bungeman@google.com9df621d2011-06-23 21:43:52 +0000148 HRESULT hr = S_OK;
bungeman@google.com60157922011-08-13 00:06:17 +0000149
bungeman@google.com9df621d2011-06-23 21:43:52 +0000150 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(
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000156 static_cast<size_t>(liDistanceToMove.QuadPart)
bungeman@google.com9df621d2011-06-23 21:43:52 +0000157 );
bungeman@google.com60157922011-08-13 00:06:17 +0000158 this->fLocation.QuadPart = skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000159 if (skipped != liDistanceToMove.QuadPart) {
160 hr = E_FAIL;
161 }
162 }
163 break;
164 }
165 case STREAM_SEEK_CUR: {
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000166 size_t skipped = this->fSkStream->skip(
167 static_cast<size_t>(liDistanceToMove.QuadPart)
168 );
bungeman@google.com60157922011-08-13 00:06:17 +0000169 this->fLocation.QuadPart += skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000170 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 {
scroggo@google.comb5571b32013-09-25 21:34:24 +0000179 // FIXME: Should not depend on getLength.
180 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com60157922011-08-13 00:06:17 +0000181 LONGLONG skip = this->fSkStream->getLength()
182 + liDistanceToMove.QuadPart;
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000183 size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
bungeman@google.com60157922011-08-13 00:06:17 +0000184 this->fLocation.QuadPart = skipped;
185 if (skipped != skip) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000186 hr = E_FAIL;
187 }
188 }
189 break;
190 }
191 default:
192 hr = STG_E_INVALIDFUNCTION;
193 break;
194 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000195
bungeman@google.come25c6842011-08-17 14:53:54 +0000196 if (NULL != lpNewFilePointer) {
197 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
bungeman@google.com60157922011-08-13 00:06:17 +0000198 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000199 return hr;
200}
201
202HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
203 , DWORD grfStatFlag)
204{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000205 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000206 return STG_E_INVALIDFLAG;
207 }
208 pStatstg->pwcsName = NULL;
scroggo@google.comb5571b32013-09-25 21:34:24 +0000209 // FIXME: Should not depend on getLength
210 // See https://code.google.com/p/skia/issues/detail?id=1570
bungeman@google.com9df621d2011-06-23 21:43:52 +0000211 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
212 pStatstg->clsid = CLSID_NULL;
213 pStatstg->type = STGTY_STREAM;
214 pStatstg->grfMode = STGM_READ;
215 return S_OK;
216}
217
218
219/**
220 * SkIWStream
221 */
222SkWIStream::SkWIStream(SkWStream* stream)
223 : SkBaseIStream()
224 , fSkWStream(stream)
225{ }
226
227SkWIStream::~SkWIStream() {
228 if (NULL != this->fSkWStream) {
229 this->fSkWStream->flush();
230 }
231}
232
233HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
234 , IStream ** ppStream)
235{
236 *ppStream = new SkWIStream(stream);
237 return S_OK;
238}
239
240// ISequentialStream Interface
241HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
242 , ULONG cb
243 , ULONG* pcbWritten)
244{
245 HRESULT hr = S_OK;
246 bool wrote = this->fSkWStream->write(pv, cb);
247 if (wrote) {
248 *pcbWritten = cb;
249 } else {
250 *pcbWritten = 0;
251 hr = S_FALSE;
252 }
253 return hr;
254}
255
256// IStream Interface
bungeman@google.com14fc3212011-08-01 20:41:53 +0000257HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
258 this->fSkWStream->flush();
259 return S_OK;
260}
261
bungeman@google.com9df621d2011-06-23 21:43:52 +0000262HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
263 , DWORD grfStatFlag)
264{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000265 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000266 return STG_E_INVALIDFLAG;
267 }
268 pStatstg->pwcsName = NULL;
269 pStatstg->cbSize.QuadPart = 0;
270 pStatstg->clsid = CLSID_NULL;
271 pStatstg->type = STGTY_STREAM;
272 pStatstg->grfMode = STGM_WRITE;
273 return S_OK;
274}