[PATCH 7/7] reg: Clean up reg_delete

Jonathan Vollebregt jnvsor at gmail.com
Tue Nov 4 14:15:14 CST 2014


---
 programs/reg/reg.c       | 147 ++++++++++++++++++++++++-----------------------
 programs/reg/reg.h       |   1 +
 programs/reg/reg.rc      |   1 +
 programs/reg/tests/reg.c |   2 +-
 4 files changed, 78 insertions(+), 73 deletions(-)

diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index d92853c..4035649 100755
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -23,9 +23,12 @@
 
 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))
 
+#define MAX_VALUE_NAME  16384
+
 #define ERROR_NO_REMOTE         20000
 #define ERROR_INVALID_TYPE      20001
 #define ERROR_NAN               20002
+#define ERROR_NO_DELETE_ROOTKEY 20003
 
 WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
@@ -162,6 +165,8 @@ static int reg_print_error(LONG error_code)
             return reg_message(STRING_UNSUPPORTED_TYPE);
         case ERROR_NAN:
             return reg_message(STRING_NAN);
+        case ERROR_NO_DELETE_ROOTKEY:
+            return reg_message(STRING_NO_DEL_ROOT);
         default:
         {
             static const WCHAR error_string[] = {'%','0','5','d',':',' ','%','s',0};
@@ -448,109 +453,107 @@ error:
     return 1;
 }
 
-static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
-    BOOL value_all, BOOL force)
+static int reg_delete(const WCHAR *key_name,    const WCHAR *value_name,  const BOOL value_empty,
+                      const BOOL value_all,     const BOOL force)
 {
-    HKEY subkey;
-    LONG err;
-
-    static const WCHAR stubW[] = {'D','E','L','E','T','E',
-        ' ','-',' ','%','s',' ','%','s',' ','%','d',' ','%','d',' ','%','d','\n'
-        ,0};
-    reg_printfW(stubW, key_name, value_name, value_empty, value_all, force);
+    HKEY key = NULL;
+    LONG err = path_get_key(key_name, &key);
 
-    err = path_get_key(key_name, &subkey);
     if (err != ERROR_SUCCESS)
-    {
-        reg_print_error(err);
-        return 1;
-    }
+        goto error;
 
-    if (value_name && value_empty)
+    /* Mutually exclusive options */
+    if ((!!value_name + !!value_empty + !!value_all) > 1)
     {
-        reg_message(STRING_INVALID_CMDLINE);
-        return 1;
+        err = ERROR_BAD_COMMAND;
+        goto error;
     }
 
-    if (value_empty && value_all)
+    if (!force)
     {
-        reg_message(STRING_INVALID_CMDLINE);
-        return 1;
+        FIXME("Prompt for delete\n");
     }
 
-    if (!force)
+    if (value_empty || value_name)
     {
-        /* FIXME:  Prompt for delete */
-    }
+        if (value_name && value_name[0])
+            err = RegDeleteValueW(key, value_name);
+        else
+            err = RegDeleteValueW(key, NULL);
 
-    /* Delete subtree only if no /v* option is given */
-    if (!value_name && !value_empty && !value_all)
+        if (err != ERROR_SUCCESS)
+            goto error;
+    }
+    else if (value_all)
     {
-        HKEY root;
-        err = path_get_rootkey(key_name, &root);
-        err = RegDeleteTreeW(root, strchrW(key_name, '\\') + 1);
+        WCHAR enum_v_name[MAX_VALUE_NAME];
+        DWORD count, max_size, i = 0, errors = 0;
+
+        err = RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL,
+                &count, NULL, NULL, NULL, NULL);
         if (err != ERROR_SUCCESS)
+            goto error;
+
+        while (i < count)
         {
-            reg_print_error(err);
-            return 1;
-        }
+            max_size = MAX_VALUE_NAME;
 
-        reg_message(STRING_SUCCESS);
-        return 0;
-    }
+            err = RegEnumValueW(key, i, enum_v_name, &max_size,
+                NULL, NULL, NULL, NULL);
 
-    if (value_all)
-    {
-        LPWSTR szValue;
-        DWORD maxValue;
-        DWORD count;
-        LONG rc;
-
-        rc = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-            &maxValue, NULL, NULL, NULL);
-        if (rc != ERROR_SUCCESS)
-        {
-            /* FIXME: failure */
-            RegCloseKey(subkey);
-            return 1;
-        }
-        maxValue++;
-        szValue = HeapAlloc(GetProcessHeap(),0,maxValue*sizeof(WCHAR));
+            if (err != ERROR_SUCCESS)
+            {
+                i++;
+                errors++;
+                reg_print_error(err);
+                continue;
+            }
 
-        while (1)
-        {
-            count = maxValue;
-            rc = RegEnumValueW(subkey, 0, szValue, &count, NULL, NULL, NULL, NULL);
-            if (rc == ERROR_SUCCESS)
+            err = RegDeleteValueW(key, enum_v_name);
+            if (err != ERROR_SUCCESS)
             {
-                rc = RegDeleteValueW(subkey, szValue);
-                if (rc != ERROR_SUCCESS)
-                    break;
+                i++;
+                errors++;
+                reg_print_error(err);
+                continue;
             }
-            else break;
+
+            count--;
         }
-        if (rc != ERROR_SUCCESS)
+
+        if (errors)
         {
-            /* FIXME  delete failed */
+            RegCloseKey(key);
+            return 1;
         }
     }
-    else if (value_name)
+    /* Delete subtree only if no /v* option is given */
+    else
     {
-        if (RegDeleteValueW(subkey,value_name) != ERROR_SUCCESS)
+        HKEY root;
+
+        err = path_get_rootkey(key_name, &root);
+        if (key == root)
         {
-            RegCloseKey(subkey);
-            reg_message(STRING_CANNOT_FIND);
-            return 1;
+            err = ERROR_NO_DELETE_ROOTKEY;
+            goto error;
         }
-    }
-    else if (value_empty)
-    {
-        RegSetValueExW(subkey,NULL,0,REG_SZ,NULL,0);
+
+        err = RegDeleteTreeW(root, strchrW(key_name, '\\') + 1);
+        if (err != ERROR_SUCCESS)
+            goto error;
     }
 
-    RegCloseKey(subkey);
+    RegCloseKey(key);
     reg_message(STRING_SUCCESS);
     return 0;
+
+error:
+    if (key)
+        RegCloseKey(key);
+
+    reg_print_error(err);
+    return 1;
 }
 
 static int reg_query(WCHAR *key_name, WCHAR *value_name, BOOL value_empty,
diff --git a/programs/reg/reg.h b/programs/reg/reg.h
index 334e7ad..88356d1 100644
--- a/programs/reg/reg.h
+++ b/programs/reg/reg.h
@@ -34,3 +34,4 @@
 #define STRING_INVALID_TYPE     111
 #define STRING_UNSUPPORTED_TYPE 112
 #define STRING_NAN              113
+#define STRING_NO_DEL_ROOT      114
diff --git a/programs/reg/reg.rc b/programs/reg/reg.rc
index a53013c..4675d35 100644
--- a/programs/reg/reg.rc
+++ b/programs/reg/reg.rc
@@ -39,4 +39,5 @@ STRINGTABLE
     STRING_INVALID_TYPE, "Error: Invalid type\n"
     STRING_UNSUPPORTED_TYPE, "Error: Unsupported type\n"
     STRING_NAN, "Error: This type requires /d to be a positive number\n"
+    STRING_NO_DEL_ROOT, "Error: Cannot delete root key\n"
 }
diff --git a/programs/reg/tests/reg.c b/programs/reg/tests/reg.c
index 0e9ad74..8a88ecf 100644
--- a/programs/reg/tests/reg.c
+++ b/programs/reg/tests/reg.c
@@ -367,7 +367,7 @@ static void test_delete(void)
     run_reg_exe("reg delete HKCU\\" KEY_BASE " /ve /f", &r);
     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
     err = RegQueryValueExA(hkey, "", NULL, NULL, NULL, NULL);
-    todo_wine ok(err == ERROR_FILE_NOT_FOUND, "got %d\n", err);
+    ok(err == ERROR_FILE_NOT_FOUND, "got %d\n", err);
 
     run_reg_exe("reg delete HKCU\\" KEY_BASE " /va /f", &r);
     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
-- 
2.1.1




More information about the wine-patches mailing list