Commit 1ffc47b5 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

dmloader: Use a simpler file stream implementation.

parent 9e0487c4
......@@ -59,26 +59,9 @@ typedef struct IDirectMusicLoaderGenericStream IDirectMusicLoaderGenericStream;
*/
extern HRESULT create_dmloader(REFIID riid, void **ret_iface);
extern HRESULT create_dmcontainer(REFIID riid, void **ret_iface);
extern HRESULT DMUSIC_CreateDirectMusicLoaderFileStream(void **ppobj);
extern HRESULT DMUSIC_CreateDirectMusicLoaderResourceStream(void **ppobj);
/*****************************************************************************
* IDirectMusicLoaderFileStream implementation structure
*/
struct IDirectMusicLoaderFileStream {
/* VTABLEs */
const IStreamVtbl *StreamVtbl;
/* reference counter */
LONG dwRef;
/* file */
WCHAR wzFileName[MAX_PATH]; /* for clone */
HANDLE hFile;
};
/* Custom: */
extern HRESULT WINAPI IDirectMusicLoaderFileStream_Attach(LPSTREAM iface, LPCWSTR wzFile);
/*****************************************************************************
* IDirectMusicLoaderResourceStream implementation structure
*/
struct IDirectMusicLoaderResourceStream {
......@@ -98,6 +81,7 @@ extern HRESULT WINAPI IDirectMusicLoaderResourceStream_Attach(LPSTREAM iface, LP
LONGLONG llMemLength, LONGLONG llPos);
extern HRESULT loader_stream_create(IDirectMusicLoader *loader, IStream *stream, IStream **ret_iface);
extern HRESULT file_stream_create(const WCHAR *path, IStream **ret_iface);
#include "debug.h"
......
......@@ -305,40 +305,29 @@ static HRESULT WINAPI loader_GetObject(IDirectMusicLoader8 *iface, DMUS_OBJECTDE
TRACE(": no cache/alias entry found for requested object\n");
}
if (pDesc->dwValidData & DMUS_OBJ_URL) {
TRACE(": loading from URLs not supported yet\n");
return DMUS_E_LOADER_FORMATNOTSUPPORTED;
}
else if (pDesc->dwValidData & DMUS_OBJ_FILENAME) {
/* load object from file */
/* generate filename; if it's full path, don't add search
directory path, otherwise do */
WCHAR wszFileName[MAX_PATH];
if (pDesc->dwValidData & DMUS_OBJ_FULLPATH) {
lstrcpyW(wszFileName, pDesc->wszFileName);
} else {
WCHAR *p;
get_search_path(This, &pDesc->guidClass, wszFileName);
p = wszFileName + lstrlenW(wszFileName);
if (p > wszFileName && p[-1] != '\\') *p++ = '\\';
lstrcpyW(p, pDesc->wszFileName);
}
TRACE(": loading from file (%s)\n", debugstr_w(wszFileName));
/* create stream and associate it with file */
result = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pStream);
if (FAILED(result)) {
ERR(": could not create file stream\n");
return result;
}
result = IDirectMusicLoaderFileStream_Attach(pStream, wszFileName);
if (FAILED(result))
{
ERR(": could not attach stream to file\n");
IStream_Release (pStream);
return result;
}
}
if (pDesc->dwValidData & DMUS_OBJ_URL)
{
TRACE(": loading from URLs not supported yet\n");
return DMUS_E_LOADER_FORMATNOTSUPPORTED;
}
else if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
{
WCHAR file_name[MAX_PATH];
if (pDesc->dwValidData & DMUS_OBJ_FULLPATH)
lstrcpyW(file_name, pDesc->wszFileName);
else
{
WCHAR *p;
get_search_path(This, &pDesc->guidClass, file_name);
p = file_name + lstrlenW(file_name);
if (p > file_name && p[-1] != '\\') *p++ = '\\';
lstrcpyW(p, pDesc->wszFileName);
}
TRACE(": loading from file (%s)\n", debugstr_w(file_name));
if (FAILED(hr = file_stream_create(file_name, &pStream))) return hr;
}
else if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
/* load object from resource */
TRACE(": loading from resource\n");
......@@ -363,9 +352,8 @@ static HRESULT WINAPI loader_GetObject(IDirectMusicLoader8 *iface, DMUS_OBJECTDE
}
else
{
/* nowhere to load from */
FIXME(": unknown/unsupported way of loading\n");
return DMUS_E_LOADER_NOFILENAME; /* test shows this is returned */
return DMUS_E_LOADER_NOFILENAME;
}
if (FAILED(hr = loader_stream_create((IDirectMusicLoader *)iface, pStream, &loader_stream)))
......@@ -459,36 +447,23 @@ static HRESULT WINAPI loader_SetObject(IDirectMusicLoader8 *iface, DMUS_OBJECTDE
if (TRACE_ON(dmloader))
dump_DMUS_OBJECTDESC(pDesc);
/* create stream and load additional info from it */
if (pDesc->dwValidData & DMUS_OBJ_FILENAME) {
/* generate filename; if it's full path, don't add search
directory path, otherwise do */
WCHAR wszFileName[MAX_PATH];
if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
{
WCHAR file_name[MAX_PATH];
if (pDesc->dwValidData & DMUS_OBJ_FULLPATH) {
lstrcpyW(wszFileName, pDesc->wszFileName);
} else {
WCHAR *p;
get_search_path(This, &pDesc->guidClass, wszFileName);
p = wszFileName + lstrlenW(wszFileName);
if (p > wszFileName && p[-1] != '\\') *p++ = '\\';
lstrcpyW(p, pDesc->wszFileName);
}
/* create stream */
hr = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pStream);
if (FAILED(hr)) {
ERR(": could not create file stream\n");
return DMUS_E_LOADER_FAILEDOPEN;
}
/* attach stream */
hr = IDirectMusicLoaderFileStream_Attach(pStream, wszFileName);
if (FAILED(hr))
{
ERR(": could not attach stream to file %s, make sure it exists\n", debugstr_w(wszFileName));
IStream_Release (pStream);
return DMUS_E_LOADER_FAILEDOPEN;
}
}
if (pDesc->dwValidData & DMUS_OBJ_FULLPATH)
lstrcpyW(file_name, pDesc->wszFileName);
else
{
WCHAR *p;
get_search_path(This, &pDesc->guidClass, file_name);
p = file_name + lstrlenW(file_name);
if (p > file_name && p[-1] != '\\') *p++ = '\\';
lstrcpyW(p, pDesc->wszFileName);
}
if (FAILED(hr = file_stream_create(file_name, &pStream))) return hr;
}
else if (pDesc->dwValidData & DMUS_OBJ_STREAM)
{
pStream = pDesc->pStream;
......
/* IDirectMusicLoaderFileStream
* IDirectMusicLoaderResourceStream
* IDirectMusicLoaderGenericStream
*
/*
* 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
......@@ -19,31 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* 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
*/
#include "dmloader_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
......@@ -284,216 +257,204 @@ HRESULT loader_stream_create(IDirectMusicLoader *loader, IStream *stream,
return S_OK;
}
static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface);
struct file_stream
{
IStream IStream_iface;
LONG ref;
/*****************************************************************************
* IDirectMusicLoaderFileStream implementation
*/
/* Custom : */
WCHAR path[MAX_PATH];
HANDLE file;
};
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';
static struct file_stream *file_stream_from_IStream(IStream *iface)
{
return CONTAINING_RECORD(iface, struct file_stream, IStream_iface);
}
HRESULT WINAPI IDirectMusicLoaderFileStream_Attach(LPSTREAM iface, LPCWSTR wzFile)
static HRESULT WINAPI file_stream_QueryInterface(IStream *iface, REFIID riid, void **ret_iface)
{
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
TRACE("(%p, %s)\n", This, debugstr_w(wzFile));
IDirectMusicLoaderFileStream_Detach (iface);
This->hFile = CreateFileW (wzFile, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (This->hFile == INVALID_HANDLE_VALUE) {
WARN(": failed\n");
return DMUS_E_LOADER_FAILEDOPEN;
}
/* create IDirectMusicGetLoader */
lstrcpynW (This->wzFileName, wzFile, MAX_PATH);
TRACE(": succeeded\n");
return S_OK;
}
struct file_stream *This = file_stream_from_IStream(iface);
TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
/* IUnknown/IStream part: */
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
if (IsEqualIID (riid, &IID_IUnknown) ||
IsEqualIID (riid, &IID_IStream)) {
*ppobj = &This->StreamVtbl;
IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
return S_OK;
}
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IStream))
{
IStream_AddRef(&This->IStream_iface);
*ret_iface = &This->IStream_iface;
return S_OK;
}
WARN(": not found\n");
return E_NOINTERFACE;
WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
*ret_iface = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
TRACE("(%p): AddRef from %ld\n", This, This->dwRef);
return InterlockedIncrement (&This->dwRef);
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 IDirectMusicLoaderFileStream_IStream_Release (LPSTREAM iface) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
DWORD dwRef = InterlockedDecrement (&This->dwRef);
TRACE("(%p): ReleaseRef to %ld\n", This, dwRef);
if (dwRef == 0) {
if (This->hFile)
IDirectMusicLoaderFileStream_Detach (iface);
free(This);
}
return dwRef;
}
static ULONG WINAPI file_stream_Release(IStream *iface)
{
struct file_stream *This = file_stream_from_IStream(iface);
ULONG ref = InterlockedDecrement(&This->ref);
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
ULONG cbRead;
TRACE_(dmfileraw)("(%p, %p, %#lx, %p)\n", This, pv, cb, pcbRead);
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;
TRACE_(dmfileraw)(": data (size = %#lx): %s\n", *pcbRead, debugstr_an(pv, *pcbRead));
return S_OK;
TRACE("(%p): new ref = %lu\n", This, ref);
if (!ref)
{
CloseHandle(This->file);
free(This);
}
return ref;
}
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
LARGE_INTEGER liNewPos;
TRACE_(dmfileraw)("(%p, %s, %s, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
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;
if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
TRACE("(%p, %p, %#lx, %p)\n", This, data, size, ret_size);
liNewPos.HighPart = dlibMove.HighPart;
liNewPos.LowPart = SetFilePointer (This->hFile, dlibMove.LowPart, &liNewPos.HighPart, dwOrigin);
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;
}
if (liNewPos.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) return E_FAIL;
if (plibNewPosition) plibNewPosition->QuadPart = liNewPos.QuadPart;
return S_OK;
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 IDirectMusicLoaderFileStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
LPSTREAM pOther = NULL;
HRESULT result;
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, %p)\n", iface, ppstm);
result = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pOther);
if (FAILED(result)) return result;
if (This->hFile != INVALID_HANDLE_VALUE) {
ULARGE_INTEGER ullCurrentPosition;
result = IDirectMusicLoaderFileStream_Attach(pOther, This->wzFileName);
if (SUCCEEDED(result))
{
LARGE_INTEGER liZero;
liZero.QuadPart = 0;
result = IDirectMusicLoaderFileStream_IStream_Seek (iface, liZero, STREAM_SEEK_CUR, &ullCurrentPosition); /* get current position in current stream */
}
if (SUCCEEDED(result)) {
LARGE_INTEGER liNewPosition;
liNewPosition.QuadPart = ullCurrentPosition.QuadPart;
result = IDirectMusicLoaderFileStream_IStream_Seek (pOther, liNewPosition, STREAM_SEEK_SET, &ullCurrentPosition);
}
if (FAILED(result)) {
TRACE(": failed\n");
IDirectMusicLoaderFileStream_IStream_Release (pOther);
return result;
}
}
TRACE(": succeeded\n");
*ppstm = pOther;
return S_OK;
}
TRACE("(%p, %I64d, %#lx, %p)\n", This, offset.QuadPart, method, ret_offset);
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
ULONG cbWrite;
TRACE_(dmfileraw)("(%p, %p, %#lx, %p)\n", This, pv, cb, pcbWritten);
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;
TRACE_(dmfileraw)(": data (size = %#lx): %s\n", *pcbWritten, debugstr_an(pv, *pcbWritten));
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 IDirectMusicLoaderFileStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
ERR(": should not be needed\n");
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 IDirectMusicLoaderFileStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
ERR(": should not be needed\n");
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 IDirectMusicLoaderFileStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
ERR(": should not be needed\n");
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 IDirectMusicLoaderFileStream_IStream_Revert (LPSTREAM iface) {
ERR(": should not be needed\n");
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 IDirectMusicLoaderFileStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
ERR(": should not be needed\n");
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 IDirectMusicLoaderFileStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
ERR(": should not be needed\n");
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 IDirectMusicLoaderFileStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
ERR(": should not be needed\n");
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 const IStreamVtbl DirectMusicLoaderFileStream_Stream_Vtbl = {
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
};
static HRESULT WINAPI file_stream_Clone(IStream *iface, IStream **ret_iface)
{
struct file_stream *This = file_stream_from_IStream(iface);
HRESULT hr;
HRESULT DMUSIC_CreateDirectMusicLoaderFileStream (void** ppobj) {
IDirectMusicLoaderFileStream *obj;
TRACE("(%p, %p)\n", This, ret_iface);
TRACE("(%p)\n", ppobj);
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);
}
*ppobj = NULL;
if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
obj->StreamVtbl = &DirectMusicLoaderFileStream_Stream_Vtbl;
obj->dwRef = 0; /* will be inited with QueryInterface */
return hr;
}
return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment