crypt32: Return an empty string from CertGetNameStringW if a name couldn't be found.
[wine] / dlls / windowscodecs / stream.c
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 "wincodec.h"
27 #include "wincodecs_private.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
30
31 /******************************************
32  * StreamOnMemory implementation
33  *
34  * Used by IWICStream_InitializeFromMemory
35  *
36  */
37 typedef struct StreamOnMemory {
38     const IStreamVtbl *lpVtbl;
39     LONG ref;
40
41     BYTE *pbMemory;
42     DWORD dwMemsize;
43     DWORD dwCurPos;
44 } StreamOnMemory;
45
46 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
47     REFIID iid, void **ppv)
48 {
49     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
50
51     if (!ppv) return E_INVALIDARG;
52
53     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
54         IsEqualIID(&IID_ISequentialStream, iid))
55     {
56         *ppv = iface;
57         IUnknown_AddRef((IUnknown*)*ppv);
58         return S_OK;
59     }
60     else
61     {
62         *ppv = NULL;
63         return E_NOINTERFACE;
64     }
65 }
66
67 static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
68 {
69     StreamOnMemory *This = (StreamOnMemory*)iface;
70     ULONG ref = InterlockedIncrement(&This->ref);
71
72     TRACE("(%p) refcount=%u\n", iface, ref);
73
74     return ref;
75 }
76
77 static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
78 {
79     StreamOnMemory *This = (StreamOnMemory*)iface;
80     ULONG ref = InterlockedDecrement(&This->ref);
81
82     TRACE("(%p) refcount=%u\n", iface, ref);
83
84     if (ref == 0) {
85         HeapFree(GetProcessHeap(), 0, This);
86     }
87     return ref;
88 }
89
90 static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
91     void *pv, ULONG cb, ULONG *pcbRead)
92 {
93     StreamOnMemory *This = (StreamOnMemory*)iface;
94     ULONG uBytesRead;
95     TRACE("(%p)\n", This);
96
97     if (!pv) return E_INVALIDARG;
98
99     uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
100     memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
101     This->dwCurPos += uBytesRead;
102     if (pcbRead) *pcbRead = uBytesRead;
103
104     return S_OK;
105 }
106
107 static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
108     void const *pv, ULONG cb, ULONG *pcbWritten)
109 {
110     StreamOnMemory *This = (StreamOnMemory*)iface;
111     TRACE("(%p)\n", This);
112
113     if (!pv) return E_INVALIDARG;
114
115     if (cb > This->dwMemsize - This->dwCurPos) return STG_E_MEDIUMFULL;
116     if (cb) {
117         memcpy(This->pbMemory + This->dwCurPos, pv, cb);
118         This->dwCurPos += cb;
119     }
120     if (pcbWritten) *pcbWritten = cb;
121
122     return S_OK;
123 }
124
125 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
126     LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
127 {
128     StreamOnMemory *This = (StreamOnMemory*)iface;
129     LARGE_INTEGER NewPosition;
130     TRACE("(%p)\n", This);
131
132     if (dlibMove.QuadPart > 0xFFFFFFFF) return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
133
134     if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
135     else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
136     else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
137     else return E_INVALIDARG;
138
139     if (NewPosition.QuadPart > This->dwMemsize) return E_INVALIDARG;
140     if (NewPosition.QuadPart < 0) return E_INVALIDARG;
141     This->dwCurPos = NewPosition.u.LowPart;
142
143     if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
144     return S_OK;
145 }
146
147 /* SetSize isn't implemented in the native windowscodecs DLL either */
148 static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
149     ULARGE_INTEGER libNewSize)
150 {
151     TRACE("(%p)\n", iface);
152     return E_NOTIMPL;
153 }
154
155 /* CopyTo isn't implemented in the native windowscodecs DLL either */
156 static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
157     IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
158 {
159     TRACE("(%p)\n", iface);
160     return E_NOTIMPL;
161 }
162
163 /* Commit isn't implemented in the native windowscodecs DLL either */
164 static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
165     DWORD grfCommitFlags)
166 {
167     TRACE("(%p)\n", iface);
168     return E_NOTIMPL;
169 }
170
171 /* Revert isn't implemented in the native windowscodecs DLL either */
172 static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
173 {
174     TRACE("(%p)\n", iface);
175     return E_NOTIMPL;
176 }
177
178 /* LockRegion isn't implemented in the native windowscodecs DLL either */
179 static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
180     ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
181 {
182     TRACE("(%p)\n", iface);
183     return E_NOTIMPL;
184 }
185
186 /* UnlockRegion isn't implemented in the native windowscodecs DLL either */
187 static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
188     ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
189 {
190     TRACE("(%p)\n", iface);
191     return E_NOTIMPL;
192 }
193
194 static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
195     STATSTG *pstatstg, DWORD grfStatFlag)
196 {
197     StreamOnMemory *This = (StreamOnMemory*)iface;
198     TRACE("(%p)\n", This);
199
200     if (!pstatstg) return E_INVALIDARG;
201
202     ZeroMemory(pstatstg, sizeof(STATSTG));
203     pstatstg->type = STGTY_STREAM;
204     pstatstg->cbSize.QuadPart = This->dwMemsize;
205
206     return S_OK;
207 }
208
209 /* Clone isn't implemented in the native windowscodecs DLL either */
210 static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
211     IStream **ppstm)
212 {
213     TRACE("(%p)\n", iface);
214     return E_NOTIMPL;
215 }
216
217
218 const IStreamVtbl StreamOnMemory_Vtbl =
219 {
220     /*** IUnknown methods ***/
221     StreamOnMemory_QueryInterface,
222     StreamOnMemory_AddRef,
223     StreamOnMemory_Release,
224     /*** ISequentialStream methods ***/
225     StreamOnMemory_Read,
226     StreamOnMemory_Write,
227     /*** IStream methods ***/
228     StreamOnMemory_Seek,
229     StreamOnMemory_SetSize,
230     StreamOnMemory_CopyTo,
231     StreamOnMemory_Commit,
232     StreamOnMemory_Revert,
233     StreamOnMemory_LockRegion,
234     StreamOnMemory_UnlockRegion,
235     StreamOnMemory_Stat,
236     StreamOnMemory_Clone,
237 };
238
239 /******************************************
240  * IWICStream implementation
241  *
242  */
243 typedef struct IWICStreamImpl
244 {
245     const IWICStreamVtbl *lpVtbl;
246     LONG ref;
247
248     IStream *pStream;
249 } IWICStreamImpl;
250
251 static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
252     REFIID iid, void **ppv)
253 {
254     IWICStreamImpl *This = (IWICStreamImpl*)iface;
255     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
256
257     if (!ppv) return E_INVALIDARG;
258
259     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
260         IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
261     {
262         *ppv = This;
263         IUnknown_AddRef((IUnknown*)*ppv);
264         return S_OK;
265     }
266     else
267     {
268         *ppv = NULL;
269         return E_NOINTERFACE;
270     }
271 }
272
273 static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
274 {
275     IWICStreamImpl *This = (IWICStreamImpl*)iface;
276     ULONG ref = InterlockedIncrement(&This->ref);
277
278     TRACE("(%p) refcount=%u\n", iface, ref);
279
280     return ref;
281 }
282
283 static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
284 {
285     IWICStreamImpl *This = (IWICStreamImpl*)iface;
286     ULONG ref = InterlockedDecrement(&This->ref);
287
288     TRACE("(%p) refcount=%u\n", iface, ref);
289
290     if (ref == 0) {
291         if (This->pStream) IStream_Release(This->pStream);
292         HeapFree(GetProcessHeap(), 0, This);
293     }
294     return ref;
295 }
296
297 static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
298     void *pv, ULONG cb, ULONG *pcbRead)
299 {
300     IWICStreamImpl *This = (IWICStreamImpl*)iface;
301     TRACE("(%p): relay\n", This);
302
303     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
304     return IStream_Read(This->pStream, pv, cb, pcbRead);
305 }
306
307 static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
308     void const *pv, ULONG cb, ULONG *pcbWritten)
309 {
310     IWICStreamImpl *This = (IWICStreamImpl*)iface;
311     TRACE("(%p): relay\n", This);
312
313     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
314     return IStream_Write(This->pStream, pv, cb, pcbWritten);
315 }
316
317 static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
318     LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
319 {
320     IWICStreamImpl *This = (IWICStreamImpl*)iface;
321     TRACE("(%p): relay\n", This);
322
323     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
324     return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
325 }
326
327 static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
328     ULARGE_INTEGER libNewSize)
329 {
330     IWICStreamImpl *This = (IWICStreamImpl*)iface;
331     TRACE("(%p): relay\n", This);
332
333     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
334     return IStream_SetSize(This->pStream, libNewSize);
335 }
336
337 static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
338     IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
339 {
340     IWICStreamImpl *This = (IWICStreamImpl*)iface;
341     TRACE("(%p): relay\n", This);
342
343     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
344     return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
345 }
346
347 static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
348     DWORD grfCommitFlags)
349 {
350     IWICStreamImpl *This = (IWICStreamImpl*)iface;
351     TRACE("(%p): relay\n", This);
352
353     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
354     return IStream_Commit(This->pStream, grfCommitFlags);
355 }
356
357 static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
358 {
359     IWICStreamImpl *This = (IWICStreamImpl*)iface;
360     TRACE("(%p): relay\n", This);
361
362     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
363     return IStream_Revert(This->pStream);
364 }
365
366 static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
367     ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
368 {
369     IWICStreamImpl *This = (IWICStreamImpl*)iface;
370     TRACE("(%p): relay\n", This);
371
372     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
373     return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
374 }
375
376 static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
377     ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
378 {
379     IWICStreamImpl *This = (IWICStreamImpl*)iface;
380     TRACE("(%p): relay\n", This);
381
382     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
383     return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
384 }
385
386 static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
387     STATSTG *pstatstg, DWORD grfStatFlag)
388 {
389     IWICStreamImpl *This = (IWICStreamImpl*)iface;
390     TRACE("(%p): relay\n", This);
391
392     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
393     return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
394 }
395
396 static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
397     IStream **ppstm)
398 {
399     IWICStreamImpl *This = (IWICStreamImpl*)iface;
400     TRACE("(%p): relay\n", This);
401
402     if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
403     return IStream_Clone(This->pStream, ppstm);
404 }
405
406 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
407     IStream *pIStream)
408 {
409     FIXME("(%p): stub\n", iface);
410     return E_NOTIMPL;
411 }
412
413 static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
414     LPCWSTR wzFileName, DWORD dwDesiredAccess)
415 {
416     FIXME("(%p): stub\n", iface);
417     return E_NOTIMPL;
418 }
419
420 /******************************************
421  * IWICStream_InitializeFromMemory
422  *
423  * Initializes the internal IStream object to retrieve its data from a memory chunk.
424  *
425  * PARAMS
426  *   pbBuffer     [I] pointer to the memory chunk
427  *   cbBufferSize [I] number of bytes to use from the memory chunk
428  *
429  * RETURNS
430  *   SUCCESS: S_OK
431  *   FAILURE: E_INVALIDARG, if pbBuffer is NULL
432  *            E_OUTOFMEMORY, if we run out of memory
433  *            WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
434  *
435  */
436 static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
437     BYTE *pbBuffer, DWORD cbBufferSize)
438 {
439     IWICStreamImpl *This = (IWICStreamImpl*)iface;
440     StreamOnMemory *pObject;
441     TRACE("(%p,%p)\n", iface, pbBuffer);
442
443     if (!pbBuffer) return E_INVALIDARG;
444     if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
445
446     pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
447     if (!pObject) return E_OUTOFMEMORY;
448
449     pObject->lpVtbl = &StreamOnMemory_Vtbl;
450     pObject->ref = 1;
451     pObject->pbMemory = pbBuffer;
452     pObject->dwMemsize = cbBufferSize;
453     pObject->dwCurPos = 0;
454
455     This->pStream = (IStream*)pObject;
456     return S_OK;
457 }
458
459 static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
460     IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
461 {
462     FIXME("(%p): stub\n", iface);
463     return E_NOTIMPL;
464 }
465
466
467 const IWICStreamVtbl WICStream_Vtbl =
468 {
469     /*** IUnknown methods ***/
470     IWICStreamImpl_QueryInterface,
471     IWICStreamImpl_AddRef,
472     IWICStreamImpl_Release,
473     /*** ISequentialStream methods ***/
474     IWICStreamImpl_Read,
475     IWICStreamImpl_Write,
476     /*** IStream methods ***/
477     IWICStreamImpl_Seek,
478     IWICStreamImpl_SetSize,
479     IWICStreamImpl_CopyTo,
480     IWICStreamImpl_Commit,
481     IWICStreamImpl_Revert,
482     IWICStreamImpl_LockRegion,
483     IWICStreamImpl_UnlockRegion,
484     IWICStreamImpl_Stat,
485     IWICStreamImpl_Clone,
486     /*** IWICStream methods ***/
487     IWICStreamImpl_InitializeFromIStream,
488     IWICStreamImpl_InitializeFromFilename,
489     IWICStreamImpl_InitializeFromMemory,
490     IWICStreamImpl_InitializeFromIStreamRegion,
491 };
492
493 HRESULT StreamImpl_Create(IWICStream **stream)
494 {
495     IWICStreamImpl *pObject;
496
497     if( !stream ) return E_INVALIDARG;
498
499     pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
500     if( !pObject ) {
501         *stream = NULL;
502         return E_OUTOFMEMORY;
503     }
504
505     pObject->lpVtbl = &WICStream_Vtbl;
506     pObject->ref = 1;
507     pObject->pStream = NULL;
508
509     *stream = (IWICStream*)pObject;
510
511     return S_OK;
512 }