kernel32: Update Italian translation.
[wine/testsucceed.git] / dlls / windowscodecs / stream.c
blobbee27dba0da768172079c187b446e4357596256b
1 /*
2 * Copyright 2009 Tony Wasserka
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.
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.
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
19 #include "wine/debug.h"
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"
30 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
32 /******************************************
33 * StreamOnMemory implementation
35 * Used by IWICStream_InitializeFromMemory
38 typedef struct StreamOnMemory {
39 const IStreamVtbl *lpVtbl;
40 LONG ref;
42 BYTE *pbMemory;
43 DWORD dwMemsize;
44 DWORD dwCurPos;
46 CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */
47 } StreamOnMemory;
49 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
50 REFIID iid, void **ppv)
52 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
54 if (!ppv) return E_INVALIDARG;
56 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
57 IsEqualIID(&IID_ISequentialStream, iid))
59 *ppv = iface;
60 IUnknown_AddRef((IUnknown*)*ppv);
61 return S_OK;
63 else
65 *ppv = NULL;
66 return E_NOINTERFACE;
70 static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
72 StreamOnMemory *This = (StreamOnMemory*)iface;
73 ULONG ref = InterlockedIncrement(&This->ref);
75 TRACE("(%p) refcount=%u\n", iface, ref);
77 return ref;
80 static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
82 StreamOnMemory *This = (StreamOnMemory*)iface;
83 ULONG ref = InterlockedDecrement(&This->ref);
85 TRACE("(%p) refcount=%u\n", iface, ref);
87 if (ref == 0) {
88 This->lock.DebugInfo->Spare[0] = 0;
89 DeleteCriticalSection(&This->lock);
90 HeapFree(GetProcessHeap(), 0, This);
92 return ref;
95 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
96 void *pv, ULONG cb, ULONG *pcbRead)
98 StreamOnMemory *This = (StreamOnMemory*)iface;
99 ULONG uBytesRead;
100 TRACE("(%p)\n", This);
102 if (!pv) return E_INVALIDARG;
104 EnterCriticalSection(&This->lock);
105 uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
106 memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
107 This->dwCurPos += uBytesRead;
108 LeaveCriticalSection(&This->lock);
110 if (pcbRead) *pcbRead = uBytesRead;
112 return S_OK;
115 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
116 void const *pv, ULONG cb, ULONG *pcbWritten)
118 StreamOnMemory *This = (StreamOnMemory*)iface;
119 HRESULT hr;
120 TRACE("(%p)\n", This);
122 if (!pv) return E_INVALIDARG;
124 EnterCriticalSection(&This->lock);
125 if (cb > This->dwMemsize - This->dwCurPos) {
126 hr = STG_E_MEDIUMFULL;
128 else {
129 memcpy(This->pbMemory + This->dwCurPos, pv, cb);
130 This->dwCurPos += cb;
131 hr = S_OK;
132 if (pcbWritten) *pcbWritten = cb;
134 LeaveCriticalSection(&This->lock);
136 return hr;
139 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
140 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
142 StreamOnMemory *This = (StreamOnMemory*)iface;
143 LARGE_INTEGER NewPosition;
144 HRESULT hr=S_OK;
145 TRACE("(%p)\n", This);
147 EnterCriticalSection(&This->lock);
148 if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
149 else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
150 else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
151 else hr = E_INVALIDARG;
153 if (SUCCEEDED(hr)) {
154 if (NewPosition.u.HighPart) hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
155 else if (NewPosition.QuadPart > This->dwMemsize) hr = E_INVALIDARG;
156 else if (NewPosition.QuadPart < 0) hr = E_INVALIDARG;
159 if (SUCCEEDED(hr)) {
160 This->dwCurPos = NewPosition.u.LowPart;
162 if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
164 LeaveCriticalSection(&This->lock);
166 return hr;
169 /* SetSize isn't implemented in the native windowscodecs DLL either */
170 static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
171 ULARGE_INTEGER libNewSize)
173 TRACE("(%p)\n", iface);
174 return E_NOTIMPL;
177 /* CopyTo isn't implemented in the native windowscodecs DLL either */
178 static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
179 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
181 TRACE("(%p)\n", iface);
182 return E_NOTIMPL;
185 /* Commit isn't implemented in the native windowscodecs DLL either */
186 static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
187 DWORD grfCommitFlags)
189 TRACE("(%p)\n", iface);
190 return E_NOTIMPL;
193 /* Revert isn't implemented in the native windowscodecs DLL either */
194 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
196 TRACE("(%p)\n", iface);
197 return E_NOTIMPL;
200 /* LockRegion isn't implemented in the native windowscodecs DLL either */
201 static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
202 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
204 TRACE("(%p)\n", iface);
205 return E_NOTIMPL;
208 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
209 static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
210 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
212 TRACE("(%p)\n", iface);
213 return E_NOTIMPL;
216 static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
217 STATSTG *pstatstg, DWORD grfStatFlag)
219 StreamOnMemory *This = (StreamOnMemory*)iface;
220 TRACE("(%p)\n", This);
222 if (!pstatstg) return E_INVALIDARG;
224 ZeroMemory(pstatstg, sizeof(STATSTG));
225 pstatstg->type = STGTY_STREAM;
226 pstatstg->cbSize.QuadPart = This->dwMemsize;
228 return S_OK;
231 /* Clone isn't implemented in the native windowscodecs DLL either */
232 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
233 IStream **ppstm)
235 TRACE("(%p)\n", iface);
236 return E_NOTIMPL;
240 const IStreamVtbl StreamOnMemory_Vtbl =
242 /*** IUnknown methods ***/
243 StreamOnMemory_QueryInterface,
244 StreamOnMemory_AddRef,
245 StreamOnMemory_Release,
246 /*** ISequentialStream methods ***/
247 StreamOnMemory_Read,
248 StreamOnMemory_Write,
249 /*** IStream methods ***/
250 StreamOnMemory_Seek,
251 StreamOnMemory_SetSize,
252 StreamOnMemory_CopyTo,
253 StreamOnMemory_Commit,
254 StreamOnMemory_Revert,
255 StreamOnMemory_LockRegion,
256 StreamOnMemory_UnlockRegion,
257 StreamOnMemory_Stat,
258 StreamOnMemory_Clone,
261 /******************************************
262 * IWICStream implementation
265 typedef struct IWICStreamImpl
267 const IWICStreamVtbl *lpVtbl;
268 LONG ref;
270 IStream *pStream;
271 } IWICStreamImpl;
273 static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
274 REFIID iid, void **ppv)
276 IWICStreamImpl *This = (IWICStreamImpl*)iface;
277 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
279 if (!ppv) return E_INVALIDARG;
281 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
282 IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
284 *ppv = This;
285 IUnknown_AddRef((IUnknown*)*ppv);
286 return S_OK;
288 else
290 *ppv = NULL;
291 return E_NOINTERFACE;
295 static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
297 IWICStreamImpl *This = (IWICStreamImpl*)iface;
298 ULONG ref = InterlockedIncrement(&This->ref);
300 TRACE("(%p) refcount=%u\n", iface, ref);
302 return ref;
305 static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
307 IWICStreamImpl *This = (IWICStreamImpl*)iface;
308 ULONG ref = InterlockedDecrement(&This->ref);
310 TRACE("(%p) refcount=%u\n", iface, ref);
312 if (ref == 0) {
313 if (This->pStream) IStream_Release(This->pStream);
314 HeapFree(GetProcessHeap(), 0, This);
316 return ref;
319 static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
320 void *pv, ULONG cb, ULONG *pcbRead)
322 IWICStreamImpl *This = (IWICStreamImpl*)iface;
323 TRACE("(%p): relay\n", This);
325 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
326 return IStream_Read(This->pStream, pv, cb, pcbRead);
329 static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
330 void const *pv, ULONG cb, ULONG *pcbWritten)
332 IWICStreamImpl *This = (IWICStreamImpl*)iface;
333 TRACE("(%p): relay\n", This);
335 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
336 return IStream_Write(This->pStream, pv, cb, pcbWritten);
339 static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
340 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
342 IWICStreamImpl *This = (IWICStreamImpl*)iface;
343 TRACE("(%p): relay\n", This);
345 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
346 return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
349 static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
350 ULARGE_INTEGER libNewSize)
352 IWICStreamImpl *This = (IWICStreamImpl*)iface;
353 TRACE("(%p): relay\n", This);
355 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
356 return IStream_SetSize(This->pStream, libNewSize);
359 static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
360 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
362 IWICStreamImpl *This = (IWICStreamImpl*)iface;
363 TRACE("(%p): relay\n", This);
365 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
366 return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
369 static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
370 DWORD grfCommitFlags)
372 IWICStreamImpl *This = (IWICStreamImpl*)iface;
373 TRACE("(%p): relay\n", This);
375 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
376 return IStream_Commit(This->pStream, grfCommitFlags);
379 static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
381 IWICStreamImpl *This = (IWICStreamImpl*)iface;
382 TRACE("(%p): relay\n", This);
384 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
385 return IStream_Revert(This->pStream);
388 static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
389 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
391 IWICStreamImpl *This = (IWICStreamImpl*)iface;
392 TRACE("(%p): relay\n", This);
394 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
395 return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
398 static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
399 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
401 IWICStreamImpl *This = (IWICStreamImpl*)iface;
402 TRACE("(%p): relay\n", This);
404 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
405 return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
408 static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
409 STATSTG *pstatstg, DWORD grfStatFlag)
411 IWICStreamImpl *This = (IWICStreamImpl*)iface;
412 TRACE("(%p): relay\n", This);
414 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
415 return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
418 static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
419 IStream **ppstm)
421 IWICStreamImpl *This = (IWICStreamImpl*)iface;
422 TRACE("(%p): relay\n", This);
424 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
425 return IStream_Clone(This->pStream, ppstm);
428 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
429 IStream *pIStream)
431 FIXME("(%p): stub\n", iface);
432 return E_NOTIMPL;
435 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
436 LPCWSTR wzFileName, DWORD dwDesiredAccess)
438 IWICStreamImpl *This = (IWICStreamImpl*)iface;
439 HRESULT hr;
440 DWORD dwMode;
441 IStream *stream;
443 TRACE("(%p, %s, %u)\n", iface, debugstr_w(wzFileName), dwDesiredAccess);
445 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
447 if(dwDesiredAccess & GENERIC_WRITE)
448 dwMode = STGM_SHARE_DENY_WRITE | STGM_WRITE | STGM_CREATE;
449 else if(dwDesiredAccess & GENERIC_READ)
450 dwMode = STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE;
451 else
452 return E_INVALIDARG;
454 hr = SHCreateStreamOnFileW(wzFileName, dwMode, &stream);
456 if (SUCCEEDED(hr))
458 if (InterlockedCompareExchangePointer((void**)&This->pStream, stream, NULL))
460 /* Some other thread set the stream first. */
461 IStream_Release(stream);
462 hr = WINCODEC_ERR_WRONGSTATE;
466 return hr;
469 /******************************************
470 * IWICStream_InitializeFromMemory
472 * Initializes the internal IStream object to retrieve its data from a memory chunk.
474 * PARAMS
475 * pbBuffer [I] pointer to the memory chunk
476 * cbBufferSize [I] number of bytes to use from the memory chunk
478 * RETURNS
479 * SUCCESS: S_OK
480 * FAILURE: E_INVALIDARG, if pbBuffer is NULL
481 * E_OUTOFMEMORY, if we run out of memory
482 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
485 static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
486 BYTE *pbBuffer, DWORD cbBufferSize)
488 IWICStreamImpl *This = (IWICStreamImpl*)iface;
489 StreamOnMemory *pObject;
490 TRACE("(%p,%p)\n", iface, pbBuffer);
492 if (!pbBuffer) return E_INVALIDARG;
493 if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
495 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
496 if (!pObject) return E_OUTOFMEMORY;
498 pObject->lpVtbl = &StreamOnMemory_Vtbl;
499 pObject->ref = 1;
500 pObject->pbMemory = pbBuffer;
501 pObject->dwMemsize = cbBufferSize;
502 pObject->dwCurPos = 0;
503 InitializeCriticalSection(&pObject->lock);
504 pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnMemory.lock");
506 if (InterlockedCompareExchangePointer((void**)&This->pStream, pObject, NULL))
508 /* Some other thread set the stream first. */
509 IStream_Release((IStream*)pObject);
510 return WINCODEC_ERR_WRONGSTATE;
513 return S_OK;
516 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
517 IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
519 FIXME("(%p): stub\n", iface);
520 return E_NOTIMPL;
524 const IWICStreamVtbl WICStream_Vtbl =
526 /*** IUnknown methods ***/
527 IWICStreamImpl_QueryInterface,
528 IWICStreamImpl_AddRef,
529 IWICStreamImpl_Release,
530 /*** ISequentialStream methods ***/
531 IWICStreamImpl_Read,
532 IWICStreamImpl_Write,
533 /*** IStream methods ***/
534 IWICStreamImpl_Seek,
535 IWICStreamImpl_SetSize,
536 IWICStreamImpl_CopyTo,
537 IWICStreamImpl_Commit,
538 IWICStreamImpl_Revert,
539 IWICStreamImpl_LockRegion,
540 IWICStreamImpl_UnlockRegion,
541 IWICStreamImpl_Stat,
542 IWICStreamImpl_Clone,
543 /*** IWICStream methods ***/
544 IWICStreamImpl_InitializeFromIStream,
545 IWICStreamImpl_InitializeFromFilename,
546 IWICStreamImpl_InitializeFromMemory,
547 IWICStreamImpl_InitializeFromIStreamRegion,
550 HRESULT StreamImpl_Create(IWICStream **stream)
552 IWICStreamImpl *pObject;
554 if( !stream ) return E_INVALIDARG;
556 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
557 if( !pObject ) {
558 *stream = NULL;
559 return E_OUTOFMEMORY;
562 pObject->lpVtbl = &WICStream_Vtbl;
563 pObject->ref = 1;
564 pObject->pStream = NULL;
566 *stream = (IWICStream*)pObject;
568 return S_OK;