diff --git a/Makefile.in b/Makefile.in
index a268e97a80d4d7da5c30aa0d3a3a2bc3015bff28..6f8cfe575547f185ab84a6035e6cacb2da6abb1d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -71,6 +71,8 @@ LIBSUBDIRS = \
 	dlls/winmm/mcicda \
 	dlls/winmm/mciseq \
 	dlls/winmm/mciwave \
+	dlls/winmm/midimap \
+	dlls/winmm/wavemap \
 	dlls/winmm/wineoss \
 	dlls/winspool \
 	dlls/wnaspi32 \
@@ -170,13 +172,15 @@ LIBOBJS = \
 	dlls/winaspi/winaspi.o \
 	dlls/windebug/windebug.o \
 	dlls/wing/wing.o \
+	dlls/winmm/winmm.o \
 	dlls/winmm/mcianim/mcianim.drv.o \
 	dlls/winmm/mciavi/mciavi.drv.o \
 	dlls/winmm/mcicda/mcicda.drv.o \
 	dlls/winmm/mciseq/mciseq.drv.o \
 	dlls/winmm/mciwave/mciwave.drv.o \
+	dlls/winmm/midimap/midimap.drv.o \
+	dlls/winmm/wavemap/msacm.drv.o \
 	dlls/winmm/wineoss/wineoss.o \
-	dlls/winmm/winmm.o \
 	dlls/winspool/winspool.o \
 	dlls/wnaspi32/wnaspi32.o \
 	files/files.o \
diff --git a/configure b/configure
index f083a6281bb63a770ee86dca675d2dd37cd9d84e..49cbdfc5eb478a1485e18d23346d7a95151f205c 100755
--- a/configure
+++ b/configure
@@ -5673,6 +5673,8 @@ dlls/winmm/mciavi/Makefile
 dlls/winmm/mcicda/Makefile
 dlls/winmm/mciseq/Makefile
 dlls/winmm/mciwave/Makefile
+dlls/winmm/midimap/Makefile
+dlls/winmm/wavemap/Makefile
 dlls/winmm/wineoss/Makefile
 dlls/winspool/Makefile
 dlls/wnaspi32/Makefile
@@ -5874,6 +5876,8 @@ dlls/winmm/mciavi/Makefile
 dlls/winmm/mcicda/Makefile
 dlls/winmm/mciseq/Makefile
 dlls/winmm/mciwave/Makefile
+dlls/winmm/midimap/Makefile
+dlls/winmm/wavemap/Makefile
 dlls/winmm/wineoss/Makefile
 dlls/winspool/Makefile
 dlls/wnaspi32/Makefile
diff --git a/configure.in b/configure.in
index 33075bf2aea6bf7310d316d60b25d71dca14792b..d15357caa8c7d44af9fc813b5dbd81a583936d09 100644
--- a/configure.in
+++ b/configure.in
@@ -880,6 +880,8 @@ dlls/winmm/mciavi/Makefile
 dlls/winmm/mcicda/Makefile
 dlls/winmm/mciseq/Makefile
 dlls/winmm/mciwave/Makefile
+dlls/winmm/midimap/Makefile
+dlls/winmm/wavemap/Makefile
 dlls/winmm/wineoss/Makefile
 dlls/winspool/Makefile
 dlls/wnaspi32/Makefile
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 1df8185388085cef068b5d58aa68c2b9ea5f6bf0..0efcaf5668ef04b3b4cea15006f4918ca32f4cb0 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -6,6 +6,7 @@ SUBDIRS = \
 	crtdll \
 	dciman32 \
 	dplayx \
+	dsound \
 	imagehlp \
 	imm32 \
 	lzexpand \
@@ -32,6 +33,7 @@ SUBDIRS = \
 	winaspi \
 	windebug \
 	wing \
+	winmm \
 	winspool \
 	wnaspi32
 
diff --git a/dlls/winmm/midimap/.cvsignore b/dlls/winmm/midimap/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..7c829838d67b8b9e09d8b4e5d3f4e53dc07ab2f6
--- /dev/null
+++ b/dlls/winmm/midimap/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+midimap.spec.c
diff --git a/dlls/winmm/midimap/Makefile.in b/dlls/winmm/midimap/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..6d587abfd25b91991ff2b55c50244cf5294b72d8
--- /dev/null
+++ b/dlls/winmm/midimap/Makefile.in
@@ -0,0 +1,21 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = midimap.drv
+
+SPEC_SRCS = \
+	midimap.spec
+
+C_SRCS = \
+	midimap.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+call32.s: $(BUILD)
+	$(BUILD) @BUILDFLAGS@ -o $@ -call32
+
+### Dependencies:
diff --git a/dlls/winmm/midimap/midimap.c b/dlls/winmm/midimap/midimap.c
new file mode 100644
index 0000000000000000000000000000000000000000..42a7525553d90400a9cc3f6d41b5c1aaf45f5a31
--- /dev/null
+++ b/dlls/winmm/midimap/midimap.c
@@ -0,0 +1,284 @@
+/* -*- tab-width: 8; c-basic-offset: 4 -*- */
+/*				   
+ * Wine Midi mapper driver
+ *
+ * Copyright 	1999 Eric Pouech
+ */
+
+#include "winuser.h"
+#include "driver.h"
+#include "mmddk.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(msacm)
+
+typedef	struct tagMIDIMAPDATA {
+    HMIDI	hMidi;
+} MIDIMAPDATA;
+
+/*======================================================================*
+ *                  MIDI OUT part                                       *
+ *======================================================================*/
+
+static	DWORD	modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
+{
+    UINT 		nd = midiOutGetNumDevs();
+    UINT		i;
+    MIDIMAPDATA*	mom = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
+
+    TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
+
+    for (i = 0; i < nd; i++) {
+	if (midiOutOpen(&mom->hMidi, i, lpDesc->dwCallback, 
+			lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
+	    lpDesc->hMidi = mom->hMidi;
+	    *lpdwUser = (DWORD)mom;
+	    return MMSYSERR_NOERROR;
+	}
+    }
+    HeapFree(GetProcessHeap(), 0, mom);
+    return MMSYSERR_ALLOCATED;
+}
+
+static	DWORD	modClose(MIDIMAPDATA* mom)
+{
+    DWORD ret = midiOutClose(mom->hMidi);
+    if (ret == MMSYSERR_NOERROR)
+	HeapFree(GetProcessHeap(), 0, mom);
+    return ret;
+}
+
+static	DWORD	modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+{
+    return midiOutLongMsg(mom->hMidi, lpMidiHdr, dwParam2);
+}
+
+static	DWORD	modData(MIDIMAPDATA* mom, DWORD dwParam)
+{
+    return midiOutShortMsg(mom->hMidi, dwParam);
+}
+
+static	DWORD	modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+{
+    return midiOutPrepareHeader(mom->hMidi, lpMidiHdr, dwParam2);
+}
+
+static	DWORD	modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+{
+    return midiOutUnprepareHeader(mom->hMidi, lpMidiHdr, dwParam2);
+}
+
+static	DWORD	modGetDevCaps(MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD dwParam2)
+{
+    return midiOutGetDevCapsA(mom->hMidi, lpMidiCaps, dwParam2);
+}
+
+static	DWORD	modGetVolume(MIDIMAPDATA* mom, LPDWORD lpVol)
+{
+    return midiOutGetVolume(mom->hMidi, lpVol);
+}
+
+static	DWORD	modSetVolume(MIDIMAPDATA* mom, DWORD vol)
+{
+    return midiOutSetVolume(mom->hMidi, vol);
+}
+
+static	DWORD	modReset(MIDIMAPDATA* mom)
+{
+    return midiOutReset(mom->hMidi);
+}
+
+/**************************************************************************
+ * 				MIDIMAP_modMessage	[sample driver]
+ */
+DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
+				DWORD dwParam1, DWORD dwParam2)
+{
+    TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
+	  wDevID, wMsg, dwUser, dwParam1, dwParam2);
+    
+    switch (wMsg) {
+    case DRVM_INIT:
+    case DRVM_EXIT:
+    case DRVM_ENABLE:
+    case DRVM_DISABLE:
+	/* FIXME: Pretend this is supported */
+	return 0;
+
+    case MODM_OPEN:	 	return modOpen		((LPDWORD)dwUser,      (LPMIDIOPENDESC)dwParam1,dwParam2);
+    case MODM_CLOSE:	 	return modClose		((MIDIMAPDATA*)dwUser);
+
+    case MODM_DATA:		return modData		((MIDIMAPDATA*)dwUser, dwParam1);
+    case MODM_LONGDATA:		return modLongData      ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1,     dwParam2);
+    case MODM_PREPARE:	 	return modPrepare	((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, 	dwParam2);
+    case MODM_UNPREPARE: 	return modUnprepare	((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, 	dwParam2);
+
+    case MODM_GETDEVCAPS:	return modGetDevCaps	((MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2);
+    case MODM_GETNUMDEVS:	return 1;
+    case MODM_GETVOLUME:	return modGetVolume	((MIDIMAPDATA*)dwUser, (LPDWORD)dwParam1);
+    case MODM_SETVOLUME:	return modSetVolume	((MIDIMAPDATA*)dwUser, dwParam1);
+    case MODM_RESET:		return modReset		((MIDIMAPDATA*)dwUser);
+    default:
+	FIXME("unknown message %d!\n", wMsg);
+    }
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+/*======================================================================*
+ *                  MIDI IN part                                        *
+ *======================================================================*/
+
+static	DWORD	midOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
+{
+    UINT 		nd = midiInGetNumDevs();
+    UINT		i;
+    MIDIMAPDATA*	wim = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
+
+    TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
+
+    for (i = 0; i < nd; i++) {
+	if (midiInOpen(&wim->hMidi, i, lpDesc->dwCallback, 
+			lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
+	    lpDesc->hMidi = wim->hMidi;
+	    *lpdwUser = (DWORD)wim;
+	    return MMSYSERR_NOERROR;
+	}
+    }
+    HeapFree(GetProcessHeap(), 0, wim);
+    return MMSYSERR_ALLOCATED;
+}
+
+static	DWORD	midClose(MIDIMAPDATA* wim)
+{
+    DWORD ret = midiInClose(wim->hMidi);
+    if (ret == MMSYSERR_NOERROR)
+	HeapFree(GetProcessHeap(), 0, wim);
+    return ret;
+}
+
+static	DWORD	midAddBuffer(MIDIMAPDATA* wim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+{
+    return midiInAddBuffer(wim->hMidi, lpMidiHdr, dwParam2);
+}
+
+static	DWORD	midPrepare(MIDIMAPDATA* wim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+{
+    return midiInPrepareHeader(wim->hMidi, lpMidiHdr, dwParam2);
+}
+
+static	DWORD	midUnprepare(MIDIMAPDATA* wim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+{
+    return midiInUnprepareHeader(wim->hMidi, lpMidiHdr, dwParam2);
+}
+
+static	DWORD	midGetDevCaps(MIDIMAPDATA* wim, LPMIDIINCAPSA lpMidiCaps, DWORD dwParam2)
+{
+    return midiInGetDevCapsA(wim->hMidi, lpMidiCaps, dwParam2);
+}
+
+static	DWORD	midStop(MIDIMAPDATA* wim)
+{
+    return midiInStop(wim->hMidi);
+}
+
+static	DWORD	midStart(MIDIMAPDATA* wim)
+{
+    return midiInStart(wim->hMidi);
+}
+
+static	DWORD	midReset(MIDIMAPDATA* wim)
+{
+    return midiInReset(wim->hMidi);
+}
+
+/**************************************************************************
+ * 				MIDIMAP_midMessage	[sample driver]
+ */
+DWORD WINAPI MIDIMAP_midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+				DWORD dwParam1, DWORD dwParam2)
+{
+    TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
+	  wDevID, wMsg, dwUser, dwParam1, dwParam2);
+
+    switch (wMsg) {
+    case DRVM_INIT:
+    case DRVM_EXIT:
+    case DRVM_ENABLE:
+    case DRVM_DISABLE:
+	/* FIXME: Pretend this is supported */
+	return 0;
+
+    case MIDM_OPEN:		return midOpen          ((LPDWORD)dwUser,     (LPMIDIOPENDESC)dwParam1, dwParam2);
+    case MIDM_CLOSE:		return midClose         ((MIDIMAPDATA*)dwUser);
+
+    case MIDM_ADDBUFFER:	return midAddBuffer     ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
+    case MIDM_PREPARE:		return midPrepare       ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
+    case MIDM_UNPREPARE:	return midUnprepare     ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
+    case MIDM_GETDEVCAPS:	return midGetDevCaps    ((MIDIMAPDATA*)dwUser, (LPMIDIINCAPSA)dwParam1, dwParam2);
+    case MIDM_GETNUMDEVS:	return 1;
+    case MIDM_RESET:		return midReset         ((MIDIMAPDATA*)dwUser);
+    case MIDM_START:		return midStart         ((MIDIMAPDATA*)dwUser);
+    case MIDM_STOP:		return midStop          ((MIDIMAPDATA*)dwUser);
+    default:
+	FIXME("unknown message %u!\n", wMsg);
+    }
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+/*======================================================================*
+ *                  Driver part                                         *
+ *======================================================================*/
+
+static	struct WINE_MIDIMAP* oss = NULL;
+
+/**************************************************************************
+ * 				MIDIMAP_drvOpen			[internal]	
+ */
+static	DWORD	MIDIMAP_drvOpen(LPSTR str)
+{
+    if (oss)
+	return 0;
+    
+    /* I know, this is ugly, but who cares... */
+    oss = (struct WINE_MIDIMAP*)1;
+    return 1;
+}
+
+/**************************************************************************
+ * 				MIDIMAP_drvClose		[internal]	
+ */
+static	DWORD	MIDIMAP_drvClose(DWORD dwDevID)
+{
+    if (oss) {
+	oss = NULL;
+	return 1;
+    }
+    return 0;
+}
+
+/**************************************************************************
+ * 				MIDIMAP_DriverProc		[internal]
+ */
+LONG CALLBACK	MIDIMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
+				   DWORD dwParam1, DWORD dwParam2)
+{
+/* EPP     TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",  */
+/* EPP 	  dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
+    
+    switch(wMsg) {
+    case DRV_LOAD:		return 1;
+    case DRV_FREE:		return 1;
+    case DRV_OPEN:		return MIDIMAP_drvOpen((LPSTR)dwParam1);
+    case DRV_CLOSE:		return MIDIMAP_drvClose(dwDevID);
+    case DRV_ENABLE:		return 1;
+    case DRV_DISABLE:		return 1;
+    case DRV_QUERYCONFIGURE:	return 1;
+    case DRV_CONFIGURE:		MessageBoxA(0, "MIDIMAP MultiMedia Driver !", "OSS Driver", MB_OK);	return 1;
+    case DRV_INSTALL:		return DRVCNF_RESTART;
+    case DRV_REMOVE:		return DRVCNF_RESTART;
+    default:
+	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+    }
+}
+
+
diff --git a/dlls/winmm/midimap/midimap.spec b/dlls/winmm/midimap/midimap.spec
new file mode 100644
index 0000000000000000000000000000000000000000..22c525332614ee1f4f4b13a5669546205ba3a744
--- /dev/null
+++ b/dlls/winmm/midimap/midimap.spec
@@ -0,0 +1,7 @@
+name midimap
+file midimap.drv
+type win32
+
+  1 stdcall DriverProc(long long long long long) MIDIMAP_DriverProc
+  2 stdcall midMessage(long long long long long) MIDIMAP_midMessage
+  3 stdcall modMessage(long long long long long) MIDIMAP_modMessage
diff --git a/dlls/winmm/wavemap/.cvsignore b/dlls/winmm/wavemap/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..313661889f4e449e63e03b8dea14663980528f11
--- /dev/null
+++ b/dlls/winmm/wavemap/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+msacm.spec.c
diff --git a/dlls/winmm/wavemap/Makefile.in b/dlls/winmm/wavemap/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..7b3569827607f70e3d696b3d50aab51a6ef9cff8
--- /dev/null
+++ b/dlls/winmm/wavemap/Makefile.in
@@ -0,0 +1,21 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = msacm.drv
+
+SPEC_SRCS = \
+	msacm.spec
+
+C_SRCS = \
+	wavemap.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+call32.s: $(BUILD)
+	$(BUILD) @BUILDFLAGS@ -o $@ -call32
+
+### Dependencies:
diff --git a/dlls/winmm/wavemap/msacm.spec b/dlls/winmm/wavemap/msacm.spec
new file mode 100644
index 0000000000000000000000000000000000000000..19fbf328fec84619ccfa9b13639f0a3683efbf11
--- /dev/null
+++ b/dlls/winmm/wavemap/msacm.spec
@@ -0,0 +1,7 @@
+name msacmmap
+file msacm.drv
+type win32
+
+  1 stdcall DriverProc(long long long long long) WAVEMAP_DriverProc
+  2 stdcall widMessage(long long long long long) WAVEMAP_widMessage
+  3 stdcall wodMessage(long long long long long) WAVEMAP_wodMessage
diff --git a/dlls/winmm/wavemap/wavemap.c b/dlls/winmm/wavemap/wavemap.c
new file mode 100644
index 0000000000000000000000000000000000000000..9dbcf06a96fa8eac1e74846a397145318e5cfcfd
--- /dev/null
+++ b/dlls/winmm/wavemap/wavemap.c
@@ -0,0 +1,501 @@
+/* -*- tab-width: 8; c-basic-offset: 4 -*- */
+/*				   
+ * Wine Wave mapper driver
+ *
+ * Copyright 	1999 Eric Pouech
+ */
+
+/* TODOs
+ *	+ implement wavein as waveout has been implemented
+ *	+ better protection against evilish dwUser parameters
+ *	+ use asynchronous ACM conversion
+ */
+
+#include "winuser.h"
+#include "driver.h"
+#include "mmddk.h"
+#include "msacm.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(msacm)
+
+typedef	struct tagWAVEMAPDATA {
+    HWAVE	hWave;
+    HACMSTREAM	hAcmStream;
+    /* needed data to filter callbacks. Only needed when hAcmStream is not 0 */
+    DWORD	dwCallback;
+    DWORD	dwClientInstance;
+    DWORD	dwFlags;
+    MMRESULT (WINAPI *acmStreamOpen)(LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD);
+    MMRESULT (WINAPI *acmStreamClose)(HACMSTREAM, DWORD);
+    MMRESULT (WINAPI *acmStreamSize)(HACMSTREAM, DWORD, LPDWORD, DWORD);
+    MMRESULT (WINAPI *acmStreamConvert)(HACMSTREAM, PACMSTREAMHEADER, DWORD);
+    MMRESULT (WINAPI *acmStreamPrepareHeader)(HACMSTREAM, PACMSTREAMHEADER, DWORD);
+    MMRESULT (WINAPI *acmStreamUnprepareHeader)(HACMSTREAM, PACMSTREAMHEADER, DWORD);
+} WAVEMAPDATA;
+
+/*======================================================================*
+ *                  WAVE OUT part                                       *
+ *======================================================================*/
+
+static void	CALLBACK WAVEMAP_DstCallback(HDRVR hDev, UINT uMsg, DWORD dwInstance, 
+					     DWORD dwParam1, DWORD dwParam2)
+{
+    WAVEMAPDATA*	wom = (WAVEMAPDATA*)dwInstance;
+
+    TRACE("(0x%x %u %ld %ld %ld);\n", hDev, uMsg, dwInstance, dwParam1, dwParam2);
+
+    switch (uMsg) {
+    case WOM_OPEN:
+    case WOM_CLOSE:
+	/* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
+	break;
+    case WOM_DONE:
+	{
+	    LPWAVEHDR		lpWaveHdrDst = (LPWAVEHDR)dwParam1;
+	    PACMSTREAMHEADER	ash = (PACMSTREAMHEADER)((LPSTR)lpWaveHdrDst - sizeof(ACMSTREAMHEADER));
+	    LPWAVEHDR		lpWaveHdrSrc = (LPWAVEHDR)ash->dwUser;
+
+	    lpWaveHdrSrc->dwFlags &= ~WHDR_INQUEUE;
+	    lpWaveHdrSrc->dwFlags |= WHDR_DONE;
+	    dwParam1 = (DWORD)lpWaveHdrSrc;
+	}
+	break;
+    default:
+	ERR("Unknown msg %u\n", uMsg);
+    }
+
+    DriverCallback(wom->dwCallback, wom->dwFlags, hDev, uMsg, 
+		   wom->dwClientInstance, dwParam1, dwParam2);
+}
+
+static	DWORD	wodOpenHelper(WAVEMAPDATA* wom, UINT idx, 
+			      LPWAVEOPENDESC lpDesc, LPWAVEFORMATEX lpwfx, 
+			      DWORD dwFlags)
+{
+    DWORD	ret;
+
+    /* destination is always PCM, so the formulas below apply */
+    lpwfx->nBlockAlign = (lpwfx->nChannels * lpwfx->wBitsPerSample) / 8;
+    lpwfx->nAvgBytesPerSec = lpwfx->nSamplesPerSec * lpwfx->nBlockAlign;
+    ret = wom->acmStreamOpen(&wom->hAcmStream, 0, lpDesc->lpFormat, lpwfx, NULL, 0L, 0L, 0L);
+    if (ret != MMSYSERR_NOERROR)
+	return ret;
+    return waveOutOpen(&wom->hWave, idx, lpwfx, (DWORD)WAVEMAP_DstCallback, 
+		       (DWORD)wom, (dwFlags & CALLBACK_TYPEMASK) | CALLBACK_FUNCTION);
+}
+
+static	DWORD	wodOpen(LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
+{
+    UINT 		nd = waveOutGetNumDevs();
+    UINT		i;
+    WAVEMAPDATA*	wom = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA));
+    WAVEFORMATEX	wfx;
+
+    TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
+
+    if (!wom)
+	return MMSYSERR_NOMEM;
+
+    for (i = 0; i < nd; i++) {
+	/* if no ACM stuff is involved, no need to handle callbacks at this
+	 * level, this will be done transparently
+	 */
+	if (waveOutOpen(&wom->hWave, i, lpDesc->lpFormat, lpDesc->dwCallback, 
+			lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
+	    wom->hAcmStream = 0;
+	    goto found;
+	}
+    }
+
+    /* temporary hack until real builtin dll loading is available */
+    do {
+	HMODULE hModule = LoadLibraryA("msacm32.dll");
+	
+	wom->acmStreamOpen            = (void*)GetProcAddress(hModule, "acmStreamOpen");
+	wom->acmStreamClose           = (void*)GetProcAddress(hModule, "acmStreamClose");
+	wom->acmStreamSize            = (void*)GetProcAddress(hModule, "acmStreamSize");
+	wom->acmStreamConvert         = (void*)GetProcAddress(hModule, "acmStreamConvert");
+	wom->acmStreamPrepareHeader   = (void*)GetProcAddress(hModule, "acmStreamPrepareHeader");
+	wom->acmStreamUnprepareHeader = (void*)GetProcAddress(hModule, "acmStreamUnprepareHeader");
+    } while (0);
+
+    wfx.wFormatTag = WAVE_FORMAT_PCM;
+    wfx.cbSize = 0; /* normally, this field is not used for PCM format, just in case */
+    /* try some ACM stuff */
+
+    wom->dwCallback = lpDesc->dwCallback;
+    wom->dwFlags = dwFlags;
+    wom->dwClientInstance = lpDesc->dwInstance;
+
+#define	TRY(sps,bps)    wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \
+                        if (wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags) == MMSYSERR_NOERROR) goto found;
+
+    for (i = 0; i < nd; i++) {
+	/* first try with same stereo/mono option as source */
+	wfx.nChannels = lpDesc->lpFormat->nChannels;
+	TRY(44100, 8);
+	TRY(22050, 8);
+	TRY(11025, 8);
+
+	/* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
+	wfx.nChannels ^= 3; 
+	TRY(44100, 8);
+	TRY(22050, 8);
+	TRY(11025, 8);
+    }
+#undef TRY
+		      
+    HeapFree(GetProcessHeap(), 0, wom);
+    return MMSYSERR_ALLOCATED;
+found:
+    lpDesc->hWave = wom->hWave;
+    *lpdwUser = (DWORD)wom;
+    return MMSYSERR_NOERROR;
+}
+
+static	DWORD	wodClose(WAVEMAPDATA* wom)
+{
+    DWORD ret = waveOutClose(wom->hWave);
+
+    if (ret == MMSYSERR_NOERROR) {
+	if (wom->hAcmStream) {
+	    ret = wom->acmStreamClose(wom->hAcmStream, 0);
+	}
+	if (ret == MMSYSERR_NOERROR) {
+	    HeapFree(GetProcessHeap(), 0, wom);
+	}
+    }
+    return ret;
+}
+
+static	DWORD	wodWrite(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
+{
+    PACMSTREAMHEADER	ash;
+    LPWAVEHDR		lpWaveHdrDst;
+
+    if (!wom->hAcmStream) {
+	return waveOutWrite(wom->hWave, lpWaveHdrSrc, dwParam2);
+    }
+    
+    lpWaveHdrSrc->dwFlags |= WHDR_INQUEUE;
+    ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved;
+    if (wom->acmStreamConvert(wom->hAcmStream, ash, 0L) != MMSYSERR_NOERROR)
+	return MMSYSERR_ERROR;
+    
+    lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
+    lpWaveHdrDst->dwBufferLength = ash->cbDstLengthUsed;
+    return waveOutWrite(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
+}
+
+static	DWORD	wodPrepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
+{
+    PACMSTREAMHEADER	ash;
+    DWORD		size;
+    DWORD		dwRet;
+    LPWAVEHDR		lpWaveHdrDst;
+
+    if (!wom->hAcmStream) {
+	return waveOutPrepareHeader(wom->hWave, lpWaveHdrSrc, dwParam2);
+    }
+    if (wom->acmStreamSize(wom->hAcmStream, lpWaveHdrSrc->dwBufferLength, &size, ACM_STREAMSIZEF_SOURCE) != MMSYSERR_NOERROR)
+	return MMSYSERR_ERROR;
+
+    ash = HeapAlloc(GetProcessHeap(), 0, sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR) + size);
+    if (ash == NULL)
+	return MMSYSERR_NOMEM;
+
+    ash->cbStruct = sizeof(*ash);
+    ash->fdwStatus = 0L;
+    ash->dwUser = (DWORD)lpWaveHdrSrc;
+    ash->pbSrc = lpWaveHdrSrc->lpData;
+    ash->cbSrcLength = lpWaveHdrSrc->dwBufferLength;
+    /* ash->cbSrcLengthUsed */
+    ash->dwSrcUser = lpWaveHdrSrc->dwUser; /* FIXME ? */
+    ash->pbDst = (LPSTR)ash + sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR);
+    ash->cbDstLength = size;
+    /* ash->cbDstLengthUsed */
+    ash->dwDstUser = 0; /* FIXME ? */
+    dwRet = wom->acmStreamPrepareHeader(wom->hAcmStream, ash, 0L);
+    if (dwRet != MMSYSERR_NOERROR)
+	goto errCleanUp;
+
+    lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
+    lpWaveHdrDst->lpData = ash->pbDst;
+    lpWaveHdrDst->dwBufferLength = size; /* conversion is not done yet */
+    lpWaveHdrDst->dwFlags = 0;
+    lpWaveHdrDst->dwLoops = 0;
+    dwRet = waveOutPrepareHeader(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
+    if (dwRet != MMSYSERR_NOERROR)
+	goto errCleanUp;
+
+    lpWaveHdrSrc->reserved = (DWORD)ash;
+    lpWaveHdrSrc->dwFlags = WHDR_PREPARED;
+    TRACE("=> (0)\n");
+    return MMSYSERR_NOERROR;
+errCleanUp:
+    TRACE("=> (%ld)\n", dwRet);
+    HeapFree(GetProcessHeap(), 0, ash);
+    return dwRet;
+}
+
+static	DWORD	wodUnprepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
+{
+    PACMSTREAMHEADER	ash;
+    LPWAVEHDR		lpWaveHdrDst;
+    DWORD		dwRet1, dwRet2;
+
+    if (!wom->hAcmStream) {
+	return waveOutUnprepareHeader(wom->hWave, lpWaveHdrSrc, dwParam2);
+    }
+    ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved;
+    dwRet1 = wom->acmStreamUnprepareHeader(wom->hAcmStream, ash, 0L);
+    
+    lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
+    dwRet2 = waveOutUnprepareHeader(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
+
+    HeapFree(GetProcessHeap(), 0, ash);
+    
+    lpWaveHdrSrc->dwFlags &= ~WHDR_PREPARED;
+    return (dwRet1 == MMSYSERR_NOERROR) ? dwRet2 : dwRet1;
+}
+
+static	DWORD	wodGetPosition(WAVEMAPDATA* wom, LPMMTIME lpTime, DWORD dwParam2)
+{
+    return waveOutGetPosition(wom->hWave, lpTime, dwParam2);
+}
+
+static	DWORD	wodGetDevCaps(WAVEMAPDATA* wom, LPWAVEOUTCAPSA lpWaveCaps, DWORD dwParam2)
+{
+    return waveOutGetDevCapsA(wom->hWave, lpWaveCaps, dwParam2);
+}
+
+static	DWORD	wodGetVolume(WAVEMAPDATA* wom, LPDWORD lpVol)
+{
+    return waveOutGetVolume(wom->hWave, lpVol);
+}
+
+static	DWORD	wodSetVolume(WAVEMAPDATA* wom, DWORD vol)
+{
+    return waveOutSetVolume(wom->hWave, vol);
+}
+
+static	DWORD	wodPause(WAVEMAPDATA* wom)
+{
+    return waveOutPause(wom->hWave);
+}
+
+static	DWORD	wodRestart(WAVEMAPDATA* wom)
+{
+    return waveOutRestart(wom->hWave);
+}
+
+static	DWORD	wodReset(WAVEMAPDATA* wom)
+{
+    return waveOutReset(wom->hWave);
+}
+
+/**************************************************************************
+ * 				WAVEMAP_wodMessage	[sample driver]
+ */
+DWORD WINAPI WAVEMAP_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
+				DWORD dwParam1, DWORD dwParam2)
+{
+    TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
+	  wDevID, wMsg, dwUser, dwParam1, dwParam2);
+    
+    switch (wMsg) {
+    case DRVM_INIT:
+    case DRVM_EXIT:
+    case DRVM_ENABLE:
+    case DRVM_DISABLE:
+	/* FIXME: Pretend this is supported */
+	return 0;
+    case WODM_OPEN:	 	return wodOpen		((LPDWORD)dwUser,      (LPWAVEOPENDESC)dwParam1,dwParam2);
+    case WODM_CLOSE:	 	return wodClose		((WAVEMAPDATA*)dwUser);
+    case WODM_WRITE:	 	return wodWrite		((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,	dwParam2);
+    case WODM_PAUSE:	 	return wodPause		((WAVEMAPDATA*)dwUser);
+    case WODM_GETPOS:	 	return wodGetPosition	((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1, 	dwParam2);
+    case WODM_BREAKLOOP: 	return MMSYSERR_NOTSUPPORTED;
+    case WODM_PREPARE:	 	return wodPrepare	((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, 	dwParam2);
+    case WODM_UNPREPARE: 	return wodUnprepare	((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, 	dwParam2);
+    case WODM_GETDEVCAPS:	return wodGetDevCaps	((WAVEMAPDATA*)dwUser, (LPWAVEOUTCAPSA)dwParam1,dwParam2);
+    case WODM_GETNUMDEVS:	return 1;
+    case WODM_GETPITCH:	 	return MMSYSERR_NOTSUPPORTED;
+    case WODM_SETPITCH:	 	return MMSYSERR_NOTSUPPORTED;
+    case WODM_GETPLAYBACKRATE:	return MMSYSERR_NOTSUPPORTED;
+    case WODM_SETPLAYBACKRATE:	return MMSYSERR_NOTSUPPORTED;
+    case WODM_GETVOLUME:	return wodGetVolume	((WAVEMAPDATA*)dwUser, (LPDWORD)dwParam1);
+    case WODM_SETVOLUME:	return wodSetVolume	((WAVEMAPDATA*)dwUser, dwParam1);
+    case WODM_RESTART:		return wodRestart	((WAVEMAPDATA*)dwUser);
+    case WODM_RESET:		return wodReset		((WAVEMAPDATA*)dwUser);
+    default:
+	FIXME("unknown message %d!\n", wMsg);
+    }
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+/*======================================================================*
+ *                  WAVE IN part                                        *
+ *======================================================================*/
+
+static	DWORD	widOpen(LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
+{
+    UINT 		nd = waveInGetNumDevs();
+    UINT		i;
+    WAVEMAPDATA*	wim = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA));
+
+    TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
+
+    for (i = 0; i < nd; i++) {
+	if (waveInOpen(&wim->hWave, i, lpDesc->lpFormat, lpDesc->dwCallback, 
+			lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
+	    lpDesc->hWave = wim->hWave;
+	    *lpdwUser = (DWORD)wim;
+	    return MMSYSERR_NOERROR;
+	}
+    }
+    HeapFree(GetProcessHeap(), 0, wim);
+    return MMSYSERR_ALLOCATED;
+}
+
+static	DWORD	widClose(WAVEMAPDATA* wim)
+{
+    DWORD ret = waveInClose(wim->hWave);
+    if (ret == MMSYSERR_NOERROR)
+	HeapFree(GetProcessHeap(), 0, wim);
+    return ret;
+}
+
+static	DWORD	widAddBuffer(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2)
+{
+    return waveInAddBuffer(wim->hWave, lpWaveHdr, dwParam2);
+}
+
+static	DWORD	widPrepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2)
+{
+    return waveInPrepareHeader(wim->hWave, lpWaveHdr, dwParam2);
+}
+
+static	DWORD	widUnprepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2)
+{
+    return waveInUnprepareHeader(wim->hWave, lpWaveHdr, dwParam2);
+}
+
+static	DWORD	widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2)
+{
+    return waveInGetPosition(wim->hWave, lpTime, dwParam2);
+}
+
+static	DWORD	widGetDevCaps(WAVEMAPDATA* wim, LPWAVEINCAPSA lpWaveCaps, DWORD dwParam2)
+{
+    return waveInGetDevCapsA(wim->hWave, lpWaveCaps, dwParam2);
+}
+
+static	DWORD	widStop(WAVEMAPDATA* wim)
+{
+    return waveInStop(wim->hWave);
+}
+
+static	DWORD	widStart(WAVEMAPDATA* wim)
+{
+    return waveInStart(wim->hWave);
+}
+
+static	DWORD	widReset(WAVEMAPDATA* wim)
+{
+    return waveInReset(wim->hWave);
+}
+
+/**************************************************************************
+ * 				WAVEMAP_widMessage	[sample driver]
+ */
+DWORD WINAPI WAVEMAP_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+				DWORD dwParam1, DWORD dwParam2)
+{
+    TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
+	  wDevID, wMsg, dwUser, dwParam1, dwParam2);
+
+    switch (wMsg) {
+    case DRVM_INIT:
+    case DRVM_EXIT:
+    case DRVM_ENABLE:
+    case DRVM_DISABLE:
+	/* FIXME: Pretend this is supported */
+	return 0;
+
+    case WIDM_OPEN:		return widOpen          ((LPDWORD)dwUser,     (LPWAVEOPENDESC)dwParam1, dwParam2);
+    case WIDM_CLOSE:		return widClose         ((WAVEMAPDATA*)dwUser);
+
+    case WIDM_ADDBUFFER:	return widAddBuffer     ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, 	dwParam2);
+    case WIDM_PREPARE:		return widPrepare       ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, 	dwParam2);
+    case WIDM_UNPREPARE:	return widUnprepare     ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, 	dwParam2);
+    case WIDM_GETDEVCAPS:	return widGetDevCaps    ((WAVEMAPDATA*)dwUser, (LPWAVEINCAPSA)dwParam1, dwParam2);
+    case WIDM_GETNUMDEVS:	return 1;
+    case WIDM_GETPOS:		return widGetPosition   ((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1, 	dwParam2);
+    case WIDM_RESET:		return widReset         ((WAVEMAPDATA*)dwUser);
+    case WIDM_START:		return widStart         ((WAVEMAPDATA*)dwUser);
+    case WIDM_STOP:		return widStop          ((WAVEMAPDATA*)dwUser);
+    default:
+	FIXME("unknown message %u!\n", wMsg);
+    }
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+/*======================================================================*
+ *                  Driver part                                         *
+ *======================================================================*/
+
+static	struct WINE_WAVEMAP* oss = NULL;
+
+/**************************************************************************
+ * 				WAVEMAP_drvOpen			[internal]	
+ */
+static	DWORD	WAVEMAP_drvOpen(LPSTR str)
+{
+    if (oss)
+	return 0;
+    
+    /* I know, this is ugly, but who cares... */
+    oss = (struct WINE_WAVEMAP*)1;
+    return 1;
+}
+
+/**************************************************************************
+ * 				WAVEMAP_drvClose		[internal]	
+ */
+static	DWORD	WAVEMAP_drvClose(DWORD dwDevID)
+{
+    if (oss) {
+	oss = NULL;
+	return 1;
+    }
+    return 0;
+}
+
+/**************************************************************************
+ * 				WAVEMAP_DriverProc		[internal]
+ */
+LONG CALLBACK	WAVEMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
+				   DWORD dwParam1, DWORD dwParam2)
+{
+/* EPP     TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",  */
+/* EPP 	  dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
+    
+    switch(wMsg) {
+    case DRV_LOAD:		return 1;
+    case DRV_FREE:		return 1;
+    case DRV_OPEN:		return WAVEMAP_drvOpen((LPSTR)dwParam1);
+    case DRV_CLOSE:		return WAVEMAP_drvClose(dwDevID);
+    case DRV_ENABLE:		return 1;
+    case DRV_DISABLE:		return 1;
+    case DRV_QUERYCONFIGURE:	return 1;
+    case DRV_CONFIGURE:		MessageBoxA(0, "WAVEMAP MultiMedia Driver !", "OSS Driver", MB_OK);	return 1;
+    case DRV_INSTALL:		return DRVCNF_RESTART;
+    case DRV_REMOVE:		return DRVCNF_RESTART;
+    default:
+	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+    }
+}
+
+
diff --git a/loader/loadorder.c b/loader/loadorder.c
index 489548538b88983f0b0aaafddaf787ac8a13b3ba..a340c8ba2dacb6cd0d6171185ba2de3d29206ecb 100644
--- a/loader/loadorder.c
+++ b/loader/loadorder.c
@@ -51,6 +51,7 @@ static struct tagDllOverride {
 	{"mcicda.drv, mciseq.drv",	"builtin, native"},
 	{"mciwave.drv",			"builtin, native"},
 	{"mciavi.drv, mcianim.drv",	"native, builtin"},
+	{"msacm.drv, midimap.drv",      "builtin, native"},
 	{"w32skrnl",			"builtin"},
 	{"wnaspi32,wow32",		"builtin"},
 	{"system,display,wprocs	",	"builtin"},
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index 450df451a0878ac92cd98ae81c27e534cfd02ec1..92c8df18a86fb83c8c239c012d5d78a2c683e5c7 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -70,7 +70,9 @@ extern const BUILTIN32_DESCRIPTOR MCIAVI_Descriptor;
 extern const BUILTIN32_DESCRIPTOR MCICDA_Descriptor;
 extern const BUILTIN32_DESCRIPTOR MCISEQ_Descriptor;
 extern const BUILTIN32_DESCRIPTOR MCIWAVE_Descriptor;
+extern const BUILTIN32_DESCRIPTOR MIDIMAP_Descriptor;
 extern const BUILTIN32_DESCRIPTOR MSACM32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR MSACMMAP_Descriptor;
 extern const BUILTIN32_DESCRIPTOR MSNET32_Descriptor;
 extern const BUILTIN32_DESCRIPTOR MSVFW32_Descriptor;
 extern const BUILTIN32_DESCRIPTOR NTDLL_Descriptor;
@@ -123,8 +125,10 @@ static BUILTIN32_DLL BuiltinDLLs[] =
     { &MCICDA_Descriptor,   0, 0, NULL },
     { &MCISEQ_Descriptor,   0, 0, NULL },
     { &MCIWAVE_Descriptor,  0, 0, NULL },
+    { &MIDIMAP_Descriptor,  0, 0, NULL },
     { &MPR_Descriptor,      0, 0, NULL },
     { &MSACM32_Descriptor,  BI32_DANGER, 0, NULL },
+    { &MSACMMAP_Descriptor, 0, 0, NULL },
     { &MSNET32_Descriptor,  0, 0, NULL },
     { &MSVFW32_Descriptor,  0, 0, NULL },
     { &NTDLL_Descriptor,    0, 0, NULL },
diff --git a/wine.ini b/wine.ini
index 98d153cd3274fab06e9b5f0671dc1c676386d21b..6f55056c0d3c134eac312404e4ff62fa75e3200f 100644
--- a/wine.ini
+++ b/wine.ini
@@ -91,6 +91,7 @@ msvideo, msvfw32        = builtin, native
 mcicda.drv, mciseq.drv  = builtin, native
 mciwave.drv		= builtin, native
 mciavi.drv, mcianim.drv = native, builtin
+msacm.drv, midimap.drv  = builtin, native
 w32skrnl                = builtin
 wnaspi32, wow32		= builtin
 system, display, wprocs	= builtin