loaderstream.c 32.2 KB
Newer Older
1 2 3
/* IDirectMusicLoaderFileStream
 * IDirectMusicLoaderResourceStream
 * IDirectMusicLoaderGenericStream
4
 *
5
 * Copyright (C) 2003-2004 Rok Mandeljc
6
 *
7 8 9 10
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
11 12 13
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
16
 *
17 18 19
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21
 */

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

/* SIDE NOTES:
 * After extensive testing and structure dumping I came to a conclusion that
 * DirectMusic as in present state implements three types of streams:
 *  1. IDirectMusicLoaderFileStream: stream that was most obvious, since 
 *     it's used for loading from files; it is sort of wrapper around 
 *     CreateFile, ReadFile, WriteFile and SetFilePointer and it supports 
 *     both read and write
 *  2. IDirectMusicLoaderResourceStream: a stream that had to exist, since 
 *     according to MSDN, IDirectMusicLoader supports loading from resource 
 *     as well; in this case, data is represented as a big chunk of bytes, 
 *     from which we "read" (copy) data and keep the trace of our position; 
 *      it supports read only
 *  3. IDirectMusicLoaderGenericStream: this one was the most problematic, 
 *     since I thought it was URL-related; besides, there's no obvious need 
 *     for it, since input streams can simply be cloned, lest loading from 
 *     stream is requested; but if one really thinks about it, input stream 
 *     could be none of 1. or 2.; in this case, a wrapper that offers
 *     IDirectMusicGetLoader interface would be nice, and this is what this 
 *     stream is; as such, all functions are supported, as long as underlying 
 *     ("low-level") stream supports them
 *
 * - Rok Mandeljc; 24. april, 2004
*/

47 48 49 50 51 52
#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "dmloader_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
53
WINE_DECLARE_DEBUG_CHANNEL(dmfileraw);
54

55 56 57 58 59 60 61 62
static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);


63
/*****************************************************************************
64
 * IDirectMusicLoaderFileStream implementation
65
 */
66
/* Custom : */
67 68 69 70 71 72 73 74

static void IDirectMusicLoaderFileStream_Detach (LPSTREAM iface) {
    ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    TRACE("(%p)\n", This);
    if (This->hFile != INVALID_HANDLE_VALUE) CloseHandle(This->hFile);
    This->wzFileName[0] = '\0';
}

75
HRESULT WINAPI IDirectMusicLoaderFileStream_Attach (LPSTREAM iface, LPCWSTR wzFile, LPDIRECTMUSICLOADER8 pLoader) {
76
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
77
    TRACE("(%p, %s, %p)\n", This, debugstr_w(wzFile), pLoader);
78 79
    IDirectMusicLoaderFileStream_Detach (iface);
    This->hFile = CreateFileW (wzFile, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
80
    if (This->hFile == INVALID_HANDLE_VALUE) {
81
        WARN(": failed\n");
82
        return DMUS_E_LOADER_FAILEDOPEN;
83
    }
84
    /* create IDirectMusicGetLoader */
85
    This->pLoader = pLoader;
86
    lstrcpynW (This->wzFileName, wzFile, MAX_PATH);
87
    TRACE(": succeeded\n");
88 89 90
    return S_OK;
}

91 92

/* IUnknown/IStream part: */
93
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
94
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
95
	
96
	TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
97 98
	if (IsEqualIID (riid, &IID_IUnknown) ||
		IsEqualIID (riid, &IID_IStream)) {
99
		*ppobj = (LPVOID)&This->StreamVtbl;
100
		IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
101 102 103
		return S_OK;
	} else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
		*ppobj = (LPVOID)&This->GetLoaderVtbl;
104
		IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);		
105 106 107
		return S_OK;
	}

108
	WARN(": not found\n");
109 110 111
	return E_NOINTERFACE;
}

112
static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface) {
113
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
114
	TRACE("(%p): AddRef from %d\n", This, This->dwRef);
115
	return InterlockedIncrement (&This->dwRef);
116 117
}

118
static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_Release (LPSTREAM iface) {
119 120 121
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
	
	DWORD dwRef = InterlockedDecrement (&This->dwRef);
122
	TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
123
	if (dwRef == 0) {
124 125 126
		if (This->hFile)
			IDirectMusicLoaderFileStream_Detach (iface);
		HeapFree (GetProcessHeap(), 0, This);
127
	}
128 129
	
	return dwRef;
130 131
}

132
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
133
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
134
    ULONG cbRead;
135
	
136
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
137 138 139
    if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
    if (pcbRead == NULL) pcbRead = &cbRead;
    if (!ReadFile (This->hFile, pv, cb, pcbRead, NULL) || *pcbRead != cb) return E_FAIL;
140
	
141
	TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", *pcbRead, debugstr_an(pv, *pcbRead));
142 143 144
    return S_OK;
}

145
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
146
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
147
    LARGE_INTEGER liNewPos;
148
	
149
    TRACE_(dmfileraw)("(%p, %s, %s, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
150

151
    if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
152

153 154
    liNewPos.u.HighPart = dlibMove.u.HighPart;
    liNewPos.u.LowPart = SetFilePointer (This->hFile, dlibMove.u.LowPart, &liNewPos.u.HighPart, dwOrigin);
155

156
    if (liNewPos.u.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) return E_FAIL;
157 158 159 160 161
    if (plibNewPosition) plibNewPosition->QuadPart = liNewPos.QuadPart;
    
    return S_OK;
}

162
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
163
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
164
	LPSTREAM pOther = NULL;
165 166 167
	HRESULT result;

	TRACE("(%p, %p)\n", iface, ppstm);
168
	result = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pOther);
169 170 171
	if (FAILED(result)) return result;
	if (This->hFile != INVALID_HANDLE_VALUE) {
		ULARGE_INTEGER ullCurrentPosition;
172
		result = IDirectMusicLoaderFileStream_Attach (pOther, This->wzFileName, This->pLoader);
173 174 175
		if (SUCCEEDED(result)) {
			LARGE_INTEGER liZero;
			liZero.QuadPart = 0;
176
			result = IDirectMusicLoaderFileStream_IStream_Seek (iface, liZero, STREAM_SEEK_CUR, &ullCurrentPosition); /* get current position in current stream */
177 178 179 180
        }
		if (SUCCEEDED(result)) {
			LARGE_INTEGER liNewPosition;
			liNewPosition.QuadPart = ullCurrentPosition.QuadPart;
181
			result = IDirectMusicLoaderFileStream_IStream_Seek (pOther, liNewPosition, STREAM_SEEK_SET, &ullCurrentPosition);
182 183 184
		}
		if (FAILED(result)) {
			TRACE(": failed\n");
185
			IDirectMusicLoaderFileStream_IStream_Release (pOther);
186 187 188 189
			return result;
		}
	}
	TRACE(": succeeded\n");
190
	*ppstm = pOther;
191 192 193
	return S_OK;
}

194
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
195 196 197
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    ULONG cbWrite;
	
198
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbWritten);
199 200 201 202
    if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
    if (pcbWritten == NULL) pcbWritten = &cbWrite;
    if (!WriteFile (This->hFile, pv, cb, pcbWritten, NULL) || *pcbWritten != cb) return E_FAIL;
	
203
	TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", *pcbWritten, debugstr_an(pv, *pcbWritten));
204 205 206
    return S_OK;
}

207
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
208 209 210 211
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

212
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
213 214 215 216
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

217
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
218 219 220 221
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

222
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Revert (LPSTREAM iface) {
223 224 225 226
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

227
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
228 229 230 231
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

232
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
233 234 235 236
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

237
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
238 239 240 241
	ERR(": should not be needed\n");
    return E_NOTIMPL;
}

242
static const IStreamVtbl DirectMusicLoaderFileStream_Stream_Vtbl = {
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
	IDirectMusicLoaderFileStream_IStream_QueryInterface,
	IDirectMusicLoaderFileStream_IStream_AddRef,
	IDirectMusicLoaderFileStream_IStream_Release,
	IDirectMusicLoaderFileStream_IStream_Read,
	IDirectMusicLoaderFileStream_IStream_Write,
	IDirectMusicLoaderFileStream_IStream_Seek,
	IDirectMusicLoaderFileStream_IStream_SetSize,
	IDirectMusicLoaderFileStream_IStream_CopyTo,
	IDirectMusicLoaderFileStream_IStream_Commit,
	IDirectMusicLoaderFileStream_IStream_Revert,
	IDirectMusicLoaderFileStream_IStream_LockRegion,
	IDirectMusicLoaderFileStream_IStream_UnlockRegion,
	IDirectMusicLoaderFileStream_IStream_Stat,
	IDirectMusicLoaderFileStream_IStream_Clone
};

/* IDirectMusicGetLoader part: */
260
static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
261 262 263 264
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

265
static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
266 267 268 269
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
}

270
static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
271 272 273 274
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderFileStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
}

275
static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
276 277 278 279 280 281 282 283 284
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);

	TRACE("(%p, %p)\n", This, ppLoader);
	*ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
	IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
	
	return S_OK;
}

285
static const IDirectMusicGetLoaderVtbl DirectMusicLoaderFileStream_GetLoader_Vtbl = {
286 287 288 289 290 291 292 293 294 295 296 297
	IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface,
	IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef,
	IDirectMusicLoaderFileStream_IDirectMusicGetLoader_Release,
	IDirectMusicLoaderFileStream_IDirectMusicGetLoader_GetLoader
};

HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderFileStream (LPVOID* ppobj) {
	IDirectMusicLoaderFileStream *obj;

	TRACE("(%p)\n", ppobj);
	obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderFileStream));
	if (NULL == obj) {
298
		*ppobj = NULL;
299 300 301 302 303 304 305 306 307 308 309 310 311 312
		return E_OUTOFMEMORY;
	}
	obj->StreamVtbl = &DirectMusicLoaderFileStream_Stream_Vtbl;
	obj->GetLoaderVtbl = &DirectMusicLoaderFileStream_GetLoader_Vtbl;
	obj->dwRef = 0; /* will be inited with QueryInterface */

	return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
}


/*****************************************************************************
 * IDirectMusicLoaderResourceStream implementation
 */
/* Custom : */
313 314 315 316 317 318 319 320 321

static void IDirectMusicLoaderResourceStream_Detach (LPSTREAM iface) {
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
	TRACE("(%p)\n", This);

	This->pbMemData = NULL;
	This->llMemLength = 0;
}

322
HRESULT WINAPI IDirectMusicLoaderResourceStream_Attach (LPSTREAM iface, LPBYTE pbMemData, LONGLONG llMemLength, LONGLONG llPos, LPDIRECTMUSICLOADER8 pLoader) {
323 324
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
    
325
	TRACE("(%p, %p, %s, %s, %p)\n", This, pbMemData, wine_dbgstr_longlong(llMemLength), wine_dbgstr_longlong(llPos), pLoader);
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	if (!pbMemData || !llMemLength) {
		WARN(": invalid pbMemData or llMemLength\n");
		return E_FAIL;
	}
	IDirectMusicLoaderResourceStream_Detach (iface);
	This->pbMemData = pbMemData;
	This->llMemLength = llMemLength;
	This->llPos = llPos;
	This->pLoader = pLoader;
	
    return S_OK;
}


/* IUnknown/IStream part: */
341
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
	
	TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
	if (IsEqualIID (riid, &IID_IUnknown) ||
		IsEqualIID (riid, &IID_IStream)) {
		*ppobj = (LPVOID)&This->StreamVtbl;
		IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
		return S_OK;
	} else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
		*ppobj = (LPVOID)&This->GetLoaderVtbl;
		IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);		
		return S_OK;
	}

	WARN(": not found\n");
	return E_NOINTERFACE;
}

360
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface) {
361
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
362
	TRACE("(%p): AddRef from %d\n", This, This->dwRef);
363 364 365
	return InterlockedIncrement (&This->dwRef);
}

366
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_Release (LPSTREAM iface) {
367 368 369
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
	
	DWORD dwRef = InterlockedDecrement (&This->dwRef);
370
	TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
371
	if (dwRef == 0) {
372 373
		IDirectMusicLoaderResourceStream_Detach (iface);
		HeapFree (GetProcessHeap(), 0, This);
374 375 376 377 378
	}
	
	return dwRef;
}

379
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
380 381 382
	LPBYTE pByte;
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
	
383
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
384 385 386 387 388 389 390 391 392
	if ((This->llPos + cb) > This->llMemLength) {
		WARN_(dmfileraw)(": requested size out of range\n");
		return E_FAIL;
	}
	
	pByte = &This->pbMemData[This->llPos];
	memcpy (pv, pByte, cb);
	This->llPos += cb; /* move pointer */
	/* FIXME: error checking would be nice */
393
	if (pcbRead) *pcbRead = cb;
394
	
395
	TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", cb, debugstr_an(pv, cb));
396 397 398
    return S_OK;
}

399
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
400
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);	
401
	TRACE_(dmfileraw)("(%p, %s, %s, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
	
	switch (dwOrigin) {
		case STREAM_SEEK_CUR: {
			if ((This->llPos + dlibMove.QuadPart) > This->llMemLength) {
				WARN_(dmfileraw)(": requested offset out of range\n");
				return E_FAIL;
			}
			break;
		}
		case STREAM_SEEK_SET: {
			if (dlibMove.QuadPart > This->llMemLength) {
				WARN_(dmfileraw)(": requested offset out of range\n");
				return E_FAIL;
			}
			/* set to the beginning of the stream */
			This->llPos = 0;
			break;
		}
		case STREAM_SEEK_END: {
			/* TODO: check if this is true... I do think offset should be negative in this case */
			if (dlibMove.QuadPart > 0) {
				WARN_(dmfileraw)(": requested offset out of range\n");
				return E_FAIL;
			}
			/* set to the end of the stream */
			This->llPos = This->llMemLength;
			break;
		}
		default: {
			ERR_(dmfileraw)(": invalid dwOrigin\n");
			return E_FAIL;
		}
	}
	/* now simply add */
	This->llPos += dlibMove.QuadPart;

	if (plibNewPosition) plibNewPosition->QuadPart = This->llPos;
    	
    return S_OK;
}

443
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
444 445 446 447 448 449 450 451 452 453 454
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
	LPSTREAM pOther = NULL;
	HRESULT result;

	TRACE("(%p, %p)\n", iface, ppstm);
	result = DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID*)&pOther);
	if (FAILED(result)) return result;
	
	IDirectMusicLoaderResourceStream_Attach (pOther, This->pbMemData, This->llMemLength, This->llPos, This->pLoader);

	TRACE(": succeeded\n");
455
	*ppstm = pOther;
456 457 458
	return S_OK;
}

459
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
460
	ERR(": should not be needed\n");
461
    return E_NOTIMPL;
462 463
}

464
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
465
	ERR(": should not be needed\n");
466 467 468
    return E_NOTIMPL;
}

469
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
470
	ERR(": should not be needed\n");
471 472 473
    return E_NOTIMPL;
}

474
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
475
	ERR(": should not be needed\n");
476 477 478
    return E_NOTIMPL;
}

479
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Revert (LPSTREAM iface) {
480
	ERR(": should not be needed\n");
481 482 483
    return E_NOTIMPL;
}

484
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
485
	ERR(": should not be needed\n");
486 487 488
    return E_NOTIMPL;
}

489
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
490
	ERR(": should not be needed\n");
491 492 493
    return E_NOTIMPL;
}

494
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
495
	ERR(": should not be needed\n");
496 497 498
    return E_NOTIMPL;
}

499
static const IStreamVtbl DirectMusicLoaderResourceStream_Stream_Vtbl = {
500 501 502 503 504 505 506 507 508 509 510 511 512 513
	IDirectMusicLoaderResourceStream_IStream_QueryInterface,
	IDirectMusicLoaderResourceStream_IStream_AddRef,
	IDirectMusicLoaderResourceStream_IStream_Release,
	IDirectMusicLoaderResourceStream_IStream_Read,
	IDirectMusicLoaderResourceStream_IStream_Write,
	IDirectMusicLoaderResourceStream_IStream_Seek,
	IDirectMusicLoaderResourceStream_IStream_SetSize,
	IDirectMusicLoaderResourceStream_IStream_CopyTo,
	IDirectMusicLoaderResourceStream_IStream_Commit,
	IDirectMusicLoaderResourceStream_IStream_Revert,
	IDirectMusicLoaderResourceStream_IStream_LockRegion,
	IDirectMusicLoaderResourceStream_IStream_UnlockRegion,
	IDirectMusicLoaderResourceStream_IStream_Stat,
	IDirectMusicLoaderResourceStream_IStream_Clone
514 515
};

516
/* IDirectMusicGetLoader part: */
517
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
518 519 520 521
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

522
static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
523 524 525 526
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
}

527
static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
528 529 530 531
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderResourceStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
}

532
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
533 534 535 536 537 538 539 540 541
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);

	TRACE("(%p, %p)\n", This, ppLoader);
	*ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
	IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
	
	return S_OK;
}

542
static const IDirectMusicGetLoaderVtbl DirectMusicLoaderResourceStream_GetLoader_Vtbl = {
543 544 545 546 547 548 549 550 551 552 553 554
	IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_QueryInterface,
	IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef,
	IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_Release,
	IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_GetLoader
};

HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderResourceStream (LPVOID* ppobj) {
	IDirectMusicLoaderResourceStream *obj;

	TRACE("(%p)\n", ppobj);
	obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderResourceStream));
	if (NULL == obj) {
555
		*ppobj = NULL;
556 557 558 559 560 561 562 563 564 565
		return E_OUTOFMEMORY;
	}
	obj->StreamVtbl = &DirectMusicLoaderResourceStream_Stream_Vtbl;
	obj->GetLoaderVtbl = &DirectMusicLoaderResourceStream_GetLoader_Vtbl;
	obj->dwRef = 0; /* will be inited with QueryInterface */

	return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
}


566
/*****************************************************************************
567
 * IDirectMusicLoaderGenericStream implementation
568
 */
569
/* Custom : */
570 571 572 573 574 575 576 577 578

static void IDirectMusicLoaderGenericStream_Detach (LPSTREAM iface) {
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);

	if (This->pStream)
		IStream_Release (This->pStream);
	This->pStream = NULL;
}

579
HRESULT WINAPI IDirectMusicLoaderGenericStream_Attach (LPSTREAM iface, LPSTREAM pStream, LPDIRECTMUSICLOADER8 pLoader) {
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
    
	TRACE("(%p, %p, %p)\n", This, pStream, pLoader);
	if (!pStream) {
		WARN(": invalid pStream\n");
		return E_FAIL;
	}
	if (!pLoader) {
		WARN(": invalid pLoader\n");
		return E_FAIL;
	}	
	
	IDirectMusicLoaderGenericStream_Detach (iface);
	IStream_Clone (pStream, &This->pStream);
	This->pLoader = pLoader;
	
    return S_OK;
597 598
}

599 600

/* IUnknown/IStream part: */
601
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
	
	TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
	if (IsEqualIID (riid, &IID_IUnknown) ||
		IsEqualIID (riid, &IID_IStream)) {
		*ppobj = (LPVOID)&This->StreamVtbl;
		IDirectMusicLoaderGenericStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
		return S_OK;
	} else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
		*ppobj = (LPVOID)&This->GetLoaderVtbl;
		IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);		
		return S_OK;
	}

	WARN(": not found\n");
	return E_NOINTERFACE;
618 619
}

620
static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_AddRef (LPSTREAM iface) {
621
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
622
	TRACE("(%p): AddRef from %d\n", This, This->dwRef);
623 624 625
	return InterlockedIncrement (&This->dwRef);
}

626
static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_Release (LPSTREAM iface) {
627 628 629
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
	
	DWORD dwRef = InterlockedDecrement (&This->dwRef);
630
	TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
631
	if (dwRef == 0) {
632 633
		IDirectMusicLoaderGenericStream_Detach (iface);
		HeapFree (GetProcessHeap(), 0, This);
634 635 636 637 638
	}
	
	return dwRef;
}

639
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
640 641
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);

642
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p): redirecting to low-level stream\n", This, pv, cb, pcbRead);
643 644 645 646 647 648
	if (!This->pStream)
		return E_FAIL;

	return IStream_Read (This->pStream, pv, cb, pcbRead);
}

649
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
650
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
651
	TRACE_(dmfileraw)("(%p, %s, %s, %p): redirecting to low-level stream\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
652 653 654 655 656 657
	if (!This->pStream)
		return E_FAIL;

	return IStream_Seek (This->pStream, dlibMove, dwOrigin, plibNewPosition);
}

658
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
	LPSTREAM pOther = NULL;
	LPSTREAM pLowLevel = NULL;
	HRESULT result;

	TRACE("(%p, %p)\n", iface, ppstm);
	result = DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID*)&pOther);
	if (FAILED(result)) return result;
	
	if (FAILED(IStream_Clone (This->pStream, &pLowLevel)))
		return E_FAIL;
	
	IDirectMusicLoaderGenericStream_Attach (pOther, pLowLevel, This->pLoader);

	TRACE(": succeeded\n");
674
	*ppstm = pOther;
675 676 677
	return S_OK;
}

678
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
679
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
680
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p): redirecting to low-level stream\n", This, pv, cb, pcbWritten);
681 682 683 684 685 686
	if (!This->pStream)
		return E_FAIL;

	return IStream_Write (This->pStream, pv, cb, pcbWritten);
}

687
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
688
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
689
	TRACE("(%p, %s): redirecting to low-level stream\n", This, wine_dbgstr_longlong(libNewSize.QuadPart));
690 691 692 693 694 695
	if (!This->pStream)
		return E_FAIL;

	return IStream_SetSize (This->pStream, libNewSize);
}

696
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
697
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
698
	TRACE("(%p, %p, %s, %p, %p): redirecting to low-level stream\n", This, pstm, wine_dbgstr_longlong(cb.QuadPart), pcbRead, pcbWritten);
699 700 701 702 703 704
	if (!This->pStream)
		return E_FAIL;

	return IStream_CopyTo (This->pStream, pstm, cb, pcbRead, pcbWritten);
}

705
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
706
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
707
	TRACE("(%p, 0x%08X): redirecting to low-level stream\n", This, grfCommitFlags);
708 709 710 711 712 713
	if (!This->pStream)
		return E_FAIL;

	return IStream_Commit (This->pStream, grfCommitFlags);
}

714
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Revert (LPSTREAM iface) {
715 716 717 718 719 720 721 722
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
	TRACE("(%p): redirecting to low-level stream\n", This);
	if (!This->pStream)
		return E_FAIL;

	return IStream_Revert (This->pStream);
}

723
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
724
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
725
	TRACE("(%p, %s, %s, 0x%08X): redirecting to low-level stream\n", This, wine_dbgstr_longlong(libOffset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), dwLockType);
726 727 728 729 730 731
	if (!This->pStream)
		return E_FAIL;

	return IStream_LockRegion (This->pStream, libOffset, cb, dwLockType);
}

732
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
733
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
734
	TRACE("(%p, %s, %s, 0x%08X): redirecting to low-level stream\n", This, wine_dbgstr_longlong(libOffset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), dwLockType);
735 736 737 738 739 740
	if (!This->pStream)
		return E_FAIL;

	return IStream_UnlockRegion (This->pStream, libOffset, cb, dwLockType);
}

741
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
742
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
743
	TRACE("(%p, %p, 0x%08X): redirecting to low-level stream\n", This, pstatstg, grfStatFlag);
744 745 746 747 748 749
	if (!This->pStream)
		return E_FAIL;

	return IStream_Stat (This->pStream, pstatstg, grfStatFlag);
}

750
static const IStreamVtbl DirectMusicLoaderGenericStream_Stream_Vtbl = {
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
	IDirectMusicLoaderGenericStream_IStream_QueryInterface,
	IDirectMusicLoaderGenericStream_IStream_AddRef,
	IDirectMusicLoaderGenericStream_IStream_Release,
	IDirectMusicLoaderGenericStream_IStream_Read,
	IDirectMusicLoaderGenericStream_IStream_Write,
	IDirectMusicLoaderGenericStream_IStream_Seek,
	IDirectMusicLoaderGenericStream_IStream_SetSize,
	IDirectMusicLoaderGenericStream_IStream_CopyTo,
	IDirectMusicLoaderGenericStream_IStream_Commit,
	IDirectMusicLoaderGenericStream_IStream_Revert,
	IDirectMusicLoaderGenericStream_IStream_LockRegion,
	IDirectMusicLoaderGenericStream_IStream_UnlockRegion,
	IDirectMusicLoaderGenericStream_IStream_Stat,
	IDirectMusicLoaderGenericStream_IStream_Clone
};

/* IDirectMusicGetLoader part: */
768
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
769 770 771 772
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

773
static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
774 775 776 777
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderGenericStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
}

778
static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
779 780 781 782
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderGenericStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
}

783
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
784
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
785 786 787

	TRACE("(%p, %p)\n", This, ppLoader);
	*ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
788 789
	IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
	
790 791 792
	return S_OK;
}

793
static const IDirectMusicGetLoaderVtbl DirectMusicLoaderGenericStream_GetLoader_Vtbl = {
794 795 796 797
	IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface,
	IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef,
	IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release,
	IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_GetLoader
798 799
};

800 801
HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderGenericStream (LPVOID* ppobj) {
	IDirectMusicLoaderGenericStream *obj;
802

803
	TRACE("(%p)\n", ppobj);
804 805
	obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderGenericStream));
	if (NULL == obj) {
806
		*ppobj = NULL;
807 808
		return E_OUTOFMEMORY;
	}
809 810 811 812 813 814
	obj->StreamVtbl = &DirectMusicLoaderGenericStream_Stream_Vtbl;
	obj->GetLoaderVtbl = &DirectMusicLoaderGenericStream_GetLoader_Vtbl;
	obj->dwRef = 0; /* will be inited with QueryInterface */

	return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
}