From 6f2e3e1b1ecce90f98d6e84170a3185a28661d1d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alexander=20Nicolaysen=20S=C3=B8rnes?= Date: Wed, 9 Jul 2008 23:39:08 +0200 Subject: [PATCH] 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 fd20a623c1f..4bf78af348a 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 8c473e690b1..8e7136b66aa 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 a42ee5c4fde..2f8b82632e9 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 d1725b125e4..0621d8b62e8 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); -- 2.11.4.GIT