blob: 8c9e180b89e3b80ed9479ac5b28e7905b749dfba [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;
37 return E_NOINTERFACE;
38 }
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
65HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
66{ 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(
156 liDistanceToMove.QuadPart
157 );
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: {
166 size_t skipped = this->fSkStream->skip(liDistanceToMove.QuadPart);
bungeman@google.com60157922011-08-13 00:06:17 +0000167 this->fLocation.QuadPart += skipped;
bungeman@google.com9df621d2011-06-23 21:43:52 +0000168 if (skipped != liDistanceToMove.QuadPart) {
169 hr = E_FAIL;
170 }
171 break;
172 }
173 case STREAM_SEEK_END: {
174 if (!this->fSkStream->rewind()) {
175 hr = E_FAIL;
176 } else {
bungeman@google.com60157922011-08-13 00:06:17 +0000177 LONGLONG skip = this->fSkStream->getLength()
178 + liDistanceToMove.QuadPart;
179 size_t skipped = this->fSkStream->skip(skip);
180 this->fLocation.QuadPart = skipped;
181 if (skipped != skip) {
bungeman@google.com9df621d2011-06-23 21:43:52 +0000182 hr = E_FAIL;
183 }
184 }
185 break;
186 }
187 default:
188 hr = STG_E_INVALIDFUNCTION;
189 break;
190 }
191
bungeman@google.come25c6842011-08-17 14:53:54 +0000192 if (NULL != lpNewFilePointer) {
193 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
bungeman@google.com60157922011-08-13 00:06:17 +0000194 }
bungeman@google.com9df621d2011-06-23 21:43:52 +0000195 return hr;
196}
197
198HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
199 , DWORD grfStatFlag)
200{
201 if (0 == grfStatFlag & STATFLAG_NONAME) {
202 return STG_E_INVALIDFLAG;
203 }
204 pStatstg->pwcsName = NULL;
205 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
206 pStatstg->clsid = CLSID_NULL;
207 pStatstg->type = STGTY_STREAM;
208 pStatstg->grfMode = STGM_READ;
209 return S_OK;
210}
211
212
213/**
214 * SkIWStream
215 */
216SkWIStream::SkWIStream(SkWStream* stream)
217 : SkBaseIStream()
218 , fSkWStream(stream)
219{ }
220
221SkWIStream::~SkWIStream() {
222 if (NULL != this->fSkWStream) {
223 this->fSkWStream->flush();
224 }
225}
226
227HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
228 , IStream ** ppStream)
229{
230 *ppStream = new SkWIStream(stream);
231 return S_OK;
232}
233
234// ISequentialStream Interface
235HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
236 , ULONG cb
237 , ULONG* pcbWritten)
238{
239 HRESULT hr = S_OK;
240 bool wrote = this->fSkWStream->write(pv, cb);
241 if (wrote) {
242 *pcbWritten = cb;
243 } else {
244 *pcbWritten = 0;
245 hr = S_FALSE;
246 }
247 return hr;
248}
249
250// IStream Interface
bungeman@google.com14fc3212011-08-01 20:41:53 +0000251HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
252 this->fSkWStream->flush();
253 return S_OK;
254}
255
bungeman@google.com9df621d2011-06-23 21:43:52 +0000256HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
257 , DWORD grfStatFlag)
258{
259 if (0 == grfStatFlag & STATFLAG_NONAME) {
260 return STG_E_INVALIDFLAG;
261 }
262 pStatstg->pwcsName = NULL;
263 pStatstg->cbSize.QuadPart = 0;
264 pStatstg->clsid = CLSID_NULL;
265 pStatstg->type = STGTY_STREAM;
266 pStatstg->grfMode = STGM_WRITE;
267 return S_OK;
268}