s3: registry: fix query empty valuenames
[amitay/samba.git] / source3 / registry / reg_backend_db.c
index 7825edd5c252689597911b78c41b326a59a89ac3..278359fa74f544e505fb9cf339af1f0577818893 100644 (file)
@@ -2,6 +2,7 @@
  *  Unix SMB/CIFS implementation.
  *  Virtual Windows Registry Layer
  *  Copyright (C) Gerald Carter                     2002-2005
+ *  Copyright (C) Michael Adam                      2007-2009
  *
  *  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
@@ -20,6 +21,8 @@
 /* Implementation of internal registry database functions. */
 
 #include "includes.h"
+#include "registry.h"
+#include "reg_db.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
@@ -64,7 +67,7 @@ static const char *builtin_registry_paths[] = {
        KEY_HKCU,
        KEY_GP_USER_POLICY,
        KEY_GP_USER_WIN_POLICY,
-       KEY_WINLOGON_GPEXT_PATH,
+       "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions",
        "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors",
        KEY_PROD_OPTIONS,
        "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration",
@@ -249,8 +252,6 @@ WERROR init_registry_key(const char *add_path)
 static void regdb_ctr_add_value(struct regval_ctr *ctr,
                                struct builtin_regkey_value *value)
 {
-       UNISTR2 data;
-
        switch(value->type) {
        case REG_DWORD:
                regval_ctr_addvalue(ctr, value->valuename, REG_DWORD,
@@ -259,10 +260,8 @@ static void regdb_ctr_add_value(struct regval_ctr *ctr,
                break;
 
        case REG_SZ:
-               init_unistr2(&data, value->data.string, UNI_STR_TERMINATE);
-               regval_ctr_addvalue(ctr, value->valuename, REG_SZ,
-                                   (char*)data.buffer,
-                                   data.uni_str_len*sizeof(uint16));
+               regval_ctr_addvalue_sz(ctr, value->valuename,
+                                      value->data.string);
                break;
 
        default:
@@ -1180,9 +1179,9 @@ done:
  * recreated on demand.
  */
 
-static int cmp_keynames(const void *p1, const void *p2)
+static int cmp_keynames(char **p1, char **p2)
 {
-       return StrCaseCmp(*((char **)p1), *((char **)p2));
+       return StrCaseCmp(*p1, *p2);
 }
 
 struct create_sorted_subkeys_context {
@@ -1251,7 +1250,7 @@ static NTSTATUS create_sorted_subkeys_action(struct db_context *db,
                len += strlen(sorted_subkeys[i])+1;
        }
 
-       qsort(sorted_subkeys, num_subkeys, sizeof(char *), cmp_keynames);
+       TYPESAFE_QSORT(sorted_subkeys, num_subkeys, cmp_keynames);
 
        buf = talloc_array(ctr, char, len);
        if (buf == NULL) {
@@ -1371,14 +1370,31 @@ static bool scan_parent_subkeys(struct db_context *db, const char *parent,
        if (state.scanned) {
                result = state.found;
        } else {
+               res = db->transaction_start(db);
+               if (res != 0) {
+                       DEBUG(0, ("error starting transacion\n"));
+                       goto fail;
+               }
+
                if (!create_sorted_subkeys(path, key)) {
+                       res = db->transaction_cancel(db);
+                       if (res != 0) {
+                               smb_panic("Failed to cancel transaction.");
+                       }
                        goto fail;
                }
+
                res = db->parse_record(db, string_term_tdb_data(key),
                                       parent_subkey_scanner, &state);
                if ((res == 0) && (state.scanned)) {
                        result = state.found;
                }
+
+               res = db->transaction_commit(db);
+               if (res != 0) {
+                       DEBUG(0, ("error committing transaction\n"));
+                       result = false;
+               }
        }
 
  fail:
@@ -1464,7 +1480,7 @@ static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
 
        value = regdb_fetch_key_internal(db, frame, key);
 
-       if (value.dptr == NULL) {
+       if (value.dsize == 0 || value.dptr == NULL) {
                DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
                           key));
                goto done;
@@ -1473,6 +1489,13 @@ static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
        buf = value.dptr;
        buflen = value.dsize;
        len = tdb_unpack( buf, buflen, "d", &num_items);
+       if (len == (uint32_t)-1) {
+               werr = WERR_NOT_FOUND;
+               goto done;
+       }
+
+       werr = regsubkey_ctr_reinit(ctr);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
 
        for (i=0; i<num_items; i++) {
                len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
@@ -1537,7 +1560,7 @@ static int regdb_unpack_values(struct regval_ctr *values, uint8 *buf, int buflen
 
                /* add the new value. Paranoid protective code -- make sure data_p is valid */
 
-               if (*valuename && size && data_p) {
+               if (size && data_p) {
                        regval_ctr_addvalue(values, valuename, type,
                                        (const char *)data_p, size);
                }