2 * IDirectMusicLoaderImpl
4 * Copyright (C) 2003-2004 Rok Mandeljc
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "dmloader_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmloader
);
25 static inline IDirectMusicLoaderImpl
* impl_from_IDirectMusicLoader8(IDirectMusicLoader8
*iface
)
27 return CONTAINING_RECORD(iface
, IDirectMusicLoaderImpl
, IDirectMusicLoader8_iface
);
30 static HRESULT
DMUSIC_InitLoaderSettings(IDirectMusicLoader8
*iface
);
31 static HRESULT
DMUSIC_GetLoaderSettings(IDirectMusicLoader8
*iface
, REFGUID class_id
, WCHAR
*search_path
, BOOL
*cache
);
32 static HRESULT
DMUSIC_SetLoaderSettings(IDirectMusicLoader8
*iface
, REFGUID class_id
, WCHAR
*search_path
, BOOL
*cache
);
34 static HRESULT
DMUSIC_CopyDescriptor(DMUS_OBJECTDESC
*pDst
, DMUS_OBJECTDESC
*pSrc
)
36 if (TRACE_ON(dmloader
))
37 dump_DMUS_OBJECTDESC(pSrc
);
39 /* copy field by field */
40 if (pSrc
->dwValidData
& DMUS_OBJ_CLASS
) pDst
->guidClass
= pSrc
->guidClass
;
41 if (pSrc
->dwValidData
& DMUS_OBJ_OBJECT
) pDst
->guidObject
= pSrc
->guidObject
;
42 if (pSrc
->dwValidData
& DMUS_OBJ_DATE
) pDst
->ftDate
= pSrc
->ftDate
;
43 if (pSrc
->dwValidData
& DMUS_OBJ_VERSION
) pDst
->vVersion
= pSrc
->vVersion
;
44 if (pSrc
->dwValidData
& DMUS_OBJ_NAME
) strcpyW (pDst
->wszName
, pSrc
->wszName
);
45 if (pSrc
->dwValidData
& DMUS_OBJ_CATEGORY
) strcpyW (pDst
->wszCategory
, pSrc
->wszCategory
);
46 if (pSrc
->dwValidData
& DMUS_OBJ_FILENAME
) strcpyW (pDst
->wszFileName
, pSrc
->wszFileName
);
47 if (pSrc
->dwValidData
& DMUS_OBJ_STREAM
) IStream_Clone (pSrc
->pStream
, &pDst
->pStream
);
48 if (pSrc
->dwValidData
& DMUS_OBJ_MEMORY
) {
49 pDst
->pbMemData
= pSrc
->pbMemData
;
50 pDst
->llMemLength
= pSrc
->llMemLength
;
53 pDst
->dwValidData
|= pSrc
->dwValidData
;
58 static BOOL
DMUSIC_IsValidLoadableClass (REFCLSID pClassID
) {
59 if (IsEqualCLSID(pClassID
, &CLSID_DirectMusicAudioPathConfig
) ||
60 IsEqualCLSID(pClassID
, &CLSID_DirectMusicBand
) ||
61 IsEqualCLSID(pClassID
, &CLSID_DirectMusicContainer
) ||
62 IsEqualCLSID(pClassID
, &CLSID_DirectMusicCollection
) ||
63 IsEqualCLSID(pClassID
, &CLSID_DirectMusicChordMap
) ||
64 IsEqualCLSID(pClassID
, &CLSID_DirectMusicSegment
) ||
65 IsEqualCLSID(pClassID
, &CLSID_DirectMusicScript
) ||
66 IsEqualCLSID(pClassID
, &CLSID_DirectMusicSong
) ||
67 IsEqualCLSID(pClassID
, &CLSID_DirectMusicStyle
) ||
68 IsEqualCLSID(pClassID
, &CLSID_DirectMusicGraph
) ||
69 IsEqualCLSID(pClassID
, &CLSID_DirectSoundWave
) ||
70 IsEqualCLSID(pClassID
, &GUID_DirectMusicAllTypes
))
76 /*****************************************************************************
77 * IDirectMusicLoaderImpl implementation
79 /* IUnknown/IDirectMusicLoader(8) part: */
81 static HRESULT WINAPI
IDirectMusicLoaderImpl_QueryInterface(IDirectMusicLoader8
*iface
, REFIID riid
, void **ppobj
)
83 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
85 TRACE("(%p, %s, %p)\n",This
, debugstr_dmguid(riid
), ppobj
);
86 if (IsEqualIID (riid
, &IID_IUnknown
) ||
87 IsEqualIID (riid
, &IID_IDirectMusicLoader
) ||
88 IsEqualIID (riid
, &IID_IDirectMusicLoader8
)) {
89 IDirectMusicLoader_AddRef (iface
);
94 WARN(": not found\n");
98 static ULONG WINAPI
IDirectMusicLoaderImpl_AddRef(IDirectMusicLoader8
*iface
)
100 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
101 ULONG ref
= InterlockedIncrement(&This
->ref
);
103 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
108 static ULONG WINAPI
IDirectMusicLoaderImpl_Release(IDirectMusicLoader8
*iface
)
110 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
111 ULONG ref
= InterlockedDecrement(&This
->ref
);
113 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
116 /* Firstly, release the cache */
117 IDirectMusicLoader8_ClearCache(iface
, &GUID_DirectMusicAllTypes
);
118 /* FIXME: Release all allocated entries */
119 HeapFree(GetProcessHeap(), 0, This
);
126 static HRESULT WINAPI
IDirectMusicLoaderImpl_GetObject(IDirectMusicLoader8
*iface
, DMUS_OBJECTDESC
*pDesc
, REFIID riid
, void **ppv
)
128 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
129 HRESULT result
= S_OK
;
130 HRESULT ret
= S_OK
; /* used at the end of function, to determine whether everything went OK */
133 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
135 IPersistStream
* pPersistStream
= NULL
;
137 LPDIRECTMUSICOBJECT pObject
;
138 DMUS_OBJECTDESC GotDesc
;
141 TRACE("(%p)->(%p, %s, %p)\n", This
, pDesc
, debugstr_dmguid(riid
), ppv
);
143 if (TRACE_ON(dmloader
))
144 dump_DMUS_OBJECTDESC(pDesc
);
146 /* sometimes it happens that guidClass is missing... which is a BadThingTM */
147 if (!(pDesc
->dwValidData
& DMUS_OBJ_CLASS
)) {
148 ERR(": guidClass not valid but needed\n");
150 return DMUS_E_LOADER_NOCLASSID
;
153 /* OK, first we iterate through the list of objects we know about; these are either loaded (GetObject, LoadObjectFromFile)
154 or set via SetObject; */
155 TRACE(": looking if we have object in the cache or if it can be found via alias\n");
156 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
157 LPWINE_LOADER_ENTRY pExistingEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
158 if ((pDesc
->dwValidData
& DMUS_OBJ_OBJECT
) &&
159 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
160 IsEqualGUID (&pDesc
->guidObject
, &pExistingEntry
->Desc
.guidObject
)) {
161 TRACE(": found it by object GUID\n");
162 /* I suppose such stuff can happen only when GUID for object is given (GUID_DefaultGMCollection) */
163 if (pExistingEntry
->bInvalidDefaultDLS
) {
164 TRACE(": found faulty default DLS collection... enabling M$ compliant behaviour\n");
165 return DMUS_E_LOADER_NOFILENAME
;
167 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
168 TRACE(": already loaded\n");
169 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
171 TRACE(": not loaded yet\n");
172 pObjectEntry
= pExistingEntry
;
175 else if ((pDesc
->dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
176 (pExistingEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
177 !strncmpW (pDesc
->wszFileName
, pExistingEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
178 TRACE(": found it by fullpath filename\n");
179 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
180 TRACE(": already loaded\n");
181 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
183 TRACE(": not loaded yet\n");
184 pObjectEntry
= pExistingEntry
;
187 else if ((pDesc
->dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
188 (pExistingEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
189 !strncmpW (pDesc
->wszName
, pExistingEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
190 !strncmpW (pDesc
->wszCategory
, pExistingEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
191 TRACE(": found it by name and category\n");
192 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
193 TRACE(": already loaded\n");
194 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
196 TRACE(": not loaded yet\n");
197 pObjectEntry
= pExistingEntry
;
200 else if ((pDesc
->dwValidData
& DMUS_OBJ_NAME
) &&
201 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
202 !strncmpW (pDesc
->wszName
, pExistingEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
203 TRACE(": found it by name\n");
204 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
205 TRACE(": already loaded\n");
206 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
208 TRACE(": not loaded yet\n");
209 pObjectEntry
= pExistingEntry
;
212 else if ((pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) &&
213 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
214 !strncmpW (pDesc
->wszFileName
, pExistingEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
215 TRACE(": found it by filename\n");
216 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
217 TRACE(": already loaded\n");
218 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
220 TRACE(": not loaded yet\n");
221 pObjectEntry
= pExistingEntry
;
226 /* basically, if we found alias, we use its descriptor to load...
227 else we use info we were given */
229 TRACE(": found alias entry for requested object... using stored info\n");
230 /* I think in certain cases it can happen that entry's descriptor lacks info about
231 where to load from (e.g.: if we loaded from stream and then released object
232 from cache; then only its CLSID, GUID and perhaps name are left); so just
233 overwrite whatever info the entry has (since it ought to be 100% correct) */
234 DMUSIC_CopyDescriptor (pDesc
, &pObjectEntry
->Desc
);
235 /*pDesc = &pObjectEntry->Desc; */ /* FIXME: is this OK? */
237 TRACE(": no cache/alias entry found for requested object\n");
240 if (pDesc
->dwValidData
& DMUS_OBJ_URL
) {
241 TRACE(": loading from URLs not supported yet\n");
242 return DMUS_E_LOADER_FORMATNOTSUPPORTED
;
244 else if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
245 /* load object from file */
246 /* generate filename; if it's full path, don't add search
247 directory path, otherwise do */
248 WCHAR wszFileName
[MAX_PATH
];
250 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
251 lstrcpyW(wszFileName
, pDesc
->wszFileName
);
253 WCHAR
*p
, wszSearchPath
[MAX_PATH
];
254 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, wszSearchPath
, NULL
);
255 lstrcpyW(wszFileName
, wszSearchPath
);
256 p
= wszFileName
+ lstrlenW(wszFileName
);
257 if (p
> wszFileName
&& p
[-1] != '\\') *p
++ = '\\';
258 strcpyW(p
, pDesc
->wszFileName
);
260 TRACE(": loading from file (%s)\n", debugstr_w(wszFileName
));
261 /* create stream and associate it with file */
262 result
= DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID
*)&pStream
);
263 if (FAILED(result
)) {
264 ERR(": could not create file stream\n");
267 result
= IDirectMusicLoaderFileStream_Attach (pStream
, wszFileName
, iface
);
268 if (FAILED(result
)) {
269 ERR(": could not attach stream to file\n");
270 IStream_Release (pStream
);
274 else if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
275 /* load object from resource */
276 TRACE(": loading from resource\n");
277 /* create stream and associate it with given resource */
278 result
= DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID
*)&pStream
);
279 if (FAILED(result
)) {
280 ERR(": could not create resource stream\n");
283 result
= IDirectMusicLoaderResourceStream_Attach (pStream
, pDesc
->pbMemData
, pDesc
->llMemLength
, 0, iface
);
284 if (FAILED(result
)) {
285 ERR(": could not attach stream to resource\n");
286 IStream_Release (pStream
);
290 else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
291 /* load object from stream */
292 TRACE(": loading from stream\n");
293 /* create universal stream and associate it with given one */
294 result
= DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID
*)&pStream
);
295 if (FAILED(result
)) {
296 ERR(": could not create generic stream\n");
299 result
= IDirectMusicLoaderGenericStream_Attach (pStream
, pDesc
->pStream
, iface
);
300 if (FAILED(result
)) {
301 ERR(": failed to attach stream\n");
302 IStream_Release (pStream
);
306 /* nowhere to load from */
307 FIXME(": unknown/unsupported way of loading\n");
308 return DMUS_E_LOADER_NOFILENAME
; /* test shows this is returned */
312 result
= CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
313 if (FAILED(result
)) {
314 ERR(": could not create object\n");
317 /* acquire PersistStream interface */
318 result
= IDirectMusicObject_QueryInterface (pObject
, &IID_IPersistStream
, (LPVOID
*)&pPersistStream
);
319 if (FAILED(result
)) {
320 ERR("failed to Query\n");
324 result
= IPersistStream_Load (pPersistStream
, pStream
);
325 if (result
!= S_OK
) {
326 WARN(": failed to (completely) load object (%s)\n", debugstr_dmreturn(result
));
330 DM_STRUCT_INIT(&GotDesc
);
331 result
= IDirectMusicObject_GetDescriptor (pObject
, &GotDesc
);
332 /* set filename (if we loaded via filename) */
333 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
334 GotDesc
.dwValidData
|= (pDesc
->dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
));
335 strcpyW (GotDesc
.wszFileName
, pDesc
->wszFileName
);
337 if (FAILED(result
)) {
338 ERR(": failed to get descriptor\n");
341 /* release all loading related stuff */
342 IStream_Release (pStream
);
343 IPersistStream_Release (pPersistStream
);
345 /* add object to cache/overwrite existing info (if cache is enabled) */
346 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, NULL
, &bCache
);
349 pObjectEntry
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_ENTRY
));
350 DM_STRUCT_INIT(&pObjectEntry
->Desc
);
351 DMUSIC_CopyDescriptor (&pObjectEntry
->Desc
, &GotDesc
);
352 pObjectEntry
->pObject
= pObject
;
353 pObjectEntry
->bInvalidDefaultDLS
= FALSE
;
354 list_add_head (This
->pObjects
, &pObjectEntry
->entry
);
356 DMUSIC_CopyDescriptor (&pObjectEntry
->Desc
, &GotDesc
);
357 pObjectEntry
->pObject
= pObject
;
358 pObjectEntry
->bInvalidDefaultDLS
= FALSE
;
360 TRACE(": filled in cache entry\n");
361 } else TRACE(": caching disabled\n");
364 /* for debug purposes (e.g. to check if all files are cached) */
365 TRACE("*** Loader's cache ***\n");
367 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
369 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
370 TRACE(": entry nr. %i:\n%s\n - bInvalidDefaultDLS = %i\n - pObject = %p\n", i
, debugstr_DMUS_OBJECTDESC(&pObjectEntry
->Desc
), pObjectEntry
->bInvalidDefaultDLS
, pObjectEntry
->pObject
);
374 result
= IDirectMusicObject_QueryInterface (pObject
, riid
, ppv
);
375 if (!bCache
) IDirectMusicObject_Release (pObject
); /* since loader's reference is not needed */
376 /* if there was trouble with loading, and if no other error occurred,
377 we should return DMUS_S_PARTIALLOAD; else, error is returned */
384 static HRESULT WINAPI
IDirectMusicLoaderImpl_SetObject(IDirectMusicLoader8
*iface
, DMUS_OBJECTDESC
*pDesc
)
386 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
388 LPDIRECTMUSICOBJECT pObject
;
389 DMUS_OBJECTDESC Desc
;
391 LPWINE_LOADER_ENTRY pObjectEntry
, pNewEntry
;
394 TRACE("(%p)->(%p)\n", This
, pDesc
);
396 if (TRACE_ON(dmloader
))
397 dump_DMUS_OBJECTDESC(pDesc
);
399 /* create stream and load additional info from it */
400 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
401 /* generate filename; if it's full path, don't add search
402 directory path, otherwise do */
403 WCHAR wszFileName
[MAX_PATH
];
405 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
406 lstrcpyW(wszFileName
, pDesc
->wszFileName
);
409 WCHAR wszSearchPath
[MAX_PATH
];
410 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, wszSearchPath
, NULL
);
411 lstrcpyW(wszFileName
, wszSearchPath
);
412 p
= wszFileName
+ lstrlenW(wszFileName
);
413 if (p
> wszFileName
&& p
[-1] != '\\') *p
++ = '\\';
414 strcpyW(p
, pDesc
->wszFileName
);
417 hr
= DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID
*)&pStream
);
419 ERR(": could not create file stream\n");
420 return DMUS_E_LOADER_FAILEDOPEN
;
423 hr
= IDirectMusicLoaderFileStream_Attach (pStream
, wszFileName
, iface
);
425 ERR(": could not attach stream to file %s, make sure it exists\n", debugstr_w(wszFileName
));
426 IStream_Release (pStream
);
427 return DMUS_E_LOADER_FAILEDOPEN
;
430 else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
432 hr
= DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID
*)&pStream
);
434 ERR(": could not create generic stream\n");
435 return DMUS_E_LOADER_FAILEDOPEN
;
438 hr
= IDirectMusicLoaderGenericStream_Attach (pStream
, pDesc
->pStream
, iface
);
440 ERR(": could not attach stream\n");
441 IStream_Release (pStream
);
442 return DMUS_E_LOADER_FAILEDOPEN
;
445 else if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
447 hr
= DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID
*)&pStream
);
449 ERR(": could not create resource stream\n");
450 return DMUS_E_LOADER_FAILEDOPEN
;
453 hr
= IDirectMusicLoaderResourceStream_Attach (pStream
, pDesc
->pbMemData
, pDesc
->llMemLength
, 0, iface
);
455 ERR(": could not attach stream to resource\n");
456 IStream_Release (pStream
);
457 return DMUS_E_LOADER_FAILEDOPEN
;
461 ERR(": no way to get additional info\n");
462 return DMUS_E_LOADER_FAILEDOPEN
;
466 hr
= CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
468 ERR("Object creation of %s failed 0x%08x\n", debugstr_guid(&pDesc
->guidClass
),hr
);
469 return DMUS_E_LOADER_FAILEDOPEN
;
472 /* *sigh*... some ms objects have lousy implementation of ParseDescriptor that clears input descriptor :( */
473 #ifdef NOW_WE_ARE_FREE
474 /* parse descriptor: we actually use input descriptor; fields that aren't available from stream remain,
475 otherwise real info is set */
476 IDirectMusicObject_ParseDescriptor (pObject
, pStream
, pDesc
);
478 /* hmph... due to some trouble I had with certain tests, we store current position and then set it back */
479 DM_STRUCT_INIT(&Desc
);
480 if (FAILED(IDirectMusicObject_ParseDescriptor (pObject
, pStream
, &Desc
))) {
481 ERR(": couldn't parse descriptor\n");
482 return DMUS_E_LOADER_FORMATNOTSUPPORTED
;
485 /* copy elements from parsed descriptor into input descriptor; this sets new info, overwriting if necessary,
486 but leaves info that's provided by input and not available from stream */
487 DMUSIC_CopyDescriptor (pDesc
, &Desc
);
489 /* release everything */
490 IDirectMusicObject_Release (pObject
);
491 IStream_Release (pStream
);
493 /* sometimes it happens that twisted programs call SetObject for same object twice...
494 in such cases, native loader returns S_OK and does nothing... a sound plan */
495 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
496 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
497 if (!memcmp (&pObjectEntry
->Desc
, pDesc
, sizeof(DMUS_OBJECTDESC
))) {
498 TRACE(": exactly same entry already exists\n");
504 TRACE(": adding alias entry with following info:\n");
505 if (TRACE_ON(dmloader
))
506 dump_DMUS_OBJECTDESC(pDesc
);
507 pNewEntry
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_ENTRY
));
508 /* use this function instead of pure memcpy due to streams (memcpy just copies pointer),
509 which is basically used further by app that called SetDescriptor... better safety than exception */
510 DMUSIC_CopyDescriptor (&pNewEntry
->Desc
, pDesc
);
511 list_add_head (This
->pObjects
, &pNewEntry
->entry
);
516 static HRESULT WINAPI
IDirectMusicLoaderImpl_SetSearchDirectory(IDirectMusicLoader8
*iface
,
517 REFGUID
class, WCHAR
*path
, BOOL clear
)
519 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
520 WCHAR current_path
[MAX_PATH
];
523 TRACE("(%p, %s, %s, %d)\n", This
, debugstr_dmguid(class), debugstr_w(path
), clear
);
525 attr
= GetFileAttributesW(path
);
526 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
527 return DMUS_E_LOADER_BADPATH
;
530 FIXME("clear flag ignored\n");
532 DMUSIC_GetLoaderSettings(iface
, class, current_path
, NULL
);
533 if (!strncmpW(current_path
, path
, MAX_PATH
))
536 return DMUSIC_SetLoaderSettings(iface
, class, path
, NULL
);
539 static HRESULT WINAPI
IDirectMusicLoaderImpl_ScanDirectory(IDirectMusicLoader8
*iface
, REFGUID rguidClass
, WCHAR
*pwzFileExtension
, WCHAR
*pwzScanFileName
)
541 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
542 static const WCHAR wszAny
[] = {'*',0};
543 WIN32_FIND_DATAW FileData
;
545 WCHAR wszSearchString
[MAX_PATH
];
548 TRACE("(%p, %s, %s, %s)\n", This
, debugstr_dmguid(rguidClass
), debugstr_w(pwzFileExtension
),
549 debugstr_w(pwzScanFileName
));
550 if (IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || !DMUSIC_IsValidLoadableClass(rguidClass
)) {
551 ERR(": rguidClass invalid CLSID\n");
552 return REGDB_E_CLASSNOTREG
;
555 if (!pwzFileExtension
)
558 /* get search path for given class */
559 DMUSIC_GetLoaderSettings (iface
, rguidClass
, wszSearchString
, NULL
);
561 p
= wszSearchString
+ lstrlenW(wszSearchString
);
562 if (p
> wszSearchString
&& p
[-1] != '\\') *p
++ = '\\';
563 *p
++ = '*'; /* any file */
564 if (strcmpW (pwzFileExtension
, wszAny
)) *p
++ = '.'; /* if we have actual extension, put a dot */
565 strcpyW (p
, pwzFileExtension
);
567 TRACE(": search string: %s\n", debugstr_w(wszSearchString
));
569 hSearch
= FindFirstFileW (wszSearchString
, &FileData
);
570 if (hSearch
== INVALID_HANDLE_VALUE
) {
571 TRACE(": no files found\n");
576 DMUS_OBJECTDESC Desc
;
577 DM_STRUCT_INIT(&Desc
);
578 Desc
.dwValidData
= DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_DATE
;
579 Desc
.guidClass
= *rguidClass
;
580 strcpyW (Desc
.wszFileName
, FileData
.cFileName
);
581 FileTimeToLocalFileTime (&FileData
.ftCreationTime
, &Desc
.ftDate
);
582 IDirectMusicLoader8_SetObject (iface
, &Desc
);
584 if (!FindNextFileW (hSearch
, &FileData
)) {
585 if (GetLastError () == ERROR_NO_MORE_FILES
) {
586 TRACE(": search completed\n");
589 ERR(": could not get next file\n");
598 static HRESULT WINAPI
IDirectMusicLoaderImpl_CacheObject(IDirectMusicLoader8
*iface
, IDirectMusicObject
*pObject
)
600 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
601 DMUS_OBJECTDESC Desc
;
602 HRESULT result
= DMUS_E_LOADER_OBJECTNOTFOUND
;
604 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
606 TRACE("(%p, %p)\n", This
, pObject
);
609 DM_STRUCT_INIT(&Desc
);
610 IDirectMusicObject_GetDescriptor (pObject
, &Desc
);
612 /* now iterate through the list and check if we have an alias (without object), corresponding
613 to the descriptor of the input object */
614 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
615 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
616 if ((Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
617 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
618 IsEqualGUID (&Desc
.guidObject
, &pObjectEntry
->Desc
.guidObject
)) {
619 TRACE(": found it by object GUID\n");
620 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
626 else if ((Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
627 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
628 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
629 TRACE(": found it by fullpath filename\n");
630 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
636 else if ((Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
637 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
638 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
639 !strncmpW (Desc
.wszCategory
, pObjectEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
640 TRACE(": found it by name and category\n");
641 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
647 else if ((Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
648 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
649 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
650 TRACE(": found it by name\n");
651 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
657 else if ((Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
658 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
659 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
660 TRACE(": found it by filename\n");
661 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
669 /* if we found such alias, then set everything */
670 if (result
== S_OK
) {
671 pObjectEntry
->Desc
.dwValidData
&= DMUS_OBJ_LOADED
;
672 pObjectEntry
->pObject
= pObject
;
673 IDirectMusicObject_AddRef (pObjectEntry
->pObject
);
679 static HRESULT WINAPI
IDirectMusicLoaderImpl_ReleaseObject(IDirectMusicLoader8
*iface
, IDirectMusicObject
*pObject
)
681 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
682 DMUS_OBJECTDESC Desc
;
684 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
685 HRESULT result
= S_FALSE
;
687 TRACE("(%p, %p)\n", This
, pObject
);
689 if(!pObject
) return E_POINTER
;
692 DM_STRUCT_INIT(&Desc
);
693 IDirectMusicObject_GetDescriptor (pObject
, &Desc
);
695 /* iterate through the list of objects we know about; check only those with DMUS_OBJ_LOADED */
696 TRACE(": looking for the object in cache\n");
697 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
698 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
699 if ((Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
700 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_OBJECT
| DMUS_OBJ_LOADED
)) &&
701 IsEqualGUID (&Desc
.guidObject
, &pObjectEntry
->Desc
.guidObject
)) {
702 TRACE(": found it by object GUID\n");
703 if (TRACE_ON(dmloader
))
704 dump_DMUS_OBJECTDESC(&pObjectEntry
->Desc
);
708 else if ((Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
709 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_LOADED
)) &&
710 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
711 TRACE(": found it by fullpath filename\n");
715 else if ((Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
716 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
| DMUS_OBJ_LOADED
)) &&
717 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
718 !strncmpW (Desc
.wszCategory
, pObjectEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
719 TRACE(": found it by name and category\n");
723 else if ((Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
724 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_LOADED
)) &&
725 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
726 TRACE(": found it by name\n");
730 else if ((Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
731 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_LOADED
)) &&
732 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
733 TRACE(": found it by filename\n");
738 if (result
== S_OK
) {
739 /*TRACE(": releasing:\n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject); */
740 IDirectMusicObject_Release (pObjectEntry
->pObject
);
741 pObjectEntry
->pObject
= NULL
;
742 pObjectEntry
->Desc
.dwValidData
&= ~DMUS_OBJ_LOADED
;
747 static HRESULT WINAPI
IDirectMusicLoaderImpl_ClearCache(IDirectMusicLoader8
*iface
, REFGUID rguidClass
)
749 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
751 LPWINE_LOADER_ENTRY pObjectEntry
;
752 TRACE("(%p, %s)\n", This
, debugstr_dmguid(rguidClass
));
754 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
755 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
757 if ((IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || IsEqualGUID (rguidClass
, &pObjectEntry
->Desc
.guidClass
)) &&
758 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
)) {
759 /* basically, wrap to ReleaseObject for each object found */
760 IDirectMusicLoader8_ReleaseObject (iface
, pObjectEntry
->pObject
);
767 static HRESULT WINAPI
IDirectMusicLoaderImpl_EnableCache(IDirectMusicLoader8
*iface
, REFGUID rguidClass
, BOOL fEnable
)
769 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
771 TRACE("(%p, %s, %d)\n", This
, debugstr_dmguid(rguidClass
), fEnable
);
772 DMUSIC_GetLoaderSettings (iface
, rguidClass
, NULL
, &bCurrent
);
773 if (bCurrent
== fEnable
)
776 return DMUSIC_SetLoaderSettings (iface
, rguidClass
, NULL
, &fEnable
);
779 static HRESULT WINAPI
IDirectMusicLoaderImpl_EnumObject(IDirectMusicLoader8
*iface
, REFGUID rguidClass
, DWORD dwIndex
, DMUS_OBJECTDESC
*pDesc
)
781 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
784 LPWINE_LOADER_ENTRY pObjectEntry
;
785 TRACE("(%p, %s, %d, %p)\n", This
, debugstr_dmguid(rguidClass
), dwIndex
, pDesc
);
787 DM_STRUCT_INIT(pDesc
);
789 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
790 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
792 if (IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || IsEqualGUID (rguidClass
, &pObjectEntry
->Desc
.guidClass
)) {
793 if (dwCount
== dwIndex
) {
794 *pDesc
= pObjectEntry
->Desc
;
795 /* we aren't supposed to reveal this info */
796 pDesc
->dwValidData
&= ~(DMUS_OBJ_MEMORY
| DMUS_OBJ_STREAM
);
797 pDesc
->pbMemData
= NULL
;
798 pDesc
->llMemLength
= 0;
799 pDesc
->pStream
= NULL
;
806 TRACE(": not found\n");
810 static void WINAPI
IDirectMusicLoaderImpl_CollectGarbage(IDirectMusicLoader8
*iface
)
812 FIXME("(%p)->(): stub\n", iface
);
815 static HRESULT WINAPI
IDirectMusicLoaderImpl_ReleaseObjectByUnknown(IDirectMusicLoader8
*iface
, IUnknown
*pObject
)
817 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
819 LPDIRECTMUSICOBJECT pObjectInterface
;
821 TRACE("(%p, %p)\n", This
, pObject
);
823 if (IsBadReadPtr (pObject
, sizeof(*pObject
))) {
824 ERR(": pObject bad write pointer\n");
827 /* we simply get IDirectMusicObject interface */
828 result
= IUnknown_QueryInterface (pObject
, &IID_IDirectMusicObject
, (LPVOID
*)&pObjectInterface
);
829 if (FAILED(result
)) return result
;
830 /* and release it in old-fashioned way */
831 result
= IDirectMusicLoader8_ReleaseObject (iface
, pObjectInterface
);
832 IDirectMusicObject_Release (pObjectInterface
);
837 static HRESULT WINAPI
IDirectMusicLoaderImpl_LoadObjectFromFile(IDirectMusicLoader8
*iface
, REFGUID rguidClassID
, REFIID iidInterfaceID
, WCHAR
*pwzFilePath
, void **ppObject
)
839 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
840 DMUS_OBJECTDESC ObjDesc
;
841 WCHAR wszLoaderSearchPath
[MAX_PATH
];
843 TRACE("(%p, %s, %s, %s, %p): wrapping to IDirectMusicLoaderImpl_GetObject\n", This
, debugstr_dmguid(rguidClassID
), debugstr_dmguid(iidInterfaceID
), debugstr_w(pwzFilePath
), ppObject
);
845 DM_STRUCT_INIT(&ObjDesc
);
846 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 */
847 ObjDesc
.guidClass
= *rguidClassID
;
848 /* OK, MSDN says that search order is the following:
849 - current directory (DONE)
850 - windows search path (FIXME: how do I get that?)
851 - loader's search path (DONE)
853 DMUSIC_GetLoaderSettings (iface
, rguidClassID
, wszLoaderSearchPath
, NULL
);
854 /* search in current directory */
855 if (!SearchPathW (NULL
, pwzFilePath
, NULL
, sizeof(ObjDesc
.wszFileName
)/sizeof(WCHAR
), ObjDesc
.wszFileName
, NULL
) &&
856 /* search in loader's search path */
857 !SearchPathW (wszLoaderSearchPath
, pwzFilePath
, NULL
, sizeof(ObjDesc
.wszFileName
)/sizeof(WCHAR
), ObjDesc
.wszFileName
, NULL
)) {
858 /* cannot find file */
859 TRACE(": cannot find file\n");
860 return DMUS_E_LOADER_FAILEDOPEN
;
863 TRACE(": full file path = %s\n", debugstr_w (ObjDesc
.wszFileName
));
865 return IDirectMusicLoader_GetObject(iface
, &ObjDesc
, iidInterfaceID
, ppObject
);
868 static const IDirectMusicLoader8Vtbl DirectMusicLoader_Loader_Vtbl
= {
869 IDirectMusicLoaderImpl_QueryInterface
,
870 IDirectMusicLoaderImpl_AddRef
,
871 IDirectMusicLoaderImpl_Release
,
872 IDirectMusicLoaderImpl_GetObject
,
873 IDirectMusicLoaderImpl_SetObject
,
874 IDirectMusicLoaderImpl_SetSearchDirectory
,
875 IDirectMusicLoaderImpl_ScanDirectory
,
876 IDirectMusicLoaderImpl_CacheObject
,
877 IDirectMusicLoaderImpl_ReleaseObject
,
878 IDirectMusicLoaderImpl_ClearCache
,
879 IDirectMusicLoaderImpl_EnableCache
,
880 IDirectMusicLoaderImpl_EnumObject
,
881 IDirectMusicLoaderImpl_CollectGarbage
,
882 IDirectMusicLoaderImpl_ReleaseObjectByUnknown
,
883 IDirectMusicLoaderImpl_LoadObjectFromFile
886 /* help function for DMUSIC_SetDefaultDLS */
887 static HRESULT
DMUSIC_GetDefaultGMPath (WCHAR wszPath
[MAX_PATH
]) {
889 DWORD returnType
, sizeOfReturnBuffer
= MAX_PATH
;
890 char szPath
[MAX_PATH
];
892 if ((RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic" , 0, KEY_READ
, &hkDM
) != ERROR_SUCCESS
) ||
893 (RegQueryValueExA (hkDM
, "GMFilePath", NULL
, &returnType
, (LPBYTE
) szPath
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
)) {
894 WARN(": registry entry missing\n" );
897 /* FIXME: Check return types to ensure we're interpreting data right */
898 MultiByteToWideChar (CP_ACP
, 0, szPath
, -1, wszPath
, MAX_PATH
);
903 /* for ClassFactory */
904 HRESULT WINAPI
create_dmloader(REFIID lpcGUID
, void **ppobj
)
906 IDirectMusicLoaderImpl
*obj
;
907 DMUS_OBJECTDESC Desc
;
908 LPWINE_LOADER_ENTRY pDefaultDLSEntry
;
911 TRACE("(%s, %p)\n", debugstr_dmguid(lpcGUID
), ppobj
);
912 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicLoaderImpl
));
915 return E_OUTOFMEMORY
;
917 obj
->IDirectMusicLoader8_iface
.lpVtbl
= &DirectMusicLoader_Loader_Vtbl
;
918 obj
->ref
= 0; /* Will be inited with QueryInterface */
919 /* init cache/alias list */
920 obj
->pObjects
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(struct list
));
921 list_init (obj
->pObjects
);
923 obj
->pClassSettings
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(struct list
));
924 list_init (obj
->pClassSettings
);
925 DMUSIC_InitLoaderSettings(&obj
->IDirectMusicLoader8_iface
);
927 /* set default DLS collection (via SetObject... so that loading via DMUS_OBJ_OBJECT is possible) */
928 DM_STRUCT_INIT(&Desc
);
929 Desc
.dwValidData
= DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_OBJECT
;
930 Desc
.guidClass
= CLSID_DirectMusicCollection
;
931 Desc
.guidObject
= GUID_DefaultGMCollection
;
932 DMUSIC_GetDefaultGMPath (Desc
.wszFileName
);
933 IDirectMusicLoader_SetObject(&obj
->IDirectMusicLoader8_iface
, &Desc
);
934 /* and now the workaroundTM for "invalid" default DLS; basically,
935 my tests showed that if GUID chunk is present in default DLS
936 collection, loader treats it as "invalid" and returns
937 DMUS_E_LOADER_NOFILENAME for all requests for it; basically, we check
938 if out input guidObject was overwritten */
939 pEntry
= list_head (obj
->pObjects
);
940 pDefaultDLSEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
941 if (!IsEqualGUID(&Desc
.guidObject
, &GUID_DefaultGMCollection
)) {
942 pDefaultDLSEntry
->bInvalidDefaultDLS
= TRUE
;
947 return IDirectMusicLoader_QueryInterface(&obj
->IDirectMusicLoader8_iface
, lpcGUID
, ppobj
);
950 /* help function for retrieval of search path and caching option for certain class */
951 static HRESULT
DMUSIC_GetLoaderSettings(IDirectMusicLoader8
*iface
, REFGUID pClassID
, WCHAR
*wszSearchPath
, BOOL
*pbCache
)
953 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
955 TRACE(": (%p, %s, %p, %p)\n", This
, debugstr_dmguid(pClassID
), wszSearchPath
, pbCache
);
957 LIST_FOR_EACH(pEntry
, This
->pClassSettings
) {
958 LPWINE_LOADER_OPTION pOptionEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_OPTION
, entry
);
959 if (IsEqualCLSID (pClassID
, &pOptionEntry
->guidClass
)) {
961 strcpyW(wszSearchPath
, pOptionEntry
->wszSearchPath
);
963 *pbCache
= pOptionEntry
->bCache
;
970 /* help function for setting search path and caching option for certain class */
971 static HRESULT
DMUSIC_SetLoaderSettings(IDirectMusicLoader8
*iface
, REFGUID pClassID
, WCHAR
*wszSearchPath
, BOOL
*pbCache
)
973 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
975 HRESULT result
= S_FALSE
; /* in case pClassID != GUID_DirectMusicAllTypes and not a valid CLSID */
976 TRACE(": (%p, %s, %p, %p)\n", This
, debugstr_dmguid(pClassID
), wszSearchPath
, pbCache
);
978 LIST_FOR_EACH(pEntry
, This
->pClassSettings
) {
979 LPWINE_LOADER_OPTION pOptionEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_OPTION
, entry
);
980 /* well, either we have GUID_DirectMusicAllTypes and need to set it to all,
981 or specific CLSID is given and we set it only to it */
982 if (IsEqualGUID (pClassID
, &GUID_DirectMusicAllTypes
) ||
983 IsEqualCLSID (pClassID
, &pOptionEntry
->guidClass
)) {
985 strcpyW(pOptionEntry
->wszSearchPath
, wszSearchPath
);
987 pOptionEntry
->bCache
= *pbCache
;
995 static HRESULT
DMUSIC_InitLoaderSettings(IDirectMusicLoader8
*iface
)
997 IDirectMusicLoaderImpl
*This
= impl_from_IDirectMusicLoader8(iface
);
999 /* hard-coded list of classes */
1000 static REFCLSID classes
[] = {
1001 &CLSID_DirectMusicAudioPathConfig
,
1002 &CLSID_DirectMusicBand
,
1003 &CLSID_DirectMusicContainer
,
1004 &CLSID_DirectMusicCollection
,
1005 &CLSID_DirectMusicChordMap
,
1006 &CLSID_DirectMusicSegment
,
1007 &CLSID_DirectMusicScript
,
1008 &CLSID_DirectMusicSong
,
1009 &CLSID_DirectMusicStyle
,
1010 &CLSID_DirectMusicGraph
,
1011 &CLSID_DirectSoundWave
1015 WCHAR wszCurrent
[MAX_PATH
];
1017 TRACE(": (%p)\n", This
);
1018 GetCurrentDirectoryW (MAX_PATH
, wszCurrent
);
1020 for (i
= 0; i
< sizeof(classes
)/sizeof(REFCLSID
); i
++) {
1021 LPWINE_LOADER_OPTION pNewSetting
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_OPTION
));
1022 pNewSetting
->guidClass
= *classes
[i
];
1023 strcpyW (pNewSetting
->wszSearchPath
, wszCurrent
);
1024 pNewSetting
->bCache
= TRUE
;
1025 list_add_tail (This
->pClassSettings
, &pNewSetting
->entry
);