Report win2k service pack 4 instead of 3.
[wine/multimedia.git] / dlls / dmscript / script.c
blobce676bbb0a7e0e3fc7aab59726cc7a2ce2b4629e
1 /* IDirectMusicScript
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.
21 #include "config.h"
22 #include "wine/port.h"
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
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);
45 return S_OK;
46 } else if (IsEqualIID (riid, &IID_IDirectMusicScript)) {
47 *ppobj = (LPVOID)&This->ScriptVtbl;
48 IDirectMusicScriptImpl_IDirectMusicScript_AddRef ((LPDIRECTMUSICSCRIPT)&This->ScriptVtbl);
49 return S_OK;
50 } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
51 *ppobj = (LPVOID)&This->ObjectVtbl;
52 IDirectMusicScriptImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);
53 return S_OK;
54 } else if (IsEqualIID (riid, &IID_IPersistStream)) {
55 *ppobj = (LPVOID)&This->PersistStreamVtbl;
56 IDirectMusicScriptImpl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);
57 return S_OK;
60 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
61 return E_NOINTERFACE;
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);
67 return ++(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);
74 if (ref == 0) {
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);
81 return ref;
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;
111 return S_OK;
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;*/
118 return S_OK;
119 /*return E_FAIL;*/
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);
125 return S_OK;
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);
131 return S_OK;
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);
137 return S_OK;
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);
143 return S_OK;
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);
149 return S_OK;
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);
155 return S_OK;
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);
161 return S_OK;
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);
167 return S_OK;
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);
208 return S_OK;
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);
239 /* add new flags */
240 This->pDesc->dwValidData |= pDesc->dwValidData;
242 return S_OK;
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) {
260 case FOURCC_RIFF: {
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);
264 StreamCount = 0;
265 if (Chunk.fccID == DMUS_FOURCC_SCRIPT_FORM) {
266 TRACE_(dmfile)(": script form\n");
267 do {
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);
276 break;
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);
282 break;
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);
288 break;
290 case FOURCC_LIST: {
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);
294 ListCount[0] = 0;
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");
299 do {
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);
311 break;
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);
318 break;
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);
325 break;
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);
332 break;
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);
339 break;
341 default: {
342 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
343 liMove.QuadPart = Chunk.dwSize;
344 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
345 break;
348 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
349 } while (ListCount[0] < ListSize[0]);
350 break;
352 default: {
353 TRACE_(dmfile)(": unknown (skipping)\n");
354 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
355 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
356 break;
359 break;
361 default: {
362 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
363 liMove.QuadPart = Chunk.dwSize;
364 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
365 break;
368 TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
369 } while (StreamCount < StreamSize);
370 break;
371 } else {
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 */
375 return E_FAIL;
378 TRACE_(dmfile)(": reading finished\n");
379 break;
381 default: {
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));
391 return S_OK;
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));
424 return S_OK;
427 HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
428 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
429 FIXME("(%p): stub, always S_FALSE\n", This);
430 return S_FALSE;
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) {
446 case FOURCC_RIFF: {
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);
450 StreamCount = 0;
451 switch (Chunk.fccID) {
452 case DMUS_FOURCC_SCRIPT_FORM: {
453 TRACE_(dmfile)(": script form\n");
454 do {
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);
463 break;
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);
470 break;
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));
477 break;
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);
487 str[count-1] = '\n';
488 TRACE("source:\n");
489 write( 2, str, count );
490 HeapFree(GetProcessHeap(), 0, str);
492 break;
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);
498 break;
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);
504 break;
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);
510 break;
512 case FOURCC_RIFF: {
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;
520 desc.pStream = NULL;
521 IStream_Clone (pStm, &desc.pStream);
523 liMove.QuadPart = 0;
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);
533 } else {
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);
546 ListCount[0] = 0;
548 switch (Chunk.fccID) {
549 default: {
550 TRACE_(dmfile)(": unknown (skipping)\n");
551 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
552 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
553 break;
557 break;
559 case FOURCC_LIST: {
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);
563 ListCount[0] = 0;
564 switch (Chunk.fccID) {
565 case DMUS_FOURCC_UNFO_LIST: {
566 TRACE_(dmfile)(": UNFO list\n");
567 do {
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);
579 break;
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);
586 break;
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);
593 break;
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);
600 break;
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);
607 break;
609 default: {
610 TRACE_(dmfile)(": unknown sub-chunk (irrevelant & skipping)\n");
611 liMove.QuadPart = Chunk.dwSize;
612 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
613 break;
616 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
617 } while (ListCount[0] < ListSize[0]);
618 break;
620 default: {
621 TRACE_(dmfile)(": unknown (skipping)\n");
622 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
623 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
624 break;
627 break;
629 default: {
630 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
631 liMove.QuadPart = Chunk.dwSize;
632 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
633 break;
636 TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
637 } while (StreamCount < StreamSize);
638 break;
640 default: {
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 */
644 return E_FAIL;
647 TRACE_(dmfile)(": reading finished\n");
648 break;
650 default: {
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 */
654 return E_FAIL;
658 return S_OK;
661 HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
662 return E_NOTIMPL;
665 HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
666 return E_NOTIMPL;
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));
686 if (NULL == obj) {
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);