blob: 29e1c87d5343c7ede66f12b80c66042cef4336d0 [file] [log] [blame]
bungeman@google.com9df621d2011-06-23 21:43:52 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#define WIN32_LEAN_AND_MEAN
18#include <Windows.h>
19#include <ole2.h>
20#include "SkIStream.h"
21#include "SkStream.h"
22
23/**
24 * SkBaseIStream
25 */
26SkBaseIStream::SkBaseIStream() : _refcount(1) { }
27SkBaseIStream::~SkBaseIStream() { }
28
29HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
30 , void ** ppvObject)
31{
32 if (NULL == ppvObject) {
33 return E_INVALIDARG;
34 }
35 if (iid == __uuidof(IUnknown)
36 || iid == __uuidof(IStream)
37 || iid == __uuidof(ISequentialStream))
38 {
39 *ppvObject = static_cast<IStream*>(this);
40 AddRef();
41 return S_OK;
42 } else {
43 *ppvObject = NULL;
44 return E_NOINTERFACE;
45 }
46}
47
48ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
49 return (ULONG)InterlockedIncrement(&_refcount);
50}
51
52ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) {
53 ULONG res = (ULONG) InterlockedDecrement(&_refcount);
54 if (0 == res) {
55 delete this;
56 }
57 return res;
58}
59
60// ISequentialStream Interface
61HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
62 , ULONG cb
63 , ULONG* pcbRead)
64{ return E_NOTIMPL; }
65
66HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
67 , ULONG cb
68 , ULONG* pcbWritten)
69{ return E_NOTIMPL; }
70
71// IStream Interface
72HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
73{ return E_NOTIMPL; }
74
75HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
76 , ULARGE_INTEGER
77 , ULARGE_INTEGER*
78 , ULARGE_INTEGER*)
79{ return E_NOTIMPL; }
80
81HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
82{ return E_NOTIMPL; }
83
84HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
85{ return E_NOTIMPL; }
86
87HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
88 , ULARGE_INTEGER
89 , DWORD)
90{ return E_NOTIMPL; }
91
92HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
93 , ULARGE_INTEGER
94 , DWORD)
95{ return E_NOTIMPL; }
96
97HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
98{ return E_NOTIMPL; }
99
100HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
101 , DWORD dwOrigin
102 , ULARGE_INTEGER* lpNewFilePointer)
103{ return E_NOTIMPL; }
104
105HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
106 , DWORD grfStatFlag)
107{ return E_NOTIMPL; }
108
109
110/**
111 * SkIStream
112 */
113SkIStream::SkIStream(SkStream* stream, bool unrefOnRelease)
114 : SkBaseIStream()
115 , fSkStream(stream)
116 , fUnrefOnRelease(unrefOnRelease)
117{ }
118
119SkIStream::~SkIStream() {
120 if (NULL != this->fSkStream && fUnrefOnRelease) {
121 this->fSkStream->unref();
122 }
123}
124
125HRESULT SkIStream::CreateFromSkStream(SkStream* stream
126 , bool unrefOnRelease
127 , IStream ** ppStream)
128{
129 *ppStream = new SkIStream(stream, unrefOnRelease);
130 return S_OK;
131}
132
133// ISequentialStream Interface
134HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
135 *pcbRead = this->fSkStream->read(pv, cb);
136 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{
151 if (lpNewFilePointer != NULL) {
152 (*lpNewFilePointer).QuadPart = NULL;
153 }
154
155 HRESULT hr = S_OK;
156 switch(dwOrigin) {
157 case STREAM_SEEK_SET: {
158 if (!this->fSkStream->rewind()) {
159 hr = E_FAIL;
160 } else {
161 size_t skipped = this->fSkStream->skip(
162 liDistanceToMove.QuadPart
163 );
164 if (skipped != liDistanceToMove.QuadPart) {
165 hr = E_FAIL;
166 }
167 }
168 break;
169 }
170 case STREAM_SEEK_CUR: {
171 size_t skipped = this->fSkStream->skip(liDistanceToMove.QuadPart);
172 if (skipped != liDistanceToMove.QuadPart) {
173 hr = E_FAIL;
174 }
175 break;
176 }
177 case STREAM_SEEK_END: {
178 if (!this->fSkStream->rewind()) {
179 hr = E_FAIL;
180 } else {
181 size_t skipped = this->fSkStream->skip(
182 this->fSkStream->getLength() + liDistanceToMove.QuadPart
183 );
184 if (skipped != liDistanceToMove.QuadPart) {
185 hr = E_FAIL;
186 }
187 }
188 break;
189 }
190 default:
191 hr = STG_E_INVALIDFUNCTION;
192 break;
193 }
194
195 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
251HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
252 , DWORD grfStatFlag)
253{
254 if (0 == grfStatFlag & STATFLAG_NONAME) {
255 return STG_E_INVALIDFLAG;
256 }
257 pStatstg->pwcsName = NULL;
258 pStatstg->cbSize.QuadPart = 0;
259 pStatstg->clsid = CLSID_NULL;
260 pStatstg->type = STGTY_STREAM;
261 pStatstg->grfMode = STGM_WRITE;
262 return S_OK;
263}