~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/windowscodecs/stream.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.