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
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
43 /**********************************************************************/
45 HANDLE MSACM_hHeap
= NULL
;
46 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID
= NULL
;
47 PWINE_ACMDRIVERID MSACM_pLastACMDriverID
= NULL
;
50 /***********************************************************************
53 static void MSACM_DumpCache(PWINE_ACMDRIVERID padid
)
57 TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
58 padid
->cFilterTags
, padid
->cFormatTags
, padid
->fdwSupport
);
59 for (i
= 0; i
< padid
->cache
->cFormatTags
; i
++) {
60 TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
61 padid
->aFormatTag
[i
].dwFormatTag
, padid
->aFormatTag
[i
].cbwfx
);
66 /***********************************************************************
67 * MSACM_FindFormatTagInCache [internal]
69 * Returns TRUE is the format tag fmtTag is present in the cache.
70 * If so, idx is set to its index.
72 BOOL
MSACM_FindFormatTagInCache(WINE_ACMDRIVERID
* padid
, DWORD fmtTag
, LPDWORD idx
)
76 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
77 if (padid
->aFormatTag
[i
].dwFormatTag
== fmtTag
) {
85 /***********************************************************************
88 static BOOL
MSACM_FillCache(PWINE_ACMDRIVERID padid
)
92 ACMDRIVERDETAILSW add
;
93 ACMFORMATTAGDETAILSW aftd
;
95 if (acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != 0)
98 padid
->aFormatTag
= NULL
;
99 add
.cbStruct
= sizeof(add
);
100 if (MSACM_Message(had
, ACMDM_DRIVER_DETAILS
, (LPARAM
)&add
, 0))
103 if (add
.cFormatTags
> 0) {
104 padid
->aFormatTag
= HeapAlloc(MSACM_hHeap
, HEAP_ZERO_MEMORY
,
105 add
.cFormatTags
* sizeof(padid
->aFormatTag
[0]));
106 if (!padid
->aFormatTag
) goto errCleanUp
;
109 padid
->cFormatTags
= add
.cFormatTags
;
110 padid
->cFilterTags
= add
.cFilterTags
;
111 padid
->fdwSupport
= add
.fdwSupport
;
113 aftd
.cbStruct
= sizeof(aftd
);
115 for (ntag
= 0; ntag
< add
.cFormatTags
; ntag
++) {
116 aftd
.dwFormatTagIndex
= ntag
;
117 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)&aftd
, ACM_FORMATTAGDETAILSF_INDEX
)) {
118 TRACE("IIOs (%s)\n", debugstr_w(padid
->pszDriverAlias
));
121 padid
->aFormatTag
[ntag
].dwFormatTag
= aftd
.dwFormatTag
;
122 padid
->aFormatTag
[ntag
].cbwfx
= aftd
.cbFormatSize
;
125 acmDriverClose(had
, 0);
130 if (had
) acmDriverClose(had
, 0);
131 HeapFree(MSACM_hHeap
, 0, padid
->aFormatTag
);
132 padid
->aFormatTag
= NULL
;
136 /***********************************************************************
137 * MSACM_GetRegistryKey
139 static LPWSTR
MSACM_GetRegistryKey(const WINE_ACMDRIVERID
* padid
)
141 static const WCHAR baseKey
[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
142 'A','u','d','i','o','C','o','m','p','r','e','s','s','i','o','n','M','a','n','a','g','e','r','\\',
143 'D','r','i','v','e','r','C','a','c','h','e','\\','\0'};
147 if (!padid
->pszDriverAlias
) {
148 ERR("No alias needed for registry entry\n");
151 len
= strlenW(baseKey
);
152 ret
= HeapAlloc(MSACM_hHeap
, 0, (len
+ strlenW(padid
->pszDriverAlias
) + 1) * sizeof(WCHAR
));
153 if (!ret
) return NULL
;
155 strcpyW(ret
, baseKey
);
156 strcpyW(ret
+ len
, padid
->pszDriverAlias
);
157 CharLowerW(ret
+ len
);
161 /***********************************************************************
164 static BOOL
MSACM_ReadCache(PWINE_ACMDRIVERID padid
)
166 LPWSTR key
= MSACM_GetRegistryKey(padid
);
170 if (!key
) return FALSE
;
172 padid
->aFormatTag
= NULL
;
174 if (RegCreateKeyW(HKEY_LOCAL_MACHINE
, key
, &hKey
))
177 size
= sizeof(padid
->cFormatTags
);
178 if (RegQueryValueExA(hKey
, "cFormatTags", 0, &type
, (void*)&padid
->cFormatTags
, &size
))
180 size
= sizeof(padid
->cFilterTags
);
181 if (RegQueryValueExA(hKey
, "cFilterTags", 0, &type
, (void*)&padid
->cFilterTags
, &size
))
183 size
= sizeof(padid
->fdwSupport
);
184 if (RegQueryValueExA(hKey
, "fdwSupport", 0, &type
, (void*)&padid
->fdwSupport
, &size
))
187 if (padid
->cFormatTags
> 0) {
188 size
= padid
->cFormatTags
* sizeof(padid
->aFormatTag
[0]);
189 padid
->aFormatTag
= HeapAlloc(MSACM_hHeap
, HEAP_ZERO_MEMORY
, size
);
190 if (!padid
->aFormatTag
) goto errCleanUp
;
191 if (RegQueryValueExA(hKey
, "aFormatTagCache", 0, &type
, (void*)padid
->aFormatTag
, &size
))
194 HeapFree(MSACM_hHeap
, 0, key
);
198 HeapFree(MSACM_hHeap
, 0, key
);
199 HeapFree(MSACM_hHeap
, 0, padid
->aFormatTag
);
200 padid
->aFormatTag
= NULL
;
205 /***********************************************************************
208 static BOOL
MSACM_WriteCache(PWINE_ACMDRIVERID padid
)
210 LPWSTR key
= MSACM_GetRegistryKey(padid
);
213 if (!key
) return FALSE
;
215 if (RegCreateKeyW(HKEY_LOCAL_MACHINE
, key
, &hKey
))
218 if (RegSetValueExA(hKey
, "cFormatTags", 0, REG_DWORD
, (void*)&padid
->cFormatTags
, sizeof(DWORD
)))
220 if (RegSetValueExA(hKey
, "cFilterTags", 0, REG_DWORD
, (void*)&padid
->cFilterTags
, sizeof(DWORD
)))
222 if (RegSetValueExA(hKey
, "fdwSupport", 0, REG_DWORD
, (void*)&padid
->fdwSupport
, sizeof(DWORD
)))
224 if (RegSetValueExA(hKey
, "aFormatTagCache", 0, REG_BINARY
,
225 (void*)padid
->aFormatTag
,
226 padid
->cFormatTags
* sizeof(padid
->aFormatTag
[0])))
228 HeapFree(MSACM_hHeap
, 0, key
);
232 HeapFree(MSACM_hHeap
, 0, key
);
236 /***********************************************************************
237 * MSACM_RegisterDriver()
239 PWINE_ACMDRIVERID
MSACM_RegisterDriver(LPCWSTR pszDriverAlias
, LPCWSTR pszFileName
,
240 HINSTANCE hinstModule
)
242 PWINE_ACMDRIVERID padid
;
244 TRACE("(%s, %s, %p)\n",
245 debugstr_w(pszDriverAlias
), debugstr_w(pszFileName
), hinstModule
);
247 padid
= (PWINE_ACMDRIVERID
) HeapAlloc(MSACM_hHeap
, 0, sizeof(WINE_ACMDRIVERID
));
248 padid
->obj
.dwType
= WINE_ACMOBJ_DRIVERID
;
249 padid
->obj
.pACMDriverID
= padid
;
250 padid
->pszDriverAlias
= NULL
;
253 padid
->pszDriverAlias
= HeapAlloc( MSACM_hHeap
, 0, (strlenW(pszDriverAlias
)+1) * sizeof(WCHAR
) );
254 strcpyW( padid
->pszDriverAlias
, pszDriverAlias
);
256 padid
->pszFileName
= NULL
;
259 padid
->pszFileName
= HeapAlloc( MSACM_hHeap
, 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
) );
260 strcpyW( padid
->pszFileName
, pszFileName
);
262 padid
->hInstModule
= hinstModule
;
264 padid
->pACMDriverList
= NULL
;
265 padid
->pNextACMDriverID
= NULL
;
266 padid
->pPrevACMDriverID
= MSACM_pLastACMDriverID
;
267 if (MSACM_pLastACMDriverID
)
268 MSACM_pLastACMDriverID
->pNextACMDriverID
= padid
;
269 MSACM_pLastACMDriverID
= padid
;
270 if (!MSACM_pFirstACMDriverID
)
271 MSACM_pFirstACMDriverID
= padid
;
272 /* disable the driver if we cannot load the cache */
273 if (!MSACM_ReadCache(padid
) && !MSACM_FillCache(padid
)) {
274 WARN("Couldn't load cache for ACM driver (%s)\n", debugstr_w(pszFileName
));
275 MSACM_UnregisterDriver(padid
);
281 /***********************************************************************
282 * MSACM_RegisterAllDrivers()
284 void MSACM_RegisterAllDrivers(void)
287 DWORD dwBufferLength
;
288 static const WCHAR msacm32
[] = {'m','s','a','c','m','3','2','.','d','l','l','\0'};
289 static const WCHAR msacmW
[] = {'M','S','A','C','M','.'};
290 static const WCHAR drv32
[] = {'d','r','i','v','e','r','s','3','2','\0'};
291 static const WCHAR sys
[] = {'s','y','s','t','e','m','.','i','n','i','\0'};
294 * What if the user edits system.ini while the program is running?
295 * Does Windows handle that?
297 if (MSACM_pFirstACMDriverID
)
300 /* FIXME: Does not work! How do I determine the section length? */
301 dwBufferLength
= 1024;
302 /* EPP GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
304 pszBuffer
= (LPWSTR
) HeapAlloc(MSACM_hHeap
, 0, dwBufferLength
* sizeof(WCHAR
));
305 if (GetPrivateProfileSectionW(drv32
, pszBuffer
, dwBufferLength
, sys
))
307 LPWSTR s
= pszBuffer
, s2
;
311 CharUpperBuffW(s
, 6);
312 if (memcmp(s
, msacmW
, 6 * sizeof(WCHAR
)) == 0)
315 while (*s2
!= '\0' && *s2
!= '=') s2
++;
319 MSACM_RegisterDriver(s
, s2
+ 1, 0);
323 s
+= strlenW(s
) + 1; /* Either next char or \0 */
327 HeapFree(MSACM_hHeap
, 0, pszBuffer
);
329 MSACM_RegisterDriver(msacm32
, msacm32
, 0);
332 /***********************************************************************
333 * MSACM_UnregisterDriver()
335 PWINE_ACMDRIVERID
MSACM_UnregisterDriver(PWINE_ACMDRIVERID p
)
337 PWINE_ACMDRIVERID pNextACMDriverID
;
339 while (p
->pACMDriverList
)
340 acmDriverClose((HACMDRIVER
) p
->pACMDriverList
, 0);
342 if (p
->pszDriverAlias
)
343 HeapFree(MSACM_hHeap
, 0, p
->pszDriverAlias
);
345 HeapFree(MSACM_hHeap
, 0, p
->pszFileName
);
346 HeapFree(MSACM_hHeap
, 0, p
->aFormatTag
);
348 if (p
== MSACM_pFirstACMDriverID
)
349 MSACM_pFirstACMDriverID
= p
->pNextACMDriverID
;
350 if (p
== MSACM_pLastACMDriverID
)
351 MSACM_pLastACMDriverID
= p
->pPrevACMDriverID
;
353 if (p
->pPrevACMDriverID
)
354 p
->pPrevACMDriverID
->pNextACMDriverID
= p
->pNextACMDriverID
;
355 if (p
->pNextACMDriverID
)
356 p
->pNextACMDriverID
->pPrevACMDriverID
= p
->pPrevACMDriverID
;
358 pNextACMDriverID
= p
->pNextACMDriverID
;
360 HeapFree(MSACM_hHeap
, 0, p
);
362 return pNextACMDriverID
;
365 /***********************************************************************
366 * MSACM_UnregisterAllDrivers()
368 void MSACM_UnregisterAllDrivers(void)
370 PWINE_ACMDRIVERID p
= MSACM_pFirstACMDriverID
;
374 p
= MSACM_UnregisterDriver(p
);
378 /***********************************************************************
381 PWINE_ACMOBJ
MSACM_GetObj(HACMOBJ hObj
, DWORD type
)
383 PWINE_ACMOBJ pao
= (PWINE_ACMOBJ
)hObj
;
385 if (pao
== NULL
|| IsBadReadPtr(pao
, sizeof(WINE_ACMOBJ
)) ||
386 ((type
!= WINE_ACMOBJ_DONTCARE
) && (type
!= pao
->dwType
)))
391 /***********************************************************************
392 * MSACM_GetDriverID()
394 PWINE_ACMDRIVERID
MSACM_GetDriverID(HACMDRIVERID hDriverID
)
396 return (PWINE_ACMDRIVERID
)MSACM_GetObj((HACMOBJ
)hDriverID
, WINE_ACMOBJ_DRIVERID
);
399 /***********************************************************************
402 PWINE_ACMDRIVER
MSACM_GetDriver(HACMDRIVER hDriver
)
404 return (PWINE_ACMDRIVER
)MSACM_GetObj((HACMOBJ
)hDriver
, WINE_ACMOBJ_DRIVER
);
407 /***********************************************************************
410 MMRESULT
MSACM_Message(HACMDRIVER had
, UINT uMsg
, LPARAM lParam1
, LPARAM lParam2
)
412 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
414 return pad
? SendDriverMessage(pad
->hDrvr
, uMsg
, lParam1
, lParam2
) : MMSYSERR_INVALHANDLE
;