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"
38 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
40 /**********************************************************************/
42 HANDLE MSACM_hHeap
= (HANDLE
) NULL
;
43 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID
= NULL
;
44 PWINE_ACMDRIVERID MSACM_pLastACMDriverID
= NULL
;
47 /***********************************************************************
50 static void MSACM_DumpCache(PWINE_ACMDRIVERID padid
)
54 TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
55 padid
->cFilterTags
, padid
->cFormatTags
, padid
->fdwSupport
);
56 for (i
= 0; i
< padid
->cache
->cFormatTags
; i
++) {
57 TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
58 padid
->aFormatTag
[i
].dwFormatTag
, padid
->aFormatTag
[i
].cbwfx
);
63 /***********************************************************************
64 * MSACM_FindFormatTagInCache [internal]
66 * Returns TRUE is the format tag fmtTag is present in the cache.
67 * If so, idx is set to its index.
69 BOOL
MSACM_FindFormatTagInCache(WINE_ACMDRIVERID
* padid
, DWORD fmtTag
, LPDWORD idx
)
73 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
74 if (padid
->aFormatTag
[i
].dwFormatTag
== fmtTag
) {
82 /***********************************************************************
85 static BOOL
MSACM_FillCache(PWINE_ACMDRIVERID padid
)
89 ACMDRIVERDETAILSW add
;
90 ACMFORMATTAGDETAILSW aftd
;
92 if (acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != 0)
95 padid
->aFormatTag
= NULL
;
96 add
.cbStruct
= sizeof(add
);
97 if (MSACM_Message(had
, ACMDM_DRIVER_DETAILS
, (LPARAM
)&add
, 0))
100 if (add
.cFormatTags
> 0) {
101 padid
->aFormatTag
= HeapAlloc(MSACM_hHeap
, HEAP_ZERO_MEMORY
,
102 add
.cFormatTags
* sizeof(padid
->aFormatTag
[0]));
103 if (!padid
->aFormatTag
) goto errCleanUp
;
106 padid
->cFormatTags
= add
.cFormatTags
;
107 padid
->cFilterTags
= add
.cFilterTags
;
108 padid
->fdwSupport
= add
.fdwSupport
;
110 aftd
.cbStruct
= sizeof(aftd
);
112 for (ntag
= 0; ntag
< add
.cFormatTags
; ntag
++) {
113 aftd
.dwFormatTagIndex
= ntag
;
114 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)&aftd
, ACM_FORMATTAGDETAILSF_INDEX
)) {
115 TRACE("IIOs (%s)\n", padid
->pszDriverAlias
);
118 padid
->aFormatTag
[ntag
].dwFormatTag
= aftd
.dwFormatTag
;
119 padid
->aFormatTag
[ntag
].cbwfx
= aftd
.cbFormatSize
;
122 acmDriverClose(had
, 0);
127 if (had
) acmDriverClose(had
, 0);
128 HeapFree(MSACM_hHeap
, 0, padid
->aFormatTag
);
129 padid
->aFormatTag
= NULL
;
133 /***********************************************************************
134 * MSACM_GetRegistryKey
136 static LPSTR
MSACM_GetRegistryKey(const WINE_ACMDRIVERID
* padid
)
138 static const char* baseKey
= "Software\\Microsoft\\AudioCompressionManager\\DriverCache\\";
142 if (!padid
->pszDriverAlias
) {
143 ERR("No alias needed for registry entry\n");
146 len
= strlen(baseKey
);
147 ret
= HeapAlloc(MSACM_hHeap
, 0, len
+ strlen(padid
->pszDriverAlias
) + 1);
148 if (!ret
) return NULL
;
150 strcpy(ret
, baseKey
);
151 strcpy(ret
+ len
, padid
->pszDriverAlias
);
152 CharLowerA(ret
+ len
);
156 /***********************************************************************
159 static BOOL
MSACM_ReadCache(PWINE_ACMDRIVERID padid
)
161 LPSTR key
= MSACM_GetRegistryKey(padid
);
165 if (!key
) return FALSE
;
167 padid
->aFormatTag
= NULL
;
169 if (RegCreateKeyA(HKEY_LOCAL_MACHINE
, key
, &hKey
))
172 size
= sizeof(padid
->cFormatTags
);
173 if (RegQueryValueExA(hKey
, "cFormatTags", 0, &type
, (void*)&padid
->cFormatTags
, &size
))
175 size
= sizeof(padid
->cFilterTags
);
176 if (RegQueryValueExA(hKey
, "cFilterTags", 0, &type
, (void*)&padid
->cFilterTags
, &size
))
178 size
= sizeof(padid
->fdwSupport
);
179 if (RegQueryValueExA(hKey
, "fdwSupport", 0, &type
, (void*)&padid
->fdwSupport
, &size
))
182 if (padid
->cFormatTags
> 0) {
183 size
= padid
->cFormatTags
* sizeof(padid
->aFormatTag
[0]);
184 padid
->aFormatTag
= HeapAlloc(MSACM_hHeap
, HEAP_ZERO_MEMORY
, size
);
185 if (!padid
->aFormatTag
) goto errCleanUp
;
186 if (RegQueryValueExA(hKey
, "aFormatTagCache", 0, &type
, (void*)padid
->aFormatTag
, &size
))
189 HeapFree(MSACM_hHeap
, 0, key
);
193 HeapFree(MSACM_hHeap
, 0, key
);
194 HeapFree(MSACM_hHeap
, 0, padid
->aFormatTag
);
195 padid
->aFormatTag
= NULL
;
200 /***********************************************************************
203 static BOOL
MSACM_WriteCache(PWINE_ACMDRIVERID padid
)
205 LPSTR key
= MSACM_GetRegistryKey(padid
);
208 if (!key
) return FALSE
;
210 if (RegCreateKeyA(HKEY_LOCAL_MACHINE
, key
, &hKey
))
213 if (RegSetValueExA(hKey
, "cFormatTags", 0, REG_DWORD
, (void*)&padid
->cFormatTags
, sizeof(DWORD
)))
215 if (RegSetValueExA(hKey
, "cFilterTags", 0, REG_DWORD
, (void*)&padid
->cFilterTags
, sizeof(DWORD
)))
217 if (RegSetValueExA(hKey
, "fdwSupport", 0, REG_DWORD
, (void*)&padid
->fdwSupport
, sizeof(DWORD
)))
219 if (RegSetValueExA(hKey
, "aFormatTagCache", 0, REG_BINARY
,
220 (void*)padid
->aFormatTag
,
221 padid
->cFormatTags
* sizeof(padid
->aFormatTag
[0])))
223 HeapFree(MSACM_hHeap
, 0, key
);
227 HeapFree(MSACM_hHeap
, 0, key
);
231 /***********************************************************************
232 * MSACM_RegisterDriver()
234 PWINE_ACMDRIVERID
MSACM_RegisterDriver(LPSTR pszDriverAlias
, LPSTR pszFileName
,
235 HINSTANCE hinstModule
)
237 PWINE_ACMDRIVERID padid
;
239 TRACE("('%s', '%s', %p)\n", pszDriverAlias
, pszFileName
, hinstModule
);
241 padid
= (PWINE_ACMDRIVERID
) HeapAlloc(MSACM_hHeap
, 0, sizeof(WINE_ACMDRIVERID
));
242 padid
->obj
.dwType
= WINE_ACMOBJ_DRIVERID
;
243 padid
->obj
.pACMDriverID
= padid
;
244 padid
->pszDriverAlias
= NULL
;
247 padid
->pszDriverAlias
= HeapAlloc( MSACM_hHeap
, 0, strlen(pszDriverAlias
)+1 );
248 strcpy( padid
->pszDriverAlias
, pszDriverAlias
);
250 padid
->pszFileName
= NULL
;
253 padid
->pszFileName
= HeapAlloc( MSACM_hHeap
, 0, strlen(pszFileName
)+1 );
254 strcpy( padid
->pszFileName
, pszFileName
);
256 padid
->hInstModule
= hinstModule
;
258 padid
->pACMDriverList
= NULL
;
259 padid
->pNextACMDriverID
= NULL
;
260 padid
->pPrevACMDriverID
= MSACM_pLastACMDriverID
;
261 if (MSACM_pLastACMDriverID
)
262 MSACM_pLastACMDriverID
->pNextACMDriverID
= padid
;
263 MSACM_pLastACMDriverID
= padid
;
264 if (!MSACM_pFirstACMDriverID
)
265 MSACM_pFirstACMDriverID
= padid
;
266 /* disable the driver if we cannot load the cache */
267 if (!MSACM_ReadCache(padid
) && !MSACM_FillCache(padid
)) {
268 WARN("Couldn't load cache for ACM driver (%s)\n", pszFileName
);
269 MSACM_UnregisterDriver(padid
);
275 /***********************************************************************
276 * MSACM_RegisterAllDrivers()
278 void MSACM_RegisterAllDrivers(void)
281 DWORD dwBufferLength
;
284 * What if the user edits system.ini while the program is running?
285 * Does Windows handle that?
287 if (MSACM_pFirstACMDriverID
)
290 /* FIXME: Does not work! How do I determine the section length? */
291 dwBufferLength
= 1024;
292 /* EPP GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
294 pszBuffer
= (LPSTR
) HeapAlloc(MSACM_hHeap
, 0, dwBufferLength
);
295 if (GetPrivateProfileSectionA("drivers32", pszBuffer
, dwBufferLength
, "system.ini")) {
298 if (!strncasecmp("MSACM.", s
, 6)) {
300 while (*s2
!= '\0' && *s2
!= '=') s2
++;
303 MSACM_RegisterDriver(s
, s2
+ 1, 0);
307 s
+= strlen(s
) + 1; /* Either next char or \0 */
311 HeapFree(MSACM_hHeap
, 0, pszBuffer
);
313 MSACM_RegisterDriver("msacm32.dll", "msacm32.dll", 0);
316 /***********************************************************************
317 * MSACM_UnregisterDriver()
319 PWINE_ACMDRIVERID
MSACM_UnregisterDriver(PWINE_ACMDRIVERID p
)
321 PWINE_ACMDRIVERID pNextACMDriverID
;
323 while (p
->pACMDriverList
)
324 acmDriverClose((HACMDRIVER
) p
->pACMDriverList
, 0);
326 if (p
->pszDriverAlias
)
327 HeapFree(MSACM_hHeap
, 0, p
->pszDriverAlias
);
329 HeapFree(MSACM_hHeap
, 0, p
->pszFileName
);
330 HeapFree(MSACM_hHeap
, 0, p
->aFormatTag
);
332 if (p
== MSACM_pFirstACMDriverID
)
333 MSACM_pFirstACMDriverID
= p
->pNextACMDriverID
;
334 if (p
== MSACM_pLastACMDriverID
)
335 MSACM_pLastACMDriverID
= p
->pPrevACMDriverID
;
337 if (p
->pPrevACMDriverID
)
338 p
->pPrevACMDriverID
->pNextACMDriverID
= p
->pNextACMDriverID
;
339 if (p
->pNextACMDriverID
)
340 p
->pNextACMDriverID
->pPrevACMDriverID
= p
->pPrevACMDriverID
;
342 pNextACMDriverID
= p
->pNextACMDriverID
;
344 HeapFree(MSACM_hHeap
, 0, p
);
346 return pNextACMDriverID
;
349 /***********************************************************************
350 * MSACM_UnregisterAllDrivers()
352 void MSACM_UnregisterAllDrivers(void)
354 PWINE_ACMDRIVERID p
= MSACM_pFirstACMDriverID
;
358 p
= MSACM_UnregisterDriver(p
);
362 /***********************************************************************
365 PWINE_ACMOBJ
MSACM_GetObj(HACMOBJ hObj
, DWORD type
)
367 PWINE_ACMOBJ pao
= (PWINE_ACMOBJ
)hObj
;
369 if (pao
== NULL
|| IsBadReadPtr(pao
, sizeof(WINE_ACMOBJ
)) ||
370 ((type
!= WINE_ACMOBJ_DONTCARE
) && (type
!= pao
->dwType
)))
375 /***********************************************************************
376 * MSACM_GetDriverID()
378 PWINE_ACMDRIVERID
MSACM_GetDriverID(HACMDRIVERID hDriverID
)
380 return (PWINE_ACMDRIVERID
)MSACM_GetObj((HACMOBJ
)hDriverID
, WINE_ACMOBJ_DRIVERID
);
383 /***********************************************************************
386 PWINE_ACMDRIVER
MSACM_GetDriver(HACMDRIVER hDriver
)
388 return (PWINE_ACMDRIVER
)MSACM_GetObj((HACMOBJ
)hDriver
, WINE_ACMOBJ_DRIVER
);
391 /***********************************************************************
394 MMRESULT
MSACM_Message(HACMDRIVER had
, UINT uMsg
, LPARAM lParam1
, LPARAM lParam2
)
396 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
398 return pad
? SendDriverMessage(pad
->hDrvr
, uMsg
, lParam1
, lParam2
) : MMSYSERR_INVALHANDLE
;