Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstream.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2009 Tony Wasserka 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "wine/debug.h" 00020 00021 #define COBJMACROS 00022 #include "windef.h" 00023 #include "winbase.h" 00024 #include "winreg.h" 00025 #include "objbase.h" 00026 #include "shlwapi.h" 00027 #include "wincodec.h" 00028 #include "wincodecs_private.h" 00029 00030 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 00031 00032 /****************************************** 00033 * StreamOnMemory implementation 00034 * 00035 * Used by IWICStream_InitializeFromMemory 00036 * 00037 */ 00038 typedef struct StreamOnMemory { 00039 const IStreamVtbl *lpVtbl; 00040 LONG ref; 00041 00042 BYTE *pbMemory; 00043 DWORD dwMemsize; 00044 DWORD dwCurPos; 00045 00046 CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */ 00047 } StreamOnMemory; 00048 00049 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface, 00050 REFIID iid, void **ppv) 00051 { 00052 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 00053 00054 if (!ppv) return E_INVALIDARG; 00055 00056 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) || 00057 IsEqualIID(&IID_ISequentialStream, iid)) 00058 { 00059 *ppv = iface; 00060 IUnknown_AddRef((IUnknown*)*ppv); 00061 return S_OK; 00062 } 00063 else 00064 { 00065 *ppv = NULL; 00066 return E_NOINTERFACE; 00067 } 00068 } 00069 00070 static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface) 00071 { 00072 StreamOnMemory *This = (StreamOnMemory*)iface; 00073 ULONG ref = InterlockedIncrement(&This->ref); 00074 00075 TRACE("(%p) refcount=%u\n", iface, ref); 00076 00077 return ref; 00078 } 00079 00080 static ULONG WINAPI StreamOnMemory_Release(IStream *iface) 00081 { 00082 StreamOnMemory *This = (StreamOnMemory*)iface; 00083 ULONG ref = InterlockedDecrement(&This->ref); 00084 00085 TRACE("(%p) refcount=%u\n", iface, ref); 00086 00087 if (ref == 0) { 00088 This->lock.DebugInfo->Spare[0] = 0; 00089 DeleteCriticalSection(&This->lock); 00090 HeapFree(GetProcessHeap(), 0, This); 00091 } 00092 return ref; 00093 } 00094 00095 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface, 00096 void *pv, ULONG cb, ULONG *pcbRead) 00097 { 00098 StreamOnMemory *This = (StreamOnMemory*)iface; 00099 ULONG uBytesRead; 00100 TRACE("(%p)\n", This); 00101 00102 if (!pv) return E_INVALIDARG; 00103 00104 EnterCriticalSection(&This->lock); 00105 uBytesRead = min(cb, This->dwMemsize - This->dwCurPos); 00106 memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead); 00107 This->dwCurPos += uBytesRead; 00108 LeaveCriticalSection(&This->lock); 00109 00110 if (pcbRead) *pcbRead = uBytesRead; 00111 00112 return S_OK; 00113 } 00114 00115 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface, 00116 void const *pv, ULONG cb, ULONG *pcbWritten) 00117 { 00118 StreamOnMemory *This = (StreamOnMemory*)iface; 00119 HRESULT hr; 00120 TRACE("(%p)\n", This); 00121 00122 if (!pv) return E_INVALIDARG; 00123 00124 EnterCriticalSection(&This->lock); 00125 if (cb > This->dwMemsize - This->dwCurPos) { 00126 hr = STG_E_MEDIUMFULL; 00127 } 00128 else { 00129 memcpy(This->pbMemory + This->dwCurPos, pv, cb); 00130 This->dwCurPos += cb; 00131 hr = S_OK; 00132 if (pcbWritten) *pcbWritten = cb; 00133 } 00134 LeaveCriticalSection(&This->lock); 00135 00136 return hr; 00137 } 00138 00139 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface, 00140 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 00141 { 00142 StreamOnMemory *This = (StreamOnMemory*)iface; 00143 LARGE_INTEGER NewPosition; 00144 HRESULT hr=S_OK; 00145 TRACE("(%p)\n", This); 00146 00147 EnterCriticalSection(&This->lock); 00148 if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart; 00149 else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart; 00150 else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart; 00151 else hr = E_INVALIDARG; 00152 00153 if (SUCCEEDED(hr)) { 00154 if (NewPosition.u.HighPart) hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW); 00155 else if (NewPosition.QuadPart > This->dwMemsize) hr = E_INVALIDARG; 00156 else if (NewPosition.QuadPart < 0) hr = E_INVALIDARG; 00157 } 00158 00159 if (SUCCEEDED(hr)) { 00160 This->dwCurPos = NewPosition.u.LowPart; 00161 00162 if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos; 00163 } 00164 LeaveCriticalSection(&This->lock); 00165 00166 return hr; 00167 } 00168 00169 /* SetSize isn't implemented in the native windowscodecs DLL either */ 00170 static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface, 00171 ULARGE_INTEGER libNewSize) 00172 { 00173 TRACE("(%p)\n", iface); 00174 return E_NOTIMPL; 00175 } 00176 00177 /* CopyTo isn't implemented in the native windowscodecs DLL either */ 00178 static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface, 00179 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) 00180 { 00181 TRACE("(%p)\n", iface); 00182 return E_NOTIMPL; 00183 } 00184 00185 /* Commit isn't implemented in the native windowscodecs DLL either */ 00186 static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface, 00187 DWORD grfCommitFlags) 00188 { 00189 TRACE("(%p)\n", iface); 00190 return E_NOTIMPL; 00191 } 00192 00193 /* Revert isn't implemented in the native windowscodecs DLL either */ 00194 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface) 00195 { 00196 TRACE("(%p)\n", iface); 00197 return E_NOTIMPL; 00198 } 00199 00200 /* LockRegion isn't implemented in the native windowscodecs DLL either */ 00201 static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface, 00202 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00203 { 00204 TRACE("(%p)\n", iface); 00205 return E_NOTIMPL; 00206 } 00207 00208 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */ 00209 static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface, 00210 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00211 { 00212 TRACE("(%p)\n", iface); 00213 return E_NOTIMPL; 00214 } 00215 00216 static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface, 00217 STATSTG *pstatstg, DWORD grfStatFlag) 00218 { 00219 StreamOnMemory *This = (StreamOnMemory*)iface; 00220 TRACE("(%p)\n", This); 00221 00222 if (!pstatstg) return E_INVALIDARG; 00223 00224 ZeroMemory(pstatstg, sizeof(STATSTG)); 00225 pstatstg->type = STGTY_STREAM; 00226 pstatstg->cbSize.QuadPart = This->dwMemsize; 00227 00228 return S_OK; 00229 } 00230 00231 /* Clone isn't implemented in the native windowscodecs DLL either */ 00232 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface, 00233 IStream **ppstm) 00234 { 00235 TRACE("(%p)\n", iface); 00236 return E_NOTIMPL; 00237 } 00238 00239 00240 const IStreamVtbl StreamOnMemory_Vtbl = 00241 { 00242 /*** IUnknown methods ***/ 00243 StreamOnMemory_QueryInterface, 00244 StreamOnMemory_AddRef, 00245 StreamOnMemory_Release, 00246 /*** ISequentialStream methods ***/ 00247 StreamOnMemory_Read, 00248 StreamOnMemory_Write, 00249 /*** IStream methods ***/ 00250 StreamOnMemory_Seek, 00251 StreamOnMemory_SetSize, 00252 StreamOnMemory_CopyTo, 00253 StreamOnMemory_Commit, 00254 StreamOnMemory_Revert, 00255 StreamOnMemory_LockRegion, 00256 StreamOnMemory_UnlockRegion, 00257 StreamOnMemory_Stat, 00258 StreamOnMemory_Clone, 00259 }; 00260 00261 /****************************************** 00262 * IWICStream implementation 00263 * 00264 */ 00265 typedef struct IWICStreamImpl 00266 { 00267 const IWICStreamVtbl *lpVtbl; 00268 LONG ref; 00269 00270 IStream *pStream; 00271 } IWICStreamImpl; 00272 00273 static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface, 00274 REFIID iid, void **ppv) 00275 { 00276 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00277 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 00278 00279 if (!ppv) return E_INVALIDARG; 00280 00281 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) || 00282 IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid)) 00283 { 00284 *ppv = This; 00285 IUnknown_AddRef((IUnknown*)*ppv); 00286 return S_OK; 00287 } 00288 else 00289 { 00290 *ppv = NULL; 00291 return E_NOINTERFACE; 00292 } 00293 } 00294 00295 static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface) 00296 { 00297 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00298 ULONG ref = InterlockedIncrement(&This->ref); 00299 00300 TRACE("(%p) refcount=%u\n", iface, ref); 00301 00302 return ref; 00303 } 00304 00305 static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface) 00306 { 00307 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00308 ULONG ref = InterlockedDecrement(&This->ref); 00309 00310 TRACE("(%p) refcount=%u\n", iface, ref); 00311 00312 if (ref == 0) { 00313 if (This->pStream) IStream_Release(This->pStream); 00314 HeapFree(GetProcessHeap(), 0, This); 00315 } 00316 return ref; 00317 } 00318 00319 static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface, 00320 void *pv, ULONG cb, ULONG *pcbRead) 00321 { 00322 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00323 TRACE("(%p): relay\n", This); 00324 00325 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00326 return IStream_Read(This->pStream, pv, cb, pcbRead); 00327 } 00328 00329 static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface, 00330 void const *pv, ULONG cb, ULONG *pcbWritten) 00331 { 00332 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00333 TRACE("(%p): relay\n", This); 00334 00335 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00336 return IStream_Write(This->pStream, pv, cb, pcbWritten); 00337 } 00338 00339 static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface, 00340 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 00341 { 00342 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00343 TRACE("(%p): relay\n", This); 00344 00345 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00346 return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition); 00347 } 00348 00349 static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface, 00350 ULARGE_INTEGER libNewSize) 00351 { 00352 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00353 TRACE("(%p): relay\n", This); 00354 00355 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00356 return IStream_SetSize(This->pStream, libNewSize); 00357 } 00358 00359 static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface, 00360 IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) 00361 { 00362 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00363 TRACE("(%p): relay\n", This); 00364 00365 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00366 return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten); 00367 } 00368 00369 static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface, 00370 DWORD grfCommitFlags) 00371 { 00372 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00373 TRACE("(%p): relay\n", This); 00374 00375 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00376 return IStream_Commit(This->pStream, grfCommitFlags); 00377 } 00378 00379 static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface) 00380 { 00381 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00382 TRACE("(%p): relay\n", This); 00383 00384 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00385 return IStream_Revert(This->pStream); 00386 } 00387 00388 static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface, 00389 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00390 { 00391 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00392 TRACE("(%p): relay\n", This); 00393 00394 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00395 return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType); 00396 } 00397 00398 static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface, 00399 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00400 { 00401 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00402 TRACE("(%p): relay\n", This); 00403 00404 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00405 return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType); 00406 } 00407 00408 static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface, 00409 STATSTG *pstatstg, DWORD grfStatFlag) 00410 { 00411 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00412 TRACE("(%p): relay\n", This); 00413 00414 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00415 return IStream_Stat(This->pStream, pstatstg, grfStatFlag); 00416 } 00417 00418 static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface, 00419 IStream **ppstm) 00420 { 00421 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00422 TRACE("(%p): relay\n", This); 00423 00424 if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED; 00425 return IStream_Clone(This->pStream, ppstm); 00426 } 00427 00428 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface, 00429 IStream *pIStream) 00430 { 00431 FIXME("(%p): stub\n", iface); 00432 return E_NOTIMPL; 00433 } 00434 00435 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface, 00436 LPCWSTR wzFileName, DWORD dwDesiredAccess) 00437 { 00438 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00439 HRESULT hr; 00440 DWORD dwMode; 00441 IStream *stream; 00442 00443 TRACE("(%p, %s, %u)\n", iface, debugstr_w(wzFileName), dwDesiredAccess); 00444 00445 if (This->pStream) return WINCODEC_ERR_WRONGSTATE; 00446 00447 if(dwDesiredAccess & GENERIC_WRITE) 00448 dwMode = STGM_SHARE_DENY_WRITE | STGM_WRITE | STGM_CREATE; 00449 else if(dwDesiredAccess & GENERIC_READ) 00450 dwMode = STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE; 00451 else 00452 return E_INVALIDARG; 00453 00454 hr = SHCreateStreamOnFileW(wzFileName, dwMode, &stream); 00455 00456 if (SUCCEEDED(hr)) 00457 { 00458 if (InterlockedCompareExchangePointer((void**)&This->pStream, stream, NULL)) 00459 { 00460 /* Some other thread set the stream first. */ 00461 IStream_Release(stream); 00462 hr = WINCODEC_ERR_WRONGSTATE; 00463 } 00464 } 00465 00466 return hr; 00467 } 00468 00469 /****************************************** 00470 * IWICStream_InitializeFromMemory 00471 * 00472 * Initializes the internal IStream object to retrieve its data from a memory chunk. 00473 * 00474 * PARAMS 00475 * pbBuffer [I] pointer to the memory chunk 00476 * cbBufferSize [I] number of bytes to use from the memory chunk 00477 * 00478 * RETURNS 00479 * SUCCESS: S_OK 00480 * FAILURE: E_INVALIDARG, if pbBuffer is NULL 00481 * E_OUTOFMEMORY, if we run out of memory 00482 * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before 00483 * 00484 */ 00485 static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface, 00486 BYTE *pbBuffer, DWORD cbBufferSize) 00487 { 00488 IWICStreamImpl *This = (IWICStreamImpl*)iface; 00489 StreamOnMemory *pObject; 00490 TRACE("(%p,%p)\n", iface, pbBuffer); 00491 00492 if (!pbBuffer) return E_INVALIDARG; 00493 if (This->pStream) return WINCODEC_ERR_WRONGSTATE; 00494 00495 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory)); 00496 if (!pObject) return E_OUTOFMEMORY; 00497 00498 pObject->lpVtbl = &StreamOnMemory_Vtbl; 00499 pObject->ref = 1; 00500 pObject->pbMemory = pbBuffer; 00501 pObject->dwMemsize = cbBufferSize; 00502 pObject->dwCurPos = 0; 00503 InitializeCriticalSection(&pObject->lock); 00504 pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnMemory.lock"); 00505 00506 if (InterlockedCompareExchangePointer((void**)&This->pStream, pObject, NULL)) 00507 { 00508 /* Some other thread set the stream first. */ 00509 IStream_Release((IStream*)pObject); 00510 return WINCODEC_ERR_WRONGSTATE; 00511 } 00512 00513 return S_OK; 00514 } 00515 00516 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface, 00517 IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize) 00518 { 00519 FIXME("(%p): stub\n", iface); 00520 return E_NOTIMPL; 00521 } 00522 00523 00524 const IWICStreamVtbl WICStream_Vtbl = 00525 { 00526 /*** IUnknown methods ***/ 00527 IWICStreamImpl_QueryInterface, 00528 IWICStreamImpl_AddRef, 00529 IWICStreamImpl_Release, 00530 /*** ISequentialStream methods ***/ 00531 IWICStreamImpl_Read, 00532 IWICStreamImpl_Write, 00533 /*** IStream methods ***/ 00534 IWICStreamImpl_Seek, 00535 IWICStreamImpl_SetSize, 00536 IWICStreamImpl_CopyTo, 00537 IWICStreamImpl_Commit, 00538 IWICStreamImpl_Revert, 00539 IWICStreamImpl_LockRegion, 00540 IWICStreamImpl_UnlockRegion, 00541 IWICStreamImpl_Stat, 00542 IWICStreamImpl_Clone, 00543 /*** IWICStream methods ***/ 00544 IWICStreamImpl_InitializeFromIStream, 00545 IWICStreamImpl_InitializeFromFilename, 00546 IWICStreamImpl_InitializeFromMemory, 00547 IWICStreamImpl_InitializeFromIStreamRegion, 00548 }; 00549 00550 HRESULT StreamImpl_Create(IWICStream **stream) 00551 { 00552 IWICStreamImpl *pObject; 00553 00554 if( !stream ) return E_INVALIDARG; 00555 00556 pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl)); 00557 if( !pObject ) { 00558 *stream = NULL; 00559 return E_OUTOFMEMORY; 00560 } 00561 00562 pObject->lpVtbl = &WICStream_Vtbl; 00563 pObject->ref = 1; 00564 pObject->pStream = NULL; 00565 00566 *stream = (IWICStream*)pObject; 00567 00568 return S_OK; 00569 } Generated on Sun May 27 2012 04:23:51 for ReactOS by
1.7.6.1
|