diff --git a/dlls/winmm/mcicda/mcicda.c b/dlls/winmm/mcicda/mcicda.c
index 77451c34c6a9995cca8b1f9fb6c4885bc076dd31..0401c8d4419e84baedb99c6941e64d3e9c47993a 100644
--- a/dlls/winmm/mcicda/mcicda.c
+++ b/dlls/winmm/mcicda/mcicda.c
@@ -1,9 +1,10 @@
 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
 /*
- * Sample MCI CDAUDIO Wine Driver for Linux
+ * MCI driver for audio CD (MCICDA)
  *
  * Copyright 1994    Martin Ayotte
  * Copyright 1998-99 Eric Pouech
+ * Copyright 2000    Andreas Mohr
  */
 
 #include "winuser.h"
@@ -12,7 +13,7 @@
 #include "cdrom.h"
 #include "debugtools.h"
 
-DEFAULT_DEBUG_CHANNEL(cdaudio)
+DEFAULT_DEBUG_CHANNEL(mcicda);
 
 typedef struct {
     UINT		wDevID;
@@ -28,9 +29,9 @@ typedef struct {
 /*-----------------------------------------------------------------------*/
 
 /**************************************************************************
- * 				CDAUDIO_drvOpen			[internal]	
+ * 				MCICDA_drvOpen			[internal]	
  */
-static	DWORD	CDAUDIO_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
+static	DWORD	MCICDA_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
 {
     WINE_MCICDAUDIO*	wmcda = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,  sizeof(WINE_MCICDAUDIO));
 
@@ -45,9 +46,9 @@ static	DWORD	CDAUDIO_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
 }
 
 /**************************************************************************
- * 				CDAUDIO_drvClose		[internal]	
+ * 				MCICDA_drvClose			[internal]	
  */
-static	DWORD	CDAUDIO_drvClose(DWORD dwDevID)
+static	DWORD	MCICDA_drvClose(DWORD dwDevID)
 {
     WINE_MCICDAUDIO*  wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(dwDevID);
 
@@ -59,9 +60,9 @@ static	DWORD	CDAUDIO_drvClose(DWORD dwDevID)
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciGetOpenDrv		[internal]	
+ * 				MCICDA_GetOpenDrv		[internal]	
  */
-static WINE_MCICDAUDIO*  CDAUDIO_mciGetOpenDrv(UINT wDevID)
+static WINE_MCICDAUDIO*  MCICDA_GetOpenDrv(UINT wDevID)
 {
     WINE_MCICDAUDIO*	wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
     
@@ -73,9 +74,9 @@ static WINE_MCICDAUDIO*  CDAUDIO_mciGetOpenDrv(UINT wDevID)
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciMode			[internal]
+ * 				MCICDA_Mode			[internal]
  */
-static	int	CDAUDIO_mciMode(int wcdaMode)
+static	int	MCICDA_Mode(int wcdaMode)
 {
     switch (wcdaMode) {
     case WINE_CDA_DONTKNOW:	return MCI_MODE_STOP;
@@ -91,9 +92,9 @@ static	int	CDAUDIO_mciMode(int wcdaMode)
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciGetError		[internal]
+ * 				MCICDA_GetError			[internal]
  */
-static	int	CDAUDIO_mciGetError(WINE_MCICDAUDIO* wmcda)
+static	int	MCICDA_GetError(WINE_MCICDAUDIO* wmcda)
 {
     switch (wmcda->wcda.cdaMode) {
     case WINE_CDA_DONTKNOW:
@@ -109,9 +110,9 @@ static	int	CDAUDIO_mciGetError(WINE_MCICDAUDIO* wmcda)
 }
 
 /**************************************************************************
- * 			CDAUDIO_CalcFrame			[internal]
+ * 			MCICDA_CalcFrame			[internal]
  */
-static DWORD CDAUDIO_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
+static DWORD MCICDA_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
 {
     DWORD	dwFrame = 0;
     UINT	wTrack;
@@ -148,9 +149,9 @@ static DWORD CDAUDIO_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
 }
 
 /**************************************************************************
- * 			CDAUDIO_CalcTime			[internal]
+ * 			MCICDA_CalcTime				[internal]
  */
-static DWORD CDAUDIO_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame, 
+static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame, 
 			      LPDWORD lpRet)
 {
     DWORD	dwTime = 0;
@@ -200,13 +201,13 @@ static DWORD CDAUDIO_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame,
     return dwTime;
 }
 
-static DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms);
-static DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
+static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms);
+static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
 
 /**************************************************************************
- * 				CDAUDIO_mciOpen			[internal]
+ * 				MCICDA_Open			[internal]
  */
-static DWORD CDAUDIO_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
+static DWORD MCICDA_Open(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
 {
     DWORD		dwDeviceID;
     WINE_MCICDAUDIO* 	wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
@@ -242,44 +243,44 @@ static DWORD CDAUDIO_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpe
     }
 
     wmcda->wNotifyDeviceID = dwDeviceID;
-    if (CDAUDIO_Open(&wmcda->wcda, -1) == -1) {
+    if (CDROM_Open(&wmcda->wcda, -1) == -1) {
 	--wmcda->nUseCount;
 	return MCIERR_HARDWARE;
     }
     wmcda->mciMode = MCI_MODE_STOP;
     wmcda->dwTimeFormat = MCI_FORMAT_MSF;
-    if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
+    if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
 	WARN("error reading TracksInfo !\n");
 	return MCIERR_INTERNAL;
     }
     
-    CDAUDIO_mciSeek(wDevID, MCI_SEEK_TO_START, &seekParms);
+    MCICDA_Seek(wDevID, MCI_SEEK_TO_START, &seekParms);
 
     return 0;
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciClose		[internal]
+ * 				MCICDA_Close			[internal]
  */
-static DWORD CDAUDIO_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
+static DWORD MCICDA_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
 
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwParam, lpParms);
 
     if (wmcda == NULL) 	return MCIERR_INVALID_DEVICE_ID;
     
     if (wmcda->nUseCount == 1) {
-	CDAUDIO_Close(&wmcda->wcda);
+	CDROM_Close(&wmcda->wcda);
     }
     wmcda->nUseCount--;
     return 0;
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciGetDevCaps		[internal]
+ * 				MCICDA_GetDevCaps		[internal]
  */
-static DWORD CDAUDIO_mciGetDevCaps(UINT wDevID, DWORD dwFlags, 
+static DWORD MCICDA_GetDevCaps(UINT wDevID, DWORD dwFlags, 
 				   LPMCI_GETDEVCAPS_PARMS lpParms)
 {
     DWORD	ret = 0;
@@ -341,12 +342,12 @@ static DWORD CDAUDIO_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciInfo			[internal]
+ * 				MCICDA_Info			[internal]
  */
-static DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
+static DWORD MCICDA_Info(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
 {
     LPSTR		str = NULL;
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     DWORD		ret = 0;
     char		buffer[16];
 
@@ -363,25 +364,19 @@ static DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpPar
     } else if (dwFlags & MCI_INFO_MEDIA_UPC) {
 	ret = MCIERR_NO_IDENTITY;
     } else if (dwFlags & MCI_INFO_MEDIA_IDENTITY) {
-	DWORD	msf, res = 0, dummy;
-	int	i;
+	DWORD	res = 0;
 
-	if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) {
-	    return CDAUDIO_mciGetError(wmcda);
+	if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) {
+	    return MCICDA_GetError(wmcda);
 	}
 
-	for (i = 0; i < wmcda->wcda.nTracks; i++) {
-	    msf = CDAUDIO_CalcTime(wmcda, MCI_FORMAT_MSF, wmcda->wcda.lpdwTrackPos[i], &dummy);
-	    res += (MCI_MSF_MINUTE(msf) << 16) +
-		   (MCI_MSF_SECOND(msf) << 8) +
-		   (MCI_MSF_FRAME(msf));
-	}
+	res = CDROM_Audio_GetSerial(&wmcda->wcda);
 	if (wmcda->wcda.nTracks <= 2) {
 	    /* there are some other values added when # of tracks < 3
 	     * for most Audio CD it will do without
  	     */
 	    FIXME("Value is not correct !! "
-                  "Please report will full audio CD information (-debugmsg +cdaudio)\n");
+                  "Please report with full audio CD information (-debugmsg +cdrom,mcicda)\n");
 	}
 	sprintf(buffer, "%lu", res);
 	str = buffer;
@@ -404,11 +399,11 @@ static DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpPar
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciStatus		[internal]
+ * 				MCICDA_Status			[internal]
  */
-static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
+static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     DWORD	        ret = 0;
 
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
@@ -424,17 +419,17 @@ static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lp
     if (dwFlags & MCI_STATUS_ITEM) {
 	switch (lpParms->dwItem) {
 	case MCI_STATUS_CURRENT_TRACK:
-	    if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) {
-		return CDAUDIO_mciGetError(wmcda);
+	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) {
+		return MCICDA_GetError(wmcda);
 	    }
 	    lpParms->dwReturn = wmcda->wcda.nCurTrack;
 	    TRACE("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
 	    break;
 	case MCI_STATUS_LENGTH:
 	    if (wmcda->wcda.nTracks == 0) {
-		if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
+		if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
 		    WARN("error reading TracksInfo !\n");
-		    return CDAUDIO_mciGetError(wmcda);
+		    return MCICDA_GetError(wmcda);
 		}
 	    }
 	    if (dwFlags & MCI_TRACK) {
@@ -445,7 +440,7 @@ static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lp
 	    } else {
 		lpParms->dwReturn = wmcda->wcda.dwLastFrame;
 	    }
-	    lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, 
+	    lpParms->dwReturn = MCICDA_CalcTime(wmcda, 
 						 (wmcda->dwTimeFormat == MCI_FORMAT_TMSF) 
 						    ? MCI_FORMAT_MSF : wmcda->dwTimeFormat,
 						 lpParms->dwReturn,
@@ -453,31 +448,31 @@ static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lp
 	    TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
 	    break;
 	case MCI_STATUS_MODE:
-	    if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) 
-		return CDAUDIO_mciGetError(wmcda);
-	    lpParms->dwReturn = CDAUDIO_mciMode(wmcda->wcda.cdaMode);
+	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) 
+		return MCICDA_GetError(wmcda);
+	    lpParms->dwReturn = MCICDA_Mode(wmcda->wcda.cdaMode);
 	    if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
 	    TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
 	    lpParms->dwReturn = MAKEMCIRESOURCE(lpParms->dwReturn, lpParms->dwReturn);
 	    ret = MCI_RESOURCE_RETURNED;
 	    break;
 	case MCI_STATUS_MEDIA_PRESENT:
-	    if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) 
-		return CDAUDIO_mciGetError(wmcda);
+	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) 
+		return MCICDA_GetError(wmcda);
 	    lpParms->dwReturn = (wmcda->wcda.nTracks == 0) ? 
 		MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
 	    TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms->dwReturn) ? 'Y' : 'N');
 	    ret = MCI_RESOURCE_RETURNED;
 	    break;
 	case MCI_STATUS_NUMBER_OF_TRACKS:
-	    lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(&wmcda->wcda);
+	    lpParms->dwReturn = CDROM_Audio_GetNumberOfTracks(&wmcda->wcda);
 	    TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
 	    if (lpParms->dwReturn == (WORD)-1) 
-		return CDAUDIO_mciGetError(wmcda);
+		return MCICDA_GetError(wmcda);
 	    break;
 	case MCI_STATUS_POSITION:
-	    if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) 
-		return CDAUDIO_mciGetError(wmcda);
+	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) 
+		return MCICDA_GetError(wmcda);
 	    lpParms->dwReturn = wmcda->wcda.dwCurFrame;
 	    if (dwFlags & MCI_STATUS_START) {
 		lpParms->dwReturn = wmcda->wcda.dwFirstFrame;
@@ -489,7 +484,7 @@ static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lp
 		lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
 		TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
 	    }
-	    lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
+	    lpParms->dwReturn = MCICDA_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
 	    TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
 	    break;
 	case MCI_STATUS_READY:
@@ -527,12 +522,12 @@ static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lp
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciPlay			[internal]
+ * 				MCICDA_Play			[internal]
  */
-static DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
+static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
 {
     int 		start, end;
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     DWORD		ret = 0;
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
@@ -543,27 +538,27 @@ static DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParm
 	ret = MCIERR_INVALID_DEVICE_ID;
     } else {
 	if (wmcda->wcda.nTracks == 0) {
-	    if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
+	    if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
 		WARN("error reading TracksInfo !\n");
 		return MCIERR_DRIVER_INTERNAL;
 	    }
 	}
 	wmcda->wcda.nCurTrack = 1;
 	if (dwFlags & MCI_FROM) {
-	    start = CDAUDIO_CalcFrame(wmcda, lpParms->dwFrom);
+	    start = MCICDA_CalcFrame(wmcda, lpParms->dwFrom);
 	    TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
 	} else {
-	    if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) return MCIERR_DRIVER_INTERNAL;
+	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) return MCIERR_DRIVER_INTERNAL;
 	    start = wmcda->wcda.dwCurFrame;
 	}
 	if (dwFlags & MCI_TO) {
-	    end = CDAUDIO_CalcFrame(wmcda, lpParms->dwTo);
+	    end = MCICDA_CalcFrame(wmcda, lpParms->dwTo);
 	    TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
 	} else {
 	    end = wmcda->wcda.dwLastFrame;
 	}
 	
-	if (CDAUDIO_Play(&wmcda->wcda, start, end) == -1)
+	if (CDROM_Audio_Play(&wmcda->wcda, start, end) == -1)
 	    return MCIERR_HARDWARE;
 	wmcda->mciMode = MCI_MODE_PLAY;
 	if (dwFlags & MCI_NOTIFY) {
@@ -578,17 +573,17 @@ static DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParm
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciStop			[internal]
+ * 				MCICDA_Stop			[internal]
  */
-static DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
+static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDAUDIO_Stop(&wmcda->wcda) == -1)
+    if (CDROM_Audio_Stop(&wmcda->wcda) == -1)
 	return MCIERR_HARDWARE;
 
     wmcda->mciMode = MCI_MODE_STOP;
@@ -601,17 +596,17 @@ static DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciPause		[internal]
+ * 				MCICDA_Pause			[internal]
  */
-static DWORD CDAUDIO_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
+static DWORD MCICDA_Pause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDAUDIO_Pause(&wmcda->wcda, 1) == -1)
+    if (CDROM_Audio_Pause(&wmcda->wcda, 1) == -1)
 	return MCIERR_HARDWARE;
     wmcda->mciMode = MCI_MODE_PAUSE;
     if (lpParms && (dwFlags & MCI_NOTIFY)) {
@@ -623,17 +618,17 @@ static DWORD CDAUDIO_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lp
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciResume		[internal]
+ * 				MCICDA_Resume			[internal]
  */
-static DWORD CDAUDIO_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
+static DWORD MCICDA_Resume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDAUDIO_Pause(&wmcda->wcda, 0) == -1)
+    if (CDROM_Audio_Pause(&wmcda->wcda, 0) == -1)
 	return MCIERR_HARDWARE;
     wmcda->mciMode = MCI_MODE_STOP;
     if (lpParms && (dwFlags & MCI_NOTIFY)) {
@@ -645,12 +640,12 @@ static DWORD CDAUDIO_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS l
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciSeek			[internal]
+ * 				MCICDA_Seek			[internal]
  */
-static DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
+static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
 {
     DWORD		at;
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
@@ -675,7 +670,7 @@ static DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParm
 	TRACE("Seeking to ??=%lu\n", dwFlags);
 	return MCIERR_UNSUPPORTED_FUNCTION;
     }
-    if (CDAUDIO_Seek(&wmcda->wcda, at) == -1) {
+    if (CDROM_Audio_Seek(&wmcda->wcda, at) == -1) {
 	return MCIERR_HARDWARE;
     }
     if (dwFlags & MCI_NOTIFY) {
@@ -687,28 +682,28 @@ static DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParm
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciSetDoor		[internal]
+ * 				MCICDA_SetDoor			[internal]
  */
-static DWORD	CDAUDIO_mciSetDoor(UINT wDevID, int open)
+static DWORD	MCICDA_SetDoor(UINT wDevID, int open)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     
     TRACE("(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
     
     if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDAUDIO_SetDoor(&wmcda->wcda, open) == -1)
+    if (CDROM_SetDoor(&wmcda->wcda, open) == -1)
 	return MCIERR_HARDWARE;
     wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
     return 0;
 }
 
 /**************************************************************************
- * 				CDAUDIO_mciSet			[internal]
+ * 				MCICDA_Set			[internal]
  */
-static DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
+static DWORD MCICDA_Set(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
+    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
@@ -736,10 +731,10 @@ static DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
 	wmcda->dwTimeFormat = lpParms->dwTimeFormat;
     }
     if (dwFlags & MCI_SET_DOOR_OPEN) {
-	CDAUDIO_mciSetDoor(wDevID, TRUE);
+	MCICDA_SetDoor(wDevID, TRUE);
     }
     if (dwFlags & MCI_SET_DOOR_CLOSED) {
-	CDAUDIO_mciSetDoor(wDevID, FALSE);
+	MCICDA_SetDoor(wDevID, FALSE);
     }
     if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
     if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
@@ -754,37 +749,39 @@ static DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
 }
 
 /**************************************************************************
- * 			MCICDAUDIO_DriverProc			[sample driver]
+ * 			MCICDA_DriverProc			[exported]
  */
-LONG CALLBACK	MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
+LONG CALLBACK	MCICDA_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
 				      DWORD dwParam1, DWORD dwParam2)
 {
     switch(wMsg) {
     case DRV_LOAD:		return 1;
     case DRV_FREE:		return 1;
-    case DRV_OPEN:		return CDAUDIO_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
-    case DRV_CLOSE:		return CDAUDIO_drvClose(dwDevID);
+    case DRV_OPEN:		return MCICDA_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
+    case DRV_CLOSE:		return MCICDA_drvClose(dwDevID);
     case DRV_ENABLE:		return 1;	
     case DRV_DISABLE:		return 1;
     case DRV_QUERYCONFIGURE:	return 1;
-    case DRV_CONFIGURE:		MessageBoxA(0, "Sample Multimedia Driver !", "Wine Driver", MB_OK); return 1;
+    case DRV_CONFIGURE:		MessageBoxA(0, "MCI audio CD driver !", "Wine Driver", MB_OK); return 1;
     case DRV_INSTALL:		return DRVCNF_RESTART;
     case DRV_REMOVE:		return DRVCNF_RESTART;
 	
-    case MCI_OPEN_DRIVER:	return CDAUDIO_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
-    case MCI_CLOSE_DRIVER:	return CDAUDIO_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
-    case MCI_GETDEVCAPS:	return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
-    case MCI_INFO:		return CDAUDIO_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMSA)dwParam2);
-    case MCI_STATUS:		return CDAUDIO_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
-    case MCI_SET:		return CDAUDIO_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
-    case MCI_PLAY:		return CDAUDIO_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
-    case MCI_STOP:		return CDAUDIO_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
-    case MCI_PAUSE:		return CDAUDIO_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
-    case MCI_RESUME:		return CDAUDIO_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
-    case MCI_SEEK:		return CDAUDIO_mciSeek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
+    case MCI_OPEN_DRIVER:	return MCICDA_Open(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
+    case MCI_CLOSE_DRIVER:	return MCICDA_Close(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
+    case MCI_GETDEVCAPS:	return MCICDA_GetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
+    case MCI_INFO:		return MCICDA_Info(dwDevID, dwParam1, (LPMCI_INFO_PARMSA)dwParam2);
+    case MCI_STATUS:		return MCICDA_Status(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
+    case MCI_SET:		return MCICDA_Set(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
+    case MCI_PLAY:		return MCICDA_Play(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
+    case MCI_STOP:		return MCICDA_Stop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
+    case MCI_PAUSE:		return MCICDA_Pause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
+    case MCI_RESUME:		return MCICDA_Resume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
+    case MCI_SEEK:		return MCICDA_Seek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
     /* FIXME: I wonder if those two next items are really called ? */
-    case MCI_SET_DOOR_OPEN:	return CDAUDIO_mciSetDoor(dwDevID, TRUE);
-    case MCI_SET_DOOR_CLOSED:	return CDAUDIO_mciSetDoor(dwDevID, FALSE);
+    case MCI_SET_DOOR_OPEN:	FIXME("MCI_SET_DOOR_OPEN called. Please report this.\n");
+				return MCICDA_SetDoor(dwDevID, TRUE);
+    case MCI_SET_DOOR_CLOSED:	FIXME("MCI_SET_DOOR_CLOSED called. Please report this.\n");
+				return MCICDA_SetDoor(dwDevID, FALSE);
     /* commands that should be supported */
     case MCI_LOAD:		
     case MCI_SAVE:		
diff --git a/dlls/winmm/mcicda/mcicda.spec b/dlls/winmm/mcicda/mcicda.spec
index ad8dc723ab6c42f60ec1975e7eb1e8a29c94cb1d..4839808d60fb4d1038dfcb8597f370ec7fead037 100644
--- a/dlls/winmm/mcicda/mcicda.spec
+++ b/dlls/winmm/mcicda/mcicda.spec
@@ -2,4 +2,4 @@ name mcicda
 file mcicda.drv
 type win32
 
-  1 stdcall DriverProc(long long long long long) MCICDAUDIO_DriverProc
+  1 stdcall DriverProc(long long long long long) MCICDA_DriverProc
diff --git a/files/drive.c b/files/drive.c
index 865439f020fe5941a30d6e1b467bb8c924b39b42..8ff68a1de1ebf954ad3ba8a76762f746aced9dc9 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -499,9 +499,9 @@ const char * DRIVE_GetLabel( int drive )
     {
 	WINE_CDAUDIO wcda;
 
-	if (!(CDAUDIO_Open(&wcda, drive)))
+	if (!(CDROM_Open(&wcda, drive)))
 	{
-	    int media = CDAUDIO_GetMediaType(&wcda);
+	    int media = CDROM_GetMediaType(&wcda);
 
 	    if (media == CDS_AUDIO)
 	    {
@@ -515,7 +515,7 @@ const char * DRIVE_GetLabel( int drive )
 		read = 1;
 	    }
 
-	    CDAUDIO_Close(&wcda);
+	    CDROM_Close(&wcda);
 }
     }
     if ((!read) && (DOSDrives[drive].read_volinfo))
@@ -545,27 +545,36 @@ const char * DRIVE_GetLabel( int drive )
 
 /***********************************************************************
  *           DRIVE_GetSerialNumber
- *
- * FIXME: apparently Win 9x (not DOS !) gives serial numbers to CD-ROMs, too.
- * How to calculate them ?
  */
 DWORD DRIVE_GetSerialNumber( int drive )
 {
+    DWORD serial = 0;
 char buff[DRIVE_SUPER];
 
     if (!DRIVE_IsValid( drive )) return 0;
-    if ( (DOSDrives[drive].read_volinfo) &&
-        ((DOSDrives[drive].type == TYPE_FLOPPY) ||
-         (DOSDrives[drive].type == TYPE_HD)))
+    
+    if (DOSDrives[drive].read_volinfo)
     {
+	switch(DOSDrives[drive].type)
+	{
+	    case TYPE_FLOPPY:
+	    case TYPE_HD:
       if (DRIVE_ReadSuperblock(drive,(char *) buff))
-
         MESSAGE("Invalid or unreadable superblock on %s (%c:)."
-           " Maybe not FAT?\n" ,DOSDrives[drive].device,(char)(drive+'A'));
+			" Maybe not FAT?\n" ,
+			DOSDrives[drive].device, 'A'+drive);
       else
-        return *((DWORD*)(buff+0x27));
+		    serial = *((DWORD*)(buff+0x27));
+		break;
+	    case TYPE_CDROM:
+		serial = CDROM_GetSerial(drive);
+		break;
+	    default:
+	        FIXME("Serial number reading from file system on drive %c: not supported yet.\n", drive+'A');
+	}
     }
-    return DOSDrives[drive].serial_conf;
+		
+    return (serial) ? serial : DOSDrives[drive].serial_conf;
 }
 
 
diff --git a/include/cdrom.h b/include/cdrom.h
index 18bdd7316ebea4c75b763c15d16e442e7f8ae7a2..0de4797cd89e9cc2054e6dd97faf7b6f1aeffa5a 100644
--- a/include/cdrom.h
+++ b/include/cdrom.h
@@ -1,9 +1,10 @@
 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
 /*
- * Sample MCI CDAUDIO Wine Driver for Linux
+ * Header file for CD-ROM support
  *
  * Copyright 1994 Martin Ayotte
  * Copyright 1999 Eric Pouech
+ * Copyright 2000 Andreas Mohr
  */
 
 #ifndef __WINE_CDROM_H__
@@ -54,18 +55,21 @@ typedef struct {
 #define	WINE_CDA_STOP			0x04
 #define	WINE_CDA_PAUSE			0x05
 
-int	CDAUDIO_Open(WINE_CDAUDIO* wcda, int drive);
-int	CDAUDIO_GetMediaType(WINE_CDAUDIO* wcda);
-int	CDAUDIO_Close(WINE_CDAUDIO* wcda);
-int	CDAUDIO_Reset(WINE_CDAUDIO* wcda);
-int	CDAUDIO_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD stop);
-int	CDAUDIO_Stop(WINE_CDAUDIO* wcda);
-int	CDAUDIO_Pause(WINE_CDAUDIO* wcda, int pauseOn);
-int	CDAUDIO_Seek(WINE_CDAUDIO* wcda, DWORD at);
-int	CDAUDIO_SetDoor(WINE_CDAUDIO* wcda, int open);
-UINT16 	CDAUDIO_GetNumberOfTracks(WINE_CDAUDIO* wcda);
-BOOL 	CDAUDIO_GetTracksInfo(WINE_CDAUDIO* wcda);
-BOOL	CDAUDIO_GetCDStatus(WINE_CDAUDIO* wcda);
+int	CDROM_Open(WINE_CDAUDIO* wcda, int drive);
+int	CDROM_GetMediaType(WINE_CDAUDIO* wcda);
+int	CDROM_Close(WINE_CDAUDIO* wcda);
+int	CDROM_Reset(WINE_CDAUDIO* wcda);
+int	CDROM_Audio_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD stop);
+int	CDROM_Audio_Stop(WINE_CDAUDIO* wcda);
+int	CDROM_Audio_Pause(WINE_CDAUDIO* wcda, int pauseOn);
+int	CDROM_Audio_Seek(WINE_CDAUDIO* wcda, DWORD at);
+int	CDROM_SetDoor(WINE_CDAUDIO* wcda, int open);
+UINT16 	CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO* wcda);
+BOOL 	CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda);
+BOOL	CDROM_Audio_GetCDStatus(WINE_CDAUDIO* wcda);
+DWORD	CDROM_Audio_GetSerial(WINE_CDAUDIO* wcda);
+DWORD	CDROM_Data_GetSerial(WINE_CDAUDIO* wcda);
+DWORD	CDROM_GetSerial(int drive);
 
 #define CDFRAMES_PERSEC 		75
 #define SECONDS_PERMIN	 		60
@@ -75,6 +79,14 @@ BOOL	CDAUDIO_GetCDStatus(WINE_CDAUDIO* wcda);
 #define CDROM_DATA_TRACK 0x04
 #endif
 
+#define CDROM_MSF_MINUTE(msf)           ((BYTE)(msf))
+#define CDROM_MSF_SECOND(msf)           ((BYTE)(((WORD)(msf)) >> 8))
+#define CDROM_MSF_FRAME(msf)            ((BYTE)((msf)>>16))
+
+#define CDROM_MAKE_MSF(m, s, f)         ((DWORD)(((BYTE)(m) | \
+                                                  ((WORD)(s)<<8)) | \
+                                                 (((DWORD)(BYTE)(f))<<16)))
+
 /* values borrowed from Linux 2.2.x cdrom.h */
 #define CDS_NO_INFO			0
 #define CDS_AUDIO			100
diff --git a/include/debugdefs.h b/include/debugdefs.h
index 4ee0ba68bd9b73db3cdeb69acbad24ae48c0ae21..16c7e05e5cdb9a143bc6a22537e187ee99463173 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -17,7 +17,7 @@ const int dbch_avifile = 5;
 const int dbch_bitblt = 6;
 const int dbch_bitmap = 7;
 const int dbch_caret = 8;
-const int dbch_cdaudio = 9;
+const int dbch_cdrom = 9;
 const int dbch_class = 10;
 const int dbch_clipboard = 11;
 const int dbch_clipping = 12;
@@ -82,95 +82,96 @@ const int dbch_local = 70;
 const int dbch_mci = 71;
 const int dbch_mcianim = 72;
 const int dbch_mciavi = 73;
-const int dbch_mcimidi = 74;
-const int dbch_mciwave = 75;
-const int dbch_mdi = 76;
-const int dbch_menu = 77;
-const int dbch_message = 78;
-const int dbch_metafile = 79;
-const int dbch_midi = 80;
-const int dbch_mmaux = 81;
-const int dbch_mmio = 82;
-const int dbch_mmsys = 83;
-const int dbch_mmtime = 84;
-const int dbch_module = 85;
-const int dbch_monthcal = 86;
-const int dbch_mpr = 87;
-const int dbch_msacm = 88;
-const int dbch_msg = 89;
-const int dbch_msvideo = 90;
-const int dbch_nativefont = 91;
-const int dbch_nonclient = 92;
-const int dbch_ntdll = 93;
-const int dbch_odbc = 94;
-const int dbch_ole = 95;
-const int dbch_pager = 96;
-const int dbch_palette = 97;
-const int dbch_pidl = 98;
-const int dbch_print = 99;
-const int dbch_process = 100;
-const int dbch_profile = 101;
-const int dbch_progress = 102;
-const int dbch_prop = 103;
-const int dbch_propsheet = 104;
-const int dbch_psapi = 105;
-const int dbch_psdrv = 106;
-const int dbch_ras = 107;
-const int dbch_rebar = 108;
-const int dbch_reg = 109;
-const int dbch_region = 110;
-const int dbch_relay = 111;
-const int dbch_resource = 112;
-const int dbch_scroll = 113;
-const int dbch_security = 114;
-const int dbch_segment = 115;
-const int dbch_seh = 116;
-const int dbch_selector = 117;
-const int dbch_sendmsg = 118;
-const int dbch_server = 119;
-const int dbch_setupx = 120;
-const int dbch_shell = 121;
-const int dbch_snoop = 122;
-const int dbch_sound = 123;
-const int dbch_static = 124;
-const int dbch_statusbar = 125;
-const int dbch_storage = 126;
-const int dbch_stress = 127;
-const int dbch_string = 128;
-const int dbch_syscolor = 129;
-const int dbch_system = 130;
-const int dbch_tab = 131;
-const int dbch_tape = 132;
-const int dbch_tapi = 133;
-const int dbch_task = 134;
-const int dbch_text = 135;
-const int dbch_thread = 136;
-const int dbch_thunk = 137;
-const int dbch_timer = 138;
-const int dbch_toolbar = 139;
-const int dbch_toolhelp = 140;
-const int dbch_tooltips = 141;
-const int dbch_trackbar = 142;
-const int dbch_treeview = 143;
-const int dbch_ttydrv = 144;
-const int dbch_tweak = 145;
-const int dbch_typelib = 146;
-const int dbch_updown = 147;
-const int dbch_ver = 148;
-const int dbch_virtual = 149;
-const int dbch_vxd = 150;
-const int dbch_wave = 151;
-const int dbch_win = 152;
-const int dbch_win16drv = 153;
-const int dbch_win32 = 154;
-const int dbch_wing = 155;
-const int dbch_winsock = 156;
-const int dbch_winspool = 157;
-const int dbch_wnet = 158;
-const int dbch_x11 = 159;
-const int dbch_x11drv = 160;
+const int dbch_mcicda = 74;
+const int dbch_mcimidi = 75;
+const int dbch_mciwave = 76;
+const int dbch_mdi = 77;
+const int dbch_menu = 78;
+const int dbch_message = 79;
+const int dbch_metafile = 80;
+const int dbch_midi = 81;
+const int dbch_mmaux = 82;
+const int dbch_mmio = 83;
+const int dbch_mmsys = 84;
+const int dbch_mmtime = 85;
+const int dbch_module = 86;
+const int dbch_monthcal = 87;
+const int dbch_mpr = 88;
+const int dbch_msacm = 89;
+const int dbch_msg = 90;
+const int dbch_msvideo = 91;
+const int dbch_nativefont = 92;
+const int dbch_nonclient = 93;
+const int dbch_ntdll = 94;
+const int dbch_odbc = 95;
+const int dbch_ole = 96;
+const int dbch_pager = 97;
+const int dbch_palette = 98;
+const int dbch_pidl = 99;
+const int dbch_print = 100;
+const int dbch_process = 101;
+const int dbch_profile = 102;
+const int dbch_progress = 103;
+const int dbch_prop = 104;
+const int dbch_propsheet = 105;
+const int dbch_psapi = 106;
+const int dbch_psdrv = 107;
+const int dbch_ras = 108;
+const int dbch_rebar = 109;
+const int dbch_reg = 110;
+const int dbch_region = 111;
+const int dbch_relay = 112;
+const int dbch_resource = 113;
+const int dbch_scroll = 114;
+const int dbch_security = 115;
+const int dbch_segment = 116;
+const int dbch_seh = 117;
+const int dbch_selector = 118;
+const int dbch_sendmsg = 119;
+const int dbch_server = 120;
+const int dbch_setupx = 121;
+const int dbch_shell = 122;
+const int dbch_snoop = 123;
+const int dbch_sound = 124;
+const int dbch_static = 125;
+const int dbch_statusbar = 126;
+const int dbch_storage = 127;
+const int dbch_stress = 128;
+const int dbch_string = 129;
+const int dbch_syscolor = 130;
+const int dbch_system = 131;
+const int dbch_tab = 132;
+const int dbch_tape = 133;
+const int dbch_tapi = 134;
+const int dbch_task = 135;
+const int dbch_text = 136;
+const int dbch_thread = 137;
+const int dbch_thunk = 138;
+const int dbch_timer = 139;
+const int dbch_toolbar = 140;
+const int dbch_toolhelp = 141;
+const int dbch_tooltips = 142;
+const int dbch_trackbar = 143;
+const int dbch_treeview = 144;
+const int dbch_ttydrv = 145;
+const int dbch_tweak = 146;
+const int dbch_typelib = 147;
+const int dbch_updown = 148;
+const int dbch_ver = 149;
+const int dbch_virtual = 150;
+const int dbch_vxd = 151;
+const int dbch_wave = 152;
+const int dbch_win = 153;
+const int dbch_win16drv = 154;
+const int dbch_win32 = 155;
+const int dbch_wing = 156;
+const int dbch_winsock = 157;
+const int dbch_winspool = 158;
+const int dbch_wnet = 159;
+const int dbch_x11 = 160;
+const int dbch_x11drv = 161;
 
-#define DEBUG_CHANNEL_COUNT 161
+#define DEBUG_CHANNEL_COUNT 162
 
 char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
@@ -333,6 +334,7 @@ char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
 {1, 1, 0, 0},
 {1, 1, 0, 0},
+{1, 1, 0, 0},
 {1, 1, 0, 0}
 };
 
@@ -346,7 +348,7 @@ const char * const debug_ch_name[DEBUG_CHANNEL_COUNT] = {
 "bitblt",
 "bitmap",
 "caret",
-"cdaudio",
+"cdrom",
 "class",
 "clipboard",
 "clipping",
@@ -411,6 +413,7 @@ const char * const debug_ch_name[DEBUG_CHANNEL_COUNT] = {
 "mci",
 "mcianim",
 "mciavi",
+"mcicda",
 "mcimidi",
 "mciwave",
 "mdi",
diff --git a/misc/cdrom.c b/misc/cdrom.c
index d2c6e0d1192bb9e20c1c7da2b401a6c8f7803752..ddce8ea72f1d9b9ca5798a6ffd73f3c1712c824d 100644
--- a/misc/cdrom.c
+++ b/misc/cdrom.c
@@ -1,9 +1,10 @@
 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
 /*
- * Sample CDAUDIO Wine Driver for Linux
+ * Main file for CD-ROM support
  *
  * Copyright 1994 Martin Ayotte
  * Copyright 1999 Eric Pouech
+ * Copyright 2000 Andreas Mohr
  */
 
 #include <errno.h>
@@ -14,17 +15,17 @@
 #include "drive.h"
 #include "debugtools.h"
 
-DEFAULT_DEBUG_CHANNEL(cdaudio)
+DEFAULT_DEBUG_CHANNEL(cdrom);
 
 #define MAX_CDAUDIO_TRACKS 	256
 
 /**************************************************************************
- * 				CDAUDIO_Open			[internal]
+ * 				CDROM_Open			[internal]
  *
  * drive = 0, 1, ...
  *      or -1 (figure it out)
  */
-int	CDAUDIO_Open(WINE_CDAUDIO* wcda, int drive)
+int	CDROM_Open(WINE_CDAUDIO* wcda, int drive)
 {
     int i;
     BOOL avail = FALSE;
@@ -72,9 +73,9 @@ int	CDAUDIO_Open(WINE_CDAUDIO* wcda, int drive)
 }
 
 /**************************************************************************
- * 				CDAUDIO_GetMediaType		[internal]
+ * 				CDROM_GetMediaType		[internal]
  */
-int	CDAUDIO_GetMediaType(WINE_CDAUDIO* wcda)
+int	CDROM_GetMediaType(WINE_CDAUDIO* wcda)
 {
 #ifdef linux
     return ioctl(wcda->unixdev, CDROM_DISC_STATUS);
@@ -84,9 +85,9 @@ int	CDAUDIO_GetMediaType(WINE_CDAUDIO* wcda)
 }
 
 /**************************************************************************
- * 				CDAUDIO_Close			[internal]
+ * 				CDROM_Close			[internal]
  */
-int	CDAUDIO_Close(WINE_CDAUDIO* wcda)
+int	CDROM_Close(WINE_CDAUDIO* wcda)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     if (wcda->lpdwTrackLen != NULL) free(wcda->lpdwTrackLen);
@@ -100,9 +101,31 @@ int	CDAUDIO_Close(WINE_CDAUDIO* wcda)
 }
 
 /**************************************************************************
- * 				CDAUDIO_GetNumberOfTracks	[internal]
+ *				CDROM_Get_UPC			[internal]
+ *
+ * upc has to be 14 bytes long
+ */
+int CDROM_Get_UPC(WINE_CDAUDIO* wcda, LPSTR upc)
+{
+#ifdef linux
+    struct cdrom_mcn mcn;
+    int status = ioctl(wcda->unixdev, CDROM_GET_MCN, &mcn);
+    if (status)
+{
+	ERR("ioctl() failed with code %d\n",status);
+	return -1;
+    }
+    strcpy(upc, mcn.medium_catalog_number);
+    return 0;
+#else
+    return -1;
+#endif
+}
+
+/**************************************************************************
+ * 				CDROM_Audio_GetNumberOfTracks	[internal]
  */
-UINT16 CDAUDIO_GetNumberOfTracks(WINE_CDAUDIO* wcda)
+UINT16 CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO* wcda)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
 #ifdef linux
@@ -118,7 +141,7 @@ UINT16 CDAUDIO_GetNumberOfTracks(WINE_CDAUDIO* wcda)
 	if (ioctl(wcda->unixdev, CDIOREADTOCHEADER, &hdr))
 #endif
 	{
-	    WARN("(%p) -- Error occured (%d)!\n", wcda, errno);
+	    WARN("(%p) -- Error occurred (%d)!\n", wcda, errno);
 	    return (WORD)-1;
 	}
 #ifdef linux
@@ -137,9 +160,9 @@ UINT16 CDAUDIO_GetNumberOfTracks(WINE_CDAUDIO* wcda)
 }
 
 /**************************************************************************
- * 			CDAUDIO_GetTracksInfo			[internal]
+ * 			CDROM_Audio_GetTracksInfo		[internal]
  */
-BOOL CDAUDIO_GetTracksInfo(WINE_CDAUDIO* wcda)
+BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int		i, length;
@@ -153,7 +176,7 @@ BOOL CDAUDIO_GetTracksInfo(WINE_CDAUDIO* wcda)
 #endif
     
     if (wcda->nTracks == 0) {
-	if (CDAUDIO_GetNumberOfTracks(wcda) == (WORD)-1) return FALSE;
+	if (CDROM_Audio_GetNumberOfTracks(wcda) == (WORD)-1) return FALSE;
     }
     TRACE("nTracks=%u\n", wcda->nTracks);
     
@@ -204,7 +227,7 @@ BOOL CDAUDIO_GetTracksInfo(WINE_CDAUDIO* wcda)
 	{
 	    WARN("error read entry (%d)\n", errno);
 	    /* update status according to new status */
-	    CDAUDIO_GetCDStatus(wcda);
+	    CDROM_Audio_GetCDStatus(wcda);
 
 	    return FALSE;
 	}
@@ -248,9 +271,9 @@ BOOL CDAUDIO_GetTracksInfo(WINE_CDAUDIO* wcda)
 }
 
 /**************************************************************************
- * 				CDAUDIO_GetCDStatus		[internal]
+ * 				CDROM_Audio_GetCDStatus		[internal]
  */
-BOOL CDAUDIO_GetCDStatus(WINE_CDAUDIO* wcda)
+BOOL CDROM_Audio_GetCDStatus(WINE_CDAUDIO* wcda)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int		oldmode = wcda->cdaMode;
@@ -350,7 +373,7 @@ BOOL CDAUDIO_GetCDStatus(WINE_CDAUDIO* wcda)
 #endif
     
     if (oldmode != wcda->cdaMode && oldmode == WINE_CDA_OPEN) {
-	if (!CDAUDIO_GetTracksInfo(wcda)) {
+	if (!CDROM_Audio_GetTracksInfo(wcda)) {
 	    WARN("error updating TracksInfo !\n");
 	    return FALSE;
 	}
@@ -362,9 +385,9 @@ BOOL CDAUDIO_GetCDStatus(WINE_CDAUDIO* wcda)
 }
 
 /**************************************************************************
- * 				CDAUDIO_Play			[internal]
+ * 				CDROM_Audio_Play		[internal]
  */
-int	CDAUDIO_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD end)
+int	CDROM_Audio_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD end)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
 #ifdef linux
@@ -422,9 +445,9 @@ int	CDAUDIO_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD end)
 }
 
 /**************************************************************************
- * 				CDAUDIO_Stop			[internal]
+ * 				CDROM_Audio_Stop		[internal]
  */
-int	CDAUDIO_Stop(WINE_CDAUDIO* wcda)
+int	CDROM_Audio_Stop(WINE_CDAUDIO* wcda)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int	ret = 0;
@@ -440,9 +463,9 @@ int	CDAUDIO_Stop(WINE_CDAUDIO* wcda)
 }
 
 /**************************************************************************
- * 				CDAUDIO_Pause			[internal]
+ * 				CDROM_Audio_Pause		[internal]
  */
-int	CDAUDIO_Pause(WINE_CDAUDIO* wcda, int pauseOn)
+int	CDROM_Audio_Pause(WINE_CDAUDIO* wcda, int pauseOn)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int	ret = 0;    
@@ -458,9 +481,9 @@ int	CDAUDIO_Pause(WINE_CDAUDIO* wcda, int pauseOn)
 }
 
 /**************************************************************************
- * 				CDAUDIO_Seek			[internal]
+ * 				CDROM_Audio_Seek		[internal]
  */
-int	CDAUDIO_Seek(WINE_CDAUDIO* wcda, DWORD at)
+int	CDROM_Audio_Seek(WINE_CDAUDIO* wcda, DWORD at)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int				ret = 0;    
@@ -486,9 +509,9 @@ int	CDAUDIO_Seek(WINE_CDAUDIO* wcda, DWORD at)
 }
 
 /**************************************************************************
- * 				CDAUDIO_SetDoor			[internal]
+ * 				CDROM_SetDoor			[internal]
  */
-int	CDAUDIO_SetDoor(WINE_CDAUDIO* wcda, int open)
+int	CDROM_SetDoor(WINE_CDAUDIO* wcda, int open)
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int	ret = 0;    
@@ -511,9 +534,9 @@ int	CDAUDIO_SetDoor(WINE_CDAUDIO* wcda, int open)
 }
 
 /**************************************************************************
- * 				CDAUDIO_Reset			[internal]
+ * 				CDROM_Reset			[internal]
  */
-int	CDAUDIO_Reset(WINE_CDAUDIO* wcda) 
+int	CDROM_Reset(WINE_CDAUDIO* wcda) 
 {
 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
     int	ret = 0;
@@ -528,3 +551,121 @@ int	CDAUDIO_Reset(WINE_CDAUDIO* wcda)
 #endif
 }
 
+unsigned int get_offs_best_voldesc(int fd)
+{
+    BYTE cur_vd_type, max_vd_type = 0;
+    unsigned int offs, best_offs = 0;
+
+    for (offs=0x8000; offs <= 0x9800; offs += 0x800)
+    {
+        lseek(fd, offs, SEEK_SET);
+        read(fd, &cur_vd_type, 1);
+        if (cur_vd_type == 0xff)
+            break;
+        if (cur_vd_type > max_vd_type)
+        {
+            max_vd_type = cur_vd_type;
+            best_offs = offs;
+        }
+    }
+    return best_offs;
+}
+
+/**************************************************************************
+ *				CDROM_Audio_GetSerial		[internal]
+ */
+DWORD CDROM_Audio_GetSerial(WINE_CDAUDIO* wcda)
+{
+    unsigned long serial = 0;
+    int i;
+    DWORD dwFrame, msf;
+    WORD wMinutes, wSeconds, wFrames;
+
+    for (i = 0; i < wcda->nTracks; i++) {
+	dwFrame = wcda->lpdwTrackPos[i];
+	wMinutes = dwFrame / CDFRAMES_PERMIN;
+	wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
+	wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
+	msf = CDROM_MAKE_MSF(wMinutes, wSeconds, wFrames);
+
+	serial += (CDROM_MSF_MINUTE(msf) << 16) +
+	(CDROM_MSF_SECOND(msf) << 8) +
+	(CDROM_MSF_FRAME(msf));
+    }
+    return serial;
+}
+
+/**************************************************************************
+ *				CDROM_Data_GetSerial		[internal]
+ */
+DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda)
+{
+    unsigned int offs = get_offs_best_voldesc(wcda->unixdev);
+    union {
+	unsigned long val;
+	unsigned char p[4];
+    } serial;
+
+    serial.val = 0;
+    if (offs)
+    {
+	BYTE buf[2048];
+	int i;
+
+	lseek(wcda->unixdev,offs,SEEK_SET);
+	read(wcda->unixdev,buf,2048);
+	for(i=0; i<2048; i+=4)
+	{
+	    /* DON'T optimize this into DWORD !! (breaks overflow) */
+	    serial.p[0] += buf[i+0];
+	    serial.p[1] += buf[i+1];
+	    serial.p[2] += buf[i+2];
+	    serial.p[3] += buf[i+3];
+	}
+    }
+    return serial.val;
+}
+
+/**************************************************************************
+ *				CDROM_GetSerial			[internal]
+ */
+DWORD CDROM_GetSerial(int drive)
+{
+    WINE_CDAUDIO wcda;
+    DWORD serial = 0;
+
+    /* EXPIRES 01.01.2001 */
+    FIXME("CD-ROM serial number calculation might fail.\n");
+    FIXME("Please test with as many exotic CDs as possible !\n");
+
+    if (!(CDROM_Open(&wcda, drive)))
+    {
+	int media = CDROM_GetMediaType(&wcda);
+	LPSTR p;
+
+	if (media == CDS_AUDIO)
+	{
+	    if (!(CDROM_Audio_GetCDStatus(&wcda))) {
+		ERR("couldn't get CD status !\n");
+		CDROM_Close(&wcda);
+		return 0;
+	    }
+	    serial = CDROM_Audio_GetSerial(&wcda);
+	}
+	else
+	if (media > CDS_AUDIO)
+	    /* hopefully a data CD */
+	    serial = CDROM_Data_GetSerial(&wcda);
+
+	p = (media == CDS_AUDIO) ? "Audio " :
+	    (media > CDS_AUDIO) ? "Data " : "";
+	if (serial)
+	    FIXME("%sCD serial number is %04x-%04x.\n",
+		p, HIWORD(serial), LOWORD(serial));
+	else
+	    ERR("couldn't get %sCD serial !\n", p);
+	CDROM_Close(&wcda);
+    }
+    return serial;
+}
+
diff --git a/msdos/int2f.c b/msdos/int2f.c
index e66cf1ac0e39594ac924a4ba3abdd4c6d9e2eaf4..4ccb01327d2faffa58934b9fad8bf9d58ed30cff 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -516,7 +516,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
 	     *       - the current implementation only supports a single CD ROM
 	     */
 	    if (wcda.unixdev <= 0) 
-		CDAUDIO_Open(&wcda, -1);
+		CDROM_Open(&wcda, -1);
 	    TRACE("CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]);
 	    
 	    for (drive = 0; 
@@ -534,7 +534,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
 	    
 	    /* set status to 0 */
 	    PTR_AT(driver_request, 3, WORD) = 0;
-	    CDAUDIO_GetCDStatus(&wcda);
+	    CDROM_Audio_GetCDStatus(&wcda);
 	    
 	    switch (driver_request[2]) {
 	    case 3:
@@ -710,22 +710,22 @@ static void MSCDEX_Handler(CONTEXT86* context)
 		TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]); 
 		switch (io_stru[0]) {
 		case 0: /* eject */ 
-		    CDAUDIO_SetDoor(&wcda, 1);
+		    CDROM_SetDoor(&wcda, 1);
 		    TRACE(" ----> EJECT\n"); 
 		    break;
 		case 2: /* reset drive */
-		    CDAUDIO_Reset(&wcda);
+		    CDROM_Reset(&wcda);
 		    TRACE(" ----> RESET\n"); 
 		    break;
 		case 3: /* Audio Channel Control */
 		    FIXME(" ----> AUDIO CHANNEL CONTROL (NIY)\n");
 		    break;
 		case 5: /* close tray */
-		    CDAUDIO_SetDoor(&wcda, 0);
+		    CDROM_SetDoor(&wcda, 0);
 		    TRACE(" ----> CLOSE TRAY\n"); 
 		    break;
 		default:
-		    FIXME(" IOCTL OUPUT: Unimplemented <%d>!!\n", io_stru[0]); 
+		    FIXME(" IOCTL OUTPUT: Unimplemented <%d>!!\n", io_stru[0]); 
 		    Error = 0x0c;
 		    break;	
 		}	
@@ -750,7 +750,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
 			    LOBYTE(LOWORD(at));
 			/* fall thru */
 		    case 0: /* HSG addressing mode */
-			CDAUDIO_Seek(&wcda, at);
+			CDROM_Audio_Seek(&wcda, at);
 			break;
 		    default:
 			ERR("Unsupported address mode !!\n");
@@ -783,7 +783,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
 			    LOBYTE(LOWORD(end));
 			/* fall thru */
 		    case 0: /* HSG addressing mode */
-			CDAUDIO_Play(&wcda, beg, end);
+			CDROM_Audio_Play(&wcda, beg, end);
 			break;
 		    default:
 			ERR("Unsupported address mode !!\n");
@@ -795,17 +795,17 @@ static void MSCDEX_Handler(CONTEXT86* context)
 		
 	    case 133:
 		if (wcda.cdaMode == WINE_CDA_PLAY) {
-		    CDAUDIO_Pause(&wcda, 1);
+		    CDROM_Audio_Pause(&wcda, 1);
 		    TRACE(" --> STOP AUDIO (Paused)\n");
 		} else {
-		    CDAUDIO_Stop(&wcda);
+		    CDROM_Audio_Stop(&wcda);
 		    TRACE(" --> STOP AUDIO (Stopped)\n");
 		}
 		break;
 		
 	    case 136:
 		TRACE(" --> RESUME AUDIO\n");
-		CDAUDIO_Pause(&wcda, 0);
+		CDROM_Audio_Pause(&wcda, 0);
 		break;
 		
 	    default: