1 /*
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 "shlwapi.h"
27 #include "wincodec.h"
28 #include "wincodecs_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
31
32 /******************************************
33 * StreamOnMemory implementation
34 *
35 * Used by IWICStream_InitializeFromMemory
36 *
37 */
38 typedef struct StreamOnMemory {
39 IStream IStream_iface;
40 LONG ref;
41
42 BYTE *pbMemory;
43 DWORD dwMemsize;
44 DWORD dwCurPos;
45
46 CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */
47 } StreamOnMemory;
48
49 static inline StreamOnMemory *StreamOnMemory_from_IStream(IStream *iface)
50 {
51 return CONTAINING_RECORD(iface, StreamOnMemory, IStream_iface);
52 }
53
54 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
55 REFIID iid, void **ppv)
56 {
57 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
58
59 if (!ppv) return E_INVALIDARG;
60
61 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
62 IsEqualIID(&IID_ISequentialStream, iid))
63 {
64 *ppv = iface;
65 IUnknown_AddRef((IUnknown*)*ppv);
66 return S_OK;
67 }
68 else
69 {
70 *ppv = NULL;
71 return E_NOINTERFACE;
72 }
73 }
74
75 static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
76 {
77 StreamOnMemory *This = StreamOnMemory_from_IStream(iface);
78 ULONG ref = InterlockedIncrement(&This->ref);
79
80 TRACE("(%p) refcount=%u\n", iface, ref);
81
82 return ref;
83 }
84
85 static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
86 {
87 StreamOnMemory *This = StreamOnMemory_from_IStream(iface);
88 ULONG ref = InterlockedDecrement(&This->ref);
89
90 TRACE("(%p) refcount=%u\n", iface, ref);
91
92 if (ref == 0) {
93 This->lock.DebugInfo->Spare[0] = 0;
94 DeleteCriticalSection(&This->lock);
95 HeapFree(GetProcessHeap(), 0, This);
96 }
97 return ref;
98 }
99
100 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
101 void *pv, ULONG cb, ULONG *pcbRead)
102 {
103 StreamOnMemory *This = StreamOnMemory_from_IStream(iface);
104 ULONG uBytesRead;
105 TRACE("(%p)\n", This);
106
107 if (!pv) return E_INVALIDARG;
108
109 EnterCriticalSection(&This->lock);
110 uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
111 memmove(pv, This->pbMemory + This->dwCurPos, uBytesRead);
112 This->dwCurPos += uBytesRead;
113 LeaveCriticalSection(&This->lock);
114
115 if (pcbRead) *pcbRead = uBytesRead;
116
117 return S_OK;
118 }
119
120 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
121 void const *pv, ULONG cb, ULONG *pcbWritten)
122 {
123 StreamOnMemory *This = StreamOnMemory_from_IStream(iface);
124 HRESULT hr;
125 TRACE("(%p)\n", This);
126
127 if (!pv) return E_INVALIDARG;
128
129 EnterCriticalSection(&This->lock);
130 if (cb > This->dwMemsize - This->dwCurPos) {
131 hr = STG_E_MEDIUMFULL;
132 }
133 else {
134 memmove(This->pbMemory + This->dwCurPos, pv, cb);
135 This->dwCurPos += cb;
136 hr = S_OK;
137 if (pcbWritten) *pcbWritten = cb;
138 }
139 LeaveCriticalSection(&This->lock);
140
141 return hr;
142 }
143
144 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
145 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
146 {
147 StreamOnMemory *This = StreamOnMemory_from_IStream(iface);
148 LARGE_INTEGER NewPosition;
149 HRESULT hr=S_OK;
150 TRACE("(%p)\n", This);
151
152 EnterCriticalSection(&This->lock);
153 if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
154 else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
155 else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
156 else hr = E_INVALIDARG;
157
158 if (SUCCEEDED(hr)) {
159 if (NewPosition.u.HighPart) hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
160 else if (NewPosition.QuadPart > This->dwMemsize) hr = E_INVALIDARG;
161 else if (NewPosition.QuadPart < 0) hr = E_INVALIDARG;
162 }
163
164 if (SUCCEEDED(hr)) {
165 This->dwCurPos = NewPosition.u.LowPart;
166
167 if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
168 }
169 LeaveCriticalSection(&This->lock);
170
171 return hr;
172 }
173
174 /* SetSize isn't implemented in the native windowscodecs DLL either */
175 static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
176 ULARGE_INTEGER libNewSize)
177 {
178 TRACE("(%p)\n", iface);
179 return E_NOTIMPL;
180 }
181
182 /* CopyTo isn't implemented in the native windowscodecs DLL either */
183 static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
184 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
185 {
186 TRACE("(%p)\n", iface);
187 return E_NOTIMPL;
188 }
189
190 /* Commit isn't implemented in the native windowscodecs DLL either */
191 static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
192 DWORD grfCommitFlags)
193 {
194 TRACE("(%p)\n", iface);
195 return E_NOTIMPL;
196 }
197
198 /* Revert isn't implemented in the native windowscodecs DLL either */
199 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
200 {
201 TRACE("(%p)\n", iface);
202 return E_NOTIMPL;
203 }
204
205 /* LockRegion isn't implemented in the native windowscodecs DLL either */
206 static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
207 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
208 {
209 TRACE("(%p)\n", iface);
210 return E_NOTIMPL;
211 }
212
213 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
214 static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
215 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
216 {
217 TRACE("(%p)\n", iface);
218 return E_NOTIMPL;
219 }
220
221 static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
222 STATSTG *pstatstg, DWORD grfStatFlag)
223 {
224 StreamOnMemory *This = StreamOnMemory_from_IStream(iface);
225 TRACE("(%p)\n", This);
226
227 if (!pstatstg) return E_INVALIDARG;
228
229 ZeroMemory(pstatstg, sizeof(STATSTG));
230 pstatstg->type = STGTY_STREAM;
231 pstatstg->cbSize.QuadPart = This->dwMemsize;
232
233 return S_OK;
234 }
235
236 /* Clone isn't implemented in the native windowscodecs DLL either */
237 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
238 IStream **ppstm)
239 {
240 TRACE("(%p)\n", iface);
241 return E_NOTIMPL;
242 }
243
244
245 static const IStreamVtbl StreamOnMemory_Vtbl =
246 {
247 /*** IUnknown methods ***/
248 StreamOnMemory_QueryInterface,
249 StreamOnMemory_AddRef,
250 StreamOnMemory_Release,
251 /*** ISequentialStream methods ***/
252 StreamOnMemory_Read,
253 StreamOnMemory_Write,
254 /*** IStream methods ***/
255 StreamOnMemory_Seek,
256 StreamOnMemory_SetSize,
257 StreamOnMemory_CopyTo,
258 StreamOnMemory_Commit,
259 StreamOnMemory_Revert,
260 StreamOnMemory_LockRegion,
261 StreamOnMemory_UnlockRegion,
262 StreamOnMemory_Stat,
263 StreamOnMemory_Clone,
264 };
265
266 /******************************************
267 * StreamOnStreamRange implementation
268 *
269 * Used by IWICStream_InitializeFromIStreamRegion
270 *
271 */
272 typedef struct StreamOnStreamRange {
273 IStream IStream_iface;
274 LONG ref;
275
276 IStream *stream;
277 ULARGE_INTEGER pos;
278 ULARGE_INTEGER offset;
279 ULARGE_INTEGER max_size;
280
281 CRITICAL_SECTION lock;
282 } StreamOnStreamRange;
283
284 static inline StreamOnStreamRange *StreamOnStreamRange_from_IStream(IStream *iface)
285 {
286 return CONTAINING_RECORD(iface, StreamOnStreamRange, IStream_iface);
287 }
288
289 static HRESULT WINAPI StreamOnStreamRange_QueryInterface(IStream *iface,
290 REFIID iid, void **ppv)
291 {
292 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
293
294 if (!ppv) return E_INVALIDARG;
295
296 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
297 IsEqualIID(&IID_ISequentialStream, iid))
298 {
299 *ppv = iface;
300 IUnknown_AddRef((IUnknown*)*ppv);
301 return S_OK;
302 }
303 else
304 {
305 *ppv = NULL;
306 return E_NOINTERFACE;
307 }
308 }
309
310 static ULONG WINAPI StreamOnStreamRange_AddRef(IStream *iface)
311 {
312 StreamOnStreamRange *This = StreamOnStreamRange_from_IStream(iface);
313 ULONG ref = InterlockedIncrement(&This->ref);
314
315 TRACE("(%p) refcount=%u\n", iface, ref);
316
317 return ref;
318 }
319
320 static ULONG WINAPI StreamOnStreamRange_Release(IStream *iface)
321 {
322 StreamOnStreamRange *This = StreamOnStreamRange_from_IStream(iface);
323 ULONG ref = InterlockedDecrement(&This->ref);
324
325 TRACE("(%p) refcount=%u\n", iface, ref);
326
327 if (ref == 0) {
328 This->lock.DebugInfo->Spare[0] = 0;
329 DeleteCriticalSection(&This->lock);
330 IStream_Release(This->stream);
331 HeapFree(GetProcessHeap(), 0, This);
332 }
333 return ref;
334 }
335
336 static HRESULT WINAPI StreamOnStreamRange_Read(IStream *iface,
337 void *pv, ULONG cb, ULONG *pcbRead)
338 {
339 StreamOnStreamRange *This = StreamOnStreamRange_from_IStream(iface);
340 ULONG uBytesRead=0;
341 HRESULT hr;
342 ULARGE_INTEGER OldPosition;
343 LARGE_INTEGER SetPosition;
344 TRACE("(%p)\n", This);
345
346 if (!pv) return E_INVALIDARG;
347
348 EnterCriticalSection(&This->lock);
349 SetPosition.QuadPart = 0;
350 hr = IStream_Seek(This->stream, SetPosition, STREAM_SEEK_CUR, &OldPosition);
351 if (SUCCEEDED(hr))
352 {
353 SetPosition.QuadPart = This->pos.QuadPart + This->offset.QuadPart;
354 hr = IStream_Seek(This->stream, SetPosition, STREAM_SEEK_SET, NULL);
355 }
356 if (SUCCEEDED(hr))
357 {
358 if (This->pos.QuadPart + cb > This->max_size.QuadPart)
359 {
360 /* This would read past the end of the stream. */
361 if (This->pos.QuadPart > This->max_size.QuadPart)
362 cb = 0;
363 else
364 cb = This->max_size.QuadPart - This->pos.QuadPart;
365 }
366 hr = IStream_Read(This->stream, pv, cb, &uBytesRead);
367 SetPosition.QuadPart = OldPosition.QuadPart;
368 IStream_Seek(This->stream, SetPosition, STREAM_SEEK_SET, NULL);
369 }
370 if (SUCCEEDED(hr))
371 This->pos.QuadPart += uBytesRead;
372 LeaveCriticalSection(&This->lock);
373
374 if (SUCCEEDED(hr) && pcbRead) *pcbRead = uBytesRead;
375
376 return hr;
377 }
378
379 static HRESULT WINAPI StreamOnStreamRange_Write(IStream *iface,
380 void const *pv, ULONG cb, ULONG *pcbWritten)
381 {
382 StreamOnStreamRange *This = StreamOnStreamRange_from_IStream(iface);
383 HRESULT hr;
384 ULARGE_INTEGER OldPosition;
385 LARGE_INTEGER SetPosition;
386 ULONG uBytesWritten=0;
387 TRACE("(%p)\n", This);
388
389 if (!pv) return E_INVALIDARG;
390
391 EnterCriticalSection(&This->lock);
392 SetPosition.QuadPart = 0;
393 hr = IStream_Seek(This->stream, SetPosition, STREAM_SEEK_CUR, &OldPosition);
394 if (SUCCEEDED(hr))
395 {
396 SetPosition.QuadPart = This->pos.QuadPart + This->offset.QuadPart;
397 hr = IStream_Seek(This->stream, SetPosition, STREAM_SEEK_SET, NULL);
398 }
399 if (SUCCEEDED(hr))
400 {
401 if (This->pos.QuadPart + cb > This->max_size.QuadPart)
402 {
403 /* This would read past the end of the stream. */
404 if (This->pos.QuadPart > This->max_size.QuadPart)
405 cb = 0;
406 else
407 cb = This->max_size.QuadPart - This->pos.QuadPart;
408 }
409 hr = IStream_Write(This->stream, pv, cb, &uBytesWritten);
410 SetPosition.QuadPart = OldPosition.QuadPart;
411 IStream_Seek(This->stream, SetPosition, STREAM_SEEK_SET, NULL);
412 }
413 if (SUCCEEDED(hr))
414 This->pos.QuadPart += uBytesWritten;
415 LeaveCriticalSection(&This->lock);
416
417 if (SUCCEEDED(hr) && pcbWritten) *pcbWritten = uBytesWritten;
418
419 return hr;
420 }
421
422 static HRESULT WINAPI StreamOnStreamRange_Seek(IStream *iface,
423 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
424 {
425 StreamOnStreamRange *This = StreamOnStreamRange_from_IStream(iface);
426 ULARGE_INTEGER NewPosition, actual_size;
427 HRESULT hr=S_OK;
428 STATSTG statstg;
429 TRACE("(%p)\n", This);
430
431 EnterCriticalSection(&This->lock);
432 actual_size = This->max_size;
433 if (dwOrigin == STREAM_SEEK_SET)
434 NewPosition.QuadPart = dlibMove.QuadPart;
435 else if (dwOrigin == STREAM_SEEK_CUR)
436 NewPosition.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
437 else if (dwOrigin == STREAM_SEEK_END)
438 {
439 hr = IStream_Stat(This->stream, &statstg, STATFLAG_NONAME);
440 if (SUCCEEDED(hr))
441 {
442 if (This->max_size.QuadPart + This->offset.QuadPart > statstg.cbSize.QuadPart)
443 actual_size.QuadPart = statstg.cbSize.QuadPart - This->offset.QuadPart;
444 NewPosition.QuadPart = dlibMove.QuadPart + actual_size.QuadPart;
445 }
446 }
447 else hr = E_INVALIDARG;
448
449 if (SUCCEEDED(hr) && (NewPosition.u.HighPart != 0 || NewPosition.QuadPart > actual_size.QuadPart))
450 hr = WINCODEC_ERR_VALUEOUTOFRANGE;
451
452 if (SUCCEEDED(hr)) {
453 This->pos.QuadPart = NewPosition.QuadPart;
454
455 if(plibNewPosition) plibNewPosition->QuadPart = This->pos.QuadPart;
456 }
457 LeaveCriticalSection(&This->lock);
458
459 return hr;
460 }
461
462 /* SetSize isn't implemented in the native windowscodecs DLL either */
463 static HRESULT WINAPI StreamOnStreamRange_SetSize(IStream *iface,
464 ULARGE_INTEGER libNewSize)
465 {
466 TRACE("(%p)\n", iface);
467 return E_NOTIMPL;
468 }
469
470 /* CopyTo isn't implemented in the native windowscodecs DLL either */
471 static HRESULT WINAPI StreamOnStreamRange_CopyTo(IStream *iface,
472 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
473 {
474 TRACE("(%p)\n", iface);
475 return E_NOTIMPL;
476 }
477
478 /* Commit isn't implemented in the native windowscodecs DLL either */
479 static HRESULT WINAPI StreamOnStreamRange_Commit(IStream *iface,
480 DWORD grfCommitFlags)
481 {
482 TRACE("(%p)\n", iface);
483 return E_NOTIMPL;
484 }
485
486 /* Revert isn't implemented in the native windowscodecs DLL either */
487 static HRESULT WINAPI StreamOnStreamRange_Revert(IStream *iface)
488 {
489 TRACE("(%p)\n", iface);
490 return E_NOTIMPL;
491 }
492
493 /* LockRegion isn't implemented in the native windowscodecs DLL either */
494 static HRESULT WINAPI StreamOnStreamRange_LockRegion(IStream *iface,
495 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
496 {
497 TRACE("(%p)\n", iface);
498 return E_NOTIMPL;
499 }
500
501 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
502 static HRESULT WINAPI StreamOnStreamRange_UnlockRegion(IStream *iface,
503 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
504 {
505 TRACE("(%p)\n", iface);
506 return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI StreamOnStreamRange_Stat(IStream *iface,
510 STATSTG *pstatstg, DWORD grfStatFlag)
511 {
512 StreamOnStreamRange *This = StreamOnStreamRange_from_IStream(iface);
513 HRESULT hr;
514 TRACE("(%p)\n", This);
515
516 if (!pstatstg) return E_INVALIDARG;
517
518 EnterCriticalSection(&This->lock);
519 hr = IStream_Stat(This->stream, pstatstg, grfStatFlag);
520 if (SUCCEEDED(hr))
521 {
522 pstatstg->cbSize.QuadPart -= This->offset.QuadPart;
523 if (This->max_size.QuadPart < pstatstg->cbSize.QuadPart)
524 pstatstg->cbSize.QuadPart = This->max_size.QuadPart;
525 }
526
527 LeaveCriticalSection(&This->lock);
528
529 return hr;
530 }
531
532 /* Clone isn't implemented in the native windowscodecs DLL either */
533 static HRESULT WINAPI StreamOnStreamRange_Clone(IStream *iface,
534 IStream **ppstm)
535 {
536 TRACE("(%p)\n", iface);
537 return E_NOTIMPL;
538 }
539
540
541 static const IStreamVtbl StreamOnStreamRange_Vtbl =
542 {
543 /*** IUnknown methods ***/
544 StreamOnStreamRange_QueryInterface,
545 StreamOnStreamRange_AddRef,
546 StreamOnStreamRange_Release,
547 /*** ISequentialStream methods ***/
548 StreamOnStreamRange_Read,
549 StreamOnStreamRange_Write,
550 /*** IStream methods ***/
551 StreamOnStreamRange_Seek,
552 StreamOnStreamRange_SetSize,
553 StreamOnStreamRange_CopyTo,
554 StreamOnStreamRange_Commit,
555 StreamOnStreamRange_Revert,
556 StreamOnStreamRange_LockRegion,
557 StreamOnStreamRange_UnlockRegion,
558 StreamOnStreamRange_Stat,
559 StreamOnStreamRange_Clone,
560 };
561
562
563 /******************************************
564 * IWICStream implementation
565 *
566 */
567 typedef struct IWICStreamImpl
568 {
569 IWICStream IWICStream_iface;
570 LONG ref;
571
572 IStream *pStream;
573 } IWICStreamImpl;
574
575 static inline IWICStreamImpl *impl_from_IWICStream(IWICStream *iface)
576 {
577 return CONTAINING_RECORD(iface, IWICStreamImpl, IWICStream_iface);
578 }
579
580 static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
581 REFIID iid, void **ppv)
582 {
583 IWICStreamImpl *This = impl_from_IWICStream(iface);
584 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
585
586 if (!ppv) return E_INVALIDARG;
587
588 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
589 IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
590 {
591 *ppv = This;
592 IUnknown_AddRef((IUnknown*)*ppv);
593 return S_OK;
594 }
595 else
596 {
597 *ppv = NULL;
598 return E_NOINTERFACE;
599 }
600 }
601
602 static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
603 {
604 IWICStreamImpl *This = impl_from_IWICStream(iface);
605 ULONG ref = InterlockedIncrement(&This->ref);
606
607 TRACE("(%p) refcount=%u\n", iface, ref);
608
609 return ref;
610 }
611
612 static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
613 {
614 IWICStreamImpl *This = impl_from_IWICStream(iface);
615 ULONG ref = InterlockedDecrement(&This->ref);
616
617 TRACE("(%p) refcount=%u\n", iface, ref);
618
619 if (ref == 0) {
620 if (This->pStream) IStream_Release(This->pStream);
621 HeapFree(GetProcessHeap(), 0, This);
622 }
623 return ref;
624 }
625
626 static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
627 void *pv, ULONG cb, ULONG *pcbRead)
628 {
629 IWICStreamImpl *This = impl_from_IWICStream(iface);
630 TRACE("(%p): relay\n", This);
631
632 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
633 return IStream_Read(This->pStream, pv, cb, pcbRead);
634 }
635
636 static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
637 void const *pv, ULONG cb, ULONG *pcbWritten)
638 {
639 IWICStreamImpl *This = impl_from_IWICStream(iface);
640 TRACE("(%p): relay\n", This);
641
642 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
643 return IStream_Write(This->pStream, pv, cb, pcbWritten);
644 }
645
646 static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
647 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
648 {
649 IWICStreamImpl *This = impl_from_IWICStream(iface);
650 TRACE("(%p): relay\n", This);
651
652 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
653 return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
654 }
655
656 static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
657 ULARGE_INTEGER libNewSize)
658 {
659 IWICStreamImpl *This = impl_from_IWICStream(iface);
660 TRACE("(%p): relay\n", This);
661
662 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
663 return IStream_SetSize(This->pStream, libNewSize);
664 }
665
666 static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
667 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
668 {
669 IWICStreamImpl *This = impl_from_IWICStream(iface);
670 TRACE("(%p): relay\n", This);
671
672 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
673 return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
674 }
675
676 static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
677 DWORD grfCommitFlags)
678 {
679 IWICStreamImpl *This = impl_from_IWICStream(iface);
680 TRACE("(%p): relay\n", This);
681
682 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
683 return IStream_Commit(This->pStream, grfCommitFlags);
684 }
685
686 static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
687 {
688 IWICStreamImpl *This = impl_from_IWICStream(iface);
689 TRACE("(%p): relay\n", This);
690
691 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
692 return IStream_Revert(This->pStream);
693 }
694
695 static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
696 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
697 {
698 IWICStreamImpl *This = impl_from_IWICStream(iface);
699 TRACE("(%p): relay\n", This);
700
701 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
702 return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
703 }
704
705 static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
706 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
707 {
708 IWICStreamImpl *This = impl_from_IWICStream(iface);
709 TRACE("(%p): relay\n", This);
710
711 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
712 return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
713 }
714
715 static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
716 STATSTG *pstatstg, DWORD grfStatFlag)
717 {
718 IWICStreamImpl *This = impl_from_IWICStream(iface);
719 TRACE("(%p): relay\n", This);
720
721 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
722 return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
723 }
724
725 static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
726 IStream **ppstm)
727 {
728 IWICStreamImpl *This = impl_from_IWICStream(iface);
729 TRACE("(%p): relay\n", This);
730
731 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
732 return IStream_Clone(This->pStream, ppstm);
733 }
734
735 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
736 IStream *pIStream)
737 {
738 FIXME("(%p): stub\n", iface);
739 return E_NOTIMPL;
740 }
741
742 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
743 LPCWSTR wzFileName, DWORD dwDesiredAccess)
744 {
745 IWICStreamImpl *This = impl_from_IWICStream(iface);
746 HRESULT hr;
747 DWORD dwMode;
748 IStream *stream;
749
750 TRACE("(%p, %s, %u)\n", iface, debugstr_w(wzFileName), dwDesiredAccess);
751
752 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
753
754 if(dwDesiredAccess & GENERIC_WRITE)
755 dwMode = STGM_SHARE_DENY_WRITE | STGM_WRITE | STGM_CREATE;
756 else if(dwDesiredAccess & GENERIC_READ)
757 dwMode = STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE;
758 else
759 return E_INVALIDARG;
760
761 hr = SHCreateStreamOnFileW(wzFileName, dwMode, &stream);
762
763 if (SUCCEEDED(hr))
764 {
765 if (InterlockedCompareExchangePointer((void**)&This->pStream, stream, NULL))
766 {
767 /* Some other thread set the stream first. */
768 IStream_Release(stream);
769 hr = WINCODEC_ERR_WRONGSTATE;
770 }
771 }
772
773 return hr;
774 }
775
776 /******************************************
777 * IWICStream_InitializeFromMemory
778 *
779 * Initializes the internal IStream object to retrieve its data from a memory chunk.
780 *
781 * PARAMS
782 * pbBuffer [I] pointer to the memory chunk
783 * cbBufferSize [I] number of bytes to use from the memory chunk
784 *
785 * RETURNS
786 * SUCCESS: S_OK
787 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
788 * E_OUTOFMEMORY, if we run out of memory
789 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
790 *
791 */
792 static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
793 BYTE *pbBuffer, DWORD cbBufferSize)
794 {
795 IWICStreamImpl *This = impl_from_IWICStream(iface);
796 StreamOnMemory *pObject;
797 TRACE("(%p,%p)\n", iface, pbBuffer);
798
799 if (!pbBuffer) return E_INVALIDARG;
800 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
801
802 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
803 if (!pObject) return E_OUTOFMEMORY;
804
805 pObject->IStream_iface.lpVtbl = &StreamOnMemory_Vtbl;
806 pObject->ref = 1;
807 pObject->pbMemory = pbBuffer;
808 pObject->dwMemsize = cbBufferSize;
809 pObject->dwCurPos = 0;
810 InitializeCriticalSection(&pObject->lock);
811 pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnMemory.lock");
812
813 if (InterlockedCompareExchangePointer((void**)&This->pStream, pObject, NULL))
814 {
815 /* Some other thread set the stream first. */
816 IStream_Release(&pObject->IStream_iface);
817 return WINCODEC_ERR_WRONGSTATE;
818 }
819
820 return S_OK;
821 }
822
823 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
824 IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
825 {
826 IWICStreamImpl *This = impl_from_IWICStream(iface);
827 StreamOnStreamRange *pObject;
828 TRACE("(%p,%p)\n", iface, pIStream);
829
830 if (!pIStream) return E_INVALIDARG;
831 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
832
833 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnStreamRange));
834 if (!pObject) return E_OUTOFMEMORY;
835
836 pObject->IStream_iface.lpVtbl = &StreamOnStreamRange_Vtbl;
837 pObject->ref = 1;
838 IStream_AddRef(pIStream);
839 pObject->stream = pIStream;
840 pObject->pos.QuadPart = 0;
841 pObject->offset = ulOffset;
842 pObject->max_size = ulMaxSize;
843 InitializeCriticalSection(&pObject->lock);
844 pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnStreamRange.lock");
845
846 if (InterlockedCompareExchangePointer((void**)&This->pStream, pObject, NULL))
847 {
848 /* Some other thread set the stream first. */
849 IStream_Release(&pObject->IStream_iface);
850 return WINCODEC_ERR_WRONGSTATE;
851 }
852
853 return S_OK;
854 }
855
856
857 static const IWICStreamVtbl WICStream_Vtbl =
858 {
859 /*** IUnknown methods ***/
860 IWICStreamImpl_QueryInterface,
861 IWICStreamImpl_AddRef,
862 IWICStreamImpl_Release,
863 /*** ISequentialStream methods ***/
864 IWICStreamImpl_Read,
865 IWICStreamImpl_Write,
866 /*** IStream methods ***/
867 IWICStreamImpl_Seek,
868 IWICStreamImpl_SetSize,
869 IWICStreamImpl_CopyTo,
870 IWICStreamImpl_Commit,
871 IWICStreamImpl_Revert,
872 IWICStreamImpl_LockRegion,
873 IWICStreamImpl_UnlockRegion,
874 IWICStreamImpl_Stat,
875 IWICStreamImpl_Clone,
876 /*** IWICStream methods ***/
877 IWICStreamImpl_InitializeFromIStream,
878 IWICStreamImpl_InitializeFromFilename,
879 IWICStreamImpl_InitializeFromMemory,
880 IWICStreamImpl_InitializeFromIStreamRegion,
881 };
882
883 HRESULT StreamImpl_Create(IWICStream **stream)
884 {
885 IWICStreamImpl *pObject;
886
887 if( !stream ) return E_INVALIDARG;
888
889 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
890 if( !pObject ) {
891 *stream = NULL;
892 return E_OUTOFMEMORY;
893 }
894
895 pObject->IWICStream_iface.lpVtbl = &WICStream_Vtbl;
896 pObject->ref = 1;
897 pObject->pStream = NULL;
898
899 *stream = &pObject->IWICStream_iface;
900
901 return S_OK;
902 }
903
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.