winecfg final patch (again)

Mike Hearn mike at navi.cx
Fri Nov 19 12:20:47 CST 2004


Hopefully builds this time (does for me :)

- More Heapification
- Split drive code into core, UI and autodetect
- Implement drive autodetection
- Slight redesign of drive tab
- Code cleanup
- More stuff


-------------- next part --------------
? programs/winecfg/drivedetect.c
? programs/winecfg/driveui.c
Index: programs/winecfg/Makefile.in
===================================================================
RCS file: /home/wine/wine/programs/winecfg/Makefile.in,v
retrieving revision 1.11
diff -u -p -r1.11 Makefile.in
--- programs/winecfg/Makefile.in	4 May 2004 02:56:46 -0000	1.11
+++ programs/winecfg/Makefile.in	19 Nov 2004 18:04:57 -0000
@@ -10,6 +10,8 @@ C_SRCS = \
 	appdefaults.c \
 	audio.c \
 	drive.c \
+	driveui.c \
+	drivedetect.c \
 	libraries.c \
 	main.c \
 	properties.c \
@@ -23,3 +25,4 @@ RC_BINARIES = idb_wine.bmp 
 @MAKE_PROG_RULES@
 
 ### Dependencies:
+winecfg.res: En.rc Es.rc It.rc Nl.rc Pt.rc Ru.rc Si.rc
Index: programs/winecfg/appdefaults.c
===================================================================
RCS file: /home/wine/wine/programs/winecfg/appdefaults.c,v
retrieving revision 1.6
diff -u -p -r1.6 appdefaults.c
--- programs/winecfg/appdefaults.c	28 Sep 2004 03:55:16 -0000	1.6
+++ programs/winecfg/appdefaults.c	19 Nov 2004 18:04:58 -0000
@@ -2,8 +2,8 @@
  * WineCfg app settings tabsheet
  *
  * Copyright 2004 Robert van Herk
- * Copyright 2004 Chris Morgan
- * Copyright 2004 Mike Hearn
+ *                Chris Morgan
+ *                Mike Hearn
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -105,7 +105,7 @@ init_comboboxes (HWND dialog)
   SendDlgItemMessage(dialog, IDC_DOSVER, CB_RESETCONTENT, 0, 0);  
   
   /* add the default entries (automatic) which correspond to no setting  */
-  if (currentApp)
+  if (current_app)
   {
       SendDlgItemMessage(dialog, IDC_WINVER, CB_ADDSTRING, 0, (LPARAM) "Use global settings");
       SendDlgItemMessage(dialog, IDC_DOSVER, CB_ADDSTRING, 0, (LPARAM) "Use global settings");      
@@ -173,7 +173,7 @@ static void init_appsheet(HWND dialog)
       size = sizeof(appname);
       while (RegEnumKeyEx(key, i, appname, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
       {
-          add_listview_item(listview, appname, strdup(appname));
+          add_listview_item(listview, appname, strdupA(appname));
 
           i++;
           size = sizeof(appname);
@@ -219,7 +219,7 @@ static int get_listview_selection(HWND l
 static void on_selection_change(HWND dialog, HWND listview)
 {
   LVITEM item;
-  char *oldapp = currentApp;
+  char *oldapp = current_app;
     
   WINE_TRACE("()\n");
   
@@ -230,23 +230,23 @@ static void on_selection_change(HWND dia
   
   ListView_GetItem(listview, &item);
 
-  currentApp = (char *) item.lParam;
+  current_app = (char *) item.lParam;
 
-  if (currentApp)
+  if (current_app)
   {
-      WINE_TRACE("currentApp is now %s\n", currentApp);
+      WINE_TRACE("current_app is now %s\n", current_app);
       enable(IDC_APP_REMOVEAPP);
   }
   else
   {
-      WINE_TRACE("currentApp=NULL, editing global settings\n");
+      WINE_TRACE("current_app=NULL, editing global settings\n");
       /* focus will never be on the button in this callback so it's safe  */
       disable(IDC_APP_REMOVEAPP);
   }
 
   /* reset the combo boxes if we changed from/to global/app-specific  */
 
-  if ((oldapp && !currentApp) || (!oldapp && currentApp))
+  if ((oldapp && !current_app) || (!oldapp && current_app))
       init_comboboxes(dialog);
   
   update_comboboxes(dialog);
@@ -276,12 +276,12 @@ static void on_add_app_click(HWND dialog
       HWND listview = GetDlgItem(dialog, IDC_APP_LISTVIEW);
       int count = ListView_GetItemCount(listview);
       
-      if (currentApp) free(currentApp);
-      currentApp = strdup(filetitle);
+      if (current_app) HeapFree(GetProcessHeap(), 0, current_app);
+      current_app = strdupA(filetitle);
 
-      WINE_TRACE("adding %s\n", currentApp);
+      WINE_TRACE("adding %s\n", current_app);
       
-      add_listview_item(listview, currentApp, currentApp);
+      add_listview_item(listview, current_app, current_app);
 
       ListView_SetItemState(listview, count, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
 
@@ -375,9 +375,11 @@ AppDlgProc (HWND hDlg, UINT uMsg, WPARAM
       break;
     
     case WM_COMMAND:
-      switch(HIWORD(wParam)) {
+      switch(HIWORD(wParam))
+      {
         case CBN_SELCHANGE:
-          switch(LOWORD(wParam)) {
+          switch(LOWORD(wParam))
+          {
             case IDC_WINVER:
               on_winver_change(hDlg);
               break;
@@ -386,7 +388,8 @@ AppDlgProc (HWND hDlg, UINT uMsg, WPARAM
               break;
           }
         case BN_CLICKED:
-          switch(LOWORD(wParam)) {
+          switch(LOWORD(wParam))
+          {
             case IDC_APP_ADDAPP:
               on_add_app_click(hDlg);
               break;
Index: programs/winecfg/drive.c
===================================================================
RCS file: /home/wine/wine/programs/winecfg/drive.c,v
retrieving revision 1.18
diff -u -p -r1.18 drive.c
--- programs/winecfg/drive.c	28 Sep 2004 04:05:55 -0000	1.18
+++ programs/winecfg/drive.c	19 Nov 2004 18:04:58 -0000
@@ -1,8 +1,8 @@
 /*
- * Drive management UI code
+ * Drive management code
  *
  * Copyright 2003 Mark Westcott
- * Copyright 2003 Mike Hearn
+ * Copyright 2003-2004 Mike Hearn
  * Copyright 2004 Chris Morgan
  *
  * This library is free software; you can redistribute it and/or
@@ -21,10 +21,6 @@
  *
  */
 
-/* TODO: */
-/* - Support for devices(not sure what this means) */
-/* - Various autodetections */
-
 #include <assert.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -47,30 +43,50 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
 
-typedef struct drive_entry_s
-{
-    char letter;
-    char *unixpath;
-    char *label;
-    char *serial;
-    uint type;
-
-    BOOL in_use;
-} drive_entry_t;
-
-static BOOL updatingUI = FALSE;
-static drive_entry_t* editDriveEntry;
-static int lastSel = 0; /* the last drive selected in the property sheet */
-drive_entry_t drives[26]; /* one for each drive letter */
+struct drive drives[26]; /* one for each drive letter */
 
-int getDrive(char letter)
+static inline int letter_to_index(char letter)
 {
     return (toupper(letter) - 'A');
 }
 
-BOOL addDrive(char letter, char *targetpath, char *label, char *serial, uint type)
+/* This function produces a mask for each drive letter that isn't
+ * currently used. Each bit of the long result represents a letter,
+ * with A being the least significant bit, and Z being the most
+ * significant.
+ *
+ * To calculate this, we loop over each letter, and see if we can get
+ * a drive entry for it. If so, we set the appropriate bit. At the
+ * end, we flip each bit, to give the desired result.
+ *
+ * The letter parameter is always marked as being available. This is
+ * so the edit dialog can display the currently used drive letter
+ * alongside the available ones.
+ */
+long drive_available_mask(char letter)
+{
+  long result = 0;
+  int i;
+
+  WINE_TRACE("\n");
+
+
+  for(i = 0; i < 26; i++)
+  {
+      if (!drives[i].in_use) continue;
+      result |= (1 << (toupper(drives[i].letter) - 'A'));
+  }
+
+  result = ~result;
+  if (letter) result |= DRIVE_MASK_BIT(letter);
+
+  WINE_TRACE("finished drive letter loop with %lx\n", result);
+  return result;
+}
+
+BOOL add_drive(char letter, char *targetpath, char *label, char *serial, uint type)
 {
-    int driveIndex = getDrive(letter);
+    int driveIndex = letter_to_index(letter);
 
     if(drives[driveIndex].in_use)
         return FALSE;
@@ -79,48 +95,32 @@ BOOL addDrive(char letter, char *targetp
                letter, targetpath, label, serial, type);
 
     drives[driveIndex].letter   = toupper(letter);
-    drives[driveIndex].unixpath = strdup(targetpath);
-    drives[driveIndex].label    = strdup(label);
-    drives[driveIndex].serial   = strdup(serial);
+    drives[driveIndex].unixpath = strdupA(targetpath);
+    drives[driveIndex].label    = strdupA(label);
+    drives[driveIndex].serial   = strdupA(serial);
     drives[driveIndex].type     = type;
     drives[driveIndex].in_use   = TRUE;
 
     return TRUE;
 }
 
-/* frees up the memory associated with a drive and returns the */
-/* pNext of the given drive entry */
-void freeDrive(drive_entry_t *pDrive)
+/* deallocates the contents of the drive. does not free the drive itself  */
+void delete_drive(struct drive *d)
 {
-    free(pDrive->unixpath);
-    free(pDrive->label);
-    free(pDrive->serial);
-
-    pDrive->in_use = FALSE;
-}
+    HeapFree(GetProcessHeap(), 0, d->unixpath);
+    HeapFree(GetProcessHeap(), 0, d->label);
+    HeapFree(GetProcessHeap(), 0, d->serial);
 
-void setDriveLabel(drive_entry_t *pDrive, char *label)
-{
-    WINE_TRACE("pDrive->letter '%c', label = '%s'\n", pDrive->letter, label);
-    free(pDrive->label);
-    pDrive->label = strdup(label);
+    d->in_use = FALSE;
 }
 
-void setDriveSerial(drive_entry_t *pDrive, char *serial)
-{
-    WINE_TRACE("pDrive->letter '%c', serial = '%s'\n", pDrive->letter, serial);
-    free(pDrive->serial);
-    pDrive->serial = strdup(serial);
-}
+#if 0
 
-void setDrivePath(drive_entry_t *pDrive, char *path)
-{
-    WINE_TRACE("pDrive->letter '%c', path = '%s'\n", pDrive->letter, path);
-    free(pDrive->unixpath);
-    pDrive->unixpath = strdup(path);
-}
+/* currently unused, but if users have this burning desire to be able to rename drives,
+   we can put it back in.
+ */
 
-BOOL copyDrive(drive_entry_t *pSrc, drive_entry_t *pDst)
+BOOL copyDrive(struct drive *pSrc, struct drive *pDst)
 {
     if(pDst->in_use)
     {
@@ -132,16 +132,16 @@ BOOL copyDrive(drive_entry_t *pSrc, driv
     if(!pSrc->label) WINE_TRACE("!pSrc->label\n");
     if(!pSrc->serial) WINE_TRACE("!pSrc->serial\n");
 
-    pDst->unixpath = strdup(pSrc->unixpath);
-    pDst->label = strdup(pSrc->label);
-    pDst->serial = strdup(pSrc->serial);
+    pDst->unixpath = strdupA(pSrc->unixpath);
+    pDst->label = strdupA(pSrc->label);
+    pDst->serial = strdupA(pSrc->serial);
     pDst->type = pSrc->type;
     pDst->in_use = TRUE;
 
     return TRUE;
 }
 
-BOOL moveDrive(drive_entry_t *pSrc, drive_entry_t *pDst)
+BOOL moveDrive(struct drive *pSrc, struct drive *pDst)
 {
     WINE_TRACE("pSrc->letter == %c, pDst->letter == %c\n", pSrc->letter, pDst->letter);
 
@@ -151,650 +151,116 @@ BOOL moveDrive(drive_entry_t *pSrc, driv
         return FALSE;
     }
 
-    freeDrive(pSrc);
+    delete_drive(pSrc);
     return TRUE;
 }
 
-int refreshDriveDlg (HWND dialog)
-{
-  int driveCount = 0;
-  int doesDriveCExist = FALSE;
-  int i;
-
-  WINE_TRACE("\n");
-
-  updatingUI = TRUE;
-
-  /* Clear the listbox */
-  SendMessageA(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_RESETCONTENT, 0, 0);
-
-  for(i = 0; i < 26; i++)
-  {
-      char *title = 0;
-      int titleLen;
-      int itemIndex;
-
-      /* skip over any unused drives */
-      if(!drives[i].in_use)
-          continue;
-
-      if(drives[i].letter == 'C')
-          doesDriveCExist = TRUE;
-
-      titleLen = snprintf(title, 0, "Drive %c:\\ %s", 'A' + i,
-                          drives[i].unixpath);
-      titleLen++; /* add a byte for the trailing null */
-
-      title = malloc(titleLen);
-
-      /* the %s in the item label will be replaced by the drive letter, so -1, then
-         -2 for the second %s which will be expanded to the label, finally + 1 for terminating #0 */
-      snprintf(title, titleLen, "Drive %c:\\ %s", 'A' + i,
-               drives[i].unixpath);
-
-      WINE_TRACE("title is '%s'\n", title);
-
-      /* the first SendMessage call adds the string and returns the index, the second associates that index with it */
-      itemIndex = SendMessageA(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_ADDSTRING ,(WPARAM) -1, (LPARAM) title);
-      SendMessageA(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_SETITEMDATA, itemIndex, (LPARAM) &drives[i]);
-
-      free(title);
-      driveCount++;
-  }
-
-  WINE_TRACE("loaded %d drives\n", driveCount);
-  SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_SETSEL, TRUE, lastSel);
-
-  /* show the warning if there is no Drive C */
-  if (!doesDriveCExist)
-    ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_NORMAL);
-  else
-    ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_HIDE);
-  
-  /* disable or enable controls depending on whether we are editing global vs app specific config */
-  if (currentApp) {
-    WINE_TRACE("enabling controls\n");
-    enable(IDC_LIST_DRIVES);
-    enable(IDC_BUTTON_ADD);
-    enable(IDC_BUTTON_REMOVE);
-    enable(IDC_BUTTON_EDIT);
-    enable(IDC_BUTTON_AUTODETECT);
-  } else {
-    WINE_TRACE("disabling controls\n");
-    disable(IDC_LIST_DRIVES);
-    disable(IDC_BUTTON_ADD);
-    disable(IDC_BUTTON_REMOVE);
-    disable(IDC_BUTTON_EDIT);
-    disable(IDC_BUTTON_AUTODETECT);    
-  }
-
-  
-  updatingUI = FALSE;
-  return driveCount;
-}
-
-/******************************************************************************/
-/*  The Drive Editing Dialog                                                  */
-/******************************************************************************/
-#define DRIVE_MASK_BIT(B) 1<<(toupper(B)-'A')
-
-typedef struct {
-  const uint sCode;
-  const char *sDesc;
-} code_desc_pair;
-
-static code_desc_pair type_pairs[] = {
-  {DRIVE_FIXED,      "Local hard disk"},
-  {DRIVE_REMOTE,     "Network share" },
-  {DRIVE_REMOVABLE,  "Floppy disk"},
-  {DRIVE_CDROM,      "CD-ROM"}
-};
-#define DRIVE_TYPE_DEFAULT 1
-
-
-void fill_drive_droplist(long mask, char currentLetter, HWND hDlg)
-{
-  int i;
-  int selection;
-  int count;
-  int next_letter;
-  char sName[4] = "A:";
-
-  for( i=0, count=0, selection=-1, next_letter=-1; i <= 'Z'-'A'; ++i ) {
-    if( mask & DRIVE_MASK_BIT('A'+i) ) {
-      int index;
-      
-      sName[0] = 'A' + i;
-      index = SendDlgItemMessage( hDlg, IDC_COMBO_LETTER, CB_ADDSTRING, 0, (LPARAM) sName );
-			  
-      if( toupper(currentLetter) == 'A' + i ) {
-          selection = count;
-      }
-      
-      if( i >= 2 && next_letter == -1){ /*default drive is first one of C-Z */
-          next_letter = count;
-      }
-      
-      count++;
-    }
-  }
-  
-  if( selection == -1 ) {
-    selection = next_letter;
-  }
-  
-  SendDlgItemMessage( hDlg, IDC_COMBO_LETTER, CB_SETCURSEL, selection, 0 );
-}
-
-#define BOX_MODE_CD_ASSIGN 1
-#define BOX_MODE_CD_AUTODETECT 2
-#define BOX_MODE_NONE 3
-#define BOX_MODE_NORMAL 4
-void enable_labelserial_box(HWND dialog, int mode)
-{
-  WINE_TRACE("mode=%d\n", mode);
-  switch (mode) {
-      case BOX_MODE_CD_ASSIGN:
-/*	enable(IDC_RADIO_AUTODETECT); */
-	enable(IDC_RADIO_ASSIGN);
-	disable(IDC_EDIT_DEVICE);
-	disable(IDC_BUTTON_BROWSE_DEVICE);
-	enable(IDC_EDIT_SERIAL);
-	enable(IDC_EDIT_LABEL);
-	enable(IDC_STATIC_SERIAL);
-	enable(IDC_STATIC_LABEL);
-	break;
-	
-      case BOX_MODE_CD_AUTODETECT:
-/*	enable(IDC_RADIO_AUTODETECT); */
-	enable(IDC_RADIO_ASSIGN);
-	enable(IDC_EDIT_DEVICE);
-	enable(IDC_BUTTON_BROWSE_DEVICE);
-	disable(IDC_EDIT_SERIAL);
-	disable(IDC_EDIT_LABEL);
-	disable(IDC_STATIC_SERIAL);
-	disable(IDC_STATIC_LABEL);
-	break;
-
-      case BOX_MODE_NONE:
-	disable(IDC_RADIO_AUTODETECT);
-	disable(IDC_RADIO_ASSIGN);
-	disable(IDC_EDIT_DEVICE);
-	disable(IDC_BUTTON_BROWSE_DEVICE);
-	disable(IDC_EDIT_SERIAL);
-	disable(IDC_EDIT_LABEL);
-	disable(IDC_STATIC_SERIAL);
-	disable(IDC_STATIC_LABEL);
-	break;
-
-      case BOX_MODE_NORMAL:
-	disable(IDC_RADIO_AUTODETECT);
-	enable(IDC_RADIO_ASSIGN);
-	disable(IDC_EDIT_DEVICE);
-	disable(IDC_BUTTON_BROWSE_DEVICE);
-	enable(IDC_EDIT_SERIAL);
-	enable(IDC_EDIT_LABEL);
-	enable(IDC_STATIC_SERIAL);
-	enable(IDC_STATIC_LABEL);
-	break;	
-  }
-}
-
-/* This function produces a mask for each drive letter that isn't currently used. Each bit of the long result
- * represents a letter, with A being the least significant bit, and Z being the most significant.
- *
- * To calculate this, we loop over each letter, and see if we can get a drive entry for it. If so, we
- * set the appropriate bit. At the end, we flip each bit, to give the desired result.
- *
- * The letter parameter is always marked as being available. This is so the edit dialog can display the
- * currently used drive letter alongside the available ones.
- */
-long drive_available_mask(char letter)
-{
-  long result = 0;
-  int i;
-
-  WINE_TRACE("\n");
-
-  
-  for(i = 0; i < 26; i++)
-  {
-      if(!drives[i].in_use) continue;
-      result |= (1 << (toupper(drives[i].letter) - 'A'));
-  }
-
-  result = ~result;
-  if (letter) result |= DRIVE_MASK_BIT(letter);
-  
-  WINE_TRACE( "finished drive letter loop with %lx\n", result );
-  return result;
-}
+#endif
 
-void advancedDriveEditDialog(HWND hDlg, BOOL showAdvanced)
+/* Load currently defined drives into the drives array  */
+void load_drives()
 {
-#define ADVANCED_DELTA      120
-
-    static RECT okpos;
-    static BOOL got_initial_ok_position = FALSE;
+    char *devices, *dev;
+    int len;
+    int drivecount = 0, i;
+    int retval;
+    static const int arraysize = 512;
 
-    static RECT windowpos; /* we only use the height of this rectangle */
-    static BOOL got_initial_window_position = FALSE;
+    WINE_TRACE("\n");
 
-    static RECT current_window;
+    /* FIXME: broken symlinks in $WINEPREFIX/dosdevices will not be
+       returned by this API, so we need to handle that  */
 
-    INT state;
-    INT offset;
-    char *text;
+    /* setup the drives array */
+    dev = devices = HeapAlloc(GetProcessHeap(), 0, arraysize);
+    len = GetLogicalDriveStrings(arraysize, devices);
 
-    if(!got_initial_ok_position)
+    /* make all devices unused */
+    for (i = 0; i < 26; i++)
     {
-        POINT pt;
-        GetWindowRect(GetDlgItem(hDlg, ID_BUTTON_OK), &okpos);
-        pt.x = okpos.left;
-        pt.y = okpos.top;
-        ScreenToClient(hDlg, &pt);
-        okpos.right+= (pt.x - okpos.left);
-        okpos.bottom+= (pt.y - okpos.top);
-        okpos.left = pt.x;
-        okpos.top = pt.y;
-        got_initial_ok_position = TRUE;
+        drives[i].letter = 'A' + i;
+        drives[i].in_use = FALSE;
     }
 
-    if(!got_initial_window_position)
-    {
-        GetWindowRect(hDlg, &windowpos);
-        got_initial_window_position = TRUE;
-    }
-          
-    if(showAdvanced)
-    {
-        state = SW_NORMAL;
-        offset = 0;
-        text = "Hide Advanced";
-    } else
+    /* work backwards through the result of GetLogicalDriveStrings  */
+    while (len)
     {
-        state = SW_HIDE;
-        offset = ADVANCED_DELTA;
-        text = "Show Advanced";
-    }
-
-    ShowWindow(GetDlgItem(hDlg, IDC_STATIC_TYPE), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_COMBO_TYPE), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_BOX_LABELSERIAL), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_RADIO_AUTODETECT), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_RADIO_ASSIGN), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_EDIT_LABEL), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DEVICE), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_STATIC_LABEL), state);
-    ShowWindow(GetDlgItem(hDlg, IDC_BUTTON_BROWSE_DEVICE), state);
-    SetWindowPos(GetDlgItem(hDlg, ID_BUTTON_OK),
-                 HWND_TOP,
-                 okpos.left, okpos.top - offset, okpos.right - okpos.left,
-                 okpos.bottom - okpos.top,
-                 0);
-
-    /* resize the parent window */
-    GetWindowRect(hDlg, &current_window);
-    SetWindowPos(hDlg, 
-                 HWND_TOP,
-                 current_window.left,
-                 current_window.top,
-                 windowpos.right - windowpos.left,
-                 windowpos.bottom - windowpos.top - offset,
-                 0);
-
-    /* update the button text based on the state */
-    SetWindowText(GetDlgItem(hDlg, IDC_BUTTON_SHOW_HIDE_ADVANCED),
-                  text);
-}
-
-
-void refreshDriveEditDialog(HWND dialog) {
-  char *path;
-  uint type;
-  char *label;
-  char *serial;
-  char *device;
-  unsigned int i;
-  int selection = -1;
-
-  updatingUI = TRUE;
-
-  WINE_TRACE("\n");
-  
-  /* Drive letters */
-  fill_drive_droplist( drive_available_mask( editDriveEntry->letter ), editDriveEntry->letter, dialog );
-
-  /* path */
-  path = editDriveEntry->unixpath;
-  if (path) {
-    WINE_TRACE("set path control text to '%s'\n", path);
-    SetWindowText(GetDlgItem(dialog, IDC_EDIT_PATH), path);
-  } else WINE_WARN("no Path field?\n");
-  
-  /* drive type */
-  type = editDriveEntry->type;
-  if (type) {
-    for(i = 0; i < sizeof(type_pairs)/sizeof(code_desc_pair); i++) {
-      SendDlgItemMessage(dialog, IDC_COMBO_TYPE, CB_ADDSTRING, 0,
-			 (LPARAM) type_pairs[i].sDesc);
-      if(type_pairs[i].sCode ==  type){
-          selection = i;
-      }
-    }
-  
-    if( selection == -1 ) selection = DRIVE_TYPE_DEFAULT;
-    SendDlgItemMessage(dialog, IDC_COMBO_TYPE, CB_SETCURSEL, selection, 0);
-  } else WINE_WARN("no Type field?\n");
-
-  
-  /* removeable media properties */
-  label = editDriveEntry->label;
-  if (label) {
-    SendDlgItemMessage(dialog, IDC_EDIT_LABEL, WM_SETTEXT, 0,(LPARAM)label);
-  } else WINE_WARN("no Label field?\n");
-
-  /* set serial edit text */
-  serial = editDriveEntry->serial;
-  if (serial) {
-    SendDlgItemMessage(dialog, IDC_EDIT_SERIAL, WM_SETTEXT, 0,(LPARAM)serial);
-  } else WINE_WARN("no Serial field?\n");
-
-  /* TODO: get the device here to put into the edit box */
-  device = "Not implemented yet";
-  if (device) {
-    SendDlgItemMessage(dialog, IDC_EDIT_DEVICE, WM_SETTEXT, 0,(LPARAM)device);
-  } else WINE_WARN("no Device field?\n");
-
-  selection = IDC_RADIO_ASSIGN;
-  if ((type == DRIVE_CDROM) || (type == DRIVE_REMOVABLE)) {
-#if 0
-    if (device) {
-      selection = IDC_RADIO_AUTODETECT;
-      enable_labelserial_box(dialog, BOX_MODE_CD_AUTODETECT);
-    } else {
-#endif
-      selection = IDC_RADIO_ASSIGN;
-      enable_labelserial_box(dialog, BOX_MODE_CD_ASSIGN);
-#if 0
-    }
-#endif
-  } else {
-    enable_labelserial_box(dialog, BOX_MODE_NORMAL);
-    selection = IDC_RADIO_ASSIGN;
-  }
-
-  CheckRadioButton( dialog, IDC_RADIO_AUTODETECT, IDC_RADIO_ASSIGN, selection );
-  
-  updatingUI = FALSE;
-  
-  return;
-}
-
-/* storing the drive propsheet HWND here is a bit ugly, but the simplest solution for now */
-static HWND driveDlgHandle;
-
-void onEditChanged(HWND hDlg, WORD controlID) {
-  WINE_TRACE("controlID=%d\n", controlID);
-  switch (controlID) {
-      case IDC_EDIT_LABEL: {
-        char *label = get_control_text(hDlg, controlID);
-        if(!label) label = strdup("");
-        setDriveLabel(editDriveEntry, label);
-        refreshDriveDlg(driveDlgHandle);
-        if (label) HeapFree(GetProcessHeap(), 0, label);
-        break;
-      }
-      case IDC_EDIT_PATH: {
-          char *path = get_control_text(hDlg, controlID);
-          if (!path) path = strdup("fake_windows"); /* default to assuming fake_windows in the .wine directory */
-          WINE_TRACE("got path from control of '%s'\n", path);
-          setDrivePath(editDriveEntry, path);
-          if (path) HeapFree(GetProcessHeap(), 0, path);
-          break;
-      }
-      case IDC_EDIT_SERIAL: {
-          char *serial = get_control_text(hDlg, controlID);
-          if(!serial) serial = strdup("");
-          setDriveSerial(editDriveEntry, serial);
-          if (serial) HeapFree(GetProcessHeap(), 0, serial);
-          break;
-      }
-      case IDC_EDIT_DEVICE: {
-          char *device = get_control_text(hDlg,controlID);
-          /* TODO: handle device if/when it makes sense to do so.... */
-          if (device) HeapFree(GetProcessHeap(), 0, device);
-          refreshDriveDlg(driveDlgHandle);
-          break;
-      }
-  }
-}
-
-/* edit a drive entry */
-INT_PTR CALLBACK DriveEditDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-  int selection;
-  static BOOL advanced = FALSE;
-
-  switch (uMsg)  {
-      case WM_CLOSE:
-	    EndDialog(hDlg, wParam);
-	    return TRUE;
-
-      case WM_INITDIALOG: {
-          enable_labelserial_box(hDlg, BOX_MODE_NORMAL);
-          advancedDriveEditDialog(hDlg, advanced);
-          editDriveEntry = (drive_entry_t*)lParam;
-          refreshDriveEditDialog(hDlg);
-      }
-
-    case WM_COMMAND:
-      switch (LOWORD(wParam)) {
-	  case IDC_COMBO_TYPE:
-	    if (HIWORD(wParam) != CBN_SELCHANGE) break;
-	    selection = SendDlgItemMessage( hDlg, IDC_COMBO_TYPE, CB_GETCURSEL, 0, 0);
-	    if( selection == 2 || selection == 3 ) { /* cdrom or floppy */
-	      if (IsDlgButtonChecked(hDlg, IDC_RADIO_AUTODETECT))
-              enable_labelserial_box(hDlg, BOX_MODE_CD_AUTODETECT);
-	      else
-              enable_labelserial_box(hDlg, BOX_MODE_CD_ASSIGN);
-	    }
-	    else {
-	      enable_labelserial_box( hDlg, BOX_MODE_NORMAL );
-	    }
-        editDriveEntry->type = type_pairs[selection].sCode;
-	    break;
-
-	  case IDC_COMBO_LETTER: {
-	    int item = SendDlgItemMessage(hDlg, IDC_COMBO_LETTER, CB_GETCURSEL, 0, 0);
-	    char newLetter[4];
-	    SendDlgItemMessage(hDlg, IDC_COMBO_LETTER, CB_GETLBTEXT, item, (LPARAM) newLetter);
-
-	    if (HIWORD(wParam) != CBN_SELCHANGE) break;
-	    if (newLetter[0] == editDriveEntry->letter) break;
-
-	    WINE_TRACE("changing drive letter to %c\n", newLetter[0]);
-            moveDrive(editDriveEntry, &drives[getDrive(newLetter[0])]);
-            editDriveEntry = &drives[getDrive(newLetter[0])];
-	    refreshDriveDlg(driveDlgHandle);
-	    break;
-	  }
-
-	  case IDC_BUTTON_BROWSE_PATH:
-	    WRITEME(hDlg);
-	    break;
-
-	  case IDC_RADIO_AUTODETECT: {
-        /* TODO: */
-        WINE_FIXME("Implement autodetection\n");
-	    enable_labelserial_box(hDlg, BOX_MODE_CD_AUTODETECT);
-        refreshDriveDlg(driveDlgHandle);
-	    break;
-	  }
-	    
-	  case IDC_RADIO_ASSIGN:
-      {
-        char *edit, *serial;
-        edit = get_control_text(hDlg, IDC_EDIT_LABEL);
-        if(!edit) edit = strdup("");
-        setDriveLabel(editDriveEntry, edit);
-        HeapFree(GetProcessHeap(), 0, edit);
-
-        serial = get_control_text(hDlg, IDC_EDIT_SERIAL);
-        if(!serial) serial = strdup("");
-        setDriveSerial(editDriveEntry, serial);
-        HeapFree(GetProcessHeap(), 0, serial);
-
-        /* TODO: we don't have a device at this point */
-/*      setDriveValue(editWindowLetter, "Device", NULL); */
-	    enable_labelserial_box(hDlg, BOX_MODE_CD_ASSIGN);
-	    refreshDriveDlg(driveDlgHandle);
-	    break;
-      }
-	    
-      case IDC_BUTTON_SHOW_HIDE_ADVANCED:
-          advanced = (advanced == TRUE) ? FALSE : TRUE; /* toggle state */
-          advancedDriveEditDialog(hDlg, advanced);
-          break;
-
-	  case ID_BUTTON_OK:	  
-	    EndDialog(hDlg, wParam);
-	    return TRUE;
-
-      }
-      if (HIWORD(wParam) == EN_CHANGE) onEditChanged(hDlg, LOWORD(wParam));
-      break;
-  }
-  return FALSE;
-}
-
-void onAddDriveClicked(HWND hDlg) {
-  /* we should allocate a drive letter automatically. We also need
-     some way to let the user choose the mapping point, for now we
-     will just force them to enter a path automatically, with / being
-     the default. In future we should be able to temporarily map /
-     then invoke the directory chooser dialog. */
-  
-  char newLetter = 'C'; /* we skip A and B, they are historically floppy drives */
-  long mask = ~drive_available_mask(0); /* the mask is now which drives aren't available */
-  
-  while (mask & (1 << (newLetter - 'A'))) {
-    newLetter++;
-    if (newLetter > 'Z') {
-      MessageBox(NULL, "You cannot add any more drives.\n\nEach drive must have a letter, from A to Z, so you cannot have more than 26", "", MB_OK | MB_ICONEXCLAMATION);
-      return;
-    }
-  }
-  WINE_TRACE("allocating drive letter %c\n", newLetter);
-
-  if(newLetter == 'C') {
-      addDrive(newLetter, "fake_windows", "System Drive", "", DRIVE_FIXED);
-  } else {
-      addDrive(newLetter, "/", "", "", DRIVE_FIXED);
-  }
-
-  refreshDriveDlg(driveDlgHandle);
-
-  DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DRIVE_EDIT), NULL, (DLGPROC) DriveEditDlgProc, (LPARAM) &(drives[getDrive(newLetter)]));
-}
-
-void onDriveInitDialog(void)
-{
-  char *pDevices, *pDev;
-  int ret;
-  int i;
-  int retval;
-
-  WINE_TRACE("\n");
-
-  /* setup the drives array */
-  pDev = pDevices = malloc(512);
-  ret = GetLogicalDriveStrings(512, pDevices);
+        char volname[512]; /* volume name  */
+        DWORD serial;
+        char serialstr[256];
+        char rootpath[256];
+        char simplepath[3];
+        int pathlen;
+        char targetpath[256];
+        char *c;
+
+        *devices = toupper(*devices);
+
+        WINE_TRACE("devices == '%s'\n", devices);
+
+        volname[0] = 0;
+
+        retval = GetVolumeInformation(devices,
+                                      volname,
+                                      sizeof(volname),
+                                      &serial,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      0);
+        if(!retval)
+        {
+            WINE_ERR("GetVolumeInformation() for '%s' failed, setting serial to 0\n", devices);
+            PRINTERROR();
+            serial = 0;
+        }
 
-  /* make all devices unused */
-  for(i = 0; i < 26; i++)
-  {
-      drives[i].letter = 'A' + i;
-      drives[i].in_use = FALSE;
-  }
+        WINE_TRACE("serial: '0x%lX'\n", serial);
 
-  i = 0;
+        /* build rootpath for GetDriveType() */
+        strncpy(rootpath, devices, sizeof(rootpath));
+        pathlen = strlen(rootpath);
 
-  while(ret)
-  {
-    CHAR volumeNameBuffer[512];
-    DWORD serialNumber;
-    CHAR serialNumberString[256];
-    DWORD maxComponentLength;
-    DWORD fileSystemFlags;
-    CHAR fileSystemName[128];
-    char rootpath[256];
-    char simplepath[3];
-    int pathlen;
-    char targetpath[256];
-
-    *pDevices = toupper(*pDevices);
-
-    WINE_TRACE("pDevices == '%s'\n", pDevices);
-
-    volumeNameBuffer[0] = 0;
-    
-    retval = GetVolumeInformation(pDevices,
-                         volumeNameBuffer,
-                         sizeof(volumeNameBuffer),
-                         &serialNumber,
-                         &maxComponentLength,
-                         &fileSystemFlags,
-                         fileSystemName,
-                         sizeof(fileSystemName));
-    if(!retval)
-    {
-        WINE_TRACE("GetVolumeInformation() for '%s' failed, setting serialNumber to 0\n", pDevices);
-        PRINTERROR();
-        serialNumber = 0;
-    }
+        /* ensure that we have a backslash on the root path */
+        if ((rootpath[pathlen - 1] != '\\') && (pathlen < sizeof(rootpath)))
+        {
+            rootpath[pathlen] = '\\';
+            rootpath[pathlen + 1] = 0;
+        }
 
-    WINE_TRACE("serialNumber: '0x%lX'\n", serialNumber);
+        strncpy(simplepath, devices, 2); /* QueryDosDevice() requires no trailing backslash */
+        simplepath[2] = 0;
+        QueryDosDevice(simplepath, targetpath, sizeof(targetpath));
+
+        /* targetpath may have forward slashes rather than backslashes, so correct */
+        c = targetpath;
+        do if (*c == '\\') *c = '/'; while (*c++);
+
+        snprintf(serialstr, sizeof(serialstr), "%lX", serial);
+        WINE_TRACE("serialstr: '%s'\n", serialstr);
+        add_drive(*devices, targetpath, volname, serialstr, GetDriveType(rootpath));
 
-    /* build rootpath for GetDriveType() */
-    strncpy(rootpath, pDevices, sizeof(rootpath));
-    pathlen = strlen(rootpath);
-    /* ensure that we have a backslash on the root path */
-    if((rootpath[pathlen - 1] != '\\') &&
-       (pathlen < sizeof(rootpath)))
-     {
-         rootpath[pathlen] = '\\';
-         rootpath[pathlen + 1] = 0;
-     }
-
-    strncpy(simplepath, pDevices, 2); /* QueryDosDevice() requires no trailing backslash */
-    simplepath[2] = 0;
-    QueryDosDevice(simplepath, targetpath, sizeof(targetpath)); 
-    
-    snprintf(serialNumberString, sizeof(serialNumberString), "%lX", serialNumber);
-    WINE_TRACE("serialNumberString: '%s'\n", serialNumberString);
-    addDrive(*pDevices, targetpath, volumeNameBuffer, serialNumberString, GetDriveType(rootpath));
+        len -= strlen(devices);
+        devices += strlen(devices);
 
-    ret-=strlen(pDevices);
-    pDevices+=strlen(pDevices);
+        /* skip over any nulls */
+        while ((*devices == 0) && (len))
+        {
+            len--;
+            devices++;
+        }
 
-    /* skip over any nulls */
-    while((*pDevices == 0) && (ret))
-    {
-        ret--;
-        pDevices++;
+        drivecount++;
     }
 
-    i++;
-  }
-
-  WINE_TRACE("found %d drives\n", i);
+    WINE_TRACE("found %d drives\n", drivecount);
 
-  free(pDev);
+    HeapFree(GetProcessHeap(), 0, dev);
 }
 
-
-void applyDriveChanges(void)
+/* some of this code appears to be broken by bugs in Wine: the label
+ * setting code has no effect, for instance  */
+void apply_drive_changes()
 {
     int i;
     CHAR devicename[4];
@@ -815,7 +281,7 @@ void applyDriveChanges(void)
     {
         defineDevice = FALSE;
         foundDrive = FALSE;
-        snprintf(devicename, sizeof(devicename), "%c:", 'A' + i); 
+        snprintf(devicename, sizeof(devicename), "%c:", 'A' + i);
 
         /* get a drive */
         if(QueryDosDevice(devicename, targetpath, sizeof(targetpath)))
@@ -866,11 +332,13 @@ void applyDriveChanges(void)
             {
                 defineDevice = TRUE;
                 WINE_TRACE("  making changes to drive '%s'\n", devicename);
-            } else
+            }
+            else
             {
                 WINE_TRACE("  no changes to drive '%s'\n", devicename);
             }
-        } else if(foundDrive && !drives[i].in_use)
+        }
+        else if(foundDrive && !drives[i].in_use)
         {
             /* remove this drive */
             if(!DefineDosDevice(DDD_REMOVE_DEFINITION, devicename, drives[i].unixpath))
@@ -878,12 +346,14 @@ void applyDriveChanges(void)
                 WINE_ERR("unable to remove devicename of '%s', targetpath of '%s'\n",
                     devicename, drives[i].unixpath);
                 PRINTERROR();
-            } else
+            }
+            else
             {
                 WINE_TRACE("removed devicename of '%s', targetpath of '%s'\n",
                            devicename, drives[i].unixpath);
             }
-        } else if(drives[i].in_use) /* foundDrive must be false from the above check */
+        }
+        else if(drives[i].in_use) /* foundDrive must be false from the above check */
         {
             defineDevice = TRUE;
         }
@@ -900,17 +370,18 @@ void applyDriveChanges(void)
 
             /* define this drive */
             /* DefineDosDevice() requires that NO trailing slash be present */
-            snprintf(devicename, sizeof(devicename), "%c:", 'A' + i); 
+            snprintf(devicename, sizeof(devicename), "%c:", 'A' + i);
             if(!DefineDosDevice(DDD_RAW_TARGET_PATH, devicename, drives[i].unixpath))
             {
                 WINE_ERR("  unable to define devicename of '%s', targetpath of '%s'\n",
                     devicename, drives[i].unixpath);
                 PRINTERROR();
-            } else
+            }
+            else
             {
                 WINE_TRACE("  added devicename of '%s', targetpath of '%s'\n",
                            devicename, drives[i].unixpath);
-                
+
                 /* SetVolumeLabel() requires a trailing slash */
                 snprintf(devicename, sizeof(devicename), "%c:\\", 'A' + i);
                 if(!SetVolumeLabel(devicename, drives[i].label))
@@ -918,7 +389,8 @@ void applyDriveChanges(void)
                     WINE_ERR("unable to set volume label for devicename of '%s', label of '%s'\n",
                         devicename, drives[i].label);
                     PRINTERROR();
-                } else
+                }
+                else
                 {
                     WINE_TRACE("  set volume label for devicename of '%s', label of '%s'\n",
                         devicename, drives[i].label);
@@ -934,7 +406,7 @@ void applyDriveChanges(void)
                 typeText = "floppy";
             else /* must be DRIVE_CDROM */
                 typeText = "cdrom";
-            
+
 
             snprintf(driveValue, sizeof(driveValue), "%c:", toupper(drives[i].letter));
 
@@ -945,7 +417,8 @@ void applyDriveChanges(void)
             if(retval != ERROR_SUCCESS)
             {
                 WINE_TRACE("  Unable to open '%s'\n", "Software\\Wine\\Drives");
-            } else
+            }
+            else
             {
                 retval = RegSetValueEx(
                               hKey,
@@ -958,7 +431,8 @@ void applyDriveChanges(void)
                 {
                     WINE_TRACE("  Unable to set value of '%s' to '%s'\n",
                                driveValue, typeText);
-                } else
+                }
+                else
                 {
                     WINE_TRACE("  Finished setting value of '%s' to '%s'\n",
                                driveValue, typeText);
@@ -978,21 +452,22 @@ void applyDriveChanges(void)
                        CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
-            if(hFile)
+            if (hFile != INVALID_HANDLE_VALUE)
             {
                 WINE_TRACE("  writing serial number of '%s'\n", drives[i].serial);
                 WriteFile(hFile,
                           drives[i].serial,
                           strlen(drives[i].serial),
                           NULL,
-                          NULL); 
+                          NULL);
                 WriteFile(hFile,
                           "\n",
                           strlen("\n"),
                           NULL,
-                          NULL); 
+                          NULL);
                 CloseHandle(hFile);
-            } else
+            }
+            else
             {
                 WINE_TRACE("  CreateFile() error with file '%s'\n", filename);
             }
@@ -1001,78 +476,9 @@ void applyDriveChanges(void)
         /* if this drive is in use we should free it up */
         if(drives[i].in_use)
         {
-            freeDrive(&drives[i]); /* free up the string memory */
+            delete_drive(&drives[i]); /* free up the string memory */
         }
     }
 }
 
 
-INT_PTR CALLBACK
-DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-  int nItem;
-  drive_entry_t *pDrive;
-
-  switch (uMsg) {
-      case WM_INITDIALOG:
-          onDriveInitDialog();
-          break;
-
-      case WM_SHOWWINDOW:
-          set_window_title(hDlg);
-          break;
-          
-      case WM_COMMAND:
-	switch (LOWORD(wParam)) {
-	    case IDC_LIST_DRIVES:
-	      /* double click should open the edit window for the chosen drive */
-	      if (HIWORD(wParam) == LBN_DBLCLK)
-	        SendMessageA(hDlg, WM_COMMAND, IDC_BUTTON_EDIT, 0);
-
-	      if (HIWORD(wParam) == LBN_SELCHANGE) lastSel = SendDlgItemMessage(hDlg, IDC_LIST_DRIVES, LB_GETCURSEL, 0, 0);
-	      break;
-
-	    case IDC_BUTTON_ADD:
-	      onAddDriveClicked(hDlg);
-	      break;
-
-	    case IDC_BUTTON_REMOVE:
-	      if (HIWORD(wParam) != BN_CLICKED) break;
-	      nItem = SendDlgItemMessage(hDlg, IDC_LIST_DRIVES,  LB_GETCURSEL, 0, 0);
-	      pDrive = (drive_entry_t*)SendDlgItemMessage(hDlg, IDC_LIST_DRIVES, LB_GETITEMDATA, nItem, 0);
-          freeDrive(pDrive);
-	      refreshDriveDlg(driveDlgHandle);
-	      break;
-	      
-	    case IDC_BUTTON_EDIT:
-	      if (HIWORD(wParam) != BN_CLICKED) break;
-	      nItem = SendMessage(GetDlgItem(hDlg, IDC_LIST_DRIVES),  LB_GETCURSEL, 0, 0);
-	      pDrive = (drive_entry_t*)SendMessage(GetDlgItem(hDlg, IDC_LIST_DRIVES), LB_GETITEMDATA, nItem, 0);
-	      DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DRIVE_EDIT), NULL, (DLGPROC) DriveEditDlgProc, (LPARAM) pDrive);
-	      break;
-
-	    case IDC_BUTTON_AUTODETECT:
-	      WRITEME(hDlg);
-	      break;
-	}
-	break;
-	
-      case WM_NOTIFY: switch(((LPNMHDR)lParam)->code) {
-	    case PSN_KILLACTIVE:
-          WINE_TRACE("PSN_KILLACTIVE\n");
-	      SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
-	      break;
-	    case PSN_APPLY:
-          applyDriveChanges();
-	      SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
-	      break;
-	    case PSN_SETACTIVE:
-	      driveDlgHandle = hDlg;
-	      refreshDriveDlg (driveDlgHandle);
-	      break;
-	}
-	break;
-  }
-
-  return FALSE;
-}
Index: programs/winecfg/resource.h
===================================================================
RCS file: /home/wine/wine/programs/winecfg/resource.h,v
retrieving revision 1.19
diff -u -p -r1.19 resource.h
--- programs/winecfg/resource.h	28 Sep 2004 03:55:16 -0000	1.19
+++ programs/winecfg/resource.h	19 Nov 2004 18:04:58 -0000
@@ -35,7 +35,6 @@
 #define IDD_GRAPHCFG                    110
 #define IDD_DLLCFG                      111
 #define IDD_DRIVECFG                    112
-#define IDD_SYSTEMCFG                   113
 #define IDD_DRIVE_EDIT                  114
 #define IDB_WINE_LOGO                   200
 #define IDC_TABABOUT                    1001
@@ -95,13 +94,15 @@
 #define IDC_RADIO_AUTODETECT            1068
 #define IDC_RADIO_ASSIGN                1069
 #define IDC_BUTTON_BROWSE_DEVICE        1070
-#define IDC_BOX_LABELSERIAL             1071
 #define IDC_STATIC_SERIAL               1072
 #define IDC_STATIC_LABEL                1073
 #define IDC_ENABLE_DESKTOP              1074
 #define IDS_DRIVE_NO_C                  1075
 #define IDC_BUTTON_SHOW_HIDE_ADVANCED   1076
 #define IDC_STATIC_TYPE                 1077
+#define IDC_LABELSERIAL_STATIC          1078
+
+#define IDC_DRIVE_LABEL                 1078
 
 /* graphics */
 #define IDC_ENABLE_MANAGED              1100
Index: programs/winecfg/winecfg.c
===================================================================
RCS file: /home/wine/wine/programs/winecfg/winecfg.c,v
retrieving revision 1.24
diff -u -p -r1.24 winecfg.c
--- programs/winecfg/winecfg.c	19 Oct 2004 23:51:16 -0000	1.24
+++ programs/winecfg/winecfg.c	19 Nov 2004 18:04:59 -0000
@@ -19,6 +19,12 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * TODO:
+ *  - Use unicode
+ *  - Icons in listviews/icons
+ *  - Better add app dialog, scan c: for EXE files and add to list in background
+ *  - Use [GNOME] HIG style groupboxes rather than win32 style (looks nicer, imho)
+ *
  */
 
 #include <assert.h>
@@ -47,11 +53,11 @@ void set_window_title(HWND dialog)
     char *newtitle;
 
     /* update the window title  */
-    if (currentApp)
+    if (current_app)
     {
         char *template = "Wine Configuration for %s";
-        newtitle = HeapAlloc(GetProcessHeap(), 0, strlen(template) + strlen(currentApp) + 1);
-        sprintf(newtitle, template, currentApp);
+        newtitle = HeapAlloc(GetProcessHeap(), 0, strlen(template) + strlen(current_app) + 1);
+        sprintf(newtitle, template, current_app);
     }
     else
     {
@@ -65,7 +71,7 @@ void set_window_title(HWND dialog)
 
 
 /**
- * get_config_key: Retrieves a configuration value from the registry
+ * getkey: Retrieves a configuration value from the registry
  *
  * char *subkey : the name of the config section
  * char *name : the name of the config value
@@ -75,7 +81,7 @@ void set_window_title(HWND dialog)
  * not. Caller is responsible for releasing the result.
  *
  */
-static char *get_config_key (char *subkey, char *name, char *def)
+static char *getkey (char *subkey, char *name, char *def)
 {
     LPBYTE buffer = NULL;
     DWORD len;
@@ -123,7 +129,7 @@ end:
 }
 
 /**
- * set_config_key: convenience wrapper to set a key/value pair
+ * setkey: convenience wrapper to set a key/value pair
  *
  * const char *subKey : the name of the config section
  * const char *valueName : the name of the config value
@@ -133,7 +139,7 @@ end:
  *
  * If valueName or value is NULL, an empty section will be created
  */
-int set_config_key(const char *subkey, const char *name, const char *value) {
+int setkey(const char *subkey, const char *name, const char *value) {
     DWORD res = 1;
     HKEY key = NULL;
 
@@ -252,7 +258,7 @@ char *get(char *path, char *name, char *
     }
 
     /* no, so get from the registry */
-    val = get_config_key(path, name, def);
+    val = getkey(path, name, def);
 
     WINE_TRACE("returning %s\n", val);
 
@@ -439,7 +445,7 @@ static void process_setting(struct setti
     if (s->value)
     {
 	WINE_TRACE("Setting %s:%s to '%s'\n", s->path, s->name, s->value);
-        set_config_key(s->path, s->name, s->value);
+        setkey(s->path, s->name, s->value);
     }
     else
     {
@@ -465,7 +471,7 @@ void apply(void)
 
 /* ================================== utility functions ============================ */
 
-char *currentApp = NULL; /* the app we are currently editing, or NULL if editing global */
+char *current_app = NULL; /* the app we are currently editing, or NULL if editing global */
 
 /* returns a registry key path suitable for passing to addTransaction  */
 char *keypath(char *section)
@@ -474,10 +480,10 @@ char *keypath(char *section)
 
     if (result) HeapFree(GetProcessHeap(), 0, result);
 
-    if (currentApp)
+    if (current_app)
     {
-        result = HeapAlloc(GetProcessHeap(), 0, strlen("AppDefaults\\") + strlen(currentApp) + 2 /* \\ */ + strlen(section) + 1 /* terminator */);
-        sprintf(result, "AppDefaults\\%s\\%s", currentApp, section);
+        result = HeapAlloc(GetProcessHeap(), 0, strlen("AppDefaults\\") + strlen(current_app) + 2 /* \\ */ + strlen(section) + 1 /* terminator */);
+        sprintf(result, "AppDefaults\\%s\\%s", current_app, section);
     }
     else
     {
@@ -494,6 +500,10 @@ void PRINTERROR(void)
         FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
                        0, GetLastError(), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
                        (LPSTR)&msg, 0, NULL);
+
+        /* eliminate trailing newline, is this a Wine bug? */
+        *(strrchr(msg, '\n')) = '\0';
+        
         WINE_TRACE("error: '%s'\n", msg);
 }
 
Index: programs/winecfg/winecfg.h
===================================================================
RCS file: /home/wine/wine/programs/winecfg/winecfg.h,v
retrieving revision 1.19
diff -u -p -r1.19 winecfg.h
--- programs/winecfg/winecfg.h	28 Sep 2004 04:05:55 -0000	1.19
+++ programs/winecfg/winecfg.h	19 Nov 2004 18:04:59 -0000
@@ -38,15 +38,7 @@
 #define IS_OPTION_FALSE(ch) \
     ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
 
-#define return_if_fail(try) \
-    if (!(try)) { \
-        WINE_ERR("check (" #try ") at %s:%d failed, returning\n", __FILE__,  __LINE__ - 1); \
-	return; \
-    }
-
-#define WRITEME(owner) MessageBox(owner, "Write me!", "", MB_OK | MB_ICONEXCLAMATION);
-
-extern char *currentApp; /* NULL means editing global settings  */
+extern char *current_app; /* NULL means editing global settings  */
 
 /* Use get and set to alter registry settings. The changes made through set
    won't be committed to the registry until process_all_settings is called,
@@ -55,6 +47,7 @@ extern char *currentApp; /* NULL means e
    You are expected to release the result of get. The parameters to set will
    be copied, so release them too when necessary.
  */
+
 void set(char *path, char *name, char *value);
 char *get(char *path, char *name, char *def);
 BOOL exists(char *path, char *name);
@@ -62,37 +55,52 @@ void apply(void);
 char **enumerate_values(char *path);
 
 /* returns a string of the form "AppDefaults\\appname.exe\\section", or just "section" if
- * the user is editing the global settings.
- *
- * no explicit free is needed of the string returned by this function
+   the user is editing the global settings.
+ 
+   no explicit free is needed of the string returned by this function
  */
 char *keypath(char *section); 
 
-/* Initializes the transaction system */
 int initialize(void);
 extern HKEY config_key;
 
+/* hack for the property sheet control  */
 void set_window_title(HWND dialog);
 
-/* Graphics */
-
-void initGraphDlg (HWND hDlg);
-void saveGraphDlgSettings (HWND hDlg);
+/* Window procedures */
 INT_PTR CALLBACK GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
-/* Drive management */
-void initDriveDlg (HWND hDlg);
-void saveDriveSettings (HWND hDlg);
-
 INT_PTR CALLBACK DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK DriveEditDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
-/* Audio config dialog */
 INT_PTR CALLBACK AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
-/* some basic utilities to make win32 suck less */
+/* Drive management  */
+void load_drives();
+int autodetect_drives();
+
+struct drive
+{
+    char letter;
+    char *unixpath;
+    char *label;
+    char *serial;
+    DWORD type; /* one of the DRIVE_ constants from winbase.h  */
+
+    BOOL in_use;
+};
+
+#define DRIVE_MASK_BIT(B) 1 << (toupper(B) - 'A')
+
+long drive_available_mask(char letter);
+BOOL add_drive(char letter, char *targetpath, char *label, char *serial, unsigned int type);
+void delete_drive(struct drive *pDrive);
+void apply_drive_changes();
+extern struct drive drives[26]; /* one for each drive letter */
+
+BOOL gui_mode;
+
+/* Some basic utilities to make win32 suck less */
 #define disable(id) EnableWindow(GetDlgItem(dialog, id), 0);
 #define enable(id) EnableWindow(GetDlgItem(dialog, id), 1);
 void PRINTERROR(void); /* WINE_TRACE() the plaintext error message from GetLastError() */
@@ -104,15 +112,20 @@ static inline char *strdupA(char *s)
     return strcpy(r, s);
 }
 
-static inline char *get_control_text(HWND dialog, WORD id)
+static inline char *get_text(HWND dialog, WORD id)
 {
     HWND item = GetDlgItem(dialog, id);
     int len = GetWindowTextLength(item) + 1;
-    char *result = HeapAlloc(GetProcessHeap(), 0, len);
-    if (GetWindowText(item, result, len) == 0) return NULL;
+    char *result = len ? HeapAlloc(GetProcessHeap(), 0, len) : NULL;
+    if (!result || GetWindowText(item, result, len) == 0) return NULL;
     return result;
 }
 
-#define WINE_KEY_ROOT "Software\\Wine\\Wine\\Config"
+static inline void set_text(HWND dialog, WORD id, char *text)
+{
+    SetWindowText(GetDlgItem(dialog, id), text);
+}
+
+#define WINE_KEY_ROOT "Software\\Wine\\Testing\\Config"
 
 #endif
Index: programs/winecfg/x11drvdlg.c
===================================================================
RCS file: /home/wine/wine/programs/winecfg/x11drvdlg.c,v
retrieving revision 1.16
diff -u -p -r1.16 x11drvdlg.c
--- programs/winecfg/x11drvdlg.c	28 Sep 2004 04:05:55 -0000	1.16
+++ programs/winecfg/x11drvdlg.c	19 Nov 2004 18:05:01 -0000
@@ -145,8 +145,8 @@ static void set_from_desktop_edits(HWND 
     
     WINE_TRACE("\n");
 
-    width = get_control_text(dialog, IDC_DESKTOP_WIDTH);
-    height = get_control_text(dialog, IDC_DESKTOP_HEIGHT);
+    width = get_text(dialog, IDC_DESKTOP_WIDTH);
+    height = get_text(dialog, IDC_DESKTOP_HEIGHT);
 
     if (strcmp(width, "") == 0)
     {
@@ -184,7 +184,7 @@ void on_enable_desktop_clicked(HWND dial
 }
 
 static void on_screen_depth_changed(HWND dialog) {
-    char *newvalue = get_control_text(dialog, IDC_SCREEN_DEPTH);
+    char *newvalue = get_text(dialog, IDC_SCREEN_DEPTH);
     char *spaceIndex = strchr(newvalue, ' ');
     
     WINE_TRACE("newvalue=%s\n", newvalue);
--- /dev/null	2004-02-23 21:02:56.000000000 +0000
+++ programs/winecfg/driveui.c	2004-11-05 20:58:47.000000000 +0000
@@ -0,0 +1,651 @@
+/*
+ * Drive management UI code
+ *
+ * Copyright 2003 Mark Westcott
+ * Copyright 2004 Chris Morgan
+ * Copyright 2003-2004 Mike Hearn <mike at navi.cx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <shellapi.h>
+#include <objbase.h>
+#include <shlguid.h>
+#include <shlwapi.h>
+#include <shlobj.h>
+#include <winuser.h>
+
+#include <wine/debug.h>
+
+#include "winecfg.h"
+#include "resource.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
+
+#define BOX_MODE_CD_ASSIGN 1
+#define BOX_MODE_CD_AUTODETECT 2
+#define BOX_MODE_NONE 3
+#define BOX_MODE_NORMAL 4
+
+static BOOL advanced = FALSE;
+static BOOL updating_ui = FALSE;
+static struct drive* current_drive;
+
+static void get_etched_rect(HWND dialog, RECT *rect);
+
+static void set_advanced(HWND dialog)
+{
+    int state;
+    char *text;
+    RECT rect;
+
+    /* FIXME: internationalization  */
+    if (advanced)
+    {
+        state = SW_NORMAL;
+        text = "&Hide Advanced";
+    }
+    else
+    {
+        state = SW_HIDE;
+        text = "&Show Advanced";
+    }
+
+    ShowWindow(GetDlgItem(dialog, IDC_RADIO_AUTODETECT), state);
+    ShowWindow(GetDlgItem(dialog, IDC_RADIO_ASSIGN), state);
+    ShowWindow(GetDlgItem(dialog, IDC_EDIT_LABEL), state);
+    ShowWindow(GetDlgItem(dialog, IDC_EDIT_DEVICE), state);
+    ShowWindow(GetDlgItem(dialog, IDC_STATIC_LABEL), state);
+    ShowWindow(GetDlgItem(dialog, IDC_BUTTON_BROWSE_DEVICE), state);
+    ShowWindow(GetDlgItem(dialog, IDC_EDIT_SERIAL), state);
+    ShowWindow(GetDlgItem(dialog, IDC_STATIC_SERIAL), state);
+    ShowWindow(GetDlgItem(dialog, IDC_LABELSERIAL_STATIC), state);
+
+    /* update the button text based on the state */
+    SetWindowText(GetDlgItem(dialog, IDC_BUTTON_SHOW_HIDE_ADVANCED), text);
+
+    /* redraw for the etched line */
+    get_etched_rect(dialog, &rect);
+    InflateRect(&rect, 5, 5);
+    InvalidateRect(dialog, &rect, TRUE);
+}
+
+struct drive_typemap {
+    const uint sCode;
+    const char *sDesc;
+};
+
+static struct drive_typemap type_pairs[] = {
+  { DRIVE_FIXED,      "Local hard disk" },
+  { DRIVE_REMOTE,     "Network share"   },
+  { DRIVE_REMOVABLE,  "Floppy disk"     },
+  { DRIVE_CDROM,      "CD-ROM"          }
+};
+
+#define DRIVE_TYPE_DEFAULT 1
+
+void fill_drive_droplist(long mask, char curletter, HWND dialog)
+{
+    int i;
+    int selection;
+    int count;
+    int next_letter;
+    char sName[4] = "A:";
+
+    for (i = 0, count = 0, selection = -1, next_letter = -1; i <= 'Z'-'A'; ++i)
+    {
+        if (mask & DRIVE_MASK_BIT('A' + i))
+        {
+            int index;
+
+            sName[0] = 'A' + i;
+            index = SendDlgItemMessage(dialog, IDC_COMBO_LETTER, CB_ADDSTRING, 0, (LPARAM) sName);
+
+            if (toupper(curletter) == 'A' + i)
+            {
+                selection = count;
+            }
+
+            if (i >= 2 && next_letter == -1)
+            {
+                /* default drive is first one of C-Z */
+                next_letter = count;
+            }
+
+            count++;
+        }
+    }
+
+    if (selection == -1)
+    {
+        selection = next_letter;
+    }
+
+    SendDlgItemMessage(dialog, IDC_COMBO_LETTER, CB_SETCURSEL, selection, 0);
+}
+
+
+void enable_labelserial_box(HWND dialog, int mode)
+{
+    WINE_TRACE("mode=%d\n", mode);
+
+    switch (mode)
+    {
+        case BOX_MODE_CD_ASSIGN:
+            enable(IDC_RADIO_ASSIGN);
+            disable(IDC_EDIT_DEVICE);
+            disable(IDC_BUTTON_BROWSE_DEVICE);
+            enable(IDC_EDIT_SERIAL);
+            enable(IDC_EDIT_LABEL);
+            enable(IDC_STATIC_SERIAL);
+            enable(IDC_STATIC_LABEL);
+            break;
+
+        case BOX_MODE_CD_AUTODETECT:
+            enable(IDC_RADIO_ASSIGN);
+            enable(IDC_EDIT_DEVICE);
+            enable(IDC_BUTTON_BROWSE_DEVICE);
+            disable(IDC_EDIT_SERIAL);
+            disable(IDC_EDIT_LABEL);
+            disable(IDC_STATIC_SERIAL);
+            disable(IDC_STATIC_LABEL);
+            break;
+
+        case BOX_MODE_NONE:
+            disable(IDC_RADIO_ASSIGN);
+            disable(IDC_EDIT_DEVICE);
+            disable(IDC_BUTTON_BROWSE_DEVICE);
+            disable(IDC_EDIT_SERIAL);
+            disable(IDC_EDIT_LABEL);
+            disable(IDC_STATIC_SERIAL);
+            disable(IDC_STATIC_LABEL);
+            break;
+
+        case BOX_MODE_NORMAL:
+            enable(IDC_RADIO_ASSIGN);
+            disable(IDC_EDIT_DEVICE);
+            disable(IDC_BUTTON_BROWSE_DEVICE);
+            enable(IDC_EDIT_SERIAL);
+            enable(IDC_EDIT_LABEL);
+            enable(IDC_STATIC_SERIAL);
+            enable(IDC_STATIC_LABEL);
+            break;
+    }
+}
+
+int fill_drives_list(HWND dialog)
+{
+    int count = 0;
+    BOOL drivec_present = FALSE;
+    int i;
+    int prevsel = -1;
+
+    WINE_TRACE("\n");
+
+    updating_ui = TRUE;
+
+    prevsel = SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_GETCURSEL, 0, 0);
+
+    /* Clear the listbox */
+    SendMessage(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_RESETCONTENT, 0, 0);
+
+    for(i = 0; i < 26; i++)
+    {
+        char *title = 0;
+        int len;
+        int index;
+
+        /* skip over any unused drives */
+        if (!drives[i].in_use)
+            continue;
+
+        if (drives[i].letter == 'C')
+            drivec_present = TRUE;
+
+        len = snprintf(title, 0, "%c:    %s", 'A' + i,
+                       drives[i].unixpath);
+        len++; /* add a byte for the trailing null */
+
+        title = HeapAlloc(GetProcessHeap(), 0, len);
+
+        /* the %s in the item label will be replaced by the drive letter, so -1, then
+           -2 for the second %s which will be expanded to the label, finally + 1 for terminating #0 */
+        snprintf(title, len, "%c:    %s", 'A' + i,
+                 drives[i].unixpath);
+
+        WINE_TRACE("title is '%s'\n", title);
+
+        /* the first SendMessage call adds the string and returns the index, the second associates that index with it */
+        index = SendMessage(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_ADDSTRING ,(WPARAM) -1, (LPARAM) title);
+        SendMessage(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_SETITEMDATA, index, (LPARAM) &drives[i]);
+
+        HeapFree(GetProcessHeap(), 0, title);
+        count++;
+    }
+
+    WINE_TRACE("loaded %d drives\n", count);
+
+    /* show the warning if there is no Drive C */
+    if (!drivec_present)
+        ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_NORMAL);
+    else
+        ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_HIDE);
+
+    SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_SETCURSEL, prevsel == -1 ? 0 : prevsel, 0);
+
+    updating_ui = FALSE;
+    return count;
+}
+
+
+void on_add_click(HWND dialog)
+{
+    /* we should allocate a drive letter automatically. We also need
+       some way to let the user choose the mapping point, for now we
+       will just force them to enter a path automatically, with / being
+       the default. In future we should be able to temporarily map /
+       then invoke the directory chooser dialog. */
+
+    char new = 'C'; /* we skip A and B, they are historically floppy drives */
+    long mask = ~drive_available_mask(0); /* the mask is now which drives aren't available */
+    int i, c;
+
+    while (mask & (1 << (new - 'A')))
+    {
+        new++;
+        if (new > 'Z')
+        {
+            MessageBox(dialog, "You cannot add any more drives.\n\nEach drive must have a letter, from A to Z, so you cannot have more than 26", "", MB_OK | MB_ICONEXCLAMATION);
+            return;
+        }
+    }
+
+    WINE_TRACE("allocating drive letter %c\n", new);
+
+    if (new == 'C') add_drive(new, "../drive_c", "System Drive", "", DRIVE_FIXED);
+    else add_drive(new, "/", "", "", DRIVE_FIXED);
+
+    fill_drives_list(dialog);
+
+    /* select the newly created drive */
+    mask = ~drive_available_mask(0);
+    c = 0;
+    for (i = 0; i < 26; i++)
+    {
+        if ('A' + i == new) break;
+        if ((1 << i) & mask) c++;
+    }
+    SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_SETCURSEL, c, 0);
+
+    SetFocus(GetDlgItem(dialog, IDC_LIST_DRIVES));
+}
+
+void on_remove_click(HWND dialog)
+{
+    int item;
+    struct drive *drive;
+
+    item = SendDlgItemMessage(dialog, IDC_LIST_DRIVES,  LB_GETCURSEL, 0, 0);
+    if (item == -1) return; /* no selection */
+
+    drive = (struct drive *) SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_GETITEMDATA, item, 0);
+
+    if (drive->letter == 'C')
+    {
+        DWORD result = MessageBox(dialog, "Are you sure you want to delete drive C?\n\nMost Windows applications expect drive C to exist, and will die messily if it doesn't. If you proceed remember to recreate it!", "", MB_YESNO | MB_ICONEXCLAMATION);
+        if (result == IDNO) return;
+    }
+
+    delete_drive(drive);
+
+    fill_drives_list(dialog);
+
+    item = item - 1;
+    if (item < 0) item = 0;
+    SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_SETCURSEL, item, 0);   /* previous item */
+
+    SetFocus(GetDlgItem(dialog, IDC_LIST_DRIVES));
+}
+
+void update_controls(HWND dialog) {
+    char *path;
+    uint type;
+    char *label;
+    char *serial;
+    char *device;
+    int i, selection = -1;
+
+    updating_ui = TRUE;
+
+    i = SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_GETCURSEL, 0, 0);
+    if (i == -1)
+    {
+        /* no selection? let's select something for the user. this will re-enter */
+        SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_SETCURSEL, 0, 0);
+        return;
+    }
+    current_drive = (struct drive *) SendDlgItemMessage(dialog, IDC_LIST_DRIVES, LB_GETITEMDATA, i, 0);
+
+    WINE_TRACE("Updating sheet for drive %c\n", current_drive->letter);
+
+    /* Drive letters */
+    fill_drive_droplist(drive_available_mask(current_drive->letter), current_drive->letter, dialog);
+
+    /* path */
+    path = current_drive->unixpath;
+    WINE_TRACE("set path control text to '%s'\n", path);
+    set_text(dialog, IDC_EDIT_PATH, path);
+
+    /* drive type */
+    type = current_drive->type;
+    if (type)
+    {
+        for (i = 0; i < sizeof(type_pairs) / sizeof(struct drive_typemap); i++)
+        {
+            SendDlgItemMessage(dialog, IDC_COMBO_TYPE, CB_ADDSTRING, 0, (LPARAM) type_pairs[i].sDesc);
+
+            if (type_pairs[i].sCode ==  type)
+            {
+                selection = i;
+            }
+        }
+
+        if (selection == -1) selection = DRIVE_TYPE_DEFAULT;
+        SendDlgItemMessage(dialog, IDC_COMBO_TYPE, CB_SETCURSEL, selection, 0);
+    } else WINE_WARN("no Type field?\n");
+
+
+    /* removeable media properties */
+    label = current_drive->label;
+    set_text(dialog, IDC_EDIT_LABEL, label);
+
+    /* set serial edit text */
+    serial = current_drive->serial;
+    set_text(dialog, IDC_EDIT_SERIAL, serial);
+
+    /* TODO: get the device here to put into the edit box */
+    device = "Not implemented yet";
+    set_text(dialog, IDC_EDIT_DEVICE, device);
+    device = NULL;
+
+    selection = IDC_RADIO_ASSIGN;
+    if ((type == DRIVE_CDROM) || (type == DRIVE_REMOVABLE))
+    {
+        if (device)
+        {
+            selection = IDC_RADIO_AUTODETECT;
+            enable_labelserial_box(dialog, BOX_MODE_CD_AUTODETECT);
+        }
+        else
+        {
+            selection = IDC_RADIO_ASSIGN;
+            enable_labelserial_box(dialog, BOX_MODE_CD_ASSIGN);
+        }
+    }
+    else
+    {
+        enable_labelserial_box(dialog, BOX_MODE_NORMAL);
+        selection = IDC_RADIO_ASSIGN;
+    }
+
+    CheckRadioButton(dialog, IDC_RADIO_AUTODETECT, IDC_RADIO_ASSIGN, selection);
+
+    updating_ui = FALSE;
+
+    return;
+}
+
+void on_edit_changed(HWND dialog, WORD id)
+{
+    if (updating_ui) return;
+
+    WINE_TRACE("edit id %d changed\n", id);
+
+    /* using fill_drives_list here is pretty lazy, but i'm tired
+
+       fortunately there are only 26 letters in the alphabet, so
+       we don't have to worry about efficiency too much here :)  */
+
+    switch (id)
+    {
+        case IDC_EDIT_LABEL:
+        {
+            char *label;
+
+            label = get_text(dialog, id);
+            if (current_drive->label) HeapFree(GetProcessHeap(), 0, current_drive->label);
+            current_drive->label = label ? label :  strdupA("");
+
+            WINE_TRACE("set label to %s\n", current_drive->label);
+
+            fill_drives_list(dialog);
+            break;
+        }
+
+        case IDC_EDIT_PATH:
+        {
+            char *path;
+
+            path = get_text(dialog, id);
+            if (current_drive->unixpath) HeapFree(GetProcessHeap(), 0, current_drive->unixpath);
+            current_drive->unixpath = path ? path : strdupA("drive_c");
+
+            WINE_TRACE("set path to %s\n", current_drive->unixpath);
+
+            fill_drives_list(dialog);
+            break;
+        }
+
+        case IDC_EDIT_SERIAL:
+        {
+            char *serial;
+
+            serial = get_text(dialog, id);
+            if (current_drive->serial) HeapFree(GetProcessHeap(), 0, current_drive->serial);
+            current_drive->serial = serial ? serial : strdupA("");
+
+            WINE_TRACE("set serial to %s", current_drive->serial);
+
+            break;
+        }
+
+        case IDC_EDIT_DEVICE:
+        {
+            char *device = get_text(dialog, id);
+            /* TODO: handle device if/when it makes sense to do so.... */
+            if (device) HeapFree(GetProcessHeap(), 0, device);
+            fill_drives_list(dialog);
+            break;
+        }
+    }
+}
+
+static void get_etched_rect(HWND dialog, RECT *rect)
+{
+    GetClientRect(dialog, rect);
+
+    /* these dimensions from the labelserial static in En.rc  */
+    rect->top = 258;
+    rect->bottom = 258;
+    rect->left += 35;
+    rect->right -= 25;
+}
+
+/* this just draws a nice line to separate the advanced gui from the n00b gui :) */
+static void paint(HWND dialog)
+{
+    PAINTSTRUCT ps;
+
+    BeginPaint(dialog, &ps);
+
+    if (advanced)
+    {
+        RECT rect;
+
+        get_etched_rect(dialog, &rect);
+
+        DrawEdge(ps.hdc, &rect, EDGE_ETCHED, BF_TOP);
+    }
+
+    EndPaint(dialog, &ps);
+}
+
+INT_PTR CALLBACK
+DriveDlgProc (HWND dialog, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    int item;
+    struct drive *drive;
+
+    switch (msg)
+    {
+        case WM_INITDIALOG:
+            load_drives();
+
+            if (!drives[2].in_use)
+                MessageBox(dialog, "You don't have a drive C. This is not so great.\n\nRemember to click 'Add' in the Drives tab to create one!\n", "", MB_OK | MB_ICONEXCLAMATION);
+
+            fill_drives_list(dialog);
+            update_controls(dialog);
+            /* put in non-advanced mode by default  */
+            set_advanced(dialog);
+            break;
+
+        case WM_SHOWWINDOW:
+            set_window_title(dialog);
+            break;
+
+        case WM_PAINT:
+            paint(dialog);
+            break;
+
+        case WM_COMMAND:
+            if (HIWORD(wParam) == EN_CHANGE)
+            {
+                on_edit_changed(dialog, LOWORD(wParam));
+                break;
+            }
+
+            switch (LOWORD(wParam))
+            {
+                case IDC_LIST_DRIVES:
+                    if (HIWORD(wParam) == LBN_SELCHANGE)
+                        update_controls(dialog);
+
+                    break;
+
+                case IDC_BUTTON_ADD:
+                    if (HIWORD(wParam) != BN_CLICKED) break;
+                    on_add_click(dialog);
+                    break;
+
+                case IDC_BUTTON_REMOVE:
+                    if (HIWORD(wParam) != BN_CLICKED) break;
+                    on_remove_click(dialog);
+                    break;
+
+                case IDC_BUTTON_EDIT:
+                    if (HIWORD(wParam) != BN_CLICKED) break;
+                    item = SendMessage(GetDlgItem(dialog, IDC_LIST_DRIVES),  LB_GETCURSEL, 0, 0);
+                    drive = (struct drive *) SendMessage(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_GETITEMDATA, item, 0);
+                    //DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DRIVE_EDIT), NULL, (DLGPROC) DriveEditDlgProc, (LPARAM) drive);
+                    break;
+
+                case IDC_BUTTON_AUTODETECT:
+                    autodetect_drives();
+                    fill_drives_list(dialog);
+                    break;
+
+                case IDC_BUTTON_SHOW_HIDE_ADVANCED:
+                    advanced = !advanced;
+                    set_advanced(dialog);
+                    break;
+
+                case IDC_BUTTON_BROWSE_PATH:
+                    MessageBox(dialog, "", "Write me!", MB_OK);
+                    break;
+
+                case IDC_RADIO_ASSIGN:
+                {
+                    char *str;
+
+                    str = get_text(dialog, IDC_EDIT_LABEL);
+                    if (current_drive->label) HeapFree(GetProcessHeap(), 0, current_drive->label);
+                    current_drive->label = str ? str : strdupA("");
+
+                    str = get_text(dialog, IDC_EDIT_SERIAL);
+                    if (current_drive->serial) HeapFree(GetProcessHeap(), 0, current_drive->serial);
+                    current_drive->serial = str ? str : strdupA("");
+
+                    /* TODO: we don't have a device at this point */
+
+                    enable_labelserial_box(dialog, BOX_MODE_CD_ASSIGN);
+
+                    break;
+                }
+
+
+                case IDC_COMBO_TYPE:
+                {
+                    int mode = BOX_MODE_NORMAL;
+                    int selection;
+
+                    if (HIWORD(wParam) != CBN_SELCHANGE) break;
+
+                    selection = SendDlgItemMessage(dialog, IDC_COMBO_TYPE, CB_GETCURSEL, 0, 0);
+
+                    if (selection == 2 || selection == 3) /* cdrom or floppy */
+                    {
+                        if (IsDlgButtonChecked(dialog, IDC_RADIO_AUTODETECT))
+                            mode = BOX_MODE_CD_AUTODETECT;
+                        else
+                            mode = BOX_MODE_CD_ASSIGN;
+                    }
+
+                    enable_labelserial_box(dialog, mode);
+
+                    current_drive->type = type_pairs[selection].sCode;
+                    break;
+                }
+
+            }
+            break;
+
+        case WM_NOTIFY:
+            switch (((LPNMHDR)lParam)->code)
+            {
+                case PSN_KILLACTIVE:
+                    WINE_TRACE("PSN_KILLACTIVE\n");
+                    SetWindowLong(dialog, DWL_MSGRESULT, FALSE);
+                    break;
+                case PSN_APPLY:
+                    apply_drive_changes();
+                    SetWindowLong(dialog, DWL_MSGRESULT, PSNRET_NOERROR);
+                    break;
+                case PSN_SETACTIVE:
+                    break;
+            }
+            break;
+    }
+
+    return FALSE;
+}
+
--- /dev/null	2004-02-23 21:02:56.000000000 +0000
+++ programs/winecfg/drivedetect.c	2004-11-05 20:55:37.000000000 +0000
@@ -0,0 +1,252 @@
+/*
+ * Drive autodetection code
+ *
+ * Copyright 2004 Mike Hearn <mike at navi.cx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <wine/debug.h>
+#include <wine/library.h>
+
+#include "winecfg.h"
+
+#include <stdio.h>
+#include <mntent.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#include <winbase.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
+
+BOOL gui_mode = TRUE;
+static long working_mask = 0;
+
+static char *ignored_fstypes[] = {
+    "devpts",
+    "tmpfs",
+    "proc",
+    "sysfs",
+    "swap",
+    "usbdevfs",
+    "rpc_pipefs",
+    NULL
+};
+
+static BOOL should_ignore_fstype(char *type)
+{
+    char **s;
+    
+    for (s = ignored_fstypes; *s; s++)
+        if (!strcmp(*s, type)) return TRUE;
+
+    return FALSE;
+}
+
+static BOOL is_drive_defined(char *path)
+{
+    int i;
+    
+    for (i = 0; i < 26; i++)
+        if (drives[i].in_use && !strcmp(drives[i].unixpath, path)) return TRUE;
+
+    return FALSE;
+}
+
+/* returns Z + 1 if there are no more available letters */
+static char allocate_letter()
+{
+    char letter;
+
+    for (letter = 'C'; letter <= 'Z'; letter++)
+        if ((DRIVE_MASK_BIT(letter) & working_mask) != 0) break;
+
+    return letter;
+}
+
+#define FSTAB_OPEN 1
+#define NO_MORE_LETTERS 2
+#define NO_ROOT 3
+#define NO_DRIVE_C 4
+
+static void report_error(int code)
+{
+    char *buffer;
+    int len;
+    
+    switch (code)
+    {
+        case FSTAB_OPEN:
+            if (gui_mode)
+            {
+                static const char *s = "Could not open your mountpoint description table.\n\nOpening of /etc/fstab failed: %s";
+                len = snprintf(NULL, 0, s, strerror(errno));
+                buffer = HeapAlloc(GetProcessHeap(), 0, len + 1);
+                snprintf(buffer, len, s, strerror(errno));
+                MessageBox(NULL, s, "", MB_OK | MB_ICONEXCLAMATION);
+                HeapFree(GetProcessHeap(), 0, buffer);
+            }
+            else
+            {
+                fprintf(stderr, "winecfg: could not open fstab: %s", strerror(errno));
+            }
+            break;
+
+        case NO_MORE_LETTERS:
+            if (gui_mode) MessageBox(NULL, "No more letters are available to auto-detect available drives with.", "", MB_OK | MB_ICONEXCLAMATION);
+            fprintf(stderr, "winecfg: no more available letters while scanning /etc/fstab");
+            break;
+
+        case NO_ROOT:
+            if (gui_mode) MessageBox(NULL, "Could not ensure that the root directory was mapped.\n\n"
+                                     "This can happen if you run out of drive letters. "
+                                     "It's important to have the root directory mapped, otherwise Wine"
+                                     "will not be able to always find the programs you want to run. "
+                                     "Try unmapping a drive letter then trying again.", "",
+                                     MB_OK | MB_ICONEXCLAMATION);
+            else fprintf(stderr, "winecfg: unable to map root drive\n");
+            break;
+
+        case NO_DRIVE_C:
+            if (gui_mode)
+                MessageBox(NULL, "No virtual drive C mapped\n\nTry running wineprefixcreate", "", MB_OK | MB_ICONEXCLAMATION);
+            else
+                fprintf(stderr, "winecfg: no drive_c directory\n");
+    }
+    
+}
+
+static void ensure_root_is_mapped()
+{
+    int i;
+    BOOL mapped = FALSE;
+
+    for (i = 0; i < 26; i++)
+        if (drives[i].in_use && !strcmp(drives[i].unixpath, "/")) mapped = TRUE;
+
+    if (!mapped)
+    {
+        /* work backwards from Z, trying to map it */
+        char letter;
+
+        for (letter = 'Z'; letter >= 'A'; letter--)
+        {
+            if (drives[letter - 'A'].in_use) continue;
+            add_drive(letter, "/", "System", 0, DRIVE_FIXED);
+            WINE_TRACE("allocated drive %c as the root drive\n", letter);
+        }
+
+        if (letter == ('A' - 1)) report_error(NO_ROOT);
+    }
+}
+
+static void ensure_drive_c_is_mapped()
+{
+    struct stat buf;
+    char *configdir = wine_get_config_dir();
+    int len;
+    char *drive_c_dir;
+    
+    if (drives[2].in_use) return;
+
+    len = snprintf(NULL, 0, "%s/../drive_c", configdir);
+    drive_c_dir = HeapAlloc(GetProcessHeap(), 0, len);
+    snprintf(drive_c_dir, len, "%s/../drive_c", configdir);
+    HeapFree(GetProcessHeap(), 0, drive_c_dir);
+
+    if (stat(drive_c_dir, &buf) == 0)
+    {
+        add_drive('C', "../drive_c", "Virtual Windows Drive", "0", DRIVE_FIXED);
+    }
+    else
+    {
+        report_error(NO_DRIVE_C);
+    }
+}
+
+int autodetect_drives()
+{
+    struct mntent *ent;
+    FILE *fstab;
+
+    /* we want to build a list of autodetected drives, then ensure each entry
+       exists in the users setup. so, we superimpose the autodetected drives
+       onto whatever is pre-existing.
+
+       for now let's just rummage around inside the fstab.
+     */
+
+    load_drives();
+
+    working_mask = drive_available_mask('\0');
+
+    fstab = fopen("/etc/fstab", "r");
+    if (!fstab)
+    {
+        report_error(FSTAB_OPEN);
+        return FALSE;
+    }
+
+    while ((ent = getmntent(fstab)))
+    {
+        char letter;
+        char label[256];
+        int type;
+        
+        WINE_TRACE("ent->mnt_dir=%s\n", ent->mnt_dir);
+
+        if (should_ignore_fstype(ent->mnt_type)) continue;
+        if (is_drive_defined(ent->mnt_dir)) continue;
+
+        /* allocate a drive for it */
+        letter = allocate_letter();
+        if (letter == ']')
+        {
+            report_error(NO_MORE_LETTERS);
+            fclose(fstab);
+            return FALSE;
+        }
+            
+        WINE_TRACE("adding drive %c for %s, type %s\n", letter, ent->mnt_dir, ent->mnt_type);
+        
+        strncpy(label, "Drive X", 8);
+        label[6] = letter;
+
+        if (!strcmp(ent->mnt_type, "nfs")) type = DRIVE_REMOTE;
+        else if (!strcmp(ent->mnt_type, "nfs4")) type = DRIVE_REMOTE;
+        else if (!strcmp(ent->mnt_type, "smbfs")) type = DRIVE_REMOTE;
+        else if (!strcmp(ent->mnt_type, "cifs")) type = DRIVE_REMOTE;
+        else if (!strcmp(ent->mnt_type, "coda")) type = DRIVE_REMOTE;
+        else if (!strcmp(ent->mnt_type, "iso9660")) type = DRIVE_CDROM;
+        else if (!strcmp(ent->mnt_type, "ramfs")) type = DRIVE_RAMDISK;
+        else type = DRIVE_FIXED;
+        
+        add_drive(letter, ent->mnt_dir, label, "0", type);
+        
+        working_mask |= DRIVE_MASK_BIT(letter);
+    }
+
+    fclose(fstab);
+
+    ensure_root_is_mapped();
+
+    ensure_drive_c_is_mapped();
+
+    return TRUE;
+}


More information about the wine-patches mailing list