1 /* IDirectMusicLoaderImpl
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "dmloader_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmloader
);
24 /*****************************************************************************
25 * IDirectMusicLoaderImpl implementation
27 /* IUnknown/IDirectMusicLoader(8) part: */
28 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface (LPDIRECTMUSICLOADER8 iface
, REFIID riid
, LPVOID
*ppobj
) {
29 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
31 TRACE("(%p, %s, %p)\n",This
, debugstr_dmguid(riid
), ppobj
);
32 if (IsEqualIID (riid
, &IID_IUnknown
) ||
33 IsEqualIID (riid
, &IID_IDirectMusicLoader
) ||
34 IsEqualIID (riid
, &IID_IDirectMusicLoader8
)) {
35 IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef (iface
);
40 WARN(": not found\n");
44 ULONG WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef (LPDIRECTMUSICLOADER8 iface
) {
45 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
46 TRACE("(%p): AddRef from %ld\n", This
, This
->dwRef
);
47 return InterlockedIncrement (&This
->dwRef
);
50 ULONG WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_Release (LPDIRECTMUSICLOADER8 iface
) {
51 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
53 DWORD dwRef
= InterlockedDecrement (&This
->dwRef
);
54 TRACE("(%p): ReleaseRef to %ld\n", This
, This
->dwRef
);
56 DMUSIC_DestroyDirectMusicLoaderImpl (iface
);
57 HeapFree (GetProcessHeap(), 0, This
);
63 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject (LPDIRECTMUSICLOADER8 iface
, LPDMUS_OBJECTDESC pDesc
, REFIID riid
, LPVOID
* ppv
) {
64 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
65 HRESULT result
= S_OK
;
66 HRESULT ret
= S_OK
; /* used at the end of function, to determine whether everything went OK */
69 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
71 IPersistStream
* pPersistStream
= NULL
;
73 LPDIRECTMUSICOBJECT pObject
;
74 DMUS_OBJECTDESC GotDesc
;
77 TRACE("(%p, %p, %s, %p): pDesc:\n%s", This
, pDesc
, debugstr_dmguid(riid
), ppv
, debugstr_DMUS_OBJECTDESC(pDesc
));
79 /* sometimes it happens that guidClass is missing... which is a BadThingTM */
80 if (!(pDesc
->dwValidData
& DMUS_OBJ_CLASS
)) {
81 ERR(": guidClass not valid but needed\n");
83 return DMUS_E_LOADER_NOCLASSID
;
86 /* OK, first we iterate thru the list of objects we know about; these are either loaded (GetObject, LoadObjectFromFile)
87 or set via SetObject; */
88 TRACE(": looking if we have object in the cache or if it can be found via alias\n");
89 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
90 LPWINE_LOADER_ENTRY pExistingEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
91 if ((pDesc
->dwValidData
& DMUS_OBJ_OBJECT
) &&
92 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
93 IsEqualGUID (&pDesc
->guidObject
, &pExistingEntry
->Desc
.guidObject
)) {
94 TRACE(": found it by object GUID\n");
95 /* I suppose such stuff can happen only when GUID for object is given (GUID_DefaultGMCollection) */
96 if (pExistingEntry
->bInvalidDefaultDLS
) {
97 TRACE(": found faulty default DLS collection... enabling M$ compliant behaviour\n");
98 return DMUS_E_LOADER_NOFILENAME
;
100 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
101 TRACE(": already loaded\n");
102 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
104 TRACE(": not loaded yet\n");
105 pObjectEntry
= pExistingEntry
;
108 else if ((pDesc
->dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
109 (pExistingEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
110 !strncmpW (pDesc
->wszFileName
, pExistingEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
111 TRACE(": found it by fullpath filename\n");
112 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
113 TRACE(": already loaded\n");
114 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
116 TRACE(": not loaded yet\n");
117 pObjectEntry
= pExistingEntry
;
120 else if ((pDesc
->dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
121 (pExistingEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
122 !strncmpW (pDesc
->wszName
, pExistingEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
123 !strncmpW (pDesc
->wszCategory
, pExistingEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
124 TRACE(": found it by name and category\n");
125 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
126 TRACE(": already loaded\n");
127 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
129 TRACE(": not loaded yet\n");
130 pObjectEntry
= pExistingEntry
;
133 else if ((pDesc
->dwValidData
& DMUS_OBJ_NAME
) &&
134 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
135 !strncmpW (pDesc
->wszName
, pExistingEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
136 TRACE(": found it by name\n");
137 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
138 TRACE(": already loaded\n");
139 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
141 TRACE(": not loaded yet\n");
142 pObjectEntry
= pExistingEntry
;
145 else if ((pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) &&
146 (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
147 !strncmpW (pDesc
->wszFileName
, pExistingEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
148 TRACE(": found it by filename\n");
149 if (pExistingEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) {
150 TRACE(": already loaded\n");
151 return IDirectMusicObject_QueryInterface (pExistingEntry
->pObject
, riid
, ppv
);
153 TRACE(": not loaded yet\n");
154 pObjectEntry
= pExistingEntry
;
159 /* basically, if we found alias, we use its descriptor to load...
160 else we use info we were given */
162 TRACE(": found alias entry for requested object... using stored info\n");
163 /* I think in certain cases it can happen that entry's descriptor lacks info
164 where to load from (e.g.: if we loaded from stream and then released object
165 from cache; then only it's CLSID, GUID and perhaps name are left); so just
166 overwrite info entry has (since it ought to be 100% correct) */
167 DMUSIC_CopyDescriptor (pDesc
, &pObjectEntry
->Desc
);
168 /*pDesc = &pObjectEntry->Desc; */ /* FIXME: is this OK? */
170 TRACE(": no cache/alias entry found for requested object\n");
173 if (pDesc
->dwValidData
& DMUS_OBJ_URL
) {
174 TRACE(": loading from URLs not supported yet\n");
175 return DMUS_E_LOADER_FORMATNOTSUPPORTED
;
177 else if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
178 /* load object from file */
179 /* generate filename; if it's full path, don't add search
180 directory path, otherwise do */
181 WCHAR wszFileName
[MAX_PATH
];
183 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
184 lstrcpyW(wszFileName
, pDesc
->wszFileName
);
186 WCHAR
*p
, wszSearchPath
[MAX_PATH
];
187 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, wszSearchPath
, NULL
);
188 lstrcpyW(wszFileName
, wszSearchPath
);
189 p
= wszFileName
+ lstrlenW(wszFileName
);
190 if (p
> wszFileName
&& p
[-1] != '\\') *p
++ = '\\';
191 strcpyW(p
, pDesc
->wszFileName
);
193 TRACE(": loading from file (%s)\n", debugstr_w(wszFileName
));
194 /* create stream and associate it with file */
195 result
= DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID
*)&pStream
);
196 if (FAILED(result
)) {
197 ERR(": could not create loader stream\n");
200 result
= IDirectMusicLoaderFileStream_Attach (pStream
, wszFileName
, iface
);
201 if (FAILED(result
)) {
202 ERR(": could not attach stream to file\n");
207 else if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
208 /* load object from resource */
209 TRACE(": loading from resource\n");
210 /* create stream and associate it with given resource */
211 result
= DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID
*)&pStream
);
212 if (FAILED(result
)) {
213 ERR(": could not create resource stream\n");
216 result
= IDirectMusicLoaderResourceStream_Attach (pStream
, pDesc
->pbMemData
, pDesc
->llMemLength
, 0, iface
);
217 if (FAILED(result
)) {
218 ERR(": could not attach stream to resource\n");
222 else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
223 /* load object from stream */
224 TRACE(": loading from stream\n");
225 /* create universal stream and associate it with given one */
226 result
= DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID
*)&pStream
);
227 if (FAILED(result
)) {
228 ERR(": could not create generic stream\n");
231 result
= IDirectMusicLoaderGenericStream_Attach (pStream
, pDesc
->pStream
, iface
);
232 if (FAILED(result
)) {
233 ERR(": failed to attach stream\n");
237 /* nowhere to load from */
238 FIXME(": unknown/unsupported way of loading\n");
239 return DMUS_E_LOADER_NOFILENAME
; /* test shows this is returned */
243 result
= CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
244 if (FAILED(result
)) {
245 ERR(": could not create object\n");
248 /* acquire PersistStream interface */
249 result
= IDirectMusicObject_QueryInterface (pObject
, &IID_IPersistStream
, (LPVOID
*)&pPersistStream
);
250 if (FAILED(result
)) {
251 ERR("failed to Query\n");
255 result
= IPersistStream_Load (pPersistStream
, pStream
);
256 if (result
!= S_OK
) {
257 WARN(": failed to (completely) load object (%s)\n", debugstr_dmreturn(result
));
258 ret
= DMUS_S_PARTIALLOAD
/*result*/;
261 DM_STRUCT_INIT(&GotDesc
);
262 result
= IDirectMusicObject_GetDescriptor (pObject
, &GotDesc
);
263 /* set filename (if we loaded via filename) */
264 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
265 GotDesc
.dwValidData
|= (pDesc
->dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
));
266 strcpyW (GotDesc
.wszFileName
, pDesc
->wszFileName
);
268 if (FAILED(result
)) {
269 ERR(": failed to get descriptor\n");
272 /* release all loading related stuff */
273 IStream_Release (pStream
);
274 IPersistStream_Release (pPersistStream
);
276 /* add object to cache/overwrite existing info (if cache is enabled) */
277 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, NULL
, &bCache
);
280 pObjectEntry
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_ENTRY
));
281 DM_STRUCT_INIT(&pObjectEntry
->Desc
);
283 DMUSIC_CopyDescriptor (&pObjectEntry
->Desc
, &GotDesc
);
284 pObjectEntry
->pObject
= pObject
;
285 pObjectEntry
->bInvalidDefaultDLS
= FALSE
;
287 list_add_head (This
->pObjects
, &pObjectEntry
->entry
);
290 DMUSIC_CopyDescriptor (&pObjectEntry
->Desc
, &GotDesc
);
291 pObjectEntry
->pObject
= pObject
;
292 pObjectEntry
->bInvalidDefaultDLS
= FALSE
;
295 TRACE(": filled in cache entry\n");
296 } else TRACE(": caching disabled\n");
299 /* for debug purposes (e.g. to check if all files are cached) */
300 TRACE("*** Loader's cache ***\n");
302 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
304 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
305 TRACE(": entry nr. %i:\n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", i
, debugstr_DMUS_OBJECTDESC(&pObjectEntry
->Desc
), pObjectEntry
->bInvalidDefaultDLS
, pObjectEntry
->pObject
);
309 result
= IDirectMusicObject_QueryInterface (pObject
, riid
, ppv
);
310 if (!bCache
) IDirectMusicObject_Release (pObject
); /* since loader's reference is not needed */
311 /* if there was trouble with loading, and if no other error occurred,
312 we should return DMUS_S_PARTIALLOAD; else, error is returned */
319 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject (LPDIRECTMUSICLOADER8 iface
, LPDMUS_OBJECTDESC pDesc
) {
320 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
322 LPDIRECTMUSICOBJECT pObject
;
323 DMUS_OBJECTDESC Desc
;
325 LPWINE_LOADER_ENTRY pObjectEntry
, pNewEntry
;
327 TRACE("(%p, %p): pDesc:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC(pDesc
));
329 /* create stream and load additional info from it */
330 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
331 /* generate filename; if it's full path, don't add search
332 directory path, otherwise do */
333 WCHAR wszFileName
[MAX_PATH
];
335 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
336 lstrcpyW(wszFileName
, pDesc
->wszFileName
);
339 WCHAR wszSearchPath
[MAX_PATH
];
340 DMUSIC_GetLoaderSettings (iface
, &pDesc
->guidClass
, wszSearchPath
, NULL
);
341 lstrcpyW(wszFileName
, wszSearchPath
);
342 p
= wszFileName
+ lstrlenW(wszFileName
);
343 if (p
> wszFileName
&& p
[-1] != '\\') *p
++ = '\\';
344 strcpyW(p
, pDesc
->wszFileName
);
347 DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID
*)&pStream
);
349 IDirectMusicLoaderFileStream_Attach (pStream
, wszFileName
, iface
);
351 else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
353 DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID
*)&pStream
);
355 IDirectMusicLoaderGenericStream_Attach (pStream
, pDesc
->pStream
, iface
);
357 else if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
359 DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID
*)&pStream
);
361 IDirectMusicLoaderResourceStream_Attach (pStream
, pDesc
->pbMemData
, pDesc
->llMemLength
, 0, iface
);
364 ERR(": no way to get additional info\n");
365 return DMUS_E_LOADER_FAILEDOPEN
;
369 CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
371 /* *sigh*... some ms objects have lousy implementation of ParseDescriptor that clears input descriptor :( */
372 #ifdef NOW_WE_ARE_FREE
373 /* parse descriptor: we actually use input descriptor; fields that aren't available from stream remain,
374 otherwise real info is set */
375 IDirectMusicObject_ParseDescriptor (pObject
, pStream
, pDesc
);
377 /* hmph... due to some trouble I had with certain tests, we store current position and then set it back */
378 DM_STRUCT_INIT(&Desc
);
379 if (FAILED(IDirectMusicObject_ParseDescriptor (pObject
, pStream
, &Desc
))) {
380 ERR(": couldn't parse descriptor\n");
381 return DMUS_E_LOADER_FORMATNOTSUPPORTED
;
384 /* copy elements from parsed descriptor into input descriptor; this sets new info, overwriting if necessary,
385 but leaves info that's provided by input and not available from stream */
386 DMUSIC_CopyDescriptor (pDesc
, &Desc
);
388 /* release everything */
389 IDirectMusicObject_Release (pObject
);
390 IStream_Release (pStream
);
392 /* sometimes it happens that twisted programs call SetObject for same object twice...
393 in such cases, native loader returns S_OK and does nothing... a sound plan */
394 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
395 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
396 if (!memcmp (&pObjectEntry
->Desc
, pDesc
, sizeof(DMUS_OBJECTDESC
))) {
397 TRACE(": exacly same entry already exists\n");
403 TRACE(": adding alias entry with following info: \n%s\n", debugstr_DMUS_OBJECTDESC(pDesc
));
404 pNewEntry
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_ENTRY
));
405 /* use this function instead of pure memcpy due to streams (memcpy just copies pointer),
406 which is basically used further by app that called SetDescriptor... better safety than exception */
407 DMUSIC_CopyDescriptor (&pNewEntry
->Desc
, pDesc
);
408 list_add_head (This
->pObjects
, &pNewEntry
->entry
);
413 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, WCHAR
* pwzPath
, BOOL fClear
) {
414 WCHAR wszCurrentPath
[MAX_PATH
];
415 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
416 TRACE("(%p, %s, %s, %d)\n", This
, debugstr_dmguid(rguidClass
), debugstr_w(pwzPath
), fClear
);
417 FIXME(": fClear ignored\n");
418 DMUSIC_GetLoaderSettings (iface
, rguidClass
, wszCurrentPath
, NULL
);
419 if (!strncmpW(wszCurrentPath
, pwzPath
, MAX_PATH
)) {
422 /* FIXME: check if path is valid; else return DMUS_E_LOADER_BADPATH */
423 return DMUSIC_SetLoaderSettings (iface
, rguidClass
, pwzPath
, NULL
);
426 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, WCHAR
* pwzFileExtension
, WCHAR
* pwzScanFileName
) {
427 static const WCHAR wszAny
[] = {'*',0};
428 WIN32_FIND_DATAW FileData
;
430 WCHAR wszSearchString
[MAX_PATH
];
433 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
434 TRACE("(%p, %s, %p, %p)\n", This
, debugstr_dmguid(rguidClass
), pwzFileExtension
, pwzScanFileName
);
435 if (IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || !DMUSIC_IsValidLoadableClass(rguidClass
)) {
436 ERR(": rguidClass invalid CLSID\n");
437 return REGDB_E_CLASSNOTREG
;
440 /* get search path for given class */
441 DMUSIC_GetLoaderSettings (iface
, rguidClass
, wszSearchString
, NULL
);
443 p
= wszSearchString
+ lstrlenW(wszSearchString
);
444 if (p
> wszSearchString
&& p
[-1] != '\\') *p
++ = '\\';
445 *p
++ = '*'; /* any file */
446 if (strcmpW (pwzFileExtension
, wszAny
)) *p
++ = '.'; /* if we have actual extension, put a dot */
447 strcpyW (p
, pwzFileExtension
);
449 TRACE(": search string: %s\n", debugstr_w(wszSearchString
));
451 hSearch
= FindFirstFileW (wszSearchString
, &FileData
);
452 if (hSearch
== INVALID_HANDLE_VALUE
) {
453 TRACE(": no files found\n");
458 DMUS_OBJECTDESC Desc
;
459 DM_STRUCT_INIT(&Desc
);
460 Desc
.dwValidData
= DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_DATE
;
461 memcpy (&Desc
.guidClass
, rguidClass
, sizeof(GUID
));
462 strcpyW (Desc
.wszFileName
, FileData
.cFileName
);
463 FileTimeToLocalFileTime (&FileData
.ftCreationTime
, &Desc
.ftDate
);
464 IDirectMusicLoader8_SetObject (iface
, &Desc
);
466 if (!FindNextFileW (hSearch
, &FileData
)) {
467 if (GetLastError () == ERROR_NO_MORE_FILES
) {
468 TRACE(": search completed\n");
471 ERR(": could not get next file\n");
480 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject (LPDIRECTMUSICLOADER8 iface
, IDirectMusicObject
* pObject
) {
481 DMUS_OBJECTDESC Desc
;
482 HRESULT result
= DMUS_E_LOADER_OBJECTNOTFOUND
;
484 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
486 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
487 TRACE("(%p, %p)\n", This
, pObject
);
490 DM_STRUCT_INIT(&Desc
);
491 IDirectMusicObject_GetDescriptor (pObject
, &Desc
);
493 /* now iterate thru list and check if we have alias (without object), corresponding
494 to descriptor of input object */
495 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
496 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
497 if ((Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
498 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
499 IsEqualGUID (&Desc
.guidObject
, &pObjectEntry
->Desc
.guidObject
)) {
500 TRACE(": found it by object GUID\n");
501 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
507 else if ((Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
508 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
509 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
510 TRACE(": found it by fullpath filename\n");
511 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
517 else if ((Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
518 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
519 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
520 !strncmpW (Desc
.wszCategory
, pObjectEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
521 TRACE(": found it by name and category\n");
522 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
528 else if ((Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
529 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
530 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
531 TRACE(": found it by name\n");
532 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
538 else if ((Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
539 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
540 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
541 TRACE(": found it by filename\n");
542 if ((pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
) && pObjectEntry
->pObject
)
550 /* if we found such alias, then set everything */
551 if (result
== S_OK
) {
552 pObjectEntry
->Desc
.dwValidData
&= DMUS_OBJ_LOADED
;
553 pObjectEntry
->pObject
= pObject
;
554 IDirectMusicObject_AddRef (pObjectEntry
->pObject
);
560 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject (LPDIRECTMUSICLOADER8 iface
, IDirectMusicObject
* pObject
) {
561 DMUS_OBJECTDESC Desc
;
563 LPWINE_LOADER_ENTRY pObjectEntry
= NULL
;
564 HRESULT result
= S_FALSE
;
566 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
567 TRACE("(%p, %p)\n", This
, pObject
);
570 DM_STRUCT_INIT(&Desc
);
571 IDirectMusicObject_GetDescriptor (pObject
, &Desc
);
573 /* iterate thru the list of objects we know about; check only those with DMUS_OBJ_LOADED */
574 TRACE(": looking for the object in cache\n");
575 LIST_FOR_EACH(pEntry
, This
->pObjects
) {
576 pObjectEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_ENTRY
, entry
);
577 if ((Desc
.dwValidData
& DMUS_OBJ_OBJECT
) &&
578 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_OBJECT
| DMUS_OBJ_LOADED
)) &&
579 IsEqualGUID (&Desc
.guidObject
, &pObjectEntry
->Desc
.guidObject
)) {
580 TRACE(": found it by object GUID\n%s", debugstr_DMUS_OBJECTDESC(&pObjectEntry
->Desc
));
584 else if ((Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
)) &&
585 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_LOADED
)) &&
586 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
587 TRACE(": found it by fullpath filename\n");
591 else if ((Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
)) &&
592 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
| DMUS_OBJ_LOADED
)) &&
593 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
) &&
594 !strncmpW (Desc
.wszCategory
, pObjectEntry
->Desc
.wszCategory
, DMUS_MAX_CATEGORY
)) {
595 TRACE(": found it by name and category\n");
599 else if ((Desc
.dwValidData
& DMUS_OBJ_NAME
) &&
600 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_NAME
| DMUS_OBJ_LOADED
)) &&
601 !strncmpW (Desc
.wszName
, pObjectEntry
->Desc
.wszName
, DMUS_MAX_NAME
)) {
602 TRACE(": found it by name\n");
606 else if ((Desc
.dwValidData
& DMUS_OBJ_FILENAME
) &&
607 (pObjectEntry
->Desc
.dwValidData
& (DMUS_OBJ_FILENAME
| DMUS_OBJ_LOADED
)) &&
608 !strncmpW (Desc
.wszFileName
, pObjectEntry
->Desc
.wszFileName
, DMUS_MAX_FILENAME
)) {
609 TRACE(": found it by filename\n");
614 if (result
== S_OK
) {
615 /*TRACE(": releasing: \n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject); */
616 IDirectMusicObject_Release (pObjectEntry
->pObject
);
617 pObjectEntry
->pObject
= NULL
;
618 pObjectEntry
->Desc
.dwValidData
&= ~DMUS_OBJ_LOADED
;
623 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
) {
625 LPWINE_LOADER_ENTRY pObjectEntry
;
626 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
627 TRACE("(%p, %s)\n", This
, debugstr_dmguid(rguidClass
));
629 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
630 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
632 if ((IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || IsEqualGUID (rguidClass
, &pObjectEntry
->Desc
.guidClass
)) &&
633 (pObjectEntry
->Desc
.dwValidData
& DMUS_OBJ_LOADED
)) {
634 /* basically, wrap to ReleaseObject for each object found */
635 IDirectMusicLoader8_ReleaseObject (iface
, pObjectEntry
->pObject
);
642 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, BOOL fEnable
) {
643 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
645 TRACE("(%p, %s, %d)\n", This
, debugstr_dmguid(rguidClass
), fEnable
);
646 DMUSIC_GetLoaderSettings (iface
, rguidClass
, NULL
, &bCurrent
);
647 if (bCurrent
== fEnable
)
650 return DMUSIC_SetLoaderSettings (iface
, rguidClass
, NULL
, &fEnable
);
653 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, DWORD dwIndex
, LPDMUS_OBJECTDESC pDesc
) {
656 LPWINE_LOADER_ENTRY pObjectEntry
;
657 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
658 TRACE("(%p, %s, %ld, %p)\n", This
, debugstr_dmguid(rguidClass
), dwIndex
, pDesc
);
660 DM_STRUCT_INIT(pDesc
);
662 LIST_FOR_EACH (pEntry
, This
->pObjects
) {
663 pObjectEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
665 if (IsEqualGUID (rguidClass
, &GUID_DirectMusicAllTypes
) || IsEqualGUID (rguidClass
, &pObjectEntry
->Desc
.guidClass
)) {
666 if (dwCount
== dwIndex
) {
667 memcpy (pDesc
, &pObjectEntry
->Desc
, sizeof(DMUS_OBJECTDESC
));
668 /* we aren't supposed to reveal this info */
669 pDesc
->dwValidData
&= ~(DMUS_OBJ_MEMORY
| DMUS_OBJ_STREAM
);
670 pDesc
->pbMemData
= NULL
;
671 pDesc
->llMemLength
= 0;
672 pDesc
->pStream
= NULL
;
679 TRACE(": not found\n");
683 void WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage (LPDIRECTMUSICLOADER8 iface
) {
684 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
685 FIXME("(%p): stub\n", This
);
688 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown (LPDIRECTMUSICLOADER8 iface
, IUnknown
* pObject
) {
689 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
691 LPDIRECTMUSICOBJECT pObjectInterface
;
693 TRACE("(%p, %p)\n", This
, pObject
);
695 if (IsBadReadPtr (pObject
, sizeof(LPUNKNOWN
))) {
696 ERR(": pObject bad write pointer\n");
699 /* we simply get IDirectMusicObject interface */
700 result
= IUnknown_QueryInterface (pObject
, &IID_IDirectMusicObject
, (LPVOID
*)&pObjectInterface
);
701 if (FAILED(result
)) return result
;
702 /* and release it in old-fashioned way */
703 result
= IDirectMusicLoader8_ReleaseObject (iface
, pObjectInterface
);
704 IDirectMusicObject_Release (pObjectInterface
);
709 HRESULT WINAPI
IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClassID
, REFIID iidInterfaceID
, WCHAR
* pwzFilePath
, void** ppObject
) {
710 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
711 DMUS_OBJECTDESC ObjDesc
;
712 WCHAR wszLoaderSearchPath
[MAX_PATH
];
714 TRACE("(%p, %s, %s, %s, %p): wrapping to IDirectMusicLoaderImpl_GetObject\n", This
, debugstr_dmguid(rguidClassID
), debugstr_dmguid(iidInterfaceID
), debugstr_w(pwzFilePath
), ppObject
);
716 DM_STRUCT_INIT(&ObjDesc
);
717 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 */
718 memcpy (&ObjDesc
.guidClass
, rguidClassID
, sizeof(CLSID
));
719 /* OK, MSDN says that search order is the following:
720 - current directory (DONE)
721 - windows search path (FIXME: how do I get that?)
722 - loader's search path (DONE)
724 DMUSIC_GetLoaderSettings (iface
, rguidClassID
, wszLoaderSearchPath
, NULL
);
725 /* search in current directory */
726 if (!SearchPathW (NULL
, pwzFilePath
, NULL
, sizeof(ObjDesc
.wszFileName
)/sizeof(WCHAR
), ObjDesc
.wszFileName
, NULL
) &&
727 /* search in loader's search path */
728 !SearchPathW (wszLoaderSearchPath
, pwzFilePath
, NULL
, sizeof(ObjDesc
.wszFileName
)/sizeof(WCHAR
), ObjDesc
.wszFileName
, NULL
)) {
729 /* cannot find file */
730 TRACE(": cannot find file\n");
731 return DMUS_E_LOADER_FAILEDOPEN
;
734 TRACE(": full file path = %s\n", debugstr_w (ObjDesc
.wszFileName
));
736 return IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject (iface
, &ObjDesc
, iidInterfaceID
, ppObject
);
739 static const IDirectMusicLoader8Vtbl DirectMusicLoader_Loader_Vtbl
= {
740 IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface
,
741 IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef
,
742 IDirectMusicLoaderImpl_IDirectMusicLoader_Release
,
743 IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject
,
744 IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject
,
745 IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory
,
746 IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory
,
747 IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject
,
748 IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject
,
749 IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache
,
750 IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache
,
751 IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject
,
752 IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage
,
753 IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown
,
754 IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile
757 /* for ClassFactory */
758 HRESULT WINAPI
DMUSIC_CreateDirectMusicLoaderImpl (LPCGUID lpcGUID
, LPVOID
*ppobj
, LPUNKNOWN pUnkOuter
) {
759 IDirectMusicLoaderImpl
*obj
;
760 DMUS_OBJECTDESC Desc
;
761 LPWINE_LOADER_ENTRY pDefaultDLSEntry
;
764 TRACE("(%s, %p, %p)\n", debugstr_dmguid(lpcGUID
), ppobj
, pUnkOuter
);
765 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicLoaderImpl
));
767 *ppobj
= (LPDIRECTMUSICLOADER8
)NULL
;
768 return E_OUTOFMEMORY
;
770 obj
->LoaderVtbl
= &DirectMusicLoader_Loader_Vtbl
;
771 obj
->dwRef
= 0; /* will be inited with QueryInterface */
772 /* init critical section */
773 /* init cache/alias list */
774 /*InitializeCriticalSection (&obj->CritSect); */
775 obj
->pObjects
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(struct list
));
776 list_init (obj
->pObjects
);
778 obj
->pClassSettings
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(struct list
));
779 list_init (obj
->pClassSettings
);
780 DMUSIC_InitLoaderSettings ((LPDIRECTMUSICLOADER8
)obj
);
782 /* set default DLS collection (via SetObject... so that loading via DMUS_OBJ_OBJECT is possible) */
783 DM_STRUCT_INIT(&Desc
);
784 Desc
.dwValidData
= DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
| DMUS_OBJ_OBJECT
;
785 memcpy (&Desc
.guidClass
, &CLSID_DirectMusicCollection
, sizeof(CLSID
));
786 memcpy (&Desc
.guidObject
, &GUID_DefaultGMCollection
, sizeof(GUID
));
787 DMUSIC_GetDefaultGMPath (Desc
.wszFileName
);
788 IDirectMusicLoader_SetObject ((LPDIRECTMUSICLOADER8
)obj
, &Desc
);
789 /* and now the workaroundTM for "invalid" default DLS; basically,
790 my tests showed that if GUID chunk is present in default DLS
791 collection, loader treats it as "invalid" and returns
792 DMUS_E_LOADER_NOFILENAME for all requests for it; basically, we check
793 if out input guidObject was overwritten */
794 pEntry
= list_head (obj
->pObjects
);
795 pDefaultDLSEntry
= LIST_ENTRY (pEntry
, WINE_LOADER_ENTRY
, entry
);
796 if (!IsEqualGUID(&Desc
.guidObject
, &GUID_DefaultGMCollection
)) {
797 pDefaultDLSEntry
->bInvalidDefaultDLS
= TRUE
;
800 /* increase number of instances */
801 InterlockedIncrement (&dwDirectMusicLoader
);
803 return IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface ((LPDIRECTMUSICLOADER8
)obj
, lpcGUID
, ppobj
);
806 HRESULT WINAPI
DMUSIC_DestroyDirectMusicLoaderImpl (LPDIRECTMUSICLOADER8 iface
) {
807 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
809 TRACE("(%p)\n", This
);
811 /* firstly, release the cache */
812 IDirectMusicLoader8_ClearCache (iface
, &GUID_DirectMusicAllTypes
);
813 /* FIXME: release all allocated entries */
814 /* destroy critical section */
815 /*DeleteCriticalSection (&This->CritSect); */
817 /* decrease number of instances */
818 InterlockedDecrement (&dwDirectMusicLoader
);
823 /* help function for DMUSIC_SetDefaultDLS */
824 HRESULT WINAPI
DMUSIC_GetDefaultGMPath (WCHAR wszPath
[MAX_PATH
]) {
826 DWORD returnType
, sizeOfReturnBuffer
= MAX_PATH
;
827 char szPath
[MAX_PATH
];
829 if ((RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic" , 0, KEY_READ
, &hkDM
) != ERROR_SUCCESS
) ||
830 (RegQueryValueExA (hkDM
, "GMFilePath", NULL
, &returnType
, (LPBYTE
) szPath
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
)) {
831 WARN(": registry entry missing\n" );
834 /* FIXME: Check return types to ensure we're interpreting data right */
835 MultiByteToWideChar (CP_ACP
, 0, szPath
, -1, wszPath
, MAX_PATH
);
840 /* help function for retrieval of search path and caching option for certain class */
841 HRESULT WINAPI
DMUSIC_GetLoaderSettings (LPDIRECTMUSICLOADER8 iface
, REFGUID pClassID
, WCHAR
* wszSearchPath
, LPBOOL pbCache
) {
842 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
844 TRACE(": (%p, %s, %p, %p)\n", This
, debugstr_dmguid(pClassID
), wszSearchPath
, pbCache
);
846 LIST_FOR_EACH(pEntry
, This
->pClassSettings
) {
847 LPWINE_LOADER_OPTION pOptionEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_OPTION
, entry
);
848 if (IsEqualCLSID (pClassID
, &pOptionEntry
->guidClass
)) {
850 strcpyW(wszSearchPath
, pOptionEntry
->wszSearchPath
);
852 *pbCache
= pOptionEntry
->bCache
;
859 /* help function for setting search path and caching option for certain class */
860 HRESULT WINAPI
DMUSIC_SetLoaderSettings (LPDIRECTMUSICLOADER8 iface
, REFGUID pClassID
, WCHAR
* wszSearchPath
, LPBOOL pbCache
) {
861 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
863 HRESULT result
= S_FALSE
; /* in case pClassID != GUID_DirectMusicAllTypes and not a valid CLSID */
864 TRACE(": (%p, %s, %p, %p)\n", This
, debugstr_dmguid(pClassID
), wszSearchPath
, pbCache
);
866 LIST_FOR_EACH(pEntry
, This
->pClassSettings
) {
867 LPWINE_LOADER_OPTION pOptionEntry
= LIST_ENTRY(pEntry
, WINE_LOADER_OPTION
, entry
);
868 /* well, either we have GUID_DirectMusicAllTypes and need to set it to all,
869 or specific CLSID is given and we set it only to it */
870 if (IsEqualGUID (pClassID
, &GUID_DirectMusicAllTypes
) ||
871 IsEqualCLSID (pClassID
, &pOptionEntry
->guidClass
)) {
873 strcpyW(pOptionEntry
->wszSearchPath
, wszSearchPath
);
875 pOptionEntry
->bCache
= *pbCache
;
883 HRESULT WINAPI
DMUSIC_InitLoaderSettings (LPDIRECTMUSICLOADER8 iface
) {
884 ICOM_THIS_MULTI(IDirectMusicLoaderImpl
, LoaderVtbl
, iface
);
886 /* hard-coded list of classes */
887 static REFCLSID classes
[] = {
888 &CLSID_DirectMusicAudioPathConfig
,
889 &CLSID_DirectMusicBand
,
890 &CLSID_DirectMusicContainer
,
891 &CLSID_DirectMusicCollection
,
892 &CLSID_DirectMusicChordMap
,
893 &CLSID_DirectMusicSegment
,
894 &CLSID_DirectMusicScript
,
895 &CLSID_DirectMusicSong
,
896 &CLSID_DirectMusicStyle
,
897 &CLSID_DirectMusicGraph
,
898 &CLSID_DirectSoundWave
902 WCHAR wszCurrent
[MAX_PATH
];
904 TRACE(": (%p)\n", This
);
905 GetCurrentDirectoryW (MAX_PATH
, wszCurrent
);
907 for (i
= 0; i
< sizeof(classes
)/sizeof(REFCLSID
); i
++) {
908 LPWINE_LOADER_OPTION pNewSetting
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(WINE_LOADER_OPTION
));
909 memcpy (&pNewSetting
->guidClass
, classes
[i
], sizeof(CLSID
));
910 strcpyW (pNewSetting
->wszSearchPath
, wszCurrent
);
911 pNewSetting
->bCache
= TRUE
;
912 list_add_tail (This
->pClassSettings
, &pNewSetting
->entry
);
918 HRESULT WINAPI
DMUSIC_CopyDescriptor (LPDMUS_OBJECTDESC pDst
, LPDMUS_OBJECTDESC pSrc
) {
919 TRACE(": copy \n%s", debugstr_DMUS_OBJECTDESC(pSrc
));
920 /* copy field by field */
921 if (pSrc
->dwValidData
& DMUS_OBJ_CLASS
) memcpy (&pDst
->guidClass
, &pSrc
->guidClass
, sizeof(CLSID
));
922 if (pSrc
->dwValidData
& DMUS_OBJ_OBJECT
) memcpy (&pDst
->guidObject
, &pSrc
->guidObject
, sizeof(GUID
));
923 if (pSrc
->dwValidData
& DMUS_OBJ_DATE
) memcpy (&pDst
->ftDate
, &pSrc
->ftDate
, sizeof(FILETIME
));
924 if (pSrc
->dwValidData
& DMUS_OBJ_VERSION
) memcpy (&pDst
->vVersion
, &pSrc
->vVersion
, sizeof(DMUS_VERSION
));
925 if (pSrc
->dwValidData
& DMUS_OBJ_NAME
) strcpyW (pDst
->wszName
, pSrc
->wszName
);
926 if (pSrc
->dwValidData
& DMUS_OBJ_CATEGORY
) strcpyW (pDst
->wszCategory
, pSrc
->wszCategory
);
927 if (pSrc
->dwValidData
& DMUS_OBJ_FILENAME
) strcpyW (pDst
->wszFileName
, pSrc
->wszFileName
);
928 if (pSrc
->dwValidData
& DMUS_OBJ_STREAM
) IStream_Clone (pSrc
->pStream
, &pDst
->pStream
);
929 if (pSrc
->dwValidData
& DMUS_OBJ_MEMORY
) {
930 pDst
->pbMemData
= pSrc
->pbMemData
;
931 pDst
->llMemLength
= pSrc
->llMemLength
;
934 pDst
->dwValidData
|= pSrc
->dwValidData
;
938 BOOL WINAPI
DMUSIC_IsValidLoadableClass (REFCLSID pClassID
) {
939 if (IsEqualCLSID(pClassID
, &CLSID_DirectMusicAudioPathConfig
) ||
940 IsEqualCLSID(pClassID
, &CLSID_DirectMusicBand
) ||
941 IsEqualCLSID(pClassID
, &CLSID_DirectMusicContainer
) ||
942 IsEqualCLSID(pClassID
, &CLSID_DirectMusicCollection
) ||
943 IsEqualCLSID(pClassID
, &CLSID_DirectMusicChordMap
) ||
944 IsEqualCLSID(pClassID
, &CLSID_DirectMusicSegment
) ||
945 IsEqualCLSID(pClassID
, &CLSID_DirectMusicScript
) ||
946 IsEqualCLSID(pClassID
, &CLSID_DirectMusicSong
) ||
947 IsEqualCLSID(pClassID
, &CLSID_DirectMusicStyle
) ||
948 IsEqualCLSID(pClassID
, &CLSID_DirectMusicGraph
) ||
949 IsEqualCLSID(pClassID
, &CLSID_DirectSoundWave
) ||
950 IsEqualCLSID(pClassID
, &GUID_DirectMusicAllTypes
))