mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 10:41:12 +00:00
672 lines
20 KiB
C
672 lines
20 KiB
C
/*
|
|
* Copyright (C) 2003-2004 Rok Mandeljc
|
|
* Copyright 2023 Rémi Bernon for CodeWeavers
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include "dmloader_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
|
|
WINE_DECLARE_DEBUG_CHANNEL(dmfileraw);
|
|
|
|
struct loader_stream
|
|
{
|
|
IStream IStream_iface;
|
|
IDirectMusicGetLoader IDirectMusicGetLoader_iface;
|
|
LONG ref;
|
|
|
|
IStream *stream;
|
|
IDirectMusicLoader *loader;
|
|
};
|
|
|
|
static struct loader_stream *impl_from_IStream(IStream *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct loader_stream, IStream_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_QueryInterface(IStream *iface, REFIID riid, void **ret_iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
|
|
TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
|
|
|
|
if (IsEqualGUID(riid, &IID_IUnknown)
|
|
|| IsEqualGUID(riid, &IID_IStream))
|
|
{
|
|
IStream_AddRef(&This->IStream_iface);
|
|
*ret_iface = &This->IStream_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
if (IsEqualGUID(riid, &IID_IDirectMusicGetLoader))
|
|
{
|
|
IDirectMusicGetLoader_AddRef(&This->IDirectMusicGetLoader_iface);
|
|
*ret_iface = &This->IDirectMusicGetLoader_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
|
|
*ret_iface = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI loader_stream_AddRef(IStream *iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
ULONG ref = InterlockedIncrement(&This->ref);
|
|
TRACE("(%p): new ref = %lu\n", This, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI loader_stream_Release(IStream *iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
ULONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
TRACE("(%p): new ref = %lu\n", This, ref);
|
|
|
|
if (!ref)
|
|
{
|
|
IDirectMusicLoader_Release(This->loader);
|
|
IStream_Release(This->stream);
|
|
free(This);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Read(IStream *iface, void *data, ULONG size, ULONG *ret_size)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
TRACE("(%p, %p, %#lx, %p)\n", This, data, size, ret_size);
|
|
return IStream_Read(This->stream, data, size, ret_size);
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Write(IStream *iface, const void *data, ULONG size, ULONG *ret_size)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD method, ULARGE_INTEGER *ret_offset)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
TRACE("(%p, %I64d, %#lx, %p)\n", This, offset.QuadPart, method, ret_offset);
|
|
return IStream_Seek(This->stream, offset, method, ret_offset);
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_SetSize(IStream *iface, ULARGE_INTEGER size)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER size,
|
|
ULARGE_INTEGER *read_size, ULARGE_INTEGER *write_size)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Commit(IStream *iface, DWORD flags)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Revert(IStream *iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
|
|
ULARGE_INTEGER size, DWORD type)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Stat(IStream *iface, STATSTG *stat, DWORD flags)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_Clone(IStream *iface, IStream **ret_iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IStream(iface);
|
|
IStream *stream;
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p, %p)\n", This, ret_iface);
|
|
|
|
if (SUCCEEDED(hr = IStream_Clone(This->stream, &stream)))
|
|
{
|
|
hr = loader_stream_create(This->loader, stream, ret_iface);
|
|
IStream_Release(stream);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
static const IStreamVtbl loader_stream_vtbl =
|
|
{
|
|
loader_stream_QueryInterface,
|
|
loader_stream_AddRef,
|
|
loader_stream_Release,
|
|
loader_stream_Read,
|
|
loader_stream_Write,
|
|
loader_stream_Seek,
|
|
loader_stream_SetSize,
|
|
loader_stream_CopyTo,
|
|
loader_stream_Commit,
|
|
loader_stream_Revert,
|
|
loader_stream_LockRegion,
|
|
loader_stream_UnlockRegion,
|
|
loader_stream_Stat,
|
|
loader_stream_Clone,
|
|
};
|
|
|
|
static struct loader_stream *impl_from_IDirectMusicGetLoader(IDirectMusicGetLoader *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct loader_stream, IDirectMusicGetLoader_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_getter_QueryInterface(IDirectMusicGetLoader *iface, REFIID iid, void **out)
|
|
{
|
|
struct loader_stream *This = impl_from_IDirectMusicGetLoader(iface);
|
|
return IStream_QueryInterface(&This->IStream_iface, iid, out);
|
|
}
|
|
|
|
static ULONG WINAPI loader_stream_getter_AddRef(IDirectMusicGetLoader *iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IDirectMusicGetLoader(iface);
|
|
return IStream_AddRef(&This->IStream_iface);
|
|
}
|
|
|
|
static ULONG WINAPI loader_stream_getter_Release(IDirectMusicGetLoader *iface)
|
|
{
|
|
struct loader_stream *This = impl_from_IDirectMusicGetLoader(iface);
|
|
return IStream_Release(&This->IStream_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI loader_stream_getter_GetLoader(IDirectMusicGetLoader *iface, IDirectMusicLoader **ret_loader)
|
|
{
|
|
struct loader_stream *This = impl_from_IDirectMusicGetLoader(iface);
|
|
|
|
TRACE("(%p, %p)\n", This, ret_loader);
|
|
|
|
*ret_loader = This->loader;
|
|
IDirectMusicLoader_AddRef(This->loader);
|
|
return S_OK;
|
|
}
|
|
|
|
static const IDirectMusicGetLoaderVtbl loader_stream_getter_vtbl =
|
|
{
|
|
loader_stream_getter_QueryInterface,
|
|
loader_stream_getter_AddRef,
|
|
loader_stream_getter_Release,
|
|
loader_stream_getter_GetLoader,
|
|
};
|
|
|
|
HRESULT loader_stream_create(IDirectMusicLoader *loader, IStream *stream,
|
|
IStream **ret_iface)
|
|
{
|
|
struct loader_stream *obj;
|
|
|
|
*ret_iface = NULL;
|
|
if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
|
|
obj->IStream_iface.lpVtbl = &loader_stream_vtbl;
|
|
obj->IDirectMusicGetLoader_iface.lpVtbl = &loader_stream_getter_vtbl;
|
|
obj->ref = 1;
|
|
|
|
obj->stream = stream;
|
|
IStream_AddRef(stream);
|
|
obj->loader = loader;
|
|
IDirectMusicLoader_AddRef(loader);
|
|
|
|
*ret_iface = &obj->IStream_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
struct file_stream
|
|
{
|
|
IStream IStream_iface;
|
|
LONG ref;
|
|
|
|
WCHAR path[MAX_PATH];
|
|
HANDLE file;
|
|
};
|
|
|
|
static struct file_stream *file_stream_from_IStream(IStream *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct file_stream, IStream_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_QueryInterface(IStream *iface, REFIID riid, void **ret_iface)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
|
|
TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
|
|
|
|
if (IsEqualGUID(riid, &IID_IUnknown)
|
|
|| IsEqualGUID(riid, &IID_IStream))
|
|
{
|
|
IStream_AddRef(&This->IStream_iface);
|
|
*ret_iface = &This->IStream_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
|
|
*ret_iface = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI file_stream_AddRef(IStream *iface)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
ULONG ref = InterlockedIncrement(&This->ref);
|
|
TRACE("(%p): new ref = %lu\n", This, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI file_stream_Release(IStream *iface)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
ULONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
TRACE("(%p): new ref = %lu\n", This, ref);
|
|
|
|
if (!ref)
|
|
{
|
|
CloseHandle(This->file);
|
|
free(This);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Read(IStream *iface, void *data, ULONG size, ULONG *ret_size)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
DWORD dummy;
|
|
|
|
TRACE("(%p, %p, %#lx, %p)\n", This, data, size, ret_size);
|
|
|
|
if (!ret_size) ret_size = &dummy;
|
|
if (!ReadFile(This->file, data, size, ret_size, NULL)) return HRESULT_FROM_WIN32(GetLastError());
|
|
return *ret_size == size ? S_OK : S_FALSE;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Write(IStream *iface, const void *data, ULONG size, ULONG *ret_size)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD method, ULARGE_INTEGER *ret_offset)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
DWORD position;
|
|
|
|
TRACE("(%p, %I64d, %#lx, %p)\n", This, offset.QuadPart, method, ret_offset);
|
|
|
|
position = SetFilePointer(This->file, offset.u.LowPart, NULL, method);
|
|
if (position == INVALID_SET_FILE_POINTER) return HRESULT_FROM_WIN32(GetLastError());
|
|
if (ret_offset) ret_offset->QuadPart = position;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_SetSize(IStream *iface, ULARGE_INTEGER size)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER size,
|
|
ULARGE_INTEGER *read_size, ULARGE_INTEGER *write_size)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Commit(IStream *iface, DWORD flags)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Revert(IStream *iface)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
|
|
ULARGE_INTEGER size, DWORD type)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Stat(IStream *iface, STATSTG *stat, DWORD flags)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
FIXME("(%p): stub\n", This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI file_stream_Clone(IStream *iface, IStream **ret_iface)
|
|
{
|
|
struct file_stream *This = file_stream_from_IStream(iface);
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p, %p)\n", This, ret_iface);
|
|
|
|
if (SUCCEEDED(hr = file_stream_create(This->path, ret_iface)))
|
|
{
|
|
LARGE_INTEGER position = {0};
|
|
position.LowPart = SetFilePointer(This->file, 0, NULL, SEEK_CUR);
|
|
hr = IStream_Seek(*ret_iface, position, SEEK_SET, NULL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
static const IStreamVtbl file_stream_vtbl =
|
|
{
|
|
file_stream_QueryInterface,
|
|
file_stream_AddRef,
|
|
file_stream_Release,
|
|
file_stream_Read,
|
|
file_stream_Write,
|
|
file_stream_Seek,
|
|
file_stream_SetSize,
|
|
file_stream_CopyTo,
|
|
file_stream_Commit,
|
|
file_stream_Revert,
|
|
file_stream_LockRegion,
|
|
file_stream_UnlockRegion,
|
|
file_stream_Stat,
|
|
file_stream_Clone,
|
|
};
|
|
|
|
HRESULT file_stream_create(const WCHAR *path, IStream **ret_iface)
|
|
{
|
|
struct file_stream *stream;
|
|
|
|
*ret_iface = NULL;
|
|
if (!(stream = calloc(1, sizeof(*stream)))) return E_OUTOFMEMORY;
|
|
stream->IStream_iface.lpVtbl = &file_stream_vtbl;
|
|
stream->ref = 1;
|
|
|
|
wcscpy(stream->path, path);
|
|
stream->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (stream->file == INVALID_HANDLE_VALUE)
|
|
{
|
|
free(stream);
|
|
return DMUS_E_LOADER_FAILEDOPEN;
|
|
}
|
|
|
|
*ret_iface = &stream->IStream_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface);
|
|
|
|
/*****************************************************************************
|
|
* IDirectMusicLoaderResourceStream implementation
|
|
*/
|
|
/* Custom : */
|
|
|
|
static void IDirectMusicLoaderResourceStream_Detach (LPSTREAM iface) {
|
|
ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
|
|
TRACE("(%p)\n", This);
|
|
|
|
This->pbMemData = NULL;
|
|
This->llMemLength = 0;
|
|
}
|
|
|
|
HRESULT WINAPI IDirectMusicLoaderResourceStream_Attach (LPSTREAM iface, LPBYTE pbMemData, LONGLONG llMemLength, LONGLONG llPos) {
|
|
ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
|
|
|
|
TRACE("(%p, %p, %s, %s)\n", This, pbMemData, wine_dbgstr_longlong(llMemLength), wine_dbgstr_longlong(llPos));
|
|
if (!pbMemData || !llMemLength) {
|
|
WARN(": invalid pbMemData or llMemLength\n");
|
|
return E_FAIL;
|
|
}
|
|
IDirectMusicLoaderResourceStream_Detach (iface);
|
|
This->pbMemData = pbMemData;
|
|
This->llMemLength = llMemLength;
|
|
This->llPos = llPos;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* IUnknown/IStream part: */
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
|
|
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 = &This->StreamVtbl;
|
|
IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
|
|
return S_OK;
|
|
}
|
|
|
|
WARN(": not found\n");
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface) {
|
|
ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
|
|
TRACE("(%p): AddRef from %ld\n", This, This->dwRef);
|
|
return InterlockedIncrement (&This->dwRef);
|
|
}
|
|
|
|
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_Release (LPSTREAM iface) {
|
|
ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
|
|
|
|
DWORD dwRef = InterlockedDecrement (&This->dwRef);
|
|
TRACE("(%p): ReleaseRef to %ld\n", This, dwRef);
|
|
if (dwRef == 0) {
|
|
IDirectMusicLoaderResourceStream_Detach (iface);
|
|
free(This);
|
|
}
|
|
|
|
return dwRef;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
|
|
LPBYTE pByte;
|
|
ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
|
|
|
|
TRACE_(dmfileraw)("(%p, %p, %#lx, %p)\n", This, pv, cb, pcbRead);
|
|
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 */
|
|
if (pcbRead) *pcbRead = cb;
|
|
|
|
TRACE_(dmfileraw)(": data (size = %#lx): %s\n", cb, debugstr_an(pv, cb));
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
|
|
ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
|
|
TRACE_(dmfileraw)("(%p, %s, %s, %p)\n", This, wine_dbgstr_longlong(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;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
|
|
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);
|
|
|
|
TRACE(": succeeded\n");
|
|
*ppstm = pOther;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Revert (LPSTREAM iface) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
|
|
ERR(": should not be needed\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IStreamVtbl DirectMusicLoaderResourceStream_Stream_Vtbl = {
|
|
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
|
|
};
|
|
|
|
HRESULT DMUSIC_CreateDirectMusicLoaderResourceStream (void** ppobj) {
|
|
IDirectMusicLoaderResourceStream *obj;
|
|
|
|
TRACE("(%p)\n", ppobj);
|
|
|
|
*ppobj = NULL;
|
|
if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
|
|
obj->StreamVtbl = &DirectMusicLoaderResourceStream_Stream_Vtbl;
|
|
obj->dwRef = 0; /* will be inited with QueryInterface */
|
|
|
|
return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
|
|
}
|