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