usp10: Update tests in test_ScriptItemIzeShapePlace to match Windows results.
[wine/multimedia.git] / dlls / dmloader / loader.c
blobe11b9a224a52daee5cf3908271ae08d30a8f89de
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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);
36 *ppobj = This;
37 return S_OK;
40 WARN(": not found\n");
41 return E_NOINTERFACE;
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);
55 if (dwRef == 0) {
56 DMUSIC_DestroyDirectMusicLoaderImpl (iface);
57 HeapFree (GetProcessHeap(), 0, This);
60 return dwRef;
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 */
68 struct list *pEntry;
69 LPWINE_LOADER_ENTRY pObjectEntry = NULL;
70 LPSTREAM pStream;
71 IPersistStream* pPersistStream = NULL;
73 LPDIRECTMUSICOBJECT pObject;
74 DMUS_OBJECTDESC GotDesc;
75 BOOL bCache;
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");
82 *ppv = NULL;
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);
103 } else {
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);
115 } else {
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);
128 } else {
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);
140 } else {
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);
152 } else {
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 */
161 if (pObjectEntry) {
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? */
169 } else {
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);
185 } else {
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 file stream\n");
198 return result;
200 result = IDirectMusicLoaderFileStream_Attach (pStream, wszFileName, iface);
201 if (FAILED(result)) {
202 ERR(": could not attach stream to file\n");
203 IStream_Release (pStream);
204 return result;
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");
214 return result;
216 result = IDirectMusicLoaderResourceStream_Attach (pStream, pDesc->pbMemData, pDesc->llMemLength, 0, iface);
217 if (FAILED(result)) {
218 ERR(": could not attach stream to resource\n");
219 IStream_Release (pStream);
220 return result;
223 else if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
224 /* load object from stream */
225 TRACE(": loading from stream\n");
226 /* create universal stream and associate it with given one */
227 result = DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID*)&pStream);
228 if (FAILED(result)) {
229 ERR(": could not create generic stream\n");
230 return result;
232 result = IDirectMusicLoaderGenericStream_Attach (pStream, pDesc->pStream, iface);
233 if (FAILED(result)) {
234 ERR(": failed to attach stream\n");
235 IStream_Release (pStream);
236 return result;
238 } else {
239 /* nowhere to load from */
240 FIXME(": unknown/unsupported way of loading\n");
241 return DMUS_E_LOADER_NOFILENAME; /* test shows this is returned */
244 /* create object */
245 result = CoCreateInstance (&pDesc->guidClass, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject, (LPVOID*)&pObject);
246 if (FAILED(result)) {
247 ERR(": could not create object\n");
248 return result;
250 /* acquire PersistStream interface */
251 result = IDirectMusicObject_QueryInterface (pObject, &IID_IPersistStream, (LPVOID*)&pPersistStream);
252 if (FAILED(result)) {
253 ERR("failed to Query\n");
254 return result;
256 /* load */
257 result = IPersistStream_Load (pPersistStream, pStream);
258 if (result != S_OK) {
259 WARN(": failed to (completely) load object (%s)\n", debugstr_dmreturn(result));
260 ret = DMUS_S_PARTIALLOAD /*result*/;
262 /* get descriptor */
263 DM_STRUCT_INIT(&GotDesc);
264 result = IDirectMusicObject_GetDescriptor (pObject, &GotDesc);
265 /* set filename (if we loaded via filename) */
266 if (pDesc->dwValidData & DMUS_OBJ_FILENAME) {
267 GotDesc.dwValidData |= (pDesc->dwValidData & (DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH));
268 strcpyW (GotDesc.wszFileName, pDesc->wszFileName);
270 if (FAILED(result)) {
271 ERR(": failed to get descriptor\n");
272 return result;
274 /* release all loading related stuff */
275 IStream_Release (pStream);
276 IPersistStream_Release (pPersistStream);
278 /* add object to cache/overwrite existing info (if cache is enabled) */
279 DMUSIC_GetLoaderSettings (iface, &pDesc->guidClass, NULL, &bCache);
280 if (bCache) {
281 if (!pObjectEntry) {
282 pObjectEntry = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(WINE_LOADER_ENTRY));
283 DM_STRUCT_INIT(&pObjectEntry->Desc);
284 if (pObject) {
285 DMUSIC_CopyDescriptor (&pObjectEntry->Desc, &GotDesc);
286 pObjectEntry->pObject = pObject;
287 pObjectEntry->bInvalidDefaultDLS = FALSE;
289 list_add_head (This->pObjects, &pObjectEntry->entry);
290 } else {
291 if (pObject) {
292 DMUSIC_CopyDescriptor (&pObjectEntry->Desc, &GotDesc);
293 pObjectEntry->pObject = pObject;
294 pObjectEntry->bInvalidDefaultDLS = FALSE;
297 TRACE(": filled in cache entry\n");
298 } else TRACE(": caching disabled\n");
300 #if 0
301 /* for debug purposes (e.g. to check if all files are cached) */
302 TRACE("*** Loader's cache ***\n");
303 int i = 0;
304 LIST_FOR_EACH (pEntry, This->pObjects) {
305 i++;
306 pObjectEntry = LIST_ENTRY(pEntry, WINE_LOADER_ENTRY, entry);
307 TRACE(": entry nr. %i:\n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", i, debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject);
309 #endif
311 result = IDirectMusicObject_QueryInterface (pObject, riid, ppv);
312 if (!bCache) IDirectMusicObject_Release (pObject); /* since loader's reference is not needed */
313 /* if there was trouble with loading, and if no other error occurred,
314 we should return DMUS_S_PARTIALLOAD; else, error is returned */
315 if (result == S_OK)
316 return ret;
317 else
318 return result;
321 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject (LPDIRECTMUSICLOADER8 iface, LPDMUS_OBJECTDESC pDesc) {
322 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
323 LPSTREAM pStream;
324 LPDIRECTMUSICOBJECT pObject;
325 DMUS_OBJECTDESC Desc;
326 struct list *pEntry;
327 LPWINE_LOADER_ENTRY pObjectEntry, pNewEntry;
328 HRESULT hr;
330 TRACE("(%p, %p): pDesc:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC(pDesc));
332 /* create stream and load additional info from it */
333 if (pDesc->dwValidData & DMUS_OBJ_FILENAME) {
334 /* generate filename; if it's full path, don't add search
335 directory path, otherwise do */
336 WCHAR wszFileName[MAX_PATH];
338 if (pDesc->dwValidData & DMUS_OBJ_FULLPATH) {
339 lstrcpyW(wszFileName, pDesc->wszFileName);
340 } else {
341 WCHAR *p;
342 WCHAR wszSearchPath[MAX_PATH];
343 DMUSIC_GetLoaderSettings (iface, &pDesc->guidClass, wszSearchPath, NULL);
344 lstrcpyW(wszFileName, wszSearchPath);
345 p = wszFileName + lstrlenW(wszFileName);
346 if (p > wszFileName && p[-1] != '\\') *p++ = '\\';
347 strcpyW(p, pDesc->wszFileName);
349 /* create stream */
350 hr = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pStream);
351 if (FAILED(hr)) {
352 ERR(": could not create file stream\n");
353 return DMUS_E_LOADER_FAILEDOPEN;
355 /* attach stream */
356 hr = IDirectMusicLoaderFileStream_Attach (pStream, wszFileName, iface);
357 if (FAILED(hr)) {
358 ERR(": could not attach stream to file\n");
359 IStream_Release (pStream);
360 return DMUS_E_LOADER_FAILEDOPEN;
363 else if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
364 /* create stream */
365 hr = DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID*)&pStream);
366 if (FAILED(hr)) {
367 ERR(": could not create generic stream\n");
368 return DMUS_E_LOADER_FAILEDOPEN;
370 /* attach stream */
371 hr = IDirectMusicLoaderGenericStream_Attach (pStream, pDesc->pStream, iface);
372 if (FAILED(hr)) {
373 ERR(": could not attach stream\n");
374 IStream_Release (pStream);
375 return DMUS_E_LOADER_FAILEDOPEN;
378 else if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
379 /* create stream */
380 hr = DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID*)&pStream);
381 if (FAILED(hr)) {
382 ERR(": could not create resource stream\n");
383 return DMUS_E_LOADER_FAILEDOPEN;
385 /* attach stream */
386 hr = IDirectMusicLoaderResourceStream_Attach (pStream, pDesc->pbMemData, pDesc->llMemLength, 0, iface);
387 if (FAILED(hr)) {
388 ERR(": could not attach stream to resource\n");
389 IStream_Release (pStream);
390 return DMUS_E_LOADER_FAILEDOPEN;
393 else {
394 ERR(": no way to get additional info\n");
395 return DMUS_E_LOADER_FAILEDOPEN;
398 /* create object */
399 CoCreateInstance (&pDesc->guidClass, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject, (LPVOID*)&pObject);
401 /* *sigh*... some ms objects have lousy implementation of ParseDescriptor that clears input descriptor :( */
402 #ifdef NOW_WE_ARE_FREE
403 /* parse descriptor: we actually use input descriptor; fields that aren't available from stream remain,
404 otherwise real info is set */
405 IDirectMusicObject_ParseDescriptor (pObject, pStream, pDesc);
406 #endif
407 /* hmph... due to some trouble I had with certain tests, we store current position and then set it back */
408 DM_STRUCT_INIT(&Desc);
409 if (FAILED(IDirectMusicObject_ParseDescriptor (pObject, pStream, &Desc))) {
410 ERR(": couldn't parse descriptor\n");
411 return DMUS_E_LOADER_FORMATNOTSUPPORTED;
414 /* copy elements from parsed descriptor into input descriptor; this sets new info, overwriting if necessary,
415 but leaves info that's provided by input and not available from stream */
416 DMUSIC_CopyDescriptor (pDesc, &Desc);
418 /* release everything */
419 IDirectMusicObject_Release (pObject);
420 IStream_Release (pStream);
422 /* sometimes it happens that twisted programs call SetObject for same object twice...
423 in such cases, native loader returns S_OK and does nothing... a sound plan */
424 LIST_FOR_EACH (pEntry, This->pObjects) {
425 pObjectEntry = LIST_ENTRY (pEntry, WINE_LOADER_ENTRY, entry);
426 if (!memcmp (&pObjectEntry->Desc, pDesc, sizeof(DMUS_OBJECTDESC))) {
427 TRACE(": exacly same entry already exists\n");
428 return S_OK;
432 /* add new entry */
433 TRACE(": adding alias entry with following info: \n%s\n", debugstr_DMUS_OBJECTDESC(pDesc));
434 pNewEntry = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(WINE_LOADER_ENTRY));
435 /* use this function instead of pure memcpy due to streams (memcpy just copies pointer),
436 which is basically used further by app that called SetDescriptor... better safety than exception */
437 DMUSIC_CopyDescriptor (&pNewEntry->Desc, pDesc);
438 list_add_head (This->pObjects, &pNewEntry->entry);
440 return S_OK;
443 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, WCHAR* pwzPath, BOOL fClear) {
444 WCHAR wszCurrentPath[MAX_PATH];
445 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
446 TRACE("(%p, %s, %s, %d)\n", This, debugstr_dmguid(rguidClass), debugstr_w(pwzPath), fClear);
447 FIXME(": fClear ignored\n");
448 DMUSIC_GetLoaderSettings (iface, rguidClass, wszCurrentPath, NULL);
449 if (!strncmpW(wszCurrentPath, pwzPath, MAX_PATH)) {
450 return S_FALSE;
452 /* FIXME: check if path is valid; else return DMUS_E_LOADER_BADPATH */
453 return DMUSIC_SetLoaderSettings (iface, rguidClass, pwzPath, NULL);
456 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, WCHAR* pwzFileExtension, WCHAR* pwzScanFileName) {
457 static const WCHAR wszAny[] = {'*',0};
458 WIN32_FIND_DATAW FileData;
459 HANDLE hSearch;
460 WCHAR wszSearchString[MAX_PATH];
461 WCHAR *p;
462 HRESULT result;
463 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
464 TRACE("(%p, %s, %p, %p)\n", This, debugstr_dmguid(rguidClass), pwzFileExtension, pwzScanFileName);
465 if (IsEqualGUID (rguidClass, &GUID_DirectMusicAllTypes) || !DMUSIC_IsValidLoadableClass(rguidClass)) {
466 ERR(": rguidClass invalid CLSID\n");
467 return REGDB_E_CLASSNOTREG;
470 /* get search path for given class */
471 DMUSIC_GetLoaderSettings (iface, rguidClass, wszSearchString, NULL);
473 p = wszSearchString + lstrlenW(wszSearchString);
474 if (p > wszSearchString && p[-1] != '\\') *p++ = '\\';
475 *p++ = '*'; /* any file */
476 if (strcmpW (pwzFileExtension, wszAny)) *p++ = '.'; /* if we have actual extension, put a dot */
477 strcpyW (p, pwzFileExtension);
479 TRACE(": search string: %s\n", debugstr_w(wszSearchString));
481 hSearch = FindFirstFileW (wszSearchString, &FileData);
482 if (hSearch == INVALID_HANDLE_VALUE) {
483 TRACE(": no files found\n");
484 return S_FALSE;
487 do {
488 DMUS_OBJECTDESC Desc;
489 DM_STRUCT_INIT(&Desc);
490 Desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_DATE;
491 memcpy (&Desc.guidClass, rguidClass, sizeof(GUID));
492 strcpyW (Desc.wszFileName, FileData.cFileName);
493 FileTimeToLocalFileTime (&FileData.ftCreationTime, &Desc.ftDate);
494 IDirectMusicLoader8_SetObject (iface, &Desc);
496 if (!FindNextFileW (hSearch, &FileData)) {
497 if (GetLastError () == ERROR_NO_MORE_FILES) {
498 TRACE(": search completed\n");
499 result = S_OK;
500 } else {
501 ERR(": could not get next file\n");
502 result = E_FAIL;
504 FindClose (hSearch);
505 return result;
507 } while (1);
510 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject (LPDIRECTMUSICLOADER8 iface, IDirectMusicObject* pObject) {
511 DMUS_OBJECTDESC Desc;
512 HRESULT result = DMUS_E_LOADER_OBJECTNOTFOUND;
513 struct list *pEntry;
514 LPWINE_LOADER_ENTRY pObjectEntry = NULL;
516 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
517 TRACE("(%p, %p)\n", This, pObject);
519 /* get descriptor */
520 DM_STRUCT_INIT(&Desc);
521 IDirectMusicObject_GetDescriptor (pObject, &Desc);
523 /* now iterate thru list and check if we have alias (without object), corresponding
524 to descriptor of input object */
525 LIST_FOR_EACH(pEntry, This->pObjects) {
526 pObjectEntry = LIST_ENTRY(pEntry, WINE_LOADER_ENTRY, entry);
527 if ((Desc.dwValidData & DMUS_OBJ_OBJECT) &&
528 (pObjectEntry->Desc.dwValidData & DMUS_OBJ_OBJECT) &&
529 IsEqualGUID (&Desc.guidObject, &pObjectEntry->Desc.guidObject)) {
530 TRACE(": found it by object GUID\n");
531 if ((pObjectEntry->Desc.dwValidData & DMUS_OBJ_LOADED) && pObjectEntry->pObject)
532 result = S_FALSE;
533 else
534 result = S_OK;
535 break;
537 else if ((Desc.dwValidData & (DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH)) &&
538 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH)) &&
539 !strncmpW (Desc.wszFileName, pObjectEntry->Desc.wszFileName, DMUS_MAX_FILENAME)) {
540 TRACE(": found it by fullpath filename\n");
541 if ((pObjectEntry->Desc.dwValidData & DMUS_OBJ_LOADED) && pObjectEntry->pObject)
542 result = S_FALSE;
543 else
544 result = S_OK;
545 break;
547 else if ((Desc.dwValidData & (DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY)) &&
548 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY)) &&
549 !strncmpW (Desc.wszName, pObjectEntry->Desc.wszName, DMUS_MAX_NAME) &&
550 !strncmpW (Desc.wszCategory, pObjectEntry->Desc.wszCategory, DMUS_MAX_CATEGORY)) {
551 TRACE(": found it by name and category\n");
552 if ((pObjectEntry->Desc.dwValidData & DMUS_OBJ_LOADED) && pObjectEntry->pObject)
553 result = S_FALSE;
554 else
555 result = S_OK;
556 break;
558 else if ((Desc.dwValidData & DMUS_OBJ_NAME) &&
559 (pObjectEntry->Desc.dwValidData & DMUS_OBJ_NAME) &&
560 !strncmpW (Desc.wszName, pObjectEntry->Desc.wszName, DMUS_MAX_NAME)) {
561 TRACE(": found it by name\n");
562 if ((pObjectEntry->Desc.dwValidData & DMUS_OBJ_LOADED) && pObjectEntry->pObject)
563 result = S_FALSE;
564 else
565 result = S_OK;
566 break;
568 else if ((Desc.dwValidData & DMUS_OBJ_FILENAME) &&
569 (pObjectEntry->Desc.dwValidData & DMUS_OBJ_FILENAME) &&
570 !strncmpW (Desc.wszFileName, pObjectEntry->Desc.wszFileName, DMUS_MAX_FILENAME)) {
571 TRACE(": found it by filename\n");
572 if ((pObjectEntry->Desc.dwValidData & DMUS_OBJ_LOADED) && pObjectEntry->pObject)
573 result = S_FALSE;
574 else
575 result = S_OK;
576 break;
580 /* if we found such alias, then set everything */
581 if (result == S_OK) {
582 pObjectEntry->Desc.dwValidData &= DMUS_OBJ_LOADED;
583 pObjectEntry->pObject = pObject;
584 IDirectMusicObject_AddRef (pObjectEntry->pObject);
587 return result;
590 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject (LPDIRECTMUSICLOADER8 iface, IDirectMusicObject* pObject) {
591 DMUS_OBJECTDESC Desc;
592 struct list *pEntry;
593 LPWINE_LOADER_ENTRY pObjectEntry = NULL;
594 HRESULT result = S_FALSE;
596 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
597 TRACE("(%p, %p)\n", This, pObject);
599 /* get descriptor */
600 DM_STRUCT_INIT(&Desc);
601 IDirectMusicObject_GetDescriptor (pObject, &Desc);
603 /* iterate thru the list of objects we know about; check only those with DMUS_OBJ_LOADED */
604 TRACE(": looking for the object in cache\n");
605 LIST_FOR_EACH(pEntry, This->pObjects) {
606 pObjectEntry = LIST_ENTRY(pEntry, WINE_LOADER_ENTRY, entry);
607 if ((Desc.dwValidData & DMUS_OBJ_OBJECT) &&
608 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_OBJECT | DMUS_OBJ_LOADED)) &&
609 IsEqualGUID (&Desc.guidObject, &pObjectEntry->Desc.guidObject)) {
610 TRACE(": found it by object GUID\n%s", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc));
611 result = S_OK;
612 break;
614 else if ((Desc.dwValidData & (DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH)) &&
615 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_LOADED)) &&
616 !strncmpW (Desc.wszFileName, pObjectEntry->Desc.wszFileName, DMUS_MAX_FILENAME)) {
617 TRACE(": found it by fullpath filename\n");
618 result = S_OK;
619 break;
621 else if ((Desc.dwValidData & (DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY)) &&
622 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY | DMUS_OBJ_LOADED)) &&
623 !strncmpW (Desc.wszName, pObjectEntry->Desc.wszName, DMUS_MAX_NAME) &&
624 !strncmpW (Desc.wszCategory, pObjectEntry->Desc.wszCategory, DMUS_MAX_CATEGORY)) {
625 TRACE(": found it by name and category\n");
626 result = S_OK;
627 break;
629 else if ((Desc.dwValidData & DMUS_OBJ_NAME) &&
630 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_NAME | DMUS_OBJ_LOADED)) &&
631 !strncmpW (Desc.wszName, pObjectEntry->Desc.wszName, DMUS_MAX_NAME)) {
632 TRACE(": found it by name\n");
633 result = S_OK;
634 break;
636 else if ((Desc.dwValidData & DMUS_OBJ_FILENAME) &&
637 (pObjectEntry->Desc.dwValidData & (DMUS_OBJ_FILENAME | DMUS_OBJ_LOADED)) &&
638 !strncmpW (Desc.wszFileName, pObjectEntry->Desc.wszFileName, DMUS_MAX_FILENAME)) {
639 TRACE(": found it by filename\n");
640 result = S_OK;
641 break;
644 if (result == S_OK) {
645 /*TRACE(": releasing: \n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject); */
646 IDirectMusicObject_Release (pObjectEntry->pObject);
647 pObjectEntry->pObject = NULL;
648 pObjectEntry->Desc.dwValidData &= ~DMUS_OBJ_LOADED;
650 return result;
653 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass) {
654 struct list *pEntry;
655 LPWINE_LOADER_ENTRY pObjectEntry;
656 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
657 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidClass));
659 LIST_FOR_EACH (pEntry, This->pObjects) {
660 pObjectEntry = LIST_ENTRY (pEntry, WINE_LOADER_ENTRY, entry);
662 if ((IsEqualGUID (rguidClass, &GUID_DirectMusicAllTypes) || IsEqualGUID (rguidClass, &pObjectEntry->Desc.guidClass)) &&
663 (pObjectEntry->Desc.dwValidData & DMUS_OBJ_LOADED)) {
664 /* basically, wrap to ReleaseObject for each object found */
665 IDirectMusicLoader8_ReleaseObject (iface, pObjectEntry->pObject);
669 return S_OK;
672 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, BOOL fEnable) {
673 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
674 BOOL bCurrent;
675 TRACE("(%p, %s, %d)\n", This, debugstr_dmguid(rguidClass), fEnable);
676 DMUSIC_GetLoaderSettings (iface, rguidClass, NULL, &bCurrent);
677 if (bCurrent == fEnable)
678 return S_FALSE;
679 else
680 return DMUSIC_SetLoaderSettings (iface, rguidClass, NULL, &fEnable);
683 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, DWORD dwIndex, LPDMUS_OBJECTDESC pDesc) {
684 DWORD dwCount = 0;
685 struct list *pEntry;
686 LPWINE_LOADER_ENTRY pObjectEntry;
687 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
688 TRACE("(%p, %s, %ld, %p)\n", This, debugstr_dmguid(rguidClass), dwIndex, pDesc);
690 DM_STRUCT_INIT(pDesc);
692 LIST_FOR_EACH (pEntry, This->pObjects) {
693 pObjectEntry = LIST_ENTRY (pEntry, WINE_LOADER_ENTRY, entry);
695 if (IsEqualGUID (rguidClass, &GUID_DirectMusicAllTypes) || IsEqualGUID (rguidClass, &pObjectEntry->Desc.guidClass)) {
696 if (dwCount == dwIndex) {
697 memcpy (pDesc, &pObjectEntry->Desc, sizeof(DMUS_OBJECTDESC));
698 /* we aren't supposed to reveal this info */
699 pDesc->dwValidData &= ~(DMUS_OBJ_MEMORY | DMUS_OBJ_STREAM);
700 pDesc->pbMemData = NULL;
701 pDesc->llMemLength = 0;
702 pDesc->pStream = NULL;
703 return S_OK;
705 dwCount++;
709 TRACE(": not found\n");
710 return S_FALSE;
713 void WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage (LPDIRECTMUSICLOADER8 iface) {
714 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
715 FIXME("(%p): stub\n", This);
718 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown (LPDIRECTMUSICLOADER8 iface, IUnknown* pObject) {
719 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
720 HRESULT result;
721 LPDIRECTMUSICOBJECT pObjectInterface;
723 TRACE("(%p, %p)\n", This, pObject);
725 if (IsBadReadPtr (pObject, sizeof(LPUNKNOWN))) {
726 ERR(": pObject bad write pointer\n");
727 return E_POINTER;
729 /* we simply get IDirectMusicObject interface */
730 result = IUnknown_QueryInterface (pObject, &IID_IDirectMusicObject, (LPVOID*)&pObjectInterface);
731 if (FAILED(result)) return result;
732 /* and release it in old-fashioned way */
733 result = IDirectMusicLoader8_ReleaseObject (iface, pObjectInterface);
734 IDirectMusicObject_Release (pObjectInterface);
736 return result;
739 HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClassID, REFIID iidInterfaceID, WCHAR* pwzFilePath, void** ppObject) {
740 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
741 DMUS_OBJECTDESC ObjDesc;
742 WCHAR wszLoaderSearchPath[MAX_PATH];
744 TRACE("(%p, %s, %s, %s, %p): wrapping to IDirectMusicLoaderImpl_GetObject\n", This, debugstr_dmguid(rguidClassID), debugstr_dmguid(iidInterfaceID), debugstr_w(pwzFilePath), ppObject);
746 DM_STRUCT_INIT(&ObjDesc);
747 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 */
748 memcpy (&ObjDesc.guidClass, rguidClassID, sizeof(CLSID));
749 /* OK, MSDN says that search order is the following:
750 - current directory (DONE)
751 - windows search path (FIXME: how do I get that?)
752 - loader's search path (DONE)
754 DMUSIC_GetLoaderSettings (iface, rguidClassID, wszLoaderSearchPath, NULL);
755 /* search in current directory */
756 if (!SearchPathW (NULL, pwzFilePath, NULL, sizeof(ObjDesc.wszFileName)/sizeof(WCHAR), ObjDesc.wszFileName, NULL) &&
757 /* search in loader's search path */
758 !SearchPathW (wszLoaderSearchPath, pwzFilePath, NULL, sizeof(ObjDesc.wszFileName)/sizeof(WCHAR), ObjDesc.wszFileName, NULL)) {
759 /* cannot find file */
760 TRACE(": cannot find file\n");
761 return DMUS_E_LOADER_FAILEDOPEN;
764 TRACE(": full file path = %s\n", debugstr_w (ObjDesc.wszFileName));
766 return IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject (iface, &ObjDesc, iidInterfaceID, ppObject);
769 static const IDirectMusicLoader8Vtbl DirectMusicLoader_Loader_Vtbl = {
770 IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface,
771 IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef,
772 IDirectMusicLoaderImpl_IDirectMusicLoader_Release,
773 IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject,
774 IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject,
775 IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory,
776 IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory,
777 IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject,
778 IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject,
779 IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache,
780 IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache,
781 IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject,
782 IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage,
783 IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown,
784 IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile
787 /* for ClassFactory */
788 HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
789 IDirectMusicLoaderImpl *obj;
790 DMUS_OBJECTDESC Desc;
791 LPWINE_LOADER_ENTRY pDefaultDLSEntry;
792 struct list *pEntry;
794 TRACE("(%s, %p, %p)\n", debugstr_dmguid(lpcGUID), ppobj, pUnkOuter);
795 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderImpl));
796 if (NULL == obj) {
797 *ppobj = (LPDIRECTMUSICLOADER8)NULL;
798 return E_OUTOFMEMORY;
800 obj->LoaderVtbl = &DirectMusicLoader_Loader_Vtbl;
801 obj->dwRef = 0; /* will be inited with QueryInterface */
802 /* init critical section */
803 /* init cache/alias list */
804 /*InitializeCriticalSection (&obj->CritSect); */
805 obj->pObjects = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(struct list));
806 list_init (obj->pObjects);
807 /* init settings */
808 obj->pClassSettings = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(struct list));
809 list_init (obj->pClassSettings);
810 DMUSIC_InitLoaderSettings ((LPDIRECTMUSICLOADER8)obj);
812 /* set default DLS collection (via SetObject... so that loading via DMUS_OBJ_OBJECT is possible) */
813 DM_STRUCT_INIT(&Desc);
814 Desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_OBJECT;
815 memcpy (&Desc.guidClass, &CLSID_DirectMusicCollection, sizeof(CLSID));
816 memcpy (&Desc.guidObject, &GUID_DefaultGMCollection, sizeof(GUID));
817 DMUSIC_GetDefaultGMPath (Desc.wszFileName);
818 IDirectMusicLoader_SetObject ((LPDIRECTMUSICLOADER8)obj, &Desc);
819 /* and now the workaroundTM for "invalid" default DLS; basically,
820 my tests showed that if GUID chunk is present in default DLS
821 collection, loader treats it as "invalid" and returns
822 DMUS_E_LOADER_NOFILENAME for all requests for it; basically, we check
823 if out input guidObject was overwritten */
824 pEntry = list_head (obj->pObjects);
825 pDefaultDLSEntry = LIST_ENTRY (pEntry, WINE_LOADER_ENTRY, entry);
826 if (!IsEqualGUID(&Desc.guidObject, &GUID_DefaultGMCollection)) {
827 pDefaultDLSEntry->bInvalidDefaultDLS = TRUE;
830 /* increase number of instances */
831 InterlockedIncrement (&dwDirectMusicLoader);
833 return IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface ((LPDIRECTMUSICLOADER8)obj, lpcGUID, ppobj);
836 HRESULT WINAPI DMUSIC_DestroyDirectMusicLoaderImpl (LPDIRECTMUSICLOADER8 iface) {
837 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
839 TRACE("(%p)\n", This);
841 /* firstly, release the cache */
842 IDirectMusicLoader8_ClearCache (iface, &GUID_DirectMusicAllTypes);
843 /* FIXME: release all allocated entries */
844 /* destroy critical section */
845 /*DeleteCriticalSection (&This->CritSect); */
847 /* decrease number of instances */
848 InterlockedDecrement (&dwDirectMusicLoader);
850 return S_OK;
853 /* help function for DMUSIC_SetDefaultDLS */
854 HRESULT WINAPI DMUSIC_GetDefaultGMPath (WCHAR wszPath[MAX_PATH]) {
855 HKEY hkDM;
856 DWORD returnType, sizeOfReturnBuffer = MAX_PATH;
857 char szPath[MAX_PATH];
859 if ((RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectMusic" , 0, KEY_READ, &hkDM) != ERROR_SUCCESS) ||
860 (RegQueryValueExA (hkDM, "GMFilePath", NULL, &returnType, (LPBYTE) szPath, &sizeOfReturnBuffer) != ERROR_SUCCESS)) {
861 WARN(": registry entry missing\n" );
862 return E_FAIL;
864 /* FIXME: Check return types to ensure we're interpreting data right */
865 MultiByteToWideChar (CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);
867 return S_OK;
870 /* help function for retrieval of search path and caching option for certain class */
871 HRESULT WINAPI DMUSIC_GetLoaderSettings (LPDIRECTMUSICLOADER8 iface, REFGUID pClassID, WCHAR* wszSearchPath, LPBOOL pbCache) {
872 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
873 struct list *pEntry;
874 TRACE(": (%p, %s, %p, %p)\n", This, debugstr_dmguid(pClassID), wszSearchPath, pbCache);
876 LIST_FOR_EACH(pEntry, This->pClassSettings) {
877 LPWINE_LOADER_OPTION pOptionEntry = LIST_ENTRY(pEntry, WINE_LOADER_OPTION, entry);
878 if (IsEqualCLSID (pClassID, &pOptionEntry->guidClass)) {
879 if (wszSearchPath)
880 strcpyW(wszSearchPath, pOptionEntry->wszSearchPath);
881 if (pbCache)
882 *pbCache = pOptionEntry->bCache;
883 return S_OK;
886 return S_FALSE;
889 /* help function for setting search path and caching option for certain class */
890 HRESULT WINAPI DMUSIC_SetLoaderSettings (LPDIRECTMUSICLOADER8 iface, REFGUID pClassID, WCHAR* wszSearchPath, LPBOOL pbCache) {
891 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
892 struct list *pEntry;
893 HRESULT result = S_FALSE; /* in case pClassID != GUID_DirectMusicAllTypes and not a valid CLSID */
894 TRACE(": (%p, %s, %p, %p)\n", This, debugstr_dmguid(pClassID), wszSearchPath, pbCache);
896 LIST_FOR_EACH(pEntry, This->pClassSettings) {
897 LPWINE_LOADER_OPTION pOptionEntry = LIST_ENTRY(pEntry, WINE_LOADER_OPTION, entry);
898 /* well, either we have GUID_DirectMusicAllTypes and need to set it to all,
899 or specific CLSID is given and we set it only to it */
900 if (IsEqualGUID (pClassID, &GUID_DirectMusicAllTypes) ||
901 IsEqualCLSID (pClassID, &pOptionEntry->guidClass)) {
902 if (wszSearchPath)
903 strcpyW(pOptionEntry->wszSearchPath, wszSearchPath);
904 if (pbCache)
905 pOptionEntry->bCache = *pbCache;
906 result = S_OK;
910 return result;
913 HRESULT WINAPI DMUSIC_InitLoaderSettings (LPDIRECTMUSICLOADER8 iface) {
914 ICOM_THIS_MULTI(IDirectMusicLoaderImpl, LoaderVtbl, iface);
916 /* hard-coded list of classes */
917 static REFCLSID classes[] = {
918 &CLSID_DirectMusicAudioPathConfig,
919 &CLSID_DirectMusicBand,
920 &CLSID_DirectMusicContainer,
921 &CLSID_DirectMusicCollection,
922 &CLSID_DirectMusicChordMap,
923 &CLSID_DirectMusicSegment,
924 &CLSID_DirectMusicScript,
925 &CLSID_DirectMusicSong,
926 &CLSID_DirectMusicStyle,
927 &CLSID_DirectMusicGraph,
928 &CLSID_DirectSoundWave
931 unsigned int i;
932 WCHAR wszCurrent[MAX_PATH];
934 TRACE(": (%p)\n", This);
935 GetCurrentDirectoryW (MAX_PATH, wszCurrent);
937 for (i = 0; i < sizeof(classes)/sizeof(REFCLSID); i++) {
938 LPWINE_LOADER_OPTION pNewSetting = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(WINE_LOADER_OPTION));
939 memcpy (&pNewSetting->guidClass, classes[i], sizeof(CLSID));
940 strcpyW (pNewSetting->wszSearchPath, wszCurrent);
941 pNewSetting->bCache = TRUE;
942 list_add_tail (This->pClassSettings, &pNewSetting->entry);
945 return S_OK;
948 HRESULT WINAPI DMUSIC_CopyDescriptor (LPDMUS_OBJECTDESC pDst, LPDMUS_OBJECTDESC pSrc) {
949 TRACE(": copy \n%s", debugstr_DMUS_OBJECTDESC(pSrc));
950 /* copy field by field */
951 if (pSrc->dwValidData & DMUS_OBJ_CLASS) memcpy (&pDst->guidClass, &pSrc->guidClass, sizeof(CLSID));
952 if (pSrc->dwValidData & DMUS_OBJ_OBJECT) memcpy (&pDst->guidObject, &pSrc->guidObject, sizeof(GUID));
953 if (pSrc->dwValidData & DMUS_OBJ_DATE) memcpy (&pDst->ftDate, &pSrc->ftDate, sizeof(FILETIME));
954 if (pSrc->dwValidData & DMUS_OBJ_VERSION) memcpy (&pDst->vVersion, &pSrc->vVersion, sizeof(DMUS_VERSION));
955 if (pSrc->dwValidData & DMUS_OBJ_NAME) strcpyW (pDst->wszName, pSrc->wszName);
956 if (pSrc->dwValidData & DMUS_OBJ_CATEGORY) strcpyW (pDst->wszCategory, pSrc->wszCategory);
957 if (pSrc->dwValidData & DMUS_OBJ_FILENAME) strcpyW (pDst->wszFileName, pSrc->wszFileName);
958 if (pSrc->dwValidData & DMUS_OBJ_STREAM) IStream_Clone (pSrc->pStream, &pDst->pStream);
959 if (pSrc->dwValidData & DMUS_OBJ_MEMORY) {
960 pDst->pbMemData = pSrc->pbMemData;
961 pDst->llMemLength = pSrc->llMemLength;
963 /* set flags */
964 pDst->dwValidData |= pSrc->dwValidData;
965 return S_OK;
968 BOOL WINAPI DMUSIC_IsValidLoadableClass (REFCLSID pClassID) {
969 if (IsEqualCLSID(pClassID, &CLSID_DirectMusicAudioPathConfig) ||
970 IsEqualCLSID(pClassID, &CLSID_DirectMusicBand) ||
971 IsEqualCLSID(pClassID, &CLSID_DirectMusicContainer) ||
972 IsEqualCLSID(pClassID, &CLSID_DirectMusicCollection) ||
973 IsEqualCLSID(pClassID, &CLSID_DirectMusicChordMap) ||
974 IsEqualCLSID(pClassID, &CLSID_DirectMusicSegment) ||
975 IsEqualCLSID(pClassID, &CLSID_DirectMusicScript) ||
976 IsEqualCLSID(pClassID, &CLSID_DirectMusicSong) ||
977 IsEqualCLSID(pClassID, &CLSID_DirectMusicStyle) ||
978 IsEqualCLSID(pClassID, &CLSID_DirectMusicGraph) ||
979 IsEqualCLSID(pClassID, &CLSID_DirectSoundWave) ||
980 IsEqualCLSID(pClassID, &GUID_DirectMusicAllTypes))
981 return TRUE;
982 else
983 return FALSE;