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 static ULONG WINAPI
IDirectMusicScriptImpl_IUnknown_AddRef (LPUNKNOWN iface
);
35 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_AddRef (LPDIRECTMUSICSCRIPT iface
);
36 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
);
37 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
);
39 /*****************************************************************************
40 * IDirectMusicScriptImpl implementation
42 /* IDirectMusicScriptImpl IUnknown part: */
43 static HRESULT WINAPI
IDirectMusicScriptImpl_IUnknown_QueryInterface (LPUNKNOWN iface
, REFIID riid
, LPVOID
*ppobj
) {
44 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, UnknownVtbl
, iface
);
45 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ppobj
);
47 if (IsEqualIID (riid
, &IID_IUnknown
)) {
48 *ppobj
= &This
->UnknownVtbl
;
49 IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
51 } else if (IsEqualIID (riid
, &IID_IDirectMusicScript
)) {
52 *ppobj
= &This
->ScriptVtbl
;
53 IDirectMusicScriptImpl_IDirectMusicScript_AddRef ((LPDIRECTMUSICSCRIPT
)&This
->ScriptVtbl
);
55 } else if (IsEqualIID (riid
, &IID_IDirectMusicObject
)) {
56 *ppobj
= &This
->ObjectVtbl
;
57 IDirectMusicScriptImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT
)&This
->ObjectVtbl
);
59 } else if (IsEqualIID (riid
, &IID_IPersistStream
)) {
60 *ppobj
= &This
->PersistStreamVtbl
;
61 IDirectMusicScriptImpl_IPersistStream_AddRef ((LPPERSISTSTREAM
)&This
->PersistStreamVtbl
);
65 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ppobj
);
69 static ULONG WINAPI
IDirectMusicScriptImpl_IUnknown_AddRef (LPUNKNOWN iface
) {
70 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, UnknownVtbl
, iface
);
71 ULONG ref
= InterlockedIncrement(&This
->ref
);
73 TRACE("(%p): AddRef from %d\n", This
, ref
- 1);
75 DMSCRIPT_LockModule();
80 static ULONG WINAPI
IDirectMusicScriptImpl_IUnknown_Release (LPUNKNOWN iface
) {
81 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, UnknownVtbl
, iface
);
82 ULONG ref
= InterlockedDecrement(&This
->ref
);
84 TRACE("(%p): ReleaseRef to %d\n", This
, ref
);
87 HeapFree(GetProcessHeap(), 0, This
->pHeader
);
88 HeapFree(GetProcessHeap(), 0, This
->pVersion
);
89 HeapFree(GetProcessHeap(), 0, This
->pwzLanguage
);
90 HeapFree(GetProcessHeap(), 0, This
->pwzSource
);
91 HeapFree(GetProcessHeap(), 0, This
);
94 DMSCRIPT_UnlockModule();
99 static const IUnknownVtbl DirectMusicScript_Unknown_Vtbl
= {
100 IDirectMusicScriptImpl_IUnknown_QueryInterface
,
101 IDirectMusicScriptImpl_IUnknown_AddRef
,
102 IDirectMusicScriptImpl_IUnknown_Release
105 /* IDirectMusicScriptImpl IDirectMusicScript part: */
106 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_QueryInterface (LPDIRECTMUSICSCRIPT iface
, REFIID riid
, LPVOID
*ppobj
) {
107 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
108 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
111 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_AddRef (LPDIRECTMUSICSCRIPT iface
) {
112 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
113 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
116 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_Release (LPDIRECTMUSICSCRIPT iface
) {
117 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
118 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
121 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_Init (LPDIRECTMUSICSCRIPT iface
, IDirectMusicPerformance
* pPerformance
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
122 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
123 FIXME("(%p, %p, %p): stub\n", This
, pPerformance
, pErrorInfo
);
124 This
->pPerformance
= pPerformance
;
128 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_CallRoutine (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszRoutineName
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
129 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
130 FIXME("(%p, %s, %p): stub\n", This
, debugstr_w(pwszRoutineName
), pErrorInfo
);
131 /*return E_NOTIMPL;*/
136 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_SetVariableVariant (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, VARIANT varValue
, BOOL fSetRef
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
137 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
138 FIXME("(%p, %s, FIXME, %d, %p): stub\n", This
, debugstr_w(pwszVariableName
),/* varValue,*/ fSetRef
, pErrorInfo
);
142 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_GetVariableVariant (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, VARIANT
* pvarValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
143 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
144 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), pvarValue
, pErrorInfo
);
148 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_SetVariableNumber (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, LONG lValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
149 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
150 FIXME("(%p, %s, %i, %p): stub\n", This
, debugstr_w(pwszVariableName
), lValue
, pErrorInfo
);
154 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_GetVariableNumber (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, LONG
* plValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
155 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
156 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), plValue
, pErrorInfo
);
160 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_SetVariableObject (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, IUnknown
* punkValue
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
161 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
162 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), punkValue
, pErrorInfo
);
166 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_GetVariableObject (LPDIRECTMUSICSCRIPT iface
, WCHAR
* pwszVariableName
, REFIID riid
, LPVOID
* ppv
, DMUS_SCRIPT_ERRORINFO
* pErrorInfo
) {
167 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
168 FIXME("(%p, %s, %s, %p, %p): stub\n", This
, debugstr_w(pwszVariableName
), debugstr_dmguid(riid
), ppv
, pErrorInfo
);
172 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_EnumRoutine (LPDIRECTMUSICSCRIPT iface
, DWORD dwIndex
, WCHAR
* pwszName
) {
173 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
174 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
178 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicScript_EnumVariable (LPDIRECTMUSICSCRIPT iface
, DWORD dwIndex
, WCHAR
* pwszName
) {
179 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ScriptVtbl
, iface
);
180 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
184 static const IDirectMusicScriptVtbl DirectMusicScript_Script_Vtbl
= {
185 IDirectMusicScriptImpl_IDirectMusicScript_QueryInterface
,
186 IDirectMusicScriptImpl_IDirectMusicScript_AddRef
,
187 IDirectMusicScriptImpl_IDirectMusicScript_Release
,
188 IDirectMusicScriptImpl_IDirectMusicScript_Init
,
189 IDirectMusicScriptImpl_IDirectMusicScript_CallRoutine
,
190 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableVariant
,
191 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableVariant
,
192 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableNumber
,
193 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableNumber
,
194 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableObject
,
195 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableObject
,
196 IDirectMusicScriptImpl_IDirectMusicScript_EnumRoutine
,
197 IDirectMusicScriptImpl_IDirectMusicScript_EnumVariable
200 /* IDirectMusicScriptImpl IDirectMusicObject part: */
201 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ppobj
) {
202 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
203 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
206 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
) {
207 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
208 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
211 static ULONG WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface
) {
212 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
213 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
216 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
217 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
218 TRACE("(%p, %p)\n", This
, pDesc
);
219 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
220 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
224 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
225 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
226 TRACE("(%p, %p): setting descriptor:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC (pDesc
));
228 /* According to MSDN, we should copy only given values, not whole struct */
229 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
230 This
->pDesc
->guidObject
= pDesc
->guidObject
;
231 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
232 This
->pDesc
->guidClass
= pDesc
->guidClass
;
233 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
234 lstrcpynW (This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
235 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
236 lstrcpynW (This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
237 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
238 lstrcpynW (This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
239 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
240 This
->pDesc
->vVersion
= pDesc
->vVersion
;
241 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
242 This
->pDesc
->ftDate
= pDesc
->ftDate
;
243 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
244 memcpy (&This
->pDesc
->llMemLength
, &pDesc
->llMemLength
, sizeof (pDesc
->llMemLength
));
245 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, sizeof (pDesc
->pbMemData
));
247 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
248 /* according to MSDN, we copy the stream */
249 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
253 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
258 static HRESULT WINAPI
IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface
, LPSTREAM pStream
, LPDMUS_OBJECTDESC pDesc
) {
259 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, ObjectVtbl
, iface
);
260 DMUS_PRIVATE_CHUNK Chunk
;
261 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
262 LARGE_INTEGER liMove
; /* used when skipping chunks */
264 TRACE("(%p, %p, %p)\n", This
, pStream
, pDesc
);
266 /* FIXME: should this be determined from stream? */
267 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
268 pDesc
->guidClass
= CLSID_DirectMusicScript
;
270 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
271 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
272 switch (Chunk
.fccID
) {
274 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
275 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
276 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
278 if (Chunk
.fccID
== DMUS_FOURCC_SCRIPT_FORM
) {
279 TRACE_(dmfile
)(": script form\n");
281 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
282 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
283 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
284 switch (Chunk
.fccID
) {
285 case DMUS_FOURCC_GUID_CHUNK
: {
286 TRACE_(dmfile
)(": GUID chunk\n");
287 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
288 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
291 case DMUS_FOURCC_VERSION_CHUNK
: {
292 TRACE_(dmfile
)(": version chunk\n");
293 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
294 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
297 case DMUS_FOURCC_CATEGORY_CHUNK
: {
298 TRACE_(dmfile
)(": category chunk\n");
299 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
300 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
304 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
305 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
306 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
308 switch (Chunk
.fccID
) {
309 /* evil M$ UNFO list, which can (!?) contain INFO elements */
310 case DMUS_FOURCC_UNFO_LIST
: {
311 TRACE_(dmfile
)(": UNFO list\n");
313 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
314 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
315 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
316 switch (Chunk
.fccID
) {
317 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
318 (though strings seem to be valid unicode) */
319 case mmioFOURCC('I','N','A','M'):
320 case DMUS_FOURCC_UNAM_CHUNK
: {
321 TRACE_(dmfile
)(": name chunk\n");
322 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
323 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
326 case mmioFOURCC('I','A','R','T'):
327 case DMUS_FOURCC_UART_CHUNK
: {
328 TRACE_(dmfile
)(": artist chunk (ignored)\n");
329 liMove
.QuadPart
= Chunk
.dwSize
;
330 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
333 case mmioFOURCC('I','C','O','P'):
334 case DMUS_FOURCC_UCOP_CHUNK
: {
335 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
336 liMove
.QuadPart
= Chunk
.dwSize
;
337 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
340 case mmioFOURCC('I','S','B','J'):
341 case DMUS_FOURCC_USBJ_CHUNK
: {
342 TRACE_(dmfile
)(": subject chunk (ignored)\n");
343 liMove
.QuadPart
= Chunk
.dwSize
;
344 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
347 case mmioFOURCC('I','C','M','T'):
348 case DMUS_FOURCC_UCMT_CHUNK
: {
349 TRACE_(dmfile
)(": comment chunk (ignored)\n");
350 liMove
.QuadPart
= Chunk
.dwSize
;
351 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
355 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
356 liMove
.QuadPart
= Chunk
.dwSize
;
357 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
361 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
362 } while (ListCount
[0] < ListSize
[0]);
366 TRACE_(dmfile
)(": unknown (skipping)\n");
367 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
368 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
375 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
376 liMove
.QuadPart
= Chunk
.dwSize
;
377 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
381 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
382 } while (StreamCount
< StreamSize
);
384 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
385 liMove
.QuadPart
= StreamSize
;
386 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
390 TRACE_(dmfile
)(": reading finished\n");
394 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
395 liMove
.QuadPart
= Chunk
.dwSize
;
396 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
397 return DMUS_E_INVALIDFILE
;
401 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
406 static const IDirectMusicObjectVtbl DirectMusicScript_Object_Vtbl
= {
407 IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface
,
408 IDirectMusicScriptImpl_IDirectMusicObject_AddRef
,
409 IDirectMusicScriptImpl_IDirectMusicObject_Release
,
410 IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor
,
411 IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor
,
412 IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor
415 /* IDirectMusicScriptImpl IPersistStream part: */
416 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ppobj
) {
417 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
418 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
421 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
) {
422 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
423 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
426 static ULONG WINAPI
IDirectMusicScriptImpl_IPersistStream_Release (LPPERSISTSTREAM iface
) {
427 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
428 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
431 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface
, CLSID
* pClassID
) {
432 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
433 TRACE("(%p, %p)\n", This
, pClassID
);
434 *pClassID
= CLSID_DirectMusicScript
;
438 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface
) {
439 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
440 FIXME("(%p): stub, always S_FALSE\n", This
);
444 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Load (LPPERSISTSTREAM iface
, IStream
* pStm
) {
445 ICOM_THIS_MULTI(IDirectMusicScriptImpl
, PersistStreamVtbl
, iface
);
447 DMUS_PRIVATE_CHUNK Chunk
;
448 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
449 LARGE_INTEGER liMove
; /* used when skipping chunks */
450 LPDIRECTMUSICGETLOADER pGetLoader
= NULL
;
451 LPDIRECTMUSICLOADER pLoader
= NULL
;
453 FIXME("(%p, %p): Loading not implemented yet\n", This
, pStm
);
454 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
455 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
456 switch (Chunk
.fccID
) {
458 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
459 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
460 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
462 switch (Chunk
.fccID
) {
463 case DMUS_FOURCC_SCRIPT_FORM
: {
464 TRACE_(dmfile
)(": script form\n");
466 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
467 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
468 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
469 switch (Chunk
.fccID
) {
470 case DMUS_FOURCC_SCRIPT_CHUNK
: {
471 TRACE_(dmfile
)(": script header chunk\n");
472 This
->pHeader
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
473 IStream_Read (pStm
, This
->pHeader
, Chunk
.dwSize
, NULL
);
476 case DMUS_FOURCC_SCRIPTVERSION_CHUNK
: {
477 TRACE_(dmfile
)(": script version chunk\n");
478 This
->pVersion
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
479 IStream_Read (pStm
, This
->pVersion
, Chunk
.dwSize
, NULL
);
480 TRACE_(dmfile
)("version: 0x%08x.0x%08x\n", This
->pVersion
->dwVersionMS
, This
->pVersion
->dwVersionLS
);
483 case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK
: {
484 TRACE_(dmfile
)(": script language chunk\n");
485 This
->pwzLanguage
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
486 IStream_Read (pStm
, This
->pwzLanguage
, Chunk
.dwSize
, NULL
);
487 TRACE_(dmfile
)("using language: %s\n", debugstr_w(This
->pwzLanguage
));
490 case DMUS_FOURCC_SCRIPTSOURCE_CHUNK
: {
491 TRACE_(dmfile
)(": script source chunk\n");
492 This
->pwzSource
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, Chunk
.dwSize
);
493 IStream_Read (pStm
, This
->pwzSource
, Chunk
.dwSize
, NULL
);
494 if (TRACE_ON(dmscript
)) {
495 int count
= WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, NULL
, 0, NULL
, NULL
);
496 LPSTR str
= HeapAlloc(GetProcessHeap (), 0, count
);
497 WideCharToMultiByte(CP_ACP
, 0, This
->pwzSource
, -1, str
, count
, NULL
, NULL
);
500 write( 2, str
, count
);
501 HeapFree(GetProcessHeap(), 0, str
);
505 case DMUS_FOURCC_GUID_CHUNK
: {
506 TRACE_(dmfile
)(": GUID chunk\n");
507 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
508 IStream_Read (pStm
, &This
->pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
511 case DMUS_FOURCC_VERSION_CHUNK
: {
512 TRACE_(dmfile
)(": version chunk\n");
513 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
514 IStream_Read (pStm
, &This
->pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
517 case DMUS_FOURCC_CATEGORY_CHUNK
: {
518 TRACE_(dmfile
)(": category chunk\n");
519 This
->pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
520 IStream_Read (pStm
, This
->pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
524 IDirectMusicObject
* pObject
= NULL
;
525 DMUS_OBJECTDESC desc
;
527 ZeroMemory (&desc
, sizeof(DMUS_OBJECTDESC
));
528 desc
.dwSize
= sizeof(DMUS_OBJECTDESC
);
529 desc
.dwValidData
= DMUS_OBJ_STREAM
| DMUS_OBJ_CLASS
;
530 desc
.guidClass
= CLSID_DirectMusicContainer
;
532 IStream_Clone (pStm
, &desc
.pStream
);
535 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
536 IStream_Seek (desc
.pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
538 IStream_QueryInterface (pStm
, &IID_IDirectMusicGetLoader
, (LPVOID
*)&pGetLoader
);
539 IDirectMusicGetLoader_GetLoader (pGetLoader
, &pLoader
);
540 IDirectMusicGetLoader_Release (pGetLoader
);
542 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader
, &desc
, &IID_IDirectMusicObject
, (LPVOID
*) &pObject
))) {
543 IDirectMusicObject_Release (pObject
);
545 ERR_(dmfile
)("Error on GetObject while trying to load Scrip SubContainer\n");
548 IDirectMusicLoader_Release (pLoader
); pLoader
= NULL
; /* release loader */
549 IStream_Release(desc
.pStream
); desc
.pStream
= NULL
; /* release cloned stream */
551 liMove
.QuadPart
= Chunk
.dwSize
;
552 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
554 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
555 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
556 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
559 switch (Chunk.fccID) {
561 TRACE_(dmfile)(": unknown (skipping)\n");
562 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
563 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
571 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
572 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
573 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
575 switch (Chunk
.fccID
) {
576 case DMUS_FOURCC_UNFO_LIST
: {
577 TRACE_(dmfile
)(": UNFO list\n");
579 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
580 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
581 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
582 switch (Chunk
.fccID
) {
583 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
584 (though strings seem to be valid unicode) */
585 case mmioFOURCC('I','N','A','M'):
586 case DMUS_FOURCC_UNAM_CHUNK
: {
587 TRACE_(dmfile
)(": name chunk\n");
588 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
589 IStream_Read (pStm
, This
->pDesc
->wszName
, Chunk
.dwSize
, NULL
);
592 case mmioFOURCC('I','A','R','T'):
593 case DMUS_FOURCC_UART_CHUNK
: {
594 TRACE_(dmfile
)(": artist chunk (ignored)\n");
595 liMove
.QuadPart
= Chunk
.dwSize
;
596 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
599 case mmioFOURCC('I','C','O','P'):
600 case DMUS_FOURCC_UCOP_CHUNK
: {
601 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
602 liMove
.QuadPart
= Chunk
.dwSize
;
603 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
606 case mmioFOURCC('I','S','B','J'):
607 case DMUS_FOURCC_USBJ_CHUNK
: {
608 TRACE_(dmfile
)(": subject chunk (ignored)\n");
609 liMove
.QuadPart
= Chunk
.dwSize
;
610 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
613 case mmioFOURCC('I','C','M','T'):
614 case DMUS_FOURCC_UCMT_CHUNK
: {
615 TRACE_(dmfile
)(": comment chunk (ignored)\n");
616 liMove
.QuadPart
= Chunk
.dwSize
;
617 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
621 TRACE_(dmfile
)(": unknown sub-chunk (irrevelant & skipping)\n");
622 liMove
.QuadPart
= Chunk
.dwSize
;
623 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
627 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
628 } while (ListCount
[0] < ListSize
[0]);
632 TRACE_(dmfile
)(": unknown (skipping)\n");
633 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
634 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
641 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
642 liMove
.QuadPart
= Chunk
.dwSize
;
643 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
647 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
648 } while (StreamCount
< StreamSize
);
652 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
653 liMove
.QuadPart
= StreamSize
;
654 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
658 TRACE_(dmfile
)(": reading finished\n");
662 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
663 liMove
.QuadPart
= Chunk
.dwSize
;
664 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
672 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
) {
676 static HRESULT WINAPI
IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
) {
680 static const IPersistStreamVtbl DirectMusicScript_PersistStream_Vtbl
= {
681 IDirectMusicScriptImpl_IPersistStream_QueryInterface
,
682 IDirectMusicScriptImpl_IPersistStream_AddRef
,
683 IDirectMusicScriptImpl_IPersistStream_Release
,
684 IDirectMusicScriptImpl_IPersistStream_GetClassID
,
685 IDirectMusicScriptImpl_IPersistStream_IsDirty
,
686 IDirectMusicScriptImpl_IPersistStream_Load
,
687 IDirectMusicScriptImpl_IPersistStream_Save
,
688 IDirectMusicScriptImpl_IPersistStream_GetSizeMax
691 /* for ClassFactory */
692 HRESULT WINAPI
DMUSIC_CreateDirectMusicScriptImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
693 IDirectMusicScriptImpl
* obj
;
695 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicScriptImpl
));
698 return E_OUTOFMEMORY
;
700 obj
->UnknownVtbl
= &DirectMusicScript_Unknown_Vtbl
;
701 obj
->ScriptVtbl
= &DirectMusicScript_Script_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
;
708 obj
->ref
= 0; /* will be inited by QueryInterface */
710 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&obj
->UnknownVtbl
, lpcGUID
, ppobj
);