blob: 5672ff50126cf4be1bb8ec3cebc9dca89eec6710 [file] [log] [blame]
Tony Wasserkaa18fc6e2009-08-18 17:48:49 +02001/*
2 * Copyright 2009 Tony Wasserka
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "wine/debug.h"
20
21#define COBJMACROS
22#include "windef.h"
23#include "winbase.h"
24#include "winreg.h"
25#include "objbase.h"
26#include "wincodec.h"
27#include "wincodecs_private.h"
28
29WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
30
31/******************************************
Tony Wasserkaaf6ece92009-08-21 12:02:10 +020032 * StreamOnMemory implementation
33 *
34 * Used by IWICStream_InitializeFromMemory
35 *
36 */
37typedef struct StreamOnMemory {
38 const IStreamVtbl *lpVtbl;
39 LONG ref;
Tony Wasserkabb83fb22009-08-21 11:07:37 +020040
41 BYTE *pbMemory;
42 DWORD dwMemsize;
43 DWORD dwCurPos;
Tony Wasserkaaf6ece92009-08-21 12:02:10 +020044} StreamOnMemory;
45
46static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
47 REFIID iid, void **ppv)
48{
49 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
50
51 if (!ppv) return E_INVALIDARG;
52
53 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
54 IsEqualIID(&IID_ISequentialStream, iid))
55 {
56 *ppv = iface;
57 IUnknown_AddRef((IUnknown*)*ppv);
58 return S_OK;
59 }
60 else
61 {
62 *ppv = NULL;
63 return E_NOINTERFACE;
64 }
65}
66
67static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
68{
69 StreamOnMemory *This = (StreamOnMemory*)iface;
70 ULONG ref = InterlockedIncrement(&This->ref);
71
72 TRACE("(%p) refcount=%u\n", iface, ref);
73
74 return ref;
75}
76
77static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
78{
79 StreamOnMemory *This = (StreamOnMemory*)iface;
80 ULONG ref = InterlockedDecrement(&This->ref);
81
82 TRACE("(%p) refcount=%u\n", iface, ref);
83
84 if (ref == 0) {
85 HeapFree(GetProcessHeap(), 0, This);
86 }
87 return ref;
88}
89
90static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
91 void *pv, ULONG cb, ULONG *pcbRead)
92{
Tony Wasserkabb83fb22009-08-21 11:07:37 +020093 StreamOnMemory *This = (StreamOnMemory*)iface;
94 ULONG uBytesRead;
95 TRACE("(%p)\n", This);
96
97 if (!pv) return E_INVALIDARG;
98
99 uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
100 memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
101 This->dwCurPos += uBytesRead;
102 if (pcbRead) *pcbRead = uBytesRead;
103
104 return S_OK;
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200105}
106
107static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
108 void const *pv, ULONG cb, ULONG *pcbWritten)
109{
Tony Wasserka0b6df192009-08-21 11:08:10 +0200110 StreamOnMemory *This = (StreamOnMemory*)iface;
111 TRACE("(%p)\n", This);
112
113 if (!pv) return E_INVALIDARG;
114
115 if (cb > This->dwMemsize - This->dwCurPos) return STG_E_MEDIUMFULL;
116 if (cb) {
117 memcpy(This->pbMemory + This->dwCurPos, pv, cb);
118 This->dwCurPos += cb;
119 }
120 if (pcbWritten) *pcbWritten = cb;
121
122 return S_OK;
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200123}
124
125static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
126 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
127{
Tony Wasserka23952022009-08-21 11:11:39 +0200128 StreamOnMemory *This = (StreamOnMemory*)iface;
129 LARGE_INTEGER NewPosition;
130 TRACE("(%p)\n", This);
131
132 if (dlibMove.QuadPart > 0xFFFFFFFF) return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
133
134 if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
135 else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
136 else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
137 else return E_INVALIDARG;
138
139 if (NewPosition.QuadPart > This->dwMemsize) return E_INVALIDARG;
140 if (NewPosition.QuadPart < 0) return E_INVALIDARG;
Francois Gouget2dd9b1d2009-08-31 11:52:57 +0200141 This->dwCurPos = NewPosition.u.LowPart;
Tony Wasserka23952022009-08-21 11:11:39 +0200142
143 if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
144 return S_OK;
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200145}
146
147/* SetSize isn't implemented in the native windowscodecs DLL either */
148static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
149 ULARGE_INTEGER libNewSize)
150{
151 TRACE("(%p)\n", iface);
152 return E_NOTIMPL;
153}
154
155/* CopyTo isn't implemented in the native windowscodecs DLL either */
156static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
157 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
158{
159 TRACE("(%p)\n", iface);
160 return E_NOTIMPL;
161}
162
163/* Commit isn't implemented in the native windowscodecs DLL either */
164static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
165 DWORD grfCommitFlags)
166{
167 TRACE("(%p)\n", iface);
168 return E_NOTIMPL;
169}
170
171/* Revert isn't implemented in the native windowscodecs DLL either */
172static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
173{
174 TRACE("(%p)\n", iface);
175 return E_NOTIMPL;
176}
177
178/* LockRegion isn't implemented in the native windowscodecs DLL either */
179static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
180 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
181{
182 TRACE("(%p)\n", iface);
183 return E_NOTIMPL;
184}
185
186/* UnlockRegion isn't implemented in the native windowscodecs DLL either */
187static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
188 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
189{
190 TRACE("(%p)\n", iface);
191 return E_NOTIMPL;
192}
193
194static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
195 STATSTG *pstatstg, DWORD grfStatFlag)
196{
Tony Wasserkaa3edb732009-08-21 11:12:03 +0200197 StreamOnMemory *This = (StreamOnMemory*)iface;
198 TRACE("(%p)\n", This);
199
200 if (!pstatstg) return E_INVALIDARG;
201
202 ZeroMemory(pstatstg, sizeof(STATSTG));
203 pstatstg->type = STGTY_STREAM;
204 pstatstg->cbSize.QuadPart = This->dwMemsize;
205
206 return S_OK;
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200207}
208
209/* Clone isn't implemented in the native windowscodecs DLL either */
210static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
211 IStream **ppstm)
212{
213 TRACE("(%p)\n", iface);
214 return E_NOTIMPL;
215}
216
217
218const IStreamVtbl StreamOnMemory_Vtbl =
219{
220 /*** IUnknown methods ***/
221 StreamOnMemory_QueryInterface,
222 StreamOnMemory_AddRef,
223 StreamOnMemory_Release,
224 /*** ISequentialStream methods ***/
225 StreamOnMemory_Read,
226 StreamOnMemory_Write,
227 /*** IStream methods ***/
228 StreamOnMemory_Seek,
229 StreamOnMemory_SetSize,
230 StreamOnMemory_CopyTo,
231 StreamOnMemory_Commit,
232 StreamOnMemory_Revert,
233 StreamOnMemory_LockRegion,
234 StreamOnMemory_UnlockRegion,
235 StreamOnMemory_Stat,
236 StreamOnMemory_Clone,
237};
238
239/******************************************
Tony Wasserkaa18fc6e2009-08-18 17:48:49 +0200240 * IWICStream implementation
241 *
242 */
243typedef struct IWICStreamImpl
244{
245 const IWICStreamVtbl *lpVtbl;
246 LONG ref;
247
248 IStream *pStream;
249} IWICStreamImpl;
250
251static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
252 REFIID iid, void **ppv)
253{
254 IWICStreamImpl *This = (IWICStreamImpl*)iface;
255 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
256
257 if (!ppv) return E_INVALIDARG;
258
259 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
260 IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
261 {
262 *ppv = This;
263 IUnknown_AddRef((IUnknown*)*ppv);
264 return S_OK;
265 }
266 else
267 {
268 *ppv = NULL;
269 return E_NOINTERFACE;
270 }
271}
272
273static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
274{
275 IWICStreamImpl *This = (IWICStreamImpl*)iface;
276 ULONG ref = InterlockedIncrement(&This->ref);
277
278 TRACE("(%p) refcount=%u\n", iface, ref);
279
280 return ref;
281}
282
283static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
284{
285 IWICStreamImpl *This = (IWICStreamImpl*)iface;
286 ULONG ref = InterlockedDecrement(&This->ref);
287
288 TRACE("(%p) refcount=%u\n", iface, ref);
289
290 if (ref == 0) {
291 if (This->pStream) IStream_Release(This->pStream);
292 HeapFree(GetProcessHeap(), 0, This);
293 }
294 return ref;
295}
296
297static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
298 void *pv, ULONG cb, ULONG *pcbRead)
299{
300 IWICStreamImpl *This = (IWICStreamImpl*)iface;
301 TRACE("(%p): relay\n", This);
302
303 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
304 return IStream_Read(This->pStream, pv, cb, pcbRead);
305}
306
307static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
308 void const *pv, ULONG cb, ULONG *pcbWritten)
309{
310 IWICStreamImpl *This = (IWICStreamImpl*)iface;
311 TRACE("(%p): relay\n", This);
312
313 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
314 return IStream_Write(This->pStream, pv, cb, pcbWritten);
315}
316
317static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
318 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
319{
320 IWICStreamImpl *This = (IWICStreamImpl*)iface;
321 TRACE("(%p): relay\n", This);
322
323 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
324 return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
325}
326
327static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
328 ULARGE_INTEGER libNewSize)
329{
330 IWICStreamImpl *This = (IWICStreamImpl*)iface;
331 TRACE("(%p): relay\n", This);
332
333 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
334 return IStream_SetSize(This->pStream, libNewSize);
335}
336
337static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
338 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
339{
340 IWICStreamImpl *This = (IWICStreamImpl*)iface;
341 TRACE("(%p): relay\n", This);
342
343 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
344 return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
345}
346
347static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
348 DWORD grfCommitFlags)
349{
350 IWICStreamImpl *This = (IWICStreamImpl*)iface;
351 TRACE("(%p): relay\n", This);
352
353 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
354 return IStream_Commit(This->pStream, grfCommitFlags);
355}
356
357static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
358{
359 IWICStreamImpl *This = (IWICStreamImpl*)iface;
360 TRACE("(%p): relay\n", This);
361
362 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
363 return IStream_Revert(This->pStream);
364}
365
366static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
367 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
368{
369 IWICStreamImpl *This = (IWICStreamImpl*)iface;
370 TRACE("(%p): relay\n", This);
371
372 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
373 return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
374}
375
376static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
377 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
378{
379 IWICStreamImpl *This = (IWICStreamImpl*)iface;
380 TRACE("(%p): relay\n", This);
381
382 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
383 return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
384}
385
386static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
387 STATSTG *pstatstg, DWORD grfStatFlag)
388{
389 IWICStreamImpl *This = (IWICStreamImpl*)iface;
390 TRACE("(%p): relay\n", This);
391
392 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
393 return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
394}
395
396static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
397 IStream **ppstm)
398{
399 IWICStreamImpl *This = (IWICStreamImpl*)iface;
400 TRACE("(%p): relay\n", This);
401
402 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
403 return IStream_Clone(This->pStream, ppstm);
404}
405
406static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
407 IStream *pIStream)
408{
409 FIXME("(%p): stub\n", iface);
410 return E_NOTIMPL;
411}
412
413static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
414 LPCWSTR wzFileName, DWORD dwDesiredAccess)
415{
416 FIXME("(%p): stub\n", iface);
417 return E_NOTIMPL;
418}
419
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200420/******************************************
421 * IWICStream_InitializeFromMemory
422 *
423 * Initializes the internal IStream object to retrieve its data from a memory chunk.
424 *
425 * PARAMS
426 * pbBuffer [I] pointer to the memory chunk
427 * cbBufferSize [I] number of bytes to use from the memory chunk
428 *
429 * RETURNS
430 * SUCCESS: S_OK
431 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
432 * E_OUTOFMEMORY, if we run out of memory
433 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
434 *
435 */
Tony Wasserkaa18fc6e2009-08-18 17:48:49 +0200436static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
437 BYTE *pbBuffer, DWORD cbBufferSize)
438{
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200439 IWICStreamImpl *This = (IWICStreamImpl*)iface;
440 StreamOnMemory *pObject;
441 TRACE("(%p,%p)\n", iface, pbBuffer);
442
443 if (!pbBuffer) return E_INVALIDARG;
444 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
445
446 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
447 if (!pObject) return E_OUTOFMEMORY;
448
449 pObject->lpVtbl = &StreamOnMemory_Vtbl;
450 pObject->ref = 1;
Tony Wasserkabb83fb22009-08-21 11:07:37 +0200451 pObject->pbMemory = pbBuffer;
452 pObject->dwMemsize = cbBufferSize;
453 pObject->dwCurPos = 0;
Tony Wasserkaaf6ece92009-08-21 12:02:10 +0200454
455 This->pStream = (IStream*)pObject;
456 return S_OK;
Tony Wasserkaa18fc6e2009-08-18 17:48:49 +0200457}
458
459static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
460 IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
461{
462 FIXME("(%p): stub\n", iface);
463 return E_NOTIMPL;
464}
465
466
467const IWICStreamVtbl WICStream_Vtbl =
468{
469 /*** IUnknown methods ***/
470 IWICStreamImpl_QueryInterface,
471 IWICStreamImpl_AddRef,
472 IWICStreamImpl_Release,
473 /*** ISequentialStream methods ***/
474 IWICStreamImpl_Read,
475 IWICStreamImpl_Write,
476 /*** IStream methods ***/
477 IWICStreamImpl_Seek,
478 IWICStreamImpl_SetSize,
479 IWICStreamImpl_CopyTo,
480 IWICStreamImpl_Commit,
481 IWICStreamImpl_Revert,
482 IWICStreamImpl_LockRegion,
483 IWICStreamImpl_UnlockRegion,
484 IWICStreamImpl_Stat,
485 IWICStreamImpl_Clone,
486 /*** IWICStream methods ***/
487 IWICStreamImpl_InitializeFromIStream,
488 IWICStreamImpl_InitializeFromFilename,
489 IWICStreamImpl_InitializeFromMemory,
490 IWICStreamImpl_InitializeFromIStreamRegion,
491};
492
493HRESULT StreamImpl_Create(IWICStream **stream)
494{
495 IWICStreamImpl *pObject;
496
497 if( !stream ) return E_INVALIDARG;
498
499 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
500 if( !pObject ) {
501 *stream = NULL;
502 return E_OUTOFMEMORY;
503 }
504
505 pObject->lpVtbl = &WICStream_Vtbl;
506 pObject->ref = 1;
507 pObject->pStream = NULL;
508
509 *stream = (IWICStream*)pObject;
510
511 return S_OK;
512}