ReactOS 0.4.17-dev-934-g091855f
container.c
Go to the documentation of this file.
1/* IDirectMusicContainerImpl
2 *
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20#include "dmloader_private.h"
21
24
25#define DMUS_MAX_CATEGORY_SIZE DMUS_MAX_CATEGORY*sizeof(WCHAR)
26#define DMUS_MAX_NAME_SIZE DMUS_MAX_NAME*sizeof(WCHAR)
27#define DMUS_MAX_FILENAME_SIZE DMUS_MAX_FILENAME*sizeof(WCHAR)
28
29typedef struct riff_chunk {
33
34/* contained object entry */
35typedef struct container_entry {
36 struct list entry;
39 DWORD dwFlags; /* DMUS_CONTAINED_OBJF_KEEP: keep object in loader's cache, even when container is released */
41 IDirectMusicObject *pObject; /* needed when releasing from loader's cache on container release */
43
44/*****************************************************************************
45 * IDirectMusicContainerImpl implementation
46 */
48 IDirectMusicContainer IDirectMusicContainer_iface;
53 struct list *pContainedObjects; /* data */
55
56static inline IDirectMusicContainerImpl *impl_from_IDirectMusicContainer(IDirectMusicContainer *iface)
57{
58 return CONTAINING_RECORD(iface, IDirectMusicContainerImpl, IDirectMusicContainer_iface);
59}
60
62{
63 LPDIRECTMUSICLOADER pLoader;
64 LPDIRECTMUSICGETLOADER pGetLoader;
65 struct list *pEntry;
66 LPWINE_CONTAINER_ENTRY pContainedObject;
67
68 /* get loader (from stream we loaded from) */
69 TRACE(": getting loader\n");
70 IStream_QueryInterface (This->pStream, &IID_IDirectMusicGetLoader, (LPVOID*)&pGetLoader);
71 IDirectMusicGetLoader_GetLoader (pGetLoader, &pLoader);
73
74 /* release objects from loader's cache (if appropriate) */
75 TRACE(": releasing objects from loader's cache\n");
76 LIST_FOR_EACH (pEntry, This->pContainedObjects) {
77 pContainedObject = LIST_ENTRY (pEntry, WINE_CONTAINER_ENTRY, entry);
78 /* my tests indicate that container releases objects *only*
79 if they were loaded at its load-time (makes sense, it doesn't
80 have pointers to objects otherwise); BTW: native container seems
81 to ignore the flags (I won't) */
82 if (pContainedObject->pObject && !(pContainedObject->dwFlags & DMUS_CONTAINED_OBJF_KEEP)) {
83 /* flags say it shouldn't be kept in loader's cache */
84 IDirectMusicLoader_ReleaseObject (pLoader, pContainedObject->pObject);
85 }
86 }
88
89 /* release stream we loaded from */
90 IStream_Release (This->pStream);
91
92 /* FIXME: release allocated entries */
93
94 return S_OK;
95}
96
97static HRESULT WINAPI IDirectMusicContainerImpl_QueryInterface(IDirectMusicContainer *iface, REFIID riid, void **ret_iface)
98{
100
101 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
102
103 if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDirectMusicContainer))
104 *ret_iface = &This->IDirectMusicContainer_iface;
105 else if (IsEqualIID (riid, &IID_IDirectMusicObject))
106 *ret_iface = &This->dmobj.IDirectMusicObject_iface;
108 *ret_iface = &This->dmobj.IPersistStream_iface;
109 else {
110 WARN("Unknown interface %s\n", debugstr_dmguid(riid));
111 *ret_iface = NULL;
112 return E_NOINTERFACE;
113 }
114
115 IUnknown_AddRef((IUnknown*)*ret_iface);
116 return S_OK;
117}
118
119static ULONG WINAPI IDirectMusicContainerImpl_AddRef(IDirectMusicContainer *iface)
120{
123
124 TRACE("(%p) ref=%ld\n", This, ref);
125
126 return ref;
127}
128
129static ULONG WINAPI IDirectMusicContainerImpl_Release(IDirectMusicContainer *iface)
130{
133
134 TRACE("(%p) ref=%ld\n", This, ref);
135
136 if (!ref) {
137 if (This->pStream)
139 free(This);
140 }
141
142 return ref;
143}
144
145static HRESULT WINAPI IDirectMusicContainerImpl_EnumObject(IDirectMusicContainer *iface,
146 REFGUID rguidClass, DWORD dwIndex, DMUS_OBJECTDESC *pDesc, WCHAR *pwszAlias)
147{
149 struct list *pEntry;
150 LPWINE_CONTAINER_ENTRY pContainedObject;
151 DWORD dwCount = 0;
152
153 TRACE("(%p, %s, %ld, %p, %p)\n", This, debugstr_dmguid(rguidClass), dwIndex, pDesc, pwszAlias);
154
155 if (!pDesc)
156 return E_POINTER;
157 if (pDesc->dwSize != sizeof(DMUS_OBJECTDESC)) {
158 ERR(": invalid pDesc->dwSize %ld\n", pDesc->dwSize);
159 return E_INVALIDARG;
160 }
161
162 DM_STRUCT_INIT(pDesc);
163
164 LIST_FOR_EACH (pEntry, This->pContainedObjects) {
165 pContainedObject = LIST_ENTRY (pEntry, WINE_CONTAINER_ENTRY, entry);
166
167 if (IsEqualGUID (rguidClass, &GUID_DirectMusicAllTypes) || IsEqualGUID (rguidClass, &pContainedObject->Desc.guidClass)) {
168 if (dwCount == dwIndex) {
170 if (pwszAlias) {
171 lstrcpynW (pwszAlias, pContainedObject->wszAlias, DMUS_MAX_FILENAME);
172 if (lstrlenW (pContainedObject->wszAlias) > DMUS_MAX_FILENAME)
174 }
175 *pDesc = pContainedObject->Desc;
176 return result;
177 }
178 dwCount++;
179 }
180 }
181
182 TRACE(": not found\n");
183 return S_FALSE;
184}
185
186static const IDirectMusicContainerVtbl dmcontainer_vtbl = {
191};
192
193/* IDirectMusicObject part: */
196{
197 struct chunk_entry riff = {0};
198 HRESULT hr;
199
200 TRACE("(%p, %p, %p)\n", iface, stream, desc);
201
202 if (!stream)
203 return E_POINTER;
204 if (!desc || desc->dwSize != sizeof(*desc))
205 return E_INVALIDARG;
206
207 if ((hr = stream_get_chunk(stream, &riff)) != S_OK)
208 return hr;
209 if (riff.id != FOURCC_RIFF || riff.type != DMUS_FOURCC_CONTAINER_FORM) {
210 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff));
213 }
214
217 if (FAILED(hr))
218 return hr;
219
220 desc->guidClass = CLSID_DirectMusicContainer;
221 desc->dwValidData |= DMUS_OBJ_CLASS;
222
223 TRACE("returning descriptor:\n");
225 return S_OK;
226}
227
228static const IDirectMusicObjectVtbl dmobject_vtbl = {
235};
236
237/* IPersistStream part: */
239{
240 return CONTAINING_RECORD(iface, IDirectMusicContainerImpl, dmobj.IPersistStream_iface);
241}
242
244{
246 WINE_CHUNK Chunk;
247 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
248 LARGE_INTEGER liMove; /* used when skipping chunks */
249 ULARGE_INTEGER uliPos; /* needed when dealing with RIFF chunks */
250 LPDIRECTMUSICGETLOADER pGetLoader;
251 LPDIRECTMUSICLOADER pLoader;
253
254 TRACE("(%p, %p):\n", This, pStm);
255
256 /* check whether pStm is valid read pointer */
257 if (IsBadReadPtr (pStm, sizeof(LPVOID))) {
258 ERR(": pStm bad read pointer\n");
259 return E_POINTER;
260 }
261 /* if stream is already set, this means the container is already loaded */
262 if (This->pStream) {
263 TRACE(": stream is already set, which means container is already loaded\n");
265 }
266
267 /* get loader since it will be needed later */
268 if (FAILED(IStream_QueryInterface (pStm, &IID_IDirectMusicGetLoader, (LPVOID*)&pGetLoader))) {
269 ERR(": stream not supported\n");
271 }
272 IDirectMusicGetLoader_GetLoader (pGetLoader, &pLoader);
274
275 This->pStream = pStm;
276 IStream_AddRef (pStm); /* add count for later references */
277
278 /* start with load */
279 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
280 TRACE_(dmfile)(": %s chunk (size = %#lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
281 switch (Chunk.fccID) {
282 case FOURCC_RIFF: {
283 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
284 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
285 StreamSize = Chunk.dwSize - sizeof(FOURCC);
286 StreamCount = 0;
287 switch (Chunk.fccID) {
289 TRACE_(dmfile)(": container form\n");
290 This->dmobj.desc.guidClass = CLSID_DirectMusicContainer;
291 This->dmobj.desc.dwValidData |= DMUS_OBJ_CLASS;
292 do {
293 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
294 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
295 TRACE_(dmfile)(": %s chunk (size = %#lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
296 switch (Chunk.fccID) {
298 IStream_Read (pStm, &This->Header, Chunk.dwSize, NULL);
299 TRACE_(dmfile)(": container header chunk:\n%s\n", debugstr_DMUS_IO_CONTAINER_HEADER(&This->Header));
300 break;
301 }
303 TRACE_(dmfile)(": GUID chunk\n");
304 IStream_Read (pStm, &This->dmobj.desc.guidObject, Chunk.dwSize, NULL);
305 This->dmobj.desc.dwValidData |= DMUS_OBJ_OBJECT;
306 break;
307 }
309 TRACE_(dmfile)(": version chunk\n");
310 IStream_Read (pStm, &This->dmobj.desc.vVersion, Chunk.dwSize, NULL);
311 This->dmobj.desc.dwValidData |= DMUS_OBJ_VERSION;
312 break;
313 }
315 TRACE_(dmfile)(": date chunk\n");
316 IStream_Read (pStm, &This->dmobj.desc.ftDate, Chunk.dwSize, NULL);
317 This->dmobj.desc.dwValidData |= DMUS_OBJ_DATE;
318 break;
319 }
321 TRACE_(dmfile)(": category chunk\n");
322 /* if it happens that string is too long,
323 read what we can and skip the rest*/
324 if (Chunk.dwSize > DMUS_MAX_CATEGORY_SIZE) {
325 IStream_Read (pStm, This->dmobj.desc.wszCategory, DMUS_MAX_CATEGORY_SIZE, NULL);
326 liMove.QuadPart = Chunk.dwSize - DMUS_MAX_CATEGORY_SIZE;
327 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
328 } else {
329 IStream_Read (pStm, This->dmobj.desc.wszCategory, Chunk.dwSize, NULL);
330 }
331 This->dmobj.desc.dwValidData |= DMUS_OBJ_CATEGORY;
332 break;
333 }
334 case FOURCC_LIST: {
335 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
336 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
337 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
338 ListCount[0] = 0;
339 switch (Chunk.fccID) {
341 TRACE_(dmfile)(": UNFO list\n");
342 do {
343 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
344 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
345 TRACE_(dmfile)(": %s chunk (size = %#lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
346 switch (Chunk.fccID) {
347 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
348 (though strings seem to be valid unicode) */
349 case mmioFOURCC('I','N','A','M'):
351 TRACE_(dmfile)(": name chunk\n");
352 /* if it happens that string is too long,
353 read what we can and skip the rest*/
354 if (Chunk.dwSize > DMUS_MAX_NAME_SIZE) {
355 IStream_Read (pStm, This->dmobj.desc.wszName, DMUS_MAX_NAME_SIZE, NULL);
356 liMove.QuadPart = Chunk.dwSize - DMUS_MAX_NAME_SIZE;
357 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
358 } else {
359 IStream_Read (pStm, This->dmobj.desc.wszName, Chunk.dwSize, NULL);
360 }
361 This->dmobj.desc.dwValidData |= DMUS_OBJ_NAME;
362 break;
363 }
364 default: {
365 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
366 liMove.QuadPart = Chunk.dwSize;
367 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
368 break;
369 }
370 }
371 TRACE_(dmfile)(": ListCount[0] = %#lx < ListSize[0] = %#lx\n", ListCount[0], ListSize[0]);
372 } while (ListCount[0] < ListSize[0]);
373 break;
374 }
376 TRACE_(dmfile)(": contained objects list\n");
377 do {
378 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
379 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
380 TRACE_(dmfile)(": %s chunk (size = %#lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
381 switch (Chunk.fccID) {
382 case FOURCC_LIST: {
383 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
384 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
385 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
386 ListCount[1] = 0;
387 switch (Chunk.fccID) {
389 LPWINE_CONTAINER_ENTRY pNewEntry;
390 TRACE_(dmfile)(": contained object list\n");
391 pNewEntry = calloc(1, sizeof(*pNewEntry));
392 DM_STRUCT_INIT(&pNewEntry->Desc);
393 do {
394 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
395 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
396 TRACE_(dmfile)(": %s chunk (size = %#lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
397 switch (Chunk.fccID) {
399 TRACE_(dmfile)(": alias chunk\n");
400 pNewEntry->wszAlias = calloc(1, Chunk.dwSize);
401 IStream_Read (pStm, pNewEntry->wszAlias, Chunk.dwSize, NULL);
402 TRACE_(dmfile)(": alias: %s\n", debugstr_w(pNewEntry->wszAlias));
403 break;
404 }
406 DMUS_IO_CONTAINED_OBJECT_HEADER tmpObjectHeader;
407 IStream_Read (pStm, &tmpObjectHeader, Chunk.dwSize, NULL);
408 TRACE_(dmfile)(": contained object header:\n%s\n", debugstr_DMUS_IO_CONTAINED_OBJECT_HEADER(&tmpObjectHeader));
409 /* copy guidClass */
410 pNewEntry->Desc.dwValidData |= DMUS_OBJ_CLASS;
411 pNewEntry->Desc.guidClass = tmpObjectHeader.guidClassID;
412 /* store flags */
413 pNewEntry->dwFlags = tmpObjectHeader.dwFlags;
414 break;
415 }
416 /* now read data... it may be safe to read everything after object header chunk,
417 but I'm not comfortable with MSDN's "the header is *normally* followed by ..." */
418 case FOURCC_LIST: {
419 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
420 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
421 ListSize[2] = Chunk.dwSize - sizeof(FOURCC);
422 ListCount[2] = 0;
423 switch (Chunk.fccID) {
425 TRACE_(dmfile)(": reference list\n");
426 pNewEntry->bIsRIFF = 0;
427 do {
428 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
429 ListCount[2] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
430 TRACE_(dmfile)(": %s chunk (size = %#lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
431 switch (Chunk.fccID) {
433 DMUS_IO_REFERENCE tmpReferenceHeader; /* temporary structure */
434 TRACE_(dmfile)(": reference header chunk\n");
435 memset (&tmpReferenceHeader, 0, sizeof(DMUS_IO_REFERENCE));
436 IStream_Read (pStm, &tmpReferenceHeader, Chunk.dwSize, NULL);
437 /* copy retrieved data to DMUS_OBJECTDESC */
438 if (!IsEqualCLSID (&pNewEntry->Desc.guidClass, &tmpReferenceHeader.guidClassID)) ERR(": object header declares different CLSID than reference header?\n");
439 /* it shouldn't be necessary to copy guidClass, since it was set in contained object header already...
440 yet if they happen to be different, I'd rather stick to this one */
441 pNewEntry->Desc.guidClass = tmpReferenceHeader.guidClassID;
442 pNewEntry->Desc.dwValidData |= tmpReferenceHeader.dwValidData;
443 break;
444 }
446 TRACE_(dmfile)(": guid chunk\n");
447 /* no need to set flags since they were copied from reference header */
448 IStream_Read (pStm, &pNewEntry->Desc.guidObject, Chunk.dwSize, NULL);
449 break;
450 }
452 TRACE_(dmfile)(": file date chunk\n");
453 /* no need to set flags since they were copied from reference header */
454 IStream_Read (pStm, &pNewEntry->Desc.ftDate, Chunk.dwSize, NULL);
455 break;
456 }
458 TRACE_(dmfile)(": name chunk\n");
459 /* no need to set flags since they were copied from reference header */
460 IStream_Read (pStm, pNewEntry->Desc.wszName, Chunk.dwSize, NULL);
461 break;
462 }
464 TRACE_(dmfile)(": file name chunk\n");
465 /* no need to set flags since they were copied from reference header */
466 IStream_Read (pStm, pNewEntry->Desc.wszFileName, Chunk.dwSize, NULL);
467 break;
468 }
470 TRACE_(dmfile)(": category chunk\n");
471 /* no need to set flags since they were copied from reference header */
472 IStream_Read (pStm, pNewEntry->Desc.wszCategory, Chunk.dwSize, NULL);
473 break;
474 }
476 TRACE_(dmfile)(": version chunk\n");
477 /* no need to set flags since they were copied from reference header */
478 IStream_Read (pStm, &pNewEntry->Desc.vVersion, Chunk.dwSize, NULL);
479 break;
480 }
481 default: {
482 TRACE_(dmfile)(": unknown chunk (skipping)\n");
483 liMove.QuadPart = Chunk.dwSize;
484 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip this chunk */
485 break;
486 }
487 }
488 TRACE_(dmfile)(": ListCount[2] = %#lx < ListSize[2] = %#lx\n", ListCount[2], ListSize[2]);
489 } while (ListCount[2] < ListSize[2]);
490 break;
491 }
492 default: {
493 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
494 return E_FAIL;
495 }
496 }
497 break;
498 }
499
500 case FOURCC_RIFF: {
501 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
502 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
503 if (IS_VALID_DMFORM (Chunk.fccID)) {
504 TRACE_(dmfile)(": valid DMUSIC form\n");
505 pNewEntry->bIsRIFF = 1;
506 /* we'll have to skip whole RIFF chunk after SetObject is called */
507 liMove.QuadPart = 0;
508 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &uliPos);
509 uliPos.QuadPart += (Chunk.dwSize - sizeof(FOURCC)); /* set uliPos at the end of RIFF chunk */
510 /* move at the beginning of RIFF chunk */
511 liMove.QuadPart = 0;
512 liMove.QuadPart -= (sizeof(FOURCC)+sizeof(DWORD)+sizeof(FOURCC));
513 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
514 /* put pointer to stream in descriptor */
515 pNewEntry->Desc.dwValidData |= DMUS_OBJ_STREAM;
516 pNewEntry->Desc.pStream = pStm; /* we don't have to worry about cloning, since SetObject will perform it */
517 /* wait till we get on the end of object list */
518 } else {
519 TRACE_(dmfile)(": invalid DMUSIC form (skipping)\n");
520 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
521 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
522 /* FIXME: should we return E_FAIL? */
523 }
524 break;
525 }
526 default: {
527 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
528 liMove.QuadPart = Chunk.dwSize;
529 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
530 break;
531 }
532 }
533 TRACE_(dmfile)(": ListCount[1] = %#lx < ListSize[1] = %#lx\n", ListCount[1], ListSize[1]);
534 } while (ListCount[1] < ListSize[1]);
535 /* SetObject: this will fill descriptor with additional info and add alias in loader's cache */
536 IDirectMusicLoader_SetObject (pLoader, &pNewEntry->Desc);
537 /* now that SetObject collected appropriate info into descriptor we can live happily ever after;
538 or not, since we have to clean evidence of loading through stream... *sigh*
539 and we have to skip rest of the chunk, if we loaded through RIFF */
540 if (pNewEntry->bIsRIFF) {
541 liMove.QuadPart = uliPos.QuadPart;
542 IStream_Seek (pStm, liMove, STREAM_SEEK_SET, NULL);
543 pNewEntry->Desc.dwValidData &= ~DMUS_OBJ_STREAM; /* clear flag (and with bitwise complement) */
544 pNewEntry->Desc.pStream = NULL;
545 }
546 /* add entry to list of objects */
547 list_add_tail (This->pContainedObjects, &pNewEntry->entry);
548 break;
549 }
550 default: {
551 TRACE_(dmfile)(": unknown (skipping)\n");
552 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
553 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
554 break;
555 }
556 }
557 break;
558 }
559 default: {
560 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
561 liMove.QuadPart = Chunk.dwSize;
562 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
563 break;
564 }
565 }
566 TRACE_(dmfile)(": ListCount[0] = %#lx < ListSize[0] = %#lx\n", ListCount[0], ListSize[0]);
567 } while (ListCount[0] < ListSize[0]);
568 break;
569 }
570 default: {
571 TRACE_(dmfile)(": unknown (skipping)\n");
572 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
573 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
574 break;
575 }
576 }
577 break;
578 }
579 default: {
580 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
581 liMove.QuadPart = Chunk.dwSize;
582 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
583 break;
584 }
585 }
586 TRACE_(dmfile)(": StreamCount[0] = %#lx < StreamSize[0] = %#lx\n", StreamCount, StreamSize);
587 } while (StreamCount < StreamSize);
588 break;
589 }
590 default: {
591 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
592 liMove.QuadPart = StreamSize;
593 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
594 return E_FAIL;
595 }
596 }
597 TRACE_(dmfile)(": reading finished\n");
598 This->dmobj.desc.dwValidData |= DMUS_OBJ_LOADED;
599 dump_DMUS_OBJECTDESC(&This->dmobj.desc);
600 break;
601 }
602 default: {
603 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
604 liMove.QuadPart = Chunk.dwSize;
605 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
606 return E_FAIL;
607 }
608 }
609
610 /* now, if DMUS_CONTAINER_NOLOADS is not set, we are supposed to load contained objects;
611 so when we call GetObject later, they'll already be in cache */
612 if (!(This->Header.dwFlags & DMUS_CONTAINER_NOLOADS)) {
613 struct list *pEntry;
614 LPWINE_CONTAINER_ENTRY pContainedObject;
615
616 TRACE(": DMUS_CONTAINER_NOLOADS not set... load all objects\n");
617
618 LIST_FOR_EACH (pEntry, This->pContainedObjects) {
619 IDirectMusicObject* pObject;
620 pContainedObject = LIST_ENTRY (pEntry, WINE_CONTAINER_ENTRY, entry);
621 /* get object from loader and then release it */
622 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader, &pContainedObject->Desc, &IID_IDirectMusicObject, (LPVOID*)&pObject))) {
623 pContainedObject->pObject = pObject; /* for final release */
624 IDirectMusicObject_Release (pObject); /* we don't really need this one */
625 } else {
626 WARN(": failed to load contained object\n");
628 }
629 }
630 }
631
632 IDirectMusicLoader_Release (pLoader); /* release loader */
633
634 return result;
635}
636
637static const IPersistStreamVtbl persiststream_vtbl = {
646};
647
648/* for ClassFactory */
649HRESULT create_dmcontainer(REFIID lpcGUID, void **ppobj)
650{
652 HRESULT hr;
653
654 *ppobj = NULL;
655 if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
656 obj->IDirectMusicContainer_iface.lpVtbl = &dmcontainer_vtbl;
657 obj->ref = 1;
658 dmobject_init(&obj->dmobj, &CLSID_DirectMusicContainer,
659 (IUnknown*)&obj->IDirectMusicContainer_iface);
660 obj->dmobj.IDirectMusicObject_iface.lpVtbl = &dmobject_vtbl;
661 obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
662 obj->pContainedObjects = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(struct list));
663 list_init (obj->pContainedObjects);
664
665 hr = IDirectMusicContainer_QueryInterface(&obj->IDirectMusicContainer_iface, lpcGUID, ppobj);
666 IDirectMusicContainer_Release(&obj->IDirectMusicContainer_iface);
667
668 return hr;
669}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_init(struct list_entry *head)
Definition: list.h:51
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
Definition: list.h:39
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
static HRESULT destroy_dmcontainer(IDirectMusicContainerImpl *This)
Definition: container.c:61
#define DMUS_MAX_NAME_SIZE
Definition: container.c:26
static IDirectMusicContainerImpl * impl_from_IPersistStream(IPersistStream *iface)
Definition: container.c:238
#define DMUS_MAX_CATEGORY_SIZE
Definition: container.c:25
struct container_entry * LPWINE_CONTAINER_ENTRY
static const IDirectMusicContainerVtbl dmcontainer_vtbl
Definition: container.c:186
static HRESULT WINAPI IDirectMusicContainerImpl_EnumObject(IDirectMusicContainer *iface, REFGUID rguidClass, DWORD dwIndex, DMUS_OBJECTDESC *pDesc, WCHAR *pwszAlias)
Definition: container.c:145
static const IDirectMusicObjectVtbl dmobject_vtbl
Definition: container.c:228
struct container_entry WINE_CONTAINER_ENTRY
static HRESULT WINAPI IDirectMusicContainerImpl_QueryInterface(IDirectMusicContainer *iface, REFIID riid, void **ret_iface)
Definition: container.c:97
static const IPersistStreamVtbl persiststream_vtbl
Definition: container.c:637
static ULONG WINAPI IDirectMusicContainerImpl_AddRef(IDirectMusicContainer *iface)
Definition: container.c:119
struct riff_chunk WINE_CHUNK
static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
Definition: container.c:243
HRESULT create_dmcontainer(REFIID lpcGUID, void **ppobj)
Definition: container.c:649
static HRESULT WINAPI cont_IDirectMusicObject_ParseDescriptor(IDirectMusicObject *iface, IStream *stream, DMUS_OBJECTDESC *desc)
Definition: container.c:194
static IDirectMusicContainerImpl * impl_from_IDirectMusicContainer(IDirectMusicContainer *iface)
Definition: container.c:56
static ULONG WINAPI IDirectMusicContainerImpl_Release(IDirectMusicContainer *iface)
Definition: container.c:129
BOOL IS_VALID_DMFORM(FOURCC chunkID)
Definition: debug.c:24
const char * debugstr_DMUS_IO_CONTAINER_HEADER(LPDMUS_IO_CONTAINER_HEADER pHeader)
Definition: debug.c:46
const char * debugstr_DMUS_IO_CONTAINED_OBJECT_HEADER(LPDMUS_IO_CONTAINED_OBJECT_HEADER pHeader)
Definition: debug.c:60
#define DM_STRUCT_INIT(x)
Definition: debug.h:30
#define GetProcessHeap()
Definition: compat.h:736
#define TRACE_(x)
Definition: compat.h:76
#define HeapAlloc
Definition: compat.h:733
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:805
DWORD FOURCC
Definition: dmdls.h:25
#define DMUS_E_UNSUPPORTED_STREAM
Definition: dmerror.h:100
#define DMUS_E_DESCEND_CHUNK_FAIL
Definition: dmerror.h:132
#define DMUS_S_STRING_TRUNCATED
Definition: dmerror.h:45
#define DMUS_E_ALREADY_LOADED
Definition: dmerror.h:61
#define DMUS_S_PARTIALLOAD
Definition: dmerror.h:40
HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface, DMUS_OBJECTDESC *desc)
Definition: dmobject.c:503
void dmobject_init(struct dmobject *dmobj, const GUID *class, IUnknown *outer_unk)
Definition: dmobject.c:749
ULONG WINAPI dmobj_IPersistStream_Release(IPersistStream *iface)
Definition: dmobject.c:702
ULONG WINAPI dmobj_IDirectMusicObject_Release(IDirectMusicObject *iface)
Definition: dmobject.c:497
HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff, DMUS_OBJECTDESC *desc, DWORD supported)
Definition: dmobject.c:591
HRESULT WINAPI dmobj_IDirectMusicObject_QueryInterface(IDirectMusicObject *iface, REFIID riid, void **ret_iface)
Definition: dmobject.c:484
HRESULT WINAPI unimpl_IPersistStream_GetSizeMax(IPersistStream *iface, ULARGE_INTEGER *size)
Definition: dmobject.c:742
HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface, DMUS_OBJECTDESC *desc)
Definition: dmobject.c:518
void dump_DMUS_OBJECTDESC(DMUS_OBJECTDESC *desc)
Definition: dmobject.c:222
const char * debugstr_chunk(const struct chunk_entry *chunk)
Definition: dmobject.c:279
HRESULT WINAPI dmobj_IPersistStream_GetClassID(IPersistStream *iface, CLSID *class)
Definition: dmobject.c:708
ULONG WINAPI dmobj_IPersistStream_AddRef(IPersistStream *iface)
Definition: dmobject.c:696
const char * debugstr_dmguid(const GUID *id)
Definition: dmobject.c:36
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid, void **ret_iface)
Definition: dmobject.c:689
ULONG WINAPI dmobj_IDirectMusicObject_AddRef(IDirectMusicObject *iface)
Definition: dmobject.c:491
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
Definition: dmobject.c:351
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
Definition: dmobject.c:307
HRESULT WINAPI unimpl_IPersistStream_IsDirty(IPersistStream *iface)
Definition: dmobject.c:729
HRESULT WINAPI unimpl_IPersistStream_Save(IPersistStream *iface, IStream *stream, BOOL clear_dirty)
Definition: dmobject.c:735
#define DMUS_FOURCC_CONTAINED_ALIAS_CHUNK
Definition: dmusicf.h:87
#define DMUS_FOURCC_CONTAINED_OBJECT_LIST
Definition: dmusicf.h:90
#define DMUS_FOURCC_GUID_CHUNK
Definition: dmusicf.h:42
#define DMUS_FOURCC_CONTAINER_CHUNK
Definition: dmusicf.h:86
#define DMUS_FOURCC_REF_CHUNK
Definition: dmusicf.h:103
#define DMUS_FOURCC_UNAM_CHUNK
Definition: dmusicf.h:45
#define DMUS_FOURCC_VERSION_CHUNK
Definition: dmusicf.h:51
#define DMUS_CONTAINER_NOLOADS
Definition: dmusicf.h:235
#define DMUS_FOURCC_CONTAINER_FORM
Definition: dmusicf.h:85
#define DMUS_FOURCC_REF_LIST
Definition: dmusicf.h:102
#define DMUS_FOURCC_FILE_CHUNK
Definition: dmusicf.h:106
#define DMUS_FOURCC_NAME_CHUNK
Definition: dmusicf.h:105
#define DMUS_FOURCC_DATE_CHUNK
Definition: dmusicf.h:104
#define DMUS_CONTAINED_OBJF_KEEP
Definition: dmusicf.h:233
#define DMUS_FOURCC_CONTAINED_OBJECTS_LIST
Definition: dmusicf.h:89
#define DMUS_FOURCC_UNFO_LIST
Definition: dmusicf.h:44
#define DMUS_FOURCC_CONTAINED_OBJECT_CHUNK
Definition: dmusicf.h:88
#define DMUS_FOURCC_CATEGORY_CHUNK
Definition: dmusicf.h:50
#define DMUS_OBJ_DATE
Definition: dmusici.h:273
#define IDirectMusicGetLoader_GetLoader(p, a)
Definition: dmusici.h:963
#define IDirectMusicObject_Release(p)
Definition: dmusici.h:844
#define IDirectMusicLoader_Release(p)
Definition: dmusici.h:879
struct IDirectMusicGetLoader * LPDIRECTMUSICGETLOADER
Definition: dmusici.h:124
#define DMUS_OBJ_NAME
Definition: dmusici.h:267
#define DMUS_OBJ_STREAM
Definition: dmusici.h:276
#define IDirectMusicLoader_SetObject(p, a)
Definition: dmusici.h:882
#define IDirectMusicLoader_ReleaseObject(p, a)
Definition: dmusici.h:886
#define DMUS_OBJ_CLASS
Definition: dmusici.h:266
#define IDirectMusicContainer_Release(p)
Definition: dmusici.h:1726
#define IDirectMusicGetLoader_Release(p)
Definition: dmusici.h:961
#define DMUS_MAX_FILENAME
Definition: dmusici.h:247
#define DMUS_OBJ_VERSION
Definition: dmusici.h:272
struct IDirectMusicLoader * LPDIRECTMUSICLOADER
Definition: dmusici.h:122
#define IDirectMusicLoader_GetObject(p, a, b, c)
Definition: dmusici.h:881
#define DMUS_OBJ_CATEGORY
Definition: dmusici.h:268
#define DMUS_OBJ_OBJECT
Definition: dmusici.h:265
#define IDirectMusicContainer_QueryInterface(p, a, b)
Definition: dmusici.h:1724
#define DMUS_OBJ_LOADED
Definition: dmusici.h:274
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
FxObject * pObject
GLuint64EXT * result
Definition: glext.h:11304
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_w
Definition: kernel32.h:32
#define FOURCC(a, b, c, d)
Definition: memtrack.h:4
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define FOURCC_LIST
Definition: mmsystem.h:565
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
D3D11_SHADER_VARIABLE_DESC desc
Definition: reflection.c:1683
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
const GUID IID_IPersistStream
Definition: proxy.cpp:13
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:96
#define calloc
Definition: rosglue.h:14
static __inline const char * debugstr_fourcc(unsigned int cc)
Definition: debug.h:397
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:226
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
IDirectMusicContainer IDirectMusicContainer_iface
Definition: container.c:48
struct list * pContainedObjects
Definition: container.c:53
DMUS_IO_CONTAINER_HEADER Header
Definition: container.c:52
struct dmobject dmobj
Definition: container.c:49
WCHAR wszCategory[DMUS_MAX_CATEGORY]
Definition: dmusici.h:749
DMUS_VERSION vVersion
Definition: dmusici.h:747
IStream * pStream
Definition: dmusici.h:753
FILETIME ftDate
Definition: dmusici.h:746
DWORD dwValidData
Definition: dmusici.h:743
WCHAR wszFileName[DMUS_MAX_FILENAME]
Definition: dmusici.h:750
WCHAR wszName[DMUS_MAX_NAME]
Definition: dmusici.h:748
Definition: scsiwmi.h:51
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: dmobject.h:26
FOURCC id
Definition: dmobject.h:27
FOURCC type
Definition: dmobject.h:29
Definition: container.c:35
WCHAR * wszAlias
Definition: container.c:40
DWORD dwFlags
Definition: container.c:39
IDirectMusicObject * pObject
Definition: container.c:41
struct list entry
Definition: container.c:36
DMUS_OBJECTDESC Desc
Definition: container.c:37
BOOL bIsRIFF
Definition: container.c:38
Definition: send.c:48
FOURCC fccID
Definition: container.c:30
DWORD dwSize
Definition: container.c:31
Definition: parse.h:23
#define LIST_ENTRY(type)
Definition: queue.h:175
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define E_NOINTERFACE
Definition: winerror.h:3479
#define E_POINTER
Definition: winerror.h:3480