winejoystick: Fix a crash on accessing a CFArray past its end due to an off-by-one...
[wine/multimedia.git] / dlls / dmloader / loaderstream.c
blob855203ec3e8fe4f1c7bc306453970a5228195699
1 /* IDirectMusicLoaderFileStream
2 * IDirectMusicLoaderResourceStream
3 * IDirectMusicLoaderGenericStream
5 * Copyright (C) 2003-2004 Rok Mandeljc
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* SIDE NOTES:
24 * After extensive testing and structure dumping I came to a conclusion that
25 * DirectMusic as in present state implements three types of streams:
26 * 1. IDirectMusicLoaderFileStream: stream that was most obvious, since
27 * it's used for loading from files; it is sort of wrapper around
28 * CreateFile, ReadFile, WriteFile and SetFilePointer and it supports
29 * both read and write
30 * 2. IDirectMusicLoaderResourceStream: a stream that had to exist, since
31 * according to MSDN, IDirectMusicLoader supports loading from resource
32 * as well; in this case, data is represented as a big chunk of bytes,
33 * from which we "read" (copy) data and keep the trace of our position;
34 * it supports read only
35 * 3. IDirectMusicLoaderGenericStream: this one was the most problematic,
36 * since I thought it was URL-related; besides, there's no obvious need
37 * for it, since input streams can simply be cloned, lest loading from
38 * stream is requested; but if one really thinks about it, input stream
39 * could be none of 1. or 2.; in this case, a wrapper that offers
40 * IDirectMusicGetLoader interface would be nice, and this is what this
41 * stream is; as such, all functions are supported, as long as underlying
42 * ("low-level") stream supports them
44 * - Rok Mandeljc; 24. April, 2004
47 #define NONAMELESSUNION
49 #include "dmloader_private.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
52 WINE_DECLARE_DEBUG_CHANNEL(dmfileraw);
54 static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface);
55 static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
56 static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
57 static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface);
58 static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_AddRef (LPSTREAM iface);
59 static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
62 /*****************************************************************************
63 * IDirectMusicLoaderFileStream implementation
65 /* Custom : */
67 static void IDirectMusicLoaderFileStream_Detach (LPSTREAM iface) {
68 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
69 TRACE("(%p)\n", This);
70 if (This->hFile != INVALID_HANDLE_VALUE) CloseHandle(This->hFile);
71 This->wzFileName[0] = '\0';
74 HRESULT WINAPI IDirectMusicLoaderFileStream_Attach (LPSTREAM iface, LPCWSTR wzFile, LPDIRECTMUSICLOADER8 pLoader) {
75 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
76 TRACE("(%p, %s, %p)\n", This, debugstr_w(wzFile), pLoader);
77 IDirectMusicLoaderFileStream_Detach (iface);
78 This->hFile = CreateFileW (wzFile, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
79 if (This->hFile == INVALID_HANDLE_VALUE) {
80 WARN(": failed\n");
81 return DMUS_E_LOADER_FAILEDOPEN;
83 /* create IDirectMusicGetLoader */
84 This->pLoader = pLoader;
85 lstrcpynW (This->wzFileName, wzFile, MAX_PATH);
86 TRACE(": succeeded\n");
87 return S_OK;
91 /* IUnknown/IStream part: */
92 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
93 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
95 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
96 if (IsEqualIID (riid, &IID_IUnknown) ||
97 IsEqualIID (riid, &IID_IStream)) {
98 *ppobj = &This->StreamVtbl;
99 IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
100 return S_OK;
101 } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
102 *ppobj = &This->GetLoaderVtbl;
103 IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);
104 return S_OK;
107 WARN(": not found\n");
108 return E_NOINTERFACE;
111 static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface) {
112 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
113 TRACE("(%p): AddRef from %d\n", This, This->dwRef);
114 return InterlockedIncrement (&This->dwRef);
117 static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_Release (LPSTREAM iface) {
118 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
120 DWORD dwRef = InterlockedDecrement (&This->dwRef);
121 TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
122 if (dwRef == 0) {
123 if (This->hFile)
124 IDirectMusicLoaderFileStream_Detach (iface);
125 HeapFree (GetProcessHeap(), 0, This);
128 return dwRef;
131 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
132 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
133 ULONG cbRead;
135 TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
136 if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
137 if (pcbRead == NULL) pcbRead = &cbRead;
138 if (!ReadFile (This->hFile, pv, cb, pcbRead, NULL) || *pcbRead != cb) return E_FAIL;
140 TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", *pcbRead, debugstr_an(pv, *pcbRead));
141 return S_OK;
144 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
145 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
146 LARGE_INTEGER liNewPos;
148 TRACE_(dmfileraw)("(%p, %s, %s, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
150 if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
152 liNewPos.u.HighPart = dlibMove.u.HighPart;
153 liNewPos.u.LowPart = SetFilePointer (This->hFile, dlibMove.u.LowPart, &liNewPos.u.HighPart, dwOrigin);
155 if (liNewPos.u.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) return E_FAIL;
156 if (plibNewPosition) plibNewPosition->QuadPart = liNewPos.QuadPart;
158 return S_OK;
161 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
162 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
163 LPSTREAM pOther = NULL;
164 HRESULT result;
166 TRACE("(%p, %p)\n", iface, ppstm);
167 result = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pOther);
168 if (FAILED(result)) return result;
169 if (This->hFile != INVALID_HANDLE_VALUE) {
170 ULARGE_INTEGER ullCurrentPosition;
171 result = IDirectMusicLoaderFileStream_Attach (pOther, This->wzFileName, This->pLoader);
172 if (SUCCEEDED(result)) {
173 LARGE_INTEGER liZero;
174 liZero.QuadPart = 0;
175 result = IDirectMusicLoaderFileStream_IStream_Seek (iface, liZero, STREAM_SEEK_CUR, &ullCurrentPosition); /* get current position in current stream */
177 if (SUCCEEDED(result)) {
178 LARGE_INTEGER liNewPosition;
179 liNewPosition.QuadPart = ullCurrentPosition.QuadPart;
180 result = IDirectMusicLoaderFileStream_IStream_Seek (pOther, liNewPosition, STREAM_SEEK_SET, &ullCurrentPosition);
182 if (FAILED(result)) {
183 TRACE(": failed\n");
184 IDirectMusicLoaderFileStream_IStream_Release (pOther);
185 return result;
188 TRACE(": succeeded\n");
189 *ppstm = pOther;
190 return S_OK;
193 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
194 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
195 ULONG cbWrite;
197 TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbWritten);
198 if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
199 if (pcbWritten == NULL) pcbWritten = &cbWrite;
200 if (!WriteFile (This->hFile, pv, cb, pcbWritten, NULL) || *pcbWritten != cb) return E_FAIL;
202 TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", *pcbWritten, debugstr_an(pv, *pcbWritten));
203 return S_OK;
206 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
207 ERR(": should not be needed\n");
208 return E_NOTIMPL;
211 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
212 ERR(": should not be needed\n");
213 return E_NOTIMPL;
216 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
217 ERR(": should not be needed\n");
218 return E_NOTIMPL;
221 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Revert (LPSTREAM iface) {
222 ERR(": should not be needed\n");
223 return E_NOTIMPL;
226 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
227 ERR(": should not be needed\n");
228 return E_NOTIMPL;
231 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
232 ERR(": should not be needed\n");
233 return E_NOTIMPL;
236 static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
237 ERR(": should not be needed\n");
238 return E_NOTIMPL;
241 static const IStreamVtbl DirectMusicLoaderFileStream_Stream_Vtbl = {
242 IDirectMusicLoaderFileStream_IStream_QueryInterface,
243 IDirectMusicLoaderFileStream_IStream_AddRef,
244 IDirectMusicLoaderFileStream_IStream_Release,
245 IDirectMusicLoaderFileStream_IStream_Read,
246 IDirectMusicLoaderFileStream_IStream_Write,
247 IDirectMusicLoaderFileStream_IStream_Seek,
248 IDirectMusicLoaderFileStream_IStream_SetSize,
249 IDirectMusicLoaderFileStream_IStream_CopyTo,
250 IDirectMusicLoaderFileStream_IStream_Commit,
251 IDirectMusicLoaderFileStream_IStream_Revert,
252 IDirectMusicLoaderFileStream_IStream_LockRegion,
253 IDirectMusicLoaderFileStream_IStream_UnlockRegion,
254 IDirectMusicLoaderFileStream_IStream_Stat,
255 IDirectMusicLoaderFileStream_IStream_Clone
258 /* IDirectMusicGetLoader part: */
259 static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
260 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
261 return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
264 static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
265 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
266 return IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
269 static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
270 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
271 return IDirectMusicLoaderFileStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
274 static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
275 ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
277 TRACE("(%p, %p)\n", This, ppLoader);
278 *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
279 IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
281 return S_OK;
284 static const IDirectMusicGetLoaderVtbl DirectMusicLoaderFileStream_GetLoader_Vtbl = {
285 IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface,
286 IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef,
287 IDirectMusicLoaderFileStream_IDirectMusicGetLoader_Release,
288 IDirectMusicLoaderFileStream_IDirectMusicGetLoader_GetLoader
291 HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderFileStream (LPVOID* ppobj) {
292 IDirectMusicLoaderFileStream *obj;
294 TRACE("(%p)\n", ppobj);
295 obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderFileStream));
296 if (NULL == obj) {
297 *ppobj = NULL;
298 return E_OUTOFMEMORY;
300 obj->StreamVtbl = &DirectMusicLoaderFileStream_Stream_Vtbl;
301 obj->GetLoaderVtbl = &DirectMusicLoaderFileStream_GetLoader_Vtbl;
302 obj->dwRef = 0; /* will be inited with QueryInterface */
304 return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
308 /*****************************************************************************
309 * IDirectMusicLoaderResourceStream implementation
311 /* Custom : */
313 static void IDirectMusicLoaderResourceStream_Detach (LPSTREAM iface) {
314 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
315 TRACE("(%p)\n", This);
317 This->pbMemData = NULL;
318 This->llMemLength = 0;
321 HRESULT WINAPI IDirectMusicLoaderResourceStream_Attach (LPSTREAM iface, LPBYTE pbMemData, LONGLONG llMemLength, LONGLONG llPos, LPDIRECTMUSICLOADER8 pLoader) {
322 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
324 TRACE("(%p, %p, %s, %s, %p)\n", This, pbMemData, wine_dbgstr_longlong(llMemLength), wine_dbgstr_longlong(llPos), pLoader);
325 if (!pbMemData || !llMemLength) {
326 WARN(": invalid pbMemData or llMemLength\n");
327 return E_FAIL;
329 IDirectMusicLoaderResourceStream_Detach (iface);
330 This->pbMemData = pbMemData;
331 This->llMemLength = llMemLength;
332 This->llPos = llPos;
333 This->pLoader = pLoader;
335 return S_OK;
339 /* IUnknown/IStream part: */
340 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
341 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
343 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
344 if (IsEqualIID (riid, &IID_IUnknown) ||
345 IsEqualIID (riid, &IID_IStream)) {
346 *ppobj = &This->StreamVtbl;
347 IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
348 return S_OK;
349 } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
350 *ppobj = &This->GetLoaderVtbl;
351 IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);
352 return S_OK;
355 WARN(": not found\n");
356 return E_NOINTERFACE;
359 static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface) {
360 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
361 TRACE("(%p): AddRef from %d\n", This, This->dwRef);
362 return InterlockedIncrement (&This->dwRef);
365 static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_Release (LPSTREAM iface) {
366 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
368 DWORD dwRef = InterlockedDecrement (&This->dwRef);
369 TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
370 if (dwRef == 0) {
371 IDirectMusicLoaderResourceStream_Detach (iface);
372 HeapFree (GetProcessHeap(), 0, This);
375 return dwRef;
378 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
379 LPBYTE pByte;
380 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
382 TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
383 if ((This->llPos + cb) > This->llMemLength) {
384 WARN_(dmfileraw)(": requested size out of range\n");
385 return E_FAIL;
388 pByte = &This->pbMemData[This->llPos];
389 memcpy (pv, pByte, cb);
390 This->llPos += cb; /* move pointer */
391 /* FIXME: error checking would be nice */
392 if (pcbRead) *pcbRead = cb;
394 TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", cb, debugstr_an(pv, cb));
395 return S_OK;
398 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
399 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
400 TRACE_(dmfileraw)("(%p, %s, %s, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
402 switch (dwOrigin) {
403 case STREAM_SEEK_CUR: {
404 if ((This->llPos + dlibMove.QuadPart) > This->llMemLength) {
405 WARN_(dmfileraw)(": requested offset out of range\n");
406 return E_FAIL;
408 break;
410 case STREAM_SEEK_SET: {
411 if (dlibMove.QuadPart > This->llMemLength) {
412 WARN_(dmfileraw)(": requested offset out of range\n");
413 return E_FAIL;
415 /* set to the beginning of the stream */
416 This->llPos = 0;
417 break;
419 case STREAM_SEEK_END: {
420 /* TODO: check if this is true... I do think offset should be negative in this case */
421 if (dlibMove.QuadPart > 0) {
422 WARN_(dmfileraw)(": requested offset out of range\n");
423 return E_FAIL;
425 /* set to the end of the stream */
426 This->llPos = This->llMemLength;
427 break;
429 default: {
430 ERR_(dmfileraw)(": invalid dwOrigin\n");
431 return E_FAIL;
434 /* now simply add */
435 This->llPos += dlibMove.QuadPart;
437 if (plibNewPosition) plibNewPosition->QuadPart = This->llPos;
439 return S_OK;
442 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
443 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
444 LPSTREAM pOther = NULL;
445 HRESULT result;
447 TRACE("(%p, %p)\n", iface, ppstm);
448 result = DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID*)&pOther);
449 if (FAILED(result)) return result;
451 IDirectMusicLoaderResourceStream_Attach (pOther, This->pbMemData, This->llMemLength, This->llPos, This->pLoader);
453 TRACE(": succeeded\n");
454 *ppstm = pOther;
455 return S_OK;
458 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
459 ERR(": should not be needed\n");
460 return E_NOTIMPL;
463 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
464 ERR(": should not be needed\n");
465 return E_NOTIMPL;
468 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
469 ERR(": should not be needed\n");
470 return E_NOTIMPL;
473 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
474 ERR(": should not be needed\n");
475 return E_NOTIMPL;
478 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Revert (LPSTREAM iface) {
479 ERR(": should not be needed\n");
480 return E_NOTIMPL;
483 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
484 ERR(": should not be needed\n");
485 return E_NOTIMPL;
488 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
489 ERR(": should not be needed\n");
490 return E_NOTIMPL;
493 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
494 ERR(": should not be needed\n");
495 return E_NOTIMPL;
498 static const IStreamVtbl DirectMusicLoaderResourceStream_Stream_Vtbl = {
499 IDirectMusicLoaderResourceStream_IStream_QueryInterface,
500 IDirectMusicLoaderResourceStream_IStream_AddRef,
501 IDirectMusicLoaderResourceStream_IStream_Release,
502 IDirectMusicLoaderResourceStream_IStream_Read,
503 IDirectMusicLoaderResourceStream_IStream_Write,
504 IDirectMusicLoaderResourceStream_IStream_Seek,
505 IDirectMusicLoaderResourceStream_IStream_SetSize,
506 IDirectMusicLoaderResourceStream_IStream_CopyTo,
507 IDirectMusicLoaderResourceStream_IStream_Commit,
508 IDirectMusicLoaderResourceStream_IStream_Revert,
509 IDirectMusicLoaderResourceStream_IStream_LockRegion,
510 IDirectMusicLoaderResourceStream_IStream_UnlockRegion,
511 IDirectMusicLoaderResourceStream_IStream_Stat,
512 IDirectMusicLoaderResourceStream_IStream_Clone
515 /* IDirectMusicGetLoader part: */
516 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
517 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
518 return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
521 static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
522 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
523 return IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
526 static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
527 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
528 return IDirectMusicLoaderResourceStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
531 static HRESULT WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
532 ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
534 TRACE("(%p, %p)\n", This, ppLoader);
535 *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
536 IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
538 return S_OK;
541 static const IDirectMusicGetLoaderVtbl DirectMusicLoaderResourceStream_GetLoader_Vtbl = {
542 IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_QueryInterface,
543 IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef,
544 IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_Release,
545 IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_GetLoader
548 HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderResourceStream (LPVOID* ppobj) {
549 IDirectMusicLoaderResourceStream *obj;
551 TRACE("(%p)\n", ppobj);
552 obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderResourceStream));
553 if (NULL == obj) {
554 *ppobj = NULL;
555 return E_OUTOFMEMORY;
557 obj->StreamVtbl = &DirectMusicLoaderResourceStream_Stream_Vtbl;
558 obj->GetLoaderVtbl = &DirectMusicLoaderResourceStream_GetLoader_Vtbl;
559 obj->dwRef = 0; /* will be inited with QueryInterface */
561 return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
565 /*****************************************************************************
566 * IDirectMusicLoaderGenericStream implementation
568 /* Custom : */
570 static void IDirectMusicLoaderGenericStream_Detach (LPSTREAM iface) {
571 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
573 if (This->pStream)
574 IStream_Release (This->pStream);
575 This->pStream = NULL;
578 HRESULT WINAPI IDirectMusicLoaderGenericStream_Attach (LPSTREAM iface, LPSTREAM pStream, LPDIRECTMUSICLOADER8 pLoader) {
579 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
581 TRACE("(%p, %p, %p)\n", This, pStream, pLoader);
582 if (!pStream) {
583 WARN(": invalid pStream\n");
584 return E_FAIL;
586 if (!pLoader) {
587 WARN(": invalid pLoader\n");
588 return E_FAIL;
591 IDirectMusicLoaderGenericStream_Detach (iface);
592 IStream_Clone (pStream, &This->pStream);
593 This->pLoader = pLoader;
595 return S_OK;
599 /* IUnknown/IStream part: */
600 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
601 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
603 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
604 if (IsEqualIID (riid, &IID_IUnknown) ||
605 IsEqualIID (riid, &IID_IStream)) {
606 *ppobj = &This->StreamVtbl;
607 IDirectMusicLoaderGenericStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
608 return S_OK;
609 } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
610 *ppobj = &This->GetLoaderVtbl;
611 IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);
612 return S_OK;
615 WARN(": not found\n");
616 return E_NOINTERFACE;
619 static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_AddRef (LPSTREAM iface) {
620 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
621 TRACE("(%p): AddRef from %d\n", This, This->dwRef);
622 return InterlockedIncrement (&This->dwRef);
625 static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_Release (LPSTREAM iface) {
626 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
628 DWORD dwRef = InterlockedDecrement (&This->dwRef);
629 TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
630 if (dwRef == 0) {
631 IDirectMusicLoaderGenericStream_Detach (iface);
632 HeapFree (GetProcessHeap(), 0, This);
635 return dwRef;
638 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
639 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
641 TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p): redirecting to low-level stream\n", This, pv, cb, pcbRead);
642 if (!This->pStream)
643 return E_FAIL;
645 return IStream_Read (This->pStream, pv, cb, pcbRead);
648 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
649 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
650 TRACE_(dmfileraw)("(%p, %s, %s, %p): redirecting to low-level stream\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
651 if (!This->pStream)
652 return E_FAIL;
654 return IStream_Seek (This->pStream, dlibMove, dwOrigin, plibNewPosition);
657 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
658 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
659 LPSTREAM pOther = NULL;
660 LPSTREAM pLowLevel = NULL;
661 HRESULT result;
663 TRACE("(%p, %p)\n", iface, ppstm);
664 result = DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID*)&pOther);
665 if (FAILED(result)) return result;
667 if (FAILED(IStream_Clone (This->pStream, &pLowLevel)))
668 return E_FAIL;
670 IDirectMusicLoaderGenericStream_Attach (pOther, pLowLevel, This->pLoader);
672 TRACE(": succeeded\n");
673 *ppstm = pOther;
674 return S_OK;
677 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
678 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
679 TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p): redirecting to low-level stream\n", This, pv, cb, pcbWritten);
680 if (!This->pStream)
681 return E_FAIL;
683 return IStream_Write (This->pStream, pv, cb, pcbWritten);
686 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
687 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
688 TRACE("(%p, %s): redirecting to low-level stream\n", This, wine_dbgstr_longlong(libNewSize.QuadPart));
689 if (!This->pStream)
690 return E_FAIL;
692 return IStream_SetSize (This->pStream, libNewSize);
695 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
696 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
697 TRACE("(%p, %p, %s, %p, %p): redirecting to low-level stream\n", This, pstm, wine_dbgstr_longlong(cb.QuadPart), pcbRead, pcbWritten);
698 if (!This->pStream)
699 return E_FAIL;
701 return IStream_CopyTo (This->pStream, pstm, cb, pcbRead, pcbWritten);
704 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
705 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
706 TRACE("(%p, 0x%08X): redirecting to low-level stream\n", This, grfCommitFlags);
707 if (!This->pStream)
708 return E_FAIL;
710 return IStream_Commit (This->pStream, grfCommitFlags);
713 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Revert (LPSTREAM iface) {
714 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
715 TRACE("(%p): redirecting to low-level stream\n", This);
716 if (!This->pStream)
717 return E_FAIL;
719 return IStream_Revert (This->pStream);
722 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
723 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
724 TRACE("(%p, %s, %s, 0x%08X): redirecting to low-level stream\n", This, wine_dbgstr_longlong(libOffset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), dwLockType);
725 if (!This->pStream)
726 return E_FAIL;
728 return IStream_LockRegion (This->pStream, libOffset, cb, dwLockType);
731 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
732 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
733 TRACE("(%p, %s, %s, 0x%08X): redirecting to low-level stream\n", This, wine_dbgstr_longlong(libOffset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), dwLockType);
734 if (!This->pStream)
735 return E_FAIL;
737 return IStream_UnlockRegion (This->pStream, libOffset, cb, dwLockType);
740 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
741 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
742 TRACE("(%p, %p, 0x%08X): redirecting to low-level stream\n", This, pstatstg, grfStatFlag);
743 if (!This->pStream)
744 return E_FAIL;
746 return IStream_Stat (This->pStream, pstatstg, grfStatFlag);
749 static const IStreamVtbl DirectMusicLoaderGenericStream_Stream_Vtbl = {
750 IDirectMusicLoaderGenericStream_IStream_QueryInterface,
751 IDirectMusicLoaderGenericStream_IStream_AddRef,
752 IDirectMusicLoaderGenericStream_IStream_Release,
753 IDirectMusicLoaderGenericStream_IStream_Read,
754 IDirectMusicLoaderGenericStream_IStream_Write,
755 IDirectMusicLoaderGenericStream_IStream_Seek,
756 IDirectMusicLoaderGenericStream_IStream_SetSize,
757 IDirectMusicLoaderGenericStream_IStream_CopyTo,
758 IDirectMusicLoaderGenericStream_IStream_Commit,
759 IDirectMusicLoaderGenericStream_IStream_Revert,
760 IDirectMusicLoaderGenericStream_IStream_LockRegion,
761 IDirectMusicLoaderGenericStream_IStream_UnlockRegion,
762 IDirectMusicLoaderGenericStream_IStream_Stat,
763 IDirectMusicLoaderGenericStream_IStream_Clone
766 /* IDirectMusicGetLoader part: */
767 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
768 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
769 return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
772 static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
773 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
774 return IDirectMusicLoaderGenericStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
777 static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
778 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
779 return IDirectMusicLoaderGenericStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
782 static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
783 ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
785 TRACE("(%p, %p)\n", This, ppLoader);
786 *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
787 IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
789 return S_OK;
792 static const IDirectMusicGetLoaderVtbl DirectMusicLoaderGenericStream_GetLoader_Vtbl = {
793 IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface,
794 IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef,
795 IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release,
796 IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_GetLoader
799 HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderGenericStream (LPVOID* ppobj) {
800 IDirectMusicLoaderGenericStream *obj;
802 TRACE("(%p)\n", ppobj);
803 obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderGenericStream));
804 if (NULL == obj) {
805 *ppobj = NULL;
806 return E_OUTOFMEMORY;
808 obj->StreamVtbl = &DirectMusicLoaderGenericStream_Stream_Vtbl;
809 obj->GetLoaderVtbl = &DirectMusicLoaderGenericStream_GetLoader_Vtbl;
810 obj->dwRef = 0; /* will be inited with QueryInterface */
812 return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);