[PATCH] dmime: Parse Wave track stream

Michael Stefaniuc mstefani at winehq.org
Sat Oct 30 11:52:40 CDT 2021


Hello Alistair,

sorry for the delay in the review.

- There is a helper dmobj_parsereference() to parse the content of a 
DMUS_FOURCC_REF_LIST. See dmime/segtriggertrack.c for an example.

- There's no real need for parse_wavetrack_list() as wave_IPersistStream_Load() 
isn't doing much.

- stream_chunk_get_data(stream, &child, &header, child.size)
   The size (4th) parameter is a safety guard to avoid corruption due to bad 
streams. So it should be size of the destination data structure aka 
"sizeof(header)".

- Please don't add a space between identifier and the paranthesis in a function 
call, e.g. "IStream_QueryInterface (stream, ...)"


thanks
bye
	michael


On 10/28/21 07:27, Alistair Leslie-Hughes wrote:
> Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
> ---
>   dlls/dmime/dmime_private.h |   6 ++
>   dlls/dmime/wavetrack.c     | 196 ++++++++++++++++++++++++++++++++++++-
>   2 files changed, 200 insertions(+), 2 deletions(-)
> 
> diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h
> index c2221a15fd2..6ab47292b39 100644
> --- a/dlls/dmime/dmime_private.h
> +++ b/dlls/dmime/dmime_private.h
> @@ -86,6 +86,12 @@ typedef struct _DMUS_PRIVATE_TEMPO_ITEM {
>     DMUS_IO_TEMPO_ITEM item;
>   } DMUS_PRIVATE_TEMPO_ITEM, *LPDMUS_PRIVATE_TEMPO_ITEM;
>   
> +struct wave_item {
> +    struct list entry;
> +    DMUS_IO_WAVE_TRACK_HEADER header;
> +    IDirectMusicObject *object;
> +};
> +
>   typedef struct _DMUS_PRIVATE_GRAPH_TOOL {
>     struct list entry; /* for listing elements */
>     DWORD dwIndex;
> diff --git a/dlls/dmime/wavetrack.c b/dlls/dmime/wavetrack.c
> index 1c6b08b5235..92419729fce 100644
> --- a/dlls/dmime/wavetrack.c
> +++ b/dlls/dmime/wavetrack.c
> @@ -20,6 +20,8 @@
>   #include "dmime_private.h"
>   #include "dmobject.h"
>   
> +#include "wine/heap.h"
> +
>   WINE_DEFAULT_DEBUG_CHANNEL(dmime);
>   
>   /*****************************************************************************
> @@ -32,6 +34,8 @@ typedef struct IDirectMusicWaveTrack {
>       IDirectMusicTrack8 IDirectMusicTrack8_iface;
>       struct dmobject dmobj;  /* IPersistStream only */
>       LONG ref;
> +
> +    struct list items;
>   } IDirectMusicWaveTrack;
>   
>   /* IDirectMusicWaveTrack IDirectMusicTrack8 part: */
> @@ -40,6 +44,11 @@ static inline IDirectMusicWaveTrack *impl_from_IDirectMusicTrack8(IDirectMusicTr
>       return CONTAINING_RECORD(iface, IDirectMusicWaveTrack, IDirectMusicTrack8_iface);
>   }
>   
> +static inline IDirectMusicWaveTrack *impl_from_IPersistStream(IPersistStream *iface)
> +{
> +    return CONTAINING_RECORD(iface, IDirectMusicWaveTrack, dmobj.IPersistStream_iface);
> +}
> +
>   static HRESULT WINAPI wave_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
>           void **ret_iface)
>   {
> @@ -81,6 +90,19 @@ static ULONG WINAPI wave_track_Release(IDirectMusicTrack8 *iface)
>       TRACE("(%p) ref=%d\n", This, ref);
>   
>       if (!ref) {
> +        struct list *cursor, *cursor2;
> +        struct wave_item *item;
> +
> +        LIST_FOR_EACH_SAFE(cursor, cursor2, &This->items) {
> +            item = LIST_ENTRY(cursor, struct wave_item, entry);
> +            list_remove(cursor);
> +
> +            if (item->object)
> +                IDirectMusicObject_Release(item->object);
> +
> +            heap_free(item);
> +        }
> +
>           HeapFree(GetProcessHeap(), 0, This);
>           DMIME_UnlockModule();
>       }
> @@ -280,10 +302,179 @@ static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
>       wave_track_Join
>   };
>   
> +static HRESULT parse_wave_item(IDirectMusicWaveTrack *This, IStream *stream,
> +        struct chunk_entry *wave, struct wave_item *item)
> +{
> +    HRESULT hr;
> +    struct chunk_entry chunk = {.parent = wave};
> +
> +    if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> +        return hr;
> +
> +    if(chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_WAVE_LIST)
> +    {
> +        struct chunk_entry child = {.parent = &chunk};
> +        DMUS_IO_WAVE_ITEM_HEADER header;
> +
> +        if (FAILED(hr = stream_next_chunk(stream, &child)))
> +            return  hr;
> +
> +        if(child.id != DMUS_FOURCC_WAVEITEM_CHUNK)
> +            return DMUS_E_UNSUPPORTED_STREAM;
> +
> +        if (FAILED(hr = stream_chunk_get_data(stream, &child, &header, child.size))) {
> +            WARN("Failed to read data of %s\n", debugstr_chunk(&child));
> +            return hr;
> +        }
> +
> +        TRACE("Found DMUS_IO_WAVE_ITEM_HEADER\n");
> +        TRACE("  - lVolume %d\n", header.lVolume);
> +        TRACE("  - dwVariations %d\n", header.dwVariations);
> +        TRACE("  - rtTime %s\n", wine_dbgstr_longlong(header.rtTime));
> +        TRACE("  - rtStartOffset %s\n", wine_dbgstr_longlong(header.rtStartOffset));
> +        TRACE("  - rtReserved %s\n", wine_dbgstr_longlong(header.rtReserved));
> +        TRACE("  - rtDuration %s\n", wine_dbgstr_longlong(header.rtDuration));
> +        TRACE("  - dwLoopStart %d\n", header.dwLoopStart);
> +        TRACE("  - dwLoopEnd %d\n", header.dwLoopEnd);
> +        TRACE("  - dwFlags 0x%08x\n", header.dwFlags);
> +        TRACE("  - wVolumeRange %d\n", header.wVolumeRange);
> +        TRACE("  - wPitchRange %d\n", header.wPitchRange);
> +
> +        if (FAILED(hr = stream_next_chunk(stream, &child)))
> +            return  hr;
> +
> +        if(child.id == FOURCC_LIST && child.type == DMUS_FOURCC_REF_LIST)
> +        {
> +            struct chunk_entry dmrf = {.parent = &child};
> +            IDirectMusicGetLoader *getloader;
> +            IDirectMusicLoader *loader;
> +            DMUS_IO_REFERENCE reference;
> +
> +            if (FAILED(hr = stream_next_chunk(stream, &dmrf)))
> +                return hr;
> +
> +            if(dmrf.id != DMUS_FOURCC_REF_CHUNK)
> +                return DMUS_E_UNSUPPORTED_STREAM;
> +
> +            if (FAILED(hr = stream_chunk_get_data(stream, &dmrf, &reference, dmrf.size))) {
> +                WARN("Failed to read data of %s\n", debugstr_chunk(&dmrf));
> +                return hr;
> +            }
> +
> +            TRACE("REFERENCE guidClassID %s, dwValidData 0x%08x\n", debugstr_dmguid(&reference.guidClassID),
> +                reference.dwValidData);
> +
> +            This->dmobj.desc.guidClass = reference.guidClassID;
> +            This->dmobj.desc.dwValidData = DMUS_OBJ_CLASS;
> +
> +            hr = dmobj_parsedescriptor(stream, &child, &This->dmobj.desc, reference.dwValidData);
> +            if (FAILED(hr))
> +                return hr;
> +
> +            dump_DMUS_OBJECTDESC(&This->dmobj.desc);
> +
> +            hr = IStream_QueryInterface (stream, &IID_IDirectMusicGetLoader, (void**)&getloader);
> +            if (FAILED(hr))
> +                return hr;
> +
> +            hr = IDirectMusicGetLoader_GetLoader (getloader, &loader);
> +            if (FAILED(hr))
> +                return hr;
> +            IDirectMusicGetLoader_Release (getloader);
> +
> +            hr = IDirectMusicLoader_GetObject (loader, &This->dmobj.desc, &IID_IDirectMusicObject,
> +                        (void**)&item->object);
> +            IDirectMusicLoader_Release (loader);
> +        }
> +    }
> +    else
> +        hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> +    return SUCCEEDED(hr) ? S_OK : hr;
> +}
> +
> +static HRESULT parse_wavetrack_list(IDirectMusicWaveTrack *This, IStream *stream,
> +        struct chunk_entry *wave)
> +{
> +    HRESULT hr;
> +    struct chunk_entry chunk = {.parent = wave};
> +    struct wave_item *item = NULL;
> +
> +    TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(wave));
> +
> +    if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> +        return hr;
> +
> +    if (chunk.id != DMUS_FOURCC_WAVETRACK_CHUNK)
> +        return DMUS_E_UNSUPPORTED_STREAM;
> +
> +    item = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(struct wave_item));
> +    if (!item)
> +        return  E_OUTOFMEMORY;
> +
> +    list_add_tail (&This->items, &item->entry);
> +
> +    if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> +        return hr;
> +
> +    if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_WAVEPART_LIST)
> +    {
> +        struct chunk_entry child = {.parent = wave};
> +        DMUS_IO_WAVE_PART_HEADER header;
> +
> +        if (FAILED(hr = stream_next_chunk(stream, &child)))
> +            return hr;
> +
> +        if (child.id != DMUS_FOURCC_WAVEPART_CHUNK)
> +            return DMUS_E_UNSUPPORTED_STREAM;
> +
> +        if (FAILED(hr = stream_chunk_get_data(stream, &child, &header, child.size))) {
> +            WARN("Failed to read data of %s\n", debugstr_chunk(&child));
> +            return hr;
> +        }
> +
> +        TRACE("Found DMUS_IO_WAVE_PART_HEADER\n");
> +        TRACE("  - lVolume %d\n", header.lVolume);
> +        TRACE("  - dwVariations %d\n", header.dwVariations);
> +        TRACE("  - dwPChannel %d\n", header.dwPChannel);
> +        TRACE("  - dwLockToPart %d\n", header.dwLockToPart);
> +        TRACE("  - dwFlags 0x%08x\n", header.dwFlags);
> +        TRACE("  - dwIndex %d\n", header.dwIndex);
> +
> +        if (FAILED(hr = stream_next_chunk(stream, &child)))
> +            return hr;
> +
> +        if(child.id != FOURCC_LIST || child.type != DMUS_FOURCC_WAVEITEM_LIST)
> +            return DMUS_E_UNSUPPORTED_STREAM;
> +
> +        hr = parse_wave_item(This, stream, &child, item);
> +    }
> +    else
> +        hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> +    return SUCCEEDED(hr) ? S_OK : hr;
> +}
> +
>   static HRESULT WINAPI wave_IPersistStream_Load(IPersistStream *iface, IStream *stream)
>   {
> -	FIXME(": Loading not implemented yet\n");
> -	return S_OK;
> +    IDirectMusicWaveTrack *This = impl_from_IPersistStream(iface);
> +    HRESULT hr;
> +    struct chunk_entry chunk = {0};
> +
> +    TRACE("%p, %p\n", This, stream);
> +
> +    if (!stream)
> +        return E_POINTER;
> +
> +    if ((hr = stream_get_chunk(stream, &chunk) != S_OK))
> +        return hr;
> +
> +    if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_WAVETRACK_LIST)
> +        hr = parse_wavetrack_list(This, stream, &chunk);
> +    else
> +        hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> +    return hr;
>   }
>   
>   static const IPersistStreamVtbl persiststream_vtbl = {
> @@ -313,6 +504,7 @@ HRESULT WINAPI create_dmwavetrack(REFIID lpcGUID, void **ppobj)
>       dmobject_init(&track->dmobj, &CLSID_DirectMusicWaveTrack,
>                     (IUnknown *)&track->IDirectMusicTrack8_iface);
>       track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
> +    list_init(&track->items);
>   
>       DMIME_LockModule();
>       hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
> 




More information about the wine-devel mailing list