? patch-multistringvalue-1.1.diff
? programs/regedit_copy
? programs/regedit/patch-multistringvalue.diff
Index: programs/regedit/En.rc
===================================================================
RCS file: /home/wine/wine/programs/regedit/En.rc,v
retrieving revision 1.21
diff -u -p -r1.21 En.rc
--- programs/regedit/En.rc	26 Oct 2005 12:07:55 -0000	1.21
+++ programs/regedit/En.rc	26 Apr 2006 03:32:53 -0000
@@ -53,6 +53,7 @@ BEGIN
             MENUITEM "&String Value",               ID_EDIT_NEW_STRINGVALUE
             MENUITEM "&Binary Value",               ID_EDIT_NEW_BINARYVALUE
             MENUITEM "&DWORD Value",                ID_EDIT_NEW_DWORDVALUE
+            MENUITEM "&Multi-String Value",         ID_EDIT_NEW_MULTISTRINGVALUE
         END
         MENUITEM SEPARATOR
         MENUITEM "&Delete\tDel",                ID_EDIT_DELETE
@@ -129,6 +130,7 @@ BEGIN
             MENUITEM "&String Value",               ID_EDIT_NEW_STRINGVALUE
             MENUITEM "&Binary Value",               ID_EDIT_NEW_BINARYVALUE
             MENUITEM "&DWORD Value",                ID_EDIT_NEW_DWORDVALUE
+            MENUITEM "&Multi-String Value",         ID_EDIT_NEW_MULTISTRINGVALUE
         END
         MENUITEM SEPARATOR
         MENUITEM "&Delete\tDel",                ID_EDIT_DELETE
@@ -179,6 +181,7 @@ BEGIN
             MENUITEM "&String Value",               ID_EDIT_NEW_STRINGVALUE
             MENUITEM "&Binary Value",               ID_EDIT_NEW_BINARYVALUE
             MENUITEM "&DWORD Value",                ID_EDIT_NEW_DWORDVALUE
+            MENUITEM "&Multi-String Value",         ID_EDIT_NEW_MULTISTRINGVALUE
         END
         MENUITEM SEPARATOR
         MENUITEM "&Delete\tDel",                ID_EDIT_DELETE
@@ -258,6 +261,19 @@ BEGIN
     PUSHBUTTON   "Cancel",IDCANCEL,175,60,30,11,WS_GROUP
 END
 
+IDD_EDIT_MULTISTRING DIALOG DISCARDABLE  22, 17, 210, 209
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Edit String"
+FONT 8, "MS Shell Dlg"
+BEGIN
+LTEXT           "Value name:",IDC_STATIC,5,5,119,8
+EDITTEXT        IDC_VALUE_NAME,5,15,200,12, WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL| WS_DISABLED
+LTEXT           "Value data:",IDC_STATIC,5,30,119,8
+EDITTEXT        IDC_VALUE_DATA,5,40,200,144, WS_BORDER | WS_TABSTOP | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE|ES_WANTRETURN
+DEFPUSHBUTTON   "OK",IDOK,140,192,30,11,WS_GROUP
+PUSHBUTTON   "Cancel",IDCANCEL,175,192,30,11,WS_GROUP
+END
+
 IDD_EDIT_DWORD DIALOG DISCARDABLE  22, 17, 210, 100
 STYLE DS_MODALFRAME | DS_NOIDLEMSG | WS_CAPTION | WS_SYSMENU
 CAPTION "Edit DWORD"
@@ -317,11 +333,12 @@ END
 
 STRINGTABLE DISCARDABLE
 BEGIN
-    ID_EDIT_MODIFY          "Modifies the value's data"
-    ID_EDIT_NEW_KEY         "Adds a new key"
-    ID_EDIT_NEW_STRINGVALUE "Adds a new string value"
-    ID_EDIT_NEW_BINARYVALUE "Adds a new binary value"
-    ID_EDIT_NEW_DWORDVALUE  "Adds a new double word value"
+    ID_EDIT_MODIFY               "Modifies the value's data"
+    ID_EDIT_NEW_KEY              "Adds a new key"
+    ID_EDIT_NEW_STRINGVALUE      "Adds a new string value"
+    ID_EDIT_NEW_BINARYVALUE      "Adds a new binary value"
+    ID_EDIT_NEW_DWORDVALUE       "Adds a new double word value"
+    ID_EDIT_NEW_MULTISTRINGVALUE "Adds a new multi-string value"
     ID_REGISTRY_IMPORTREGISTRYFILE "Imports a text file into the registry"
     ID_REGISTRY_EXPORTREGISTRYFILE
                             "Exports all or part of the registry to a text file"
Index: programs/regedit/edit.c
===================================================================
RCS file: /home/wine/wine/programs/regedit/edit.c,v
retrieving revision 1.20
diff -u -p -r1.20 edit.c
--- programs/regedit/edit.c	26 Oct 2005 12:07:55 -0000	1.20
+++ programs/regedit/edit.c	26 Apr 2006 03:32:53 -0000
@@ -242,6 +242,107 @@ done:
     return NULL;
 }
 
+/* This functions interpret a REG_MULTI_SZ element data to make it accessible within the GUI.
+   REG_MULTI_SZ is stored as a serie of NULL terminated strings, each of those strings
+   representing a single line. The list is terminated by an additionnal NULL character.
+   This function replaces the NULL terminators by new lines characters */
+/* Set 'toRegistryFormat' to 'TRUE' to convert from a list with strings separated by new line
+   characters to a list compromised of NULL terminated strings or false for the inverse
+   operation */
+/* 'len' is the length in bytes of the returned string */
+/* The returned string must be freed with HeapFree() once no more required! */
+TCHAR* convert_multistringvalue( BOOL toRegistryFormat, TCHAR* value, LONG *len )
+{
+    int charcount = 0, newlinepos = 0, indexold = 0;
+    int lenchar, lenbytes;
+    BOOL newLine = FALSE; /* This variable is used to ignore empty lines */
+                          /* This is important as we want to avoid storing 
+                             two consequtive NULL characters */
+    int stringsamount = 0, index=0, cindex=0;
+    SIZE_T newstringsize;
+    TCHAR *newString;
+    *len = 0;
+    if(toRegistryFormat == FALSE) {
+        for(;stringValueData[cindex]!=0; cindex++) {
+            for(;stringValueData[cindex]!=0; cindex++) {}
+            stringsamount++;
+        }
+        if(stringsamount == 0) { /* Empty string list.. return a zero length string */
+            if( !(newString = HeapAlloc(GetProcessHeap(), 0, (sizeof(TCHAR)))) )
+                return NULL;
+            newString[0] = 0;
+            *len = sizeof(TCHAR);
+            return newString;
+        }
+
+        /* We found out the amount of strings in the list. Allocate enough memory for the
+           new list of strings separated by new lines. */
+        newstringsize = (cindex + (stringsamount-1))*(sizeof(TCHAR));
+        if( !(newString = HeapAlloc(GetProcessHeap(), 0, newstringsize)) )
+            return NULL;
+        /* Loop and copy each string from the original list in the new list and append CR LF */
+        for(;stringValueData[index]!=0; index++) {
+            for(;stringValueData[index]!=0; index++) {}
+            memcpy((LPBYTE)(newString+charcount), (LPBYTE)(stringValueData+indexold),
+                   (index-indexold)*sizeof(TCHAR));
+            charcount += index-indexold;
+            if(index < cindex-1) {
+                newString[charcount] = '\r';
+                newString[charcount+1] = '\n';
+                charcount += 2;
+                indexold = index+1;
+            }
+            else
+                newString[charcount] = 0;
+        }
+        *len = newstringsize;
+        return newString;
+    }
+    else
+    {
+        /* A REG_MULTI_SZ entry is basically a list of NULL terminated strings */
+        /* Each string represents a single line. The list is terminated by another NULL characters */
+        /* Here we convert all the new line charaters to NULL characters */
+        /* Also we make sure to terminate with two NULL characters */
+        lenchar = (lstrlen(value) + 2); /* Minimum size for the new list of strings */
+        lenbytes = lenchar*sizeof(TCHAR);
+
+        /* Loop and everytime CR LF is found, append the preceding text to the new string */
+        /* Each substring is separated by a NULL characters */
+        if( !(newString = HeapAlloc(GetProcessHeap(), 0, lenbytes)) )
+            return NULL;
+        memset(newString, 0, lenbytes);
+        while(value[index]!=0) {
+            if(value[index] == '\r' && value[index+1] == '\n') {
+                if(newLine) { /* If last iteration was also a new line, this is an empty new line */
+                    newlinepos += 2; /* Skip over the CR and LF characters */
+                    index += 2;
+                }
+                else { /* Copy the string between the last two CR LF */
+                    memcpy((LPBYTE)(newString+charcount),
+                            (LPBYTE)(value+newlinepos), (index-newlinepos)*sizeof(TCHAR));
+                    charcount += (index - newlinepos) + 1;
+
+                    index += 2; /* Move on after the CR and LF characters */
+                    newlinepos = index;
+                    newLine = TRUE;
+                }
+            } else {
+                index++;
+                newLine = FALSE;
+            }
+        }
+
+        /* Append the rest of the string, which is everything that goes after the last CR LF found */
+        memcpy( (LPBYTE)(newString+charcount), (LPBYTE)(value+newlinepos),
+                (lstrlen(value)-newlinepos)*sizeof(TCHAR) );
+        charcount += (lstrlen(value) - newlinepos) + 2;
+
+        *len = charcount*sizeof(TCHAR);
+        return newString;
+    }
+}
+
 BOOL CreateKey(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath, LPTSTR keyName)
 {
     BOOL result = FALSE;
@@ -267,7 +368,7 @@ BOOL CreateKey(HWND hwnd, HKEY hKeyRoot,
 	RegCloseKey(retKey);
     }
     if (lRet == ERROR_SUCCESS) goto done;
-    
+
     lRet = RegCreateKey(hKey, keyName, &retKey);
     if (lRet != ERROR_SUCCESS) {
 	error_code_messagebox(hwnd, lRet);
@@ -287,6 +388,7 @@ BOOL ModifyValue(HWND hwnd, HKEY hKeyRoo
     DWORD type;
     LONG lRet;
     HKEY hKey;
+    TCHAR *newvalue;
     LONG len;
 
     lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
@@ -304,6 +406,20 @@ BOOL ModifyValue(HWND hwnd, HKEY hKeyRoo
             if (lRet == ERROR_SUCCESS) result = TRUE;
             else error_code_messagebox(hwnd, lRet);
         }
+    } else if ( type == REG_MULTI_SZ ) {
+        /* Convert 'stringValueData' to a list of strings separated by new lines */
+        newvalue = convert_multistringvalue(FALSE, stringValueData, &len);
+        HeapFree(GetProcessHeap(), 0, stringValueData);
+        stringValueData = newvalue;
+        if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_MULTISTRING), hwnd, modify_dlgproc) == IDOK) {
+            newvalue = convert_multistringvalue(TRUE, stringValueData, &len);
+            if(len>0) {
+                lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)newvalue, len);
+                if (lRet == ERROR_SUCCESS) result = TRUE;
+                else error_code_messagebox(hwnd, lRet);
+            }
+            HeapFree(GetProcessHeap(), 0, newvalue);
+        }
     } else if ( type == REG_DWORD ) {
 	wsprintf(stringValueData, isDecimal ? "%ld" : "%lx", *((DWORD*)stringValueData));
 	if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dlgproc) == IDOK) {
Index: programs/regedit/framewnd.c
===================================================================
RCS file: /home/wine/wine/programs/regedit/framewnd.c,v
retrieving revision 1.23
diff -u -p -r1.23 framewnd.c
--- programs/regedit/framewnd.c	3 Mar 2006 14:48:10 -0000	1.23
+++ programs/regedit/framewnd.c	26 Apr 2006 03:32:54 -0000
@@ -727,6 +727,9 @@ static BOOL _CmdWndProc(HWND hWnd, UINT 
     case ID_EDIT_NEW_STRINGVALUE:
 	valueType = REG_SZ;
 	goto create_value;
+    case ID_EDIT_NEW_MULTISTRINGVALUE:
+	valueType = REG_MULTI_SZ;
+	goto create_value;
     case ID_EDIT_NEW_BINARYVALUE:
 	valueType = REG_BINARY;
 	goto create_value;
Index: programs/regedit/resource.h
===================================================================
RCS file: /home/wine/wine/programs/regedit/resource.h,v
retrieving revision 1.13
diff -u -p -r1.13 resource.h
--- programs/regedit/resource.h	26 Oct 2005 12:07:55 -0000	1.13
+++ programs/regedit/resource.h	26 Apr 2006 03:32:54 -0000
@@ -64,13 +64,14 @@
 #define ID_EDIT_NEW_STRINGVALUE         32786
 #define ID_EDIT_NEW_BINARYVALUE         32787
 #define ID_EDIT_NEW_DWORDVALUE          32788
-#define ID_REGISTRY_IMPORTREGISTRYFILE  32789
-#define ID_REGISTRY_EXPORTREGISTRYFILE  32790
-#define ID_REGISTRY_CONNECTNETWORKREGISTRY 32791
-#define ID_REGISTRY_DISCONNECTNETWORKREGISTRY 32792
-#define ID_REGISTRY_PRINT               32793
-#define ID_HELP_HELPTOPICS              32794
-#define ID_HELP_ABOUT                   32795
+#define ID_EDIT_NEW_MULTISTRINGVALUE    32789
+#define ID_REGISTRY_IMPORTREGISTRYFILE  32790
+#define ID_REGISTRY_EXPORTREGISTRYFILE  32791
+#define ID_REGISTRY_CONNECTNETWORKREGISTRY 32792
+#define ID_REGISTRY_DISCONNECTNETWORKREGISTRY 32793
+#define ID_REGISTRY_PRINT               32794
+#define ID_HELP_HELPTOPICS              32795
+#define ID_HELP_ABOUT                   32796
 #define ID_WINDOW_CASCADE               32797
 #define ID_WINDOW_TILE                  32798
 #define ID_WINDOW_ARRANGEICONS          32799
@@ -116,6 +117,7 @@
 #define IDS_DELETE_BOX_TEXT		32841
 #define IDS_NOTFOUND    		32842
 #define IDD_EDIT_DWORD			32850
+#define IDD_EDIT_MULTISTRING		32851
 #define IDC_DWORD_BASE			32852
 #define IDC_DWORD_HEX			32853
 #define IDC_DWORD_DEC			32854
