loaderstream.c 32.1 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
HRESULT WINAPI IDirectMusicLoaderFileStream_Attach (LPSTREAM iface, LPCWSTR wzFile, LPDIRECTMUSICLOADER8 pLoader) {
68
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
69
    TRACE("(%p, %s, %p)\n", This, debugstr_w(wzFile), pLoader);
70 71
    IDirectMusicLoaderFileStream_Detach (iface);
    This->hFile = CreateFileW (wzFile, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
72
    if (This->hFile == INVALID_HANDLE_VALUE) {
73
        WARN(": failed\n");
74
        return DMUS_E_LOADER_FAILEDOPEN;
75
    }
76
    /* create IDirectMusicGetLoader */
77
    This->pLoader = pLoader;
78
    lstrcpynW (This->wzFileName, wzFile, MAX_PATH);
79
    TRACE(": succeeded\n");
80 81 82
    return S_OK;
}

83 84 85
void WINAPI IDirectMusicLoaderFileStream_Detach (LPSTREAM iface) {
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
	TRACE("(%p)\n", This);
86 87 88
	if (This->hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(This->hFile);
    }
89
    This->wzFileName[0] = '\0';
90 91
}

92 93

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

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

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

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

133
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
134
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
135
    ULONG cbRead;
136
	
137
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
138 139 140
    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;
141
	
142
	TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", *pcbRead, debugstr_an(pv, *pcbRead));
143 144 145
    return S_OK;
}

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

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

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

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

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

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

195
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
196 197 198
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    ULONG cbWrite;
	
199
	TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbWritten);
200 201 202 203
    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;
	
204
	TRACE_(dmfileraw)(": data (size = 0x%08X): %s\n", *pcbWritten, debugstr_an(pv, *pcbWritten));
205 206 207
    return S_OK;
}

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

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

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

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

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

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

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

243
static const IStreamVtbl DirectMusicLoaderFileStream_Stream_Vtbl = {
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	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: */
261
static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
262 263 264 265
	ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

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

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

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

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

286
static const IDirectMusicGetLoaderVtbl DirectMusicLoaderFileStream_GetLoader_Vtbl = {
287 288 289 290 291 292 293 294 295 296 297 298
	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) {
299
		*ppobj = NULL;
300 301 302 303 304 305 306 307 308 309 310 311 312 313
		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 : */
314
HRESULT WINAPI IDirectMusicLoaderResourceStream_Attach (LPSTREAM iface, LPBYTE pbMemData, LONGLONG llMemLength, LONGLONG llPos, LPDIRECTMUSICLOADER8 pLoader) {
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
    
	TRACE("(%p, %p, 0x%08llX, 0x%08llx, %p)\n", This, pbMemData, llMemLength, llPos, pLoader);
	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;
}

void WINAPI IDirectMusicLoaderResourceStream_Detach (LPSTREAM iface) {
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
	TRACE("(%p)\n", This);
	
	This->pbMemData = NULL;
	This->llMemLength = 0;
}


/* 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 401 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
	ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);	
	TRACE_(dmfileraw)("(%p, 0x%08llX, %s, %p)\n", This, dlibMove.QuadPart, resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
	
	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 455 456 457 458
	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");
	*ppstm = (IStream*)pOther;
	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
HRESULT WINAPI IDirectMusicLoaderGenericStream_Attach (LPSTREAM iface, LPSTREAM pStream, LPDIRECTMUSICLOADER8 pLoader) {
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
	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;
588 589
}

590 591 592 593 594 595
void WINAPI IDirectMusicLoaderGenericStream_Detach (LPSTREAM iface) {
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
	
	if (This->pStream)
		IStream_Release (This->pStream);
	This->pStream = NULL;
596 597
}

598 599

/* IUnknown/IStream part: */
600
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
	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;
617 618
}

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 623 624
	return InterlockedIncrement (&This->dwRef);
}

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

638
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
639 640
	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 643 644 645 646 647
	if (!This->pStream)
		return E_FAIL;

	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 650 651 652 653 654 655 656
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
	TRACE_(dmfileraw)("(%p, 0x%08llX, %s, %p): redirecting to low-level stream\n", This, dlibMove.QuadPart, resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
	if (!This->pStream)
		return E_FAIL;

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

657
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
	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");
	*ppstm = (IStream*)pOther;
	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 681 682 683 684 685
	if (!This->pStream)
		return E_FAIL;

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

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

	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 697 698 699 700 701 702 703
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
	TRACE("(%p, %p, 0x%08llX, %p, %p): redirecting to low-level stream\n", This, pstm, cb.QuadPart, pcbRead, pcbWritten);
	if (!This->pStream)
		return E_FAIL;

	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 708 709 710 711 712
	if (!This->pStream)
		return E_FAIL;

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

713
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Revert (LPSTREAM iface) {
714 715 716 717 718 719 720 721
	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);
}

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, 0x%08llX, 0x%08llX, 0x%08X): redirecting to low-level stream\n", This, libOffset.QuadPart, cb.QuadPart, dwLockType);
725 726 727 728 729 730
	if (!This->pStream)
		return E_FAIL;

	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, 0x%08llX, 0x%08llX, 0x%08X): redirecting to low-level stream\n", This, libOffset.QuadPart, cb.QuadPart, dwLockType);
734 735 736 737 738 739
	if (!This->pStream)
		return E_FAIL;

	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 744 745 746 747 748
	if (!This->pStream)
		return E_FAIL;

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

749
static const IStreamVtbl DirectMusicLoaderGenericStream_Stream_Vtbl = {
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
	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: */
767
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
768 769 770 771
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
	return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

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

777
static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
778 779 780 781
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
	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);
784 785 786

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

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

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

802
	TRACE("(%p)\n", ppobj);
803 804
	obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderGenericStream));
	if (NULL == obj) {
805
		*ppobj = NULL;
806 807
		return E_OUTOFMEMORY;
	}
808 809 810 811 812 813
	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);
}