Use native msi until our own implementation works decently.
[wine/wine-kai.git] / dlls / dmloader / loader.c
blob01f5a12b3c099714cb1effcee9347a5bddc618b9
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.
20 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "wingdi.h"
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
28 #include "winreg.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);
45 *ppobj = This;
46 return S_OK;
49 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
50 return E_NOINTERFACE;
53 ULONG WINAPI IDirectMusicLoader8Impl_AddRef (LPDIRECTMUSICLOADER8 iface)
55 ICOM_THIS(IDirectMusicLoader8Impl,iface);
56 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
57 return ++(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);
65 if (ref == 0) {
66 HeapFree(GetProcessHeap(), 0, This);
68 return ref;
71 /* IDirectMusicLoader8 IDirectMusicLoader part: */
72 HRESULT WINAPI IDirectMusicLoader8Impl_GetObject (LPDIRECTMUSICLOADER8 iface, LPDMUS_OBJECTDESC pDesc, REFIID riid, LPVOID* ppv)
74 IDirectMusicObject* pObject;
75 DMUS_OBJECTDESC desc;
76 ICOM_THIS(IDirectMusicLoader8Impl,iface);
77 int i;
78 HRESULT result;
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 );
113 } else {
114 WCHAR *p;
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");
145 return result;
148 result = IStream_Clone (pDesc->pStream, &pClonedStream);
149 if (FAILED(result)) {
150 TRACE("failed to clone\n");
151 return result;
154 result = IPersistStream_Load (pPersistStream, pClonedStream);
155 if (FAILED(result)) {
156 TRACE("failed to load\n");
157 return result;
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)))
169 return E_FAIL;
170 return IDirectMusicLoader8Impl_GetObject (iface, pDesc, riid, ppv);
171 } else {
172 return E_FAIL;
174 } else {
175 /* nowhere to load from */
176 FIXME(": unknown/unsupported way of loading\n");
177 return E_FAIL;
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);
214 return S_OK;
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)) {
223 return S_FALSE;
225 strncpyW(This->wzSearchPath, pwzPath, MAX_PATH);
227 return S_OK;
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);
236 return S_OK;
239 HRESULT WINAPI IDirectMusicLoader8Impl_CacheObject (LPDIRECTMUSICLOADER8 iface, IDirectMusicObject* pObject)
241 ICOM_THIS(IDirectMusicLoader8Impl,iface);
243 FIXME("(%p, %p): stub\n", This, pObject);
245 return S_OK;
248 HRESULT WINAPI IDirectMusicLoader8Impl_ReleaseObject (LPDIRECTMUSICLOADER8 iface, IDirectMusicObject* pObject)
250 ICOM_THIS(IDirectMusicLoader8Impl,iface);
252 FIXME("(%p, %p): stub\n", This, pObject);
254 return S_OK;
257 HRESULT WINAPI IDirectMusicLoader8Impl_ClearCache (LPDIRECTMUSICLOADER8 iface, REFGUID rguidClass)
259 ICOM_THIS(IDirectMusicLoader8Impl,iface);
261 FIXME("(%p, %s): stub\n", This, debugstr_guid(rguidClass));
263 return S_OK;
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);
272 return S_OK;
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);
281 return S_OK;
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);
298 return S_OK;
301 HRESULT WINAPI IDirectMusicLoader8Impl_LoadObjectFromFile (LPDIRECTMUSICLOADER8 iface,
302 REFGUID rguidClassID,
303 REFIID iidInterfaceID,
304 WCHAR* pwzFilePath,
305 void** ppObject)
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;
354 dmloader->ref = 1;
355 *ppDMLoad = (LPDIRECTMUSICLOADER8)dmloader;
356 return S_OK;
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])
366 HKEY hkDM;
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" );
373 return E_FAIL;
375 /* FIXME: Check return types to ensure we're interpreting data right */
376 MultiByteToWideChar (CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);
378 return S_OK;