Started a unit test case for the updown control.
[wine] / dlls / dmstyle / style.c
1 /* IDirectMusicStyle8 Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  * Copyright (C) 2003-2004 Raphael Junqueira
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "dmstyle_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
25
26 /*****************************************************************************
27  * IDirectMusicStyleImpl implementation
28  */
29 /* IDirectMusicStyleImpl IUnknown part: */
30 HRESULT WINAPI IDirectMusicStyle8Impl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
31         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface);
32         TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
33         
34         if (IsEqualIID (riid, &IID_IUnknown)) {
35                 *ppobj = (LPVOID)&This->UnknownVtbl;
36                 IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
37                 return S_OK;    
38         } else if (IsEqualIID (riid, &IID_IDirectMusicStyle)) {
39                 *ppobj = (LPVOID)&This->StyleVtbl;
40                 IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef ((LPDIRECTMUSICSTYLE8)&This->StyleVtbl);
41                 return S_OK;
42         } else if (IsEqualIID (riid, &IID_IDirectMusicStyle8)) {
43                 *ppobj = (LPVOID)&This->StyleVtbl;
44                 IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef ((LPDIRECTMUSICSTYLE8)&This->StyleVtbl);
45                 return S_OK;
46         } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
47                 *ppobj = (LPVOID)&This->ObjectVtbl;
48                 IDirectMusicStyle8Impl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);              
49                 return S_OK;
50         } else if (IsEqualIID (riid, &IID_IPersistStream)) {
51                 *ppobj = (LPVOID)&This->PersistStreamVtbl;
52                 IDirectMusicStyle8Impl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);               
53                 return S_OK;
54         }
55         
56         WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
57         return E_NOINTERFACE;
58 }
59
60 ULONG WINAPI IDirectMusicStyle8Impl_IUnknown_AddRef (LPUNKNOWN iface) {
61         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface);
62         ULONG ref = InterlockedIncrement(&This->ref);
63
64         TRACE("(%p): AddRef from %ld\n", This, ref - 1);
65
66         DMSTYLE_LockModule();
67
68         return ref;
69 }
70
71 ULONG WINAPI IDirectMusicStyle8Impl_IUnknown_Release (LPUNKNOWN iface) {
72         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface);
73         ULONG ref = InterlockedDecrement(&This->ref);
74
75         TRACE("(%p): ReleaseRef to %ld\n", This, ref);
76
77         if (ref == 0) {
78                 HeapFree(GetProcessHeap(), 0, This);
79         }
80         
81         DMSTYLE_UnlockModule();
82         
83         return ref;
84 }
85
86 IUnknownVtbl DirectMusicStyle8_Unknown_Vtbl = {
87         IDirectMusicStyle8Impl_IUnknown_QueryInterface,
88         IDirectMusicStyle8Impl_IUnknown_AddRef,
89         IDirectMusicStyle8Impl_IUnknown_Release
90 };
91
92 /* IDirectMusicStyle8Impl IDirectMusicStyle8 part: */
93 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_QueryInterface (LPDIRECTMUSICSTYLE8 iface, REFIID riid, LPVOID *ppobj) {
94         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
95         return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
96 }
97
98 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef (LPDIRECTMUSICSTYLE8 iface) {
99         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
100         return IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
101 }
102
103 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_Release (LPDIRECTMUSICSTYLE8 iface) {
104         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
105         return IDirectMusicStyle8Impl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
106 }
107
108 /* IDirectMusicStyle8Impl IDirectMusicStyle(8) part: */
109 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetBand (LPDIRECTMUSICSTYLE8 iface, WCHAR* pwszName, IDirectMusicBand** ppBand) {
110         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
111         FIXME("(%p, %p, %p): stub\n", This, pwszName, ppBand);
112         return S_OK;
113 }
114
115 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumBand (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, WCHAR* pwszName) {
116         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
117         FIXME("(%p, %ld, %p): stub\n", This, dwIndex, pwszName);
118         return S_OK;
119 }
120
121 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultBand (LPDIRECTMUSICSTYLE8 iface, IDirectMusicBand** ppBand) {
122         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
123         FIXME("(%p, %p): stub\n", This, ppBand);
124         return S_OK;
125 }
126
127 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumMotif (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, WCHAR* pwszName) {
128         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
129         FIXME("(%p, %ld, %p): stub\n", This, dwIndex, pwszName);
130         return S_OK;
131 }
132
133 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetMotif (LPDIRECTMUSICSTYLE8 iface, WCHAR* pwszName, IDirectMusicSegment** ppSegment) {
134         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
135         FIXME("(%p, %p, %p): stub\n", This, pwszName, ppSegment);
136         return S_OK;
137 }
138
139 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultChordMap (LPDIRECTMUSICSTYLE8 iface, IDirectMusicChordMap** ppChordMap) {
140         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
141         FIXME("(%p, %p): stub\n", This, ppChordMap);
142         return S_OK;
143 }
144
145 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumChordMap (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, WCHAR* pwszName) {
146         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
147         FIXME("(%p, %ld, %p): stub\n", This, dwIndex, pwszName);
148         return S_OK;
149 }
150
151 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetChordMap (LPDIRECTMUSICSTYLE8 iface, WCHAR* pwszName, IDirectMusicChordMap** ppChordMap) {
152         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
153         FIXME("(%p, %p, %p): stub\n", This, pwszName, ppChordMap);
154         return S_OK;
155 }
156
157 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTimeSignature (LPDIRECTMUSICSTYLE8 iface, DMUS_TIMESIGNATURE* pTimeSig) {
158         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
159         FIXME("(%p, %p): stub\n", This, pTimeSig);
160         return S_OK;
161 }
162
163 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetEmbellishmentLength (LPDIRECTMUSICSTYLE8 iface, DWORD dwType, DWORD dwLevel, DWORD* pdwMin, DWORD* pdwMax) {
164         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
165         FIXME("(%p, %ld, %ld, %p, %p): stub\n", This, dwType, dwLevel, pdwMin, pdwMax);
166         return S_OK;
167 }
168
169 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTempo (LPDIRECTMUSICSTYLE8 iface, double* pTempo) {
170         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
171         FIXME("(%p, %p): stub\n", This, pTempo);
172         return S_OK;
173 }
174
175 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumPattern (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, DWORD dwPatternType, WCHAR* pwszName) {
176         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
177         FIXME("(%p, %ld, %ld, %p): stub\n", This, dwIndex, dwPatternType, pwszName);
178         return S_OK;
179 }
180
181 IDirectMusicStyle8Vtbl DirectMusicStyle8_Style_Vtbl = {
182         IDirectMusicStyle8Impl_IDirectMusicStyle8_QueryInterface,
183         IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef,
184         IDirectMusicStyle8Impl_IDirectMusicStyle8_Release,
185         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetBand,
186         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumBand,
187         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultBand,
188         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumMotif,
189         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetMotif,
190         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultChordMap,
191         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumChordMap,
192         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetChordMap,
193         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTimeSignature,
194         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetEmbellishmentLength,
195         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTempo,
196         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumPattern
197 };
198
199 /* IDirectMusicStyle8Impl IDirectMusicObject part: */
200 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
201         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
202         return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
203 }
204
205 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
206         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
207         return IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
208 }
209
210 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
211         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
212         return IDirectMusicStyle8Impl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
213 }
214
215 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
216         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
217         TRACE("(%p, %p)\n", This, pDesc);
218         /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
219         memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
220         return S_OK;
221 }
222
223 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
224         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
225         TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
226         
227         /* According to MSDN, we should copy only given values, not whole struct */     
228         if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
229                 memcpy (&This->pDesc->guidObject, &pDesc->guidObject, sizeof (pDesc->guidObject));
230         if (pDesc->dwValidData & DMUS_OBJ_CLASS)
231                 memcpy (&This->pDesc->guidClass, &pDesc->guidClass, sizeof (pDesc->guidClass));         
232         if (pDesc->dwValidData & DMUS_OBJ_NAME)
233                 strncpyW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
234         if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
235                 strncpyW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);             
236         if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
237                 strncpyW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);             
238         if (pDesc->dwValidData & DMUS_OBJ_VERSION)
239                 memcpy (&This->pDesc->vVersion, &pDesc->vVersion, sizeof (pDesc->vVersion));                            
240         if (pDesc->dwValidData & DMUS_OBJ_DATE)
241                 memcpy (&This->pDesc->ftDate, &pDesc->ftDate, sizeof (pDesc->ftDate));                          
242         if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
243                 memcpy (&This->pDesc->llMemLength, &pDesc->llMemLength, sizeof (pDesc->llMemLength));                           
244                 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, sizeof (pDesc->pbMemData));
245         }
246         if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
247                 /* according to MSDN, we copy the stream */
248                 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);  
249         }
250         
251         /* add new flags */
252         This->pDesc->dwValidData |= pDesc->dwValidData;
253
254         return S_OK;
255 }
256
257 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
258         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
259         DMUS_PRIVATE_CHUNK Chunk;
260         DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
261         LARGE_INTEGER liMove; /* used when skipping chunks */
262
263         TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
264         
265         /* FIXME: should this be determined from stream? */
266         pDesc->dwValidData |= DMUS_OBJ_CLASS;
267         memcpy (&pDesc->guidClass, &CLSID_DirectMusicStyle, sizeof(CLSID));
268         
269         IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
270         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
271         switch (Chunk.fccID) {  
272                 case FOURCC_RIFF: {
273                         IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);                             
274                         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
275                         StreamSize = Chunk.dwSize - sizeof(FOURCC);
276                         StreamCount = 0;
277                         if (Chunk.fccID == DMUS_FOURCC_STYLE_FORM) {
278                                 TRACE_(dmfile)(": style form\n");
279                                 do {
280                                         IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
281                                         StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
282                                         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
283                                         switch (Chunk.fccID) {
284                                                 case DMUS_FOURCC_GUID_CHUNK: {
285                                                         TRACE_(dmfile)(": GUID chunk\n");
286                                                         pDesc->dwValidData |= DMUS_OBJ_OBJECT;
287                                                         IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
288                                                         break;
289                                                 }
290                                                 case DMUS_FOURCC_VERSION_CHUNK: {
291                                                         TRACE_(dmfile)(": version chunk\n");
292                                                         pDesc->dwValidData |= DMUS_OBJ_VERSION;
293                                                         IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
294                                                         break;
295                                                 }
296                                                 case DMUS_FOURCC_CATEGORY_CHUNK: {
297                                                         TRACE_(dmfile)(": category chunk\n");
298                                                         pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
299                                                         IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
300                                                         break;
301                                                 }
302                                                 case FOURCC_LIST: {
303                                                         IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);                             
304                                                         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
305                                                         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
306                                                         ListCount[0] = 0;
307                                                         switch (Chunk.fccID) {
308                                                                 /* evil M$ UNFO list, which can (!?) contain INFO elements */
309                                                                 case DMUS_FOURCC_UNFO_LIST: {
310                                                                         TRACE_(dmfile)(": UNFO list\n");
311                                                                         do {
312                                                                                 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
313                                                                                 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
314                                                                                 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
315                                                                                 switch (Chunk.fccID) {
316                                                                                         /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
317                                              (though strings seem to be valid unicode) */
318                                                                                         case mmioFOURCC('I','N','A','M'):
319                                                                                         case DMUS_FOURCC_UNAM_CHUNK: {
320                                                                                                 TRACE_(dmfile)(": name chunk\n");
321                                                                                                 pDesc->dwValidData |= DMUS_OBJ_NAME;
322                                                                                                 IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
323                                                                                                 break;
324                                                                                         }
325                                                                                         case mmioFOURCC('I','A','R','T'):
326                                                                                         case DMUS_FOURCC_UART_CHUNK: {
327                                                                                                 TRACE_(dmfile)(": artist chunk (ignored)\n");
328                                                                                                 liMove.QuadPart = Chunk.dwSize;
329                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
330                                                                                                 break;
331                                                                                         }
332                                                                                         case mmioFOURCC('I','C','O','P'):
333                                                                                         case DMUS_FOURCC_UCOP_CHUNK: {
334                                                                                                 TRACE_(dmfile)(": copyright chunk (ignored)\n");
335                                                                                                 liMove.QuadPart = Chunk.dwSize;
336                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
337                                                                                                 break;
338                                                                                         }
339                                                                                         case mmioFOURCC('I','S','B','J'):
340                                                                                         case DMUS_FOURCC_USBJ_CHUNK: {
341                                                                                                 TRACE_(dmfile)(": subject chunk (ignored)\n");
342                                                                                                 liMove.QuadPart = Chunk.dwSize;
343                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
344                                                                                                 break;
345                                                                                         }
346                                                                                         case mmioFOURCC('I','C','M','T'):
347                                                                                         case DMUS_FOURCC_UCMT_CHUNK: {
348                                                                                                 TRACE_(dmfile)(": comment chunk (ignored)\n");
349                                                                                                 liMove.QuadPart = Chunk.dwSize;
350                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
351                                                                                                 break;
352                                                                                         }
353                                                                                         default: {
354                                                                                                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
355                                                                                                 liMove.QuadPart = Chunk.dwSize;
356                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
357                                                                                                 break;                                          
358                                                                                         }
359                                                                                 }
360                                                                                 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
361                                                                         } while (ListCount[0] < ListSize[0]);
362                                                                         break;
363                                                                 }
364                                                                 default: {
365                                                                         TRACE_(dmfile)(": unknown (skipping)\n");
366                                                                         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
367                                                                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
368                                                                         break;                                          
369                                                                 }
370                                                         }
371                                                         break;
372                                                 }       
373                                                 default: {
374                                                         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
375                                                         liMove.QuadPart = Chunk.dwSize;
376                                                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
377                                                         break;                                          
378                                                 }
379                                         }
380                                         TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
381                                 } while (StreamCount < StreamSize);
382                         } else {
383                                 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
384                                 liMove.QuadPart = StreamSize;
385                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
386                                 return E_FAIL;
387                         }
388                 
389                         TRACE_(dmfile)(": reading finished\n");
390                         break;
391                 }
392                 default: {
393                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
394                         liMove.QuadPart = Chunk.dwSize;
395                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
396                         return DMUS_E_INVALIDFILE;
397                 }
398         }       
399         
400         TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
401         
402         return S_OK;
403 }
404
405 IDirectMusicObjectVtbl DirectMusicStyle8_Object_Vtbl = {
406   IDirectMusicStyle8Impl_IDirectMusicObject_QueryInterface,
407   IDirectMusicStyle8Impl_IDirectMusicObject_AddRef,
408   IDirectMusicStyle8Impl_IDirectMusicObject_Release,
409   IDirectMusicStyle8Impl_IDirectMusicObject_GetDescriptor,
410   IDirectMusicStyle8Impl_IDirectMusicObject_SetDescriptor,
411   IDirectMusicStyle8Impl_IDirectMusicObject_ParseDescriptor
412 };
413
414 /* IDirectMusicStyle8Impl IPersistStream part: */
415 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
416   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
417   return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
418 }
419
420 ULONG WINAPI IDirectMusicStyle8Impl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
421   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
422   return IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
423 }
424
425 ULONG WINAPI IDirectMusicStyle8Impl_IPersistStream_Release (LPPERSISTSTREAM iface) {
426   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
427   return IDirectMusicStyle8Impl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
428 }
429
430 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
431   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
432   TRACE("(%p, %p)\n", This, pClassID);
433   memcpy(pClassID, &CLSID_DirectMusicStyle, sizeof(CLSID));
434   return S_OK;
435 }
436
437 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
438   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
439   FIXME("(%p): stub, always S_FALSE\n", This);
440   return S_FALSE;
441 }
442
443 static HRESULT IDirectMusicStyle8Impl_IPersistStream_LoadBand (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicBand** ppBand) {
444
445   HRESULT hr = E_FAIL;
446   IPersistStream* pPersistStream = NULL;
447   
448   hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand);
449   if (FAILED(hr)) {
450     ERR(": could not create object\n");
451     return hr;
452   }
453   /* acquire PersistStream interface */
454   hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream);
455   if (FAILED(hr)) {
456     ERR(": could not acquire IPersistStream\n");
457     return hr;
458   }
459   /* load */
460   hr = IPersistStream_Load (pPersistStream, pClonedStream);
461   if (FAILED(hr)) {
462     ERR(": failed to load object\n");
463     return hr;
464   }
465   
466   /* release all loading-related stuff */
467   IPersistStream_Release (pPersistStream);
468
469   return S_OK;
470 }
471
472 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm, LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif) {
473   /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/
474   HRESULT hr = E_FAIL;
475   DMUS_PRIVATE_CHUNK Chunk;
476   DWORD ListSize[3], ListCount[3];
477   LARGE_INTEGER liMove; /* used when skipping chunks */
478
479   LPDMUS_PRIVATE_STYLE_PARTREF_ITEM pNewItem = NULL;
480
481
482   if (pChunk->fccID != DMUS_FOURCC_PARTREF_LIST) {
483     ERR_(dmfile)(": %s chunk should be a PARTREF list\n", debugstr_fourcc (pChunk->fccID));
484     return E_FAIL;
485   }  
486
487   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
488   ListCount[0] = 0;
489
490   do {
491     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
492     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
493     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
494     switch (Chunk.fccID) {
495     case DMUS_FOURCC_PARTREF_CHUNK: {
496       TRACE_(dmfile)(": PartRef chunk\n");
497       pNewItem = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_PARTREF_ITEM));
498       if (NULL == pNewItem) {
499         ERR(": no more memory\n");
500         return  E_OUTOFMEMORY;
501       }
502       hr = IStream_Read (pStm, &pNewItem->part_ref, sizeof(DMUS_IO_PARTREF), NULL);
503       /*TRACE_(dmfile)(" - sizeof %lu\n",  sizeof(DMUS_IO_PARTREF));*/
504       list_add_tail (&pNewMotif->Items, &pNewItem->entry);      
505       DM_STRUCT_INIT(&pNewItem->desc);
506       break;
507     }    
508     case FOURCC_LIST: {
509       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
510       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
511       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
512       ListCount[1] = 0;
513       switch (Chunk.fccID) {  
514       case DMUS_FOURCC_UNFO_LIST: { 
515         TRACE_(dmfile)(": UNFO list\n");
516         do {
517           IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
518           ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
519           TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
520           
521           hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &pNewItem->desc);
522           if (FAILED(hr)) return hr;
523           
524           if (hr == S_FALSE) {
525             switch (Chunk.fccID) {
526             default: {
527               TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
528               liMove.QuadPart = Chunk.dwSize;
529               IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
530               break;                            
531             }
532             }
533           }  
534           TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
535         } while (ListCount[1] < ListSize[1]);
536         break;
537       }
538       default: {
539         TRACE_(dmfile)(": unknown chunk (skipping)\n");
540         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
541         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
542         break;                                          
543       }
544       }
545       break;
546     }
547     default: {
548       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
549       liMove.QuadPart = Chunk.dwSize;
550       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
551       break;                                            
552     }
553     }
554     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
555   } while (ListCount[0] < ListSize[0]);
556
557   return S_OK;
558 }
559
560 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
561
562   /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/
563   HRESULT hr = E_FAIL;
564   DMUS_PRIVATE_CHUNK Chunk;
565   DWORD ListSize[3], ListCount[3];
566   LARGE_INTEGER liMove; /* used when skipping chunks */
567
568   DMUS_OBJECTDESC desc;
569   DWORD dwSize = 0;
570   DWORD cnt = 0;
571
572   if (pChunk->fccID != DMUS_FOURCC_PART_LIST) {
573     ERR_(dmfile)(": %s chunk should be a PART list\n", debugstr_fourcc (pChunk->fccID));
574     return E_FAIL;
575   }  
576
577   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
578   ListCount[0] = 0;
579
580   do {
581     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
582     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
583     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
584     switch (Chunk.fccID) {
585     case DMUS_FOURCC_PART_CHUNK: {
586       TRACE_(dmfile)(": Part chunk (skipping for now) (sizeof %u)\n", sizeof(DMUS_IO_STYLEPART));
587       liMove.QuadPart = Chunk.dwSize;
588       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
589       break;
590     }
591     case DMUS_FOURCC_NOTE_CHUNK: { 
592       TRACE_(dmfile)(": Note chunk (skipping for now) (sizeof %u)\n", sizeof(DMUS_IO_STYLENOTE));
593       IStream_Read (pStm, &dwSize, sizeof(DWORD), NULL);
594       cnt = (Chunk.dwSize - sizeof(DWORD));
595       TRACE_(dmfile)(" - dwSize: %lu\n", dwSize);
596       TRACE_(dmfile)(" - cnt: %lu (%lu / %lu)\n", cnt / dwSize, (Chunk.dwSize - sizeof(DWORD)), dwSize);
597       if (cnt % dwSize != 0) {
598         ERR("Invalid Array Size");
599         return E_FAIL;
600       }
601       cnt /= dwSize;
602       /** skip for now */
603       liMove.QuadPart = cnt * dwSize;
604       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
605       break;
606     }
607     case DMUS_FOURCC_CURVE_CHUNK: { 
608       TRACE_(dmfile)(": Curve chunk (skipping for now) (sizeof %u)\n", sizeof(DMUS_IO_STYLECURVE));
609       IStream_Read (pStm, &dwSize, sizeof(DWORD), NULL);
610       cnt = (Chunk.dwSize - sizeof(DWORD));
611       TRACE_(dmfile)(" - dwSize: %lu\n", dwSize);
612       TRACE_(dmfile)(" - cnt: %lu (%lu / %lu)\n", cnt / dwSize, (Chunk.dwSize - sizeof(DWORD)), dwSize);
613       if (cnt % dwSize != 0) {
614         ERR("Invalid Array Size");
615         return E_FAIL;
616       }
617       cnt /= dwSize;
618       /** skip for now */
619       liMove.QuadPart = cnt * dwSize;
620       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
621       break;
622     }
623     case DMUS_FOURCC_MARKER_CHUNK: { 
624       TRACE_(dmfile)(": Marker chunk (skipping for now)\n");
625       liMove.QuadPart = Chunk.dwSize;
626       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
627       break;
628     }
629     case DMUS_FOURCC_RESOLUTION_CHUNK: { 
630       TRACE_(dmfile)(": Resolution chunk (skipping for now)\n");
631       liMove.QuadPart = Chunk.dwSize;
632       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
633       break;
634     }
635     case DMUS_FOURCC_ANTICIPATION_CHUNK: { 
636       TRACE_(dmfile)(": Anticipation chunk (skipping for now)\n");
637       liMove.QuadPart = Chunk.dwSize;
638       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
639       break;
640     }
641     case FOURCC_LIST: {
642       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
643       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
644       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
645       ListCount[1] = 0;
646       switch (Chunk.fccID) { 
647       case DMUS_FOURCC_UNFO_LIST: { 
648         TRACE_(dmfile)(": UNFO list\n");
649         do {
650           IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
651           ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
652           TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
653           
654           hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &desc);
655           if (FAILED(hr)) return hr;
656           
657           if (hr == S_FALSE) {
658             switch (Chunk.fccID) {
659             default: {
660               TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
661               liMove.QuadPart = Chunk.dwSize;
662               IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
663               break;                            
664             }
665             }
666           }  
667           TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
668         } while (ListCount[1] < ListSize[1]);
669         break;
670       }
671       default: {
672         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
673         liMove.QuadPart = Chunk.dwSize;
674         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
675         break;                                          
676       }
677       }
678     break;
679     }
680     default: {
681       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
682       liMove.QuadPart = Chunk.dwSize;
683       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
684       break;                                            
685     }
686     }
687     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
688   } while (ListCount[0] < ListSize[0]);
689
690   return S_OK;
691 }
692
693 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
694
695   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
696   HRESULT hr = E_FAIL;
697   DMUS_PRIVATE_CHUNK Chunk;
698   DWORD ListSize[3], ListCount[3];
699   LARGE_INTEGER liMove; /* used when skipping chunks */
700
701   DMUS_OBJECTDESC desc;
702   IDirectMusicBand* pBand = NULL;
703   LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif = NULL;
704
705   DM_STRUCT_INIT(&desc);
706
707   if (pChunk->fccID != DMUS_FOURCC_PATTERN_LIST) {
708     ERR_(dmfile)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk->fccID));
709     return E_FAIL;
710   }  
711
712   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
713   ListCount[0] = 0;
714
715   do {
716     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
717     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
718     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
719     switch (Chunk.fccID) {
720     case DMUS_FOURCC_PATTERN_CHUNK: {
721       TRACE_(dmfile)(": Pattern chunk\n");
722       /** alloc new motif entry */
723       pNewMotif = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_MOTIF));
724       list_add_tail (&This->Motifs, &pNewMotif->entry);
725       if (NULL == pNewMotif) {
726         ERR(": no more memory\n");
727         return  E_OUTOFMEMORY;
728       }
729
730       IStream_Read (pStm, &pNewMotif->pattern, Chunk.dwSize, NULL);
731       /** TODO trace pattern */
732
733       /** reset all datas, as a new pattern begin */
734       DM_STRUCT_INIT(&pNewMotif->desc);
735       list_init (&pNewMotif->Items);
736       break;
737     }
738     case DMUS_FOURCC_RHYTHM_CHUNK: { 
739       TRACE_(dmfile)(": Rythm chunk\n");
740       IStream_Read (pStm, &pNewMotif->dwRythm, sizeof(DWORD), NULL);
741       TRACE_(dmfile)(" - dwRythm: %lu\n", pNewMotif->dwRythm);
742       /** TODO understand why some Chunks have size > 4 */
743       liMove.QuadPart = Chunk.dwSize - sizeof(DWORD);
744       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
745       break;
746     }
747     case DMUS_FOURCC_MOTIFSETTINGS_CHUNK: {
748       TRACE_(dmfile)(": MotifSettigns chunk (skipping for now)\n");
749       IStream_Read (pStm, &pNewMotif->settings, Chunk.dwSize, NULL);
750       /** TODO trace settings */
751       break;
752     }
753     case FOURCC_RIFF: {
754       /**
755        * sould be embededs Bands into pattern
756        */
757       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
758       TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
759       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
760       ListCount[1] = 0;
761       switch (Chunk.fccID) {
762       case DMUS_FOURCC_BAND_FORM: { 
763         LPSTREAM pClonedStream = NULL;
764         
765         TRACE_(dmfile)(": BAND RIFF\n");
766         
767         IStream_Clone (pStm, &pClonedStream);
768         
769         liMove.QuadPart = 0;
770         liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
771         IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
772         
773         hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand);
774         if (FAILED(hr)) {
775           ERR(": could not load track\n");
776           return hr;
777         }
778         IStream_Release (pClonedStream);
779         
780         pNewMotif->pBand = pBand;
781         IDirectMusicBand_AddRef(pBand);
782
783         IDirectMusicTrack_Release(pBand); pBand = NULL;  /* now we can release at as it inserted */
784         
785         /** now safe move the cursor */
786         liMove.QuadPart = ListSize[1];
787         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
788         
789         break;
790       }
791       default: {
792         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
793         liMove.QuadPart = ListSize[1];
794         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
795         break;
796       }
797       }
798       break;
799     }
800     case FOURCC_LIST: {
801       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
802       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
803       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
804       ListCount[1] = 0;
805       switch (Chunk.fccID) {
806       case DMUS_FOURCC_UNFO_LIST: { 
807         TRACE_(dmfile)(": UNFO list\n");
808         do {
809           IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
810           ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
811           TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
812           
813           hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &pNewMotif->desc);
814           if (FAILED(hr)) return hr;
815           
816           if (hr == S_FALSE) {
817             switch (Chunk.fccID) {
818             default: {
819               TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
820               liMove.QuadPart = Chunk.dwSize;
821               IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
822               break;                            
823             }
824             }
825           }  
826           TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
827         } while (ListCount[1] < ListSize[1]);
828         break;
829       }
830       case DMUS_FOURCC_PARTREF_LIST: {
831         TRACE_(dmfile)(": PartRef list\n");
832         hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (iface, &Chunk, pStm, pNewMotif);
833         if (FAILED(hr)) return hr;
834         break;
835       }
836       default: {
837         TRACE_(dmfile)(": unknown (skipping)\n");
838         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
839         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
840         break;                                          
841       }
842       }
843       break;    
844     }
845     default: {
846       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
847       liMove.QuadPart = Chunk.dwSize;
848       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
849       break;                                            
850     }
851     }
852     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
853   } while (ListCount[0] < ListSize[0]);
854
855   return S_OK;
856 }
857
858 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
859   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
860
861   HRESULT hr = E_FAIL;
862   DMUS_PRIVATE_CHUNK Chunk;
863   DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
864   LARGE_INTEGER liMove; /* used when skipping chunks */
865
866   IDirectMusicBand* pBand = NULL;
867
868   if (pChunk->fccID != DMUS_FOURCC_STYLE_FORM) {
869     ERR_(dmfile)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk->fccID));
870     return E_FAIL;
871   }  
872
873   StreamSize = pChunk->dwSize - sizeof(FOURCC);
874   StreamCount = 0;
875
876   do {
877     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
878     StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
879     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
880     
881     hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc);
882     if (FAILED(hr)) return hr;
883
884     if (hr == S_FALSE) {
885       switch (Chunk.fccID) {
886       case DMUS_FOURCC_STYLE_CHUNK: {
887         TRACE_(dmfile)(": Style chunk\n");
888         IStream_Read (pStm, &This->style, sizeof(DMUS_IO_STYLE), NULL);
889         /** TODO dump DMUS_IO_TIMESIG style.timeSig */
890         TRACE_(dmfile)(" - dblTempo: %g\n", This->style.dblTempo);
891         break;
892       }   
893       case FOURCC_RIFF: {
894         /**
895          * sould be embededs Bands into style
896          */
897         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
898         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
899         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
900         ListCount[0] = 0;
901         switch (Chunk.fccID) {
902         case DMUS_FOURCC_BAND_FORM: { 
903           LPSTREAM pClonedStream = NULL;
904           LPDMUS_PRIVATE_STYLE_BAND pNewBand;
905
906           TRACE_(dmfile)(": BAND RIFF\n");
907           
908           IStream_Clone (pStm, &pClonedStream);
909             
910           liMove.QuadPart = 0;
911           liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
912           IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
913           
914           hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand);
915           if (FAILED(hr)) {
916             ERR(": could not load track\n");
917             return hr;
918           }
919           IStream_Release (pClonedStream);
920           
921           pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_BAND));
922           if (NULL == pNewBand) {
923             ERR(": no more memory\n");
924             return  E_OUTOFMEMORY;
925           }
926           pNewBand->pBand = pBand;
927           IDirectMusicBand_AddRef(pBand);
928           list_add_tail (&This->Bands, &pNewBand->entry);
929
930           IDirectMusicTrack_Release(pBand); pBand = NULL;  /* now we can release at as it inserted */
931         
932           /** now safe move the cursor */
933           liMove.QuadPart = ListSize[0];
934           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
935           
936           break;
937         }
938         default: {
939           TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
940           liMove.QuadPart = ListSize[0];
941           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
942           break;
943         }
944         }
945         break;
946       }
947       case FOURCC_LIST: {
948         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
949         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
950         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
951         ListCount[0] = 0;
952         switch (Chunk.fccID) {
953         case DMUS_FOURCC_UNFO_LIST: { 
954           TRACE_(dmfile)(": UNFO list\n");
955           do {
956             IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
957             ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
958             TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
959             
960             hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc);
961             if (FAILED(hr)) return hr;
962             
963             if (hr == S_FALSE) {
964               switch (Chunk.fccID) {
965               default: {
966                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
967                 liMove.QuadPart = Chunk.dwSize;
968                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
969                 break;                          
970               }
971               }
972             }  
973             TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
974           } while (ListCount[0] < ListSize[0]);
975           break;
976         }
977         case DMUS_FOURCC_PART_LIST: {
978           TRACE_(dmfile)(": PART list\n");
979           hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartList (iface, &Chunk, pStm);
980           if (FAILED(hr)) return hr;
981           break;
982         }
983         case  DMUS_FOURCC_PATTERN_LIST: {
984           TRACE_(dmfile)(": PATTERN list\n");
985           hr = IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (iface, &Chunk, pStm);
986           if (FAILED(hr)) return hr;
987           break;
988         }
989         default: {
990           TRACE_(dmfile)(": unknown (skipping)\n");
991           liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
992           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
993           break;                                                
994         }
995         }
996         break;
997       }
998       default: {
999         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
1000         liMove.QuadPart = Chunk.dwSize;
1001         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1002         break;                                          
1003       }
1004       }
1005     }
1006     TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
1007   } while (StreamCount < StreamSize);  
1008
1009   return S_OK;
1010 }
1011
1012 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
1013   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
1014   
1015   DMUS_PRIVATE_CHUNK Chunk;
1016   LARGE_INTEGER liMove; /* used when skipping chunks */
1017   HRESULT hr;
1018
1019   FIXME("(%p, %p): Loading\n", This, pStm);
1020
1021   IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
1022   TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
1023   switch (Chunk.fccID) {
1024   case FOURCC_RIFF: {
1025     IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
1026     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
1027     switch (Chunk.fccID) {
1028     case DMUS_FOURCC_STYLE_FORM: {
1029       TRACE_(dmfile)(": Style form\n");
1030       hr = IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (iface, &Chunk, pStm);
1031       if (FAILED(hr)) return hr;
1032       break;
1033     }
1034     default: {
1035       TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
1036       liMove.QuadPart = Chunk.dwSize;
1037       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
1038       return E_FAIL;
1039     }
1040     }
1041     TRACE_(dmfile)(": reading finished\n");
1042     break;
1043   }
1044   default: {
1045     TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
1046     liMove.QuadPart = Chunk.dwSize;
1047     IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
1048     return E_FAIL;
1049   }
1050   }
1051   
1052   return S_OK;
1053 }
1054
1055 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
1056   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
1057   FIXME("(%p): Saving not implemented yet\n", This);
1058   return E_NOTIMPL;
1059 }
1060
1061 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
1062   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
1063   FIXME("(%p, %p): stub\n", This, pcbSize);
1064   return E_NOTIMPL;
1065
1066 }
1067
1068 IPersistStreamVtbl DirectMusicStyle8_PersistStream_Vtbl = {
1069   IDirectMusicStyle8Impl_IPersistStream_QueryInterface,
1070   IDirectMusicStyle8Impl_IPersistStream_AddRef,
1071   IDirectMusicStyle8Impl_IPersistStream_Release,
1072   IDirectMusicStyle8Impl_IPersistStream_GetClassID,
1073   IDirectMusicStyle8Impl_IPersistStream_IsDirty,
1074   IDirectMusicStyle8Impl_IPersistStream_Load,
1075   IDirectMusicStyle8Impl_IPersistStream_Save,
1076   IDirectMusicStyle8Impl_IPersistStream_GetSizeMax
1077 };
1078
1079 /* for ClassFactory */
1080 HRESULT WINAPI DMUSIC_CreateDirectMusicStyleImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
1081   IDirectMusicStyle8Impl* obj;
1082         
1083   obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicStyle8Impl));
1084   if (NULL == obj) {
1085     *ppobj = NULL;
1086     return E_OUTOFMEMORY;
1087   }
1088   obj->UnknownVtbl = &DirectMusicStyle8_Unknown_Vtbl;
1089   obj->StyleVtbl = &DirectMusicStyle8_Style_Vtbl;
1090   obj->ObjectVtbl = &DirectMusicStyle8_Object_Vtbl;
1091   obj->PersistStreamVtbl = &DirectMusicStyle8_PersistStream_Vtbl;
1092   obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
1093   DM_STRUCT_INIT(obj->pDesc);
1094   obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
1095   memcpy (&obj->pDesc->guidClass, &CLSID_DirectMusicStyle, sizeof (CLSID));
1096   obj->ref = 0; /* will be inited by QueryInterface */
1097   list_init (&obj->Bands);
1098   list_init (&obj->Motifs);
1099
1100   return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);
1101 }