Thanks a lot for the comments guys!
Here's a revised patch.. no more C++ style comments, no more inline
variable declarations and no more useless casting!
I think it should work pretty well.
I'll keep you updated with anything else I try soon as promised!
Philippe
? 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