1 /* IDirectMusicLoader8 Implementation
3 * Copyright (C) 2003 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.
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
30 #include "dmloader_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
34 HRESULT WINAPI DMUSIC_GetDefaultGMPath (WCHAR wszPath[MAX_PATH]);
36 /* IDirectMusicLoader8 IUnknown part: */
37 HRESULT WINAPI IDirectMusicLoader8Impl_QueryInterface (LPDIRECTMUSICLOADER8 iface, REFIID riid, LPVOID *ppobj)
39 ICOM_THIS(IDirectMusicLoader8Impl,iface);
41 if (IsEqualIID (riid, &IID_IUnknown) ||
42 IsEqualIID (riid, &IID_IDirectMusicLoader) ||
43 IsEqualIID (riid, &IID_IDirectMusicLoader8)) {
44 IDirectMusicLoader8Impl_AddRef(iface);
49 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
53 ULONG WINAPI IDirectMusicLoader8Impl_AddRef (LPDIRECTMUSICLOADER8 iface)
55 ICOM_THIS(IDirectMusicLoader8Impl,iface);
56 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
60 ULONG WINAPI IDirectMusicLoader8Impl_Release (LPDIRECTMUSICLOADER8 iface)
62 ICOM_THIS(IDirectMusicLoader8Impl,iface);
63 ULONG ref = --This->ref;
64 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
66 HeapFree(GetProcessHeap(), 0, This);
71 /* IDirectMusicLoader8 IDirectMusicLoader part: */
72 HRESULT WINAPI IDirectMusicLoader8Impl_GetObject (LPDIRECTMUSICLOADER8 iface, LPDMUS_OBJECTDESC pDesc, REFIID riid, LPVOID* ppv)
74 IDirectMusicObject* pObject;
75 ICOM_THIS(IDirectMusicLoader8Impl,iface);
77 struct list *listEntry;
78 DMUS_PRIVATE_CACHE_ENTRY *cacheEntry;
79 LPDMUS_PRIVATE_CACHE_ENTRY newEntry;
81 TRACE("(%p, %p, %s, %p)\n", This, pDesc, debugstr_guid(riid), ppv);
83 TRACE("looking up cache...\n");
85 LIST_FOR_EACH (listEntry, &This->CacheList) {
86 cacheEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_CACHE_ENTRY, entry );
88 if ((pDesc->dwValidData & DMUS_OBJ_OBJECT) || (pDesc->dwValidData & DMUS_OBJ_FILENAME)) {
89 if (pDesc->dwValidData & DMUS_OBJ_OBJECT) {
90 if (IsEqualGUID (&cacheEntry->guidObject, &pDesc->guidObject)) {
91 TRACE(": found it by GUID\n");
92 if (cacheEntry->pObject)
93 return IDirectMusicObject_QueryInterface ((LPDIRECTMUSICOBJECT)cacheEntry->pObject, riid, ppv);
96 if (pDesc->dwValidData & DMUS_OBJ_FILENAME) {
97 if (cacheEntry->wzFileName && !strncmpW (pDesc->wszFileName, cacheEntry->wzFileName, MAX_PATH)) {
98 TRACE(": found it by FileName\n");
99 if (cacheEntry->pObject)
100 return IDirectMusicObject_QueryInterface ((LPDIRECTMUSICOBJECT)cacheEntry->pObject, riid, ppv);
106 /* object doesn't exist in cache... guess we'll have to load it */
107 TRACE(": object does not exist in cache\n");
108 result = CoCreateInstance (&pDesc->guidClass, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject, (LPVOID*)&pObject);
109 if (FAILED(result)) return result;
110 if (pDesc->dwValidData & DMUS_OBJ_FILENAME) {
111 /* load object from file */
112 WCHAR wzFileName[MAX_PATH];
113 ILoaderStream* pStream;
114 IPersistStream *pPersistStream = NULL;
115 /* if it's full path, don't add search directory path, otherwise do */
116 if (pDesc->dwValidData & DMUS_OBJ_FULLPATH) {
117 lstrcpyW( wzFileName, pDesc->wszFileName );
120 lstrcpyW( wzFileName, This->wzSearchPath );
121 p = wzFileName + lstrlenW(wzFileName);
122 if (p > wzFileName && p[-1] != '\\') *p++ = '\\';
123 strcpyW( p, pDesc->wszFileName );
125 TRACE(": loading from file (%s)\n", debugstr_w(wzFileName));
127 result = DMUSIC_CreateLoaderStream ((LPSTREAM*)&pStream);
128 if (FAILED(result)) return result;
130 result = ILoaderStream_Attach (pStream, wzFileName, (LPDIRECTMUSICLOADER)iface);
131 if (FAILED(result)) return result;
133 result = IDirectMusicObject_QueryInterface (pObject, &IID_IPersistStream, (LPVOID*)&pPersistStream);
134 if (FAILED(result)) return result;
136 result = IPersistStream_Load (pPersistStream, (LPSTREAM)pStream);
137 if (FAILED(result)) return result;
139 ILoaderStream_IStream_Release ((LPSTREAM)pStream);
140 IPersistStream_Release (pPersistStream);
141 } else if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
142 /* load object from stream */
143 IStream* pClonedStream = NULL;
144 IPersistStream* pPersistStream = NULL;
146 TRACE(": loading from stream\n");
147 result = IDirectMusicObject_QueryInterface (pObject, &IID_IPersistStream, (LPVOID*)&pPersistStream);
148 if (FAILED(result)) return result;
150 result = IStream_Clone (pDesc->pStream, &pClonedStream);
151 if (FAILED(result)) return result;
153 result = IPersistStream_Load (pPersistStream, pClonedStream);
154 if (FAILED(result)) return result;
156 IPersistStream_Release (pPersistStream);
157 IStream_Release (pClonedStream);
158 } else if (pDesc->dwValidData & DMUS_OBJ_OBJECT) {
159 /* load object by GUID */
160 TRACE(": loading by GUID (only default DLS supported)\n");
161 if (IsEqualGUID (&pDesc->guidObject, &GUID_DefaultGMCollection)) {
162 WCHAR wzFileName[MAX_PATH];
163 IPersistStream *pPersistStream = NULL;
164 ILoaderStream* pStream;
165 if (FAILED(DMUSIC_GetDefaultGMPath (wzFileName)))
167 /* load object from file */
168 result = DMUSIC_CreateLoaderStream ((LPSTREAM*)&pStream);
169 if (FAILED(result)) return result;
171 result = ILoaderStream_Attach (pStream, wzFileName, (LPDIRECTMUSICLOADER)iface);
172 if (FAILED(result)) return result;
174 result = IDirectMusicObject_QueryInterface (pObject, &IID_IPersistStream, (LPVOID*)&pPersistStream);
175 if (FAILED(result)) return result;
177 result = IPersistStream_Load (pPersistStream, (LPSTREAM)pStream);
178 if (FAILED(result)) return result;
180 ILoaderStream_IStream_Release ((LPSTREAM)pStream);
181 IPersistStream_Release (pPersistStream);
186 /* nowhere to load from */
187 FIXME(": unknown/unsupported way of loading\n");
190 /* add object to cache */
191 newEntry = (LPDMUS_PRIVATE_CACHE_ENTRY) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_CACHE_ENTRY));
192 if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
193 memcpy (&newEntry->guidObject, &pDesc->guidObject, sizeof (pDesc->guidObject));
194 if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
195 strncpyW (newEntry->wzFileName, pDesc->wszFileName, MAX_PATH);
197 newEntry->pObject = pObject;
198 list_add_tail (&This->CacheList, &newEntry->entry);
199 TRACE(": filled in cache entry\n");
201 /* for debug purposes (e.g. to check if all files are cached) */
204 LIST_FOR_EACH (listEntry, &This->CacheList) {
206 cacheEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_CACHE_ENTRY, entry );
207 TRACE("Entry nr. %i: GUID = %s, FileName = %s\n", i, debugstr_guid (&cacheEntry->guidObject), debugstr_w (cacheEntry->wzFileName));
211 return IDirectMusicObject_QueryInterface (pObject, riid, ppv);
214 HRESULT WINAPI IDirectMusicLoader8Impl_SetObject (LPDIRECTMUSICLOADER8 iface, LPDMUS_OBJECTDESC pDesc)
216 ICOM_THIS(IDirectMusicLoader8Impl,iface);
218 FIXME("(%p, %p): stub\n", This, pDesc);
223 HRESULT WINAPI IDirectMusicLoader8Impl_SetSearchDirectory (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, WCHAR* pwzPath, BOOL fClear)
225 ICOM_THIS(IDirectMusicLoader8Impl,iface);
227 TRACE("(%p, %s, %p, %d)\n", This, debugstr_guid(rguidClass), pwzPath, fClear);
228 if (0 == strncmpW(This->wzSearchPath, pwzPath, MAX_PATH)) {
231 strncpyW(This->wzSearchPath, pwzPath, MAX_PATH);
236 HRESULT WINAPI IDirectMusicLoader8Impl_ScanDirectory (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, WCHAR* pwzFileExtension, WCHAR* pwzScanFileName)
238 ICOM_THIS(IDirectMusicLoader8Impl,iface);
240 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_guid(rguidClass), pwzFileExtension, pwzScanFileName);
245 HRESULT WINAPI IDirectMusicLoader8Impl_CacheObject (LPDIRECTMUSICLOADER8 iface, IDirectMusicObject* pObject)
247 ICOM_THIS(IDirectMusicLoader8Impl,iface);
249 FIXME("(%p, %p): stub\n", This, pObject);
254 HRESULT WINAPI IDirectMusicLoader8Impl_ReleaseObject (LPDIRECTMUSICLOADER8 iface, IDirectMusicObject* pObject)
256 ICOM_THIS(IDirectMusicLoader8Impl,iface);
258 FIXME("(%p, %p): stub\n", This, pObject);
263 HRESULT WINAPI IDirectMusicLoader8Impl_ClearCache (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass)
265 ICOM_THIS(IDirectMusicLoader8Impl,iface);
267 FIXME("(%p, %s): stub\n", This, debugstr_guid(rguidClass));
272 HRESULT WINAPI IDirectMusicLoader8Impl_EnableCache (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, BOOL fEnable)
274 ICOM_THIS(IDirectMusicLoader8Impl,iface);
276 FIXME("(%p, %s, %d): stub\n", This, debugstr_guid(rguidClass), fEnable);
281 HRESULT WINAPI IDirectMusicLoader8Impl_EnumObject (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass, DWORD dwIndex, LPDMUS_OBJECTDESC pDesc)
283 ICOM_THIS(IDirectMusicLoader8Impl,iface);
285 FIXME("(%p, %s, %ld, %p): stub\n", This, debugstr_guid(rguidClass), dwIndex, pDesc);
290 /* IDirectMusicLoader8 Interface part follow: */
291 void WINAPI IDirectMusicLoader8Impl_CollectGarbage (LPDIRECTMUSICLOADER8 iface)
293 ICOM_THIS(IDirectMusicLoader8Impl,iface);
295 FIXME("(%p): stub\n", This);
298 HRESULT WINAPI IDirectMusicLoader8Impl_ReleaseObjectByUnknown (LPDIRECTMUSICLOADER8 iface, IUnknown* pObject)
300 ICOM_THIS(IDirectMusicLoader8Impl,iface);
302 FIXME("(%p, %p): stub\n", This, pObject);
307 HRESULT WINAPI IDirectMusicLoader8Impl_LoadObjectFromFile (LPDIRECTMUSICLOADER8 iface,
308 REFGUID rguidClassID,
309 REFIID iidInterfaceID,
313 ICOM_THIS(IDirectMusicLoader8Impl,iface);
314 DMUS_OBJECTDESC ObjDesc;
316 TRACE("(%p, %s, %s, %s, %p): wrapping to IDirectMusicLoader8Impl_GetObject\n", This, debugstr_guid(rguidClassID), debugstr_guid(iidInterfaceID), debugstr_w(pwzFilePath), ppObject);
318 ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
319 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 */
320 ObjDesc.guidClass = *rguidClassID;
321 strncpyW (ObjDesc.wszFileName, pwzFilePath, MAX_PATH);
323 return IDirectMusicLoader8Impl_GetObject (iface, &ObjDesc, iidInterfaceID, ppObject);
326 ICOM_VTABLE(IDirectMusicLoader8) DirectMusicLoader8_Vtbl =
328 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
329 IDirectMusicLoader8Impl_QueryInterface,
330 IDirectMusicLoader8Impl_AddRef,
331 IDirectMusicLoader8Impl_Release,
332 IDirectMusicLoader8Impl_GetObject,
333 IDirectMusicLoader8Impl_SetObject,
334 IDirectMusicLoader8Impl_SetSearchDirectory,
335 IDirectMusicLoader8Impl_ScanDirectory,
336 IDirectMusicLoader8Impl_CacheObject,
337 IDirectMusicLoader8Impl_ReleaseObject,
338 IDirectMusicLoader8Impl_ClearCache,
339 IDirectMusicLoader8Impl_EnableCache,
340 IDirectMusicLoader8Impl_EnumObject,
341 IDirectMusicLoader8Impl_CollectGarbage,
342 IDirectMusicLoader8Impl_ReleaseObjectByUnknown,
343 IDirectMusicLoader8Impl_LoadObjectFromFile
346 /* for ClassFactory */
347 HRESULT WINAPI DMUSIC_CreateDirectMusicLoader (LPCGUID lpcGUID, LPDIRECTMUSICLOADER8 *ppDMLoad, LPUNKNOWN pUnkOuter)
349 IDirectMusicLoader8Impl *dmloader;
351 TRACE("(%p,%p,%p)\n",lpcGUID, ppDMLoad, pUnkOuter);
352 if (IsEqualIID (lpcGUID, &IID_IDirectMusicLoader) ||
353 IsEqualIID (lpcGUID, &IID_IDirectMusicLoader8)) {
354 dmloader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoader8Impl));
355 if (NULL == dmloader) {
356 *ppDMLoad = (LPDIRECTMUSICLOADER8)NULL;
357 return E_OUTOFMEMORY;
359 dmloader->lpVtbl = &DirectMusicLoader8_Vtbl;
361 list_init (&dmloader->CacheList);
362 *ppDMLoad = (LPDIRECTMUSICLOADER8)dmloader;
366 WARN("No interface found\n");
367 return E_NOINTERFACE;
370 /* help function for IDirectMusicLoader8Impl_GetObject */
371 HRESULT WINAPI DMUSIC_GetDefaultGMPath (WCHAR wszPath[MAX_PATH])
374 DWORD returnType, sizeOfReturnBuffer = MAX_PATH;
375 char szPath[MAX_PATH];
377 if ((RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectMusic" , 0, KEY_READ, &hkDM) != ERROR_SUCCESS) ||
378 (RegQueryValueExA (hkDM, "GMFilePath", NULL, &returnType, szPath, &sizeOfReturnBuffer) != ERROR_SUCCESS)) {
379 WARN(": registry entry missing\n" );
382 /* FIXME: Check return types to ensure we're interpreting data right */
383 MultiByteToWideChar (CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);