[PATCH 2/2] regedit: Clean up command-line argument handling

Hugh McMaster hugh.mcmaster at outlook.com
Fri Jun 17 04:06:01 CDT 2016


Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
 programs/regedit/main.c    |   2 +-
 programs/regedit/regedit.c | 307 ++++++++++++++-------------------------------
 2 files changed, 96 insertions(+), 213 deletions(-)

diff --git a/programs/regedit/main.c b/programs/regedit/main.c
index 3f9e432..36f7454 100644
--- a/programs/regedit/main.c
+++ b/programs/regedit/main.c
@@ -139,7 +139,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, WCHAR *lpCmdLi
     MSG msg;
     HACCEL hAccel;
 
-    if (ProcessCmdLine(lpCmdLine)) {
+    if (ProcessCmdLine(GetCommandLineW())) {
         return 0;
     }
 
diff --git a/programs/regedit/regedit.c b/programs/regedit/regedit.c
index 3ce25ce..f2af1c0 100644
--- a/programs/regedit/regedit.c
+++ b/programs/regedit/regedit.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <windows.h>
+#include <shellapi.h>
 #include "wine/unicode.h"
 #include "regproc.h"
 
@@ -57,7 +58,7 @@ static const char *usage =
     "regedit.\n";
 
 typedef enum {
-    ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
+    ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
 } REGEDIT_ACTION;
 
 
@@ -66,154 +67,63 @@ const CHAR *getAppName(void)
     return "regedit";
 }
 
-/******************************************************************************
- * Copies file name from command line string to the buffer.
- * Rewinds the command line string pointer to the next non-space character
- * after the file name.
- * Buffer contains an empty string if no filename was found;
- *
- * params:
- * command_line - command line current position pointer
- *      where *s[0] is the first symbol of the file name.
- * file_name - buffer to write the file name to.
- */
-static void get_file_name(WCHAR **command_line, WCHAR *file_name)
-{
-    WCHAR *s = *command_line;
-    int pos = 0;                /* position of pointer "s" in *command_line */
-    file_name[0] = 0;
-
-    if (!s[0]) {
-        return;
-    }
-
-    if (s[0] == '"') {
-        s++;
-        (*command_line)++;
-        while(s[0] != '"') {
-            if (!s[0]) {
-                fprintf(stderr,"%s: Unexpected end of file name!\n",
-                        getAppName());
-                exit(1);
-            }
-            s++;
-            pos++;
-        }
-    } else {
-        while(s[0] && !isspaceW(s[0])) {
-            s++;
-            pos++;
-        }
-    }
-    memcpy(file_name, *command_line, pos * sizeof((*command_line)[0]));
-    /* Terminate the string and remove the trailing backslash */
-    if (pos > 0 && file_name[pos - 1] == '\\') {
-        file_name[pos - 1] = '\0';
-    } else {
-        file_name[pos] = '\0';
-    }
-
-    if (s[0]) {
-        s++;
-        pos++;
-    }
-    while(s[0] && isspaceW(s[0])) {
-        s++;
-        pos++;
-    }
-    (*command_line) += pos;
-}
-
-static BOOL PerformRegAction(REGEDIT_ACTION action, WCHAR *s)
+static BOOL PerformRegAction(REGEDIT_ACTION action, WCHAR **argv, int *i)
 {
     switch (action) {
     case ACTION_ADD: {
-            WCHAR filename[MAX_PATH];
-            FILE *reg_file;
+            WCHAR *filename = argv[*i];
             WCHAR hyphenW[] = {'-',0};
+            WCHAR *realname = NULL;
+            FILE *reg_file;
 
-            get_file_name(&s, filename);
-            if (!filename[0]) {
-                fprintf(stderr,"%s: No file name was specified\n", getAppName());
-                fprintf(stderr,usage);
-                exit(1);
+            if (!strcmpW(filename, hyphenW))
+            {
+                reg_file = stdin;
             }
+            else
+            {
+                int size;
+                WCHAR rb_modeW[] = {'r','b',0};
 
-            while(filename[0]) {
-                WCHAR *realname = NULL;
-
-                if (!strcmpW(filename, hyphenW))
+                size = SearchPathW(NULL, filename, NULL, 0, NULL, NULL);
+                if (size > 0)
                 {
-                    reg_file = stdin;
+                    realname = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+                    size = SearchPathW(NULL, filename, NULL, size, realname, NULL);
                 }
-                else
+                if (size == 0)
                 {
-                    int size;
-                    WCHAR rb_modeW[] = {'r','b',0};
-
-                    size = SearchPathW(NULL, filename, NULL, 0, NULL, NULL);
-                    if (size > 0)
-                    {
-                        realname = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
-                        size = SearchPathW(NULL, filename, NULL, size, realname, NULL);
-                    }
-                    if (size == 0)
-                    {
-                        fprintf(stderr, "%s: File not found \"%ls\" (%d)\n",
-                                getAppName(), filename, GetLastError());
-                        exit(1);
-                    }
-                    reg_file = _wfopen(realname, rb_modeW);
-                    if (reg_file == NULL)
-                    {
-                        perror("");
-                        fprintf(stderr, "%s: Can't open file \"%ls\"\n", getAppName(), filename);
-                        exit(1);
-                    }
+                    fprintf(stderr, "regedit: File not found \"%ls\" (%d)\n",
+                            filename, GetLastError());
+                    exit(1);
                 }
-                import_registry_file(reg_file);
-                if (realname)
+                reg_file = _wfopen(realname, rb_modeW);
+                if (reg_file == NULL)
                 {
-                    HeapFree(GetProcessHeap(),0,realname);
-                    fclose(reg_file);
+                    perror("");
+                    fprintf(stderr, "regedit: Can't open file \"%ls\"\n", filename);
+                    exit(1);
                 }
-                get_file_name(&s, filename);
             }
-            break;
-        }
-    case ACTION_DELETE: {
-            WCHAR reg_key_name[KEY_MAX_LEN];
-
-            get_file_name(&s, reg_key_name);
-            if (!reg_key_name[0]) {
-                fprintf(stderr,"%s: No registry key was specified for removal\n",
-                        getAppName());
-                fprintf(stderr,usage);
-                exit(1);
-            } else {
-                delete_registry_key(reg_key_name);
+            import_registry_file(reg_file);
+            if (realname)
+            {
+                fclose(reg_file);
+                HeapFree(GetProcessHeap(),0,realname);
             }
             break;
         }
+    case ACTION_DELETE:
+            delete_registry_key(argv[*i]);
+            break;
     case ACTION_EXPORT: {
-            WCHAR filename[MAX_PATH];
-
-            filename[0] = '\0';
-            get_file_name(&s, filename);
-            if (!filename[0]) {
-                fprintf(stderr,"%s: No file name was specified\n", getAppName());
-                fprintf(stderr,usage);
-                exit(1);
-            }
+            WCHAR *filename = argv[*i];
+            WCHAR *reg_key_name = argv[++(*i)];
 
-            if (s[0]) {
-                WCHAR reg_key_name[KEY_MAX_LEN];
-
-                get_file_name(&s, reg_key_name);
+            if (reg_key_name)
                 export_registry_key(filename, reg_key_name, REG_FORMAT_4);
-            } else {
+            else
                 export_registry_key(filename, NULL, REG_FORMAT_4);
-            }
             break;
         }
     default:
@@ -224,99 +134,72 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, WCHAR *s)
     return TRUE;
 }
 
-/**
- * Process unknown switch.
- *
- * Params:
- *   chu - the switch character in upper-case.
- *   s - the command line string where s points to the switch character.
- */
-static void error_unknown_switch(WCHAR chu, WCHAR *s)
-{
-    if (isalphaW(chu)) {
-        fprintf(stderr,"%s: Undefined switch /%lc!\n", getAppName(), chu);
-    } else {
-        fprintf(stderr,"%s: Alphabetic character is expected after '%lc' "
-                "in switch specification\n", getAppName(), *(s - 1));
-    }
-    exit(1);
-}
-
 BOOL ProcessCmdLine(WCHAR *lpCmdLine)
 {
-    REGEDIT_ACTION action = ACTION_UNDEF;
-    WCHAR *s = lpCmdLine; /* command line pointer */
-    WCHAR ch = *s;        /* current character */
+    WCHAR **argv;
+    int argc, i;
+    REGEDIT_ACTION action = ACTION_ADD;
+
+    argv = CommandLineToArgvW(lpCmdLine, &argc);
+
+    if (argc == 1)
+        return FALSE;
+
+    for (i = 1; i < argc; i++)
+    {
+        if (argv[i][0] != '/' && argv[i][0] != '-')
+            break; /* No flags specified. */
 
-    while (ch && ((ch == '-') || (ch == '/'))) {
-        WCHAR chu;
-        WCHAR ch2;
+        if (!argv[i][1] && argv[i][0] == '-')
+            break; /* '-' is a filename. It indicates we should use stdin. */
 
-        s++;
-        ch = *s;
-        if (!ch || isspaceW(ch))
+        if (argv[i][2] && argv[i][2] != ':')
+            break; /* This is a file path beginning with '/'. */
+
+        switch (toupperW(argv[i][1]))
         {
-            /* '-' is a file name. It indicates we should use stdin */
-            s--;
+        case '?':
+            fprintf(stderr, usage);
+            exit(0);
             break;
-        }
-        ch2 = *(s+1);
-        chu = toupperW(ch);
-        if (!ch2 || isspaceW(ch2)) {
-            if (chu == 'S' || chu == 'V') {
-                /* ignore these switches */
-            } else {
-                switch (chu) {
-                case 'D':
-                    action = ACTION_DELETE;
-                    break;
-                case 'E':
-                    action = ACTION_EXPORT;
-                    break;
-                case '?':
-                    fprintf(stderr,usage);
-                    exit(0);
-                    break;
-                default:
-                    error_unknown_switch(chu, s);
-                    break;
-                }
-            }
-            s++;
-        } else {
-            if (ch2 == ':') {
-                switch (chu) {
-                case 'L':
-                    /* fall through */
-                case 'R':
-                    s += 2;
-                    while (*s && !isspaceW(*s)) {
-                        s++;
-                    }
-                    break;
-                default:
-                    error_unknown_switch(chu, s);
-                    break;
-                }
-            } else {
-                /* this is a file name, starting from '/' */
-                s--;
-                break;
-            }
-        }
-        /* skip spaces to the next parameter */
-        ch = *s;
-        while (ch && isspaceW(ch)) {
-            s++;
-            ch = *s;
+        case 'S':
+        case 'V':
+            /* ignored */;
+            break;
+        case 'D':
+            action = ACTION_DELETE;
+            break;
+        case 'E':
+            action = ACTION_EXPORT;
+            break;
+        case 'L':
+        case 'R':
+            /* unhandled */;
+            break;
+        default:
+            fprintf(stderr, "regedit: Invalid switch [%ls]\n", argv[i]);
+            exit(1);
         }
     }
 
-    if (*s && action == ACTION_UNDEF)
-        action = ACTION_ADD;
+    if (i == argc)
+    {
+        switch (action)
+        {
+        case ACTION_ADD:
+        case ACTION_EXPORT:
+            fprintf(stderr, "regedit: No file name was specified\n\n");
+            break;
+        case ACTION_DELETE:
+            fprintf(stderr,"regedit: No registry key was specified for removal\n\n");
+            break;
+        }
+        fprintf(stderr, usage);
+        exit(1);
+    }
 
-    if (action == ACTION_UNDEF)
-        return FALSE;
+    for (; i < argc; i++)
+        PerformRegAction(action, argv, &i);
 
-    return PerformRegAction(action, s);
+    return TRUE;
 }
-- 
2.7.4




More information about the wine-patches mailing list