Added cache for drivers information.
Fixed a few bugs (memory handling, version info...)
Enhanced validity checks.
diff --git a/dlls/msacm/internal.c b/dlls/msacm/internal.c
index 4f6924c..566a984 100644
--- a/dlls/msacm/internal.c
+++ b/dlls/msacm/internal.c
@@ -14,6 +14,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
+#include "winreg.h"
#include "mmsystem.h"
#include "msacm.h"
#include "msacmdrv.h"
@@ -28,6 +29,195 @@
PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
+#if 0
+/***********************************************************************
+ * MSACM_DumpCache
+ */
+static void MSACM_DumpCache(PWINE_ACMDRIVERID padid)
+{
+ unsigned i;
+
+ TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
+ padid->cFilterTags, padid->cFormatTags, padid->fdwSupport);
+ for (i = 0; i < padid->cache->cFormatTags; i++) {
+ TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
+ padid->aFormatTag[i].dwFormatTag, padid->aFormatTag[i].cbwfx);
+ }
+}
+#endif
+
+/***********************************************************************
+ * MSACM_FindFormatTagInCache [internal]
+ *
+ * Returns TRUE is the format tag fmtTag is present in the cache.
+ * If so, idx is set to its index.
+ */
+BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID* padid, DWORD fmtTag, LPDWORD idx)
+{
+ unsigned i;
+
+ for (i = 0; i < padid->cFormatTags; i++) {
+ if (padid->aFormatTag[i].dwFormatTag == fmtTag) {
+ if (idx) *idx = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/***********************************************************************
+ * MSACM_FillCache
+ */
+static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid)
+{
+ HACMDRIVER had = 0;
+ int ntag;
+ ACMDRIVERDETAILSW add;
+ ACMFORMATDETAILSW aftd;
+ WAVEFORMATEX wfx;
+
+ if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0)
+ return FALSE;
+
+ padid->aFormatTag = NULL;
+ add.cbStruct = sizeof(add);
+ if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add, 0))
+ goto errCleanUp;
+
+ if (add.cFormatTags > 0) {
+ padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY,
+ add.cFormatTags * sizeof(padid->aFormatTag[0]));
+ if (!padid->aFormatTag) goto errCleanUp;
+ }
+
+ padid->cFormatTags = add.cFormatTags;
+ padid->cFilterTags = add.cFilterTags;
+ padid->fdwSupport = add.fdwSupport;
+
+ aftd.cbStruct = sizeof(aftd);
+ /* don't care about retrieving full struct... so a bare WAVEFORMATEX should do */
+ aftd.pwfx = &wfx;
+ aftd.cbwfx = sizeof(wfx);
+
+ for (ntag = 0; ntag < add.cFormatTags; ntag++) {
+ aftd.dwFormatIndex = ntag;
+ if (MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)&aftd, ACM_FORMATDETAILSF_INDEX)) {
+ TRACE("IIOs (%s)\n", padid->pszDriverAlias);
+ goto errCleanUp;
+ }
+ padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag;
+ padid->aFormatTag[ntag].cbwfx = aftd.cbwfx;
+ }
+
+ acmDriverClose(had, 0);
+
+ return TRUE;
+
+errCleanUp:
+ if (had) acmDriverClose(had, 0);
+ HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
+ padid->aFormatTag = NULL;
+ return FALSE;
+}
+
+/***********************************************************************
+ * MSACM_GetRegistryKey
+ */
+static LPSTR MSACM_GetRegistryKey(const WINE_ACMDRIVERID* padid)
+{
+ static const char* baseKey = "Software\\Microsoft\\AudioCompressionManager\\DriverCache\\";
+ LPSTR ret;
+ int len;
+
+ if (!padid->pszDriverAlias) {
+ ERR("No alias needed for registry entry\n");
+ return NULL;
+ }
+ len = strlen(baseKey);
+ ret = HeapAlloc(MSACM_hHeap, 0, len + strlen(padid->pszDriverAlias) + 1);
+ if (!ret) return NULL;
+
+ strcpy(ret, baseKey);
+ strcpy(ret + len, padid->pszDriverAlias);
+ CharLowerA(ret + len);
+ return ret;
+}
+
+/***********************************************************************
+ * MSACM_ReadCache
+ */
+static BOOL MSACM_ReadCache(PWINE_ACMDRIVERID padid)
+{
+ LPSTR key = MSACM_GetRegistryKey(padid);
+ HKEY hKey;
+ DWORD type, size;
+
+ if (!key) return FALSE;
+
+ padid->aFormatTag = NULL;
+
+ if (RegCreateKeyA(HKEY_LOCAL_MACHINE, key, &hKey))
+ goto errCleanUp;
+
+ size = sizeof(padid->cFormatTags);
+ if (RegQueryValueExA(hKey, "cFormatTags", 0, &type, (void*)&padid->cFormatTags, &size))
+ goto errCleanUp;
+ size = sizeof(padid->cFilterTags);
+ if (RegQueryValueExA(hKey, "cFilterTags", 0, &type, (void*)&padid->cFilterTags, &size))
+ goto errCleanUp;
+ size = sizeof(padid->fdwSupport);
+ if (RegQueryValueExA(hKey, "fdwSupport", 0, &type, (void*)&padid->fdwSupport, &size))
+ goto errCleanUp;
+
+ if (padid->cFormatTags > 0) {
+ size = padid->cFormatTags * sizeof(padid->aFormatTag[0]);
+ padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, size);
+ if (!padid->aFormatTag) goto errCleanUp;
+ if (RegQueryValueExA(hKey, "aFormatTagCache", 0, &type, (void*)padid->aFormatTag, &size))
+ goto errCleanUp;
+ }
+ HeapFree(MSACM_hHeap, 0, key);
+ return TRUE;
+
+ errCleanUp:
+ HeapFree(MSACM_hHeap, 0, key);
+ HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
+ padid->aFormatTag = NULL;
+ RegCloseKey(hKey);
+ return FALSE;
+}
+
+/***********************************************************************
+ * MSACM_WriteCache
+ */
+static BOOL MSACM_WriteCache(PWINE_ACMDRIVERID padid)
+{
+ LPSTR key = MSACM_GetRegistryKey(padid);
+ HKEY hKey;
+
+ if (!key) return FALSE;
+
+ if (RegCreateKeyA(HKEY_LOCAL_MACHINE, key, &hKey))
+ goto errCleanUp;
+
+ if (RegSetValueExA(hKey, "cFormatTags", 0, REG_DWORD, (void*)&padid->cFormatTags, sizeof(DWORD)))
+ goto errCleanUp;
+ if (RegSetValueExA(hKey, "cFilterTags", 0, REG_DWORD, (void*)&padid->cFilterTags, sizeof(DWORD)))
+ goto errCleanUp;
+ if (RegSetValueExA(hKey, "fdwSupport", 0, REG_DWORD, (void*)&padid->fdwSupport, sizeof(DWORD)))
+ goto errCleanUp;
+ if (RegSetValueExA(hKey, "aFormatTagCache", 0, REG_BINARY,
+ (void*)padid->aFormatTag,
+ padid->cFormatTags * sizeof(padid->aFormatTag[0])))
+ goto errCleanUp;
+ HeapFree(MSACM_hHeap, 0, key);
+ return TRUE;
+
+ errCleanUp:
+ HeapFree(MSACM_hHeap, 0, key);
+ return FALSE;
+}
+
/***********************************************************************
* MSACM_RegisterDriver()
*/
@@ -54,6 +244,7 @@
strcpy( padid->pszFileName, pszFileName );
}
padid->hInstModule = hinstModule;
+
padid->bEnabled = TRUE;
padid->pACMDriverList = NULL;
padid->pNextACMDriverID = NULL;
@@ -63,7 +254,12 @@
MSACM_pLastACMDriverID = padid;
if (!MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID = padid;
-
+ /* disable the driver if we cannot load the cache */
+ if (!MSACM_ReadCache(padid) && !MSACM_FillCache(padid)) {
+ WARN("Couldn't load cache for ACM driver (%s)\n", pszFileName);
+ MSACM_UnregisterDriver(padid);
+ return NULL;
+ }
return padid;
}
@@ -82,7 +278,7 @@
if (MSACM_pFirstACMDriverID)
return;
- /* FIXME: Do not work! How do I determine the section length? */
+ /* FIXME: Does not work! How do I determine the section length? */
dwBufferLength = 1024;
/* EPP GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
@@ -122,7 +318,8 @@
HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
if (p->pszFileName)
HeapFree(MSACM_hHeap, 0, p->pszFileName);
-
+ HeapFree(MSACM_hHeap, 0, p->aFormatTag);
+
if (p == MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID = p->pNextACMDriverID;
if (p == MSACM_pLastACMDriverID)
@@ -142,14 +339,15 @@
/***********************************************************************
* MSACM_UnregisterAllDrivers()
- * FIXME
- * Where should this function be called?
*/
void MSACM_UnregisterAllDrivers(void)
{
- PWINE_ACMDRIVERID p;
+ PWINE_ACMDRIVERID p = MSACM_pFirstACMDriverID;
- for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
+ while (p) {
+ MSACM_WriteCache(p);
+ p = MSACM_UnregisterDriver(p);
+ }
}
/***********************************************************************