Allow configuration of output devices to use and change standard
[wine] / dlls / dswave / dswave.c
1 /* IDirectMusicWave Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (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
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include "dswave_private.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(dswave);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
24                                                                                  
25 /* an interface that is, according to my tests, obtained by loader after loading object; is it acting
26    as some sort of bridge between object and loader? */
27 const GUID IID_IDirectMusicWavePRIVATE = {0x69e934e4,0x97f1,0x4f1d,{0x88,0xe8,0xf2,0xac,0x88,0x67,0x13,0x27}};
28
29 /*****************************************************************************
30  * IDirectMusicWaveImpl implementation
31  */
32 /* IDirectMusicWaveImpl IUnknown part: */
33 HRESULT WINAPI IDirectMusicWaveImpl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
34         ICOM_THIS_MULTI(IDirectMusicWaveImpl, UnknownVtbl, iface);
35         
36         TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
37
38         if (IsEqualIID (riid, &IID_IUnknown)) {
39                 *ppobj = (LPVOID)&This->UnknownVtbl;
40                 IDirectMusicWaveImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
41                 return S_OK;
42         } else if (IsEqualIID (riid, &IID_IDirectMusicSegment)
43         || IsEqualIID (riid, &IID_IDirectMusicSegment2)
44         || IsEqualIID (riid, &IID_IDirectMusicSegment8)) {
45                 *ppobj = (LPVOID)&This->SegmentVtbl;
46                 IDirectMusicWaveImpl_IDirectMusicSegment8_AddRef ((LPDIRECTMUSICSEGMENT8)&This->SegmentVtbl);
47                 return S_OK;
48         } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
49                 *ppobj = (LPVOID)&This->ObjectVtbl;
50                 IDirectMusicWaveImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);                
51                 return S_OK;
52         } else if (IsEqualIID (riid, &IID_IPersistStream)) {
53                 *ppobj = (LPVOID)&This->PersistStreamVtbl;
54                 IDirectMusicWaveImpl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);         
55                 return S_OK;
56         } else if (IsEqualIID (riid, &IID_IDirectMusicWavePRIVATE)) {
57                 WARN(": requested private interface, expect crash\n");
58                 return E_NOINTERFACE;
59         }
60         
61         WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
62         return E_NOINTERFACE;
63 }
64
65 ULONG WINAPI IDirectMusicWaveImpl_IUnknown_AddRef (LPUNKNOWN iface) {
66         ICOM_THIS_MULTI(IDirectMusicWaveImpl, UnknownVtbl, iface);
67         TRACE("(%p): AddRef from %ld\n", This, This->ref);
68         return ++(This->ref);
69 }
70
71 ULONG WINAPI IDirectMusicWaveImpl_IUnknown_Release (LPUNKNOWN iface) {
72         ICOM_THIS_MULTI(IDirectMusicWaveImpl, UnknownVtbl, iface);
73         ULONG ref = --This->ref;
74         TRACE("(%p): ReleaseRef to %ld\n", This, This->ref);
75         if (ref == 0) {
76                 HeapFree(GetProcessHeap(), 0, This);
77         }
78         return ref;
79 }
80
81 ICOM_VTABLE(IUnknown) DirectMusicWave_Unknown_Vtbl = {
82     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
83         IDirectMusicWaveImpl_IUnknown_QueryInterface,
84         IDirectMusicWaveImpl_IUnknown_AddRef,
85         IDirectMusicWaveImpl_IUnknown_Release
86 };
87
88 /* IDirectMusicSegment8Impl IDirectMusicSegment part: */
89 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_QueryInterface (LPDIRECTMUSICSEGMENT8 iface, REFIID riid, LPVOID *ppobj) {
90         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
91         return IDirectMusicWaveImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
92 }
93
94 ULONG WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_AddRef (LPDIRECTMUSICSEGMENT8 iface) {
95         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
96         return IDirectMusicWaveImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
97 }
98
99 ULONG WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_Release (LPDIRECTMUSICSEGMENT8 iface) {
100         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
101         return IDirectMusicWaveImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
102 }
103
104 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetLength (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME* pmtLength) {
105         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
106         FIXME("(%p, %p): stub\n", This, pmtLength);
107         return S_OK;
108 }
109
110 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetLength (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME mtLength) {
111         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
112         FIXME("(%p, %ld): stub\n", This, mtLength);
113         return S_OK;
114 }
115
116 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetRepeats (LPDIRECTMUSICSEGMENT8 iface, DWORD* pdwRepeats) { 
117         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
118         FIXME("(%p, %p): stub\n", This, pdwRepeats);
119         return S_OK;
120 }
121
122 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetRepeats (LPDIRECTMUSICSEGMENT8 iface, DWORD dwRepeats) {
123         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
124         FIXME("(%p, %ld): stub\n", This, dwRepeats);    
125         return S_OK;
126 }
127
128 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetDefaultResolution (LPDIRECTMUSICSEGMENT8 iface, DWORD* pdwResolution) {
129         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
130         FIXME("(%p, %p): stub\n", This, pdwResolution);
131         return S_OK;
132 }
133
134 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetDefaultResolution (LPDIRECTMUSICSEGMENT8 iface, DWORD dwResolution) {
135         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
136         FIXME("(%p, %ld): stub\n", This, dwResolution);
137         return S_OK;
138 }
139
140 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetTrack (LPDIRECTMUSICSEGMENT8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, IDirectMusicTrack** ppTrack) {
141         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
142         FIXME("(%p, %s, %ld, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, ppTrack);
143         return S_OK;
144 }
145
146 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetTrackGroup (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicTrack* pTrack, DWORD* pdwGroupBits) {
147         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
148         FIXME("(%p, %p, %p): stub\n", This, pTrack, pdwGroupBits);
149         return S_OK;
150 }
151
152 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_InsertTrack (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicTrack* pTrack, DWORD dwGroupBits) {
153         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
154         FIXME("(%p, %p, %ld): stub\n", This, pTrack, dwGroupBits);
155         return S_OK;
156 }
157
158 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_RemoveTrack (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicTrack* pTrack) {
159         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
160         FIXME("(%p, %p): stub\n", This, pTrack);
161         return S_OK;
162 }
163
164 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_InitPlay (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicSegmentState** ppSegState, IDirectMusicPerformance* pPerformance, DWORD dwFlags) {
165         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
166         FIXME("(%p, %p, %p, %ld): stub\n", This, ppSegState, pPerformance, dwFlags);
167         return S_OK;
168 }
169
170 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetGraph (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicGraph** ppGraph) {
171         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
172         FIXME("(%p, %p): stub\n", This, ppGraph);
173         return S_OK;
174 }
175
176 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetGraph (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicGraph* pGraph) {
177         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
178         FIXME("(%p, %p): stub\n", This, pGraph);
179         return S_OK;
180 }
181
182 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_AddNotificationType (LPDIRECTMUSICSEGMENT8 iface, REFGUID rguidNotificationType) {
183         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
184         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
185         return S_OK;
186 }
187
188 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_RemoveNotificationType (LPDIRECTMUSICSEGMENT8 iface, REFGUID rguidNotificationType) {
189         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
190         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
191         return S_OK;
192 }
193
194 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetParam (LPDIRECTMUSICSEGMENT8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
195         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
196         FIXME("(%p, %s, %ld, %ld, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
197         return S_OK;
198 }
199
200 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetParam (LPDIRECTMUSICSEGMENT8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void* pParam) {
201         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
202         FIXME("(%p, %s, %ld, %ld, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
203         return S_OK;
204 }
205
206 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_Clone (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, IDirectMusicSegment** ppSegment) {
207         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
208         FIXME("(%p, %ld, %ld, %p): stub\n", This, mtStart, mtEnd, ppSegment);
209         return S_OK;
210 }
211
212 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetStartPoint (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME mtStart) {
213         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
214         FIXME("(%p, %ld): stub\n", This, mtStart);
215         return S_OK;
216 }
217
218 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetStartPoint (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME* pmtStart) {
219         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
220         FIXME("(%p, %p): stub\n", This, pmtStart);
221         return S_OK;
222 }
223
224 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetLoopPoints (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) {
225         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
226         FIXME("(%p, %ld, %ld): stub\n", This, mtStart, mtEnd);
227         return S_OK;
228 }
229
230 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetLoopPoints (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME* pmtStart, MUSIC_TIME* pmtEnd) {
231         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
232         FIXME("(%p, %p, %p): stub\n", This, pmtStart, pmtEnd);
233         return S_OK;
234 }
235
236 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetPChannelsUsed (LPDIRECTMUSICSEGMENT8 iface, DWORD dwNumPChannels, DWORD* paPChannels) {
237         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
238         FIXME("(%p, %ld, %p): stub\n", This, dwNumPChannels, paPChannels);      
239         return S_OK;
240 }
241
242 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_SetTrackConfig (LPDIRECTMUSICSEGMENT8 iface, REFGUID rguidTrackClassID, DWORD dwGroupBits, DWORD dwIndex, DWORD dwFlagsOn, DWORD dwFlagsOff) {
243         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
244         FIXME("(%p, %s, %ld, %ld, %ld, %ld): stub\n", This, debugstr_dmguid(rguidTrackClassID), dwGroupBits, dwIndex, dwFlagsOn, dwFlagsOff);
245         return S_OK;
246 }
247
248 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_GetAudioPathConfig (LPDIRECTMUSICSEGMENT8 iface, IUnknown** ppAudioPathConfig){
249         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
250         FIXME("(%p, %p): stub\n", This, ppAudioPathConfig);
251         return S_OK;
252 }
253
254 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_Compose (LPDIRECTMUSICSEGMENT8 iface, MUSIC_TIME mtTime, IDirectMusicSegment* pFromSegment, IDirectMusicSegment* pToSegment, IDirectMusicSegment** ppComposedSegment) {
255         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
256         FIXME("(%p, %ld, %p, %p, %p): stub\n", This, mtTime, pFromSegment, pToSegment, ppComposedSegment);
257         return S_OK;
258 }
259
260 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_Download (LPDIRECTMUSICSEGMENT8 iface, IUnknown *pAudioPath) {
261         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
262         FIXME("(%p, %p): stub\n", This, pAudioPath);
263         return S_OK;
264 }
265
266 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicSegment8_Unload (LPDIRECTMUSICSEGMENT8 iface, IUnknown *pAudioPath) {
267         ICOM_THIS_MULTI(IDirectMusicWaveImpl, SegmentVtbl, iface);
268         FIXME("(%p, %p): stub\n", This, pAudioPath);
269         return S_OK;
270 }
271
272 ICOM_VTABLE(IDirectMusicSegment8) DirectMusicSegment8_Segment_Vtbl = {
273     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
274         IDirectMusicWaveImpl_IDirectMusicSegment8_QueryInterface,
275         IDirectMusicWaveImpl_IDirectMusicSegment8_AddRef,
276         IDirectMusicWaveImpl_IDirectMusicSegment8_Release,
277         IDirectMusicWaveImpl_IDirectMusicSegment8_GetLength,
278         IDirectMusicWaveImpl_IDirectMusicSegment8_SetLength,
279         IDirectMusicWaveImpl_IDirectMusicSegment8_GetRepeats,
280         IDirectMusicWaveImpl_IDirectMusicSegment8_SetRepeats,
281         IDirectMusicWaveImpl_IDirectMusicSegment8_GetDefaultResolution,
282         IDirectMusicWaveImpl_IDirectMusicSegment8_SetDefaultResolution,
283         IDirectMusicWaveImpl_IDirectMusicSegment8_GetTrack,
284         IDirectMusicWaveImpl_IDirectMusicSegment8_GetTrackGroup,
285         IDirectMusicWaveImpl_IDirectMusicSegment8_InsertTrack,
286         IDirectMusicWaveImpl_IDirectMusicSegment8_RemoveTrack,
287         IDirectMusicWaveImpl_IDirectMusicSegment8_InitPlay,
288         IDirectMusicWaveImpl_IDirectMusicSegment8_GetGraph,
289         IDirectMusicWaveImpl_IDirectMusicSegment8_SetGraph,
290         IDirectMusicWaveImpl_IDirectMusicSegment8_AddNotificationType,
291         IDirectMusicWaveImpl_IDirectMusicSegment8_RemoveNotificationType,
292         IDirectMusicWaveImpl_IDirectMusicSegment8_GetParam,
293         IDirectMusicWaveImpl_IDirectMusicSegment8_SetParam,
294         IDirectMusicWaveImpl_IDirectMusicSegment8_Clone,
295         IDirectMusicWaveImpl_IDirectMusicSegment8_SetStartPoint,
296         IDirectMusicWaveImpl_IDirectMusicSegment8_GetStartPoint,
297         IDirectMusicWaveImpl_IDirectMusicSegment8_SetLoopPoints,
298         IDirectMusicWaveImpl_IDirectMusicSegment8_GetLoopPoints,
299         IDirectMusicWaveImpl_IDirectMusicSegment8_SetPChannelsUsed,
300         IDirectMusicWaveImpl_IDirectMusicSegment8_SetTrackConfig,
301         IDirectMusicWaveImpl_IDirectMusicSegment8_GetAudioPathConfig,
302         IDirectMusicWaveImpl_IDirectMusicSegment8_Compose,
303         IDirectMusicWaveImpl_IDirectMusicSegment8_Download,
304         IDirectMusicWaveImpl_IDirectMusicSegment8_Unload
305 };
306
307 /* IDirectMusicWaveImpl IDirectMusicObject part: */
308 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
309         ICOM_THIS_MULTI(IDirectMusicWaveImpl, ObjectVtbl, iface);
310         return IDirectMusicWaveImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
311 }
312
313 ULONG WINAPI IDirectMusicWaveImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
314         ICOM_THIS_MULTI(IDirectMusicWaveImpl, ObjectVtbl, iface);
315         return IDirectMusicWaveImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
316 }
317
318 ULONG WINAPI IDirectMusicWaveImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
319         ICOM_THIS_MULTI(IDirectMusicWaveImpl, ObjectVtbl, iface);
320         return IDirectMusicWaveImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
321 }
322
323 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
324         ICOM_THIS_MULTI(IDirectMusicWaveImpl, ObjectVtbl, iface);
325         TRACE("(%p, %p)\n", This, pDesc);
326         /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
327         memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
328         return S_OK;
329 }
330
331 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
332         ICOM_THIS_MULTI(IDirectMusicWaveImpl, ObjectVtbl, iface);
333         TRACE("(%p, %p, %s): setting descriptor:\n", This, pDesc, debugstr_DMUS_OBJECTDESC(pDesc));
334         
335         /* According to MSDN, we should copy only given values, not whole struct */     
336         if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
337                 memcpy (&This->pDesc->guidObject, &pDesc->guidObject, sizeof (pDesc->guidObject));
338         if (pDesc->dwValidData & DMUS_OBJ_CLASS)
339                 memcpy (&This->pDesc->guidClass, &pDesc->guidClass, sizeof (pDesc->guidClass));         
340         if (pDesc->dwValidData & DMUS_OBJ_NAME)
341                 strncpyW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
342         if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
343                 strncpyW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);             
344         if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
345                 strncpyW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);             
346         if (pDesc->dwValidData & DMUS_OBJ_VERSION)
347                 memcpy (&This->pDesc->vVersion, &pDesc->vVersion, sizeof (pDesc->vVersion));                            
348         if (pDesc->dwValidData & DMUS_OBJ_DATE)
349                 memcpy (&This->pDesc->ftDate, &pDesc->ftDate, sizeof (pDesc->ftDate));                          
350         if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
351                 memcpy (&This->pDesc->llMemLength, &pDesc->llMemLength, sizeof (pDesc->llMemLength));                           
352                 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, sizeof (pDesc->pbMemData));
353         }
354         if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
355                 /* according to MSDN, we copy the stream */
356                 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);  
357         }
358         
359         /* add new flags */
360         This->pDesc->dwValidData |= pDesc->dwValidData;
361
362         return S_OK;
363 }
364
365 HRESULT WINAPI IDirectMusicWaveImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
366         DMUS_PRIVATE_CHUNK Chunk;
367         DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
368         LARGE_INTEGER liMove; /* used when skipping chunks */
369
370         TRACE("(%p, %p)\n", pStream, pDesc);
371         
372         /* FIXME: should this be determined from stream? */
373         pDesc->dwValidData |= DMUS_OBJ_CLASS;
374         memcpy (&pDesc->guidClass, &CLSID_DirectMusicSegment, sizeof(CLSID));
375         
376         IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
377         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
378         switch (Chunk.fccID) {  
379                 case FOURCC_RIFF: {
380                         IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);                             
381                         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
382                         StreamSize = Chunk.dwSize - sizeof(FOURCC);
383                         StreamCount = 0;
384                         if (Chunk.fccID == mmioFOURCC('W','A','V','E')) {
385                                 TRACE_(dmfile)(": wave form\n");
386                                 do {
387                                         IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
388                                         StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
389                                         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
390                                         switch (Chunk.fccID) {
391                                                 case DMUS_FOURCC_GUID_CHUNK: {
392                                                         TRACE_(dmfile)(": GUID chunk\n");
393                                                         pDesc->dwValidData |= DMUS_OBJ_OBJECT;
394                                                         IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
395                                                         break;
396                                                 }
397                                                 case DMUS_FOURCC_VERSION_CHUNK: {
398                                                         TRACE_(dmfile)(": version chunk\n");
399                                                         pDesc->dwValidData |= DMUS_OBJ_VERSION;
400                                                         IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
401                                                         break;
402                                                 }
403                                                 case DMUS_FOURCC_CATEGORY_CHUNK: {
404                                                         TRACE_(dmfile)(": category chunk\n");
405                                                         pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
406                                                         IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
407                                                         break;
408                                                 }
409                                                 case FOURCC_LIST: {
410                                                         IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);                             
411                                                         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
412                                                         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
413                                                         ListCount[0] = 0;
414                                                         switch (Chunk.fccID) {
415                                                                 /* evil M$ UNFO list, which can (!?) contain INFO elements */
416                                                                 case DMUS_FOURCC_UNFO_LIST: {
417                                                                         TRACE_(dmfile)(": UNFO list\n");
418                                                                         do {
419                                                                                 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
420                                                                                 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
421                                                                                 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
422                                                                                 switch (Chunk.fccID) {
423                                                                                         /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
424                                              (though strings seem to be valid unicode) */
425                                                                                         case mmioFOURCC('I','N','A','M'):
426                                                                                         case DMUS_FOURCC_UNAM_CHUNK: {
427                                                                                                 TRACE_(dmfile)(": name chunk\n");
428                                                                                                 pDesc->dwValidData |= DMUS_OBJ_NAME;
429                                                                                                 IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
430                                                                                                 break;
431                                                                                         }
432                                                                                         case mmioFOURCC('I','A','R','T'):
433                                                                                         case DMUS_FOURCC_UART_CHUNK: {
434                                                                                                 TRACE_(dmfile)(": artist chunk (ignored)\n");
435                                                                                                 liMove.QuadPart = Chunk.dwSize;
436                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
437                                                                                                 break;
438                                                                                         }
439                                                                                         case mmioFOURCC('I','C','O','P'):
440                                                                                         case DMUS_FOURCC_UCOP_CHUNK: {
441                                                                                                 TRACE_(dmfile)(": copyright chunk (ignored)\n");
442                                                                                                 liMove.QuadPart = Chunk.dwSize;
443                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
444                                                                                                 break;
445                                                                                         }
446                                                                                         case mmioFOURCC('I','S','B','J'):
447                                                                                         case DMUS_FOURCC_USBJ_CHUNK: {
448                                                                                                 TRACE_(dmfile)(": subject chunk (ignored)\n");
449                                                                                                 liMove.QuadPart = Chunk.dwSize;
450                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
451                                                                                                 break;
452                                                                                         }
453                                                                                         case mmioFOURCC('I','C','M','T'):
454                                                                                         case DMUS_FOURCC_UCMT_CHUNK: {
455                                                                                                 TRACE_(dmfile)(": comment chunk (ignored)\n");
456                                                                                                 liMove.QuadPart = Chunk.dwSize;
457                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
458                                                                                                 break;
459                                                                                         }
460                                                                                         default: {
461                                                                                                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
462                                                                                                 liMove.QuadPart = Chunk.dwSize;
463                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
464                                                                                                 break;                                          
465                                                                                         }
466                                                                                 }
467                                                                                 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
468                                                                         } while (ListCount[0] < ListSize[0]);
469                                                                         break;
470                                                                 }
471                                                                 default: {
472                                                                         TRACE_(dmfile)(": unknown (skipping)\n");
473                                                                         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
474                                                                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
475                                                                         break;                                          
476                                                                 }
477                                                         }
478                                                         break;
479                                                 }       
480                                                 default: {
481                                                         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
482                                                         liMove.QuadPart = Chunk.dwSize;
483                                                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
484                                                         break;                                          
485                                                 }
486                                         }
487                                         TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
488                                 } while (StreamCount < StreamSize);
489                                 break;
490                         } else {
491                                 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
492                                 liMove.QuadPart = StreamSize;
493                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
494                                 return E_FAIL;
495                         }
496                 
497                         TRACE_(dmfile)(": reading finished\n");
498                         break;
499                 }
500                 default: {
501                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
502                         liMove.QuadPart = Chunk.dwSize;
503                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
504                         return DMUS_E_INVALIDFILE;
505                 }
506         }       
507         
508         TRACE(": returning descriptor: %s\n", debugstr_DMUS_OBJECTDESC (pDesc));
509         
510         return S_OK;    
511 }
512
513 ICOM_VTABLE(IDirectMusicObject) DirectMusicWave_Object_Vtbl = {
514     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
515         IDirectMusicWaveImpl_IDirectMusicObject_QueryInterface,
516         IDirectMusicWaveImpl_IDirectMusicObject_AddRef,
517         IDirectMusicWaveImpl_IDirectMusicObject_Release,
518         IDirectMusicWaveImpl_IDirectMusicObject_GetDescriptor,
519         IDirectMusicWaveImpl_IDirectMusicObject_SetDescriptor,
520         IDirectMusicWaveImpl_IDirectMusicObject_ParseDescriptor
521 };
522
523 /* IDirectMusicWaveImpl IPersistStream part: */
524 HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
525         ICOM_THIS_MULTI(IDirectMusicWaveImpl, PersistStreamVtbl, iface);
526         return IDirectMusicWaveImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
527 }
528
529 ULONG WINAPI IDirectMusicWaveImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
530         ICOM_THIS_MULTI(IDirectMusicWaveImpl, PersistStreamVtbl, iface);
531         return IDirectMusicWaveImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
532 }
533
534 ULONG WINAPI IDirectMusicWaveImpl_IPersistStream_Release (LPPERSISTSTREAM iface) {
535         ICOM_THIS_MULTI(IDirectMusicWaveImpl, PersistStreamVtbl, iface);
536         return IDirectMusicWaveImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
537 }
538
539 HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
540         return E_NOTIMPL;
541 }
542
543 HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
544         return E_NOTIMPL;
545 }
546
547 HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
548         ICOM_THIS_MULTI(IDirectMusicWaveImpl, PersistStreamVtbl, iface);
549         
550         DMUS_PRIVATE_CHUNK Chunk;
551         DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
552         LARGE_INTEGER liMove; /* used when skipping chunks */
553
554         FIXME("(%p, %p): loading not implemented yet (only descriptor is loaded)\n", This, pStm);
555         
556         /* FIXME: should this be determined from stream? */
557         This->pDesc->dwValidData |= DMUS_OBJ_CLASS;
558         memcpy (&This->pDesc->guidClass, &CLSID_DirectMusicSegment, sizeof(CLSID));
559         
560         IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
561         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
562         switch (Chunk.fccID) {  
563                 case FOURCC_RIFF: {
564                         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);                                
565                         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
566                         StreamSize = Chunk.dwSize - sizeof(FOURCC);
567                         StreamCount = 0;
568                         if (Chunk.fccID == mmioFOURCC('W','A','V','E')) {
569                                 TRACE_(dmfile)(": wave form\n");
570                                 do {
571                                         IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
572                                         StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
573                                         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
574                                         switch (Chunk.fccID) {
575                                                 case DMUS_FOURCC_GUID_CHUNK: {
576                                                         TRACE_(dmfile)(": GUID chunk\n");
577                                                         This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
578                                                         IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL);
579                                                         break;
580                                                 }
581                                                 case DMUS_FOURCC_VERSION_CHUNK: {
582                                                         TRACE_(dmfile)(": version chunk\n");
583                                                         This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
584                                                         IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL);
585                                                         break;
586                                                 }
587                                                 case DMUS_FOURCC_CATEGORY_CHUNK: {
588                                                         TRACE_(dmfile)(": category chunk\n");
589                                                         This->pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
590                                                         IStream_Read (pStm, This->pDesc->wszCategory, Chunk.dwSize, NULL);
591                                                         break;
592                                                 }
593                                                 case FOURCC_LIST: {
594                                                         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);                                
595                                                         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
596                                                         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
597                                                         ListCount[0] = 0;
598                                                         switch (Chunk.fccID) {
599                                                                 /* evil M$ UNFO list, which can (!?) contain INFO elements */
600                                                                 case DMUS_FOURCC_UNFO_LIST: {
601                                                                         TRACE_(dmfile)(": UNFO list\n");
602                                                                         do {
603                                                                                 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
604                                                                                 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
605                                                                                 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
606                                                                                 switch (Chunk.fccID) {
607                                                                                         /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
608                                              (though strings seem to be valid unicode) */
609                                                                                         case mmioFOURCC('I','N','A','M'):
610                                                                                         case DMUS_FOURCC_UNAM_CHUNK: {
611                                                                                                 TRACE_(dmfile)(": name chunk\n");
612                                                                                                 This->pDesc->dwValidData |= DMUS_OBJ_NAME;
613                                                                                                 IStream_Read (pStm, This->pDesc->wszName, Chunk.dwSize, NULL);
614                                                                                                 break;
615                                                                                         }
616                                                                                         case mmioFOURCC('I','A','R','T'):
617                                                                                         case DMUS_FOURCC_UART_CHUNK: {
618                                                                                                 TRACE_(dmfile)(": artist chunk (ignored)\n");
619                                                                                                 liMove.QuadPart = Chunk.dwSize;
620                                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
621                                                                                                 break;
622                                                                                         }
623                                                                                         case mmioFOURCC('I','C','O','P'):
624                                                                                         case DMUS_FOURCC_UCOP_CHUNK: {
625                                                                                                 TRACE_(dmfile)(": copyright chunk (ignored)\n");
626                                                                                                 liMove.QuadPart = Chunk.dwSize;
627                                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
628                                                                                                 break;
629                                                                                         }
630                                                                                         case mmioFOURCC('I','S','B','J'):
631                                                                                         case DMUS_FOURCC_USBJ_CHUNK: {
632                                                                                                 TRACE_(dmfile)(": subject chunk (ignored)\n");
633                                                                                                 liMove.QuadPart = Chunk.dwSize;
634                                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
635                                                                                                 break;
636                                                                                         }
637                                                                                         case mmioFOURCC('I','C','M','T'):
638                                                                                         case DMUS_FOURCC_UCMT_CHUNK: {
639                                                                                                 TRACE_(dmfile)(": comment chunk (ignored)\n");
640                                                                                                 liMove.QuadPart = Chunk.dwSize;
641                                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
642                                                                                                 break;
643                                                                                         }
644                                                                                         default: {
645                                                                                                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
646                                                                                                 liMove.QuadPart = Chunk.dwSize;
647                                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
648                                                                                                 break;                                          
649                                                                                         }
650                                                                                 }
651                                                                                 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
652                                                                         } while (ListCount[0] < ListSize[0]);
653                                                                         break;
654                                                                 }
655                                                                 default: {
656                                                                         TRACE_(dmfile)(": unknown (skipping)\n");
657                                                                         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
658                                                                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
659                                                                         break;                                          
660                                                                 }
661                                                         }
662                                                         break;
663                                                 }       
664                                                 default: {
665                                                         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
666                                                         liMove.QuadPart = Chunk.dwSize;
667                                                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
668                                                         break;                                          
669                                                 }
670                                         }
671                                         TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
672                                 } while (StreamCount < StreamSize);
673                                 break;
674                         } else {
675                                 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
676                                 liMove.QuadPart = StreamSize;
677                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
678                                 return E_FAIL;
679                         }
680                 
681                         TRACE_(dmfile)(": reading finished\n");
682                         break;
683                 }
684                 default: {
685                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
686                         liMove.QuadPart = Chunk.dwSize;
687                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
688                         return DMUS_E_INVALIDFILE;
689                 }
690         }
691         
692         return S_OK;
693 }
694
695 HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
696         return E_NOTIMPL;
697 }
698
699 HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
700         return E_NOTIMPL;
701 }
702
703 ICOM_VTABLE(IPersistStream) DirectMusicWave_PersistStream_Vtbl = {
704     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
705         IDirectMusicWaveImpl_IPersistStream_QueryInterface,
706         IDirectMusicWaveImpl_IPersistStream_AddRef,
707         IDirectMusicWaveImpl_IPersistStream_Release,
708         IDirectMusicWaveImpl_IPersistStream_GetClassID,
709         IDirectMusicWaveImpl_IPersistStream_IsDirty,
710         IDirectMusicWaveImpl_IPersistStream_Load,
711         IDirectMusicWaveImpl_IPersistStream_Save,
712         IDirectMusicWaveImpl_IPersistStream_GetSizeMax
713 };
714
715
716 /* for ClassFactory */
717 HRESULT WINAPI DMUSIC_CreateDirectMusicWaveImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
718         IDirectMusicWaveImpl* obj;
719         
720         obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicWaveImpl));
721         if (NULL == obj) {
722                 *ppobj = (LPVOID) NULL;
723                 return E_OUTOFMEMORY;
724         }
725         obj->UnknownVtbl = &DirectMusicWave_Unknown_Vtbl;
726         obj->ObjectVtbl = &DirectMusicWave_Object_Vtbl;
727         obj->PersistStreamVtbl = &DirectMusicWave_PersistStream_Vtbl;
728         obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
729         DM_STRUCT_INIT(obj->pDesc);
730         obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
731         memcpy (&obj->pDesc->guidClass, &CLSID_DirectMusicSegment, sizeof (CLSID)); /* shown by tests */
732         obj->ref = 0; /* will be inited by QueryInterface */
733         
734         return IDirectMusicWaveImpl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);
735 }