1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1998 Patrik Stridvall
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
41 /**********************************************************************/
43 HANDLE MSACM_hHeap = NULL;
44 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
45 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
48 /***********************************************************************
51 static void MSACM_DumpCache(PWINE_ACMDRIVERID padid)
55 TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
56 padid->cFilterTags, padid->cFormatTags, padid->fdwSupport);
57 for (i = 0; i < padid->cache->cFormatTags; i++) {
58 TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
59 padid->aFormatTag[i].dwFormatTag, padid->aFormatTag[i].cbwfx);
64 /***********************************************************************
65 * MSACM_FindFormatTagInCache [internal]
67 * Returns TRUE is the format tag fmtTag is present in the cache.
68 * If so, idx is set to its index.
70 BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID* padid, DWORD fmtTag, LPDWORD idx)
74 for (i = 0; i < padid->cFormatTags; i++) {
75 if (padid->aFormatTag[i].dwFormatTag == fmtTag) {
83 /***********************************************************************
86 static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid)
90 ACMDRIVERDETAILSW add;
91 ACMFORMATTAGDETAILSW aftd;
93 if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0)
96 padid->aFormatTag = NULL;
97 add.cbStruct = sizeof(add);
98 if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add, 0))
101 if (add.cFormatTags > 0) {
102 padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY,
103 add.cFormatTags * sizeof(padid->aFormatTag[0]));
104 if (!padid->aFormatTag) goto errCleanUp;
107 padid->cFormatTags = add.cFormatTags;
108 padid->cFilterTags = add.cFilterTags;
109 padid->fdwSupport = add.fdwSupport;
111 aftd.cbStruct = sizeof(aftd);
113 for (ntag = 0; ntag < add.cFormatTags; ntag++) {
114 aftd.dwFormatTagIndex = ntag;
115 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&aftd, ACM_FORMATTAGDETAILSF_INDEX)) {
116 TRACE("IIOs (%s)\n", debugstr_w(padid->pszDriverAlias));
119 padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag;
120 padid->aFormatTag[ntag].cbwfx = aftd.cbFormatSize;
123 acmDriverClose(had, 0);
128 if (had) acmDriverClose(had, 0);
129 HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
130 padid->aFormatTag = NULL;
134 /***********************************************************************
135 * MSACM_GetRegistryKey
137 static LPWSTR MSACM_GetRegistryKey(const WINE_ACMDRIVERID* padid)
139 static const WCHAR baseKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
140 'A','u','d','i','o','C','o','m','p','r','e','s','s','i','o','n','M','a','n','a','g','e','r','\\',
141 'D','r','i','v','e','r','C','a','c','h','e','\\','\0'};
145 if (!padid->pszDriverAlias) {
146 ERR("No alias needed for registry entry\n");
149 len = strlenW(baseKey);
150 ret = HeapAlloc(MSACM_hHeap, 0, (len + strlenW(padid->pszDriverAlias) + 1) * sizeof(WCHAR));
151 if (!ret) return NULL;
153 strcpyW(ret, baseKey);
154 strcpyW(ret + len, padid->pszDriverAlias);
155 CharLowerW(ret + len);
159 /***********************************************************************
162 static BOOL MSACM_ReadCache(PWINE_ACMDRIVERID padid)
164 LPWSTR key = MSACM_GetRegistryKey(padid);
168 if (!key) return FALSE;
170 padid->aFormatTag = NULL;
172 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, key, &hKey))
175 size = sizeof(padid->cFormatTags);
176 if (RegQueryValueExA(hKey, "cFormatTags", 0, &type, (void*)&padid->cFormatTags, &size))
178 size = sizeof(padid->cFilterTags);
179 if (RegQueryValueExA(hKey, "cFilterTags", 0, &type, (void*)&padid->cFilterTags, &size))
181 size = sizeof(padid->fdwSupport);
182 if (RegQueryValueExA(hKey, "fdwSupport", 0, &type, (void*)&padid->fdwSupport, &size))
185 if (padid->cFormatTags > 0) {
186 size = padid->cFormatTags * sizeof(padid->aFormatTag[0]);
187 padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, size);
188 if (!padid->aFormatTag) goto errCleanUp;
189 if (RegQueryValueExA(hKey, "aFormatTagCache", 0, &type, (void*)padid->aFormatTag, &size))
192 HeapFree(MSACM_hHeap, 0, key);
196 HeapFree(MSACM_hHeap, 0, key);
197 HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
198 padid->aFormatTag = NULL;
203 /***********************************************************************
206 static BOOL MSACM_WriteCache(PWINE_ACMDRIVERID padid)
208 LPWSTR key = MSACM_GetRegistryKey(padid);
211 if (!key) return FALSE;
213 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, key, &hKey))
216 if (RegSetValueExA(hKey, "cFormatTags", 0, REG_DWORD, (void*)&padid->cFormatTags, sizeof(DWORD)))
218 if (RegSetValueExA(hKey, "cFilterTags", 0, REG_DWORD, (void*)&padid->cFilterTags, sizeof(DWORD)))
220 if (RegSetValueExA(hKey, "fdwSupport", 0, REG_DWORD, (void*)&padid->fdwSupport, sizeof(DWORD)))
222 if (RegSetValueExA(hKey, "aFormatTagCache", 0, REG_BINARY,
223 (void*)padid->aFormatTag,
224 padid->cFormatTags * sizeof(padid->aFormatTag[0])))
226 HeapFree(MSACM_hHeap, 0, key);
230 HeapFree(MSACM_hHeap, 0, key);
234 /***********************************************************************
235 * MSACM_RegisterDriver()
237 PWINE_ACMDRIVERID MSACM_RegisterDriver(LPWSTR pszDriverAlias, LPWSTR pszFileName,
238 HINSTANCE hinstModule)
240 PWINE_ACMDRIVERID padid;
242 TRACE("(%s, %s, %p)\n",
243 debugstr_w(pszDriverAlias), debugstr_w(pszFileName), hinstModule);
245 padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
246 padid->obj.dwType = WINE_ACMOBJ_DRIVERID;
247 padid->obj.pACMDriverID = padid;
248 padid->pszDriverAlias = NULL;
251 padid->pszDriverAlias = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszDriverAlias)+1) * sizeof(WCHAR) );
252 strcpyW( padid->pszDriverAlias, pszDriverAlias );
254 padid->pszFileName = NULL;
257 padid->pszFileName = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszFileName)+1) * sizeof(WCHAR) );
258 strcpyW( padid->pszFileName, pszFileName );
260 padid->hInstModule = hinstModule;
262 padid->pACMDriverList = NULL;
263 padid->pNextACMDriverID = NULL;
264 padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
265 if (MSACM_pLastACMDriverID)
266 MSACM_pLastACMDriverID->pNextACMDriverID = padid;
267 MSACM_pLastACMDriverID = padid;
268 if (!MSACM_pFirstACMDriverID)
269 MSACM_pFirstACMDriverID = padid;
270 /* disable the driver if we cannot load the cache */
271 if (!MSACM_ReadCache(padid) && !MSACM_FillCache(padid)) {
272 WARN("Couldn't load cache for ACM driver (%s)\n", debugstr_w(pszFileName));
273 MSACM_UnregisterDriver(padid);
279 /***********************************************************************
280 * MSACM_RegisterAllDrivers()
282 void MSACM_RegisterAllDrivers(void)
285 DWORD dwBufferLength;
286 static WCHAR msacm32[] = {'m','s','a','c','m','3','2','.','d','l','l','\0'};
287 static WCHAR msacmW[] = {'M','S','A','C','M','.'};
288 static WCHAR drv32[] = {'d','r','i','v','e','r','s','3','2','\0'};
289 static WCHAR sys[] = {'s','y','s','t','e','m','.','i','n','i','\0'};
292 * What if the user edits system.ini while the program is running?
293 * Does Windows handle that?
295 if (MSACM_pFirstACMDriverID)
298 /* FIXME: Does not work! How do I determine the section length? */
299 dwBufferLength = 1024;
300 /* EPP GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
302 pszBuffer = (LPWSTR) HeapAlloc(MSACM_hHeap, 0, dwBufferLength * sizeof(WCHAR));
303 if (GetPrivateProfileSectionW(drv32, pszBuffer, dwBufferLength, sys))
305 LPWSTR s = pszBuffer, s2;
309 CharUpperBuffW(s, 6);
310 if (memcmp(s, msacmW, 6 * sizeof(WCHAR)) == 0)
313 while (*s2 != '\0' && *s2 != '=') s2++;
317 MSACM_RegisterDriver(s, s2 + 1, 0);
321 s += strlenW(s) + 1; /* Either next char or \0 */
325 HeapFree(MSACM_hHeap, 0, pszBuffer);
327 MSACM_RegisterDriver(msacm32, msacm32, 0);
330 /***********************************************************************
331 * MSACM_UnregisterDriver()
333 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
335 PWINE_ACMDRIVERID pNextACMDriverID;
337 while (p->pACMDriverList)
338 acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
340 if (p->pszDriverAlias)
341 HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
343 HeapFree(MSACM_hHeap, 0, p->pszFileName);
344 HeapFree(MSACM_hHeap, 0, p->aFormatTag);
346 if (p == MSACM_pFirstACMDriverID)
347 MSACM_pFirstACMDriverID = p->pNextACMDriverID;
348 if (p == MSACM_pLastACMDriverID)
349 MSACM_pLastACMDriverID = p->pPrevACMDriverID;
351 if (p->pPrevACMDriverID)
352 p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
353 if (p->pNextACMDriverID)
354 p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
356 pNextACMDriverID = p->pNextACMDriverID;
358 HeapFree(MSACM_hHeap, 0, p);
360 return pNextACMDriverID;
363 /***********************************************************************
364 * MSACM_UnregisterAllDrivers()
366 void MSACM_UnregisterAllDrivers(void)
368 PWINE_ACMDRIVERID p = MSACM_pFirstACMDriverID;
372 p = MSACM_UnregisterDriver(p);
376 /***********************************************************************
379 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type)
381 PWINE_ACMOBJ pao = (PWINE_ACMOBJ)hObj;
383 if (pao == NULL || IsBadReadPtr(pao, sizeof(WINE_ACMOBJ)) ||
384 ((type != WINE_ACMOBJ_DONTCARE) && (type != pao->dwType)))
389 /***********************************************************************
390 * MSACM_GetDriverID()
392 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
394 return (PWINE_ACMDRIVERID)MSACM_GetObj((HACMOBJ)hDriverID, WINE_ACMOBJ_DRIVERID);
397 /***********************************************************************
400 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
402 return (PWINE_ACMDRIVER)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_DRIVER);
405 /***********************************************************************
408 MMRESULT MSACM_Message(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
410 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
412 return pad ? SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2) : MMSYSERR_INVALHANDLE;