Started the implementation of MSACM.DLL and MSACM32.DLL.

diff --git a/dlls/msacm/.cvsignore b/dlls/msacm/.cvsignore
new file mode 100644
index 0000000..f3c7a7c
--- /dev/null
+++ b/dlls/msacm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/dlls/msacm/Makefile.in b/dlls/msacm/Makefile.in
new file mode 100644
index 0000000..5bb7d5d
--- /dev/null
+++ b/dlls/msacm/Makefile.in
@@ -0,0 +1,16 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = msacm
+
+C_SRCS = \
+	msacm_main.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
+
diff --git a/dlls/msacm/msacm_main.c b/dlls/msacm/msacm_main.c
new file mode 100644
index 0000000..206c4ce
--- /dev/null
+++ b/dlls/msacm/msacm_main.c
@@ -0,0 +1,411 @@
+/*
+ *      MSACM library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "mmsystem.h"
+#include "msacm.h"
+
+/***********************************************************************
+ *           ACMGETVERSION (MSACM.7)
+ */
+DWORD WINAPI acmGetVersion16()
+{
+  FIXME(msacm, "(): stub\n");
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0; /* FIXME */
+}
+
+/***********************************************************************
+ *           ACMMETRICS (MSACM.8)
+ */
+
+MMRESULT16 WINAPI acmMetrics16(
+  HACMOBJ16 hao, UINT16 uMetric, LPVOID pMetric)
+{
+  FIXME(msacm, "(0x%04x, %d, %p): stub\n", hao, uMetric, pMetric);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERENUM (MSACM.10)
+ */
+MMRESULT16 WINAPI acmDriverEnum16(
+  ACMDRIVERENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(%p, %ld, %ld): stub\n",
+    fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERDETAILS (MSACM.11)
+ */
+
+MMRESULT16 WINAPI acmDriverDetails16(
+  HACMDRIVERID16 hadid, LPACMDRIVERDETAILS16 padd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", hadid, padd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERADD (MSACM.12)
+ */
+MMRESULT16 WINAPI acmDriverAdd16(
+  LPHACMDRIVERID16 phadid, HINSTANCE16 hinstModule,
+  LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
+{
+  FIXME(msacm, "(%p, 0x%04x, %ld, %ld, %ld): stub\n",
+    phadid, hinstModule, lParam, dwPriority, fdwAdd
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERREMOVE (MSACM.13)
+ */
+MMRESULT16 WINAPI acmDriverRemove16(
+  HACMDRIVERID16 hadid, DWORD fdwRemove)
+{
+  FIXME(msacm, "(0x%04x, %ld): stub\n", hadid, fdwRemove);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVEROPEN (MSACM.14)
+ */
+MMRESULT16 WINAPI acmDriverOpen16(
+  LPHACMDRIVER16 phad, HACMDRIVERID16 hadid, DWORD fdwOpen)
+{
+  FIXME(msacm, "(%p, 0x%04x, %ld): stub\n", phad, hadid, fdwOpen);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERCLOSE (MSACM.15)
+ */
+MMRESULT16 WINAPI acmDriverClose16(
+  HACMDRIVER16 had, DWORD fdwClose)
+{
+  FIXME(msacm, "(0x%04x, %ld): stub\n", had, fdwClose);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERMESSAGE (MSACM.16)
+ */
+LRESULT WINAPI acmDriverMessage16(
+  HACMDRIVER16 had, UINT16 uMsg, LPARAM lParam1, LPARAM lParam2)
+{
+  FIXME(msacm, "(0x%04x, %d, %ld, %ld): stub\n",
+    had, uMsg, lParam1, lParam2
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0;
+}
+
+/***********************************************************************
+ *           ACMDRIVERID (MSACM.17)
+ */
+MMRESULT16 WINAPI acmDriverID16(
+  HACMOBJ16 hao, LPHACMDRIVERID16 phadid, DWORD fdwDriverID)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", hao, phadid, fdwDriverID);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMDRIVERPRIORITY (MSACM.18)
+ */
+MMRESULT16 WINAPI acmDriverPriority16(
+ HACMDRIVERID16 hadid, DWORD dwPriority, DWORD fdwPriority)
+{
+  FIXME(msacm, "(0x%04x, %ld, %ld): stub\n",
+    hadid, dwPriority, fdwPriority
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFORMATTAGDETAILS (MSACM.30)
+ */
+MMRESULT16 WINAPI acmFormatTagDetails16(
+  HACMDRIVER16 had, LPACMFORMATTAGDETAILS16 paftd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", had, paftd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFORMATTAGENUM (MSACM.31)
+ */
+MMRESULT16 WINAPI acmFormatTagEnum16(
+  HACMDRIVER16 had, LPACMFORMATTAGDETAILS16 paftd,
+  ACMFORMATTAGENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%04x, %p, %p, %ld, %ld): stub\n",
+    had, paftd, fnCallback, dwInstance, fdwEnum
+  ); 
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFORMATCHOOSE (MSACM.40)
+ */
+MMRESULT16 WINAPI acmFormatChoose16(
+  LPACMFORMATCHOOSE16 pafmtc)
+{
+  FIXME(msacm, "(%p): stub\n", pafmtc);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFORMATDETAILS (MSACM.41)
+ */
+MMRESULT16 WINAPI acmFormatDetails16(
+  HACMDRIVER16 had, LPACMFORMATDETAILS16 pafd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", had, pafd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFORMATENUM (MSACM.42)
+ */
+MMRESULT16 WINAPI acmFormatEnum16(
+  HACMDRIVER16 had, LPACMFORMATDETAILS16 pafd,
+  ACMFORMATENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%04x, %p, %p, %ld, %ld): stub\n",
+    had, pafd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFORMATSUGGEST (MSACM.45)
+ */
+MMRESULT16 WINAPI acmFormatSuggest16(
+  HACMDRIVER16 had, LPWAVEFORMATEX16 pwfxSrc, 
+  LPWAVEFORMATEX16 pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
+{
+  FIXME(msacm, "(0x%04x, %p, %p, %ld, %ld): stub\n",
+    had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFILTERTAGDETAILS (MSACM.50)
+ */
+MMRESULT16 WINAPI acmFilterTagDetails16(
+  HACMDRIVER16 had, LPACMFILTERTAGDETAILS16 paftd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", had, paftd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFILTERTAGENUM (MSACM.51)
+ */
+MMRESULT16 WINAPI acmFilterTagEnum16(
+  HACMDRIVER16 had, LPACMFILTERTAGDETAILS16 paftd,
+  ACMFILTERTAGENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%04x, %p, %p, %ld, %ld): stub\n",
+    had, paftd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFILTERCHOOSE (MSACM.60)
+ */
+MMRESULT16 WINAPI acmFilterChoose16(
+  LPACMFILTERCHOOSE16 pafltrc)
+{
+  FIXME(msacm, "(%p): stub\n", pafltrc);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFILTERDETAILS (MSACM.61)
+ */
+MMRESULT16 WINAPI acmFilterDetails16(
+  HACMDRIVER16 had, LPACMFILTERDETAILS16 pafd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", had, pafd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMFILTERENUM (MSACM.62)
+ */
+MMRESULT16 WINAPI acmFilterEnum16(
+  HACMDRIVER16 had, LPACMFILTERDETAILS16 pafd,
+  ACMFILTERENUMCB16 fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%04x, %p, %p, %ld, %ld): stub\n",
+    had, pafd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMOPEN (MSACM.70)
+ */
+MMRESULT16 WINAPI acmStreamOpen16(
+  LPHACMSTREAM16 phas, HACMDRIVER16 had,
+  LPWAVEFORMATEX16 pwfxSrc, LPWAVEFORMATEX16 pwfxDst,
+  LPWAVEFILTER16 pwfltr, DWORD dwCallback,
+  DWORD dwInstance, DWORD fdwOpen)
+{
+  FIXME(msacm, "(%p, 0x%04x, %p, %p, %p, %ld, %ld, %ld): stub\n",
+    phas, had, pwfxSrc, pwfxDst, pwfltr,
+    dwCallback, dwInstance, fdwOpen
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMCLOSE (MSACM.71)
+ */
+MMRESULT16 WINAPI acmStreamClose16(
+  HACMSTREAM16 has, DWORD fdwClose)
+{
+  FIXME(msacm, "(0x%04x, %ld): stub\n", has, fdwClose);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMSIZE (MSACM.72)
+ */
+MMRESULT16 WINAPI acmStreamSize16(
+  HACMSTREAM16 has, DWORD cbInput, 
+  LPDWORD pdwOutputBytes, DWORD fdwSize)
+{
+  FIXME(msacm, "(0x%04x, %ld, %p, %ld): stub\n",
+    has, cbInput, pdwOutputBytes, fdwSize
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMCONVERT (MSACM.75)
+ */
+MMRESULT16 WINAPI acmStreamConvert16(
+  HACMSTREAM16 has, LPACMSTREAMHEADER16 pash, DWORD fdwConvert)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", has, pash, fdwConvert);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMRESET (MSACM.76)
+ */
+MMRESULT16 WINAPI acmStreamReset16(
+  HACMSTREAM16 has, DWORD fdwReset)
+{
+  FIXME(msacm, "(0x%04x, %ld): stub\n", has, fdwReset);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMPREPAREHEADER (MSACM.77)
+ */
+MMRESULT16 WINAPI acmStreamPrepareHeader16(
+  HACMSTREAM16 has, LPACMSTREAMHEADER16 pash, DWORD fdwPrepare)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n", has, pash, fdwPrepare);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMSTREAMUNPREPAREHEADER (MSACM.78)
+ */
+MMRESULT16 WINAPI acmStreamUnprepareHeader16(
+  HACMSTREAM16 has, LPACMSTREAMHEADER16 pash, DWORD fdwUnprepare)
+{
+  FIXME(msacm, "(0x%04x, %p, %ld): stub\n",
+    has, pash, fdwUnprepare
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           ACMAPPLICATIONEXIT (MSACM.150)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           ACMHUGEPAGELOCK (MSACM.175)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           ACMHUGEPAGEUNLOCK (MSACM.176)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           ACMOPENCONVERSION (MSACM.200)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           ACMCLOSECONVERSION (MSACM.201)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           ACMCONVERT (MSACM.202)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           ACMCHOOSEFORMAT (MSACM.203)
+ * FIXME
+ *   No documentation found.
+ */
+
+
diff --git a/dlls/msacm32/.cvsignore b/dlls/msacm32/.cvsignore
new file mode 100644
index 0000000..f3c7a7c
--- /dev/null
+++ b/dlls/msacm32/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/dlls/msacm32/Makefile.in b/dlls/msacm32/Makefile.in
new file mode 100644
index 0000000..eb4ca98
--- /dev/null
+++ b/dlls/msacm32/Makefile.in
@@ -0,0 +1,22 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = msacm32
+
+C_SRCS = \
+	builtin.c \
+	driver.c \
+	filter.c \
+	format.c \
+	internal.c \
+	msacm32_main.c \
+	stream.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
+
diff --git a/dlls/msacm32/builtin.c b/dlls/msacm32/builtin.c
new file mode 100644
index 0000000..a3a8779
--- /dev/null
+++ b/dlls/msacm32/builtin.c
@@ -0,0 +1,77 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "driver.h"
+#include "heap.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+
+/***********************************************************************
+ *           MSACM_BuiltinDrivers
+ */
+LONG MSACM_DummyDriverProc(
+   DWORD dwDriverId, HDRVR32 hdrvr, UINT32 msg,
+   LONG lParam1, LONG lParam2); 
+
+WINE_ACMBUILTINDRIVER32 MSACM_BuiltinDrivers32[] = {
+  { "MSACM.dummy", &MSACM_DummyDriverProc },
+  { NULL, NULL }
+};
+
+/***********************************************************************
+ *           MSACM_DummyDriverProc
+ */
+LONG MSACM_DummyDriverProc(
+   DWORD dwDriverId, HDRVR32 hdrvr, UINT32 msg,
+   LONG lParam1, LONG lParam2)
+{
+  switch(msg)
+    {
+    case DRV_LOAD:
+    case DRV_ENABLE:
+    case DRV_OPEN:
+    case DRV_CLOSE:
+    case DRV_DISABLE:
+    case DRV_FREE:
+    case DRV_CONFIGURE:
+    case DRV_QUERYCONFIGURE:
+    case DRV_INSTALL:
+    case DRV_REMOVE:
+    case DRV_EXITSESSION:
+    case DRV_EXITAPPLICATION:
+    case DRV_POWER:
+    case ACMDM_DRIVER_NOTIFY:
+    case ACMDM_DRIVER_DETAILS:
+    case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
+    case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
+    case ACMDM_FORMATTAG_DETAILS:
+    case ACMDM_FORMAT_DETAILS:
+    case ACMDM_FORMAT_SUGGEST:   
+    case ACMDM_FILTERTAG_DETAILS:
+    case ACMDM_FILTER_DETAILS:
+    case ACMDM_STREAM_OPEN:
+    case ACMDM_STREAM_CLOSE:
+    case ACMDM_STREAM_SIZE:
+    case ACMDM_STREAM_CONVERT:
+    case ACMDM_STREAM_RESET:
+    case ACMDM_STREAM_PREPARE:
+    case ACMDM_STREAM_UNPREPARE:
+    case ACMDM_STREAM_UPDATE:
+    default:
+      /* FIXME: DefDriverProc not implemented  */
+#if 0
+      DefDriverProc32(dwDriverId, hdrvr, msg, lParam1, lParam2);
+#endif
+      break;
+    }
+  return 0;
+} 
+
diff --git a/dlls/msacm32/driver.c b/dlls/msacm32/driver.c
new file mode 100644
index 0000000..06fe045
--- /dev/null
+++ b/dlls/msacm32/driver.c
@@ -0,0 +1,349 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "driver.h"
+#include "heap.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+#include "winreg.h"
+
+/***********************************************************************
+ *           acmDriverAddA (MSACM32.2)
+ */
+MMRESULT32 WINAPI acmDriverAdd32A(
+  PHACMDRIVERID32 phadid, HINSTANCE32 hinstModule,
+  LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
+{
+  PWINE_ACMLOCALDRIVER32 pld;
+  if(!phadid)
+    return MMSYSERR_INVALPARAM;
+
+  /* Check if any unknown flags */
+  if(fdwAdd & 
+     ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
+       ACM_DRIVERADDF_GLOBAL))
+    return MMSYSERR_INVALFLAG;
+
+  /* Check if any incompatible flags */
+  if((fdwAdd & ACM_DRIVERADDF_FUNCTION) && 
+     (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
+    return MMSYSERR_INVALFLAG;
+
+  pld = HeapAlloc(MSACM_hHeap32, 0, sizeof(WINE_ACMLOCALDRIVER32));
+  pld->pfnDriverProc = (DRIVERPROC32) 
+    GetProcAddress32(hinstModule, "DriverProc");
+  *phadid = (HACMDRIVERID32) MSACM_RegisterDriver32(NULL, NULL, pld);
+
+  /* FIXME: lParam, dwPriority and fdwAdd ignored */
+
+  return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ *           acmDriverAddW (MSACM32.3)
+ * FIXME
+ *   Not implemented
+ */
+MMRESULT32 WINAPI acmDriverAdd32W(
+  PHACMDRIVERID32 phadid, HINSTANCE32 hinstModule,
+  LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
+{
+  FIXME(msacm, "(%p, 0x%08x, %ld, %ld, %ld): stub\n",
+    phadid, hinstModule, lParam, dwPriority, fdwAdd
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmDriverClose (MSACM32.4)
+ */
+MMRESULT32 WINAPI acmDriverClose32(
+  HACMDRIVER32 had, DWORD fdwClose)
+{
+  PWINE_ACMDRIVER32 p;
+
+  if(fdwClose)
+    return MMSYSERR_INVALFLAG;
+
+  p = MSACM_GetDriver32(had);
+  if(!p)
+    return MMSYSERR_INVALHANDLE;
+
+  p->obj.pACMDriverID->pACMDriver = NULL;
+
+  /* FIXME: CloseDriver32 not implemented */
+#if 0
+  if(p->hDrvr)
+    CloseDriver32(p->hDrvr, 0, 0);
+#endif
+
+  HeapFree(MSACM_hHeap32, 0, p);
+
+  return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ *           acmDriverDetailsA (MSACM32.5)
+ */
+MMRESULT32 WINAPI acmDriverDetails32A(
+  HACMDRIVERID32 hadid, PACMDRIVERDETAILS32A padd, DWORD fdwDetails)
+{
+  PWINE_ACMDRIVERID32 p;
+  MMRESULT32 mmr;
+  BOOL32 bOpenTemporary;
+
+  p = MSACM_GetDriverID32(hadid);
+  if(!p)
+    return MMSYSERR_INVALHANDLE;
+  
+  if(fdwDetails)
+    return MMSYSERR_INVALFLAG;
+
+  bOpenTemporary = !p->pACMDriver;
+  if(bOpenTemporary) {
+    bOpenTemporary = TRUE;
+    acmDriverOpen32((PHACMDRIVER32) &p->pACMDriver, hadid, 0);
+  }
+  
+  /* FIXME
+   *   How does the driver know if the ANSI or 
+   *   the UNICODE variant of PACMDRIVERDETAILS is used?
+   *   It might check cbStruct or does it only accept ANSI.
+   */
+  mmr = (MMRESULT32) acmDriverMessage32(
+    (HACMDRIVER32) p->pACMDriver, ACMDM_DRIVER_DETAILS, 
+    (LPARAM) padd,  0
+  );
+
+  if(bOpenTemporary) {
+    acmDriverClose32((HACMDRIVER32) p->pACMDriver, 0);
+    p->pACMDriver = NULL;
+  }
+
+  return mmr;
+}
+
+/***********************************************************************
+ *           acmDriverDetailsW (MSACM32.6)
+ * FIXME
+ *   Not implemented
+ */
+MMRESULT32 WINAPI acmDriverDetails32W(
+  HACMDRIVERID32 hadid, PACMDRIVERDETAILS32W padd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", hadid, padd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmDriverEnum (MSACM32.7)
+ */
+MMRESULT32 WINAPI acmDriverEnum32(
+  ACMDRIVERENUMCB32 fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  PWINE_ACMDRIVERID32 p;
+
+  if(!fnCallback)
+    {
+      return MMSYSERR_INVALPARAM;
+    }
+
+  if(fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED))
+    {
+      return MMSYSERR_INVALFLAG;
+    }
+
+  p = MSACM_pFirstACMDriverID32;
+  while(p)
+    {
+      (*fnCallback)((HACMDRIVERID32) p, dwInstance, ACMDRIVERDETAILS_SUPPORTF_CODEC);
+      p = p->pNextACMDriverID;
+    }
+
+  return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ *           acmDriverID (MSACM32.8)
+ */
+MMRESULT32 WINAPI acmDriverID32(
+  HACMOBJ32 hao, PHACMDRIVERID32 phadid, DWORD fdwDriverID)
+{
+  PWINE_ACMOBJ32 pao;
+
+  pao = MSACM_GetObj32(hao);
+  if(!pao)
+    return MMSYSERR_INVALHANDLE;
+
+  if(!phadid)
+    return MMSYSERR_INVALPARAM;
+
+  if(fdwDriverID)
+    return MMSYSERR_INVALFLAG;
+
+  *phadid = (HACMDRIVERID32) pao->pACMDriverID;
+
+  return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ *           acmDriverMessage (MSACM32.9)
+ * FIXME
+ *   Not implemented
+ */
+LRESULT WINAPI acmDriverMessage32(
+  HACMDRIVER32 had, UINT32 uMsg, LPARAM lParam1, LPARAM lParam2)
+{
+  PWINE_ACMDRIVER32 pad = MSACM_GetDriver32(had);
+  if(!pad)
+    return MMSYSERR_INVALPARAM;
+
+  /* FIXME: Check if uMsg legal */
+
+  if(!SendDriverMessage32(pad->hDrvr, uMsg, lParam1, lParam2))
+    return MMSYSERR_NOTSUPPORTED;
+
+  return MMSYSERR_NOERROR;
+}
+
+
+/***********************************************************************
+ *           acmDriverOpen (MSACM32.10)
+ */
+MMRESULT32 WINAPI acmDriverOpen32(
+  PHACMDRIVER32 phad, HACMDRIVERID32 hadid, DWORD fdwOpen)
+{
+  PWINE_ACMDRIVERID32 padid;
+
+  if(!phad)
+    return MMSYSERR_INVALPARAM;
+
+  padid = MSACM_GetDriverID32(hadid); 
+  if(!padid)
+    return MMSYSERR_INVALHANDLE;
+
+  if(fdwOpen)
+    return MMSYSERR_INVALFLAG;
+
+  if(padid->pACMDriver)
+    {
+      /* FIXME: Is it allowed? */
+      ERR(msacm, "Can't open driver twice\n");
+      return MMSYSERR_ERROR;
+    }
+
+  padid->pACMDriver = HeapAlloc(
+    MSACM_hHeap32, 0, sizeof(WINE_ACMDRIVER32)
+  );
+  padid->pACMDriver->obj.pACMDriverID = padid;
+  
+  if(!padid->pACMLocalDriver)
+      padid->pACMDriver->hDrvr =
+        OpenDriver32A(padid->pszDriverAlias, "drivers32", 0);
+  else
+    {
+      padid->pACMDriver->hDrvr = MSACM_OpenDriverProc32(
+	padid->pACMLocalDriver->pfnDriverProc
+      );
+    }
+
+  if(!padid->pACMDriver->hDrvr)
+    return MMSYSERR_ERROR;
+ 
+  /* FIXME: Create a WINE_ACMDRIVER32 */
+  *phad = (HACMDRIVER32) NULL;
+
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmDriverPriority (MSACM32.11)
+ */
+MMRESULT32 WINAPI acmDriverPriority32(
+  HACMDRIVERID32 hadid, DWORD dwPriority, DWORD fdwPriority)
+{
+  PWINE_ACMDRIVERID32 padid;
+  CHAR szSubKey[17];
+  CHAR szBuffer[256];
+  LONG lBufferLength = sizeof(szBuffer);
+  LONG lError;
+  HKEY hPriorityKey;
+  DWORD dwPriorityCounter;
+
+  padid = MSACM_GetDriverID32(hadid);
+  if(!padid)
+    return MMSYSERR_INVALHANDLE;
+
+  /* Check for unknown flags */
+  if(fdwPriority & 
+     ~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE|
+       ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END))
+    return MMSYSERR_INVALFLAG;
+
+  /* Check for incompatible flags */
+  if((fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) &&
+    (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE))
+    return MMSYSERR_INVALFLAG;
+
+  /* Check for incompatible flags */
+  if((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) &&
+    (fdwPriority & ACM_DRIVERPRIORITYF_END))
+    return MMSYSERR_INVALFLAG;
+
+  lError = RegOpenKey32A(HKEY_CURRENT_USER, 
+    "Software\\Microsoft\\Multimedia\\"
+      "Audio Compression Manager\\Priority v4.00",
+    &hPriorityKey
+  );
+  /* FIXME: Create key */
+  if(lError != ERROR_SUCCESS)
+    return MMSYSERR_ERROR;
+
+  for(dwPriorityCounter = 1; ; dwPriorityCounter++)
+  {
+    snprintf(szSubKey, 17, "Priorty%ld", dwPriorityCounter);
+    lError = RegQueryValue32A(hPriorityKey, szSubKey, szBuffer, &lBufferLength);
+    if(lError != ERROR_SUCCESS)
+      break;
+
+    FIXME(msacm, "(0x%08x, %ld, %ld): stub (partial)\n", 
+      hadid, dwPriority, fdwPriority
+    );
+    break;
+  }
+
+  RegCloseKey(hPriorityKey);
+
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmDriverRemove (MSACM32.12)
+ */
+MMRESULT32 WINAPI acmDriverRemove32(
+  HACMDRIVERID32 hadid, DWORD fdwRemove)
+{
+  PWINE_ACMDRIVERID32 padid;
+
+  padid = MSACM_GetDriverID32(hadid);
+  if(!padid)
+    return MMSYSERR_INVALHANDLE;
+
+  if(fdwRemove)
+    return MMSYSERR_INVALFLAG;
+
+  MSACM_UnregisterDriver32(padid);
+
+  return MMSYSERR_NOERROR;
+}
+
diff --git a/dlls/msacm32/filter.c b/dlls/msacm32/filter.c
new file mode 100644
index 0000000..45dc02c
--- /dev/null
+++ b/dlls/msacm32/filter.c
@@ -0,0 +1,155 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+
+/***********************************************************************
+ *           acmFilterChooseA (MSACM32.13)
+ */
+MMRESULT32 WINAPI acmFilterChoose32A(
+  PACMFILTERCHOOSE32A pafltrc)
+{
+  FIXME(msacm, "(%p): stub\n", pafltrc);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterChooseW (MSACM32.14)
+ */
+MMRESULT32 WINAPI acmFilterChoose32W(
+  PACMFILTERCHOOSE32W pafltrc)
+{
+  FIXME(msacm, "(%p): stub\n", pafltrc);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterDetailsA (MSACM32.15)
+ */
+MMRESULT32 WINAPI acmFilterDetails32A(
+  HACMDRIVER32 had, PACMFILTERDETAILS32A pafd, DWORD fdwDetails)
+{
+  if(fdwDetails & ~(ACM_FILTERDETAILSF_FILTER))
+    return MMSYSERR_INVALFLAG;
+
+  /* FIXME
+   *   How does the driver know if the ANSI or
+   *   the UNICODE variant of PACMFILTERDETAILS is used?
+   *   It might check cbStruct or does it only accept ANSI.
+   */
+  return (MMRESULT32) acmDriverMessage32(
+    had, ACMDM_FILTER_DETAILS,
+    (LPARAM) pafd,  (LPARAM) fdwDetails
+  );
+}
+
+/***********************************************************************
+ *           acmFilterDetailsW (MSACM32.16)
+ */
+MMRESULT32 WINAPI acmFilterDetails32W(
+  HACMDRIVER32 had, PACMFILTERDETAILS32W pafd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", had, pafd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterEnumA (MSACM32.17)
+ */
+MMRESULT32 WINAPI acmFilterEnum32A(
+  HACMDRIVER32 had, PACMFILTERDETAILS32A pafd, 
+  ACMFILTERENUMCB32A fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, pafd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterEnumW (MSACM32.18)
+ */
+MMRESULT32 WINAPI acmFilterEnum32W(
+  HACMDRIVER32 had, PACMFILTERDETAILS32W pafd, 
+  ACMFILTERENUMCB32W fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, pafd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterTagDetailsA (MSACM32.19)
+ */
+MMRESULT32 WINAPI acmFilterTagDetails32A(
+  HACMDRIVER32 had, PACMFILTERTAGDETAILS32A paftd, DWORD fdwDetails)
+{
+  if(fdwDetails & 
+     ~(ACM_FILTERTAGDETAILSF_FILTERTAG|
+       ACM_FILTERTAGDETAILSF_LARGESTSIZE))
+    return MMSYSERR_INVALFLAG;
+
+  /* FIXME
+   *   How does the driver know if the ANSI or
+   *   the UNICODE variant of PACMFILTERTAGDETAILS is used?
+   *   It might check cbStruct or does it only accept ANSI.
+   */
+  return (MMRESULT32) acmDriverMessage32(
+    had, ACMDM_FILTERTAG_DETAILS,
+    (LPARAM) paftd,  (LPARAM) fdwDetails
+  );
+}
+
+/***********************************************************************
+ *           acmFilterTagDetailsW (MSACM32.20)
+ */
+MMRESULT32 WINAPI acmFilterTagDetails32W(
+  HACMDRIVER32 had, PACMFILTERTAGDETAILS32W paftd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", had, paftd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterTagEnumA (MSACM32.21)
+ */
+MMRESULT32 WINAPI acmFilterTagEnum32A(
+  HACMDRIVER32 had, PACMFILTERTAGDETAILS32A  paftd,
+  ACMFILTERTAGENUMCB32A fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, paftd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFilterTagEnumW (MSACM32.22)
+ */
+MMRESULT32 WINAPI acmFilterTagEnum32W(
+  HACMDRIVER32 had, PACMFILTERTAGDETAILS32W paftd,
+  ACMFILTERTAGENUMCB32W fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, paftd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
diff --git a/dlls/msacm32/format.c b/dlls/msacm32/format.c
new file mode 100644
index 0000000..5495c92
--- /dev/null
+++ b/dlls/msacm32/format.c
@@ -0,0 +1,168 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+
+/***********************************************************************
+ *           acmFormatChooseA (MSACM32.23)
+ */
+MMRESULT32 WINAPI acmFormatChoose32A(
+  PACMFORMATCHOOSE32A pafmtc)
+{
+  FIXME(msacm, "(%p): stub\n", pafmtc);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatChooseW (MSACM32.24)
+ */
+MMRESULT32 WINAPI acmFormatChoose32W(
+  PACMFORMATCHOOSE32W pafmtc)
+{
+  FIXME(msacm, "(%p): stub\n", pafmtc);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatDetailsA (MSACM32.25)
+ */
+MMRESULT32 WINAPI acmFormatDetails32A(
+  HACMDRIVER32 had, PACMFORMATDETAILS32A pafd, DWORD fdwDetails)
+{
+  if(fdwDetails & ~(ACM_FORMATDETAILSF_FORMAT))
+    return MMSYSERR_INVALFLAG;
+
+  /* FIXME
+   *   How does the driver know if the ANSI or
+   *   the UNICODE variant of PACMFORMATDETAILS is used?
+   *   It might check cbStruct or does it only accept ANSI.
+   */
+  return (MMRESULT32) acmDriverMessage32(
+    had, ACMDM_FORMAT_DETAILS,
+    (LPARAM) pafd,  (LPARAM) fdwDetails
+  );
+}
+
+/***********************************************************************
+ *           acmFormatDetailsW (MSACM32.26)
+ */
+MMRESULT32 WINAPI acmFormatDetails32W(
+  HACMDRIVER32 had, PACMFORMATDETAILS32W pafd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", had, pafd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatEnumA (MSACM32.27)
+ */
+MMRESULT32 WINAPI acmFormatEnum32A(
+  HACMDRIVER32 had, PACMFORMATDETAILS32A pafd,
+  ACMFORMATENUMCB32A fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, pafd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatEnumW (MSACM32.28)
+ */
+MMRESULT32 WINAPI acmFormatEnum32W(
+  HACMDRIVER32 had, PACMFORMATDETAILS32W pafd,
+  ACMFORMATENUMCB32W fnCallback, DWORD dwInstance,  DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, pafd, fnCallback, dwInstance, fdwEnum
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatSuggest (MSACM32.29)
+ */
+MMRESULT32 WINAPI acmFormatSuggest32(
+  HACMDRIVER32 had, PWAVEFORMATEX32 pwfxSrc, PWAVEFORMATEX32 pwfxDst,
+  DWORD cbwfxDst, DWORD fdwSuggest)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatTagDetailsA (MSACM32.30)
+ */
+MMRESULT32 WINAPI acmFormatTagDetails32A(
+  HACMDRIVER32 had, PACMFORMATTAGDETAILS32A paftd, DWORD fdwDetails)
+{
+  if(fdwDetails & 
+     ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_LARGESTSIZE))
+    return MMSYSERR_INVALFLAG;
+
+  /* FIXME
+   *   How does the driver know if the ANSI or
+   *   the UNICODE variant of PACMFORMATTAGDETAILS is used?
+   *   It might check cbStruct or does it only accept ANSI.
+   */
+  return (MMRESULT32) acmDriverMessage32(
+    had, ACMDM_FORMATTAG_DETAILS,
+    (LPARAM) paftd,  (LPARAM) fdwDetails
+  );
+}
+
+/***********************************************************************
+ *           acmFormatTagDetailsW (MSACM32.31)
+ */
+MMRESULT32 WINAPI acmFormatTagDetails32W(
+  HACMDRIVER32 had, PACMFORMATTAGDETAILS32W paftd, DWORD fdwDetails)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", had, paftd, fdwDetails);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatTagEnumA (MSACM32.32)
+ */
+MMRESULT32 WINAPI acmFormatTagEnum32A(
+  HACMDRIVER32 had, PACMFORMATTAGDETAILS32A paftd,
+  ACMFORMATTAGENUMCB32A fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, paftd, fnCallback, dwInstance, fdwEnum
+  ); 
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmFormatTagEnumW (MSACM32.33)
+ */
+MMRESULT32 WINAPI acmFormatTagEnum32W(
+  HACMDRIVER32 had, PACMFORMATTAGDETAILS32W paftd,
+  ACMFORMATTAGENUMCB32W fnCallback, DWORD dwInstance, DWORD fdwEnum)
+{
+  FIXME(msacm, "(0x%08x, %p, %p, %ld, %ld): stub\n",
+    had, paftd, fnCallback, dwInstance, fdwEnum
+  ); 
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
diff --git a/dlls/msacm32/internal.c b/dlls/msacm32/internal.c
new file mode 100644
index 0000000..3c5bc26
--- /dev/null
+++ b/dlls/msacm32/internal.c
@@ -0,0 +1,196 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "driver.h"
+#include "heap.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+
+/**********************************************************************/
+
+HANDLE32 MSACM_hHeap32 = (HANDLE32) NULL;
+PWINE_ACMDRIVERID32 MSACM_pFirstACMDriverID32 = NULL;
+PWINE_ACMDRIVERID32 MSACM_pLastACMDriverID32 = NULL;
+
+/***********************************************************************
+ *           MSACM_RegisterDriver32() 
+ */
+PWINE_ACMDRIVERID32 MSACM_RegisterDriver32(
+  LPSTR pszDriverAlias, LPSTR pszFileName,
+  PWINE_ACMLOCALDRIVER32 pLocalDriver)
+{
+  PWINE_ACMDRIVERID32 padid;
+  padid = (PWINE_ACMDRIVERID32) HeapAlloc(
+    MSACM_hHeap32, 0, sizeof(WINE_ACMDRIVERID32)
+  );
+  padid->pszDriverAlias = 
+    HEAP_strdupA(MSACM_hHeap32, 0, pszDriverAlias);
+  padid->pszFileName = 
+    HEAP_strdupA(MSACM_hHeap32, 0, pszFileName);
+  padid->pACMLocalDriver = pLocalDriver; 
+  padid->bEnabled = TRUE;
+  padid->pACMDriver = NULL;
+  padid->pNextACMDriverID = NULL;
+  padid->pPreviousACMDriverID = 
+    MSACM_pLastACMDriverID32;
+  MSACM_pLastACMDriverID32 = padid;
+  if(!MSACM_pFirstACMDriverID32)
+    MSACM_pFirstACMDriverID32 = padid;
+
+  return padid;
+}
+
+/***********************************************************************
+ *           MSACM_RegisterAllDrivers32() 
+ */
+void MSACM_RegisterAllDrivers32()
+{
+  PWINE_ACMBUILTINDRIVER32 pbd;
+  LPSTR pszBuffer;
+  DWORD dwBufferLength;
+
+  /* FIXME 
+   *  What if the user edits system.ini while the program is running?
+   *  Does Windows handle that?
+   */
+  if(!MSACM_pFirstACMDriverID32)
+    return;
+
+  /* FIXME: Do not work! How do I determine the section length? */
+  dwBufferLength = 
+    GetPrivateProfileSection32A("drivers32", NULL, 0, "system.ini");
+
+  pszBuffer = (LPSTR) HeapAlloc(
+    MSACM_hHeap32, 0, dwBufferLength
+  );
+  if(GetPrivateProfileSection32A(
+    "drivers32", pszBuffer, dwBufferLength, "system.ini"))
+    {
+      char *s = pszBuffer;
+      while(*s)
+	{
+	  if(!lstrncmpi32A("MSACM.", s, 6))
+	    {
+	      char *s2 = s;
+	      while(*s2 != '\0' && *s2 != '=') s2++;
+	      if(*s2)
+		{
+		  *s2++='\0';
+		  MSACM_RegisterDriver32(s, s2, NULL);
+		}
+	    }  
+	  s += lstrlen32A(s) + 1; /* Either next char or \0 */
+	}
+    }
+
+  /* FIXME
+   *   Check if any of the builtin driver was added
+   *   when the external drivers was. 
+   */
+
+  pbd = MSACM_BuiltinDrivers32;
+  while(pbd->pszDriverAlias)
+    {
+      PWINE_ACMLOCALDRIVER32 pld;
+      pld = HeapAlloc(MSACM_hHeap32, 0, sizeof(WINE_ACMLOCALDRIVER32));
+      pld->pfnDriverProc = pbd->pfnDriverProc;
+      MSACM_RegisterDriver32(pbd->pszDriverAlias, NULL, pld);
+      pbd++;
+    }
+   HeapFree(MSACM_hHeap32, 0, pszBuffer);
+}
+
+/***********************************************************************
+ *           MSACM_UnregisterDriver32()
+ */
+PWINE_ACMDRIVERID32 MSACM_UnregisterDriver32(PWINE_ACMDRIVERID32 p)
+{
+  PWINE_ACMDRIVERID32 pNextACMDriverID;
+
+  if(p->pACMDriver)
+    acmDriverClose32((HACMDRIVER32) p->pACMDriver, 0);
+
+  if(p->pszDriverAlias)
+    HeapFree(MSACM_hHeap32, 0, p->pszDriverAlias);
+  if(p->pszFileName)
+    HeapFree(MSACM_hHeap32, 0, p->pszFileName);
+  if(p->pACMLocalDriver)
+    HeapFree(MSACM_hHeap32, 0, p->pACMLocalDriver);
+
+  if(p->pPreviousACMDriverID)
+    p->pPreviousACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
+  if(p->pNextACMDriverID)
+    p->pNextACMDriverID->pPreviousACMDriverID = p->pPreviousACMDriverID;
+
+  pNextACMDriverID = p->pNextACMDriverID;
+
+  HeapFree(MSACM_hHeap32, 0, p);
+
+  return pNextACMDriverID;
+}
+
+/***********************************************************************
+ *           MSACM_UnregisterAllDrivers32()
+ * FIXME
+ *   Where should this function be called?
+ */
+void MSACM_UnregisterAllDrivers32()
+{
+  PWINE_ACMDRIVERID32 p = MSACM_pFirstACMDriverID32;
+  while(p) p = MSACM_UnregisterDriver32(p);
+}
+
+/***********************************************************************
+ *           MSACM_GetDriverID32() 
+ */
+PWINE_ACMDRIVERID32 MSACM_GetDriverID32(HACMDRIVERID32 hDriverID)
+{
+  return (PWINE_ACMDRIVERID32) hDriverID;
+}
+
+/***********************************************************************
+ *           MSACM_GetDriver32()
+ */
+PWINE_ACMDRIVER32 MSACM_GetDriver32(HACMDRIVER32 hDriver)
+{
+  return (PWINE_ACMDRIVER32) hDriver;
+}
+
+/***********************************************************************
+ *           MSACM_GetObj32()
+ */
+PWINE_ACMOBJ32 MSACM_GetObj32(HACMOBJ32 hObj)
+{
+  return (PWINE_ACMOBJ32) hObj;
+}
+
+/***********************************************************************
+ *           MSACM_OpenDriverProc32
+ * FIXME
+ *  This function should be integrated with OpenDriver,
+ *  renamed and moved there.
+ */
+HDRVR32 MSACM_OpenDriverProc32(DRIVERPROC32 pfnDriverProc)
+{
+  LPDRIVERITEM32A pDrvr;
+
+  /* FIXME: This is a very bad solution */
+  pDrvr = (LPDRIVERITEM32A) HeapAlloc(MSACM_hHeap32, HEAP_ZERO_MEMORY, sizeof(DRIVERITEM32A));
+  pDrvr->count = 1;
+  pDrvr->driverproc = pfnDriverProc;
+  
+  /* FIXME: Send DRV_OPEN among others to DriverProc */
+
+  return (HDRVR32) pDrvr;
+}
+
+
+
diff --git a/dlls/msacm32/msacm32_main.c b/dlls/msacm32/msacm32_main.c
new file mode 100644
index 0000000..f1dc476
--- /dev/null
+++ b/dlls/msacm32/msacm32_main.c
@@ -0,0 +1,131 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+#include "winversion.h"
+
+/**********************************************************************/
+
+static DWORD MSACM_dwProcessesAttached32 = 0;
+
+/***********************************************************************
+ *           MSACM_LibMain32 (MSACM32.init) 
+ */
+BOOL32 WINAPI MSACM32_LibMain(
+  HINSTANCE32 hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+  switch(fdwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+      if(MSACM_dwProcessesAttached32 == 0)
+	{
+	  MSACM_hHeap32 = HeapCreate(0, 0x10000, 0);
+	  MSACM_RegisterAllDrivers32();
+	}
+      MSACM_dwProcessesAttached32++;
+      break;
+    case DLL_PROCESS_DETACH:
+      MSACM_dwProcessesAttached32--;
+      if(MSACM_dwProcessesAttached32 == 0)
+	{
+	  MSACM_UnregisterAllDrivers32();
+	  HeapDestroy(MSACM_hHeap32);
+	  MSACM_hHeap32 = (HANDLE32) NULL;
+	}
+      break;
+    case DLL_THREAD_ATTACH:
+      break;
+    case DLL_THREAD_DETACH:
+      break;
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+/***********************************************************************
+ *           XRegThunkEntry (MSACM32.1)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           acmGetVersion32 (MSACM32.34)
+ */
+DWORD WINAPI acmGetVersion32()
+{
+  switch(VERSION_GetVersion()) 
+    {
+    default: 
+      FIXME(msacm, "%s not supported\n", VERSION_GetVersionName());
+    case WIN95:
+      return 0x04000000; /* 4.0.0 */
+    case NT40:
+      return 0x04000565; /* 4.0.1381 */
+    }
+}
+
+/***********************************************************************
+ *           acmMessage32 (MSACM32.35)
+ * FIXME
+ *   No documentation found.
+ */
+
+/***********************************************************************
+ *           acmMetrics (MSACM32.36)
+ */
+MMRESULT32 WINAPI acmMetrics32(
+  HACMOBJ32 hao, UINT32 uMetric, LPVOID  pMetric)
+{
+  PWINE_ACMOBJ32 pao = MSACM_GetObj32(hao);
+  BOOL32 bLocal = TRUE;
+
+  FIXME(msacm, "(0x%08x, %d, %p): stub\n", hao, uMetric, pMetric);
+
+  switch(uMetric)
+    {
+    case ACM_METRIC_COUNT_DRIVERS:
+      bLocal = FALSE;
+    case ACM_METRIC_COUNT_LOCAL_DRIVERS:
+      if(!pao)
+	return MMSYSERR_INVALHANDLE;  
+      return MMSYSERR_NOTSUPPORTED;
+    case ACM_METRIC_COUNT_CODECS:
+      bLocal = FALSE;
+    case ACM_METRIC_COUNT_LOCAL_CODECS:
+      return MMSYSERR_NOTSUPPORTED;
+    case ACM_METRIC_COUNT_CONVERTERS:
+      bLocal = FALSE;
+    case ACM_METRIC_COUNT_LOCAL_CONVERTERS:
+      return MMSYSERR_NOTSUPPORTED;
+    case ACM_METRIC_COUNT_FILTERS:
+      bLocal = FALSE;
+    case ACM_METRIC_COUNT_LOCAL_FILTERS:
+      return MMSYSERR_NOTSUPPORTED;
+    case ACM_METRIC_COUNT_DISABLED:
+      bLocal = FALSE;
+    case ACM_METRIC_COUNT_LOCAL_DISABLED:
+      if(!pao)
+	return MMSYSERR_INVALHANDLE;  
+      return MMSYSERR_NOTSUPPORTED;
+    case ACM_METRIC_COUNT_HARDWARE:
+    case ACM_METRIC_HARDWARE_WAVE_INPUT:
+    case ACM_METRIC_HARDWARE_WAVE_OUTPUT:
+    case ACM_METRIC_MAX_SIZE_FORMAT:
+    case ACM_METRIC_MAX_SIZE_FILTER:
+    case ACM_METRIC_DRIVER_SUPPORT:
+    case ACM_METRIC_DRIVER_PRIORITY:
+    default:
+      return MMSYSERR_NOTSUPPORTED;
+    }
+  return MMSYSERR_NOERROR;
+}
diff --git a/dlls/msacm32/stream.c b/dlls/msacm32/stream.c
new file mode 100644
index 0000000..2a29faa
--- /dev/null
+++ b/dlls/msacm32/stream.c
@@ -0,0 +1,114 @@
+/*
+ *      MSACM32 library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winerror.h"
+#include "wintypes.h"
+#include "debug.h"
+#include "mmsystem.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+
+/***********************************************************************
+ *           acmStreamClose (MSACM32.37)
+ */
+MMRESULT32 WINAPI acmStreamClose32(
+  HACMSTREAM32 has, DWORD fdwClose)
+{
+  FIXME(msacm, "(0x%08x, %ld): stub\n", has, fdwClose);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmStreamConvert (MSACM32.38)
+ */
+MMRESULT32 WINAPI acmStreamConvert32(
+  HACMSTREAM32 has, PACMSTREAMHEADER32 pash, DWORD fdwConvert)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", has, pash, fdwConvert);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmStreamMessage (MSACM32.39)
+ */
+MMRESULT32 WINAPI acmStreamMessage32(
+  HACMSTREAM32 has, UINT32 uMsg, LPARAM lParam1, LPARAM lParam2)
+{
+  FIXME(msacm, "(0x%08x, %u, %ld, %ld): stub\n",
+    has, uMsg, lParam1, lParam2
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmStreamOpen (MSACM32.40)
+ */
+MMRESULT32 WINAPI acmStreamOpen32(
+  PHACMSTREAM32 phas, HACMDRIVER32 had, PWAVEFORMATEX32 pwfxSrc,
+  PWAVEFORMATEX32 pwfxDst, PWAVEFILTER32 pwfltr, DWORD dwCallback,
+  DWORD dwInstance, DWORD fdwOpen)
+{
+  FIXME(msacm, "(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld): stub\n",
+    phas, had, pwfxSrc, pwfxDst, pwfltr,
+    dwCallback, dwInstance, fdwOpen
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+
+/***********************************************************************
+ *           acmStreamPrepareHeader (MSACM32.41)
+ */
+MMRESULT32 WINAPI acmStreamPrepareHeader32(
+  HACMSTREAM32 has, PACMSTREAMHEADER32 pash, DWORD fdwPrepare)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n", has, pash, fdwPrepare);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmStreamReset (MSACM32.42)
+ */
+MMRESULT32 WINAPI acmStreamReset32(
+  HACMSTREAM32 has, DWORD fdwReset)
+{
+  FIXME(msacm, "(0x%08x, %ld): stub\n", has, fdwReset);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmStreamSize (MSACM32.43)
+ */
+MMRESULT32 WINAPI acmStreamSize32(
+  HACMSTREAM32 has, DWORD cbInput, 
+  LPDWORD pdwOutputBytes, DWORD fdwSize)
+{
+  FIXME(msacm, "(0x%08x, %ld, %p, %ld): stub\n",
+    has, cbInput, pdwOutputBytes, fdwSize
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}
+
+/***********************************************************************
+ *           acmStreamUnprepareHeader (MSACM32.44)
+ */
+MMRESULT32 WINAPI acmStreamUnprepareHeader32(
+  HACMSTREAM32 has, PACMSTREAMHEADER32 pash, DWORD fdwUnprepare)
+{
+  FIXME(msacm, "(0x%08x, %p, %ld): stub\n",
+    has, pash, fdwUnprepare
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return MMSYSERR_ERROR;
+}