From 4c7fb67fc145c0009a276c6e0022ab2f29dc9c06 Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Mon, 21 May 2012 09:39:54 +0200 Subject: [PATCH] dmusic: Simplify IPersistStream_Load by checking DLS header first and exit if it is wrong. --- dlls/dmusic/collection.c | 604 +++++++++++++++++++-------------------- 1 file changed, 300 insertions(+), 304 deletions(-) diff --git a/dlls/dmusic/collection.c b/dlls/dmusic/collection.c index 474557d9298..c06d9886fba 100644 --- a/dlls/dmusic/collection.c +++ b/dlls/dmusic/collection.c @@ -485,314 +485,310 @@ static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_IsDirty(LPPERSIS return E_NOTIMPL; } -static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) +static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Load(LPPERSISTSTREAM iface, IStream* stream) { - IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface); - DMUS_PRIVATE_CHUNK Chunk; - DWORD StreamSize, StreamCount, ListSize[3], ListCount[3]; - LARGE_INTEGER liMove; /* used when skipping chunks */ - ULARGE_INTEGER dlibCollectionPosition, dlibInstrumentPosition, dlibWavePoolPosition; - - IStream_AddRef (pStm); /* add count for later references */ - liMove.QuadPart = 0; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibCollectionPosition); /* store offset, in case it'll be needed later */ - This->liCollectionPosition.QuadPart = dlibCollectionPosition.QuadPart; - This->pStm = pStm; - - IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); - switch (Chunk.fccID) { - case FOURCC_RIFF: { - IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); - TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID)); - StreamSize = Chunk.dwSize - sizeof(FOURCC); - StreamCount = 0; - switch (Chunk.fccID) { - case FOURCC_DLS: { - TRACE_(dmfile)(": collection form\n"); - do { - IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); - StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); - switch (Chunk.fccID) { - case FOURCC_COLH: { - TRACE_(dmfile)(": collection header chunk\n"); - This->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize); - IStream_Read (pStm, This->pHeader, Chunk.dwSize, NULL); - break; - } - case FOURCC_DLID: { - TRACE_(dmfile)(": DLID (GUID) chunk\n"); - This->pDesc->dwValidData |= DMUS_OBJ_OBJECT; - IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL); - break; - } - case FOURCC_VERS: { - TRACE_(dmfile)(": version chunk\n"); - This->pDesc->dwValidData |= DMUS_OBJ_VERSION; - IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL); - break; - } - case FOURCC_PTBL: { - TRACE_(dmfile)(": pool table chunk\n"); - This->pPoolTable = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(POOLTABLE)); - IStream_Read (pStm, This->pPoolTable, sizeof(POOLTABLE), NULL); - Chunk.dwSize -= sizeof(POOLTABLE); - This->pPoolCues = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, This->pPoolTable->cCues*sizeof(POOLCUE)); - IStream_Read (pStm, This->pPoolCues, Chunk.dwSize, NULL); - break; - } - case FOURCC_LIST: { - IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); - TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); - ListSize[0] = Chunk.dwSize - sizeof(FOURCC); - ListCount[0] = 0; - switch (Chunk.fccID) { - case mmioFOURCC('I','N','F','O'): { - TRACE_(dmfile)(": INFO list\n"); - do { - IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); - ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); - switch (Chunk.fccID) { - case mmioFOURCC('I','N','A','M'): { - CHAR szName[DMUS_MAX_NAME]; - TRACE_(dmfile)(": name chunk\n"); - This->pDesc->dwValidData |= DMUS_OBJ_NAME; - IStream_Read (pStm, szName, Chunk.dwSize, NULL); - MultiByteToWideChar (CP_ACP, 0, szName, -1, This->pDesc->wszName, DMUS_MAX_NAME); - if (even_or_odd(Chunk.dwSize)) { - ListCount[0] ++; - liMove.QuadPart = 1; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - } - break; - } - case mmioFOURCC('I','A','R','T'): { - TRACE_(dmfile)(": artist chunk (ignored)\n"); - if (even_or_odd(Chunk.dwSize)) { - ListCount[0] ++; - Chunk.dwSize++; - } - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - case mmioFOURCC('I','C','O','P'): { - TRACE_(dmfile)(": copyright chunk\n"); - This->szCopyright = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize); - IStream_Read (pStm, This->szCopyright, Chunk.dwSize, NULL); - if (even_or_odd(Chunk.dwSize)) { - ListCount[0] ++; - liMove.QuadPart = 1; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - } - break; - } - case mmioFOURCC('I','S','B','J'): { - TRACE_(dmfile)(": subject chunk (ignored)\n"); - if (even_or_odd(Chunk.dwSize)) { - ListCount[0] ++; - Chunk.dwSize++; - } - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - case mmioFOURCC('I','C','M','T'): { - TRACE_(dmfile)(": comment chunk (ignored)\n"); - if (even_or_odd(Chunk.dwSize)) { - ListCount[0] ++; - Chunk.dwSize++; - } - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - default: { - TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); - if (even_or_odd(Chunk.dwSize)) { - ListCount[0] ++; - Chunk.dwSize++; - } - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - } - TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); - } while (ListCount[0] < ListSize[0]); - break; - } - case FOURCC_WVPL: { - TRACE_(dmfile)(": wave pool list (mark & skip)\n"); - liMove.QuadPart = 0; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibWavePoolPosition); /* store position */ - This->liWavePoolTablePosition.QuadPart = dlibWavePoolPosition.QuadPart; - liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - case FOURCC_LINS: { - TRACE_(dmfile)(": instruments list\n"); - do { - IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); - ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); - switch (Chunk.fccID) { - case FOURCC_LIST: { - IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); - TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); - ListSize[1] = Chunk.dwSize - sizeof(FOURCC); - ListCount[1] = 0; - switch (Chunk.fccID) { - case FOURCC_INS: { - LPDMUS_PRIVATE_INSTRUMENTENTRY pNewInstrument = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY)); - TRACE_(dmfile)(": instrument list\n"); - DMUSIC_CreateDirectMusicInstrumentImpl (&IID_IDirectMusicInstrument, (LPVOID*)&pNewInstrument->pInstrument, NULL); /* only way to create this one... even M$ does it discretely */ - { - IDirectMusicInstrumentImpl *pInstrument = impl_from_IDirectMusicInstrument(pNewInstrument->pInstrument); - liMove.QuadPart = 0; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibInstrumentPosition); - pInstrument->liInstrumentPosition.QuadPart = dlibInstrumentPosition.QuadPart - (2*sizeof(FOURCC) + sizeof(DWORD)); /* store offset, it'll be needed later */ + IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface); + DMUS_PRIVATE_CHUNK chunk; + DWORD StreamSize, StreamCount, ListSize[3], ListCount[3]; + LARGE_INTEGER liMove; /* used when skipping chunks */ + ULARGE_INTEGER dlibCollectionPosition, dlibInstrumentPosition, dlibWavePoolPosition; - do { - IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); - ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); - switch (Chunk.fccID) { - case FOURCC_INSH: { - TRACE_(dmfile)(": instrument header chunk\n"); - pInstrument->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize); - IStream_Read (pStm, pInstrument->pHeader, Chunk.dwSize, NULL); - break; - } - case FOURCC_DLID: { - TRACE_(dmfile)(": DLID (GUID) chunk\n"); - pInstrument->pInstrumentID = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize); - IStream_Read (pStm, pInstrument->pInstrumentID, Chunk.dwSize, NULL); - break; - } - case FOURCC_LIST: { - IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); - TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); - ListSize[2] = Chunk.dwSize - sizeof(FOURCC); - ListCount[2] = 0; - switch (Chunk.fccID) { - default: { - TRACE_(dmfile)(": unknown (skipping)\n"); - liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - } - break; - } - default: { - TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - } - TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]); - } while (ListCount[1] < ListSize[1]); - /* DEBUG: dumps whole instrument object tree: */ - if (TRACE_ON(dmusic)) { - TRACE("*** IDirectMusicInstrument (%p) ***\n", pInstrument); - if (pInstrument->pInstrumentID) - TRACE(" - GUID = %s\n", debugstr_dmguid(pInstrument->pInstrumentID)); - - TRACE(" - Instrument header:\n"); - TRACE(" - cRegions: %d\n", pInstrument->pHeader->cRegions); - TRACE(" - Locale:\n"); - TRACE(" - ulBank: %d\n", pInstrument->pHeader->Locale.ulBank); - TRACE(" - ulInstrument: %d\n", pInstrument->pHeader->Locale.ulInstrument); - TRACE(" => dwPatch: %d\n", MIDILOCALE2Patch(&pInstrument->pHeader->Locale)); - } - list_add_tail (&This->Instruments, &pNewInstrument->entry); - } - break; - } - } - break; - } - default: { - TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - } - TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); - } while (ListCount[0] < ListSize[0]); - break; - } - default: { - TRACE_(dmfile)(": unknown (skipping)\n"); - liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - } - break; - } - default: { - TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); - break; - } - } - TRACE_(dmfile)(": StreamCount = %d < StreamSize = %d\n", StreamCount, StreamSize); - } while (StreamCount < StreamSize); - break; - } - default: { - TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); - liMove.QuadPart = StreamSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ - return E_FAIL; - } - } - TRACE_(dmfile)(": reading finished\n"); - break; - } - default: { - TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ - return E_FAIL; - } - } + IStream_AddRef(stream); /* add count for later references */ + liMove.QuadPart = 0; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibCollectionPosition); /* store offset, in case it'll be needed later */ + This->liCollectionPosition.QuadPart = dlibCollectionPosition.QuadPart; + This->pStm = stream; - /* DEBUG: dumps whole collection object tree: */ - if (TRACE_ON(dmusic)) { - int r = 0; - DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry; - struct list *listEntry; + IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL); + TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); - TRACE("*** IDirectMusicCollection (%p) ***\n", &This->IDirectMusicCollection_iface); - if (This->pDesc->dwValidData & DMUS_OBJ_OBJECT) - TRACE(" - GUID = %s\n", debugstr_dmguid(&This->pDesc->guidObject)); - if (This->pDesc->dwValidData & DMUS_OBJ_VERSION) - TRACE(" - Version = %i,%i,%i,%i\n", (This->pDesc->vVersion.dwVersionMS >> 8) & 0x0000FFFF, This->pDesc->vVersion.dwVersionMS & 0x0000FFFF, - (This->pDesc->vVersion.dwVersionLS >> 8) & 0x0000FFFF, This->pDesc->vVersion.dwVersionLS & 0x0000FFFF); - if (This->pDesc->dwValidData & DMUS_OBJ_NAME) - TRACE(" - Name = %s\n", debugstr_w(This->pDesc->wszName)); - - TRACE(" - Collection header:\n"); - TRACE(" - cInstruments: %d\n", This->pHeader->cInstruments); - TRACE(" - Instruments:\n"); - - LIST_FOR_EACH (listEntry, &This->Instruments) { - tmpEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry ); - TRACE(" - Instrument[%i]: %p\n", r, tmpEntry->pInstrument); - r++; - } - } - - return S_OK; + if (chunk.fccID != FOURCC_RIFF) { + TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ + return E_FAIL; + } + + IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL); + TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunk.fccID)); + StreamSize = chunk.dwSize - sizeof(FOURCC); + StreamCount = 0; + + if (chunk.fccID != FOURCC_DLS) { + TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); + liMove.QuadPart = StreamSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ + return E_FAIL; + } + + TRACE_(dmfile)(": collection form\n"); + do { + IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL); + StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize; + TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); + switch (chunk.fccID) { + case FOURCC_COLH: { + TRACE_(dmfile)(": collection header chunk\n"); + This->pHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, chunk.dwSize); + IStream_Read(stream, This->pHeader, chunk.dwSize, NULL); + break; + } + case FOURCC_DLID: { + TRACE_(dmfile)(": DLID (GUID) chunk\n"); + This->pDesc->dwValidData |= DMUS_OBJ_OBJECT; + IStream_Read(stream, &This->pDesc->guidObject, chunk.dwSize, NULL); + break; + } + case FOURCC_VERS: { + TRACE_(dmfile)(": version chunk\n"); + This->pDesc->dwValidData |= DMUS_OBJ_VERSION; + IStream_Read(stream, &This->pDesc->vVersion, chunk.dwSize, NULL); + break; + } + case FOURCC_PTBL: { + TRACE_(dmfile)(": pool table chunk\n"); + This->pPoolTable = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POOLTABLE)); + IStream_Read(stream, This->pPoolTable, sizeof(POOLTABLE), NULL); + chunk.dwSize -= sizeof(POOLTABLE); + This->pPoolCues = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pPoolTable->cCues * sizeof(POOLCUE)); + IStream_Read(stream, This->pPoolCues, chunk.dwSize, NULL); + break; + } + case FOURCC_LIST: { + IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL); + TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID)); + ListSize[0] = chunk.dwSize - sizeof(FOURCC); + ListCount[0] = 0; + switch (chunk.fccID) { + case mmioFOURCC('I','N','F','O'): { + TRACE_(dmfile)(": INFO list\n"); + do { + IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL); + ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize; + TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); + switch (chunk.fccID) { + case mmioFOURCC('I','N','A','M'): { + CHAR szName[DMUS_MAX_NAME]; + TRACE_(dmfile)(": name chunk\n"); + This->pDesc->dwValidData |= DMUS_OBJ_NAME; + IStream_Read(stream, szName, chunk.dwSize, NULL); + MultiByteToWideChar(CP_ACP, 0, szName, -1, This->pDesc->wszName, DMUS_MAX_NAME); + if (even_or_odd(chunk.dwSize)) { + ListCount[0]++; + liMove.QuadPart = 1; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + } + break; + } + case mmioFOURCC('I','A','R','T'): { + TRACE_(dmfile)(": artist chunk (ignored)\n"); + if (even_or_odd(chunk.dwSize)) { + ListCount[0]++; + chunk.dwSize++; + } + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + case mmioFOURCC('I','C','O','P'): { + TRACE_(dmfile)(": copyright chunk\n"); + This->szCopyright = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, chunk.dwSize); + IStream_Read(stream, This->szCopyright, chunk.dwSize, NULL); + if (even_or_odd(chunk.dwSize)) { + ListCount[0]++; + liMove.QuadPart = 1; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + } + break; + } + case mmioFOURCC('I','S','B','J'): { + TRACE_(dmfile)(": subject chunk (ignored)\n"); + if (even_or_odd(chunk.dwSize)) { + ListCount[0]++; + chunk.dwSize++; + } + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + case mmioFOURCC('I','C','M','T'): { + TRACE_(dmfile)(": comment chunk (ignored)\n"); + if (even_or_odd(chunk.dwSize)) { + ListCount[0]++; + chunk.dwSize++; + } + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + default: { + TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); + if (even_or_odd(chunk.dwSize)) { + ListCount[0]++; + chunk.dwSize++; + } + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } + TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); + } while (ListCount[0] < ListSize[0]); + break; + } + case FOURCC_WVPL: { + TRACE_(dmfile)(": wave pool list (mark & skip)\n"); + liMove.QuadPart = 0; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibWavePoolPosition); /* store position */ + This->liWavePoolTablePosition.QuadPart = dlibWavePoolPosition.QuadPart; + liMove.QuadPart = chunk.dwSize - sizeof(FOURCC); + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + case FOURCC_LINS: { + TRACE_(dmfile)(": instruments list\n"); + do { + IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL); + ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize; + TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); + switch (chunk.fccID) { + case FOURCC_LIST: { + IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL); + TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID)); + ListSize[1] = chunk.dwSize - sizeof(FOURCC); + ListCount[1] = 0; + switch (chunk.fccID) { + case FOURCC_INS: { + LPDMUS_PRIVATE_INSTRUMENTENTRY new_instrument = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY)); + TRACE_(dmfile)(": instrument list\n"); + /* Only way to create this one... even M$ does it discretely */ + DMUSIC_CreateDirectMusicInstrumentImpl(&IID_IDirectMusicInstrument, (LPVOID*)&new_instrument->pInstrument, NULL); + { + IDirectMusicInstrumentImpl *instrument = impl_from_IDirectMusicInstrument(new_instrument->pInstrument); + liMove.QuadPart = 0; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibInstrumentPosition); + /* Store offset, it'll be needed later */ + instrument->liInstrumentPosition.QuadPart = dlibInstrumentPosition.QuadPart - (2 * sizeof(FOURCC) + sizeof(DWORD)); + do { + IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL); + ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize; + TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); + switch (chunk.fccID) { + case FOURCC_INSH: { + TRACE_(dmfile)(": instrument header chunk\n"); + instrument->pHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, chunk.dwSize); + IStream_Read(stream, instrument->pHeader, chunk.dwSize, NULL); + break; + } + case FOURCC_DLID: { + TRACE_(dmfile)(": DLID (GUID) chunk\n"); + instrument->pInstrumentID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, chunk.dwSize); + IStream_Read(stream, instrument->pInstrumentID, chunk.dwSize, NULL); + break; + } + case FOURCC_LIST: { + IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL); + TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID)); + ListSize[2] = chunk.dwSize - sizeof(FOURCC); + ListCount[2] = 0; + switch (chunk.fccID) { + default: { + TRACE_(dmfile)(": unknown (skipping)\n"); + liMove.QuadPart = chunk.dwSize - sizeof(FOURCC); + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } + break; + } + default: { + TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } + TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]); + } while (ListCount[1] < ListSize[1]); + /* DEBUG: dumps whole instrument object tree: */ + if (TRACE_ON(dmusic)) { + TRACE("*** IDirectMusicInstrument (%p) ***\n", instrument); + if (instrument->pInstrumentID) + TRACE(" - GUID = %s\n", debugstr_dmguid(instrument->pInstrumentID)); + TRACE(" - Instrument header:\n"); + TRACE(" - cRegions: %d\n", instrument->pHeader->cRegions); + TRACE(" - Locale:\n"); + TRACE(" - ulBank: %d\n", instrument->pHeader->Locale.ulBank); + TRACE(" - ulInstrument: %d\n", instrument->pHeader->Locale.ulInstrument); + TRACE(" => dwPatch: %d\n", MIDILOCALE2Patch(&instrument->pHeader->Locale)); + } + list_add_tail(&This->Instruments, &new_instrument->entry); + } + break; + } + } + break; + } + default: { + TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } + TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); + } while (ListCount[0] < ListSize[0]); + break; + } + default: { + TRACE_(dmfile)(": unknown (skipping)\n"); + liMove.QuadPart = chunk.dwSize - sizeof(FOURCC); + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } + break; + } + default: { + TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); + liMove.QuadPart = chunk.dwSize; + IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } + TRACE_(dmfile)(": StreamCount = %d < StreamSize = %d\n", StreamCount, StreamSize); + } while (StreamCount < StreamSize); + + TRACE_(dmfile)(": reading finished\n"); + + + /* DEBUG: dumps whole collection object tree: */ + if (TRACE_ON(dmusic)) { + int r = 0; + DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry; + struct list *listEntry; + + TRACE("*** IDirectMusicCollection (%p) ***\n", &This->IDirectMusicCollection_iface); + if (This->pDesc->dwValidData & DMUS_OBJ_OBJECT) + TRACE(" - GUID = %s\n", debugstr_dmguid(&This->pDesc->guidObject)); + if (This->pDesc->dwValidData & DMUS_OBJ_VERSION) + TRACE(" - Version = %i,%i,%i,%i\n", (This->pDesc->vVersion.dwVersionMS >> 8) & 0x0000FFFF, This->pDesc->vVersion.dwVersionMS & 0x0000FFFF, + (This->pDesc->vVersion.dwVersionLS >> 8) & 0x0000FFFF, This->pDesc->vVersion.dwVersionLS & 0x0000FFFF); + if (This->pDesc->dwValidData & DMUS_OBJ_NAME) + TRACE(" - Name = %s\n", debugstr_w(This->pDesc->wszName)); + + TRACE(" - Collection header:\n"); + TRACE(" - cInstruments: %d\n", This->pHeader->cInstruments); + TRACE(" - Instruments:\n"); + + LIST_FOR_EACH(listEntry, &This->Instruments) { + tmpEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry ); + TRACE(" - Instrument[%i]: %p\n", r, tmpEntry->pInstrument); + r++; + } + } + + return S_OK; } static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Save(LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty)