[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    [PATCH v3 2/2] programs/sc: Allow using separate arguments for parameter name and value.
From:       Torge Matthies <tmatthies () codeweavers ! com>
Date:       2022-04-29 13:40:47
Message-ID: 20220429134047.61880-2-tmatthies () codeweavers ! com
[Download RAW message or body]

In addition to using one argument for both parameter name and value.

This fixes a regression from commit 8b38c91d83844dea882922055ced7cdeb79c1693.

Signed-off-by: Torge Matthies <tmatthies@codeweavers.com>
---
 programs/sc/sc.c       | 101 ++++++++++++++++++++++++++++-------------
 programs/sc/tests/sc.c |  95 ++++++++++++++++++++------------------
 2 files changed, 120 insertions(+), 76 deletions(-)

diff --git a/programs/sc/sc.c b/programs/sc/sc.c
index 43148ab99d60..bd7e093b61d2 100644
--- a/programs/sc/sc.c
+++ b/programs/sc/sc.c
@@ -27,6 +27,26 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(sc);
 
+static BOOL parse_string_param( int argc, const WCHAR *argv[], unsigned int *index,
+                                const WCHAR *param_name, size_t name_len, const \
WCHAR **out ) +{
+    if (!wcsnicmp( argv[*index], param_name, name_len ))
+    {
+        if (argv[*index][name_len])
+        {
+            *out = &argv[*index][name_len];
+            return TRUE;
+        }
+        else if (*index < argc - 1)
+        {
+            *index += 1;
+            *out = argv[*index];
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 struct create_params
 {
     const WCHAR *displayname;
@@ -56,48 +76,56 @@ static BOOL parse_create_params( int argc, const WCHAR *argv[], \
struct create_pa  cp->obj         = NULL;
     cp->password    = NULL;
 
+#define PARSE(x, y) parse_string_param( (argc), (argv), &(i), (x), ARRAY_SIZE(x) - \
1, (y) )  for (i = 0; i < argc; i++)
     {
-        if (!wcsnicmp( argv[i], L"displayname=", 12 )) cp->displayname = argv[i] + \
                12;
-        if (!wcsnicmp( argv[i], L"binpath=", 8 )) cp->binpath = argv[i] + 8;
-        if (!wcsnicmp( argv[i], L"group=", 6 )) cp->group = argv[i] + 6;
-        if (!wcsnicmp( argv[i], L"depend=", 7 )) cp->depend = argv[i] + 7;
-        if (!wcsnicmp( argv[i], L"obj=", 4 )) cp->obj = argv[i] + 4;
-        if (!wcsnicmp( argv[i], L"password=", 9 )) cp->password = argv[i] + 9;
-
-        if (!wcsnicmp( argv[i], L"tag=", 4 ))
+        const WCHAR *tag, *type, *start, *error;
+
+        if (PARSE( L"displayname=", &cp->displayname )) continue;
+        if (PARSE( L"binpath=", &cp->binpath )) continue;
+        if (PARSE( L"group=", &cp->group )) continue;
+        if (PARSE( L"depend=", &cp->depend )) continue;
+        if (PARSE( L"obj=", &cp->obj )) continue;
+        if (PARSE( L"password=", &cp->password )) continue;
+
+        if (PARSE( L"tag=", &tag ))
         {
-            if (!wcsicmp( argv[i] + 4, L"yes" ))
+            if (!wcsicmp( tag, L"yes" ))
             {
                 WINE_FIXME("tag argument not supported\n");
                 cp->tag = TRUE;
             }
+            continue;
         }
-        if (!wcsnicmp( argv[i], L"type=", 5 ))
+        if (PARSE( L"type=", &type ))
         {
-            if (!wcsicmp( argv[i] + 5, L"own" )) cp->type = \
                SERVICE_WIN32_OWN_PROCESS;
-            if (!wcsicmp( argv[i] + 5, L"share" )) cp->type = \
                SERVICE_WIN32_SHARE_PROCESS;
-            if (!wcsicmp( argv[i] + 5, L"kernel" )) cp->type = \
                SERVICE_KERNEL_DRIVER;
-            if (!wcsicmp( argv[i] + 5, L"filesys" )) cp->type = \
                SERVICE_FILE_SYSTEM_DRIVER;
-            if (!wcsicmp( argv[i] + 5, L"rec" )) cp->type = \
                SERVICE_RECOGNIZER_DRIVER;
-            if (!wcsicmp( argv[i] + 5, L"interact" )) cp->type |= \
SERVICE_INTERACTIVE_PROCESS; +            if (!wcsicmp( type, L"own" )) cp->type = \
SERVICE_WIN32_OWN_PROCESS; +            else if (!wcsicmp( type, L"share" )) cp->type \
= SERVICE_WIN32_SHARE_PROCESS; +            else if (!wcsicmp( type, L"kernel" )) \
cp->type = SERVICE_KERNEL_DRIVER; +            else if (!wcsicmp( type, L"filesys" )) \
cp->type = SERVICE_FILE_SYSTEM_DRIVER; +            else if (!wcsicmp( type, L"rec" \
)) cp->type = SERVICE_RECOGNIZER_DRIVER; +            else if (!wcsicmp( type, \
L"interact" )) cp->type |= SERVICE_INTERACTIVE_PROCESS; +            continue;
         }
-        if (!wcsnicmp( argv[i], L"start=", 6 ))
+        if (PARSE( L"start=", &start ))
         {
-            if (!wcsicmp( argv[i] + 6, L"boot" )) cp->start = SERVICE_BOOT_START;
-            if (!wcsicmp( argv[i] + 6, L"system" )) cp->start = \
                SERVICE_SYSTEM_START;
-            if (!wcsicmp( argv[i] + 6, L"auto" )) cp->start = SERVICE_AUTO_START;
-            if (!wcsicmp( argv[i] + 6, L"demand" )) cp->start = \
                SERVICE_DEMAND_START;
-            if (!wcsicmp( argv[i] + 6, L"disabled" )) cp->start = SERVICE_DISABLED;
+            if (!wcsicmp( start, L"boot" )) cp->start = SERVICE_BOOT_START;
+            else if (!wcsicmp( start, L"system" )) cp->start = SERVICE_SYSTEM_START;
+            else if (!wcsicmp( start, L"auto" )) cp->start = SERVICE_AUTO_START;
+            else if (!wcsicmp( start, L"demand" )) cp->start = SERVICE_DEMAND_START;
+            else if (!wcsicmp( start, L"disabled" )) cp->start = SERVICE_DISABLED;
+            continue;
         }
-        if (!wcsnicmp( argv[i], L"error=", 6 ))
+        if (PARSE( L"error=", &error ))
         {
-            if (!wcsicmp( argv[i] + 6, L"normal" )) cp->error = \
                SERVICE_ERROR_NORMAL;
-            if (!wcsicmp( argv[i] + 6, L"severe" )) cp->error = \
                SERVICE_ERROR_SEVERE;
-            if (!wcsicmp( argv[i] + 6, L"critical" )) cp->error = \
                SERVICE_ERROR_CRITICAL;
-            if (!wcsicmp( argv[i] + 6, L"ignore" )) cp->error = \
SERVICE_ERROR_IGNORE; +            if (!wcsicmp( error, L"normal" )) cp->error = \
SERVICE_ERROR_NORMAL; +            else if (!wcsicmp( error, L"severe" )) cp->error = \
SERVICE_ERROR_SEVERE; +            else if (!wcsicmp( error, L"critical" )) cp->error \
= SERVICE_ERROR_CRITICAL; +            else if (!wcsicmp( error, L"ignore" )) \
cp->error = SERVICE_ERROR_IGNORE; +            continue;
         }
     }
+#undef PARSE
     if (!cp->binpath) return FALSE;
     return TRUE;
 }
@@ -156,16 +184,25 @@ static BOOL parse_failure_params( int argc, const WCHAR \
*argv[], SERVICE_FAILURE  fa->cActions      = 0;
     fa->lpsaActions   = NULL;
 
+#define PARSE(x, y) parse_string_param( (argc), (argv), &(i), (x), ARRAY_SIZE(x) - \
1, (y) )  for (i = 0; i < argc; i++)
     {
-        if (!wcsnicmp( argv[i], L"reset=", 6 )) fa->dwResetPeriod = wcstol( argv[i] \
                + 6, NULL, 10 );
-        if (!wcsnicmp( argv[i], L"reboot=", 7 )) fa->lpRebootMsg = (WCHAR *)argv[i] \
                + 7;
-        if (!wcsnicmp( argv[i], L"command=", 8 )) fa->lpCommand = (WCHAR *)argv[i] + \
                8;
-        if (!wcsnicmp( argv[i], L"actions=", 8 ))
+        const WCHAR *reset, *actions;
+
+        if (PARSE( L"reset=", &reset ))
+        {
+            fa->dwResetPeriod = wcstol( reset, NULL, 10 );
+            continue;
+        }
+        if (PARSE( L"reboot=", (const WCHAR **)&fa->lpRebootMsg )) continue;
+        if (PARSE( L"command=", (const WCHAR **)&fa->lpCommand )) continue;
+        if (PARSE( L"actions=", &actions ))
         {
-            if (!parse_failure_actions( argv[i] + 8, fa )) return FALSE;
+            if (!parse_failure_actions( actions, fa )) return FALSE;
+            continue;
         }
     }
+#undef PARSE
     return TRUE;
 }
 
diff --git a/programs/sc/tests/sc.c b/programs/sc/tests/sc.c
index 66493ed578c7..57046905a4b0 100644
--- a/programs/sc/tests/sc.c
+++ b/programs/sc/tests/sc.c
@@ -168,13 +168,20 @@ static void test_create_service(BOOL elevated)
         DWORD expected_start_type;
         DWORD expected_service_type;
         const char * expected_binary_path;
+        DWORD broken;
     } start_types[] = {
-        { "boot type= kernel", SERVICE_BOOT_START, SERVICE_KERNEL_DRIVER, \
                TEST_SERVICE_BINARY_START_BOOT },
-        { "system type= kernel", SERVICE_SYSTEM_START, SERVICE_KERNEL_DRIVER, \
                TEST_SERVICE_BINARY_START_SYSTEM },
-        { "auto", SERVICE_AUTO_START, SERVICE_WIN32_OWN_PROCESS, TEST_SERVICE_BINARY \
                },
-        { "demand", SERVICE_DEMAND_START, SERVICE_WIN32_OWN_PROCESS, \
                TEST_SERVICE_BINARY },
-        { "disabled", SERVICE_DISABLED, SERVICE_WIN32_OWN_PROCESS, \
                TEST_SERVICE_BINARY },
-        { "delayed-auto", SERVICE_DELAYED_AUTO_START, SERVICE_WIN32_OWN_PROCESS, \
TEST_SERVICE_BINARY } +        { "boot type= kernel", SERVICE_BOOT_START, \
SERVICE_KERNEL_DRIVER, TEST_SERVICE_BINARY_START_BOOT, +          BROKEN_BINPATH | \
BROKEN_DISPLAY_NAME }, +        { "system type= kernel", SERVICE_SYSTEM_START, \
SERVICE_KERNEL_DRIVER, TEST_SERVICE_BINARY_START_SYSTEM, +          BROKEN_BINPATH | \
BROKEN_DISPLAY_NAME }, +        { "auto", SERVICE_AUTO_START, \
SERVICE_WIN32_OWN_PROCESS, TEST_SERVICE_BINARY, +          BROKEN_DISPLAY_NAME },
+        { "demand", SERVICE_DEMAND_START, SERVICE_WIN32_OWN_PROCESS, \
TEST_SERVICE_BINARY, +          BROKEN_DISPLAY_NAME },
+        { "disabled", SERVICE_DISABLED, SERVICE_WIN32_OWN_PROCESS, \
TEST_SERVICE_BINARY, +          BROKEN_DISPLAY_NAME },
+        { "delayed-auto", SERVICE_DELAYED_AUTO_START, SERVICE_WIN32_OWN_PROCESS, \
TEST_SERVICE_BINARY, +          BROKEN_START | BROKEN_DISPLAY_NAME | \
BROKEN_DELAYED_AUTO_START }  };
     static struct {
         const char *param;
@@ -217,45 +224,45 @@ static void test_create_service(BOOL elevated)
     /* binpath= */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY \
                "\"", &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL, "", NULL,
-                       BROKEN_CREATE);
+                       BROKEN_DISPLAY_NAME);
 
     /* existing service */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
start= auto", &r);  todo_wine check_exit_code(SC_EXIT_SERVICE_EXISTS);
     check_test_service(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL, "", NULL,
-                       BROKEN_CREATE);
-    delete_test_service(TRUE, TRUE);
+                       BROKEN_DISPLAY_NAME);
+    delete_test_service(TRUE, FALSE);
 
     /* type= */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
type= invalid", &r);  todo_wine check_exit_code(SC_EXIT_INVALID_COMMAND_LINE);
-    delete_test_service(FALSE, FALSE);
+    delete_test_service(FALSE, TRUE);
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
                type= own", &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL, "", NULL,
-                       BROKEN_CREATE);
-    delete_test_service(TRUE, TRUE);
+                       BROKEN_DISPLAY_NAME);
+    delete_test_service(TRUE, FALSE);
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
type= interact", &r);  todo_wine check_exit_code(SC_EXIT_INVALID_PARAMETER);
-    delete_test_service(FALSE, FALSE);
+    delete_test_service(FALSE, TRUE);
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
                type= interact type= own", &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service(SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, \
                SERVICE_DEMAND_START,
-                       SERVICE_ERROR_NORMAL, "", NULL, BROKEN_CREATE);
-    delete_test_service(TRUE, TRUE);
+                       SERVICE_ERROR_NORMAL, "", NULL, BROKEN_TYPE | \
BROKEN_DISPLAY_NAME); +    delete_test_service(TRUE, FALSE);
 
     /* start= */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
start= invalid", &r);  todo_wine check_exit_code(SC_EXIT_INVALID_COMMAND_LINE);
-    delete_test_service(FALSE, FALSE);
+    delete_test_service(FALSE, TRUE);
 
     for (i = 0; i < ARRAY_SIZE(start_types); i++)
     {
@@ -264,11 +271,11 @@ static void test_create_service(BOOL elevated)
         strcpy(cmdline, "sc create " TEST_SERVICE_NAME " binpath= \"" \
TEST_SERVICE_BINARY "\" start= ");  strcat(cmdline, start_types[i].param);
         run_sc_exe(cmdline, &r);
-        todo_wine check_exit_code(SC_EXIT_SUCCESS);
+        check_exit_code(SC_EXIT_SUCCESS);
         check_service_definition(TEST_SERVICE_NAME, \
                start_types[i].expected_binary_path,
                                  start_types[i].expected_service_type, \
                start_types[i].expected_start_type,
-                                 SERVICE_ERROR_NORMAL, "", TEST_SERVICE_NAME, \
                BROKEN_CREATE);
-        delete_test_service(TRUE, TRUE);
+                                 SERVICE_ERROR_NORMAL, "", TEST_SERVICE_NAME, \
start_types[i].broken); +        delete_test_service(TRUE, FALSE);
     }
 
     /* error= */
@@ -280,53 +287,53 @@ static void test_create_service(BOOL elevated)
         strcpy(cmdline, "sc create " TEST_SERVICE_NAME " binpath= \"" \
TEST_SERVICE_BINARY "\" error= ");  strcat(cmdline, error_severities[i].param);
         run_sc_exe(cmdline, &r);
-        todo_wine check_exit_code(SC_EXIT_SUCCESS);
+        check_exit_code(SC_EXIT_SUCCESS);
         check_test_service(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
-                           error_severities[i].expected_error_control, "", NULL, \
                BROKEN_CREATE);
-        delete_test_service(TRUE, TRUE);
+                           error_severities[i].expected_error_control, "", NULL, \
BROKEN_DISPLAY_NAME); +        delete_test_service(TRUE, FALSE);
     }
 
     /* tag= */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
tag= yes", &r);  todo_wine check_exit_code(SC_EXIT_INVALID_PARAMETER);
-    delete_test_service(FALSE, FALSE);
+    delete_test_service(FALSE, TRUE);
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
                tag= no", &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL, "", NULL,
-                       BROKEN_CREATE);
-    delete_test_service(TRUE, TRUE);
+                       BROKEN_DISPLAY_NAME);
+    delete_test_service(TRUE, FALSE);
 
     /* depend= */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= \"" TEST_SERVICE_BINARY "\" \
depend= " TEST_SERVICE_NAME, &r);  todo_wine \
                check_exit_code(SC_EXIT_CIRCULAR_DEPENDENCY);
-    delete_test_service(FALSE, FALSE);
+    delete_test_service(FALSE, TRUE);
 
     run_sc_exe("sc create " TEST_SERVICE_NAME2 " binpath= \"" TEST_SERVICE_BINARY \
                "\" depend= " TEST_SERVICE_NAME, &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service2(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL,
-                        TEST_SERVICE_NAME, NULL, BROKEN_CREATE);
-    delete_test_service2(TRUE, TRUE);
+                        TEST_SERVICE_NAME, NULL, BROKEN_DEPEND | \
BROKEN_DISPLAY_NAME); +    delete_test_service2(TRUE, FALSE);
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= " TEST_SERVICE_BINARY, &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     run_sc_exe("sc create " TEST_SERVICE_NAME2 " binpath= \"" TEST_SERVICE_BINARY \
                "\" depend= " TEST_SERVICE_NAME, &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service2(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL,
-                        TEST_SERVICE_NAME, NULL, BROKEN_CREATE);
-    delete_test_service2(TRUE, TRUE);
-    delete_test_service(TRUE, TRUE);
+                        TEST_SERVICE_NAME, NULL, BROKEN_DEPEND | \
BROKEN_DISPLAY_NAME); +    delete_test_service2(TRUE, FALSE);
+    delete_test_service(TRUE, FALSE);
 
     /* displayname= */
 
     run_sc_exe("sc create " TEST_SERVICE_NAME " binpath= " TEST_SERVICE_BINARY
                " displayname= \"Wine Test Service\"", &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service(SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
                SERVICE_ERROR_NORMAL, "",
-                       "Wine Test Service", BROKEN_CREATE);
-    delete_test_service(TRUE, TRUE);
+                       "Wine Test Service", 0);
+    delete_test_service(TRUE, FALSE);
 
     /* without spaces */
 
@@ -349,10 +356,10 @@ static void test_create_service(BOOL elevated)
 
     run_sc_exe("SC CREATE " TEST_SERVICE_NAME2 " BINPATH= \"" TEST_SERVICE_BINARY \
                "\" TYPE= OWN START= AUTO"
                " ERROR= NORMAL TAG= NO DEPEND= " TEST_SERVICE_NAME " DISPLAYNAME= \
                \"Wine Test Service\"", &r);
-    todo_wine check_exit_code(SC_EXIT_SUCCESS);
+    check_exit_code(SC_EXIT_SUCCESS);
     check_test_service2(SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, \
                SERVICE_ERROR_NORMAL,
-                        TEST_SERVICE_NAME, "Wine Test Service", BROKEN_CREATE);
-    delete_test_service2(TRUE, TRUE);
+                        TEST_SERVICE_NAME, "Wine Test Service", BROKEN_DEPEND);
+    delete_test_service2(TRUE, FALSE);
 
 #undef delete_test_service2
 #undef check_test_service2
-- 
2.36.0


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic