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 static inline IDirectMusicScriptImpl
*impl_from_IDirectMusicScript(IDirectMusicScript
*iface
)
39 return CONTAINING_RECORD(iface
, IDirectMusicScriptImpl
, IDirectMusicScript_iface
);
42 static HRESULT WINAPI
IDirectMusicScriptImpl_QueryInterface(IDirectMusicScript
*iface
, REFIID riid
,
45 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
47 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
51 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicScript
))
53 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
54 *ret_iface
= &This
->ObjectVtbl
;
55 else if (IsEqualIID(riid
, &IID_IPersistStream
))
56 *ret_iface
= &This
->PersistStreamVtbl
;
58 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
62 IUnknown_AddRef((IUnknown
*)*ret_iface
);
66 static ULONG WINAPI
IDirectMusicScriptImpl_AddRef(IDirectMusicScript
*iface
)
68 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
69 LONG ref
= InterlockedIncrement(&This
->ref
);
71 TRACE("(%p) ref=%d\n", This
, ref
);
76 static ULONG WINAPI
IDirectMusicScriptImpl_Release(IDirectMusicScript
*iface
)
78 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
79 LONG ref
= InterlockedDecrement(&This
->ref
);
81 TRACE("(%p) ref=%d\n", This
, ref
);
84 HeapFree(GetProcessHeap(), 0, This
->pHeader
);
85 HeapFree(GetProcessHeap(), 0, This
->pVersion
);
86 HeapFree(GetProcessHeap(), 0, This
->pwzLanguage
);
87 HeapFree(GetProcessHeap(), 0, This
->pwzSource
);
88 HeapFree(GetProcessHeap(), 0, This
->pDesc
);
89 HeapFree(GetProcessHeap(), 0, This
);
90 DMSCRIPT_UnlockModule();
96 static HRESULT WINAPI
IDirectMusicScriptImpl_Init(IDirectMusicScript
*iface
,
97 IDirectMusicPerformance
*pPerformance
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
99 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
100 FIXME("(%p, %p, %p): stub\n", This
, pPerformance
, pErrorInfo
);
101 This
->pPerformance
= pPerformance
;
105 static HRESULT WINAPI
IDirectMusicScriptImpl_CallRoutine(IDirectMusicScript
*iface
,
106 WCHAR
*pwszRoutineName
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
108 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
109 FIXME("(%p, %s, %p): stub\n", This
, debugstr_w(pwszRoutineName
), pErrorInfo
);
110 /*return E_NOTIMPL;*/
115 static HRESULT WINAPI
IDirectMusicScriptImpl_SetVariableVariant(IDirectMusicScript
*iface
,
116 WCHAR
*pwszVariableName
, VARIANT varValue
, BOOL fSetRef
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
118 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
119 FIXME("(%p, %s, FIXME, %d, %p): stub\n", This
, debugstr_w(pwszVariableName
),/* varValue,*/ fSetRef
, pErrorInfo
);
123 static HRESULT WINAPI
IDirectMusicScriptImpl_GetVariableVariant(IDirectMusicScript
*iface
,
124 WCHAR
*pwszVariableName
, VARIANT
*pvarValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
126 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
127 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), pvarValue
, pErrorInfo
);
131 static HRESULT WINAPI
IDirectMusicScriptImpl_SetVariableNumber(IDirectMusicScript
*iface
,
132 WCHAR
*pwszVariableName
, LONG lValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
134 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
135 FIXME("(%p, %s, %i, %p): stub\n", This
, debugstr_w(pwszVariableName
), lValue
, pErrorInfo
);
139 static HRESULT WINAPI
IDirectMusicScriptImpl_GetVariableNumber(IDirectMusicScript
*iface
,
140 WCHAR
*pwszVariableName
, LONG
*plValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
142 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
143 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), plValue
, pErrorInfo
);
147 static HRESULT WINAPI
IDirectMusicScriptImpl_SetVariableObject(IDirectMusicScript
*iface
,
148 WCHAR
*pwszVariableName
, IUnknown
*punkValue
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
150 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
151 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), punkValue
, pErrorInfo
);
155 static HRESULT WINAPI
IDirectMusicScriptImpl_GetVariableObject(IDirectMusicScript
*iface
,
156 WCHAR
*pwszVariableName
, REFIID riid
, void **ppv
, DMUS_SCRIPT_ERRORINFO
*pErrorInfo
)
158 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
159 FIXME("(%p, %s, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), debugstr_dmguid(riid
), ppv
, pErrorInfo
);
163 static HRESULT WINAPI
IDirectMusicScriptImpl_EnumRoutine(IDirectMusicScript
*iface
, DWORD dwIndex
,
166 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
167 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
171 static HRESULT WINAPI
IDirectMusicScriptImpl_EnumVariable(IDirectMusicScript
*iface
, DWORD dwIndex
,
174 IDirectMusicScriptImpl
*This
= impl_from_IDirectMusicScript(iface
);
175 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
179 static const IDirectMusicScriptVtbl dmscript_vtbl
= {
180 IDirectMusicScriptImpl_QueryInterface
,
181 IDirectMusicScriptImpl_AddRef
,
182 IDirectMusicScriptImpl_Release
,
183 IDirectMusicScriptImpl_Init
,
184 IDirectMusicScriptImpl_CallRoutine
,
185 IDirectMusicScriptImpl_SetVariableVariant
,
186 IDirectMusicScriptImpl_GetVariableVariant
,
187 IDirectMusicScriptImpl_SetVariableNumber
,
188 IDirectMusicScriptImpl_GetVariableNumber
,
189 IDirectMusicScriptImpl_SetVariableObject
,
190 IDirectMusicScriptImpl_GetVariableObject
,
191 IDirectMusicScriptImpl_EnumRoutine
,
192 IDirectMusicScriptImpl_EnumVariable
195 /* IDirectMusicScriptImpl IDirectMusicObject part: */
196 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ppobj
) {
197 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
198 return IDirectMusicScript_QueryInterface(&This
->IDirectMusicScript_iface
, riid
, ppobj
);
201 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
) {
202 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
203 return IDirectMusicScript_AddRef (&This
->IDirectMusicScript_iface
);
206 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface
) {
207 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
208 return IDirectMusicScript_Release (&This
->IDirectMusicScript_iface
);
211 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
212 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
213 TRACE("(%p, %p)\n", This
, pDesc
);
214 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
215 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
219 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
220 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
221 TRACE("(%p, %p): setting descriptor:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC (pDesc
));
223 /* According to MSDN, we should copy only given values, not whole struct */
224 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
225 This
->pDesc
->guidObject
= pDesc
->guidObject
;
226 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
227 This
->pDesc
->guidClass
= pDesc
->guidClass
;
228 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
229 lstrcpynW (This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
230 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
231 lstrcpynW (This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
232 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
233 lstrcpynW (This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
234 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
235 This
->pDesc
->vVersion
= pDesc
->vVersion
;
236 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
237 This
->pDesc
->ftDate
= pDesc
->ftDate
;
238 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
239 This
->pDesc
->llMemLength
= pDesc
->llMemLength
;
240 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, pDesc
->llMemLength
);
242 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
243 /* according to MSDN, we copy the stream */
244 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
248 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
253 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface
, LPSTREAM pStream
, LPDMUS_OBJECTDESC pDesc
) {
254 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
255 DMUS_PRIVATE_CHUNK Chunk
;
256 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
257 LARGE_INTEGER liMove
; /* used when skipping chunks */
259 TRACE("(%p, %p, %p)\n", This
, pStream
, pDesc
);
261 /* FIXME: should this be determined from stream? */
262 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
263 pDesc
->guidClass
= CLSID_DirectMusicScript
;
265 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
266 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
267 switch (Chunk
.fccID
) {
269 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
270 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
271 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
273 if (Chunk
.fccID
== DMUS_FOURCC_SCRIPT_FORM
) {
274 TRACE_(dmfile
)(": script form\n");
276 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
277 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
278 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
279 switch (Chunk
.fccID
) {
280 case DMUS_FOURCC_GUID_CHUNK
: {
281 TRACE_(dmfile
)(": GUID chunk\n");
282 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
283 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
286 case DMUS_FOURCC_VERSION_CHUNK
: {
287 TRACE_(dmfile
)(": version chunk\n");
288 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
289 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
292 case DMUS_FOURCC_CATEGORY_CHUNK
: {
293 TRACE_(dmfile
)(": category chunk\n");
294 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
295 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
299 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
300 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
301 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
303 switch (Chunk
.fccID
) {
304 /* evil M$ UNFO list, which can (!?) contain INFO elements */
305 case DMUS_FOURCC_UNFO_LIST
: {
306 TRACE_(dmfile
)(": UNFO list\n");
308 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
309 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
310 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
311 switch (Chunk
.fccID
) {
312 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
313 (though strings seem to be valid unicode) */
314 case mmioFOURCC('I','N','A','M'):
315 case DMUS_FOURCC_UNAM_CHUNK
: {
316 TRACE_(dmfile
)(": name chunk\n");
317 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
318 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
321 case mmioFOURCC('I','A','R','T'):
322 case DMUS_FOURCC_UART_CHUNK
: {
323 TRACE_(dmfile
)(": artist chunk (ignored)\n");
324 liMove
.QuadPart
= Chunk
.dwSize
;
325 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
328 case mmioFOURCC('I','C','O','P'):
329 case DMUS_FOURCC_UCOP_CHUNK
: {
330 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
331 liMove
.QuadPart
= Chunk
.dwSize
;
332 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
335 case mmioFOURCC('I','S','B','J'):
336 case DMUS_FOURCC_USBJ_CHUNK
: {
337 TRACE_(dmfile
)(": subject chunk (ignored)\n");
338 liMove
.QuadPart
= Chunk
.dwSize
;
339 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
342 case mmioFOURCC('I','C','M','T'):
343 case DMUS_FOURCC_UCMT_CHUNK
: {
344 TRACE_(dmfile
)(": comment chunk (ignored)\n");
345 liMove
.QuadPart
= Chunk
.dwSize
;
346 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
350 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
351 liMove
.QuadPart
= Chunk
.dwSize
;
352 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
356 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
357 } while (ListCount
[0] < ListSize
[0]);
361 TRACE_(dmfile
)(": unknown (skipping)\n");
362 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
363 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
370 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
371 liMove
.QuadPart
= Chunk
.dwSize
;
372 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
376 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
377 } while (StreamCount
< StreamSize
);
379 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
380 liMove
.QuadPart
= StreamSize
;
381 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
385 TRACE_(dmfile
)(": reading finished\n");
389 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
390 liMove
.QuadPart
= Chunk
.dwSize
;
391 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
392 return DMUS_E_INVALIDFILE
;
396 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
401 static const IDirectMusicObjectVtbl DirectMusicScript_Object_Vtbl
= {
402 IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface
,
403 IDirectMusicScriptImpl_IDirectMusicObject_AddRef
,
404 IDirectMusicScriptImpl_IDirectMusicObject_Release
,
405 IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor
,
406 IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor
,
407 IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor
410 /* IDirectMusicScriptImpl IPersistStream part: */
411 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ppobj
) {
412 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
413 return IDirectMusicScript_QueryInterface(&This
->IDirectMusicScript_iface
, riid
, ppobj
);
416 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
) {
417 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
418 return IDirectMusicScript_AddRef(&This
->IDirectMusicScript_iface
);
421 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_Release (LPPERSISTSTREAM iface
) {
422 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
423 return IDirectMusicScript_Release(&This
->IDirectMusicScript_iface
);
426 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface
, CLSID
* pClassID
) {
427 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
428 TRACE("(%p, %p)\n", This
, pClassID
);
429 *pClassID
= CLSID_DirectMusicScript
;
433 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface
) {
434 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
435 FIXME("(%p): stub, always S_FALSE\n", This
);
439 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Load (LPPERSISTSTREAM iface
, IStream
* pStm
) {
440 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
442 DMUS_PRIVATE_CHUNK Chunk
;
443 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
444 LARGE_INTEGER liMove
; /* used when skipping chunks */
445 LPDIRECTMUSICGETLOADER pGetLoader
= NULL
;
446 LPDIRECTMUSICLOADER pLoader
= NULL
;
448 FIXME("(%p, %p): Loading not implemented yet\n", This
, pStm
);
449 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
450 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
451 switch (Chunk
.fccID
) {
453 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
454 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
455 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
457 switch (Chunk
.fccID
) {
458 case DMUS_FOURCC_SCRIPT_FORM
: {
459 TRACE_(dmfile
)(": script form\n");
461 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
462 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
463 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
464 switch (Chunk
.fccID
) {
465 case DMUS_FOURCC_SCRIPT_CHUNK
: {
466 TRACE_(dmfile
)(": script header chunk\n");
467 This
->pHeader
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
468 IStream_Read (pStm
, This
->pHeader
, Chunk
.dwSize
, NULL
);
471 case DMUS_FOURCC_SCRIPTVERSION_CHUNK
: {
472 TRACE_(dmfile
)(": script version chunk\n");
473 This
->pVersion
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
474 IStream_Read (pStm
, This
->pVersion
, Chunk
.dwSize
, NULL
);
475 TRACE_(dmfile
)("version: 0x%08x.0x%08x\n", This
->pVersion
->dwVersionMS
, This
->pVersion
->dwVersionLS
);
478 case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK
: {
479 TRACE_(dmfile
)(": script language chunk\n");
480 This
->pwzLanguage
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
481 IStream_Read (pStm
, This
->pwzLanguage
, Chunk
.dwSize
, NULL
);
482 TRACE_(dmfile
)("using language: %s\n", debugstr_w(This
->pwzLanguage
));
485 case DMUS_FOURCC_SCRIPTSOURCE_CHUNK
: {
486 TRACE_(dmfile
)(": script source chunk\n");
487 This
->pwzSource
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
488 IStream_Read (pStm
, This
->pwzSource
, Chunk
.dwSize
, NULL
);
489 if (TRACE_ON(dmscript
)) {
490 int count
= WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, NULL
, 0, NULL
, NULL
);
491 LPSTR str
= HeapAlloc(GetProcessHeap (), 0, count
);
492 WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, str
, count
, NULL
, NULL
);
495 write( 2, str
, count
);
496 HeapFree(GetProcessHeap(), 0, str
);
500 case DMUS_FOURCC_GUID_CHUNK
: {
501 TRACE_(dmfile
)(": GUID chunk\n");
502 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
503 IStream_Read (pStm
, &This
->pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
506 case DMUS_FOURCC_VERSION_CHUNK
: {
507 TRACE_(dmfile
)(": version chunk\n");
508 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
509 IStream_Read (pStm
, &This
->pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
512 case DMUS_FOURCC_CATEGORY_CHUNK
: {
513 TRACE_(dmfile
)(": category chunk\n");
514 This
->pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
515 IStream_Read (pStm
, This
->pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
519 IDirectMusicObject
* pObject
= NULL
;
520 DMUS_OBJECTDESC desc
;
522 ZeroMemory (&desc
, sizeof(DMUS_OBJECTDESC
));
523 desc
.dwSize
= sizeof(DMUS_OBJECTDESC
);
524 desc
.dwValidData
= DMUS_OBJ_STREAM
| DMUS_OBJ_CLASS
;
525 desc
.guidClass
= CLSID_DirectMusicContainer
;
527 IStream_Clone (pStm
, &desc
.pStream
);
530 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
531 IStream_Seek (desc
.pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
533 IStream_QueryInterface (pStm
, &IID_IDirectMusicGetLoader
, (LPVOID
*)&pGetLoader
);
534 IDirectMusicGetLoader_GetLoader (pGetLoader
, &pLoader
);
535 IDirectMusicGetLoader_Release (pGetLoader
);
537 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader
, &desc
, &IID_IDirectMusicObject
, (LPVOID
*) &pObject
))) {
538 IDirectMusicObject_Release (pObject
);
540 ERR_(dmfile
)("Error on GetObject while trying to load Scrip SubContainer\n");
543 IDirectMusicLoader_Release (pLoader
); pLoader
= NULL
; /* release loader */
544 IStream_Release(desc
.pStream
); desc
.pStream
= NULL
; /* release cloned stream */
546 liMove
.QuadPart
= Chunk
.dwSize
;
547 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
549 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
550 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
551 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
554 switch (Chunk.fccID) {
556 TRACE_(dmfile)(": unknown (skipping)\n");
557 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
558 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
566 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
567 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
568 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
570 switch (Chunk
.fccID
) {
571 case DMUS_FOURCC_UNFO_LIST
: {
572 TRACE_(dmfile
)(": UNFO list\n");
574 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
575 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
576 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
577 switch (Chunk
.fccID
) {
578 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
579 (though strings seem to be valid unicode) */
580 case mmioFOURCC('I','N','A','M'):
581 case DMUS_FOURCC_UNAM_CHUNK
: {
582 TRACE_(dmfile
)(": name chunk\n");
583 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
584 IStream_Read (pStm
, This
->pDesc
->wszName
, Chunk
.dwSize
, NULL
);
587 case mmioFOURCC('I','A','R','T'):
588 case DMUS_FOURCC_UART_CHUNK
: {
589 TRACE_(dmfile
)(": artist chunk (ignored)\n");
590 liMove
.QuadPart
= Chunk
.dwSize
;
591 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
594 case mmioFOURCC('I','C','O','P'):
595 case DMUS_FOURCC_UCOP_CHUNK
: {
596 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
597 liMove
.QuadPart
= Chunk
.dwSize
;
598 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
601 case mmioFOURCC('I','S','B','J'):
602 case DMUS_FOURCC_USBJ_CHUNK
: {
603 TRACE_(dmfile
)(": subject chunk (ignored)\n");
604 liMove
.QuadPart
= Chunk
.dwSize
;
605 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
608 case mmioFOURCC('I','C','M','T'):
609 case DMUS_FOURCC_UCMT_CHUNK
: {
610 TRACE_(dmfile
)(": comment chunk (ignored)\n");
611 liMove
.QuadPart
= Chunk
.dwSize
;
612 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
616 TRACE_(dmfile
)(": unknown sub-chunk (irrelevant & skipping)\n");
617 liMove
.QuadPart
= Chunk
.dwSize
;
618 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
622 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
623 } while (ListCount
[0] < ListSize
[0]);
627 TRACE_(dmfile
)(": unknown (skipping)\n");
628 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
629 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
636 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
637 liMove
.QuadPart
= Chunk
.dwSize
;
638 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
642 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
643 } while (StreamCount
< StreamSize
);
647 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
648 liMove
.QuadPart
= StreamSize
;
649 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
653 TRACE_(dmfile
)(": reading finished\n");
657 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
658 liMove
.QuadPart
= Chunk
.dwSize
;
659 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
667 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
) {
671 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
) {
675 static const IPersistStreamVtbl DirectMusicScript_PersistStream_Vtbl
= {
676 IDirectMusicScriptImpl_IPersistStream_QueryInterface
,
677 IDirectMusicScriptImpl_IPersistStream_AddRef
,
678 IDirectMusicScriptImpl_IPersistStream_Release
,
679 IDirectMusicScriptImpl_IPersistStream_GetClassID
,
680 IDirectMusicScriptImpl_IPersistStream_IsDirty
,
681 IDirectMusicScriptImpl_IPersistStream_Load
,
682 IDirectMusicScriptImpl_IPersistStream_Save
,
683 IDirectMusicScriptImpl_IPersistStream_GetSizeMax
686 /* for ClassFactory */
687 HRESULT WINAPI
DMUSIC_CreateDirectMusicScriptImpl(REFIID lpcGUID
, void **ppobj
, IUnknown
*pUnkOuter
)
689 IDirectMusicScriptImpl
*obj
;
695 return CLASS_E_NOAGGREGATION
;
697 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicScriptImpl
));
699 return E_OUTOFMEMORY
;
701 obj
->IDirectMusicScript_iface
.lpVtbl
= &dmscript_vtbl
;
702 obj
->ObjectVtbl
= &DirectMusicScript_Object_Vtbl
;
703 obj
->PersistStreamVtbl
= &DirectMusicScript_PersistStream_Vtbl
;
704 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
705 DM_STRUCT_INIT(obj
->pDesc
);
706 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
707 obj
->pDesc
->guidClass
= CLSID_DirectMusicScript
;
710 DMSCRIPT_LockModule();
711 hr
= IDirectMusicScript_QueryInterface(&obj
->IDirectMusicScript_iface
, lpcGUID
, ppobj
);
712 IDirectMusicScript_Release(&obj
->IDirectMusicScript_iface
);