dmusic: Sync up the dmobject.[ch] files.
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2ad09b0167
commit
9f9fce44fc
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dmusics.h"
|
||||
#include "dmobject.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
|
||||
|
@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
|
||||
{
|
||||
LARGE_INTEGER end;
|
||||
|
||||
|
@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
|
|||
return stream_get_chunk(stream, chunk);
|
||||
}
|
||||
|
||||
/* Reads chunk data of the form:
|
||||
DWORD - size of array element
|
||||
element[] - Array of elements
|
||||
The caller needs to heap_free() the array.
|
||||
*/
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size)
|
||||
{
|
||||
DWORD size;
|
||||
HRESULT hr;
|
||||
|
||||
*array = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (chunk->size < sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
|
||||
return E_FAIL;
|
||||
}
|
||||
if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
|
||||
return hr;
|
||||
if (size != elem_size) {
|
||||
WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
|
||||
debugstr_chunk(chunk), size, elem_size);
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
}
|
||||
|
||||
*count = (chunk->size - sizeof(DWORD)) / elem_size;
|
||||
size = *count * elem_size;
|
||||
if (!(*array = heap_alloc(size)))
|
||||
return E_OUTOFMEMORY;
|
||||
if (FAILED(hr = stream_read(stream, *array, size))) {
|
||||
heap_free(*array);
|
||||
*array = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (chunk->size > size + sizeof(DWORD)) {
|
||||
WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
|
||||
stream_skip_chunk(stream, chunk);
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size)
|
||||
{
|
||||
|
@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
|
||||
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
|
||||
switch (chunk.id) {
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
break;
|
||||
case DMUS_FOURCC_DATE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->ftDate, sizeof(desc->ftDate)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_DATE;
|
||||
break;
|
||||
case DMUS_FOURCC_FILE_CHUNK:
|
||||
if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_FILENAME;
|
||||
break;
|
||||
case DMUS_FOURCC_GUID_CHUNK:
|
||||
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
|
||||
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_OBJECT;
|
||||
break;
|
||||
case DMUS_FOURCC_CATEGORY_CHUNK:
|
||||
if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_CATEGORY;
|
||||
case DMUS_FOURCC_NAME_CHUNK:
|
||||
if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
|
||||
desc->wszName, sizeof(desc->wszName)) == S_OK)
|
||||
desc->dwValidData |= DMUS_OBJ_NAME;
|
||||
break;
|
||||
case DMUS_FOURCC_VERSION_CHUNK:
|
||||
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
|
||||
|
@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = list};
|
||||
IDirectMusicGetLoader *getloader;
|
||||
IDirectMusicLoader *loader;
|
||||
DMUS_OBJECTDESC desc;
|
||||
DMUS_IO_REFERENCE reference;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = stream_next_chunk(stream, &chunk)))
|
||||
return hr;
|
||||
if (chunk.id != DMUS_FOURCC_REF_CHUNK)
|
||||
return DMUS_E_UNSUPPORTED_STREAM;
|
||||
|
||||
if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
|
||||
WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
|
||||
return hr;
|
||||
}
|
||||
TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
|
||||
reference.dwValidData);
|
||||
|
||||
if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
|
||||
return hr;
|
||||
desc.guidClass = reference.guidClassID;
|
||||
desc.dwValidData |= DMUS_OBJ_CLASS;
|
||||
dump_DMUS_OBJECTDESC(&desc);
|
||||
|
||||
if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
|
||||
return hr;
|
||||
hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
|
||||
IDirectMusicGetLoader_Release(getloader);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
|
||||
IDirectMusicLoader_Release(loader);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@ struct chunk_entry {
|
|||
|
||||
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
|
||||
unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
|
||||
ULONG size) DECLSPEC_HIDDEN;
|
||||
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
|
||||
|
@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
|
|||
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
|
||||
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
|
||||
|
||||
/* 'DMRF' (reference list) helper */
|
||||
HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
|
||||
IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Generic IPersistStream methods */
|
||||
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
|
||||
void **ret_iface) DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Reference in New Issue