Index: trunk/src/msacm32/driver.cpp
===================================================================
--- trunk/src/msacm32/driver.cpp	(revision 2101)
+++ trunk/src/msacm32/driver.cpp	(revision 2103)
@@ -61,6 +61,6 @@
 			      LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
 {
-    FIXME("(%p, 0x%08x, %ld, %ld, %ld): stub\n",
-	  phadid, hinstModule, lParam, dwPriority, fdwAdd);
+    dprintf(("(%p, 0x%08x, %ld, %ld, %ld): stub\n",
+	  phadid, hinstModule, lParam, dwPriority, fdwAdd));
     
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -73,5 +73,6 @@
 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
 {
-    PWINE_ACMDRIVER p;
+    PWINE_ACMDRIVER  p;
+    PWINE_ACMDRIVER* tp;
     
     if (fdwClose)
@@ -81,8 +82,13 @@
     if (!p)
 	return MMSYSERR_INVALHANDLE;
-    
-    p->obj.pACMDriverID->pACMDriver = NULL;
-    
-    if (p->hDrvr)
+
+    for (tp = &(p->obj.pACMDriverID->pACMDriverList); *tp; *tp = (*tp)->pNextACMDriver) {
+	if (*tp == p) {
+	    *tp = (*tp)->pNextACMDriver;
+	    break;
+	}
+    }
+    
+    if (p->hDrvr && !p->obj.pACMDriverID->pACMDriverList)
 	CloseDriver(p->hDrvr, 0, 0);
     
@@ -127,27 +133,15 @@
 MMRESULT WINAPI acmDriverDetailsW(HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails)
 {
-    PWINE_ACMDRIVERID p;
+    HACMDRIVER acmDrvr;
     MMRESULT mmr;
-    BOOL bOpenTemporary;
-    
-    p = MSACM_GetDriverID(hadid);
-    if (!p)
-	return MMSYSERR_INVALHANDLE;
     
     if (fdwDetails)
 	return MMSYSERR_INVALFLAG;
     
-    bOpenTemporary = !p->pACMDriver;
-    if (bOpenTemporary) {
-	bOpenTemporary = TRUE;
-	acmDriverOpen((PHACMDRIVER) &p->pACMDriver, hadid, 0);
-    }
-    
-    mmr = (MMRESULT) acmDriverMessage((HACMDRIVER) p->pACMDriver, ACMDM_DRIVER_DETAILS, 
-				      (LPARAM) padd,  0);
-    
-    if (bOpenTemporary) {
-	acmDriverClose((HACMDRIVER) p->pACMDriver, 0);
-	p->pACMDriver = NULL;
+    mmr = acmDriverOpen(&acmDrvr, hadid, 0);
+    if (mmr == 0) {
+	mmr = (MMRESULT)acmDriverMessage(acmDrvr, ACMDM_DRIVER_DETAILS, (LPARAM) padd,  0);
+    
+	acmDriverClose(acmDrvr, 0);
     }
     
@@ -160,6 +154,7 @@
 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
 {
-    PWINE_ACMDRIVERID p;
-    
+    PWINE_ACMDRIVERID	p;
+    DWORD		fdwSupport;
+
     if (!fnCallback) {
 	return MMSYSERR_INVALPARAM;
@@ -170,8 +165,13 @@
     }
     
-    p = MSACM_pFirstACMDriverID;
-    while (p) {
-	(*fnCallback)((HACMDRIVERID) p, dwInstance, ACMDRIVERDETAILS_SUPPORTF_CODEC);
-	p = p->pNextACMDriverID;
+    for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
+	fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+	if (!p->bEnabled) {
+	    if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
+		fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
+	    else
+		continue;
+	}
+	(*fnCallback)((HACMDRIVERID) p, dwInstance, fdwSupport);
     }
     
@@ -226,7 +226,8 @@
 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
 {
-    PWINE_ACMDRIVERID padid;
-
-    TRACE("(%p, %x, %08lu\n", phad, hadid, fdwOpen);
+    PWINE_ACMDRIVERID	padid;
+    PWINE_ACMDRIVER	pad;
+
+    dprintf(("(%p, %x, %08lu)\n", phad, hadid, fdwOpen));
 
     if (!phad)
@@ -240,29 +241,27 @@
 	return MMSYSERR_INVALFLAG;
     
-    if (padid->pACMDriver) {
-	/* FIXME: Is it allowed? */
-	ERR("Can't open driver twice\n");
+    pad = PWINE_ACMDRIVER(HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER)));
+    if (!pad) return MMSYSERR_NOMEM;
+
+    pad->obj.pACMDriverID = padid;
+    
+    if (!padid->hInstModule)
+	pad->hDrvr = OpenDriverA(padid->pszDriverAlias, "drivers32", 0);
+    else
+	pad->hDrvr = padid->hInstModule;
+    
+    if (!pad->hDrvr) {
+	HeapFree(MSACM_hHeap, 0, pad);
 	return MMSYSERR_ERROR;
     }
     
-    padid->pACMDriver = PWINE_ACMDRIVER(HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER)));
-    padid->pACMDriver->obj.pACMDriverID = padid;
-    
-    if (!padid->hInstModule)
-	padid->pACMDriver->hDrvr = OpenDriverA(padid->pszDriverAlias, "drivers32", 0);
-    else
-	padid->pACMDriver->hDrvr = padid->hInstModule;
-    
-    if (!padid->pACMDriver->hDrvr) {
-	HeapFree(MSACM_hHeap, 0, padid->pACMDriver);
-	padid->pACMDriver = NULL;
-	return MMSYSERR_ERROR;
-    }
-    
-    /* FIXME-ICC: "FARPROC" cannot be converted to "extern "STDCALL" LRESULT(*)(DWORD,HDRVR,UINT,LPARAM,LPARAM)" */
-//   padid->pACMDriver->pfnDriverProc = GetProcAddress(padid->pACMDriver->hDrvr, "DriverProc");
-    
+//    pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc");
+
+    /* insert new pad at beg of list */
+    pad->pNextACMDriver = padid->pACMDriverList;
+    padid->pACMDriverList = pad;
+
     /* FIXME: Create a WINE_ACMDRIVER32 */
-    *phad = (HACMDRIVER) padid->pACMDriver;
+    *phad = (HACMDRIVER)pad;
     
 //    return MMSYSERR_NOERROR;
@@ -318,6 +317,6 @@
 	    break;
 	
-	FIXME("(0x%08x, %ld, %ld): stub (partial)\n", 
-	      hadid, dwPriority, fdwPriority);
+	dprintf(("(0x%08x, %ld, %ld): stub (partial)\n", 
+	      hadid, dwPriority, fdwPriority));
 	break;
     }
Index: trunk/src/msacm32/msacm32.cpp
===================================================================
--- trunk/src/msacm32/msacm32.cpp	(revision 2101)
+++ trunk/src/msacm32/msacm32.cpp	(revision 2103)
@@ -70,5 +70,5 @@
     switch (GetVersion()) {
     default: 
-	dprintf(("OS not supported\n"));
+	dprintf(("Current OS not supported\n"));
     case WIN95:
 	return 0x04000000; /* 4.0.0 */
@@ -89,7 +89,9 @@
 MMRESULT WINAPI acmMetrics(HACMOBJ hao, UINT uMetric, LPVOID  pMetric)
 {
-    PWINE_ACMOBJ pao = MSACM_GetObj(hao);
-    BOOL bLocal = TRUE;
-    
+    PWINE_ACMOBJ 	pao = MSACM_GetObj(hao);
+    BOOL 		bLocal = TRUE;
+    PWINE_ACMDRIVERID	padid;
+    DWORD		val = 0;
+
     dprintf(("(0x%08x, %d, %p): stub\n", hao, uMetric, pMetric));
     
@@ -97,26 +99,61 @@
     case ACM_METRIC_COUNT_DRIVERS:
 	bLocal = FALSE;
+	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_DRIVERS:
 	if (!pao)
-	    return MMSYSERR_INVALHANDLE;  
-	return MMSYSERR_NOTSUPPORTED;
+	    return MMSYSERR_INVALHANDLE;
+	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
+	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+		val++;
+	*(LPDWORD)pMetric = val;
+	return 0;
+
     case ACM_METRIC_COUNT_CODECS:
+	if (!pao)
+	    return MMSYSERR_INVALHANDLE;
 	bLocal = FALSE;
+	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_CODECS:
-	return MMSYSERR_NOTSUPPORTED;
+	/* FIXME: don't know how to differentiate codec, converters & filters yet */
+	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
+	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+		val++;
+	*(LPDWORD)pMetric = val;
+	return 0;
+
     case ACM_METRIC_COUNT_CONVERTERS:
 	bLocal = FALSE;
+	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_CONVERTERS:
-	return MMSYSERR_NOTSUPPORTED;
+	/* FIXME: don't know how to differentiate codec, converters & filters yet */
+	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
+	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+		val++;
+	*(LPDWORD)pMetric = val;
+	return 0;
+
     case ACM_METRIC_COUNT_FILTERS:
 	bLocal = FALSE;
+	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_FILTERS:
-	return MMSYSERR_NOTSUPPORTED;
+	/* FIXME: don't know how to differentiate codec, converters & filters yet */
+	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
+	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+		val++;
+	*(LPDWORD)pMetric = val;
+	return 0;
+
     case ACM_METRIC_COUNT_DISABLED:
 	bLocal = FALSE;
+	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_DISABLED:
 	if (!pao)
 	    return MMSYSERR_INVALHANDLE;  
-	return MMSYSERR_NOTSUPPORTED;
+	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
+	    if (!padid->bEnabled /* && (local(padid) || !bLocal) */)
+		val++;
+	*(LPDWORD)pMetric = val;
+	return 0;
+
     case ACM_METRIC_COUNT_HARDWARE:
     case ACM_METRIC_HARDWARE_WAVE_INPUT:
Index: trunk/src/msacm32/stream.cpp
===================================================================
--- trunk/src/msacm32/stream.cpp	(revision 2101)
+++ trunk/src/msacm32/stream.cpp	(revision 2103)
@@ -48,5 +48,6 @@
     ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
     if (ret == MMSYSERR_NOERROR) {
-	/* FIXME: shall the was->pDrv->hDrvr be also closed ? */
+	if (was->hAcmDriver)
+	    acmDriverClose(was->hAcmDriver, 0L);	
 	HeapFree(MSACM_hHeap, 0, was);
     }
@@ -169,5 +170,6 @@
 	was->obj.pACMDriverID = wad->obj.pACMDriverID;
 	was->pDrv = wad;
-	
+	was->hAcmDriver = 0; /* not to close it in acmStreamClose */
+
 	ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
 	if (ret != MMSYSERR_NOERROR)
@@ -183,9 +185,13 @@
 		    was->obj.pACMDriverID = wad->obj.pACMDriverID;
 		    was->pDrv = wad;
+		    was->hAcmDriver = had;
 		    
 		    ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
-		    /* FIXME: when shall the acmDriver be Close():d ? */
-		    if (ret == MMSYSERR_NOERROR)
+		    if (ret == MMSYSERR_NOERROR) {
+			if (fdwOpen & ACM_STREAMOPENF_QUERY) {
+			    acmDriverClose(had, 0L);
+			}
 			break;
+		    }
 		}
 		/* no match, close this acm driver and try next one */
@@ -198,11 +204,14 @@
 	}
     }
+    ret = MMSYSERR_NOERROR;
+    if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
+	if (phas)
+	    *phas = (HACMSTREAM)was;
+	dprintf(("=> (%d)\n", ret));
+	return ret;
+    }
+errCleanUp:		
     if (phas)
-	*phas = (HACMSTREAM)was;
-    dprintf(("=> (%d)\n", ret));
-    ret = MMSYSERR_NOERROR;
-    if (!(fdwOpen & ACM_STREAMOPENF_QUERY))
-	return ret;
-errCleanUp:		
+	*phas = (HACMSTREAM)0;
     HeapFree(MSACM_hHeap, 0, was);
     dprintf(("=> (%d)\n", ret));
Index: trunk/src/msacm32/wineacm.h
===================================================================
--- trunk/src/msacm32/wineacm.h	(revision 2101)
+++ trunk/src/msacm32/wineacm.h	(revision 2103)
@@ -5,4 +5,5 @@
  */
 typedef struct _WINE_ACMDRIVERID *PWINE_ACMDRIVERID;
+typedef struct _WINE_ACMDRIVER   *PWINE_ACMDRIVER;
 
 typedef struct _WINE_ACMOBJ
@@ -16,5 +17,6 @@
     HDRVR      		hDrvr;
     DRIVERPROC		pfnDriverProc;
-} WINE_ACMDRIVER, *PWINE_ACMDRIVER;
+    PWINE_ACMDRIVER	pNextACMDriver;
+} WINE_ACMDRIVER;
 
 typedef struct _WINE_ACMSTREAM
@@ -23,4 +25,5 @@
     PWINE_ACMDRIVER	pDrv;
     ACMDRVSTREAMINSTANCE drvInst;
+    HACMDRIVER		hAcmDriver;
 } WINE_ACMSTREAM, *PWINE_ACMSTREAM;
 
@@ -32,7 +35,7 @@
     DWORD		dwProcessID;	      /* ID of process which installed a local driver */
     BOOL                bEnabled;
-    PWINE_ACMDRIVER     pACMDriver;           /* NULL if not open; shouldn't this be a list ? */
+    PWINE_ACMDRIVER     pACMDriverList;
     PWINE_ACMDRIVERID   pNextACMDriverID;
-    PWINE_ACMDRIVERID	pPreviousACMDriverID;
+    PWINE_ACMDRIVERID	pPrevACMDriverID;
 } WINE_ACMDRIVERID;
 
