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:
Michael Stefaniuc 2020-11-30 21:41:01 +01:00 committed by Alexandre Julliard
parent 2ad09b0167
commit 9f9fce44fc
14 changed files with 791 additions and 42 deletions

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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;