[PATCH 3/3] reg: Split 'add' functions from reg.c

Hugh McMaster hugh.mcmaster at outlook.com
Wed Mar 17 07:38:06 CDT 2021


Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
 programs/reg/Makefile.in |   1 +
 programs/reg/add.c       | 213 +++++++++++++++++++++++++++++++++++++++
 programs/reg/reg.c       | 192 -----------------------------------
 programs/reg/reg.h       |   4 +
 4 files changed, 218 insertions(+), 192 deletions(-)
 create mode 100644 programs/reg/add.c

diff --git a/programs/reg/Makefile.in b/programs/reg/Makefile.in
index 161be0062f1..5ef0d0854aa 100644
--- a/programs/reg/Makefile.in
+++ b/programs/reg/Makefile.in
@@ -5,6 +5,7 @@ DELAYIMPORTS = user32
 EXTRADLLFLAGS = -mconsole -municode -mno-cygwin
 
 C_SRCS = \
+	add.c \
 	delete.c \
 	export.c \
 	import.c \
diff --git a/programs/reg/add.c b/programs/reg/add.c
new file mode 100644
index 00000000000..2d8521f9234
--- /dev/null
+++ b/programs/reg/add.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2016-2017, 2021 Hugh McMaster
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <wine/heap.h>
+#include "reg.h"
+
+static DWORD wchar_get_type(const WCHAR *type_name)
+{
+    DWORD i;
+
+    if (!type_name)
+        return REG_SZ;
+
+    for (i = 0; i < ARRAY_SIZE(type_rels); i++)
+    {
+        if (!wcsicmp(type_rels[i].name, type_name))
+            return type_rels[i].type;
+    }
+
+    return ~0u;
+}
+
+/* hexchar_to_byte from programs/regedit/hexedit.c */
+static inline BYTE hexchar_to_byte(WCHAR ch)
+{
+    if (ch >= '0' && ch <= '9')
+        return ch - '0';
+    else if (ch >= 'a' && ch <= 'f')
+        return ch - 'a' + 10;
+    else if (ch >= 'A' && ch <= 'F')
+        return ch - 'A' + 10;
+    else
+        return -1;
+}
+
+static LPBYTE get_regdata(const WCHAR *data, DWORD reg_type, WCHAR separator, DWORD *reg_count)
+{
+    static const WCHAR empty;
+    LPBYTE out_data = NULL;
+    *reg_count = 0;
+
+    if (!data) data = ∅
+
+    switch (reg_type)
+    {
+        case REG_NONE:
+        case REG_SZ:
+        case REG_EXPAND_SZ:
+        {
+            *reg_count = (lstrlenW(data) + 1) * sizeof(WCHAR);
+            out_data = heap_xalloc(*reg_count);
+            lstrcpyW((LPWSTR)out_data,data);
+            break;
+        }
+        case REG_DWORD:
+     /* case REG_DWORD_LITTLE_ENDIAN: */
+        case REG_DWORD_BIG_ENDIAN: /* Yes, this is correct! */
+        {
+            LPWSTR rest;
+            unsigned long val;
+            val = wcstoul(data, &rest, (towlower(data[1]) == 'x') ? 16 : 10);
+            if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE)) {
+                output_message(STRING_MISSING_INTEGER);
+                break;
+            }
+            *reg_count = sizeof(DWORD);
+            out_data = heap_xalloc(*reg_count);
+            ((LPDWORD)out_data)[0] = val;
+            break;
+        }
+        case REG_BINARY:
+        {
+            BYTE hex0, hex1;
+            int i = 0, destByteIndex = 0, datalen = lstrlenW(data);
+            *reg_count = ((datalen + datalen % 2) / 2) * sizeof(BYTE);
+            out_data = heap_xalloc(*reg_count);
+            if(datalen % 2)
+            {
+                hex1 = hexchar_to_byte(data[i++]);
+                if(hex1 == 0xFF)
+                    goto no_hex_data;
+                out_data[destByteIndex++] = hex1;
+            }
+            for(;i + 1 < datalen;i += 2)
+            {
+                hex0 = hexchar_to_byte(data[i]);
+                hex1 = hexchar_to_byte(data[i + 1]);
+                if(hex0 == 0xFF || hex1 == 0xFF)
+                    goto no_hex_data;
+                out_data[destByteIndex++] = (hex0 << 4) | hex1;
+            }
+            break;
+            no_hex_data:
+            /* cleanup, print error */
+            heap_free(out_data);
+            output_message(STRING_MISSING_HEXDATA);
+            out_data = NULL;
+            break;
+        }
+        case REG_MULTI_SZ:
+        {
+            int i, destindex, len = lstrlenW(data);
+            WCHAR *buffer = heap_xalloc((len + 2) * sizeof(WCHAR));
+
+            for (i = 0, destindex = 0; i < len; i++, destindex++)
+            {
+                if (!separator && data[i] == '\\' && data[i + 1] == '0')
+                {
+                    buffer[destindex] = 0;
+                    i++;
+                }
+                else if (data[i] == separator)
+                    buffer[destindex] = 0;
+                else
+                    buffer[destindex] = data[i];
+
+                if (destindex && !buffer[destindex - 1] && (!buffer[destindex] || destindex == 1))
+                {
+                    heap_free(buffer);
+                    output_message(STRING_INVALID_STRING);
+                    return NULL;
+                }
+            }
+            buffer[destindex] = 0;
+            if (destindex && buffer[destindex - 1])
+                buffer[++destindex] = 0;
+            *reg_count = (destindex + 1) * sizeof(WCHAR);
+            return (BYTE *)buffer;
+        }
+        default:
+            output_message(STRING_UNHANDLED_TYPE, reg_type, data);
+    }
+
+    return out_data;
+}
+
+int reg_add(HKEY root, WCHAR *path, WCHAR *value_name, BOOL value_empty,
+            WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
+{
+    HKEY key;
+
+    if (RegCreateKeyW(root, path, &key) != ERROR_SUCCESS)
+    {
+        output_message(STRING_INVALID_KEY);
+        return 1;
+    }
+
+    if (value_name || value_empty || data)
+    {
+        DWORD reg_type;
+        DWORD reg_count = 0;
+        BYTE* reg_data = NULL;
+
+        if (!force)
+        {
+            if (RegQueryValueExW(key, value_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+            {
+                if (!ask_confirm(STRING_OVERWRITE_VALUE, value_name))
+                {
+                    RegCloseKey(key);
+                    output_message(STRING_CANCELLED);
+                    return 0;
+                }
+            }
+        }
+
+        reg_type = wchar_get_type(type);
+        if (reg_type == ~0u)
+        {
+            RegCloseKey(key);
+            output_message(STRING_UNSUPPORTED_TYPE, type);
+            return 1;
+        }
+        if ((reg_type == REG_DWORD || reg_type == REG_DWORD_BIG_ENDIAN) && !data)
+        {
+             RegCloseKey(key);
+             output_message(STRING_INVALID_CMDLINE);
+             return 1;
+        }
+
+        if (!(reg_data = get_regdata(data, reg_type, separator, &reg_count)))
+        {
+            RegCloseKey(key);
+            return 1;
+        }
+
+        RegSetValueExW(key, value_name, 0, reg_type, reg_data, reg_count);
+        heap_free(reg_data);
+    }
+
+    RegCloseKey(key);
+    output_message(STRING_SUCCESS);
+
+    return 0;
+}
diff --git a/programs/reg/reg.c b/programs/reg/reg.c
index 079ed9b1a1e..071fb6f88ea 100644
--- a/programs/reg/reg.c
+++ b/programs/reg/reg.c
@@ -17,8 +17,6 @@
  */
 
 #include <windows.h>
-#include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <wine/debug.h>
 #include <wine/heap.h>
@@ -213,136 +211,6 @@ HKEY path_get_rootkey(const WCHAR *path)
     return NULL;
 }
 
-static DWORD wchar_get_type(const WCHAR *type_name)
-{
-    DWORD i;
-
-    if (!type_name)
-        return REG_SZ;
-
-    for (i = 0; i < ARRAY_SIZE(type_rels); i++)
-    {
-        if (!wcsicmp(type_rels[i].name, type_name))
-            return type_rels[i].type;
-    }
-
-    return ~0u;
-}
-
-/* hexchar_to_byte from programs/regedit/hexedit.c */
-static inline BYTE hexchar_to_byte(WCHAR ch)
-{
-    if (ch >= '0' && ch <= '9')
-        return ch - '0';
-    else if (ch >= 'a' && ch <= 'f')
-        return ch - 'a' + 10;
-    else if (ch >= 'A' && ch <= 'F')
-        return ch - 'A' + 10;
-    else
-        return -1;
-}
-
-static LPBYTE get_regdata(const WCHAR *data, DWORD reg_type, WCHAR separator, DWORD *reg_count)
-{
-    static const WCHAR empty;
-    LPBYTE out_data = NULL;
-    *reg_count = 0;
-
-    if (!data) data = ∅
-
-    switch (reg_type)
-    {
-        case REG_NONE:
-        case REG_SZ:
-        case REG_EXPAND_SZ:
-        {
-            *reg_count = (lstrlenW(data) + 1) * sizeof(WCHAR);
-            out_data = heap_xalloc(*reg_count);
-            lstrcpyW((LPWSTR)out_data,data);
-            break;
-        }
-        case REG_DWORD:
-     /* case REG_DWORD_LITTLE_ENDIAN: */
-        case REG_DWORD_BIG_ENDIAN: /* Yes, this is correct! */
-        {
-            LPWSTR rest;
-            unsigned long val;
-            val = wcstoul(data, &rest, (towlower(data[1]) == 'x') ? 16 : 10);
-            if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE)) {
-                output_message(STRING_MISSING_INTEGER);
-                break;
-            }
-            *reg_count = sizeof(DWORD);
-            out_data = heap_xalloc(*reg_count);
-            ((LPDWORD)out_data)[0] = val;
-            break;
-        }
-        case REG_BINARY:
-        {
-            BYTE hex0, hex1;
-            int i = 0, destByteIndex = 0, datalen = lstrlenW(data);
-            *reg_count = ((datalen + datalen % 2) / 2) * sizeof(BYTE);
-            out_data = heap_xalloc(*reg_count);
-            if(datalen % 2)
-            {
-                hex1 = hexchar_to_byte(data[i++]);
-                if(hex1 == 0xFF)
-                    goto no_hex_data;
-                out_data[destByteIndex++] = hex1;
-            }
-            for(;i + 1 < datalen;i += 2)
-            {
-                hex0 = hexchar_to_byte(data[i]);
-                hex1 = hexchar_to_byte(data[i + 1]);
-                if(hex0 == 0xFF || hex1 == 0xFF)
-                    goto no_hex_data;
-                out_data[destByteIndex++] = (hex0 << 4) | hex1;
-            }
-            break;
-            no_hex_data:
-            /* cleanup, print error */
-            heap_free(out_data);
-            output_message(STRING_MISSING_HEXDATA);
-            out_data = NULL;
-            break;
-        }
-        case REG_MULTI_SZ:
-        {
-            int i, destindex, len = lstrlenW(data);
-            WCHAR *buffer = heap_xalloc((len + 2) * sizeof(WCHAR));
-
-            for (i = 0, destindex = 0; i < len; i++, destindex++)
-            {
-                if (!separator && data[i] == '\\' && data[i + 1] == '0')
-                {
-                    buffer[destindex] = 0;
-                    i++;
-                }
-                else if (data[i] == separator)
-                    buffer[destindex] = 0;
-                else
-                    buffer[destindex] = data[i];
-
-                if (destindex && !buffer[destindex - 1] && (!buffer[destindex] || destindex == 1))
-                {
-                    heap_free(buffer);
-                    output_message(STRING_INVALID_STRING);
-                    return NULL;
-                }
-            }
-            buffer[destindex] = 0;
-            if (destindex && buffer[destindex - 1])
-                buffer[++destindex] = 0;
-            *reg_count = (destindex + 1) * sizeof(WCHAR);
-            return (BYTE *)buffer;
-        }
-        default:
-            output_message(STRING_UNHANDLED_TYPE, reg_type, data);
-    }
-
-    return out_data;
-}
-
 static BOOL sane_path(const WCHAR *key)
 {
     unsigned int i = lstrlenW(key);
@@ -362,66 +230,6 @@ static BOOL sane_path(const WCHAR *key)
     return TRUE;
 }
 
-static int reg_add(HKEY root, WCHAR *path, WCHAR *value_name, BOOL value_empty,
-                   WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
-{
-    HKEY key;
-
-    if (RegCreateKeyW(root, path, &key) != ERROR_SUCCESS)
-    {
-        output_message(STRING_INVALID_KEY);
-        return 1;
-    }
-
-    if (value_name || value_empty || data)
-    {
-        DWORD reg_type;
-        DWORD reg_count = 0;
-        BYTE* reg_data = NULL;
-
-        if (!force)
-        {
-            if (RegQueryValueExW(key, value_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
-            {
-                if (!ask_confirm(STRING_OVERWRITE_VALUE, value_name))
-                {
-                    RegCloseKey(key);
-                    output_message(STRING_CANCELLED);
-                    return 0;
-                }
-            }
-        }
-
-        reg_type = wchar_get_type(type);
-        if (reg_type == ~0u)
-        {
-            RegCloseKey(key);
-            output_message(STRING_UNSUPPORTED_TYPE, type);
-            return 1;
-        }
-        if ((reg_type == REG_DWORD || reg_type == REG_DWORD_BIG_ENDIAN) && !data)
-        {
-             RegCloseKey(key);
-             output_message(STRING_INVALID_CMDLINE);
-             return 1;
-        }
-
-        if (!(reg_data = get_regdata(data, reg_type, separator, &reg_count)))
-        {
-            RegCloseKey(key);
-            return 1;
-        }
-
-        RegSetValueExW(key, value_name, 0, reg_type, reg_data, reg_count);
-        heap_free(reg_data);
-    }
-
-    RegCloseKey(key);
-    output_message(STRING_SUCCESS);
-
-    return 0;
-}
-
 WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
 {
     WCHAR *subkey_path;
diff --git a/programs/reg/reg.h b/programs/reg/reg.h
index c8baaa0f9a9..b14470b2cbf 100644
--- a/programs/reg/reg.h
+++ b/programs/reg/reg.h
@@ -41,6 +41,10 @@ HKEY path_get_rootkey(const WCHAR *path);
 WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len);
 BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key);
 
+/* add.c */
+int reg_add(HKEY root, WCHAR *path, WCHAR *value_name, BOOL value_empty,
+            WCHAR *type, WCHAR separator, WCHAR *data, BOOL force);
+
 /* delete.c */
 int reg_delete(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name,
                BOOL value_empty, BOOL value_all, BOOL force);
-- 
2.31.0




More information about the wine-devel mailing list