s3-talloc Change TALLOC_ARRAY() to talloc_array()
[samba.git] / source3 / registry / reg_backend_db.c
index 47f95905766fbf89dfd9cc6a00b7bf486dacdaff..05f3a5a0ab7c1f014da1e563be08bb1d34c2d986 100644 (file)
 /* Implementation of internal registry database functions. */
 
 #include "includes.h"
-
+#include "system/filesys.h"
 #include "registry.h"
 #include "reg_db.h"
 #include "reg_util_internal.h"
 #include "reg_backend_db.h"
 #include "reg_objects.h"
+#include "nt_printing.h"
+#include "util_tdb.h"
+#include "dbwrap.h"
+#include "../libcli/security/secdesc.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
@@ -45,6 +49,8 @@ static int regdb_fetch_values_internal(struct db_context *db, const char* key,
 static bool regdb_store_values_internal(struct db_context *db, const char *key,
                                        struct regval_ctr *values);
 
+static NTSTATUS create_sorted_subkeys(const char *key);
+
 /* List the deepest path into the registry.  All part components will be created.*/
 
 /* If you want to have a part of the path controlled by the tdb and part by
@@ -59,6 +65,9 @@ static const char *builtin_registry_paths[] = {
        KEY_PRINTING_2K,
        KEY_PRINTING_PORTS,
        KEY_PRINTING,
+       KEY_PRINTING "\\Forms",
+       KEY_PRINTING "\\Printers",
+       KEY_PRINTING "\\Environments\\Windows NT x86\\Print Processors\\winprint",
        KEY_SHARES,
        KEY_EVENTLOG,
        KEY_SMBCONF,
@@ -99,7 +108,7 @@ static struct builtin_regkey_value builtin_registry_values[] = {
        { KEY_PRINTING_2K,
                "DefaultSpoolDirectory", REG_SZ, { "C:\\Windows\\System32\\Spool\\Printers" } },
        { KEY_EVENTLOG,
-               "DisplayName", REG_SZ, { "Event Log" } }, 
+               "DisplayName", REG_SZ, { "Event Log" } },
        { KEY_EVENTLOG,
                "ErrorControl", REG_DWORD, { (char*)0x00000001 } },
        { NULL, NULL, 0, { NULL } }
@@ -412,10 +421,8 @@ static int regdb_normalize_keynames_fn(struct db_record *rec,
                          (const char *) rec->key.dptr,
                          keyname));
 
-               new_rec.value.dptr = rec->value.dptr;
-               new_rec.value.dsize = rec->value.dsize;
-               new_rec.key.dptr = (unsigned char *) keyname;
-               new_rec.key.dsize = strlen(keyname);
+               new_rec.value = rec->value;
+               new_rec.key = string_term_tdb_data(keyname);
                new_rec.private_data = rec->private_data;
 
                /* Delete the original record and store the normalized key */
@@ -450,11 +457,11 @@ static WERROR regdb_store_regdb_version(uint32_t version)
 
        status = dbwrap_trans_store_int32(regdb, version_keyname, version);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
+               DEBUG(1, ("regdb_store_regdb_version: error storing %s = %d: %s\n",
                          version_keyname, version, nt_errstr(status)));
                return ntstatus_to_werror(status);
        } else {
-               DEBUG(10, ("regdb_init: stored %s = %d\n",
+               DEBUG(10, ("regdb_store_regdb_version: stored %s = %d\n",
                          version_keyname, version));
                return WERR_OK;
        }
@@ -494,8 +501,8 @@ WERROR regdb_init(void)
        WERROR werr;
 
        if (regdb) {
-               DEBUG(10, ("regdb_init: incrementing refcount (%d)\n",
-                         regdb_refcount));
+               DEBUG(10, ("regdb_init: incrementing refcount (%d->%d)\n",
+                          regdb_refcount, regdb_refcount+1));
                regdb_refcount++;
                return WERR_OK;
        }
@@ -511,33 +518,24 @@ WERROR regdb_init(void)
                                state_path("registry.tdb"), strerror(errno) ));
                        return werr;
                }
-               
+
                DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
        }
 
        regdb_refcount = 1;
+       DEBUG(10, ("regdb_init: registry db openend. refcount reset (%d)\n",
+                  regdb_refcount));
 
        expected_version = REGVER_V2;
 
        vers_id = dbwrap_fetch_int32(regdb, vstring);
        if (vers_id == -1) {
-               NTSTATUS status;
-
                DEBUG(10, ("regdb_init: registry version uninitialized "
                           "(got %d), initializing to version %d\n",
                           vers_id, expected_version));
 
-               status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V2);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
-                                 vstring, expected_version, nt_errstr(status)));
-                       return ntstatus_to_werror(status);
-               } else {
-                       DEBUG(10, ("regdb_init: stored %s = %d\n",
-                                 vstring, expected_version));
-               }
-
-               return WERR_OK;
+               werr = regdb_store_regdb_version(expected_version);
+               return werr;
        }
 
        if (vers_id > expected_version || vers_id == 0) {
@@ -582,25 +580,27 @@ WERROR regdb_open( void )
        WERROR result = WERR_OK;
 
        if ( regdb ) {
-               DEBUG(10,("regdb_open: incrementing refcount (%d)\n", regdb_refcount));
+               DEBUG(10, ("regdb_open: incrementing refcount (%d->%d)\n",
+                          regdb_refcount, regdb_refcount+1));
                regdb_refcount++;
                return WERR_OK;
        }
-       
+
        become_root();
 
        regdb = db_open(NULL, state_path("registry.tdb"), 0,
                              REG_TDB_FLAGS, O_RDWR, 0600);
        if ( !regdb ) {
                result = ntstatus_to_werror( map_nt_error_from_unix( errno ) );
-               DEBUG(0,("regdb_open: Failed to open %s! (%s)\n", 
+               DEBUG(0,("regdb_open: Failed to open %s! (%s)\n",
                        state_path("registry.tdb"), strerror(errno) ));
        }
 
        unbecome_root();
 
        regdb_refcount = 1;
-       DEBUG(10,("regdb_open: refcount reset (%d)\n", regdb_refcount));
+       DEBUG(10, ("regdb_open: registry db opened. refcount reset (%d)\n",
+                  regdb_refcount));
 
        return result;
 }
@@ -616,7 +616,8 @@ int regdb_close( void )
 
        regdb_refcount--;
 
-       DEBUG(10,("regdb_close: decrementing refcount (%d)\n", regdb_refcount));
+       DEBUG(10, ("regdb_close: decrementing refcount (%d->%d)\n",
+                  regdb_refcount+1, regdb_refcount));
 
        if ( regdb_refcount > 0 )
                return 0;
@@ -834,22 +835,9 @@ static WERROR regdb_store_keys_internal2(struct db_context *db,
        W_ERROR_NOT_OK_GOTO_DONE(werr);
 
        /*
-        * Delete a sorted subkey cache for regdb_key_exists, will be
-        * recreated automatically
+        * recreate the sorted subkey cache for regdb_key_exists()
         */
-       keyname = talloc_asprintf(ctx, "%s\\%s", REG_SORTED_SUBKEYS_PREFIX,
-                                 keyname);
-       if (keyname == NULL) {
-               werr = WERR_NOMEM;
-               goto done;
-       }
-
-       werr = ntstatus_to_werror(dbwrap_delete_bystring(db, keyname));
-
-       /* don't treat WERR_NOT_FOUND as an error here */
-       if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
-               werr = WERR_OK;
-       }
+       werr = ntstatus_to_werror(create_sorted_subkeys(keyname));
 
 done:
        TALLOC_FREE(ctx);
@@ -1313,7 +1301,7 @@ done:
 
 static int cmp_keynames(char **p1, char **p2)
 {
-       return StrCaseCmp(*p1, *p2);
+       return strcasecmp_m(*p1, *p2);
 }
 
 struct create_sorted_subkeys_context {
@@ -1410,7 +1398,8 @@ done:
        return status;
 }
 
-static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
+static NTSTATUS create_sorted_subkeys_internal(const char *key,
+                                              const char *sorted_keyname)
 {
        NTSTATUS status;
        struct create_sorted_subkeys_context sorted_ctx;
@@ -1422,7 +1411,26 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
                                 create_sorted_subkeys_action,
                                 &sorted_ctx);
 
-       return NT_STATUS_IS_OK(status);
+       return status;
+}
+
+static NTSTATUS create_sorted_subkeys(const char *key)
+{
+       char *sorted_subkeys_keyname;
+       NTSTATUS status;
+
+       sorted_subkeys_keyname = talloc_asprintf(talloc_tos(), "%s\\%s",
+                                                REG_SORTED_SUBKEYS_PREFIX,
+                                                key);
+       if (sorted_subkeys_keyname == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       status = create_sorted_subkeys_internal(key, sorted_subkeys_keyname);
+
+done:
+       return status;
 }
 
 struct scan_subkey_state {
@@ -1502,13 +1510,21 @@ static bool scan_parent_subkeys(struct db_context *db, const char *parent,
        if (state.scanned) {
                result = state.found;
        } else {
+               NTSTATUS status;
+
                res = db->transaction_start(db);
                if (res != 0) {
-                       DEBUG(0, ("error starting transacion\n"));
+                       DEBUG(0, ("error starting transaction\n"));
                        goto fail;
                }
 
-               if (!create_sorted_subkeys(path, key)) {
+               DEBUG(2, (__location__ " WARNING: recreating the sorted "
+                         "subkeys cache for key '%s' from scan_parent_subkeys "
+                         "this should not happen (too frequently)...\n",
+                         path));
+
+               status = create_sorted_subkeys_internal(path, key);
+               if (!NT_STATUS_IS_OK(status)) {
                        res = db->transaction_cancel(db);
                        if (res != 0) {
                                smb_panic("Failed to cancel transaction.");
@@ -1599,8 +1615,6 @@ static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
 
        DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
 
-       frame = talloc_stackframe();
-
        if (!regdb_key_exists(db, key)) {
                DEBUG(10, ("key [%s] not found\n", key));
                werr = WERR_NOT_FOUND;
@@ -1690,12 +1704,8 @@ static int regdb_unpack_values(struct regval_ctr *values, uint8 *buf, int buflen
                                  &size,
                                  &data_p);
 
-               /* add the new value. Paranoid protective code -- make sure data_p is valid */
-
-               if (size && data_p) {
-                       regval_ctr_addvalue(values, valuename, type,
-                                       (uint8_t *)data_p, size);
-               }
+               regval_ctr_addvalue(values, valuename, type,
+                               (uint8_t *)data_p, size);
                SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */
 
                DEBUG(8,("specific: [%s], len: %d\n", valuename, size));
@@ -1810,7 +1820,7 @@ static bool regdb_store_values_internal(struct db_context *db, const char *key,
                goto done;
        }
 
-       data.dptr = TALLOC_ARRAY(ctx, uint8, len);
+       data.dptr = talloc_array(ctx, uint8, len);
        data.dsize = len;
 
        len = regdb_pack_values(values, data.dptr, data.dsize);
@@ -1952,10 +1962,10 @@ bool regdb_values_need_update(struct regval_ctr *values)
        return (regdb_get_seqnum() != regval_ctr_get_seqnum(values));
 }
 
-/* 
+/*
  * Table of function pointers for default access
  */
+
 struct registry_ops regdb_ops = {
        .fetch_subkeys = regdb_fetch_keys,
        .fetch_values = regdb_fetch_values,