blob: a857f40e7df4af9ae786627f5563ff35ba1f2ca2 [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)
110{ }
111
112SkIStream::~SkIStream() {
113 if (NULL != this->fSkStream && fUnrefOnRelease) {
114 this->fSkStream->unref();
115 }
116}
117
118HRESULT SkIStream::CreateFromSkStream(SkStream* stream
119 , bool unrefOnRelease
120 , IStream ** ppStream)
121{
122 *ppStream = new SkIStream(stream, unrefOnRelease);
123 return S_OK;
124}
125
126// ISequentialStream Interface
127HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
128 *pcbRead = this->fSkStream->read(pv, cb);
129 return (*pcbRead == cb) ? S_OK : S_FALSE;
130}
131
132HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
133 , ULONG cb
134 , ULONG* pcbWritten)
135{
136 return STG_E_CANTSAVE;
137}
138
139// IStream Interface
140HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
141 , DWORD dwOrigin
142 , ULARGE_INTEGER* lpNewFilePointer)
143{
144 if (lpNewFilePointer != NULL) {
145 (*lpNewFilePointer).QuadPart = NULL;
146 }
147
148 HRESULT hr = S_OK;
149 switch(dwOrigin) {
150 case STREAM_SEEK_SET: {
151 if (!this->fSkStream->rewind()) {
152 hr = E_FAIL;
153 } else {
154 size_t skipped = this->fSkStream->skip(
155 liDistanceToMove.QuadPart
156 );
157 if (skipped != liDistanceToMove.QuadPart) {
158 hr = E_FAIL;
159 }
160 }
161 break;
162 }
163 case STREAM_SEEK_CUR: {
164 size_t skipped = this->fSkStream->skip(liDistanceToMove.QuadPart);
165 if (skipped != liDistanceToMove.QuadPart) {
166 hr = E_FAIL;
167 }
168 break;
169 }
170 case STREAM_SEEK_END: {
171 if (!this->fSkStream->rewind()) {
172 hr = E_FAIL;
173 } else {
174 size_t skipped = this->fSkStream->skip(
175 this->fSkStream->getLength() + liDistanceToMove.QuadPart
176 );
177 if (skipped != liDistanceToMove.QuadPart) {
178 hr = E_FAIL;
179 }
180 }
181 break;
182 }
183 default:
184 hr = STG_E_INVALIDFUNCTION;
185 break;
186 }
187
188 return hr;
189}
190
191HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
192 , DWORD grfStatFlag)
193{
194 if (0 == grfStatFlag & STATFLAG_NONAME) {
195 return STG_E_INVALIDFLAG;
196 }
197 pStatstg->pwcsName = NULL;
198 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
199 pStatstg->clsid = CLSID_NULL;
200 pStatstg->type = STGTY_STREAM;
201 pStatstg->grfMode = STGM_READ;
202 return S_OK;
203}
204
205
206/**
207 * SkIWStream
208 */
209SkWIStream::SkWIStream(SkWStream* stream)
210 : SkBaseIStream()
211 , fSkWStream(stream)
212{ }
213
214SkWIStream::~SkWIStream() {
215 if (NULL != this->fSkWStream) {
216 this->fSkWStream->flush();
217 }
218}
219
220HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
221 , IStream ** ppStream)
222{
223 *ppStream = new SkWIStream(stream);
224 return S_OK;
225}
226
227// ISequentialStream Interface
228HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
229 , ULONG cb
230 , ULONG* pcbWritten)
231{
232 HRESULT hr = S_OK;
233 bool wrote = this->fSkWStream->write(pv, cb);
234 if (wrote) {
235 *pcbWritten = cb;
236 } else {
237 *pcbWritten = 0;
238 hr = S_FALSE;
239 }
240 return hr;
241}
242
243// IStream Interface
244HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
245 , DWORD grfStatFlag)
246{
247 if (0 == grfStatFlag & STATFLAG_NONAME) {
248 return STG_E_INVALIDFLAG;
249 }
250 pStatstg->pwcsName = NULL;
251 pStatstg->cbSize.QuadPart = 0;
252 pStatstg->clsid = CLSID_NULL;
253 pStatstg->type = STGTY_STREAM;
254 pStatstg->grfMode = STGM_WRITE;
255 return S_OK;
256}