Moved creation of the CDROM registry keys into the registry loading
code.

diff --git a/dlls/ntdll/cdrom.c b/dlls/ntdll/cdrom.c
index 1d6ca23..59dcedf 100644
--- a/dlls/ntdll/cdrom.c
+++ b/dlls/ntdll/cdrom.c
@@ -377,8 +377,6 @@
  * number of the device on that interface for ide cdroms (*port == 0).
  * Determines the scsi information for scsi cdroms (*port >= 1).
  * Returns false if the info cannot not be obtained.
- *
- * NOTE: this function is used in CDROM_InitRegistry and CDROM_GetAddress
  */
 static int CDROM_GetInterfaceInfo(int fd, int* port, int* iface, int* device,int* lun)
 {
@@ -421,8 +419,7 @@
         else
 #endif
         {
-            FIXME("CD-ROM device (%d, %d) not supported\n",
-                  major(st.st_rdev), minor(st.st_rdev));
+            WARN("CD-ROM device (%d, %d) not supported\n", major(st.st_rdev), minor(st.st_rdev));
             return 0;
         }
     }
@@ -458,143 +455,6 @@
 
 
 /******************************************************************
- *		CDROM_InitRegistry
- *
- * Initializes registry to contain scsi info about the cdrom in NT.
- * All devices (even not real scsi ones) have this info in NT.
- * TODO: for now it only works for non scsi devices
- * NOTE: programs usually read these registry entries after sending the
- *       IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom
- */
-void CDROM_InitRegistry(int fd)
-{
-    int portnum, busid, targetid, lun;
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING nameW;
-    WCHAR dataW[50];
-    DWORD lenW;
-    char buffer[40];
-    DWORD value;
-    const char *data;
-    HKEY scsiKey;
-    HKEY portKey;
-    HKEY busKey;
-    HKEY targetKey;
-    DWORD disp;
-
-    attr.Length = sizeof(attr);
-    attr.RootDirectory = 0;
-    attr.ObjectName = &nameW;
-    attr.Attributes = 0;
-    attr.SecurityDescriptor = NULL;
-    attr.SecurityQualityOfService = NULL;
-
-    if (!CDROM_GetInterfaceInfo(fd, &portnum, &busid, &targetid, &lun))
-        return;
-
-    /* Ensure there is Scsi key */
-    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Machine\\HARDWARE\\DEVICEMAP\\Scsi" ) ||
-        NtCreateKey( &scsiKey, KEY_ALL_ACCESS, &attr, 0,
-                     NULL, REG_OPTION_VOLATILE, &disp ))
-    {
-        ERR("Cannot create DEVICEMAP\\Scsi registry key\n" );
-        return;
-    }
-    RtlFreeUnicodeString( &nameW );
-
-    snprintf(buffer,sizeof(buffer),"Scsi Port %d",portnum);
-    attr.RootDirectory = scsiKey;
-    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
-        NtCreateKey( &portKey, KEY_ALL_ACCESS, &attr, 0,
-                     NULL, REG_OPTION_VOLATILE, &disp ))
-    {
-        ERR("Cannot create DEVICEMAP\\Scsi Port registry key\n" );
-        return;
-    }
-    RtlFreeUnicodeString( &nameW );
-
-    RtlCreateUnicodeStringFromAsciiz( &nameW, "Driver" );
-    data = "atapi";
-    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
-    NtSetValueKey( portKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
-    RtlFreeUnicodeString( &nameW );
-    value = 10;
-    RtlCreateUnicodeStringFromAsciiz( &nameW, "FirstBusTimeScanInMs" );
-    NtSetValueKey( portKey,&nameW, 0, REG_DWORD, (BYTE *)&value, sizeof(DWORD));
-    RtlFreeUnicodeString( &nameW );
-    value = 0;
-#ifdef HDIO_GET_DMA
-    {
-        int dma;
-        if (ioctl(fd,HDIO_GET_DMA, &dma) != -1) {
-            value = dma;
-            TRACE("setting dma to %lx\n", value);
-        }
-    }
-#endif
-    RtlCreateUnicodeStringFromAsciiz( &nameW, "DMAEnabled" );
-    NtSetValueKey( portKey,&nameW, 0, REG_DWORD, (BYTE *)&value, sizeof(DWORD));
-    RtlFreeUnicodeString( &nameW );
-
-    snprintf(buffer,40,"Scsi Bus %d", busid);
-    attr.RootDirectory = portKey;
-    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
-        NtCreateKey( &busKey, KEY_ALL_ACCESS, &attr, 0,
-                     NULL, REG_OPTION_VOLATILE, &disp ))
-    {
-        ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus registry key\n" );
-        return;
-    }
-    RtlFreeUnicodeString( &nameW );
-
-    attr.RootDirectory = busKey;
-    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Initiator Id 255" ) ||
-        NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0,
-                     NULL, REG_OPTION_VOLATILE, &disp ))
-    {
-        ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus\\Initiator Id 255 registry key\n" );
-        return;
-    }
-    RtlFreeUnicodeString( &nameW );
-    NtClose( targetKey );
-
-    snprintf(buffer,40,"Target Id %d", targetid);
-    attr.RootDirectory = busKey;
-    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
-        NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0,
-                     NULL, REG_OPTION_VOLATILE, &disp ))
-    {
-        ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus 0\\Target Id registry key\n" );
-        return;
-    }
-    RtlFreeUnicodeString( &nameW );
-
-    RtlCreateUnicodeStringFromAsciiz( &nameW, "Type" );
-    data = "CdRomPeripheral";
-    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
-    NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
-    RtlFreeUnicodeString( &nameW );
-    /* FIXME - maybe read the real identifier?? */
-    RtlCreateUnicodeStringFromAsciiz( &nameW, "Identifier" );
-    data = "Wine CDROM";
-    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
-    NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
-    RtlFreeUnicodeString( &nameW );
-    /* FIXME - we always use Cdrom0 - do not know about the nt behaviour */
-    RtlCreateUnicodeStringFromAsciiz( &nameW, "DeviceName" );
-    data = "Cdrom0";
-    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
-    NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
-    RtlFreeUnicodeString( &nameW );
-
-    NtClose( targetKey );
-    NtClose( busKey );
-    NtClose( portKey );
-    NtClose( scsiKey );
-}
-
-
-/******************************************************************
  *		CDROM_Open
  *
  */
@@ -1721,7 +1581,7 @@
 
     piosb->Information = 0;
 
-    if ((status = wine_server_handle_to_fd( hDevice, GENERIC_READ, &fd, NULL, NULL ))) goto error;
+    if ((status = wine_server_handle_to_fd( hDevice, 0, &fd, NULL, NULL ))) goto error;
     if ((status = CDROM_Open(fd, &dev)))
     {
         wine_server_release_fd( hDevice, fd );
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 364c872..a1f72a7 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1129,7 +1129,6 @@
 ################################################################
 # Wine dll separation hacks, these will go away, don't use them
 #
-@ cdecl CDROM_InitRegistry(long)
 @ cdecl MODULE_DllThreadAttach(ptr)
 @ cdecl MODULE_GetLoadOrderW(ptr wstr wstr)
 @ cdecl VERSION_Init(wstr)
diff --git a/files/drive.c b/files/drive.c
index f532dd7..025f289 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -100,8 +100,6 @@
     return p;
 }
 
-extern void CDROM_InitRegistry(int dev);
-
 /***********************************************************************
  *           DRIVE_GetDriveType
  */
@@ -270,16 +268,6 @@
                 len = WideCharToMultiByte(CP_UNIXCP, 0, data, -1, NULL, 0, NULL, NULL);
                 drive->device = HeapAlloc(GetProcessHeap(), 0, len);
                 WideCharToMultiByte(CP_UNIXCP, 0, data, -1, drive->device, len, NULL, NULL);
-
-                if (drive->type == DRIVE_CDROM)
-                {
-                    int cd_fd;
-                    if ((cd_fd = open(drive->device, O_RDONLY|O_NONBLOCK)) != -1)
-                    {
-                        CDROM_InitRegistry(cd_fd);
-                        close(cd_fd);
-                    }
-                }
             }
 
             /* Make the first hard disk the current drive */
diff --git a/misc/registry.c b/misc/registry.c
index 18c6757..3835bf9 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -50,6 +50,12 @@
 #ifdef HAVE_SYS_MMAN_H
 # include <sys/mman.h>
 #endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LINUX_HDREG_H
+# include <linux/hdreg.h>
+#endif
 
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
@@ -57,6 +63,8 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
+#include "winioctl.h"
+#include "ntddscsi.h"
 
 #include "wine/winbase16.h"
 #include "wine/library.h"
@@ -1213,7 +1221,7 @@
 
     attr.Length = sizeof(attr);
     attr.RootDirectory = 0;
-    attr.Attributes = OBJ_CASE_INSENSITIVE;
+    attr.Attributes = 0;
     attr.ObjectName = &name;
     attr.SecurityDescriptor = NULL;
     attr.SecurityQualityOfService = NULL;
@@ -1666,6 +1674,165 @@
 }
 
 
+/******************************************************************
+ *		init_cdrom_registry
+ *
+ * Initializes registry to contain scsi info about the cdrom in NT.
+ * All devices (even not real scsi ones) have this info in NT.
+ * TODO: for now it only works for non scsi devices
+ * NOTE: programs usually read these registry entries after sending the
+ *       IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom
+ */
+static void init_cdrom_registry( HANDLE handle )
+{
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    WCHAR dataW[50];
+    DWORD lenW;
+    char buffer[40];
+    DWORD value;
+    const char *data;
+    HKEY scsiKey;
+    HKEY portKey;
+    HKEY busKey;
+    HKEY targetKey;
+    DWORD disp;
+    IO_STATUS_BLOCK io;
+    SCSI_ADDRESS scsi_addr;
+
+    if (NtDeviceIoControlFile( handle, 0, NULL, NULL, &io, IOCTL_SCSI_GET_ADDRESS,
+                               NULL, 0, &scsi_addr, sizeof(scsi_addr) ))
+        return;
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    /* Ensure there is Scsi key */
+    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Machine\\HARDWARE\\DEVICEMAP\\Scsi" ) ||
+        NtCreateKey( &scsiKey, KEY_ALL_ACCESS, &attr, 0,
+                     NULL, REG_OPTION_VOLATILE, &disp ))
+    {
+        ERR("Cannot create DEVICEMAP\\Scsi registry key\n" );
+        return;
+    }
+    RtlFreeUnicodeString( &nameW );
+
+    snprintf(buffer,sizeof(buffer),"Scsi Port %d",scsi_addr.PortNumber);
+    attr.RootDirectory = scsiKey;
+    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
+        NtCreateKey( &portKey, KEY_ALL_ACCESS, &attr, 0,
+                     NULL, REG_OPTION_VOLATILE, &disp ))
+    {
+        ERR("Cannot create DEVICEMAP\\Scsi Port registry key\n" );
+        return;
+    }
+    RtlFreeUnicodeString( &nameW );
+
+    RtlCreateUnicodeStringFromAsciiz( &nameW, "Driver" );
+    data = "atapi";
+    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
+    NtSetValueKey( portKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
+    RtlFreeUnicodeString( &nameW );
+    value = 10;
+    RtlCreateUnicodeStringFromAsciiz( &nameW, "FirstBusTimeScanInMs" );
+    NtSetValueKey( portKey,&nameW, 0, REG_DWORD, (BYTE *)&value, sizeof(DWORD));
+    RtlFreeUnicodeString( &nameW );
+    value = 0;
+#ifdef HDIO_GET_DMA
+    {
+        int fd, dma;
+        if (!wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL ))
+        {
+            if (ioctl(fd,HDIO_GET_DMA, &dma) != -1) value = dma;
+            wine_server_release_fd( handle, fd );
+        }
+    }
+#endif
+    RtlCreateUnicodeStringFromAsciiz( &nameW, "DMAEnabled" );
+    NtSetValueKey( portKey,&nameW, 0, REG_DWORD, (BYTE *)&value, sizeof(DWORD));
+    RtlFreeUnicodeString( &nameW );
+
+    snprintf(buffer,40,"Scsi Bus %d", scsi_addr.PathId);
+    attr.RootDirectory = portKey;
+    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
+        NtCreateKey( &busKey, KEY_ALL_ACCESS, &attr, 0,
+                     NULL, REG_OPTION_VOLATILE, &disp ))
+    {
+        ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus registry key\n" );
+        return;
+    }
+    RtlFreeUnicodeString( &nameW );
+
+    attr.RootDirectory = busKey;
+    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Initiator Id 255" ) ||
+        NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0,
+                     NULL, REG_OPTION_VOLATILE, &disp ))
+    {
+        ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus\\Initiator Id 255 registry key\n" );
+        return;
+    }
+    RtlFreeUnicodeString( &nameW );
+    NtClose( targetKey );
+
+    snprintf(buffer,40,"Target Id %d", scsi_addr.TargetId);
+    attr.RootDirectory = busKey;
+    if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
+        NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0,
+                     NULL, REG_OPTION_VOLATILE, &disp ))
+    {
+        ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus 0\\Target Id registry key\n" );
+        return;
+    }
+    RtlFreeUnicodeString( &nameW );
+
+    RtlCreateUnicodeStringFromAsciiz( &nameW, "Type" );
+    data = "CdRomPeripheral";
+    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
+    NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
+    RtlFreeUnicodeString( &nameW );
+    /* FIXME - maybe read the real identifier?? */
+    RtlCreateUnicodeStringFromAsciiz( &nameW, "Identifier" );
+    data = "Wine CDROM";
+    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
+    NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
+    RtlFreeUnicodeString( &nameW );
+    /* FIXME - we always use Cdrom0 - do not know about the nt behaviour */
+    RtlCreateUnicodeStringFromAsciiz( &nameW, "DeviceName" );
+    data = "Cdrom0";
+    RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
+    NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
+    RtlFreeUnicodeString( &nameW );
+
+    NtClose( targetKey );
+    NtClose( busKey );
+    NtClose( portKey );
+    NtClose( scsiKey );
+}
+
+
+/* create the hardware registry branch */
+static void create_hardware_branch(void)
+{
+    int i;
+    HANDLE handle;
+    char drive[] = "\\\\.\\A:";
+
+    /* create entries for cdroms */
+    for (i = 0; i < 26; i++)
+    {
+        drive[4] = 'A' + i;
+        handle = CreateFileA( drive, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
+        if (handle == INVALID_HANDLE_VALUE) continue;
+        init_cdrom_registry( handle );
+        CloseHandle( handle );
+    }
+}
+
+
 /* load all registry (native and global and home) */
 void SHELL_LoadRegistry( void )
 {
@@ -1794,6 +1961,10 @@
     }
     if (res) _load_home_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
 
+    /* create hardware registry branch */
+
+    create_hardware_branch();
+
     /* setup registry saving */
 
     all = FALSE;