1 /* IDirectMusicLoaderImpl
3 * Copyright (C) 2003-2004 Rok Mandeljc
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.
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.
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
20 #include "dmloader_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmloader
);
24 static HRESULT
DMUSIC_InitLoaderSettings (LPDIRECTMUSICLOADER8 iface
);
25 static HRESULT
DMUSIC_GetLoaderSettings (LPDIRECTMUSICLOADER8 iface
, REFGUID pClassID
, WCHAR
* wszSearchPath
, LPBOOL pbCache
);
26 static HRESULT
DMUSIC_SetLoaderSettings (LPDIRECTMUSICLOADER8 iface
, REFGUID pClassID
, WCHAR
* wszSearchPath
, LPBOOL pbCache
);
28 static HRESULT
DMUSIC_CopyDescriptor (LPDMUS_OBJECTDESC pDst
, LPDMUS_OBJECTDESC pSrc
) {
29 TRACE(": copy\n%s\n", debugstr_DMUS_OBJECTDESC(pSrc
));
30 /* copy field by field */
31 if (pSrc
->dwValidData
& DMUS_OBJ_CLASS
) pDst
->guidClass
= pSrc
->guidClass
;
32 if (pSrc
->dwValidData
& DMUS_OBJ_OBJECT
) pDst
->guidObject
= pSrc
->guidObject
;
33 if (pSrc
->dwValidData
& DMUS_OBJ_DATE
) pDst
->ftDate
= pSrc
->ftDate
;
34 if (pSrc
->dwValidData
& DMUS_OBJ_VERSION
) pDst
->vVersion
= pSrc
->vVersion
;
35 if (pSrc
->dwValidData
& DMUS_OBJ_NAME
) strcpyW (pDst
->wszName
, pSrc
->wszName
);
36 if (pSrc
->dwValidData
& DMUS_OBJ_CATEGORY
) strcpyW (pDst
->wszCategory
, pSrc
->wszCategory
);
37 if (pSrc
->dwValidData
& DMUS_OBJ_FILENAME
) strcpyW (pDst
->wszFileName
, pSrc
->wszFileName
);
38 if (pSrc
->dwValidData
& DMUS_OBJ_STREAM
) IStream_Clone (pSrc
->pStream
, &pDst
->pStream
);
39 if (pSrc
->dwValidData
& DMUS_OBJ_MEMORY
) {
40 pDst
->pbMemData
= pSrc
->pbMemData
;
41 pDst
->llMemLength
= pSrc
->llMemLength
;
44 pDst
->dwValidData
|= pSrc
->dwValidData
;
49 static BOOL
DMUSIC_IsValidLoadableClass (REFCLSID pClassID
) {
50 if (IsEqualCLSID(pClassID
, &CLSID_DirectMusicAudioPathConfig
) ||
51 IsEqualCLSID(pClassID
, &CLSID_DirectMusicBand
) ||
52 IsEqualCLSID(pClassID
, &CLSID_DirectMusicContainer
) ||
53 IsEqualCLSID(pClassID
, &CLSID_DirectMusicCollection
) ||
54 IsEqualCLSID(pClassID
, &CLSID_DirectMusicChordMap
) ||
55 IsEqualCLSID(pClassID
, &CLSID_DirectMusicSegment
) ||
56 IsEqualCLSID(pClassID
, &CLSID_DirectMusicScript
) ||
57 IsEqualCLSID(pClassID
, &CLSID_DirectMusicSong
) ||
58 IsEqualCLSID(pClassID
, &CLSID_DirectMusicStyle
) ||
59 IsEqualCLSID(pClassID
, &CLSID_DirectMusicGraph
) ||
60 IsEqualCLSID(pClassID
, &CLSID_DirectSoundWave
) ||
61 IsEqualCLSID(pClassID
, &GUID_DirectMusicAllTypes
))
67 /*****************************************************************************
68 * IDirectMusicLoaderImpl implementation
70 /* IUnknown/IDirectMusicLoader(8) part: */
72 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface (LPDIRECTMUSICLOADER8 iface
, REFIID riid
, LPVOID
*ppobj
) {
73 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
75 TRACE("(%p, %s, %p)\n",This
, debugstr_dmguid(riid
), ppobj
);
76 if (IsEqualIID (riid
, &IID_IUnknown
) ||
77 IsEqualIID (riid
, &IID_IDirectMusicLoader
) ||
78 IsEqualIID (riid
, &IID_IDirectMusicLoader8
)) {
79 IDirectMusicLoader_AddRef (iface
);
84 WARN(": not found\n");
88 static ULONG WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef (LPDIRECTMUSICLOADER8 iface
) {
89 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
90 TRACE("(%p): AddRef from %d\n", This
, This
->dwRef
);
91 return InterlockedIncrement (&This
->dwRef
);
94 static ULONG WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_Release (LPDIRECTMUSICLOADER8 iface
) {
95 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
97 DWORD dwRef
= InterlockedDecrement (&This
->dwRef
);
98 TRACE("(%p): ReleaseRef to %d\n", This
, This
->dwRef
);
100 /* firstly, release the cache */
101 IDirectMusicLoader8_ClearCache (iface
, &GUID_DirectMusicAllTypes
);
102 /* FIXME: release all allocated entries */
103 /* destroy critical section */
104 /*This->CritSect.DebugInfo->Spare[0] = 0;
105 DeleteCriticalSection (&This->CritSect); */
106 HeapFree (GetProcessHeap(), 0, This
);
108 /* decrease number of instances */
109 InterlockedDecrement (&dwDirectMusicLoader
);
115 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject (LPDIRECTMUSICLOADER8 iface
, LPDMUS_OBJECTDESC pDesc
, REFIID riid
, LPVOID
* ppv
) {
116 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
117 HRESULT result
= S_OK
;
118 HRESULT ret
= S_OK
; /* used at the end of function, to determine whether everything went OK */
121 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
123 IPersistStream
* pPersistStream
= NULL
;
125 LPDIRECTMUSICOBJECT pObject
;
126 DMUS_OBJECTDESC GotDesc
;
129 TRACE("(%p, %p, %s, %p): pDesc:\n%s\n", This
, pDesc
, debugstr_dmguid(riid
), ppv
, debugstr_DMUS_OBJECTDESC(pDesc
));
131 /* sometimes it happens that guidClass is missing... which is a BadThingTM */
132 if (!(pDesc
->dwValidData
& DMUS_OBJ_CLASS
)) {
133 ERR(": guidClass not valid but needed\n");
135 return DMUS_E_LOADER_NOCLASSID
;
138 /* OK, first we iterate thru the list of objects we know about; these are either loaded (GetObject, LoadObjectFromFile)
139 or set via SetObject; */
140 TRACE(": looking if we have object in the cache or if it can be found via alias\n");
141 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
142 LPWINE_LOADER_ENTRY pExistingEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
143 if ((pDesc
->dwValidData
& DMUS_OBJ_OBJECT
) &&
144 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
145 IsEqualGUID (&pDesc
->guidObject
, &pExistingEntry
->Desc
.guidObject
)) {
146 TRACE(": found it by object GUID\n");
147 /* I suppose such stuff can happen only when GUID for object is given (GUID_DefaultGMCollection) */
148 if (pExistingEntry
->bInvalidDefaultDLS
) {
149 TRACE(": found faulty default DLS collection... enabling M$ compliant behaviour\n");
150 return DMUS_E_LOADER_NOFILENAME
;
152 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
153 TRACE(": already loaded\n");
154 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
156 TRACE(": not loaded yet\n");
157 pObjectEntry
= pExistingEntry
;
160 else if ((pDesc
->dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
161 (pExistingEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
162 !strncmpW (pDesc
->wszFileName
, pExistingEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
163 TRACE(": found it by fullpath filename\n");
164 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
165 TRACE(": already loaded\n");
166 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
168 TRACE(": not loaded yet\n");
169 pObjectEntry
= pExistingEntry
;
172 else if ((pDesc
->dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
173 (pExistingEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
174 !strncmpW (pDesc
->wszName
, pExistingEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
175 !strncmpW (pDesc
->wszCategory
, pExistingEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
176 TRACE(": found it by name and category\n");
177 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
178 TRACE(": already loaded\n");
179 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
181 TRACE(": not loaded yet\n");
182 pObjectEntry
= pExistingEntry
;
185 else if ((pDesc
->dwValidData
& DMUS_OBJ_NAME
) &&
186 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
187 !strncmpW (pDesc
->wszName
, pExistingEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
188 TRACE(": found it by name\n");
189 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
190 TRACE(": already loaded\n");
191 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
193 TRACE(": not loaded yet\n");
194 pObjectEntry
= pExistingEntry
;
197 else if ((pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) &&
198 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
199 !strncmpW (pDesc
->wszFileName
, pExistingEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
200 TRACE(": found it by filename\n");
201 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
202 TRACE(": already loaded\n");
203 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
205 TRACE(": not loaded yet\n");
206 pObjectEntry
= pExistingEntry
;
211 /* basically, if we found alias, we use its descriptor to load...
212 else we use info we were given */
214 TRACE(": found alias entry for requested object... using stored info\n");
215 /* I think in certain cases it can happen that entry's descriptor lacks info about
216 where to load from (e.g.: if we loaded from stream and then released object
217 from cache; then only its CLSID, GUID and perhaps name are left); so just
218 overwrite whatever info the entry has (since it ought to be 100% correct) */
219 DMUSIC_CopyDescriptor (pDesc
, &pObjectEntry
->Desc
);
220 /*pDesc = &pObjectEntry->Desc; */ /* FIXME: is this OK? */
222 TRACE(": no cache/alias entry found for requested object\n");
225 if (pDesc
->dwValidData
& DMUS_OBJ_URL
) {
226 TRACE(": loading from URLs not supported yet\n");
227 return DMUS_E_LOADER_FORMATNOTSUPPORTED
;
229 else if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
230 /* load object from file */
231 /* generate filename; if it's full path, don't add search
232 directory path, otherwise do */
233 WCHAR wszFileName
[MAX_PATH
];
235 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
236 lstrcpyW(wszFileName
, pDesc
->wszFileName
);
238 WCHAR
*p
, wszSearchPath
[MAX_PATH
];
239 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, wszSearchPath
, NULL
);
240 lstrcpyW(wszFileName
, wszSearchPath
);
241 p
= wszFileName
+ lstrlenW(wszFileName
);
242 if (p
> wszFileName
&& p
[-1] != '\\') *p
++ = '\\';
243 strcpyW(p
, pDesc
->wszFileName
);
245 TRACE(": loading from file (%s)\n", debugstr_w(wszFileName
));
246 /* create stream and associate it with file */
247 result
= DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID
*)&pStream
);
248 if (FAILED(result
)) {
249 ERR(": could not create file stream\n");
252 result
= IDirectMusicLoaderFileStream_Attach (pStream
, wszFileName
, iface
);
253 if (FAILED(result
)) {
254 ERR(": could not attach stream to file\n");
255 IStream_Release (pStream
);
259 else if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
260 /* load object from resource */
261 TRACE(": loading from resource\n");
262 /* create stream and associate it with given resource */
263 result
= DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID
*)&pStream
);
264 if (FAILED(result
)) {
265 ERR(": could not create resource stream\n");
268 result
= IDirectMusicLoaderResourceStream_Attach (pStream
, pDesc
->pbMemData
, pDesc
->llMemLength
, 0, iface
);
269 if (FAILED(result
)) {
270 ERR(": could not attach stream to resource\n");
271 IStream_Release (pStream
);
275 else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
276 /* load object from stream */
277 TRACE(": loading from stream\n");
278 /* create universal stream and associate it with given one */
279 result
= DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID
*)&pStream
);
280 if (FAILED(result
)) {
281 ERR(": could not create generic stream\n");
284 result
= IDirectMusicLoaderGenericStream_Attach (pStream
, pDesc
->pStream
, iface
);
285 if (FAILED(result
)) {
286 ERR(": failed to attach stream\n");
287 IStream_Release (pStream
);
291 /* nowhere to load from */
292 FIXME(": unknown/unsupported way of loading\n");
293 return DMUS_E_LOADER_NOFILENAME
; /* test shows this is returned */
297 result
= CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
298 if (FAILED(result
)) {
299 ERR(": could not create object\n");
302 /* acquire PersistStream interface */
303 result
= IDirectMusicObject_QueryInterface (pObject
, &IID_IPersistStream
, (LPVOID
*)&pPersistStream
);
304 if (FAILED(result
)) {
305 ERR("failed to Query\n");
309 result
= IPersistStream_Load (pPersistStream
, pStream
);
310 if (result
!= S_OK
) {
311 WARN(": failed to (completely) load object (%s)\n", debugstr_dmreturn(result
));
312 ret
= DMUS_S_PARTIALLOAD
/*result*/;
315 DM_STRUCT_INIT(&GotDesc
);
316 result
= IDirectMusicObject_GetDescriptor (pObject
, &GotDesc
);
317 /* set filename (if we loaded via filename) */
318 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
319 GotDesc
.dwValidData
|= (pDesc
->dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
));
320 strcpyW (GotDesc
.wszFileName
, pDesc
->wszFileName
);
322 if (FAILED(result
)) {
323 ERR(": failed to get descriptor\n");
326 /* release all loading related stuff */
327 IStream_Release (pStream
);
328 IPersistStream_Release (pPersistStream
);
330 /* add object to cache/overwrite existing info (if cache is enabled) */
331 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, NULL
, &bCache
);
334 pObjectEntry
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_ENTRY
));
335 DM_STRUCT_INIT(&pObjectEntry
->Desc
);
336 DMUSIC_CopyDescriptor (&pObjectEntry
->Desc
, &GotDesc
);
337 pObjectEntry
->pObject
= pObject
;
338 pObjectEntry
->bInvalidDefaultDLS
= FALSE
;
339 list_add_head (This
->pObjects
, &pObjectEntry
->entry
);
341 DMUSIC_CopyDescriptor (&pObjectEntry
->Desc
, &GotDesc
);
342 pObjectEntry
->pObject
= pObject
;
343 pObjectEntry
->bInvalidDefaultDLS
= FALSE
;
345 TRACE(": filled in cache entry\n");
346 } else TRACE(": caching disabled\n");
349 /* for debug purposes (e.g. to check if all files are cached) */
350 TRACE("*** Loader's cache ***\n");
352 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
354 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
355 TRACE(": entry nr. %i:\n%s\n - bInvalidDefaultDLS = %i\n - pObject = %p\n", i
, debugstr_DMUS_OBJECTDESC(&pObjectEntry
->Desc
), pObjectEntry
->bInvalidDefaultDLS
, pObjectEntry
->pObject
);
359 result
= IDirectMusicObject_QueryInterface (pObject
, riid
, ppv
);
360 if (!bCache
) IDirectMusicObject_Release (pObject
); /* since loader's reference is not needed */
361 /* if there was trouble with loading, and if no other error occurred,
362 we should return DMUS_S_PARTIALLOAD; else, error is returned */
369 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject (LPDIRECTMUSICLOADER8 iface
, LPDMUS_OBJECTDESC pDesc
) {
370 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
372 LPDIRECTMUSICOBJECT pObject
;
373 DMUS_OBJECTDESC Desc
;
375 LPWINE_LOADER_ENTRY pObjectEntry
, pNewEntry
;
378 TRACE("(%p, %p): pDesc:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC(pDesc
));
380 /* create stream and load additional info from it */
381 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
382 /* generate filename; if it's full path, don't add search
383 directory path, otherwise do */
384 WCHAR wszFileName
[MAX_PATH
];
386 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
387 lstrcpyW(wszFileName
, pDesc
->wszFileName
);
390 WCHAR wszSearchPath
[MAX_PATH
];
391 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, wszSearchPath
, NULL
);
392 lstrcpyW(wszFileName
, wszSearchPath
);
393 p
= wszFileName
+ lstrlenW(wszFileName
);
394 if (p
> wszFileName
&& p
[-1] != '\\') *p
++ = '\\';
395 strcpyW(p
, pDesc
->wszFileName
);
398 hr
= DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID
*)&pStream
);
400 ERR(": could not create file stream\n");
401 return DMUS_E_LOADER_FAILEDOPEN
;
404 hr
= IDirectMusicLoaderFileStream_Attach (pStream
, wszFileName
, iface
);
406 ERR(": could not attach stream to file\n");
407 IStream_Release (pStream
);
408 return DMUS_E_LOADER_FAILEDOPEN
;
411 else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
413 hr
= DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID
*)&pStream
);
415 ERR(": could not create generic stream\n");
416 return DMUS_E_LOADER_FAILEDOPEN
;
419 hr
= IDirectMusicLoaderGenericStream_Attach (pStream
, pDesc
->pStream
, iface
);
421 ERR(": could not attach stream\n");
422 IStream_Release (pStream
);
423 return DMUS_E_LOADER_FAILEDOPEN
;
426 else if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
428 hr
= DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID
*)&pStream
);
430 ERR(": could not create resource stream\n");
431 return DMUS_E_LOADER_FAILEDOPEN
;
434 hr
= IDirectMusicLoaderResourceStream_Attach (pStream
, pDesc
->pbMemData
, pDesc
->llMemLength
, 0, iface
);
436 ERR(": could not attach stream to resource\n");
437 IStream_Release (pStream
);
438 return DMUS_E_LOADER_FAILEDOPEN
;
442 ERR(": no way to get additional info\n");
443 return DMUS_E_LOADER_FAILEDOPEN
;
447 CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
449 /* *sigh*... some ms objects have lousy implementation of ParseDescriptor that clears input descriptor :( */
450 #ifdef NOW_WE_ARE_FREE
451 /* parse descriptor: we actually use input descriptor; fields that aren't available from stream remain,
452 otherwise real info is set */
453 IDirectMusicObject_ParseDescriptor (pObject
, pStream
, pDesc
);
455 /* hmph... due to some trouble I had with certain tests, we store current position and then set it back */
456 DM_STRUCT_INIT(&Desc
);
457 if (FAILED(IDirectMusicObject_ParseDescriptor (pObject
, pStream
, &Desc
))) {
458 ERR(": couldn't parse descriptor\n");
459 return DMUS_E_LOADER_FORMATNOTSUPPORTED
;
462 /* copy elements from parsed descriptor into input descriptor; this sets new info, overwriting if necessary,
463 but leaves info that's provided by input and not available from stream */
464 DMUSIC_CopyDescriptor (pDesc
, &Desc
);
466 /* release everything */
467 IDirectMusicObject_Release (pObject
);
468 IStream_Release (pStream
);
470 /* sometimes it happens that twisted programs call SetObject for same object twice...
471 in such cases, native loader returns S_OK and does nothing... a sound plan */
472 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
473 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
474 if (!memcmp (&pObjectEntry
->Desc
, pDesc
, sizeof(DMUS_OBJECTDESC
))) {
475 TRACE(": exactly same entry already exists\n");
481 TRACE(": adding alias entry with following info:\n%s\n", debugstr_DMUS_OBJECTDESC(pDesc
));
482 pNewEntry
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_ENTRY
));
483 /* use this function instead of pure memcpy due to streams (memcpy just copies pointer),
484 which is basically used further by app that called SetDescriptor... better safety than exception */
485 DMUSIC_CopyDescriptor (&pNewEntry
->Desc
, pDesc
);
486 list_add_head (This
->pObjects
, &pNewEntry
->entry
);
491 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, WCHAR
* pwzPath
, BOOL fClear
) {
492 WCHAR wszCurrentPath
[MAX_PATH
];
493 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
494 TRACE("(%p, %s, %s, %d)\n", This
, debugstr_dmguid(rguidClass
), debugstr_w(pwzPath
), fClear
);
495 FIXME(": fClear ignored\n");
496 DMUSIC_GetLoaderSettings (iface
, rguidClass
, wszCurrentPath
, NULL
);
497 if (!strncmpW(wszCurrentPath
, pwzPath
, MAX_PATH
)) {
500 /* FIXME: check if path is valid; else return DMUS_E_LOADER_BADPATH */
501 return DMUSIC_SetLoaderSettings (iface
, rguidClass
, pwzPath
, NULL
);
504 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, WCHAR
* pwzFileExtension
, WCHAR
* pwzScanFileName
) {
505 static const WCHAR wszAny
[] = {'*',0};
506 WIN32_FIND_DATAW FileData
;
508 WCHAR wszSearchString
[MAX_PATH
];
511 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
512 TRACE("(%p, %s, %p, %p)\n", This
, debugstr_dmguid(rguidClass
), pwzFileExtension
, pwzScanFileName
);
513 if (IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || !DMUSIC_IsValidLoadableClass(rguidClass
)) {
514 ERR(": rguidClass invalid CLSID\n");
515 return REGDB_E_CLASSNOTREG
;
518 /* get search path for given class */
519 DMUSIC_GetLoaderSettings (iface
, rguidClass
, wszSearchString
, NULL
);
521 p
= wszSearchString
+ lstrlenW(wszSearchString
);
522 if (p
> wszSearchString
&& p
[-1] != '\\') *p
++ = '\\';
523 *p
++ = '*'; /* any file */
524 if (strcmpW (pwzFileExtension
, wszAny
)) *p
++ = '.'; /* if we have actual extension, put a dot */
525 strcpyW (p
, pwzFileExtension
);
527 TRACE(": search string: %s\n", debugstr_w(wszSearchString
));
529 hSearch
= FindFirstFileW (wszSearchString
, &FileData
);
530 if (hSearch
== INVALID_HANDLE_VALUE
) {
531 TRACE(": no files found\n");
536 DMUS_OBJECTDESC Desc
;
537 DM_STRUCT_INIT(&Desc
);
538 Desc
.dwValidData
= DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_DATE
;
539 Desc
.guidClass
= *rguidClass
;
540 strcpyW (Desc
.wszFileName
, FileData
.cFileName
);
541 FileTimeToLocalFileTime (&FileData
.ftCreationTime
, &Desc
.ftDate
);
542 IDirectMusicLoader8_SetObject (iface
, &Desc
);
544 if (!FindNextFileW (hSearch
, &FileData
)) {
545 if (GetLastError () == ERROR_NO_MORE_FILES
) {
546 TRACE(": search completed\n");
549 ERR(": could not get next file\n");
558 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject (LPDIRECTMUSICLOADER8 iface
, IDirectMusicObject
* pObject
) {
559 DMUS_OBJECTDESC Desc
;
560 HRESULT result
= DMUS_E_LOADER_OBJECTNOTFOUND
;
562 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
564 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
565 TRACE("(%p, %p)\n", This
, pObject
);
568 DM_STRUCT_INIT(&Desc
);
569 IDirectMusicObject_GetDescriptor (pObject
, &Desc
);
571 /* now iterate thru list and check if we have alias (without object), corresponding
572 to descriptor of input object */
573 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
574 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
575 if ((Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
576 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
577 IsEqualGUID (&Desc
.guidObject
, &pObjectEntry
->Desc
.guidObject
)) {
578 TRACE(": found it by object GUID\n");
579 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
585 else if ((Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
586 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
587 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
588 TRACE(": found it by fullpath filename\n");
589 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
595 else if ((Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
596 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
597 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
598 !strncmpW (Desc
.wszCategory
, pObjectEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
599 TRACE(": found it by name and category\n");
600 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
606 else if ((Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
607 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
608 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
609 TRACE(": found it by name\n");
610 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
616 else if ((Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
617 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
618 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
619 TRACE(": found it by filename\n");
620 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
628 /* if we found such alias, then set everything */
629 if (result
== S_OK
) {
630 pObjectEntry
->Desc
.dwValidData
&= DMUS_OBJ_LOADED
;
631 pObjectEntry
->pObject
= pObject
;
632 IDirectMusicObject_AddRef (pObjectEntry
->pObject
);
638 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject (LPDIRECTMUSICLOADER8 iface
, IDirectMusicObject
* pObject
) {
639 DMUS_OBJECTDESC Desc
;
641 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
642 HRESULT result
= S_FALSE
;
644 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
645 TRACE("(%p, %p)\n", This
, pObject
);
648 DM_STRUCT_INIT(&Desc
);
649 IDirectMusicObject_GetDescriptor (pObject
, &Desc
);
651 /* iterate thru the list of objects we know about; check only those with DMUS_OBJ_LOADED */
652 TRACE(": looking for the object in cache\n");
653 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
654 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
655 if ((Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
656 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_OBJECT
| DMUS_OBJ_LOADED
)) &&
657 IsEqualGUID (&Desc
.guidObject
, &pObjectEntry
->Desc
.guidObject
)) {
658 TRACE(": found it by object GUID\n%s\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry
->Desc
));
662 else if ((Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
663 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_LOADED
)) &&
664 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
665 TRACE(": found it by fullpath filename\n");
669 else if ((Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
670 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
| DMUS_OBJ_LOADED
)) &&
671 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
672 !strncmpW (Desc
.wszCategory
, pObjectEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
673 TRACE(": found it by name and category\n");
677 else if ((Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
678 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_LOADED
)) &&
679 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
680 TRACE(": found it by name\n");
684 else if ((Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
685 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_LOADED
)) &&
686 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
687 TRACE(": found it by filename\n");
692 if (result
== S_OK
) {
693 /*TRACE(": releasing:\n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject); */
694 IDirectMusicObject_Release (pObjectEntry
->pObject
);
695 pObjectEntry
->pObject
= NULL
;
696 pObjectEntry
->Desc
.dwValidData
&= ~DMUS_OBJ_LOADED
;
701 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
) {
703 LPWINE_LOADER_ENTRY pObjectEntry
;
704 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
705 TRACE("(%p, %s)\n", This
, debugstr_dmguid(rguidClass
));
707 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
708 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
710 if ((IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || IsEqualGUID (rguidClass
, &pObjectEntry
->Desc
.guidClass
)) &&
711 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
)) {
712 /* basically, wrap to ReleaseObject for each object found */
713 IDirectMusicLoader8_ReleaseObject (iface
, pObjectEntry
->pObject
);
720 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, BOOL fEnable
) {
721 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
723 TRACE("(%p, %s, %d)\n", This
, debugstr_dmguid(rguidClass
), fEnable
);
724 DMUSIC_GetLoaderSettings (iface
, rguidClass
, NULL
, &bCurrent
);
725 if (bCurrent
== fEnable
)
728 return DMUSIC_SetLoaderSettings (iface
, rguidClass
, NULL
, &fEnable
);
731 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, DWORD dwIndex
, LPDMUS_OBJECTDESC pDesc
) {
734 LPWINE_LOADER_ENTRY pObjectEntry
;
735 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
736 TRACE("(%p, %s, %d, %p)\n", This
, debugstr_dmguid(rguidClass
), dwIndex
, pDesc
);
738 DM_STRUCT_INIT(pDesc
);
740 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
741 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
743 if (IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || IsEqualGUID (rguidClass
, &pObjectEntry
->Desc
.guidClass
)) {
744 if (dwCount
== dwIndex
) {
745 *pDesc
= pObjectEntry
->Desc
;
746 /* we aren't supposed to reveal this info */
747 pDesc
->dwValidData
&= ~(DMUS_OBJ_MEMORY
| DMUS_OBJ_STREAM
);
748 pDesc
->pbMemData
= NULL
;
749 pDesc
->llMemLength
= 0;
750 pDesc
->pStream
= NULL
;
757 TRACE(": not found\n");
761 static void WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage (LPDIRECTMUSICLOADER8 iface
) {
762 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
763 FIXME("(%p): stub\n", This
);
766 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown (LPDIRECTMUSICLOADER8 iface
, IUnknown
* pObject
) {
767 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
769 LPDIRECTMUSICOBJECT pObjectInterface
;
771 TRACE("(%p, %p)\n", This
, pObject
);
773 if (IsBadReadPtr (pObject
, sizeof(LPUNKNOWN
))) {
774 ERR(": pObject bad write pointer\n");
777 /* we simply get IDirectMusicObject interface */
778 result
= IUnknown_QueryInterface (pObject
, &IID_IDirectMusicObject
, (LPVOID
*)&pObjectInterface
);
779 if (FAILED(result
)) return result
;
780 /* and release it in old-fashioned way */
781 result
= IDirectMusicLoader8_ReleaseObject (iface
, pObjectInterface
);
782 IDirectMusicObject_Release (pObjectInterface
);
787 static HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClassID
, REFIID iidInterfaceID
, WCHAR
* pwzFilePath
, void** ppObject
) {
788 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
789 DMUS_OBJECTDESC ObjDesc
;
790 WCHAR wszLoaderSearchPath
[MAX_PATH
];
792 TRACE("(%p, %s, %s, %s, %p): wrapping to IDirectMusicLoaderImpl_GetObject\n", This
, debugstr_dmguid(rguidClassID
), debugstr_dmguid(iidInterfaceID
), debugstr_w(pwzFilePath
), ppObject
);
794 DM_STRUCT_INIT(&ObjDesc
);
795 ObjDesc
.dwValidData
= DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_CLASS
; /* I believe I've read somewhere in MSDN that this function requires either full path or relative path */
796 ObjDesc
.guidClass
= *rguidClassID
;
797 /* OK, MSDN says that search order is the following:
798 - current directory (DONE)
799 - windows search path (FIXME: how do I get that?)
800 - loader's search path (DONE)
802 DMUSIC_GetLoaderSettings (iface
, rguidClassID
, wszLoaderSearchPath
, NULL
);
803 /* search in current directory */
804 if (!SearchPathW (NULL
, pwzFilePath
, NULL
, sizeof(ObjDesc
.wszFileName
)/sizeof(WCHAR
), ObjDesc
.wszFileName
, NULL
) &&
805 /* search in loader's search path */
806 !SearchPathW (wszLoaderSearchPath
, pwzFilePath
, NULL
, sizeof(ObjDesc
.wszFileName
)/sizeof(WCHAR
), ObjDesc
.wszFileName
, NULL
)) {
807 /* cannot find file */
808 TRACE(": cannot find file\n");
809 return DMUS_E_LOADER_FAILEDOPEN
;
812 TRACE(": full file path = %s\n", debugstr_w (ObjDesc
.wszFileName
));
814 return IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject (iface
, &ObjDesc
, iidInterfaceID
, ppObject
);
817 static const IDirectMusicLoader8Vtbl DirectMusicLoader_Loader_Vtbl
= {
818 IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface
,
819 IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef
,
820 IDirectMusicLoaderImpl_IDirectMusicLoader_Release
,
821 IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject
,
822 IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject
,
823 IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory
,
824 IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory
,
825 IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject
,
826 IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject
,
827 IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache
,
828 IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache
,
829 IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject
,
830 IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage
,
831 IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown
,
832 IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile
835 /* help function for DMUSIC_SetDefaultDLS */
836 static HRESULT
DMUSIC_GetDefaultGMPath (WCHAR wszPath
[MAX_PATH
]) {
838 DWORD returnType
, sizeOfReturnBuffer
= MAX_PATH
;
839 char szPath
[MAX_PATH
];
841 if ((RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic" , 0, KEY_READ
, &hkDM
) != ERROR_SUCCESS
) ||
842 (RegQueryValueExA (hkDM
, "GMFilePath", NULL
, &returnType
, (LPBYTE
) szPath
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
)) {
843 WARN(": registry entry missing\n" );
846 /* FIXME: Check return types to ensure we're interpreting data right */
847 MultiByteToWideChar (CP_ACP
, 0, szPath
, -1, wszPath
, MAX_PATH
);
852 /* for ClassFactory */
853 HRESULT WINAPI
DMUSIC_CreateDirectMusicLoaderImpl (LPCGUID lpcGUID
, LPVOID
*ppobj
, LPUNKNOWN pUnkOuter
) {
854 IDirectMusicLoaderImpl
*obj
;
855 DMUS_OBJECTDESC Desc
;
856 LPWINE_LOADER_ENTRY pDefaultDLSEntry
;
859 TRACE("(%s, %p, %p)\n", debugstr_dmguid(lpcGUID
), ppobj
, pUnkOuter
);
860 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicLoaderImpl
));
863 return E_OUTOFMEMORY
;
865 obj
->LoaderVtbl
= &DirectMusicLoader_Loader_Vtbl
;
866 obj
->dwRef
= 0; /* will be inited with QueryInterface */
867 /* init critical section */
868 /* init cache/alias list */
869 /*InitializeCriticalSection (&obj->CritSect);
870 obj->CritSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectMusicLoaderImpl.CritSect"); */
871 obj
->pObjects
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(struct list
));
872 list_init (obj
->pObjects
);
874 obj
->pClassSettings
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(struct list
));
875 list_init (obj
->pClassSettings
);
876 DMUSIC_InitLoaderSettings ((LPDIRECTMUSICLOADER8
)obj
);
878 /* set default DLS collection (via SetObject... so that loading via DMUS_OBJ_OBJECT is possible) */
879 DM_STRUCT_INIT(&Desc
);
880 Desc
.dwValidData
= DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_OBJECT
;
881 Desc
.guidClass
= CLSID_DirectMusicCollection
;
882 Desc
.guidObject
= GUID_DefaultGMCollection
;
883 DMUSIC_GetDefaultGMPath (Desc
.wszFileName
);
884 IDirectMusicLoader_SetObject ((LPDIRECTMUSICLOADER8
)obj
, &Desc
);
885 /* and now the workaroundTM for "invalid" default DLS; basically,
886 my tests showed that if GUID chunk is present in default DLS
887 collection, loader treats it as "invalid" and returns
888 DMUS_E_LOADER_NOFILENAME for all requests for it; basically, we check
889 if out input guidObject was overwritten */
890 pEntry
= list_head (obj
->pObjects
);
891 pDefaultDLSEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
892 if (!IsEqualGUID(&Desc
.guidObject
, &GUID_DefaultGMCollection
)) {
893 pDefaultDLSEntry
->bInvalidDefaultDLS
= TRUE
;
896 /* increase number of instances */
897 InterlockedIncrement (&dwDirectMusicLoader
);
899 return IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface ((LPDIRECTMUSICLOADER8
)obj
, lpcGUID
, ppobj
);
902 /* help function for retrieval of search path and caching option for certain class */
903 static HRESULT
DMUSIC_GetLoaderSettings (LPDIRECTMUSICLOADER8 iface
, REFGUID pClassID
, WCHAR
* wszSearchPath
, LPBOOL pbCache
) {
904 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
906 TRACE(": (%p, %s, %p, %p)\n", This
, debugstr_dmguid(pClassID
), wszSearchPath
, pbCache
);
908 LIST_FOR_EACH(pEntry
, This
->pClassSettings
) {
909 LPWINE_LOADER_OPTION pOptionEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_OPTION
, entry
);
910 if (IsEqualCLSID (pClassID
, &pOptionEntry
->guidClass
)) {
912 strcpyW(wszSearchPath
, pOptionEntry
->wszSearchPath
);
914 *pbCache
= pOptionEntry
->bCache
;
921 /* help function for setting search path and caching option for certain class */
922 static HRESULT
DMUSIC_SetLoaderSettings (LPDIRECTMUSICLOADER8 iface
, REFGUID pClassID
, WCHAR
* wszSearchPath
, LPBOOL pbCache
) {
923 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
925 HRESULT result
= S_FALSE
; /* in case pClassID != GUID_DirectMusicAllTypes and not a valid CLSID */
926 TRACE(": (%p, %s, %p, %p)\n", This
, debugstr_dmguid(pClassID
), wszSearchPath
, pbCache
);
928 LIST_FOR_EACH(pEntry
, This
->pClassSettings
) {
929 LPWINE_LOADER_OPTION pOptionEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_OPTION
, entry
);
930 /* well, either we have GUID_DirectMusicAllTypes and need to set it to all,
931 or specific CLSID is given and we set it only to it */
932 if (IsEqualGUID (pClassID
, &GUID_DirectMusicAllTypes
) ||
933 IsEqualCLSID (pClassID
, &pOptionEntry
->guidClass
)) {
935 strcpyW(pOptionEntry
->wszSearchPath
, wszSearchPath
);
937 pOptionEntry
->bCache
= *pbCache
;
945 static HRESULT
DMUSIC_InitLoaderSettings (LPDIRECTMUSICLOADER8 iface
) {
946 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
948 /* hard-coded list of classes */
949 static REFCLSID classes
[] = {
950 &CLSID_DirectMusicAudioPathConfig
,
951 &CLSID_DirectMusicBand
,
952 &CLSID_DirectMusicContainer
,
953 &CLSID_DirectMusicCollection
,
954 &CLSID_DirectMusicChordMap
,
955 &CLSID_DirectMusicSegment
,
956 &CLSID_DirectMusicScript
,
957 &CLSID_DirectMusicSong
,
958 &CLSID_DirectMusicStyle
,
959 &CLSID_DirectMusicGraph
,
960 &CLSID_DirectSoundWave
964 WCHAR wszCurrent
[MAX_PATH
];
966 TRACE(": (%p)\n", This
);
967 GetCurrentDirectoryW (MAX_PATH
, wszCurrent
);
969 for (i
= 0; i
< sizeof(classes
)/sizeof(REFCLSID
); i
++) {
970 LPWINE_LOADER_OPTION pNewSetting
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_OPTION
));
971 pNewSetting
->guidClass
= *classes
[i
];
972 strcpyW (pNewSetting
->wszSearchPath
, wszCurrent
);
973 pNewSetting
->bCache
= TRUE
;
974 list_add_tail (This
->pClassSettings
, &pNewSetting
->entry
);