Added a per-drive FailReadOnly flag, and removed the global
--failreadonly option.

diff --git a/documentation/wine.conf.man.in b/documentation/wine.conf.man.in
index 7c827ce..0587788 100644
--- a/documentation/wine.conf.man.in
+++ b/documentation/wine.conf.man.in
@@ -97,6 +97,12 @@
 .br
 Always try to avoid using FAT16. Use VFAT/FAT32 OS file system driver instead !
 .PP
+.I format: FailReadOnly=<boolean>
+.br
+Read-only files may not be opened in write mode (the default is to
+allow opening read-only files for writing, because most Windows
+programs always request read-write access, even on CD-ROM drives...).
+.PP
 .B [wine]
 .br
 .I format: windows = <directory>
diff --git a/documentation/wine.man.in b/documentation/wine.man.in
index 8481353..a7b2e56 100644
--- a/documentation/wine.man.in
+++ b/documentation/wine.man.in
@@ -215,11 +215,6 @@
 should imitate (e.g. 6.22) This option
 is only valid when used in conjunction with --winver win31.
 .TP
-.I --failreadonly
-Read only files may not be opened in write mode (the default is to
-allow opening read-only files for writing, because most Windows
-programs always request read-write access, even on CD-ROM drives...).
-.TP
 .I --language xx
 Set the language to
 .I xx
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 81025f1..0355f60 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -660,7 +660,7 @@
 		if (!strcmp(DOSFS_Devices[i].name,"NUL"))
                     return FILE_CreateFile( "/dev/null", access,
                                             FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
-                                            OPEN_EXISTING, 0, -1 );
+                                            OPEN_EXISTING, 0, -1, TRUE );
 		if (!strcmp(DOSFS_Devices[i].name,"CON")) {
 			HFILE to_dup;
 			HFILE handle;
@@ -697,7 +697,7 @@
                                      DOSFS_Devices[i].name,devname);
 			r =  FILE_CreateFile( devname, access,
 				FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
-				OPEN_EXISTING, 0, -1 );
+				OPEN_EXISTING, 0, -1, TRUE );
 			TRACE_(file)("Create_File return %08X\n",r);
 			return r;
 		    }
diff --git a/files/drive.c b/files/drive.c
index 14d12d0..eda5db4 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -60,7 +60,6 @@
     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 */
-    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 */
@@ -208,11 +207,13 @@
             if (buffer[0])
 	    {
                 drive->device = HEAP_strdupA( GetProcessHeap(), 0, buffer );
-		drive->read_volinfo =
-		(BOOL)PROFILE_GetWineIniInt( name, "ReadVolInfo", 1);
+		if (PROFILE_GetWineIniBool( name, "ReadVolInfo", 1))
+                    drive->flags |= DRIVE_READ_VOL_INFO;
 	    }
-	    else
-		drive->read_volinfo = FALSE;
+
+            /* Get the FailReadOnly flag */
+            if (PROFILE_GetWineIniBool( name, "FailReadOnly", 0 ))
+                drive->flags |= DRIVE_FAIL_READ_ONLY;
 
             /* Make the first hard disk the current drive */
             if ((DRIVE_CurDrive == -1) && (drive->type == TYPE_HD))
@@ -564,7 +565,7 @@
 	    CDROM_Close(&wcda);
 }
     }
-    if ((!read) && (DOSDrives[drive].read_volinfo))
+    if ((!read) && (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO))
     {
 	if (DRIVE_ReadSuperblock(drive,(char *) buff))
 	    ERR("Invalid or unreadable superblock on %s (%c:).\n",
@@ -599,7 +600,7 @@
 
     if (!DRIVE_IsValid( drive )) return 0;
     
-    if (DOSDrives[drive].read_volinfo)
+    if (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO)
     {
 	switch(DOSDrives[drive].type)
 	{
@@ -633,7 +634,7 @@
 
     if (!DRIVE_IsValid( drive )) return 0;
 
-    if (DOSDrives[drive].read_volinfo)
+    if (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO)
     {
         if ((DOSDrives[drive].type != TYPE_FLOPPY) &&
             (DOSDrives[drive].type != TYPE_HD)) return 0;
diff --git a/files/file.c b/files/file.c
index f10a9bd..206667f 100644
--- a/files/file.c
+++ b/files/file.c
@@ -42,7 +42,6 @@
 #include "global.h"
 #include "heap.h"
 #include "msdos.h"
-#include "options.h"
 #include "ldt.h"
 #include "process.h"
 #include "task.h"
@@ -322,11 +321,13 @@
  * Implementation of CreateFile. Takes a Unix path name.
  */
 HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
-                         LPSECURITY_ATTRIBUTES sa, DWORD creation,
-                         DWORD attributes, HANDLE template )
+                        LPSECURITY_ATTRIBUTES sa, DWORD creation,
+                        DWORD attributes, HANDLE template, BOOL fail_read_only )
 {
+    DWORD err;
     struct create_file_request *req = get_req_buffer();
 
+ restart:
     req->access  = access;
     req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
     req->sharing = sharing;
@@ -334,22 +335,19 @@
     req->attrs   = attributes;
     lstrcpynA( req->name, filename, server_remaining(req->name) );
     SetLastError(0);
-    server_call( REQ_CREATE_FILE );
+    err = server_call( REQ_CREATE_FILE );
 
     /* If write access failed, retry without GENERIC_WRITE */
 
-    if ((req->handle == -1) && !Options.failReadOnly &&
-        (access & GENERIC_WRITE)) 
+    if ((req->handle == -1) && !fail_read_only && (access & GENERIC_WRITE)) 
     {
-    	DWORD lasterror = GetLastError();
-
-	if ((lasterror == ERROR_ACCESS_DENIED) ||
-	    (lasterror == ERROR_WRITE_PROTECT)) {
+	if ((err == ERROR_ACCESS_DENIED) || (err == ERROR_WRITE_PROTECT))
+        {
 	    TRACE("Write access failed for file '%s', trying without "
 		  "write access", filename);
-            return FILE_CreateFile( filename, access & ~GENERIC_WRITE, sharing,
-                                    sa, creation, attributes, template );
-    }
+            access &= ~GENERIC_WRITE;
+            goto restart;
+        }
     }
 
     if (req->handle == -1)
@@ -491,7 +489,8 @@
     }
 
     return FILE_CreateFile( full_name.long_name, access, sharing,
-                            sa, creation, attributes, template );
+                            sa, creation, attributes, template,
+                            DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY );
 }
 
 
@@ -917,7 +916,8 @@
     }
 
     hFileRet = FILE_CreateFile( full_name.long_name, access, sharing,
-                                NULL, OPEN_EXISTING, 0, -1 );
+                                NULL, OPEN_EXISTING, 0, -1,
+                                DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY );
     if (hFileRet == HFILE_ERROR) goto not_found;
 
     GetFileTime( hFileRet, NULL, NULL, &filetime );
diff --git a/include/drive.h b/include/drive.h
index 9328af8..631fdd6 100644
--- a/include/drive.h
+++ b/include/drive.h
@@ -26,6 +26,8 @@
 #define DRIVE_SHORT_NAMES     0x0002  /* Drive fs has 8.3 file names */
 #define DRIVE_CASE_SENSITIVE  0x0004  /* Drive fs is case sensitive */
 #define DRIVE_CASE_PRESERVING 0x0008  /* Drive fs is case preserving */
+#define DRIVE_FAIL_READ_ONLY  0x0010  /* Fail opening read-only files for writing */
+#define DRIVE_READ_VOL_INFO   0x0020  /* Try to read volume info from the device? */
 
 extern int DRIVE_Init(void);
 extern int DRIVE_IsValid( int drive );
diff --git a/include/file.h b/include/file.h
index 6e9ebc3..4250243 100644
--- a/include/file.h
+++ b/include/file.h
@@ -36,8 +36,8 @@
 extern BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
 extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 );
 extern HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
-                                LPSECURITY_ATTRIBUTES sa, DWORD creation,
-                                DWORD attributes, HANDLE template );
+                               LPSECURITY_ATTRIBUTES sa, DWORD creation,
+                               DWORD attributes, HANDLE template, BOOL fail_read_only );
 extern HFILE FILE_CreateDevice( int client_id, DWORD access,
                                   LPSECURITY_ATTRIBUTES sa );
 extern LPVOID FILE_dommap( int unix_handle, LPVOID start,
diff --git a/include/options.h b/include/options.h
index 8bd15f8..d05fde3 100644
--- a/include/options.h
+++ b/include/options.h
@@ -62,8 +62,6 @@
     char  *dllFlags;        /* -dll flags (hack for Winelib support) */
     int    synchronous;     /* X synchronous mode */
     int    debug;
-    int    failReadOnly;    /* Opening a read only file will fail
-			       if write access is requested */
     WINE_LANGUAGE language; /* Current language */
     int    managed;	    /* Managed windows */
     char * configFileName;  /* Command line config file */
diff --git a/misc/main.c b/misc/main.c
index 69152a2..9214206 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -90,7 +90,6 @@
     NULL,           /* dllFlags */
     FALSE,          /* synchronous */
     FALSE,          /* debug */
-    FALSE,          /* failReadOnly */
     0,              /* language */
     FALSE,          /* Managed windows */
     NULL            /* Alternate config file name */
diff --git a/misc/options.c b/misc/options.c
index c86e7d4..b2c613d 100644
--- a/misc/options.c
+++ b/misc/options.c
@@ -49,8 +49,6 @@
       "--dll name       Enable or disable built-in DLLs" },
     { "dosver",       0, 1, VERSION_ParseDosVersion,
       "--dosver x.xx    DOS version to imitate (e.g. 6.22). Only valid with --winver win31" },
-    { "failreadonly", 0, 0, do_failreadonly,
-      "--failreadonly   Read only files may not be opened in write mode" },
     { "help",       'h', 0, do_help,
       "--help,-h        Show this help message" },
     { "language",     0, 1, MAIN_ParseLanguageOption,
@@ -89,11 +87,6 @@
     Options.debug = TRUE;
 }
 
-static void do_failreadonly( const char *arg )
-{
-    Options.failReadOnly = TRUE;
-}
-
 static void do_desktop( const char *arg )
 {
     Options.desktopGeometry = strdup( arg );
diff --git a/misc/registry.c b/misc/registry.c
index 76c71b9..66754d2 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -203,7 +203,7 @@
     {
         sprintf( p, "reg%04x.tmp", count++ );
         handle = FILE_CreateFile( name, GENERIC_WRITE, 0, NULL,
-                                  CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
+                                  CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1, TRUE );
         if (handle != INVALID_HANDLE_VALUE) break;
         if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) break;
     }
@@ -628,7 +628,7 @@
             {
                 HANDLE file;
                 if ((file = FILE_CreateFile( fn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
-                                             FILE_ATTRIBUTE_NORMAL, -1 )) != INVALID_HANDLE_VALUE)
+                                      FILE_ATTRIBUTE_NORMAL, -1, TRUE )) != INVALID_HANDLE_VALUE)
                 {
                     struct load_registry_request *req = get_req_buffer();
                     req->hkey    = hkey;