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 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.
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.
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.
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 /* IDirectMusicScriptImpl IUnknown part: */
38 HRESULT WINAPI
IDirectMusicScriptImpl_IUnknown_QueryInterface (LPUNKNOWN iface
, REFIID riid
, LPVOID
*ppobj
) {
39 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, UnknownVtbl
, iface
);
40 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ppobj
);
42 if (IsEqualIID (riid
, &IID_IUnknown
)) {
43 *ppobj
= (LPVOID
)&This
->UnknownVtbl
;
44 IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
46 } else if (IsEqualIID (riid
, &IID_IDirectMusicScript
)) {
47 *ppobj
= (LPVOID
)&This
->ScriptVtbl
;
48 IDirectMusicScriptImpl_IDirectMusicScript_AddRef ((LPDIRECTMUSICSCRIPT
)&This
->ScriptVtbl
);
50 } else if (IsEqualIID (riid
, &IID_IDirectMusicObject
)) {
51 *ppobj
= (LPVOID
)&This
->ObjectVtbl
;
52 IDirectMusicScriptImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT
)&This
->ObjectVtbl
);
54 } else if (IsEqualIID (riid
, &IID_IPersistStream
)) {
55 *ppobj
= (LPVOID
)&This
->PersistStreamVtbl
;
56 IDirectMusicScriptImpl_IPersistStream_AddRef ((LPPERSISTSTREAM
)&This
->PersistStreamVtbl
);
60 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ppobj
);
64 ULONG WINAPI
IDirectMusicScriptImpl_IUnknown_AddRef (LPUNKNOWN iface
) {
65 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, UnknownVtbl
, iface
);
66 TRACE("(%p): AddRef from %ld\n", This
, This
->ref
);
70 ULONG WINAPI
IDirectMusicScriptImpl_IUnknown_Release (LPUNKNOWN iface
) {
71 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, UnknownVtbl
, iface
);
72 ULONG ref
= --This
->ref
;
73 TRACE("(%p): ReleaseRef to %ld\n", This
, This
->ref
);
75 if (NULL
!= This
->pHeader
) HeapFree(GetProcessHeap(), 0, This
->pHeader
);
76 if (NULL
!= This
->pVersion
) HeapFree(GetProcessHeap(), 0, This
->pVersion
);
77 if (NULL
!= This
->pwzLanguage
) HeapFree(GetProcessHeap(), 0, This
->pwzLanguage
);
78 if (NULL
!= This
->pwzSource
) HeapFree(GetProcessHeap(), 0, This
->pwzSource
);
79 HeapFree(GetProcessHeap(), 0, This
);
84 ICOM_VTABLE(IUnknown
) DirectMusicScript_Unknown_Vtbl
= {
85 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
86 IDirectMusicScriptImpl_IUnknown_QueryInterface
,
87 IDirectMusicScriptImpl_IUnknown_AddRef
,
88 IDirectMusicScriptImpl_IUnknown_Release
91 /* IDirectMusicScriptImpl IDirectMusicScript part: */
92 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_QueryInterface (LPDIRECTMUSICSCRIPT iface
, REFIID riid
, LPVOID
*ppobj
) {
93 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
94 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
97 ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_AddRef (LPDIRECTMUSICSCRIPT iface
) {
98 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
99 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
102 ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_Release (LPDIRECTMUSICSCRIPT iface
) {
103 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
104 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
107 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_Init (LPDIRECTMUSICSCRIPT iface
, IDirectMusicPerformance
* pPerformance
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
108 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
109 FIXME("(%p, %p, %p): stub\n", This
, pPerformance
, pErrorInfo
);
110 This
->pPerformance
= pPerformance
;
114 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_CallRoutine (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszRoutineName
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
115 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
116 FIXME("(%p, %s, %p): stub\n", This
, debugstr_w(pwszRoutineName
), pErrorInfo
);
117 /*return E_NOTIMPL;*/
122 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_SetVariableVariant (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, VARIANT varValue
, BOOL fSetRef
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
123 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
124 FIXME("(%p, %s, FIXME, %d, %p): stub\n", This
, debugstr_w(pwszVariableName
),/* varValue,*/ fSetRef
, pErrorInfo
);
128 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_GetVariableVariant (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, VARIANT
* pvarValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
129 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
130 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), pvarValue
, pErrorInfo
);
134 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_SetVariableNumber (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, LONG lValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
135 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
136 FIXME("(%p, %s, %li, %p): stub\n", This
, debugstr_w(pwszVariableName
), lValue
, pErrorInfo
);
140 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_GetVariableNumber (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, LONG
* plValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
141 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
142 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), plValue
, pErrorInfo
);
146 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_SetVariableObject (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, IUnknown
* punkValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
147 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
148 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), punkValue
, pErrorInfo
);
152 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_GetVariableObject (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, REFIID riid
, LPVOID
* ppv
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
153 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
154 FIXME("(%p, %s, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), debugstr_dmguid(riid
), ppv
, pErrorInfo
);
158 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_EnumRoutine (LPDIRECTMUSICSCRIPT iface
, DWORD dwIndex
, WCHAR
* pwszName
) {
159 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
160 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, pwszName
);
164 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_EnumVariable (LPDIRECTMUSICSCRIPT iface
, DWORD dwIndex
, WCHAR
* pwszName
) {
165 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
166 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, pwszName
);
170 ICOM_VTABLE(IDirectMusicScript
) DirectMusicScript_Script_Vtbl
= {
171 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
172 IDirectMusicScriptImpl_IDirectMusicScript_QueryInterface
,
173 IDirectMusicScriptImpl_IDirectMusicScript_AddRef
,
174 IDirectMusicScriptImpl_IDirectMusicScript_Release
,
175 IDirectMusicScriptImpl_IDirectMusicScript_Init
,
176 IDirectMusicScriptImpl_IDirectMusicScript_CallRoutine
,
177 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableVariant
,
178 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableVariant
,
179 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableNumber
,
180 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableNumber
,
181 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableObject
,
182 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableObject
,
183 IDirectMusicScriptImpl_IDirectMusicScript_EnumRoutine
,
184 IDirectMusicScriptImpl_IDirectMusicScript_EnumVariable
187 /* IDirectMusicScriptImpl IDirectMusicObject part: */
188 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ppobj
) {
189 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
190 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
193 ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
) {
194 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
195 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
198 ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface
) {
199 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
200 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
203 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
204 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
205 TRACE("(%p, %p)\n", This
, pDesc
);
206 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
207 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
211 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
212 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
213 TRACE("(%p, %p): setting descriptor:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC (pDesc
));
215 /* According to MSDN, we should copy only given values, not whole struct */
216 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
217 memcpy (&This
->pDesc
->guidObject
, &pDesc
->guidObject
, sizeof (pDesc
->guidObject
));
218 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
219 memcpy (&This
->pDesc
->guidClass
, &pDesc
->guidClass
, sizeof (pDesc
->guidClass
));
220 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
221 strncpyW (This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
222 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
223 strncpyW (This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
224 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
225 strncpyW (This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
226 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
227 memcpy (&This
->pDesc
->vVersion
, &pDesc
->vVersion
, sizeof (pDesc
->vVersion
));
228 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
229 memcpy (&This
->pDesc
->ftDate
, &pDesc
->ftDate
, sizeof (pDesc
->ftDate
));
230 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
231 memcpy (&This
->pDesc
->llMemLength
, &pDesc
->llMemLength
, sizeof (pDesc
->llMemLength
));
232 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, sizeof (pDesc
->pbMemData
));
234 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
235 /* according to MSDN, we copy the stream */
236 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
240 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
245 HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface
, LPSTREAM pStream
, LPDMUS_OBJECTDESC pDesc
) {
246 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
247 DMUS_PRIVATE_CHUNK Chunk
;
248 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
249 LARGE_INTEGER liMove
; /* used when skipping chunks */
251 TRACE("(%p, %p, %p)\n", This
, pStream
, pDesc
);
253 /* FIXME: should this be determined from stream? */
254 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
255 memcpy (&pDesc
->guidClass
, &CLSID_DirectMusicScript
, sizeof(CLSID
));
257 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
258 TRACE_(dmfile
)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
259 switch (Chunk
.fccID
) {
261 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
262 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
263 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
265 if (Chunk
.fccID
== DMUS_FOURCC_SCRIPT_FORM
) {
266 TRACE_(dmfile
)(": script form\n");
268 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
269 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
270 TRACE_(dmfile
)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
271 switch (Chunk
.fccID
) {
272 case DMUS_FOURCC_GUID_CHUNK
: {
273 TRACE_(dmfile
)(": GUID chunk\n");
274 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
275 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
278 case DMUS_FOURCC_VERSION_CHUNK
: {
279 TRACE_(dmfile
)(": version chunk\n");
280 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
281 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
284 case DMUS_FOURCC_CATEGORY_CHUNK
: {
285 TRACE_(dmfile
)(": category chunk\n");
286 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
287 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
291 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
292 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
293 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
295 switch (Chunk
.fccID
) {
296 /* evil M$ UNFO list, which can (!?) contain INFO elements */
297 case DMUS_FOURCC_UNFO_LIST
: {
298 TRACE_(dmfile
)(": UNFO list\n");
300 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
301 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
302 TRACE_(dmfile
)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
303 switch (Chunk
.fccID
) {
304 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
305 (though strings seem to be valid unicode) */
306 case mmioFOURCC('I','N','A','M'):
307 case DMUS_FOURCC_UNAM_CHUNK
: {
308 TRACE_(dmfile
)(": name chunk\n");
309 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
310 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
313 case mmioFOURCC('I','A','R','T'):
314 case DMUS_FOURCC_UART_CHUNK
: {
315 TRACE_(dmfile
)(": artist chunk (ignored)\n");
316 liMove
.QuadPart
= Chunk
.dwSize
;
317 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
320 case mmioFOURCC('I','C','O','P'):
321 case DMUS_FOURCC_UCOP_CHUNK
: {
322 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
323 liMove
.QuadPart
= Chunk
.dwSize
;
324 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
327 case mmioFOURCC('I','S','B','J'):
328 case DMUS_FOURCC_USBJ_CHUNK
: {
329 TRACE_(dmfile
)(": subject chunk (ignored)\n");
330 liMove
.QuadPart
= Chunk
.dwSize
;
331 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
334 case mmioFOURCC('I','C','M','T'):
335 case DMUS_FOURCC_UCMT_CHUNK
: {
336 TRACE_(dmfile
)(": comment chunk (ignored)\n");
337 liMove
.QuadPart
= Chunk
.dwSize
;
338 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
342 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
343 liMove
.QuadPart
= Chunk
.dwSize
;
344 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
348 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
349 } while (ListCount
[0] < ListSize
[0]);
353 TRACE_(dmfile
)(": unknown (skipping)\n");
354 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
355 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
362 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
363 liMove
.QuadPart
= Chunk
.dwSize
;
364 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
368 TRACE_(dmfile
)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount
, StreamSize
);
369 } while (StreamCount
< StreamSize
);
372 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
373 liMove
.QuadPart
= StreamSize
;
374 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
378 TRACE_(dmfile
)(": reading finished\n");
382 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
383 liMove
.QuadPart
= Chunk
.dwSize
;
384 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
385 return DMUS_E_INVALIDFILE
;
389 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
394 ICOM_VTABLE(IDirectMusicObject
) DirectMusicScript_Object_Vtbl
= {
395 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
396 IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface
,
397 IDirectMusicScriptImpl_IDirectMusicObject_AddRef
,
398 IDirectMusicScriptImpl_IDirectMusicObject_Release
,
399 IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor
,
400 IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor
,
401 IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor
404 /* IDirectMusicScriptImpl IPersistStream part: */
405 HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ppobj
) {
406 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
407 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
410 ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
) {
411 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
412 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
415 ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_Release (LPPERSISTSTREAM iface
) {
416 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
417 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
420 HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface
, CLSID
* pClassID
) {
421 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
422 TRACE("(%p, %p)\n", This
, pClassID
);
423 memcpy(pClassID
, &CLSID_DirectMusicScript
, sizeof(CLSID
));
427 HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface
) {
428 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
429 FIXME("(%p): stub, always S_FALSE\n", This
);
433 HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Load (LPPERSISTSTREAM iface
, IStream
* pStm
) {
434 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
436 DMUS_PRIVATE_CHUNK Chunk
;
437 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
438 LARGE_INTEGER liMove
; /* used when skipping chunks */
439 LPDIRECTMUSICGETLOADER pGetLoader
= NULL
;
440 LPDIRECTMUSICLOADER pLoader
= NULL
;
442 FIXME("(%p, %p): Loading not implemented yet\n", This
, pStm
);
443 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
444 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
445 switch (Chunk
.fccID
) {
447 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
448 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
449 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
451 switch (Chunk
.fccID
) {
452 case DMUS_FOURCC_SCRIPT_FORM
: {
453 TRACE_(dmfile
)(": script form\n");
455 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
456 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
457 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
458 switch (Chunk
.fccID
) {
459 case DMUS_FOURCC_SCRIPT_CHUNK
: {
460 TRACE_(dmfile
)(": script header chunk\n");
461 This
->pHeader
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
462 IStream_Read (pStm
, This
->pHeader
, Chunk
.dwSize
, NULL
);
465 case DMUS_FOURCC_SCRIPTVERSION_CHUNK
: {
466 TRACE_(dmfile
)(": script version chunk\n");
467 This
->pVersion
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
468 IStream_Read (pStm
, This
->pVersion
, Chunk
.dwSize
, NULL
);
469 TRACE_(dmfile
)("version: 0x%08lx.0x%08lx \n", This
->pVersion
->dwVersionMS
, This
->pVersion
->dwVersionLS
);
472 case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK
: {
473 TRACE_(dmfile
)(": script language chunk\n");
474 This
->pwzLanguage
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
475 IStream_Read (pStm
, This
->pwzLanguage
, Chunk
.dwSize
, NULL
);
476 TRACE_(dmfile
)("using language: %s \n", debugstr_w(This
->pwzLanguage
));
479 case DMUS_FOURCC_SCRIPTSOURCE_CHUNK
: {
480 TRACE_(dmfile
)(": script source chunk\n");
481 This
->pwzSource
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
482 IStream_Read (pStm
, This
->pwzSource
, Chunk
.dwSize
, NULL
);
483 if (TRACE_ON(dmscript
)) {
484 int count
= WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, NULL
, 0, NULL
, NULL
);
485 LPSTR str
= HeapAlloc(GetProcessHeap (), 0, count
);
486 WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, str
, count
, NULL
, NULL
);
489 write( 2, str
, count
);
490 HeapFree(GetProcessHeap(), 0, str
);
494 case DMUS_FOURCC_GUID_CHUNK
: {
495 TRACE_(dmfile
)(": GUID chunk\n");
496 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
497 IStream_Read (pStm
, &This
->pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
500 case DMUS_FOURCC_VERSION_CHUNK
: {
501 TRACE_(dmfile
)(": version chunk\n");
502 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
503 IStream_Read (pStm
, &This
->pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
506 case DMUS_FOURCC_CATEGORY_CHUNK
: {
507 TRACE_(dmfile
)(": category chunk\n");
508 This
->pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
509 IStream_Read (pStm
, This
->pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
513 IDirectMusicObject
* pObject
= NULL
;
514 DMUS_OBJECTDESC desc
;
516 ZeroMemory ((LPVOID
)&desc
, sizeof(DMUS_OBJECTDESC
));
517 desc
.dwSize
= sizeof(DMUS_OBJECTDESC
);
518 desc
.dwValidData
= DMUS_OBJ_STREAM
| DMUS_OBJ_CLASS
;
519 desc
.guidClass
= CLSID_DirectMusicContainer
;
521 IStream_Clone (pStm
, &desc
.pStream
);
524 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
525 IStream_Seek (desc
.pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
527 IStream_QueryInterface (pStm
, &IID_IDirectMusicGetLoader
, (LPVOID
*)&pGetLoader
);
528 IDirectMusicGetLoader_GetLoader (pGetLoader
, &pLoader
);
529 IDirectMusicGetLoader_Release (pGetLoader
);
531 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader
, &desc
, &IID_IDirectMusicObject
, (LPVOID
*) &pObject
))) {
532 IDirectMusicObject_Release (pObject
);
534 ERR_(dmfile
)("Error on GetObject while trying to load Scrip SubContainer\n");
537 IDirectMusicLoader_Release (pLoader
); pLoader
= NULL
; /* release loader */
538 IStream_Release(desc
.pStream
); desc
.pStream
= NULL
; /* release cloned stream */
540 liMove
.QuadPart
= Chunk
.dwSize
;
541 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
543 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
544 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
545 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
548 switch (Chunk.fccID) {
550 TRACE_(dmfile)(": unknown (skipping)\n");
551 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
552 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
560 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
561 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
562 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
564 switch (Chunk
.fccID
) {
565 case DMUS_FOURCC_UNFO_LIST
: {
566 TRACE_(dmfile
)(": UNFO list\n");
568 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
569 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
570 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
571 switch (Chunk
.fccID
) {
572 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
573 (though strings seem to be valid unicode) */
574 case mmioFOURCC('I','N','A','M'):
575 case DMUS_FOURCC_UNAM_CHUNK
: {
576 TRACE_(dmfile
)(": name chunk\n");
577 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
578 IStream_Read (pStm
, This
->pDesc
->wszName
, Chunk
.dwSize
, NULL
);
581 case mmioFOURCC('I','A','R','T'):
582 case DMUS_FOURCC_UART_CHUNK
: {
583 TRACE_(dmfile
)(": artist chunk (ignored)\n");
584 liMove
.QuadPart
= Chunk
.dwSize
;
585 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
588 case mmioFOURCC('I','C','O','P'):
589 case DMUS_FOURCC_UCOP_CHUNK
: {
590 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
591 liMove
.QuadPart
= Chunk
.dwSize
;
592 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
595 case mmioFOURCC('I','S','B','J'):
596 case DMUS_FOURCC_USBJ_CHUNK
: {
597 TRACE_(dmfile
)(": subject chunk (ignored)\n");
598 liMove
.QuadPart
= Chunk
.dwSize
;
599 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
602 case mmioFOURCC('I','C','M','T'):
603 case DMUS_FOURCC_UCMT_CHUNK
: {
604 TRACE_(dmfile
)(": comment chunk (ignored)\n");
605 liMove
.QuadPart
= Chunk
.dwSize
;
606 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
610 TRACE_(dmfile
)(": unknown sub-chunk (irrevelant & skipping)\n");
611 liMove
.QuadPart
= Chunk
.dwSize
;
612 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
616 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
617 } while (ListCount
[0] < ListSize
[0]);
621 TRACE_(dmfile
)(": unknown (skipping)\n");
622 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
623 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
630 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
631 liMove
.QuadPart
= Chunk
.dwSize
;
632 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
636 TRACE_(dmfile
)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount
, StreamSize
);
637 } while (StreamCount
< StreamSize
);
641 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
642 liMove
.QuadPart
= StreamSize
;
643 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
647 TRACE_(dmfile
)(": reading finished\n");
651 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
652 liMove
.QuadPart
= Chunk
.dwSize
;
653 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
661 HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
) {
665 HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
) {
669 ICOM_VTABLE(IPersistStream
) DirectMusicScript_PersistStream_Vtbl
= {
670 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
671 IDirectMusicScriptImpl_IPersistStream_QueryInterface
,
672 IDirectMusicScriptImpl_IPersistStream_AddRef
,
673 IDirectMusicScriptImpl_IPersistStream_Release
,
674 IDirectMusicScriptImpl_IPersistStream_GetClassID
,
675 IDirectMusicScriptImpl_IPersistStream_IsDirty
,
676 IDirectMusicScriptImpl_IPersistStream_Load
,
677 IDirectMusicScriptImpl_IPersistStream_Save
,
678 IDirectMusicScriptImpl_IPersistStream_GetSizeMax
681 /* for ClassFactory */
682 HRESULT WINAPI
DMUSIC_CreateDirectMusicScriptImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
683 IDirectMusicScriptImpl
* obj
;
685 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicScriptImpl
));
687 *ppobj
= (LPVOID
) NULL
;
688 return E_OUTOFMEMORY
;
690 obj
->UnknownVtbl
= &DirectMusicScript_Unknown_Vtbl
;
691 obj
->ScriptVtbl
= &DirectMusicScript_Script_Vtbl
;
692 obj
->ObjectVtbl
= &DirectMusicScript_Object_Vtbl
;
693 obj
->PersistStreamVtbl
= &DirectMusicScript_PersistStream_Vtbl
;
694 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
695 DM_STRUCT_INIT(obj
->pDesc
);
696 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
697 memcpy (&obj
->pDesc
->guidClass
, &CLSID_DirectMusicScript
, sizeof (CLSID
));
698 obj
->ref
= 0; /* will be inited by QueryInterface */
700 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&obj
->UnknownVtbl
, lpcGUID
, ppobj
);