blob: 1d00611f79ce7d19b2f80ee9d630b19b30de4a65 [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) {
131 *pcbRead = 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 {
bungeman@google.com60157922011-08-13 00:06:17 +0000179 LONGLONG skip = this->fSkStream->getLength()
180 + liDistanceToMove.QuadPart;
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000181 size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
bungeman@google.com60157922011-08-13 00:06:17 +0000182 this->fLocation.QuadPart = skipped;
183 if (skipped != skip) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000184 hr = E_FAIL;
185 }
186 }
187 break;
188 }
189 default:
190 hr = STG_E_INVALIDFUNCTION;
191 break;
192 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000193
bungeman@google.come25c6842011-08-17 14:53:54 +0000194 if (NULL != lpNewFilePointer) {
195 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
bungeman@google.com60157922011-08-13 00:06:17 +0000196 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000197 return hr;
198}
199
200HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
201 , DWORD grfStatFlag)
202{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000203 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000204 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
bungeman@google.com14fc3212011-08-01 20:41:53 +0000253HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
254 this->fSkWStream->flush();
255 return S_OK;
256}
257
bungeman@google.com9df621d2011-06-23 21:43:52 +0000258HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
259 , DWORD grfStatFlag)
260{
bsalomon@google.com9d12f5c2011-09-29 18:08:18 +0000261 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000262 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}