registry...
[metze/samba/wip.git] / source4 / lib / registry / util.c
index fce420e6256f9aca6f4051a6b3f8012ef5d798e2..7681f0ae287c6f127f74ce44edefa8ad903d9512 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    Transparent registry backend handling
    Copyright (C) Jelmer Vernooij                       2003-2007.
+   Copyright (C) Wilco Baan Hofman                     2010.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "includes.h"
 #include "lib/registry/registry.h"
 #include "librpc/gen_ndr/winreg.h"
+#include "lib/util/data_blob.h"
 
 _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
                                   const DATA_BLOB data)
 {
+       size_t converted_size = 0;
        char *ret = NULL;
 
        if (data.length == 0)
@@ -33,19 +36,21 @@ _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
                case REG_EXPAND_SZ:
                case REG_SZ:
                        convert_string_talloc(mem_ctx,
-                                                         CH_UTF16, CH_UNIX, data.data, data.length,
-                                                         (void **)&ret, NULL, false);
+                                             CH_UTF16, CH_UNIX,
+                                             data.data, data.length,
+                                             (void **)&ret, &converted_size);
                        break;
                case REG_DWORD:
+                       ret = talloc_asprintf(mem_ctx, "0x%8.8x",
+                                             RIVAL(data.data, 0));
+                       break;
                case REG_DWORD_BIG_ENDIAN:
-                       SMB_ASSERT(data.length == sizeof(uint32_t));
                        ret = talloc_asprintf(mem_ctx, "0x%8.8x",
                                              IVAL(data.data, 0));
                        break;
                case REG_QWORD:
-                       SMB_ASSERT(data.length == sizeof(uint64_t));
                        ret = talloc_asprintf(mem_ctx, "0x%16.16llx",
-                                             BVAL(data.data, 0));
+                                             (long long)BVAL(data.data, 0));
                        break;
                case REG_BINARY:
                        ret = data_blob_hex_string_upper(mem_ctx, &data);
@@ -66,7 +71,7 @@ _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
 }
 
 /** Generate a string that describes a registry value */
-_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, 
+_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx,
                                   const char *name,
                                   uint32_t data_type,
                                   const DATA_BLOB data)
@@ -76,11 +81,78 @@ _PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx,
                               reg_val_data_string(mem_ctx, data_type, data));
 }
 
+/*
+ * This implements reading hex bytes that include comma's.
+ * It was previously handled by strhex_to_data_blob, but that did not cover
+ * the format used by windows.
+ */
+static DATA_BLOB reg_strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *str)
+{
+       DATA_BLOB ret;
+       const char *HEXCHARS = "0123456789ABCDEF";
+       size_t i, j;
+       char *hi, *lo;
+
+       ret = data_blob_talloc_zero(mem_ctx, (strlen(str)+(strlen(str) % 3))/3);
+       j = 0;
+       for (i = 0; i < strlen(str); i++) {
+               hi = strchr(HEXCHARS, toupper(str[i]));
+               if (hi == NULL)
+                       continue;
+
+               i++;
+               lo = strchr(HEXCHARS, toupper(str[i]));
+               if (lo == NULL)
+                       break;
+
+               ret.data[j] = PTR_DIFF(hi, HEXCHARS) << 4;
+               ret.data[j] += PTR_DIFF(lo, HEXCHARS);
+               j++;
+
+               if (j > ret.length) {
+                       DEBUG(0, ("Trouble converting hex string to bin\n"));
+                       break;
+               }
+       }
+       return ret;
+}
+
+
 _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str,
                                const char *data_str, uint32_t *type, DATA_BLOB *data)
 {
+       char *tmp_type_str, *p, *q;
+       int result;
+
        *type = regtype_by_string(type_str);
 
+       if (*type == -1) {
+               /* Normal windows format is hex, hex(type int as string),
+                  dword or just a string. */
+               if (strncmp(type_str, "hex(", 4) == 0) {
+                       /* there is a hex string with the value type between
+                          the braces */
+                       tmp_type_str = talloc_strdup(mem_ctx, type_str);
+                       q = p = tmp_type_str + strlen("hex(");
+
+                       /* Go to the closing brace or end of the string */
+                       while (*q != ')' && *q != '\0') q++;
+                       *q = '\0';
+
+                       /* Convert hex string to int, store it in type */
+                       result = sscanf(p, "%x", type);
+                       if (!result) {
+                               DEBUG(0, ("Could not convert hex to int\n"));
+                               return false;
+                       }
+                       talloc_free(tmp_type_str);
+               } else if (strcmp(type_str, "hex") == 0) {
+                       *type = REG_BINARY;
+               } else if (strcmp(type_str, "dword") == 0) {
+                       *type = REG_DWORD;
+               }
+       }
+
        if (*type == -1)
                return false;
 
@@ -88,26 +160,27 @@ _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str,
 
        switch (*type) {
                case REG_SZ:
-               case REG_EXPAND_SZ:
                        return convert_string_talloc(mem_ctx,
-                                                                CH_UNIX, CH_UTF16, data_str,
-                                                                strlen(data_str)+1,
-                                                                (void **)&data->data,
-                                                                &data->length, false);
+                                                    CH_UNIX, CH_UTF16,
+                                                    data_str, strlen(data_str)+1,
+                                                    (void **)&data->data,
+                                                    &data->length);
                        break;
+               case REG_MULTI_SZ:
+               case REG_EXPAND_SZ:
                case REG_BINARY:
-                       *data = strhex_to_data_blob(mem_ctx, data_str);
+                       *data = reg_strhex_to_data_blob(mem_ctx, data_str);
                        break;
                case REG_DWORD:
                case REG_DWORD_BIG_ENDIAN: {
-                       uint32_t tmp = strtol(data_str, NULL, 0);
+                       uint32_t tmp = strtol(data_str, NULL, 16);
                        *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint32_t));
                        if (data->data == NULL) return false;
                        SIVAL(data->data, 0, tmp);
                        }
                        break;
                case REG_QWORD: {
-                       uint64_t tmp = strtoll(data_str, NULL, 0);
+                       uint64_t tmp = strtoll(data_str, NULL, 16);
                        *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint64_t));
                        if (data->data == NULL) return false;
                        SBVAL(data->data, 0, tmp);
@@ -116,9 +189,6 @@ _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str,
                case REG_NONE:
                        ZERO_STRUCTP(data);
                        break;
-               case REG_MULTI_SZ:
-                       /* FIXME: We don't support this yet */
-                       return false;
                default:
                        /* FIXME */
                        /* Other datatypes aren't supported -> return no success */