Alexander Nicolaysen Sørnes : regedit: Add support for importing Unicode files.

Alexandre Julliard julliard at winehq.org
Thu Jul 10 14:07:24 CDT 2008


Module: wine
Branch: master
Commit: 6f2e3e1b1ecce90f98d6e84170a3185a28661d1d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6f2e3e1b1ecce90f98d6e84170a3185a28661d1d

Author: Alexander Nicolaysen Sørnes <alex at thehandofagony.com>
Date:   Wed Jul  9 23:39:08 2008 +0200

regedit: Add support for importing Unicode files.

---

 programs/regedit/framewnd.c |   12 +++-
 programs/regedit/regedit.c  |    2 +-
 programs/regedit/regproc.c  |  164 ++++++++++++++++++++++++++++++++++--------
 programs/regedit/regproc.h  |    3 +-
 4 files changed, 145 insertions(+), 36 deletions(-)

diff --git a/programs/regedit/framewnd.c b/programs/regedit/framewnd.c
index fd20a62..4bf78af 100644
--- a/programs/regedit/framewnd.c
+++ b/programs/regedit/framewnd.c
@@ -311,6 +311,16 @@ static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME *pofn)
     return TRUE;
 }
 
+static BOOL import_registry_filename(LPTSTR filename)
+{
+    FILE* reg_file = fopen(filename, "r");
+
+    if(!reg_file)
+        return FALSE;
+
+    return import_registry_file(reg_file);
+}
+
 static BOOL ImportRegistryFile(HWND hWnd)
 {
     OPENFILENAME ofn;
@@ -320,7 +330,7 @@ static BOOL ImportRegistryFile(HWND hWnd)
     LoadString(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
     ofn.lpstrTitle = title;
     if (GetOpenFileName(&ofn)) {
-        if (!import_registry_file(ofn.lpstrFile)) {
+        if (!import_registry_filename(ofn.lpstrFile)) {
             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
             return FALSE;
         }
diff --git a/programs/regedit/regedit.c b/programs/regedit/regedit.c
index 8c473e6..8e7136b 100644
--- a/programs/regedit/regedit.c
+++ b/programs/regedit/regedit.c
@@ -167,7 +167,7 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
                         exit(1);
                     }
                 }
-                processRegLines(reg_file);
+                import_registry_file(reg_file);
                 if (realname)
                 {
                     HeapFree(GetProcessHeap(),0,realname);
diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index a42ee5c..2f8b826 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -594,11 +594,10 @@ static void processRegEntry(WCHAR* stdInput)
  * Parameters:
  *   in - input stream to read from
  */
-void processRegLines(FILE *in)
+void processRegLinesA(FILE *in)
 {
     LPSTR line           = NULL;  /* line read from input stream */
     ULONG lineSize       = REG_VAL_BUF_SIZE;
-    BOOL  unicode_check  = TRUE;
 
     line = HeapAlloc(GetProcessHeap(), 0, lineSize);
     CHECK_ENOUGH_MEMORY(line);
@@ -636,31 +635,7 @@ void processRegLines(FILE *in)
              */
             size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining);
 
-            if (unicode_check)
-            {
-                if (fread( s, 2, 1, in) == 1)
-                {
-                    if ((BYTE)s[0] == 0xff && (BYTE)s[1] == 0xfe)
-                    {
-                        printf("Trying to import from a unicode file: this isn't supported yet.\n"
-                               "Please use export as Win 9x/NT4 files from native regedit\n");
-                        HeapFree(GetProcessHeap(), 0, line);
-                        return;
-                    }
-                    else
-                    {
-                        unicode_check = FALSE;
-                        check = fgets (&s[2], size_to_get-2, in);
-                    }
-                }
-                else
-                {
-                    unicode_check = FALSE;
-                    check = NULL;
-                }
-            }
-            else
-                check = fgets (s, size_to_get, in);
+            check = fgets (s, size_to_get, in);
 
             if (check == NULL) {
                 if (ferror(in)) {
@@ -725,6 +700,119 @@ void processRegLines(FILE *in)
     HeapFree(GetProcessHeap(), 0, line);
 }
 
+void processRegLinesW(FILE *in)
+{
+    WCHAR* buf           = NULL;  /* line read from input stream */
+    ULONG lineSize       = REG_VAL_BUF_SIZE;
+    size_t check = -1;
+
+    WCHAR* s; /* The pointer into line for where the current fgets should read */
+    int i;
+
+    buf = HeapAlloc(GetProcessHeap(), 0, lineSize * sizeof(WCHAR));
+    CHECK_ENOUGH_MEMORY(buf);
+
+    s = buf;
+
+    while(!feof(in)) {
+        size_t size_remaining;
+        int size_to_get;
+        WCHAR *s_eol = NULL; /* various local uses */
+
+        /* Do we need to expand the buffer ? */
+        assert (s >= buf && s <= buf + lineSize);
+        size_remaining = lineSize - (s-buf);
+        if (size_remaining < 2) /* room for 1 character and the \0 */
+        {
+            WCHAR *new_buffer;
+            size_t new_size = lineSize + (REG_VAL_BUF_SIZE / sizeof(WCHAR));
+            if (new_size > lineSize) /* no arithmetic overflow */
+                new_buffer = HeapReAlloc (GetProcessHeap(), 0, buf, new_size * sizeof(WCHAR));
+            else
+                new_buffer = NULL;
+            CHECK_ENOUGH_MEMORY(new_buffer);
+            buf = new_buffer;
+            s = buf + lineSize - size_remaining;
+            lineSize = new_size;
+            size_remaining = lineSize - (s-buf);
+        }
+
+        /* Get as much as possible into the buffer, terminated either by
+        * eof, error, eol or getting the maximum amount.  Abort on error.
+        */
+        size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining);
+
+        check = fread(s, sizeof(WCHAR), size_to_get, in);
+
+        if (check == 0) {
+            if (ferror(in)) {
+                perror ("While reading input");
+                exit (IO_ERROR);
+            } else {
+                assert (feof(in));
+                *s = '\0';
+                /* It is not clear to me from the definition that the
+                * contents of the buffer are well defined on detecting
+                * an eof without managing to read anything.
+                */
+            }
+        }
+
+        /* If we didn't read the eol nor the eof go around for the rest */
+        while(1)
+        {
+            for(i = 0; s[i] != 0; i++)
+            {
+                if(s[i] == '\n')
+                {
+                    s_eol = &s[i];
+                    break;
+                }
+            }
+
+            /* If it is a comment line then discard it and go around again */
+            if (buf[0] == '#') {
+                s = buf;
+                continue;
+            }
+
+            /* Remove any line feed.  Leave s_eol on the \0 */
+            if (s_eol) {
+                *s_eol = '\0';
+                if (s_eol > buf && *(s_eol-1) == '\r')
+                    *(s_eol-1) = '\0';
+            }
+
+            /* If there is a concatenating \\ then go around again */
+            if (s_eol > buf && *(s_eol-1) == '\\') {
+                WCHAR c[2];
+                s = s_eol+1;
+                /* The following error protection could be made more self-
+                * correcting but I thought it not worth trying.
+                */
+                if(!fread(&c, sizeof(WCHAR), 2, in))
+                    break;
+                if (feof(in) || c[0] != ' ' || c[1] != ' ')
+                    fprintf(stderr,"%s: ERROR - invalid continuation.\n",
+                            getAppName());
+                continue;
+            }
+
+            if(!s_eol)
+                break;
+
+            processRegEntry(s);
+            s = s_eol + 1;
+            s_eol = 0;
+            continue; /* That is the full virtual line */
+        }
+    }
+
+    processRegEntry(NULL);
+
+    HeapFree(GetProcessHeap(), 0, buf);
+}
+
 /****************************************************************************
  * REGPROC_print_error
  *
@@ -1080,12 +1168,24 @@ BOOL export_registry_key(CHAR *file_name, CHAR *reg_key_name)
 /******************************************************************************
  * Reads contents of the specified file into the registry.
  */
-BOOL import_registry_file(LPTSTR filename)
+BOOL import_registry_file(FILE* reg_file)
 {
-    FILE* reg_file = fopen(filename, "r");
-
-    if (reg_file) {
-        processRegLines(reg_file);
+    if (reg_file)
+    {
+        BYTE s[2];
+        if (fread( s, 2, 1, reg_file) == 1)
+        {
+            if (s[0] == 0xff && s[1] == 0xfe)
+            {
+                printf("Trying to open unicode file\n");
+                processRegLinesW(reg_file);
+            } else
+            {
+                printf("ansi file\n");
+                rewind(reg_file);
+                processRegLinesA(reg_file);
+            }
+        }
         return TRUE;
     }
     return FALSE;
diff --git a/programs/regedit/regproc.h b/programs/regedit/regproc.h
index d1725b1..0621d8b 100644
--- a/programs/regedit/regproc.h
+++ b/programs/regedit/regproc.h
@@ -22,7 +22,6 @@
 const CHAR *getAppName(void);
 
 BOOL export_registry_key(CHAR *file_name, CHAR *reg_key_name);
-BOOL import_registry_file(LPTSTR filename);
+BOOL import_registry_file(FILE *in);
 void delete_registry_key(WCHAR *reg_key_name);
 WCHAR* GetWideString(const char* strA);
-void processRegLines(FILE *in);




More information about the wine-cvs mailing list