diff --git a/dlls/winmm/mcicda/mcicda.c b/dlls/winmm/mcicda/mcicda.c
index 9a87d187004ec35b0d0b0700003d9d5060480904..77451c34c6a9995cca8b1f9fb6c4885bc076dd31 100644
--- a/dlls/winmm/mcicda/mcicda.c
+++ b/dlls/winmm/mcicda/mcicda.c
@@ -242,7 +242,7 @@ static DWORD CDAUDIO_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpe
     }
 
     wmcda->wNotifyDeviceID = dwDeviceID;
-    if (CDAUDIO_Open(&wmcda->wcda) == -1) {
+    if (CDAUDIO_Open(&wmcda->wcda, -1) == -1) {
 	--wmcda->nUseCount;
 	return MCIERR_HARDWARE;
     }
diff --git a/documentation/cdrom-labels b/documentation/cdrom-labels
index a2f2bca8f71ae2fc5f56918b9fe7245e07344d51..ce3bc7c81f770eacc01a9df3b0eed47d0f8baf7d 100644
--- a/documentation/cdrom-labels
+++ b/documentation/cdrom-labels
@@ -1,60 +1,70 @@
-*** VOLUME LABEL
-
-If a program depends on the correct label and/or serial number for the
-CD-Rom, you can use the following command to extract that information:
-
-      dd if=<your cdrom device> bs=1 skip=32808 count=32
-
-You need read access to the device, so perhaps you have to do it as root.
-Put the resulting string (without trailing blanks) into your
-wine.ini/.winerc file like:
-Label=<the label>
-
-*** SERIAL NUMBER
-
-[FIXME: if someone knows how to get the serial number in Linux, please
-        put this information here].
-
-If you have access to a Win32 system and C-compiler, you can compile the
-following program to extract this information:
-
-------------------------- begin volinfo.c ---------------------------
-#include <windows.h>
-#include <stdio.h>
-
-int main(int argc,char **argv[])
-{
-    char  drive, root[]="C:\\", label[1002], fsname[1002];
-    DWORD serial, flags, filenamelen, labellen = 1000, fsnamelen = 1000;
-
-    printf("Drive Serial     Flags      Filename-Length "
-           "Label                 Fsname\n");
-    for (drive = 'C'; drive <= 'Z'; drive++)
-    {
-        root[0] = drive;
-        if (GetVolumeInformationA(root,label,labellen,&serial,
-                                  &filenamelen,&flags,fsname,fsnamelen))
-        {
-            strcat(label,"\""); strcat (fsname,"\"");
-            printf("%c:\\   0x%08lx 0x%08lx %15ld \"%-20s \"%-20s\n",
-                   drive, (long) serial, (long) flags, (long) filenamelen,
-                   label, fsname);
-        }
-    }
-    return 0;
-}
-
-Probably you can get that information also from the File Manager in
-Windows.
-
-------------------------- end volinfo.c -----------------------------
-
-
-*** DRIVE LETTER
-
-Some installed programs only look for the CD-Rom in the drive letter
-that the CD-Rom had when the program was installed. In this case, make
-sure you use the correct letter, especially if you installed the
-program under Windows and are now trying to run it in Wine.
-Some programs reportedly store the drive letter in their .INI file,
-so you might look there and try to change it.
+               Drive labels and serial numbers with wine
+               -----------------------------------------
+
+       Until now, your only possibility of specifying drive volume labels
+and serial numbers was to set them manually in the wine config file.
+By now, wine can read them directly from the device as well. This may be
+useful for many Win 9x games or for setup programs distributed on CD-ROMs
+that check for volume label.
+
+WHAT'S SUPPORTED ?
+
+    *  FAT systems (types 'hd' and 'floppy'): reads labels and serial num's.
+    *  Iso9660 ('cdrom'):                     reads labels only.
+
+HOW TO SET UP ?
+
+	Reading labels and serial numbers just works automagically if
+you specify a 'Device=' line in the [Drive X] section in your wine.conf.
+Note that the device has to exist and must be accessible if you do this,
+though.
+If you don't do that, then you should give fixed 'Label=' or 'Serial=' entries
+in wine.conf, as Wine returns these entries instead if no device is given.
+If they don't exist, then Wine will return default values (label "Drive X"
+and serial 12345678).
+
+Now a seldom needed one:
+If you want to give a 'Device=' entry *only* for drive raw sector accesses, but
+not for reading the volume info from the device (i.e. you want a *fixed*,
+preconfigured label), you need to specify 'ReadVolInfo=0' to tell Wine to skip
+the volume reading.
+
+EXAMPLES
+
+*** Simple example of cdrom and floppy; labels will be read from the device on
+both cdrom and floppy; serial numbers on floppy only:
+
+[Drive A]
+Path=/mnt/floppy
+Type=floppy
+Device=/dev/fd0
+Filesystem=msdos
+
+[Drive R]
+Path=/mnt/cdrom
+Type=cdrom
+Device=/dev/hda1
+Filesystem=win95
+
+*** CD-ROM. We want to override the label:
+
+[Drive J]
+Path=/mnt/cdrom
+Type=cdrom
+Label=X234GCDSE
+; note that the device isn't really needed here as we have a fixed label
+Device=/dev/cdrom
+Filesystem=msdos
+
+TODO / OPEN ISSUES
+
+ - The cdrom label can be read only if the data track of the disk resides in
+the first track and the cdrom is iso9660.
+ - Better checking for FAT superblock (it now check's only one byte).
+ - Support for labels/serial num's WRITING.
+ - Can the label be longer than 11 chars? (iso9660 has 32 chars).
+ - What about reading ext2 volume label? ....
+
+Petr Tomasek				changes by:	Andreas Mohr
+<tomasek@etf.cuni.cz>					<a.mohr@mailto.de>
+Nov 14 1999						Jan 25 2000
diff --git a/files/drive.c b/files/drive.c
index 7363c2f7333f5262b4c0b6ab5550f745fcdb1f1e..865439f020fe5941a30d6e1b467bb8c924b39b42 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -3,6 +3,11 @@
  *
  * Copyright 1993 Erik Bos
  * Copyright 1996 Alexandre Julliard
+ *
+ * Label & serial number read support.
+ *  (c) 1999 Petr Tomasek <tomasek@etf.cuni.cz>
+ *  (c) 2000 Andreas Mohr (changes)
+ *
  */
 
 #include "config.h"
@@ -37,6 +42,7 @@
 #include "wine/winestring.h"  /* for lstrcpyAtoW */
 #include "winerror.h"
 #include "drive.h"
+#include "cdrom.h"
 #include "file.h"
 #include "heap.h"
 #include "msdos.h"
@@ -54,8 +60,10 @@ typedef struct
     char     *dos_cwd;   /* cwd in DOS format without leading or trailing \ */
     char     *unix_cwd;  /* cwd in Unix format without leading or trailing / */
     char     *device;    /* raw device path */
-    char      label[12]; /* drive label */
-    DWORD     serial;    /* drive serial number */
+    BOOL      read_volinfo; /* read the volume info from the device ? */
+    char      label_conf[12]; /* drive label as cfg'd in wine.conf */
+    char      label_read[12]; /* drive label as read from device */
+    DWORD     serial_conf;    /* drive serial number as cfg'd in wine.conf */
     DRIVETYPE type;      /* drive type */
     UINT    flags;     /* drive flags */
     dev_t     dev;       /* unix device number */
@@ -111,7 +119,8 @@ static DRIVETYPE DRIVE_GetDriveType( const char *name )
     {
         if (!strcasecmp( buffer, DRIVE_Types[i] )) return (DRIVETYPE)i;
     }
-    MESSAGE("%s: unknown type '%s', defaulting to 'hd'.\n", name, buffer );
+    MESSAGE("%s: unknown drive type '%s', defaulting to 'hd'.\n",
+	name, buffer );
     return TYPE_HD;
 }
 
@@ -175,18 +184,18 @@ int DRIVE_Init(void)
             drive->ino      = drive_stat_buffer.st_ino;
 
             /* Get the drive label */
-            PROFILE_GetWineIniString( name, "Label", name, drive->label, 12 );
-            if ((len = strlen(drive->label)) < 11)
+            PROFILE_GetWineIniString( name, "Label", name, drive->label_conf, 12 );
+            if ((len = strlen(drive->label_conf)) < 11)
             {
                 /* Pad label with spaces */
-                memset( drive->label + len, ' ', 11 - len );
-                drive->label[12] = '\0';
+                memset( drive->label_conf + len, ' ', 11 - len );
+                drive->label_conf[11] = '\0';
             }
 
             /* Get the serial number */
             PROFILE_GetWineIniString( name, "Serial", "12345678",
                                       buffer, sizeof(buffer) );
-            drive->serial = strtoul( buffer, NULL, 16 );
+            drive->serial_conf = strtoul( buffer, NULL, 16 );
 
             /* Get the filesystem type */
             PROFILE_GetWineIniString( name, "Filesystem", "win95",
@@ -197,7 +206,13 @@ int DRIVE_Init(void)
             PROFILE_GetWineIniString( name, "Device", "",
                                       buffer, sizeof(buffer) );
             if (buffer[0])
+	    {
                 drive->device = HEAP_strdupA( SystemHeap, 0, buffer );
+		drive->read_volinfo =
+		(BOOL)PROFILE_GetWineIniInt( name, "ReadVolInfo", 1);
+	    }
+	    else
+		drive->read_volinfo = FALSE;
 
             /* Make the first hard disk the current drive */
             if ((DRIVE_CurDrive == -1) && (drive->type == TYPE_HD))
@@ -207,7 +222,7 @@ int DRIVE_Init(void)
             TRACE("%s: path=%s type=%s label='%s' serial=%08lx "
                   "flags=%08x dev=%x ino=%x\n",
                   name, path, DRIVE_Types[drive->type],
-                  drive->label, drive->serial, drive->flags,
+                  drive->label_conf, drive->serial_conf, drive->flags,
                   (int)drive->dev, (int)drive->ino );
         }
         else WARN("%s: not defined\n", name );
@@ -220,8 +235,8 @@ int DRIVE_Init(void)
         DOSDrives[2].root     = HEAP_strdupA( SystemHeap, 0, "/" );
         DOSDrives[2].dos_cwd  = HEAP_strdupA( SystemHeap, 0, "" );
         DOSDrives[2].unix_cwd = HEAP_strdupA( SystemHeap, 0, "" );
-        strcpy( DOSDrives[2].label, "Drive C    " );
-        DOSDrives[2].serial   = 0x12345678;
+        strcpy( DOSDrives[2].label_conf, "Drive C    " );
+        DOSDrives[2].serial_conf   = 12345678;
         DOSDrives[2].type     = TYPE_HD;
         DOSDrives[2].flags    = 0;
         DRIVE_CurDrive = 2;
@@ -395,23 +410,162 @@ const char * DRIVE_GetUnixCwd( int drive )
 }
 
 
+/***********************************************************************
+ *           DRIVE_GetDevice
+ */
+const char * DRIVE_GetDevice( int drive )
+{
+    return (DRIVE_IsValid( drive )) ? DOSDrives[drive].device : NULL;
+}
+
+
+/***********************************************************************
+ *           DRIVE_ReadSuperblock
+ *
+ * Used in DRIVE_GetLabel
+ */
+int DRIVE_ReadSuperblock (int drive, char * buff)
+{
+#define DRIVE_SUPER 96
+    int fd;
+    off_t offs;
+
+    if (memset(buff,0,DRIVE_SUPER)!=buff) return -1;
+    if ((fd=open(DOSDrives[drive].device,O_RDONLY)) == -1)
+    {
+	struct stat st;
+	if (!DOSDrives[drive].device)
+	    ERR("No device configured for drive %c: !\n", 'A'+drive);
+	else
+	    ERR("Couldn't open device '%s' for drive %c: ! (%s)\n", DOSDrives[drive].device, 'A'+drive,
+		 (stat(DOSDrives[drive].device, &st)) ?
+			"not available or symlink not valid ?" : "no permission");
+	ERR("Can't read drive volume info ! Either pre-set it or make sure the device to read it from is accessible !\n");
+	PROFILE_UsageWineIni();
+	return -1;
+    }
+
+    switch(DOSDrives[drive].type)
+    {
+	case TYPE_FLOPPY:
+	case TYPE_HD:
+	    offs = 0;
+	    break;
+	case TYPE_CDROM:
+	/* FIXME: Maybe we should search for the first data track on the CD,
+		  not just assume that it is the first track */
+	    offs = (off_t)2048*(16+0);
+	    break;
+		default:
+		    offs = 0;
+		    break;
+    }
+
+    if ((offs) && (lseek(fd,offs,SEEK_SET)!=offs)) return -4;
+    if (read(fd,buff,DRIVE_SUPER)!=DRIVE_SUPER) return -2;
+
+    switch(DOSDrives[drive].type)
+    {
+	case TYPE_FLOPPY:
+	case TYPE_HD:
+	    if (buff[0x26]!=0x29) /* Check for FAT present */
+		return -3;
+		break;
+	case TYPE_CDROM:
+	    if (strncmp(&buff[1],"CD001",5)) /* Check for iso9660 present */
+		return -3;
+	    /* FIXME: do we need to check for "CDROM", too ? (high sierra) */
+		break;
+	default:
+		return -3;
+		break;
+    }
+
+    return close(fd);
+}
+
+
 /***********************************************************************
  *           DRIVE_GetLabel
  */
 const char * DRIVE_GetLabel( int drive )
 {
+    int read = 0;
+    char buff[DRIVE_SUPER];
+    int offs = -1;
+
     if (!DRIVE_IsValid( drive )) return NULL;
-    return DOSDrives[drive].label;
+    if (DRIVE_GetType(drive) == TYPE_CDROM)
+    {
+	WINE_CDAUDIO wcda;
+
+	if (!(CDAUDIO_Open(&wcda, drive)))
+	{
+	    int media = CDAUDIO_GetMediaType(&wcda);
+
+	    if (media == CDS_AUDIO)
+	    {
+		strcpy(DOSDrives[drive].label_read, "Audio CD   ");
+		read = 1;
+	    }
+	    else
+	    if (media == CDS_NO_INFO)
+	    {
+		strcpy(DOSDrives[drive].label_read, "           ");
+		read = 1;
+	    }
+
+	    CDAUDIO_Close(&wcda);
+}
+    }
+    if ((!read) && (DOSDrives[drive].read_volinfo))
+    {
+	if (DRIVE_ReadSuperblock(drive,(char *) buff))
+	    ERR("Invalid or unreadable superblock on %s (%c:).\n",
+		DOSDrives[drive].device, (char)(drive+'A'));
+	else {
+	    if (DOSDrives[drive].type == TYPE_CDROM)
+		offs = 40;
+	    else
+	    if (DOSDrives[drive].type == TYPE_FLOPPY ||
+		DOSDrives[drive].type == TYPE_HD)
+		offs = 0x2b;
+
+	    /* FIXME: ISO9660 uses 32-bytes long label. Should we do also? */
+	    if (offs != -1) memcpy(DOSDrives[drive].label_read,buff+offs,11);
+	    DOSDrives[drive].label_read[11]='\0';
+	    read = 1;
+	}
+    }
+
+    return (read) ?
+	DOSDrives[drive].label_read : DOSDrives[drive].label_conf;
 }
 
 
 /***********************************************************************
  *           DRIVE_GetSerialNumber
+ *
+ * FIXME: apparently Win 9x (not DOS !) gives serial numbers to CD-ROMs, too.
+ * How to calculate them ?
  */
 DWORD DRIVE_GetSerialNumber( int drive )
 {
+char buff[DRIVE_SUPER];
+
     if (!DRIVE_IsValid( drive )) return 0;
-    return DOSDrives[drive].serial;
+    if ( (DOSDrives[drive].read_volinfo) &&
+        ((DOSDrives[drive].type == TYPE_FLOPPY) ||
+         (DOSDrives[drive].type == 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'));
+      else
+        return *((DWORD*)(buff+0x27));
+    }
+    return DOSDrives[drive].serial_conf;
 }
 
 
@@ -421,7 +575,10 @@ DWORD DRIVE_GetSerialNumber( int drive )
 int DRIVE_SetSerialNumber( int drive, DWORD serial )
 {
     if (!DRIVE_IsValid( drive )) return 0;
-    DOSDrives[drive].serial = serial;
+    if ((DOSDrives[drive].read_volinfo) &&
+	(DOSDrives[drive].type != TYPE_CDROM))
+	FIXME("Setting the serial number is useless for drive %c: until writing it is properly implemented, as this drive reads it from the device.\n", 'A'+drive);
+    DOSDrives[drive].serial_conf = serial;
     return 1;
 }
 
@@ -556,8 +713,8 @@ int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive )
     new->root = HEAP_strdupA( SystemHeap, 0, old->root );
     new->dos_cwd = HEAP_strdupA( SystemHeap, 0, old->dos_cwd );
     new->unix_cwd = HEAP_strdupA( SystemHeap, 0, old->unix_cwd );
-    memcpy ( new->label, old->label, 12 );
-    new->serial = old->serial;
+    memcpy ( new->label_conf, old->label_conf, 12 );
+    new->serial_conf = old->serial_conf;
     new->type = old->type;
     new->flags = old->flags;
     new->dev = old->dev;
@@ -922,7 +1079,7 @@ BOOL WINAPI GetDiskFreeSpaceExW( LPCWSTR root, PULARGE_INTEGER avail,
 
 /***********************************************************************
  *           GetDriveType16   (KERNEL.136)
- * This functions returns the drivetype of a drive in Win16. 
+ * This function returns the type of a drive in Win16. 
  * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
  * remote drive API. The returnvalue DRIVE_REMOTE for CD-ROMs has been
  * verified on Win3.11 and Windows 95. Some programs rely on it, so don't
@@ -972,7 +1129,7 @@ UINT16 WINAPI GetDriveType16(
  *
  *  Currently returns DRIVE_DOESNOTEXIST and DRIVE_CANNOTDETERMINE
  *  when it really should return DRIVE_NO_ROOT_DIR and DRIVE_UNKNOWN.
- *  Why where the former defines used?
+ *  Why were the former defines used?
  *
  *  DRIVE_RAMDISK is unsupported.
  */
@@ -1173,7 +1330,11 @@ DWORD WINAPI GetLogicalDrives(void)
     int drive;
 
     for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
-        if (DRIVE_IsValid(drive)) ret |= (1 << drive);
+    {
+        if ( (DRIVE_IsValid(drive)) ||
+            (DOSDrives[drive].type == TYPE_CDROM)) /* audio CD is also valid */
+            ret |= (1 << drive);
+    }
     return ret;
 }
 
@@ -1189,7 +1350,7 @@ BOOL WINAPI GetVolumeInformationA( LPCSTR root, LPSTR label,
     int drive;
     char *cp;
 
-    /* FIXME, SetLastErrors missing */
+    /* FIXME, SetLastError()s missing */
 
     if (!root) drive = DRIVE_GetCurrentDrive();
     else
@@ -1212,7 +1373,7 @@ BOOL WINAPI GetVolumeInformationA( LPCSTR root, LPSTR label,
     if (serial) *serial = DRIVE_GetSerialNumber(drive);
 
     /* Set the filesystem information */
-    /* Note: we only emulate a FAT fs at the present */
+    /* Note: we only emulate a FAT fs at present */
 
     if (filename_len) {
     	if (DOSDrives[drive].flags & DRIVE_SHORT_NAMES)
diff --git a/include/cdrom.h b/include/cdrom.h
index 660325ce5d8c69a8b74ce57d7987bcf98a8e8778..18bdd7316ebea4c75b763c15d16e442e7f8ae7a2 100644
--- a/include/cdrom.h
+++ b/include/cdrom.h
@@ -54,7 +54,8 @@ typedef struct {
 #define	WINE_CDA_STOP			0x04
 #define	WINE_CDA_PAUSE			0x05
 
-int	CDAUDIO_Open(WINE_CDAUDIO* wcda);
+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);
@@ -74,5 +75,9 @@ BOOL	CDAUDIO_GetCDStatus(WINE_CDAUDIO* wcda);
 #define CDROM_DATA_TRACK 0x04
 #endif
 
+/* values borrowed from Linux 2.2.x cdrom.h */
+#define CDS_NO_INFO			0
+#define CDS_AUDIO			100
+
 #endif
 
diff --git a/include/debugdefs.h b/include/debugdefs.h
index dd649e449d47b567552526147e5fabf7cc2352ff..4ee0ba68bd9b73db3cdeb69acbad24ae48c0ae21 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -128,48 +128,49 @@ const int dbch_seh = 116;
 const int dbch_selector = 117;
 const int dbch_sendmsg = 118;
 const int dbch_server = 119;
-const int dbch_shell = 120;
-const int dbch_snoop = 121;
-const int dbch_sound = 122;
-const int dbch_static = 123;
-const int dbch_statusbar = 124;
-const int dbch_storage = 125;
-const int dbch_stress = 126;
-const int dbch_string = 127;
-const int dbch_syscolor = 128;
-const int dbch_system = 129;
-const int dbch_tab = 130;
-const int dbch_tape = 131;
-const int dbch_tapi = 132;
-const int dbch_task = 133;
-const int dbch_text = 134;
-const int dbch_thread = 135;
-const int dbch_thunk = 136;
-const int dbch_timer = 137;
-const int dbch_toolbar = 138;
-const int dbch_toolhelp = 139;
-const int dbch_tooltips = 140;
-const int dbch_trackbar = 141;
-const int dbch_treeview = 142;
-const int dbch_ttydrv = 143;
-const int dbch_tweak = 144;
-const int dbch_typelib = 145;
-const int dbch_updown = 146;
-const int dbch_ver = 147;
-const int dbch_virtual = 148;
-const int dbch_vxd = 149;
-const int dbch_wave = 150;
-const int dbch_win = 151;
-const int dbch_win16drv = 152;
-const int dbch_win32 = 153;
-const int dbch_wing = 154;
-const int dbch_winsock = 155;
-const int dbch_winspool = 156;
-const int dbch_wnet = 157;
-const int dbch_x11 = 158;
-const int dbch_x11drv = 159;
+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;
 
-#define DEBUG_CHANNEL_COUNT 160
+#define DEBUG_CHANNEL_COUNT 161
 
 char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
@@ -331,6 +332,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}
 };
 
@@ -455,6 +457,7 @@ const char * const debug_ch_name[DEBUG_CHANNEL_COUNT] = {
 "selector",
 "sendmsg",
 "server",
+"setupx",
 "shell",
 "snoop",
 "sound",
diff --git a/include/drive.h b/include/drive.h
index 891ae7e9c9bd5f6a1fac7c4fd53b714bd57f7227..9328af8c85bd8de23c07f47e1c827004bd335b9f 100644
--- a/include/drive.h
+++ b/include/drive.h
@@ -35,6 +35,7 @@ extern int DRIVE_FindDriveRoot( const char **path );
 extern const char * DRIVE_GetRoot( int drive );
 extern const char * DRIVE_GetDosCwd( int drive );
 extern const char * DRIVE_GetUnixCwd( int drive );
+extern const char * DRIVE_GetDevice( int drive );
 extern const char * DRIVE_GetLabel( int drive );
 extern DWORD DRIVE_GetSerialNumber( int drive );
 extern int DRIVE_SetSerialNumber( int drive, DWORD serial );
diff --git a/libtest/volinfo.c b/libtest/volinfo.c
index 7b64afcf6efd56dafdc8852c2606ab818b9c335e..26d112a2f1ef990dba098b74e99a4d682ddc13a2 100644
--- a/libtest/volinfo.c
+++ b/libtest/volinfo.c
@@ -13,7 +13,7 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 
     printf("Drive Serial     Flags      Filename-Length "
            "Label                 Fsname\n");
-    for (drive = 'C'; drive <= 'Z'; drive++)
+    for (drive = 'A'; drive <= 'Z'; drive++)
     {
         root[0] = drive;
         if (GetVolumeInformation(root,label,labellen,&serial,
diff --git a/misc/cdrom.c b/misc/cdrom.c
index 098737c56cb85fe3dd1371ec0db2ce28ac3cb452..d2c6e0d1192bb9e20c1c7da2b401a6c8f7803752 100644
--- a/misc/cdrom.c
+++ b/misc/cdrom.c
@@ -11,29 +11,53 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "cdrom.h"
+#include "drive.h"
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(cdaudio)
 
-#if defined(__NetBSD__)
-# define CDAUDIO_DEV "/dev/rcd0d"
-#elif defined(__FreeBSD__)
-# define CDAUDIO_DEV "/dev/rcd0c"
-#else
-# define CDAUDIO_DEV "/dev/cdrom"
-#endif
-
 #define MAX_CDAUDIO_TRACKS 	256
 
 /**************************************************************************
  * 				CDAUDIO_Open			[internal]
+ *
+ * drive = 0, 1, ...
+ *      or -1 (figure it out)
  */
-int	CDAUDIO_Open(WINE_CDAUDIO* wcda)
+int	CDAUDIO_Open(WINE_CDAUDIO* wcda, int drive)
 {
-#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
-    wcda->unixdev = open(CDAUDIO_DEV, O_RDONLY | O_NONBLOCK, 0);
+    int i;
+    BOOL avail = FALSE;
+    const char *dev;
+
+    if (drive == -1)
+    {
+	for (i=0; i < MAX_DOS_DRIVES; i++)
+	    if (DRIVE_GetType(i) == TYPE_CDROM)
+	    {
+		drive = i;
+		avail = TRUE;
+		break;
+	    }
+    }
+    else
+	avail = TRUE;
+    
+    if (avail == FALSE)
+    {
+	WARN("No CD-ROM #%d found !\n", drive);
+	return -1;
+    }
+    if ((dev = DRIVE_GetDevice(drive)) == NULL)
+{
+	WARN("No device entry for CD-ROM #%d (drive %c:) found !\n",
+		drive, 'A' + drive);
+	return -1;
+    }
+
+    wcda->unixdev = open(dev, O_RDONLY | O_NONBLOCK, 0);
     if (wcda->unixdev == -1) {
-	WARN("can't open '%s'!.  errno=%d\n", CDAUDIO_DEV, errno);
+	WARN("can't open '%s'!.  errno=%d\n", dev, errno);
 	return -1;
     }
     wcda->cdaMode = WINE_CDA_OPEN;	/* to force reading tracks info */
@@ -45,8 +69,16 @@ int	CDAUDIO_Open(WINE_CDAUDIO* wcda)
     wcda->lpdwTrackPos = NULL;
     wcda->lpbTrackFlags = NULL;
     return 0;
+}
+
+/**************************************************************************
+ * 				CDAUDIO_GetMediaType		[internal]
+ */
+int	CDAUDIO_GetMediaType(WINE_CDAUDIO* wcda)
+{
+#ifdef linux
+    return ioctl(wcda->unixdev, CDROM_DISC_STATUS);
 #else
-    wcda->unixdev = -1;
     return -1;
 #endif
 }
diff --git a/msdos/int2f.c b/msdos/int2f.c
index 517185f511c7897e1e7ac290cc23d2f328e411bc..e66cf1ac0e39594ac924a4ba3abdd4c6d9e2eaf4 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -490,7 +490,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
 	TRACE("Get drive letters\n");
 	break;
 	
-    case 0x10: /* direct driver acces */
+    case 0x10: /* direct driver access */
 	{
 	    static 	WINE_CDAUDIO	wcda;
 	    BYTE* 	driver_request;
@@ -511,12 +511,12 @@ static void MSCDEX_Handler(CONTEXT86* context)
 		driver_request[3] = 5;	/* bad request length */
 		return;
 	    }
-	    /* FIXME - would be better to open the device at the begining of the wine session...
+	    /* FIXME - would be better to open the device at the beginning of the wine session...
 	     *       - the device is also never closed...
 	     *       - the current implementation only supports a single CD ROM
 	     */
 	    if (wcda.unixdev <= 0) 
-		CDAUDIO_Open(&wcda);
+		CDAUDIO_Open(&wcda, -1);
 	    TRACE("CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]);
 	    
 	    for (drive = 0; 
diff --git a/wine.ini b/wine.ini
index efad4d80542d9824c0b9c87f2db8483f85662505..268fcc1f43cc9e1132c509bc227db2596464f0e0 100644
--- a/wine.ini
+++ b/wine.ini
@@ -34,6 +34,8 @@ Path=/cdrom
 Type=cdrom
 Label=CD-Rom
 Filesystem=win95
+; make sure that device is correct and has proper permissions !
+Device=/dev/cdrom
 
 [Drive E]
 Path=/tmp