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
;
76 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
80 TRACE("(%p, %p, %s, %p)\n", This
, pDesc
, debugstr_guid(riid
), ppv
);
81 TRACE(": looking up cache");
82 /* first, check if requested object is already in cache (check by name and GUID) */
83 for (i
= 0; i
< This
->dwCacheSize
; i
++) {
84 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
) {
85 if (IsEqualGUID (&pDesc
->guidObject
, &This
->pCache
[i
].guidObject
)) {
86 TRACE(": object already exist in cache (found by GUID)\n");
87 if (This
->pCache
[i
].pObject
) {
88 return IDirectMusicObject_QueryInterface (This
->pCache
[i
].pObject
, riid
, ppv
);
91 } else if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
92 if (This
->pCache
[i
].pwzFileName
&& !strncmpW(pDesc
->wszFileName
, This
->pCache
[i
].pwzFileName
, MAX_PATH
)) {
93 TRACE(": object already exist in cache (found by file name)\n");
94 if (This
->pCache
[i
].pObject
) {
95 return IDirectMusicObject_QueryInterface (This
->pCache
[i
].pObject
, riid
, ppv
);
101 /* object doesn't exist in cache... guess we'll have to load it */
102 TRACE(": object does not exist in cache\n");
103 result
= CoCreateInstance (&pDesc
->guidClass
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*)&pObject
);
104 if (FAILED(result
)) return result
;
105 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
) {
106 /* load object from file */
107 WCHAR wzFileName
[MAX_PATH
];
108 ILoaderStream
* pStream
;
109 IPersistStream
*pPersistStream
= NULL
;
110 /* if it's full path, don't add search directory path, otherwise do */
111 if (pDesc
->dwValidData
& DMUS_OBJ_FULLPATH
) {
112 lstrcpyW( wzFileName
, pDesc
->wszFileName
);
115 lstrcpyW( wzFileName
, This
->wzSearchPath
);
116 p
= wzFileName
+ lstrlenW(wzFileName
);
117 if (p
> wzFileName
&& p
[-1] != '\\') *p
++ = '\\';
118 lstrcpyW( p
, pDesc
->wszFileName
);
120 TRACE(": loading from file (%s)\n", debugstr_w(wzFileName
));
122 result
= DMUSIC_CreateLoaderStream ((LPSTREAM
*)&pStream
);
123 if (FAILED(result
)) return result
;
125 result
= ILoaderStream_Attach (pStream
, wzFileName
, (LPDIRECTMUSICLOADER
)iface
);
126 if (FAILED(result
)) return result
;
128 result
= IDirectMusicObject_QueryInterface (pObject
, &IID_IPersistStream
, (LPVOID
*)&pPersistStream
);
129 if (FAILED(result
)) return result
;
131 result
= IPersistStream_Load (pPersistStream
, (LPSTREAM
)pStream
);
132 if (FAILED(result
)) return result
;
134 ILoaderStream_IStream_Release ((LPSTREAM
)pStream
);
135 IPersistStream_Release (pPersistStream
);
136 } else if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
137 /* load object from stream */
138 IStream
* pClonedStream
= NULL
;
139 IPersistStream
* pPersistStream
= NULL
;
141 TRACE(": loading from stream\n");
142 result
= IDirectMusicObject_QueryInterface (pObject
, &IID_IPersistStream
, (LPVOID
*)&pPersistStream
);
143 if (FAILED(result
)) {
144 TRACE("couln\'t get IPersistStream\n");
148 result
= IStream_Clone (pDesc
->pStream
, &pClonedStream
);
149 if (FAILED(result
)) {
150 TRACE("failed to clone\n");
154 result
= IPersistStream_Load (pPersistStream
, pClonedStream
);
155 if (FAILED(result
)) {
156 TRACE("failed to load\n");
160 IPersistStream_Release (pPersistStream
);
161 IStream_Release (pClonedStream
);
162 } else if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
) {
163 /* load object by GUID */
164 TRACE(": loading by GUID (only default DLS supported)\n");
165 if (IsEqualGUID (&pDesc
->guidObject
, &GUID_DefaultGMCollection
)) {
166 /* great idea: let's just change dwValid and wszFileName fields and then call ourselves again :D */
167 pDesc
->dwValidData
= DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
;
168 if (FAILED(DMUSIC_GetDefaultGMPath (pDesc
->wszFileName
)))
170 return IDirectMusicLoader8Impl_GetObject (iface
, pDesc
, riid
, ppv
);
175 /* nowhere to load from */
176 FIXME(": unknown/unsupported way of loading\n");
180 memset((LPVOID
)&desc
, 0, sizeof(desc
));
181 desc
.dwSize
= sizeof (DMUS_OBJECTDESC
);
182 IDirectMusicObject_GetDescriptor (pObject
, &desc
);
184 /* tests with native dlls show that descriptor, which is received by GetDescriptor doesn't contain filepath
185 therefore we must copy it from input description */
186 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
|| desc
.dwValidData
& DMUS_OBJ_OBJECT
) {
187 DMUS_PRIVATE_CACHE_ENTRY CacheEntry
;
188 This
->dwCacheSize
++; /* increase size of cache for one entry */
189 This
->pCache
= HeapReAlloc (GetProcessHeap (), 0, This
->pCache
, sizeof(DMUS_PRIVATE_CACHE_ENTRY
) * This
->dwCacheSize
);
190 if (desc
.dwValidData
& DMUS_OBJ_OBJECT
)
191 CacheEntry
.guidObject
= desc
.guidObject
;
192 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
193 strncpyW (CacheEntry
.pwzFileName
, pDesc
->wszFileName
, MAX_PATH
);
194 CacheEntry
.pObject
= pObject
;
195 IDirectMusicObject_AddRef (pObject
); /* MSDN says that we should */
196 This
->pCache
[This
->dwCacheSize
- 1] = CacheEntry
; /* fill in one backward, as list is zero based */
197 TRACE(": filled in cache entry\n");
200 TRACE(": nr. of entries = %ld\n", This
->dwCacheSize
);
201 for (i
= 0; i
< This
->dwCacheSize
; i
++) {
202 TRACE(": cache entry [%i]: GUID = %s, file name = %s, object = %p\n", i
, debugstr_guid(&This
->pCache
[i
].guidObject
), debugstr_w(This
->pCache
[i
].pwzFileName
), This
->pCache
[i
].pObject
);
205 return IDirectMusicObject_QueryInterface (pObject
, riid
, ppv
);
208 HRESULT WINAPI
IDirectMusicLoader8Impl_SetObject (LPDIRECTMUSICLOADER8 iface
, LPDMUS_OBJECTDESC pDesc
)
210 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
212 FIXME("(%p, %p): stub\n", This
, pDesc
);
217 HRESULT WINAPI
IDirectMusicLoader8Impl_SetSearchDirectory (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, WCHAR
* pwzPath
, BOOL fClear
)
219 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
221 TRACE("(%p, %s, %p, %d)\n", This
, debugstr_guid(rguidClass
), pwzPath
, fClear
);
222 if (0 == strncmpW(This
->wzSearchPath
, pwzPath
, MAX_PATH
)) {
225 strncpyW(This
->wzSearchPath
, pwzPath
, MAX_PATH
);
230 HRESULT WINAPI
IDirectMusicLoader8Impl_ScanDirectory (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, WCHAR
* pwzFileExtension
, WCHAR
* pwzScanFileName
)
232 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
234 FIXME("(%p, %s, %p, %p): stub\n", This
, debugstr_guid(rguidClass
), pwzFileExtension
, pwzScanFileName
);
239 HRESULT WINAPI
IDirectMusicLoader8Impl_CacheObject (LPDIRECTMUSICLOADER8 iface
, IDirectMusicObject
* pObject
)
241 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
243 FIXME("(%p, %p): stub\n", This
, pObject
);
248 HRESULT WINAPI
IDirectMusicLoader8Impl_ReleaseObject (LPDIRECTMUSICLOADER8 iface
, IDirectMusicObject
* pObject
)
250 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
252 FIXME("(%p, %p): stub\n", This
, pObject
);
257 HRESULT WINAPI
IDirectMusicLoader8Impl_ClearCache (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
)
259 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
261 FIXME("(%p, %s): stub\n", This
, debugstr_guid(rguidClass
));
266 HRESULT WINAPI
IDirectMusicLoader8Impl_EnableCache (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, BOOL fEnable
)
268 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
270 FIXME("(%p, %s, %d): stub\n", This
, debugstr_guid(rguidClass
), fEnable
);
275 HRESULT WINAPI
IDirectMusicLoader8Impl_EnumObject (LPDIRECTMUSICLOADER8 iface
, REFGUID rguidClass
, DWORD dwIndex
, LPDMUS_OBJECTDESC pDesc
)
277 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
279 FIXME("(%p, %s, %ld, %p): stub\n", This
, debugstr_guid(rguidClass
), dwIndex
, pDesc
);
284 /* IDirectMusicLoader8 Interface part follow: */
285 void WINAPI
IDirectMusicLoader8Impl_CollectGarbage (LPDIRECTMUSICLOADER8 iface
)
287 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
289 FIXME("(%p): stub\n", This
);
292 HRESULT WINAPI
IDirectMusicLoader8Impl_ReleaseObjectByUnknown (LPDIRECTMUSICLOADER8 iface
, IUnknown
* pObject
)
294 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
296 FIXME("(%p, %p): stub\n", This
, pObject
);
301 HRESULT WINAPI
IDirectMusicLoader8Impl_LoadObjectFromFile (LPDIRECTMUSICLOADER8 iface
,
302 REFGUID rguidClassID
,
303 REFIID iidInterfaceID
,
307 ICOM_THIS(IDirectMusicLoader8Impl
,iface
);
308 DMUS_OBJECTDESC ObjDesc
;
310 TRACE("(%p, %s, %s, %s, %p): wrapping to IDirectMusicLoader8Impl_GetObject\n", This
, debugstr_guid(rguidClassID
), debugstr_guid(iidInterfaceID
), debugstr_w(pwzFilePath
), ppObject
);
312 ObjDesc
.dwSize
= sizeof(DMUS_OBJECTDESC
);
313 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 */
314 ObjDesc
.guidClass
= *rguidClassID
;
315 strncpyW (ObjDesc
.wszFileName
, pwzFilePath
, MAX_PATH
);
317 return IDirectMusicLoader8Impl_GetObject (iface
, &ObjDesc
, iidInterfaceID
, ppObject
);
320 ICOM_VTABLE(IDirectMusicLoader8
) DirectMusicLoader8_Vtbl
=
322 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
323 IDirectMusicLoader8Impl_QueryInterface
,
324 IDirectMusicLoader8Impl_AddRef
,
325 IDirectMusicLoader8Impl_Release
,
326 IDirectMusicLoader8Impl_GetObject
,
327 IDirectMusicLoader8Impl_SetObject
,
328 IDirectMusicLoader8Impl_SetSearchDirectory
,
329 IDirectMusicLoader8Impl_ScanDirectory
,
330 IDirectMusicLoader8Impl_CacheObject
,
331 IDirectMusicLoader8Impl_ReleaseObject
,
332 IDirectMusicLoader8Impl_ClearCache
,
333 IDirectMusicLoader8Impl_EnableCache
,
334 IDirectMusicLoader8Impl_EnumObject
,
335 IDirectMusicLoader8Impl_CollectGarbage
,
336 IDirectMusicLoader8Impl_ReleaseObjectByUnknown
,
337 IDirectMusicLoader8Impl_LoadObjectFromFile
340 /* for ClassFactory */
341 HRESULT WINAPI
DMUSIC_CreateDirectMusicLoader (LPCGUID lpcGUID
, LPDIRECTMUSICLOADER8
*ppDMLoad
, LPUNKNOWN pUnkOuter
)
343 IDirectMusicLoader8Impl
*dmloader
;
345 TRACE("(%p,%p,%p)\n",lpcGUID
, ppDMLoad
, pUnkOuter
);
346 if (IsEqualIID (lpcGUID
, &IID_IDirectMusicLoader
) ||
347 IsEqualIID (lpcGUID
, &IID_IDirectMusicLoader8
)) {
348 dmloader
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicLoader8Impl
));
349 if (NULL
== dmloader
) {
350 *ppDMLoad
= (LPDIRECTMUSICLOADER8
)NULL
;
351 return E_OUTOFMEMORY
;
353 dmloader
->lpVtbl
= &DirectMusicLoader8_Vtbl
;
355 *ppDMLoad
= (LPDIRECTMUSICLOADER8
)dmloader
;
359 WARN("No interface found\n");
360 return E_NOINTERFACE
;
363 /* help function for IDirectMusicLoader8Impl_GetObject */
364 HRESULT WINAPI
DMUSIC_GetDefaultGMPath (WCHAR wszPath
[MAX_PATH
])
367 DWORD returnType
, sizeOfReturnBuffer
= MAX_PATH
;
368 char szPath
[MAX_PATH
];
370 if ((RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic" , 0, KEY_READ
, &hkDM
) != ERROR_SUCCESS
) ||
371 (RegQueryValueExA (hkDM
, "GMFilePath", NULL
, &returnType
, szPath
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
)) {
372 WARN(": registry entry missing\n" );
375 /* FIXME: Check return types to ensure we're interpreting data right */
376 MultiByteToWideChar (CP_ACP
, 0, szPath
, -1, wszPath
, MAX_PATH
);