Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / dmband / bandtrack.c
1 /* IDirectMusicBandTrack Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include "dmband_private.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(dmband);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
24
25 /*****************************************************************************
26  * IDirectMusicBandTrack implementation
27  */
28 /* IDirectMusicBandTrack IUnknown part: */
29 HRESULT WINAPI IDirectMusicBandTrack_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
30         ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface);
31         TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
32
33         if (IsEqualIID (riid, &IID_IUnknown)) {
34                 *ppobj = (LPUNKNOWN)&This->UnknownVtbl;
35                 IDirectMusicBandTrack_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
36                 return S_OK;
37         } else if (IsEqualIID (riid, &IID_IDirectMusicTrack)
38           || IsEqualIID (riid, &IID_IDirectMusicTrack8)) {
39                 *ppobj = (LPDIRECTMUSICTRACK8)&This->TrackVtbl;
40                 IDirectMusicBandTrack_IDirectMusicTrack_AddRef ((LPDIRECTMUSICTRACK8)&This->TrackVtbl);
41                 return S_OK;
42         } else if (IsEqualIID (riid, &IID_IPersistStream)) {
43                 *ppobj = (LPPERSISTSTREAM)&This->PersistStreamVtbl;
44                 IDirectMusicBandTrack_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);
45                 return S_OK;
46         }
47         
48         WARN("(%p, %s,%p): not found\n", This, debugstr_dmguid(riid), ppobj);
49         return E_NOINTERFACE;
50 }
51
52 ULONG WINAPI IDirectMusicBandTrack_IUnknown_AddRef (LPUNKNOWN iface) {
53   ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface);
54   TRACE("(%p) : AddRef from %ld\n", This, This->ref);
55   return ++(This->ref);
56 }
57
58 ULONG WINAPI IDirectMusicBandTrack_IUnknown_Release (LPUNKNOWN iface) {
59   ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface);
60   ULONG ref = --This->ref;
61   TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
62   if (ref == 0) {
63     HeapFree(GetProcessHeap(), 0, This);
64   }
65   return ref;
66 }
67
68 ICOM_VTABLE(IUnknown) DirectMusicBandTrack_Unknown_Vtbl = {
69   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
70   IDirectMusicBandTrack_IUnknown_QueryInterface,
71   IDirectMusicBandTrack_IUnknown_AddRef,
72   IDirectMusicBandTrack_IUnknown_Release
73 };
74
75 /* IDirectMusicBandTrack IDirectMusicTrack8 part: */
76 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_QueryInterface (LPDIRECTMUSICTRACK8 iface, REFIID riid, LPVOID *ppobj) {
77   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
78   return IDirectMusicBandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
79 }
80
81 ULONG WINAPI IDirectMusicBandTrack_IDirectMusicTrack_AddRef (LPDIRECTMUSICTRACK8 iface) {
82   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
83   return IDirectMusicBandTrack_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
84 }
85
86 ULONG WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Release (LPDIRECTMUSICTRACK8 iface) {
87   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
88   return IDirectMusicBandTrack_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
89 }
90
91 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Init (LPDIRECTMUSICTRACK8 iface, IDirectMusicSegment* pSegment) {
92   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
93   FIXME("(%p, %p): stub\n", This, pSegment);
94   return S_OK;
95 }
96
97 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_InitPlay (LPDIRECTMUSICTRACK8 iface, IDirectMusicSegmentState* pSegmentState, IDirectMusicPerformance* pPerformance, void** ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags) {
98   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
99   FIXME("(%p, %p, %p, %p, %ld, %ld): stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
100   return S_OK;
101 }
102
103 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_EndPlay (LPDIRECTMUSICTRACK8 iface, void* pStateData) {
104   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
105   FIXME("(%p, %p): stub\n", This, pStateData);
106   return S_OK;
107 }
108
109 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Play (LPDIRECTMUSICTRACK8 iface, void* pStateData, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags, IDirectMusicPerformance* pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID) {
110   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
111   
112   FIXME("(%p, %p, %ld, %ld, %ld, %ld, %p, %p, %ld): semi-stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
113   /* Sends following pMSG:
114      - DMUS_PATCH_PMSG
115      - DMUS_TRANSPOSE_PMSG
116      - DMUS_CHANNEL_PRIORITY_PMSG
117      - DMUS_MIDI_PMSG
118   */
119
120   return S_OK;
121 }
122
123 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_GetParam (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
124   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
125   FIXME("(%p, %s, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pmtNext, pParam);
126   return S_OK;
127 }
128
129 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_SetParam (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, MUSIC_TIME mtTime, void* pParam) {
130   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
131   FIXME("(%p, %s, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pParam);
132   return S_OK;
133 }
134
135 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_IsParamSupported (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType) {
136   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
137   
138   TRACE("(%p, %s): ", This, debugstr_dmguid(rguidType));
139   if (IsEqualGUID (rguidType, &GUID_BandParam)
140       || IsEqualGUID (rguidType, &GUID_Clear_All_Bands)
141       || IsEqualGUID (rguidType, &GUID_ConnectToDLSCollection)
142       || IsEqualGUID (rguidType, &GUID_Disable_Auto_Download)
143       || IsEqualGUID (rguidType, &GUID_Download)
144       || IsEqualGUID (rguidType, &GUID_DownloadToAudioPath)
145       || IsEqualGUID (rguidType, &GUID_Enable_Auto_Download)
146       || IsEqualGUID (rguidType, &GUID_IDirectMusicBand)
147       || IsEqualGUID (rguidType, &GUID_StandardMIDIFile)
148       || IsEqualGUID (rguidType, &GUID_Unload)
149       || IsEqualGUID (rguidType, &GUID_UnloadFromAudioPath)) {
150     TRACE("param supported\n");
151     return S_OK;
152   }
153   
154   TRACE("param unsupported\n");
155   return DMUS_E_TYPE_UNSUPPORTED;
156 }
157
158 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_AddNotificationType (LPDIRECTMUSICTRACK8 iface, REFGUID rguidNotificationType) {
159   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
160   FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
161   return S_OK;
162 }
163
164 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_RemoveNotificationType (LPDIRECTMUSICTRACK8 iface, REFGUID rguidNotificationType) {
165   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
166   FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
167   return S_OK;
168 }
169
170 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Clone (LPDIRECTMUSICTRACK8 iface, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, IDirectMusicTrack** ppTrack) {
171   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
172   FIXME("(%p, %ld, %ld, %p): stub\n", This, mtStart, mtEnd, ppTrack);
173   return S_OK;
174 }
175
176 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_PlayEx (LPDIRECTMUSICTRACK8 iface, void* pStateData, REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags, IDirectMusicPerformance* pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID) {
177   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
178   FIXME("(%p, %p, %lli, %lli, %lli, %ld, %p, %p, %ld): stub\n", This, pStateData, rtStart, rtEnd, rtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
179   return S_OK;
180 }
181
182 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_GetParamEx (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME* prtNext, void* pParam, void* pStateData, DWORD dwFlags) {
183   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
184   FIXME("(%p, %s, %lli, %p, %p, %p, %ld): stub\n", This, debugstr_dmguid(rguidType), rtTime, prtNext, pParam, pStateData, dwFlags);
185   return S_OK;
186 }
187
188 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_SetParamEx (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, REFERENCE_TIME rtTime, void* pParam, void* pStateData, DWORD dwFlags) {
189   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
190   FIXME("(%p, %s, %lli, %p, %p, %ld): stub\n", This, debugstr_dmguid(rguidType), rtTime, pParam, pStateData, dwFlags);
191   return S_OK;
192 }
193
194 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Compose (LPDIRECTMUSICTRACK8 iface, IUnknown* pContext, DWORD dwTrackGroup, IDirectMusicTrack** ppResultTrack) {
195   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
196   FIXME("(%p, %p, %ld, %p): stub\n", This, pContext, dwTrackGroup, ppResultTrack);
197   return S_OK;
198 }
199
200 HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Join (LPDIRECTMUSICTRACK8 iface, IDirectMusicTrack* pNewTrack, MUSIC_TIME mtJoin, IUnknown* pContext, DWORD dwTrackGroup, IDirectMusicTrack** ppResultTrack) {
201   ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
202   FIXME("(%p, %p, %ld, %p, %ld, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
203   return S_OK;
204 }
205
206 ICOM_VTABLE(IDirectMusicTrack8) DirectMusicBandTrack_DirectMusicTrack_Vtbl = {
207   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
208   IDirectMusicBandTrack_IDirectMusicTrack_QueryInterface,
209   IDirectMusicBandTrack_IDirectMusicTrack_AddRef,
210   IDirectMusicBandTrack_IDirectMusicTrack_Release,
211   IDirectMusicBandTrack_IDirectMusicTrack_Init,
212   IDirectMusicBandTrack_IDirectMusicTrack_InitPlay,
213   IDirectMusicBandTrack_IDirectMusicTrack_EndPlay,
214   IDirectMusicBandTrack_IDirectMusicTrack_Play,
215   IDirectMusicBandTrack_IDirectMusicTrack_GetParam,
216   IDirectMusicBandTrack_IDirectMusicTrack_SetParam,
217   IDirectMusicBandTrack_IDirectMusicTrack_IsParamSupported,
218   IDirectMusicBandTrack_IDirectMusicTrack_AddNotificationType,
219   IDirectMusicBandTrack_IDirectMusicTrack_RemoveNotificationType,
220   IDirectMusicBandTrack_IDirectMusicTrack_Clone,
221   IDirectMusicBandTrack_IDirectMusicTrack_PlayEx,
222   IDirectMusicBandTrack_IDirectMusicTrack_GetParamEx,
223   IDirectMusicBandTrack_IDirectMusicTrack_SetParamEx,
224   IDirectMusicBandTrack_IDirectMusicTrack_Compose,
225   IDirectMusicBandTrack_IDirectMusicTrack_Join
226 };
227
228 /* IDirectMusicBandTrack IPersistStream part: */
229 HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
230   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
231   return IDirectMusicBandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
232 }
233
234 ULONG WINAPI IDirectMusicBandTrack_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
235   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
236   return IDirectMusicBandTrack_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
237 }
238
239 ULONG WINAPI IDirectMusicBandTrack_IPersistStream_Release (LPPERSISTSTREAM iface) {
240   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
241   return IDirectMusicBandTrack_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
242 }
243
244 HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
245   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
246   TRACE("(%p, %p)\n", This, pClassID);
247   memcpy(pClassID, &CLSID_DirectMusicBandTrack, sizeof(CLSID));
248   return S_OK;
249 }
250
251 HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
252   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
253   FIXME("(%p): stub, always S_FALSE\n", This);
254   return S_FALSE;
255 }
256
257 static HRESULT IDirectMusicBandTrack_IPersistStream_LoadBand (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicBand** ppBand,
258                                                               DMUS_PRIVATE_BAND_ITEM_HEADER* pHeader) {
259
260   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
261   HRESULT hr = E_FAIL;
262   IPersistStream* pPersistStream = NULL;
263   
264   hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand);
265   if (FAILED(hr)) {
266     ERR(": could not create object\n");
267     return hr;
268   }
269   /* acquire PersistStream interface */
270   hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream);
271   if (FAILED(hr)) {
272     ERR(": could not acquire IPersistStream\n");
273     return hr;
274   }
275   /* load */
276   hr = IPersistStream_Load (pPersistStream, pClonedStream);
277   if (FAILED(hr)) {
278     ERR(": failed to load object\n");
279     return hr;
280   }
281   
282   /* release all loading-related stuff */
283   IPersistStream_Release (pPersistStream);
284
285   /*
286    * @TODO insert pBand into This
287    */
288   if (SUCCEEDED(hr)) {
289     LPDMUS_PRIVATE_BAND pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_BAND));
290     if (NULL == pNewBand) {
291       ERR(": no more memory\n");
292       return  E_OUTOFMEMORY;
293     }
294     memcpy(&pNewBand->pBandHeader, pHeader, sizeof(DMUS_PRIVATE_BAND_ITEM_HEADER));
295     pNewBand->ppBand = (IDirectMusicBandImpl*)((char*)(*ppBand) - offsetof(IDirectMusicBandImpl,BandVtbl));
296     IDirectMusicBandImpl_IDirectMusicBand_AddRef(*ppBand);
297     list_add_tail (&This->Bands, &pNewBand->entry);
298   }
299
300   return S_OK;
301 }
302
303 static HRESULT IDirectMusicBandTrack_IPersistStream_ParseBandsList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
304
305   /*ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);*/
306   HRESULT hr = E_FAIL;
307   DMUS_PRIVATE_CHUNK Chunk;
308   DWORD StreamSize, ListSize[3], ListCount[3];
309   LARGE_INTEGER liMove; /* used when skipping chunks */
310
311   IDirectMusicBand* pBand = NULL;
312   DMUS_PRIVATE_BAND_ITEM_HEADER header;
313
314   if (pChunk->fccID != DMUS_FOURCC_BANDS_LIST) {
315     ERR_(dmfile)(": %s chunk should be a BANDS list\n", debugstr_fourcc (pChunk->fccID));
316     return E_FAIL;
317   }  
318
319   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
320   ListCount[0] = 0;
321
322   do {
323     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
324     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
325     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
326     switch (Chunk.fccID) {
327     case FOURCC_LIST: {
328       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
329       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
330       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
331       ListCount[1] = 0;
332       do {
333         IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
334         ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
335         TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
336         switch (Chunk.fccID) { 
337         case DMUS_FOURCC_BANDITEM_CHUNK: {
338           DMUS_IO_BAND_ITEM_HEADER tmp_header;
339           TRACE_(dmfile)(": Band Item chunk v1\n");
340           
341           IStream_Read (pStm, &tmp_header, sizeof(DMUS_IO_BAND_ITEM_HEADER), NULL);
342           TRACE_(dmfile)(" - lBandTime: %lu\n", tmp_header.lBandTime);
343           
344           header.dwVersion = 1;
345           header.lBandTime = tmp_header.lBandTime;
346           break;
347         }
348         case DMUS_FOURCC_BANDITEM_CHUNK2: { 
349           DMUS_IO_BAND_ITEM_HEADER2 tmp_header2;
350           TRACE_(dmfile)(": Band Item chunk v2\n");
351           
352           IStream_Read (pStm, &tmp_header2, sizeof(DMUS_IO_BAND_ITEM_HEADER2), NULL);
353           TRACE_(dmfile)(" - lBandTimeLogical: %lu\n", tmp_header2.lBandTimeLogical);
354           TRACE_(dmfile)(" - lBandTimePhysical: %lu\n", tmp_header2.lBandTimePhysical);
355           
356           header.dwVersion = 2;
357           header.lBandTimeLogical = tmp_header2.lBandTimeLogical;
358           header.lBandTimePhysical = tmp_header2.lBandTimePhysical;
359           break;
360         }
361         case FOURCC_RIFF: { 
362           IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
363           TRACE_(dmfile)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk.fccID));
364           StreamSize = Chunk.dwSize - sizeof(FOURCC);
365           switch (Chunk.fccID) {
366           case DMUS_FOURCC_BAND_FORM: {
367             LPSTREAM pClonedStream = NULL;
368             TRACE_(dmfile)(": BAND RIFF\n");
369             
370             IStream_Clone (pStm, &pClonedStream);
371             
372             liMove.QuadPart = 0;
373             liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
374             IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
375             
376             hr = IDirectMusicBandTrack_IPersistStream_LoadBand (iface, pClonedStream, &pBand, &header);
377             if (FAILED(hr)) {
378               ERR(": could not load track\n");
379               return hr;
380             }
381             IStream_Release (pClonedStream);
382             
383             IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */
384             
385             /** now safe move the cursor */
386             liMove.QuadPart = StreamSize;
387             IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
388             break;
389           }
390           default: {
391             TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
392             liMove.QuadPart = StreamSize;
393             IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
394             break;                                              
395           }
396           }
397           break;
398         }
399         default: {
400           TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
401           liMove.QuadPart = Chunk.dwSize;
402           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
403           break;                                                
404          }
405         }
406         TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
407       } while (ListCount[1] < ListSize[1]);
408       break;
409     }
410     default: {
411       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
412       liMove.QuadPart = Chunk.dwSize;
413       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
414       break;                                            
415     }
416     }
417     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
418   } while (ListCount[0] < ListSize[0]);
419
420   return S_OK;
421 }
422
423 static HRESULT IDirectMusicBandTrack_IPersistStream_ParseBandTrackForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
424
425   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
426   HRESULT hr = E_FAIL;
427   DMUS_PRIVATE_CHUNK Chunk;
428   DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
429   LARGE_INTEGER liMove; /* used when skipping chunks */
430
431   if (pChunk->fccID != DMUS_FOURCC_BANDTRACK_FORM) {
432     ERR_(dmfile)(": %s chunk should be a BANDTRACK form\n", debugstr_fourcc (pChunk->fccID));
433     return E_FAIL;
434   }  
435
436   StreamSize = pChunk->dwSize - sizeof(FOURCC);
437   StreamCount = 0;
438
439   do {
440     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
441     StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
442     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
443     
444     hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc);
445     if (FAILED(hr)) return hr;
446
447     if (hr == S_FALSE) {
448       switch (Chunk.fccID) {
449       case DMUS_FOURCC_BANDTRACK_CHUNK: {
450         TRACE_(dmfile)(": BandTrack chunk\n");
451         IStream_Read (pStm, &This->header, sizeof(DMUS_IO_BAND_TRACK_HEADER), NULL);
452         TRACE_(dmfile)(" - bAutoDownload: %u\n", This->header.bAutoDownload);
453         break;
454       }   
455       case FOURCC_LIST: {
456         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
457         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
458         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
459         ListCount[0] = 0;
460         switch (Chunk.fccID) {
461         case DMUS_FOURCC_UNFO_LIST: { 
462           TRACE_(dmfile)(": UNFO list\n");
463           do {
464             IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
465             ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
466             TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
467             
468             hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc);
469             if (FAILED(hr)) return hr;
470             
471             if (hr == S_FALSE) {
472               switch (Chunk.fccID) {
473               default: {
474                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
475                 liMove.QuadPart = Chunk.dwSize;
476                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
477                 break;                          
478               }
479               }
480             }  
481             TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
482           } while (ListCount[0] < ListSize[0]);
483           break;
484         }
485         case DMUS_FOURCC_BANDS_LIST: {
486           TRACE_(dmfile)(": TRACK list\n");
487           hr = IDirectMusicBandTrack_IPersistStream_ParseBandsList (iface, &Chunk, pStm);
488           if (FAILED(hr)) return hr;
489           break;
490         }
491         default: {
492           TRACE_(dmfile)(": unknown (skipping)\n");
493           liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
494           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
495           break;                                                
496         }
497         }
498         break;
499       }
500       default: {
501         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
502         liMove.QuadPart = Chunk.dwSize;
503         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
504         break;                                          
505       }
506       }
507     }
508     TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
509   } while (StreamCount < StreamSize);  
510
511   return S_OK;
512 }
513
514
515 HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
516   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
517
518   DMUS_PRIVATE_CHUNK Chunk;
519   LARGE_INTEGER liMove;
520   HRESULT hr;
521
522   TRACE("(%p, %p): Loading\n", This, pStm);
523
524   IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
525   TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
526   switch (Chunk.fccID) {
527   case FOURCC_RIFF: {
528     IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
529     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
530     switch (Chunk.fccID) {
531     case DMUS_FOURCC_BANDTRACK_FORM: {
532       TRACE_(dmfile)(": Band track form\n");
533       hr = IDirectMusicBandTrack_IPersistStream_ParseBandTrackForm (iface, &Chunk, pStm);
534       if (FAILED(hr)) return hr;
535       break;    
536     }
537     default: {
538       TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
539       liMove.QuadPart = Chunk.dwSize;
540       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
541       return E_FAIL;
542     }
543     }
544     TRACE_(dmfile)(": reading finished\n");
545     break;
546   }
547   default: {
548     TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
549     liMove.QuadPart = Chunk.dwSize;
550     IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
551     return E_FAIL;
552   }
553   }
554
555   return S_OK;
556 }
557
558 HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
559   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
560   FIXME("(%p): Saving not implemented yet\n", This);
561   return E_NOTIMPL;
562 }
563
564 HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
565   ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
566   FIXME("(%p, %p): stub\n", This, pcbSize);
567   return E_NOTIMPL;
568 }
569
570 ICOM_VTABLE(IPersistStream) DirectMusicBandTrack_PerststStream_Vtbl = {
571   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
572   IDirectMusicBandTrack_IPersistStream_QueryInterface,
573   IDirectMusicBandTrack_IPersistStream_AddRef,
574   IDirectMusicBandTrack_IPersistStream_Release,
575   IDirectMusicBandTrack_IPersistStream_GetClassID,
576   IDirectMusicBandTrack_IPersistStream_IsDirty,
577   IDirectMusicBandTrack_IPersistStream_Load,
578   IDirectMusicBandTrack_IPersistStream_Save,
579   IDirectMusicBandTrack_IPersistStream_GetSizeMax
580 };
581
582 /* for ClassFactory */
583 HRESULT WINAPI DMUSIC_CreateDirectMusicBandTrack (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
584   IDirectMusicBandTrack* track;
585         
586   track = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicBandTrack));
587   if (NULL == track) {
588     *ppobj = (LPVOID) NULL;
589     return E_OUTOFMEMORY;
590   }
591   track->UnknownVtbl = &DirectMusicBandTrack_Unknown_Vtbl;
592   track->TrackVtbl = &DirectMusicBandTrack_DirectMusicTrack_Vtbl;
593   track->PersistStreamVtbl = &DirectMusicBandTrack_PerststStream_Vtbl;
594   track->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
595   DM_STRUCT_INIT(track->pDesc);
596   track->pDesc->dwValidData |= DMUS_OBJ_CLASS;
597   memcpy (&track->pDesc->guidClass, &CLSID_DirectMusicBandTrack, sizeof (CLSID));
598   track->ref = 0; /* will be inited by QueryInterface */
599   list_init (&track->Bands);
600   
601   return IDirectMusicBandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&track->UnknownVtbl, lpcGUID, ppobj);
602 }