3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2003-2004 Raphael Junqueira
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
28 #include "dmscript_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dmscript
);
31 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
34 /*****************************************************************************
35 * IDirectMusicScriptImpl implementation
37 typedef struct IDirectMusicScriptImpl
{
38 IDirectMusicScript IDirectMusicScript_iface
;
39 const IDirectMusicObjectVtbl
*ObjectVtbl
;
40 const IPersistStreamVtbl
*PersistStreamVtbl
;
42 IDirectMusicPerformance
*pPerformance
;
43 DMUS_OBJECTDESC
*pDesc
;
44 DMUS_IO_SCRIPT_HEADER
*pHeader
;
45 DMUS_IO_VERSION
*pVersion
;
48 } IDirectMusicScriptImpl
;
50 static inline IDirectMusicScriptImpl
*impl_from_IDirectMusicScript(IDirectMusicScript
*iface
)
52 return CONTAINING_RECORD(iface
, IDirectMusicScriptImpl
, IDirectMusicScript_iface
);
55 static HRESULT WINAPI
IDirectMusicScriptImpl_QueryInterface(IDirectMusicScript
*iface
, REFIID riid
,
58 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
60 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
64 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicScript
))
66 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
67 *ret_iface
= &This
->ObjectVtbl
;
68 else if (IsEqualIID(riid
, &IID_IPersistStream
))
69 *ret_iface
= &This
->PersistStreamVtbl
;
71 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
75 IUnknown_AddRef((IUnknown
*)*ret_iface
);
79 static ULONG WINAPI
IDirectMusicScriptImpl_AddRef(IDirectMusicScript
*iface
)
81 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
82 LONG ref
= InterlockedIncrement(&This
->ref
);
84 TRACE("(%p) ref=%d\n", This
, ref
);
89 static ULONG WINAPI
IDirectMusicScriptImpl_Release(IDirectMusicScript
*iface
)
91 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
92 LONG ref
= InterlockedDecrement(&This
->ref
);
94 TRACE("(%p) ref=%d\n", This
, ref
);
97 HeapFree(GetProcessHeap(), 0, This
->pHeader
);
98 HeapFree(GetProcessHeap(), 0, This
->pVersion
);
99 HeapFree(GetProcessHeap(), 0, This
->pwzLanguage
);
100 HeapFree(GetProcessHeap(), 0, This
->pwzSource
);
101 HeapFree(GetProcessHeap(), 0, This
->pDesc
);
102 HeapFree(GetProcessHeap(), 0, This
);
103 DMSCRIPT_UnlockModule();
109 static HRESULT WINAPI
IDirectMusicScriptImpl_Init(IDirectMusicScript
*iface
,
110 IDirectMusicPerformance
*pPerformance
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
112 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
113 FIXME("(%p, %p, %p): stub\n", This
, pPerformance
, pErrorInfo
);
114 This
->pPerformance
= pPerformance
;
118 static HRESULT WINAPI
IDirectMusicScriptImpl_CallRoutine(IDirectMusicScript
*iface
,
119 WCHAR
*pwszRoutineName
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
121 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
122 FIXME("(%p, %s, %p): stub\n", This
, debugstr_w(pwszRoutineName
), pErrorInfo
);
123 /*return E_NOTIMPL;*/
128 static HRESULT WINAPI
IDirectMusicScriptImpl_SetVariableVariant(IDirectMusicScript
*iface
,
129 WCHAR
*pwszVariableName
, VARIANT varValue
, BOOL fSetRef
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
131 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
132 FIXME("(%p, %s, FIXME, %d, %p): stub\n", This
, debugstr_w(pwszVariableName
),/* varValue,*/ fSetRef
, pErrorInfo
);
136 static HRESULT WINAPI
IDirectMusicScriptImpl_GetVariableVariant(IDirectMusicScript
*iface
,
137 WCHAR
*pwszVariableName
, VARIANT
*pvarValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
139 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
140 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), pvarValue
, pErrorInfo
);
144 static HRESULT WINAPI
IDirectMusicScriptImpl_SetVariableNumber(IDirectMusicScript
*iface
,
145 WCHAR
*pwszVariableName
, LONG lValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
147 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
148 FIXME("(%p, %s, %i, %p): stub\n", This
, debugstr_w(pwszVariableName
), lValue
, pErrorInfo
);
152 static HRESULT WINAPI
IDirectMusicScriptImpl_GetVariableNumber(IDirectMusicScript
*iface
,
153 WCHAR
*pwszVariableName
, LONG
*plValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
155 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
156 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), plValue
, pErrorInfo
);
160 static HRESULT WINAPI
IDirectMusicScriptImpl_SetVariableObject(IDirectMusicScript
*iface
,
161 WCHAR
*pwszVariableName
, IUnknown
*punkValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
163 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
164 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), punkValue
, pErrorInfo
);
168 static HRESULT WINAPI
IDirectMusicScriptImpl_GetVariableObject(IDirectMusicScript
*iface
,
169 WCHAR
*pwszVariableName
, REFIID riid
, void **ppv
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
171 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
172 FIXME("(%p, %s, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), debugstr_dmguid(riid
), ppv
, pErrorInfo
);
176 static HRESULT WINAPI
IDirectMusicScriptImpl_EnumRoutine(IDirectMusicScript
*iface
, DWORD dwIndex
,
179 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
180 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
184 static HRESULT WINAPI
IDirectMusicScriptImpl_EnumVariable(IDirectMusicScript
*iface
, DWORD dwIndex
,
187 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
188 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
192 static const IDirectMusicScriptVtbl dmscript_vtbl
= {
193 IDirectMusicScriptImpl_QueryInterface
,
194 IDirectMusicScriptImpl_AddRef
,
195 IDirectMusicScriptImpl_Release
,
196 IDirectMusicScriptImpl_Init
,
197 IDirectMusicScriptImpl_CallRoutine
,
198 IDirectMusicScriptImpl_SetVariableVariant
,
199 IDirectMusicScriptImpl_GetVariableVariant
,
200 IDirectMusicScriptImpl_SetVariableNumber
,
201 IDirectMusicScriptImpl_GetVariableNumber
,
202 IDirectMusicScriptImpl_SetVariableObject
,
203 IDirectMusicScriptImpl_GetVariableObject
,
204 IDirectMusicScriptImpl_EnumRoutine
,
205 IDirectMusicScriptImpl_EnumVariable
208 /* IDirectMusicScriptImpl IDirectMusicObject part: */
209 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ppobj
) {
210 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
211 return IDirectMusicScript_QueryInterface(&This
->IDirectMusicScript_iface
, riid
, ppobj
);
214 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
) {
215 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
216 return IDirectMusicScript_AddRef (&This
->IDirectMusicScript_iface
);
219 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface
) {
220 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
221 return IDirectMusicScript_Release (&This
->IDirectMusicScript_iface
);
224 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
225 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
226 TRACE("(%p, %p)\n", This
, pDesc
);
227 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
228 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
232 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
233 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
234 TRACE("(%p, %p): setting descriptor:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC (pDesc
));
236 /* According to MSDN, we should copy only given values, not whole struct */
237 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
238 This
->pDesc
->guidObject
= pDesc
->guidObject
;
239 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
240 This
->pDesc
->guidClass
= pDesc
->guidClass
;
241 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
242 lstrcpynW (This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
243 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
244 lstrcpynW (This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
245 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
246 lstrcpynW (This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
247 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
248 This
->pDesc
->vVersion
= pDesc
->vVersion
;
249 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
250 This
->pDesc
->ftDate
= pDesc
->ftDate
;
251 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
252 This
->pDesc
->llMemLength
= pDesc
->llMemLength
;
253 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, pDesc
->llMemLength
);
255 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
256 /* according to MSDN, we copy the stream */
257 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
261 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
266 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface
, LPSTREAM pStream
, LPDMUS_OBJECTDESC pDesc
) {
267 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
268 DMUS_PRIVATE_CHUNK Chunk
;
269 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
270 LARGE_INTEGER liMove
; /* used when skipping chunks */
272 TRACE("(%p, %p, %p)\n", This
, pStream
, pDesc
);
274 /* FIXME: should this be determined from stream? */
275 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
276 pDesc
->guidClass
= CLSID_DirectMusicScript
;
278 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
279 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
280 switch (Chunk
.fccID
) {
282 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
283 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
284 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
286 if (Chunk
.fccID
== DMUS_FOURCC_SCRIPT_FORM
) {
287 TRACE_(dmfile
)(": script form\n");
289 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
290 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
291 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
292 switch (Chunk
.fccID
) {
293 case DMUS_FOURCC_GUID_CHUNK
: {
294 TRACE_(dmfile
)(": GUID chunk\n");
295 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
296 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
299 case DMUS_FOURCC_VERSION_CHUNK
: {
300 TRACE_(dmfile
)(": version chunk\n");
301 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
302 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
305 case DMUS_FOURCC_CATEGORY_CHUNK
: {
306 TRACE_(dmfile
)(": category chunk\n");
307 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
308 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
312 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
313 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
314 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
316 switch (Chunk
.fccID
) {
317 /* evil M$ UNFO list, which can (!?) contain INFO elements */
318 case DMUS_FOURCC_UNFO_LIST
: {
319 TRACE_(dmfile
)(": UNFO list\n");
321 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
322 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
323 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
324 switch (Chunk
.fccID
) {
325 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
326 (though strings seem to be valid unicode) */
327 case mmioFOURCC('I','N','A','M'):
328 case DMUS_FOURCC_UNAM_CHUNK
: {
329 TRACE_(dmfile
)(": name chunk\n");
330 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
331 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
334 case mmioFOURCC('I','A','R','T'):
335 case DMUS_FOURCC_UART_CHUNK
: {
336 TRACE_(dmfile
)(": artist chunk (ignored)\n");
337 liMove
.QuadPart
= Chunk
.dwSize
;
338 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
341 case mmioFOURCC('I','C','O','P'):
342 case DMUS_FOURCC_UCOP_CHUNK
: {
343 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
344 liMove
.QuadPart
= Chunk
.dwSize
;
345 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
348 case mmioFOURCC('I','S','B','J'):
349 case DMUS_FOURCC_USBJ_CHUNK
: {
350 TRACE_(dmfile
)(": subject chunk (ignored)\n");
351 liMove
.QuadPart
= Chunk
.dwSize
;
352 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
355 case mmioFOURCC('I','C','M','T'):
356 case DMUS_FOURCC_UCMT_CHUNK
: {
357 TRACE_(dmfile
)(": comment chunk (ignored)\n");
358 liMove
.QuadPart
= Chunk
.dwSize
;
359 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
363 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
364 liMove
.QuadPart
= Chunk
.dwSize
;
365 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
369 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
370 } while (ListCount
[0] < ListSize
[0]);
374 TRACE_(dmfile
)(": unknown (skipping)\n");
375 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
376 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
383 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
384 liMove
.QuadPart
= Chunk
.dwSize
;
385 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
389 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
390 } while (StreamCount
< StreamSize
);
392 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
393 liMove
.QuadPart
= StreamSize
;
394 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
398 TRACE_(dmfile
)(": reading finished\n");
402 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
403 liMove
.QuadPart
= Chunk
.dwSize
;
404 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
405 return DMUS_E_INVALIDFILE
;
409 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
414 static const IDirectMusicObjectVtbl DirectMusicScript_Object_Vtbl
= {
415 IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface
,
416 IDirectMusicScriptImpl_IDirectMusicObject_AddRef
,
417 IDirectMusicScriptImpl_IDirectMusicObject_Release
,
418 IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor
,
419 IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor
,
420 IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor
423 /* IDirectMusicScriptImpl IPersistStream part: */
424 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ppobj
) {
425 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
426 return IDirectMusicScript_QueryInterface(&This
->IDirectMusicScript_iface
, riid
, ppobj
);
429 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
) {
430 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
431 return IDirectMusicScript_AddRef(&This
->IDirectMusicScript_iface
);
434 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_Release (LPPERSISTSTREAM iface
) {
435 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
436 return IDirectMusicScript_Release(&This
->IDirectMusicScript_iface
);
439 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface
, CLSID
* pClassID
) {
440 TRACE("(%p, %p) method not implemented\n", iface
, pClassID
);
445 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface
) {
449 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Load (LPPERSISTSTREAM iface
, IStream
* pStm
) {
450 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
452 DMUS_PRIVATE_CHUNK Chunk
;
453 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
454 LARGE_INTEGER liMove
; /* used when skipping chunks */
455 LPDIRECTMUSICGETLOADER pGetLoader
= NULL
;
456 LPDIRECTMUSICLOADER pLoader
= NULL
;
458 FIXME("(%p, %p): Loading not implemented yet\n", This
, pStm
);
459 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
460 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
461 switch (Chunk
.fccID
) {
463 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
464 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
465 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
467 switch (Chunk
.fccID
) {
468 case DMUS_FOURCC_SCRIPT_FORM
: {
469 TRACE_(dmfile
)(": script form\n");
471 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
472 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
473 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
474 switch (Chunk
.fccID
) {
475 case DMUS_FOURCC_SCRIPT_CHUNK
: {
476 TRACE_(dmfile
)(": script header chunk\n");
477 This
->pHeader
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
478 IStream_Read (pStm
, This
->pHeader
, Chunk
.dwSize
, NULL
);
481 case DMUS_FOURCC_SCRIPTVERSION_CHUNK
: {
482 TRACE_(dmfile
)(": script version chunk\n");
483 This
->pVersion
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
484 IStream_Read (pStm
, This
->pVersion
, Chunk
.dwSize
, NULL
);
485 TRACE_(dmfile
)("version: 0x%08x.0x%08x\n", This
->pVersion
->dwVersionMS
, This
->pVersion
->dwVersionLS
);
488 case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK
: {
489 TRACE_(dmfile
)(": script language chunk\n");
490 This
->pwzLanguage
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
491 IStream_Read (pStm
, This
->pwzLanguage
, Chunk
.dwSize
, NULL
);
492 TRACE_(dmfile
)("using language: %s\n", debugstr_w(This
->pwzLanguage
));
495 case DMUS_FOURCC_SCRIPTSOURCE_CHUNK
: {
496 TRACE_(dmfile
)(": script source chunk\n");
497 This
->pwzSource
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
498 IStream_Read (pStm
, This
->pwzSource
, Chunk
.dwSize
, NULL
);
499 if (TRACE_ON(dmscript
)) {
500 int count
= WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, NULL
, 0, NULL
, NULL
);
501 LPSTR str
= HeapAlloc(GetProcessHeap (), 0, count
);
502 WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, str
, count
, NULL
, NULL
);
505 write( 2, str
, count
);
506 HeapFree(GetProcessHeap(), 0, str
);
510 case DMUS_FOURCC_GUID_CHUNK
: {
511 TRACE_(dmfile
)(": GUID chunk\n");
512 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
513 IStream_Read (pStm
, &This
->pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
516 case DMUS_FOURCC_VERSION_CHUNK
: {
517 TRACE_(dmfile
)(": version chunk\n");
518 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
519 IStream_Read (pStm
, &This
->pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
522 case DMUS_FOURCC_CATEGORY_CHUNK
: {
523 TRACE_(dmfile
)(": category chunk\n");
524 This
->pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
525 IStream_Read (pStm
, This
->pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
529 IDirectMusicObject
* pObject
= NULL
;
530 DMUS_OBJECTDESC desc
;
532 ZeroMemory (&desc
, sizeof(DMUS_OBJECTDESC
));
533 desc
.dwSize
= sizeof(DMUS_OBJECTDESC
);
534 desc
.dwValidData
= DMUS_OBJ_STREAM
| DMUS_OBJ_CLASS
;
535 desc
.guidClass
= CLSID_DirectMusicContainer
;
537 IStream_Clone (pStm
, &desc
.pStream
);
540 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
541 IStream_Seek (desc
.pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
543 IStream_QueryInterface (pStm
, &IID_IDirectMusicGetLoader
, (LPVOID
*)&pGetLoader
);
544 IDirectMusicGetLoader_GetLoader (pGetLoader
, &pLoader
);
545 IDirectMusicGetLoader_Release (pGetLoader
);
547 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader
, &desc
, &IID_IDirectMusicObject
, (LPVOID
*) &pObject
))) {
548 IDirectMusicObject_Release (pObject
);
550 ERR_(dmfile
)("Error on GetObject while trying to load Scrip SubContainer\n");
553 IDirectMusicLoader_Release (pLoader
); pLoader
= NULL
; /* release loader */
554 IStream_Release(desc
.pStream
); desc
.pStream
= NULL
; /* release cloned stream */
556 liMove
.QuadPart
= Chunk
.dwSize
;
557 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
559 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
560 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
561 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
564 switch (Chunk.fccID) {
566 TRACE_(dmfile)(": unknown (skipping)\n");
567 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
568 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
576 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
577 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
578 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
580 switch (Chunk
.fccID
) {
581 case DMUS_FOURCC_UNFO_LIST
: {
582 TRACE_(dmfile
)(": UNFO list\n");
584 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
585 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
586 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
587 switch (Chunk
.fccID
) {
588 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
589 (though strings seem to be valid unicode) */
590 case mmioFOURCC('I','N','A','M'):
591 case DMUS_FOURCC_UNAM_CHUNK
: {
592 TRACE_(dmfile
)(": name chunk\n");
593 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
594 IStream_Read (pStm
, This
->pDesc
->wszName
, Chunk
.dwSize
, NULL
);
597 case mmioFOURCC('I','A','R','T'):
598 case DMUS_FOURCC_UART_CHUNK
: {
599 TRACE_(dmfile
)(": artist chunk (ignored)\n");
600 liMove
.QuadPart
= Chunk
.dwSize
;
601 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
604 case mmioFOURCC('I','C','O','P'):
605 case DMUS_FOURCC_UCOP_CHUNK
: {
606 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
607 liMove
.QuadPart
= Chunk
.dwSize
;
608 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
611 case mmioFOURCC('I','S','B','J'):
612 case DMUS_FOURCC_USBJ_CHUNK
: {
613 TRACE_(dmfile
)(": subject chunk (ignored)\n");
614 liMove
.QuadPart
= Chunk
.dwSize
;
615 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
618 case mmioFOURCC('I','C','M','T'):
619 case DMUS_FOURCC_UCMT_CHUNK
: {
620 TRACE_(dmfile
)(": comment chunk (ignored)\n");
621 liMove
.QuadPart
= Chunk
.dwSize
;
622 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
626 TRACE_(dmfile
)(": unknown sub-chunk (irrelevant & skipping)\n");
627 liMove
.QuadPart
= Chunk
.dwSize
;
628 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
632 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
633 } while (ListCount
[0] < ListSize
[0]);
637 TRACE_(dmfile
)(": unknown (skipping)\n");
638 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
639 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
646 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
647 liMove
.QuadPart
= Chunk
.dwSize
;
648 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
652 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
653 } while (StreamCount
< StreamSize
);
657 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
658 liMove
.QuadPart
= StreamSize
;
659 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
663 TRACE_(dmfile
)(": reading finished\n");
667 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
668 liMove
.QuadPart
= Chunk
.dwSize
;
669 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
677 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
) {
681 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
) {
685 static const IPersistStreamVtbl DirectMusicScript_PersistStream_Vtbl
= {
686 IDirectMusicScriptImpl_IPersistStream_QueryInterface
,
687 IDirectMusicScriptImpl_IPersistStream_AddRef
,
688 IDirectMusicScriptImpl_IPersistStream_Release
,
689 IDirectMusicScriptImpl_IPersistStream_GetClassID
,
690 IDirectMusicScriptImpl_IPersistStream_IsDirty
,
691 IDirectMusicScriptImpl_IPersistStream_Load
,
692 IDirectMusicScriptImpl_IPersistStream_Save
,
693 IDirectMusicScriptImpl_IPersistStream_GetSizeMax
696 /* for ClassFactory */
697 HRESULT WINAPI
DMUSIC_CreateDirectMusicScriptImpl(REFIID lpcGUID
, void **ppobj
, IUnknown
*pUnkOuter
)
699 IDirectMusicScriptImpl
*obj
;
705 return CLASS_E_NOAGGREGATION
;
707 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicScriptImpl
));
709 return E_OUTOFMEMORY
;
711 obj
->IDirectMusicScript_iface
.lpVtbl
= &dmscript_vtbl
;
712 obj
->ObjectVtbl
= &DirectMusicScript_Object_Vtbl
;
713 obj
->PersistStreamVtbl
= &DirectMusicScript_PersistStream_Vtbl
;
714 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
715 DM_STRUCT_INIT(obj
->pDesc
);
716 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
717 obj
->pDesc
->guidClass
= CLSID_DirectMusicScript
;
720 DMSCRIPT_LockModule();
721 hr
= IDirectMusicScript_QueryInterface(&obj
->IDirectMusicScript_iface
, lpcGUID
, ppobj
);
722 IDirectMusicScript_Release(&obj
->IDirectMusicScript_iface
);