lib: directory_create_or_exist() does not use "uid" parameter
[amitay/samba.git] / source3 / registry / reg_perfcount.c
index 28cbec51fae5156ecc566085439a1640cebfa833..b875067721d1d880994fb451a162e2123f648527 100644 (file)
  */
 
 #include "includes.h"
+#include "system/filesys.h"
+#include "../librpc/gen_ndr/perfcount.h"
+#include "registry.h"
+#include "reg_perfcount.h"
+#include "../libcli/registry/util_reg.h"
+#include "util_tdb.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
@@ -30,7 +36,7 @@
 #define NAMES_DB       "names.tdb"
 #define DATA_DB                "data.tdb"
 
-PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind);
+struct PERF_OBJECT_TYPE *_reg_perfcount_find_obj(struct PERF_DATA_BLOCK *block, int objind);
 
 /*********************************************************************
 *********************************************************************/
@@ -41,8 +47,10 @@ static char *counters_directory(const char *dbname)
        char *ret = NULL;
        TALLOC_CTX *ctx = talloc_tos();
 
-       if (!dbname)
+       path = state_path(PERFCOUNTDIR);
+       if (!directory_create_or_exist(path, 0755)) {
                return NULL;
+       }
 
        path = talloc_asprintf(ctx, "%s/%s", PERFCOUNTDIR, dbname);
        if (!path) {
@@ -57,21 +65,6 @@ static char *counters_directory(const char *dbname)
 /*********************************************************************
 *********************************************************************/
 
-void perfcount_init_keys( void )
-{
-       char *p = state_path(PERFCOUNTDIR);
-
-       /* no registry keys; just create the perfmon directory */
-
-       if ( !directory_exist( p ) )
-               mkdir( p, 0755 );
-
-       return;
-}
-
-/*********************************************************************
-*********************************************************************/
-
 uint32 reg_perfcount_get_base_index(void)
 {
        const char *fname = counters_directory( NAMES_DB );
@@ -84,7 +77,7 @@ uint32 reg_perfcount_get_base_index(void)
        names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
 
        if ( !names ) {
-               DEBUG(1, ("reg_perfcount_get_base_index: unable to open [%s].\n", fname));
+               DEBUG(2, ("reg_perfcount_get_base_index: unable to open [%s].\n", fname));
                return 0;
        }    
        /* needs to read the value of key "1" from the counter_names.tdb file, as that is
@@ -102,7 +95,7 @@ uint32 reg_perfcount_get_base_index(void)
           and so on.
           So last_counter becomes num_counters*2, and last_help will be last_counter+1 */
        kbuf = string_tdb_data(key);
-       dbuf = tdb_fetch(names, kbuf);
+       dbuf = tdb_fetch_compat(names, kbuf);
        if(dbuf.dptr == NULL)
        {
                DEBUG(1, ("reg_perfcount_get_base_index: failed to find key \'1\' in [%s].\n", fname));
@@ -164,12 +157,13 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
        char temp[256];
        char *buf1 = *retbuf;
        uint32 working_size = 0;
-       UNISTR2 name_index, name;
+       DATA_BLOB name_index, name;
+       bool ok;
 
        memset(temp, 0, sizeof(temp));
        snprintf(temp, sizeof(temp), "%d", keyval);
        kbuf = string_tdb_data(temp);
-       dbuf = tdb_fetch(tdb, kbuf);
+       dbuf = tdb_fetch_compat(tdb, kbuf);
        if(dbuf.dptr == NULL)
        {
                /* If a key isn't there, just bypass it -- this really shouldn't 
@@ -185,8 +179,12 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
                buffer_size = 0;
                return buffer_size;
        }
-       init_unistr2(&name_index, (const char *)kbuf.dptr, UNI_STR_TERMINATE);
-       memcpy(buf1+buffer_size, (char *)name_index.buffer, working_size);
+       ok = push_reg_sz(talloc_tos(), &name_index, (const char *)kbuf.dptr);
+       if (!ok) {
+               buffer_size = 0;
+               return buffer_size;
+       }
+       memcpy(buf1+buffer_size, (char *)name_index.data, working_size);
        buffer_size += working_size;
        /* Now encode the actual name */
        working_size = (dbuf.dsize + 1)*sizeof(uint16);
@@ -198,8 +196,12 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
        memset(temp, 0, sizeof(temp));
        memcpy(temp, dbuf.dptr, dbuf.dsize);
        SAFE_FREE(dbuf.dptr);
-       init_unistr2(&name, temp, UNI_STR_TERMINATE);
-       memcpy(buf1+buffer_size, (char *)name.buffer, working_size);
+       ok = push_reg_sz(talloc_tos(), &name, temp);
+       if (!ok) {
+               buffer_size = 0;
+               return buffer_size;
+       }
+       memcpy(buf1+buffer_size, (char *)name.data, working_size);
        buffer_size += working_size;
 
        *retbuf = buf1;
@@ -354,7 +356,7 @@ static uint32 _reg_perfcount_get_numinst(int objInd, TDB_CONTEXT *names)
        char buf[PERFCOUNT_MAX_LEN];
 
        _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, objInd, "inst");
-       data = tdb_fetch(names, key);
+       data = tdb_fetch_compat(names, key);
 
        if(data.dptr == NULL)
                return (uint32)PERF_NO_INSTANCES;
@@ -368,24 +370,29 @@ static uint32 _reg_perfcount_get_numinst(int objInd, TDB_CONTEXT *names)
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
-                                     prs_struct *ps,
+static bool _reg_perfcount_add_instance(struct PERF_OBJECT_TYPE *obj,
+                                       TALLOC_CTX *mem_ctx,
+                                       int instInd,
+                                       TDB_CONTEXT *names);
+
+static bool _reg_perfcount_add_object(struct PERF_DATA_BLOCK *block,
+                                     TALLOC_CTX *mem_ctx,
                                      int num,
                                      TDB_DATA data,
                                      TDB_CONTEXT *names)
 {
        int i;
        bool success = True;
-       PERF_OBJECT_TYPE *obj;
+       struct PERF_OBJECT_TYPE *obj;
 
-       block->objects = (PERF_OBJECT_TYPE *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+       block->objects = (struct PERF_OBJECT_TYPE *)talloc_realloc(mem_ctx,
                                                                  block->objects,
-                                                                 PERF_OBJECT_TYPE,
+                                                                 struct PERF_OBJECT_TYPE,
                                                                  block->NumObjectTypes+1);
        if(block->objects == NULL)
                return False;
        obj = &(block->objects[block->NumObjectTypes]);
-       memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(PERF_OBJECT_TYPE));
+       memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(struct PERF_OBJECT_TYPE));
        block->objects[block->NumObjectTypes].ObjectNameTitleIndex = num;
        block->objects[block->NumObjectTypes].ObjectNameTitlePointer = 0;
        block->objects[block->NumObjectTypes].ObjectHelpTitleIndex = num+1;
@@ -401,7 +408,7 @@ static bool _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
        block->NumObjectTypes+=1;
 
        for(i = 0; i < (int)obj->NumInstances; i++) {
-               success = _reg_perfcount_add_instance(obj, ps, i, names);
+               success = _reg_perfcount_add_instance(obj, mem_ctx, i, names);
        }
 
        return success;
@@ -410,7 +417,7 @@ static bool _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
 /*********************************************************************
 *********************************************************************/
 
-bool _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data)
+static bool _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data)
 {
        TDB_CONTEXT *counters;
        const char *fname = counters_directory( DATA_DB );
@@ -423,7 +430,7 @@ bool _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data)
                return False;
        }    
 
-       *data = tdb_fetch(counters, key);
+       *data = tdb_fetch_compat(counters, key);
 
        tdb_close(counters);
 
@@ -472,10 +479,10 @@ static uint32 _reg_perfcount_compute_scale(int64_t data)
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
-                                           prs_struct *ps,
+static bool _reg_perfcount_get_counter_info(struct PERF_DATA_BLOCK *block,
+                                           TALLOC_CTX *mem_ctx,
                                            int CounterIndex,
-                                           PERF_OBJECT_TYPE *obj,
+                                           struct PERF_OBJECT_TYPE *obj,
                                            TDB_CONTEXT *names)
 {
        TDB_DATA key, data;
@@ -490,7 +497,7 @@ static bool _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
        padding = 0;
 
        _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "type");
-       data = tdb_fetch(names, key);
+       data = tdb_fetch_compat(names, key);
        if(data.dptr == NULL)
        {
                DEBUG(3, ("_reg_perfcount_get_counter_info: No type data for counter [%d].\n", CounterIndex));
@@ -549,7 +556,7 @@ static bool _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
        SAFE_FREE(data.dptr);
 
        obj->counter_data.ByteLength += dsize + padding;
-       obj->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+       obj->counter_data.data = talloc_realloc(mem_ctx,
                                                      obj->counter_data.data,
                                                      uint8,
                                                      obj->counter_data.ByteLength - sizeof(uint32));
@@ -581,11 +588,11 @@ static bool _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
 /*********************************************************************
 *********************************************************************/
 
-PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind)
+struct PERF_OBJECT_TYPE *_reg_perfcount_find_obj(struct PERF_DATA_BLOCK *block, int objind)
 {
        int i;
 
-       PERF_OBJECT_TYPE *obj = NULL;
+       struct PERF_OBJECT_TYPE *obj = NULL;
 
        for(i = 0; i < block->NumObjectTypes; i++)
        {
@@ -601,29 +608,29 @@ PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind)
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
-                                      prs_struct *ps,
+static bool _reg_perfcount_add_counter(struct PERF_DATA_BLOCK *block,
+                                      TALLOC_CTX *mem_ctx,
                                       int num,
                                       TDB_DATA data,
                                       TDB_CONTEXT *names)
 {
        char *begin, *end, *start, *stop;
        int parent;
-       PERF_OBJECT_TYPE *obj;
+       struct PERF_OBJECT_TYPE *obj;
        bool success = True;
        char buf[PERFCOUNT_MAX_LEN];
 
        obj = NULL;
        memset(buf, 0, PERFCOUNT_MAX_LEN);
        memcpy(buf, data.dptr, data.dsize);
-       begin = index(buf, '[');
-       end = index(buf, ']');
+       begin = strchr(buf, '[');
+       end = strchr(buf, ']');
        if(begin == NULL || end == NULL)
                return False;
        start = begin+1;
 
        while(start < end) {
-               stop = index(start, ',');
+               stop = strchr(start, ',');
                if(stop == NULL)
                        stop = end;
                *stop = '\0';
@@ -637,18 +644,18 @@ static bool _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
                                  parent, num));
                        return False;
                }
-               obj->counters = (PERF_COUNTER_DEFINITION *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+               obj->counters = (struct PERF_COUNTER_DEFINITION *)talloc_realloc(mem_ctx,
                                                                                obj->counters,
-                                                                               PERF_COUNTER_DEFINITION,
+                                                                               struct PERF_COUNTER_DEFINITION,
                                                                                obj->NumCounters+1);
                if(obj->counters == NULL)
                        return False;
-               memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(PERF_COUNTER_DEFINITION));
+               memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(struct PERF_COUNTER_DEFINITION));
                obj->counters[obj->NumCounters].CounterNameTitleIndex=num;
                obj->counters[obj->NumCounters].CounterHelpTitleIndex=num+1;
                obj->counters[obj->NumCounters].DetailLevel = PERF_DETAIL_NOVICE;
-               obj->counters[obj->NumCounters].ByteLength = sizeof(PERF_COUNTER_DEFINITION);
-               success = _reg_perfcount_get_counter_info(block, ps, num, obj, names);
+               obj->counters[obj->NumCounters].ByteLength = sizeof(struct PERF_COUNTER_DEFINITION);
+               success = _reg_perfcount_get_counter_info(block, mem_ctx, num, obj, names);
                obj->NumCounters += 1;
                start = stop + 1;
        }
@@ -663,11 +670,11 @@ static bool _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
 /*********************************************************************
 *********************************************************************/
 
-bool _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
-                                     prs_struct *ps,
-                                     int instId,
-                                     PERF_OBJECT_TYPE *obj,
-                                     TDB_CONTEXT *names)
+static bool _reg_perfcount_get_instance_info(struct PERF_INSTANCE_DEFINITION *inst,
+                                            TALLOC_CTX *mem_ctx,
+                                            int instId,
+                                            struct PERF_OBJECT_TYPE *obj,
+                                            TDB_CONTEXT *names)
 {
        TDB_DATA key, data;
        char buf[PERFCOUNT_MAX_LEN], temp[PERFCOUNT_MAX_LEN];
@@ -689,7 +696,7 @@ bool _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
                return False;
        }
        inst->counter_data.ByteLength = data.dsize + sizeof(inst->counter_data.ByteLength);
-       inst->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+       inst->counter_data.data = talloc_realloc(mem_ctx,
                                                       inst->counter_data.data,
                                                       uint8,
                                                       data.dsize);
@@ -703,7 +710,7 @@ bool _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
        memset(temp, 0, PERFCOUNT_MAX_LEN);
        snprintf(temp, PERFCOUNT_MAX_LEN, "i%dname", instId);
        _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
-       data = tdb_fetch(names, key);
+       data = tdb_fetch_compat(names, key);
        if(data.dptr == NULL)
        {
                /* Not actually an error, but possibly unintended? -- just logging FYI */
@@ -716,12 +723,12 @@ bool _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
                memset(buf, 0, PERFCOUNT_MAX_LEN);
                memcpy(buf, data.dptr, MIN(PERFCOUNT_MAX_LEN-1,data.dsize));
                buf[PERFCOUNT_MAX_LEN-1] = '\0';
-               inst->NameLength = rpcstr_push_talloc(ps->mem_ctx, &name, buf);
+               inst->NameLength = rpcstr_push_talloc(mem_ctx, &name, buf);
                if (inst->NameLength == (uint32_t)-1 || !name) {
                        SAFE_FREE(data.dptr);
                        return False;
                }
-               inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+               inst->data = talloc_realloc(mem_ctx,
                                                  inst->data,
                                                  uint8,
                                                  inst->NameLength);
@@ -743,7 +750,7 @@ bool _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
        if((pad = (inst->ByteLength % 8)))
        {
                pad = 8 - pad;
-               inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+               inst->data = talloc_realloc(mem_ctx,
                                                  inst->data,
                                                  uint8,
                                                  inst->NameLength + pad);
@@ -757,32 +764,32 @@ bool _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
 /*********************************************************************
 *********************************************************************/
 
-bool _reg_perfcount_add_instance(PERF_OBJECT_TYPE *obj,
-                                prs_struct *ps,
-                                int instInd,
-                                TDB_CONTEXT *names)
+static bool _reg_perfcount_add_instance(struct PERF_OBJECT_TYPE *obj,
+                                       TALLOC_CTX *mem_ctx,
+                                       int instInd,
+                                       TDB_CONTEXT *names)
 {
-       PERF_INSTANCE_DEFINITION *inst;
+       struct PERF_INSTANCE_DEFINITION *inst;
 
        if(obj->instances == NULL) {
-               obj->instances = TALLOC_REALLOC_ARRAY(ps->mem_ctx, 
+               obj->instances = talloc_realloc(mem_ctx,
                                                      obj->instances,
-                                                     PERF_INSTANCE_DEFINITION,
+                                                     struct PERF_INSTANCE_DEFINITION,
                                                      obj->NumInstances);
        }
        if(obj->instances == NULL)
                return False;
 
-       memset(&(obj->instances[instInd]), 0, sizeof(PERF_INSTANCE_DEFINITION));
+       memset(&(obj->instances[instInd]), 0, sizeof(struct PERF_INSTANCE_DEFINITION));
        inst = &(obj->instances[instInd]);
-       return _reg_perfcount_get_instance_info(inst, ps, instInd, obj, names);
+       return _reg_perfcount_get_instance_info(inst, mem_ctx, instInd, obj, names);
 }
 
 /*********************************************************************
 *********************************************************************/
 
-static int _reg_perfcount_assemble_global(PERF_DATA_BLOCK *block,
-                                         prs_struct *ps,
+static int _reg_perfcount_assemble_global(struct PERF_DATA_BLOCK *block,
+                                         TALLOC_CTX *mem_ctx,
                                          int base_index,
                                          TDB_CONTEXT *names)
 {
@@ -795,13 +802,13 @@ static int _reg_perfcount_assemble_global(PERF_DATA_BLOCK *block,
        {
                j = i*2;
                _reg_perfcount_make_key(&key, keybuf, PERFCOUNT_MAX_LEN, j, "rel");
-               data = tdb_fetch(names, key);
+               data = tdb_fetch_compat(names, key);
                if(data.dptr != NULL)
                {
                        if(_reg_perfcount_isparent(data))
-                               success = _reg_perfcount_add_object(block, ps, j, data, names);
+                               success = _reg_perfcount_add_object(block, mem_ctx, j, data, names);
                        else if(_reg_perfcount_ischild(data))
-                               success = _reg_perfcount_add_counter(block, ps, j, data, names);
+                               success = _reg_perfcount_add_counter(block, mem_ctx, j, data, names);
                        else
                        {
                                DEBUG(3, ("Bogus relationship [%s] for counter [%d].\n", data.dptr, j));
@@ -833,7 +840,7 @@ static bool _reg_perfcount_get_64(uint64_t *retval,
 
        _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, key_part1, key_part2);
 
-       data = tdb_fetch(tdb, key);
+       data = tdb_fetch_compat(tdb, key);
        if(data.dptr == NULL)
        {
                DEBUG(3,("_reg_perfcount_get_64: No data found for key [%s].\n", key.dptr));
@@ -852,7 +859,7 @@ static bool _reg_perfcount_get_64(uint64_t *retval,
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_init_data_block_perf(PERF_DATA_BLOCK *block,
+static bool _reg_perfcount_init_data_block_perf(struct PERF_DATA_BLOCK *block,
                                                TDB_CONTEXT *names)
 {
        uint64_t PerfFreq, PerfTime, PerfTime100nSec;
@@ -896,24 +903,42 @@ static bool _reg_perfcount_init_data_block_perf(PERF_DATA_BLOCK *block,
        return True;
 }
 
+/*******************************************************************
+********************************************************************/
+
+static bool make_systemtime(struct SYSTEMTIME *systime, struct tm *unixtime)
+{
+       systime->year=unixtime->tm_year+1900;
+       systime->month=unixtime->tm_mon+1;
+       systime->dayofweek=unixtime->tm_wday;
+       systime->day=unixtime->tm_mday;
+       systime->hour=unixtime->tm_hour;
+       systime->minute=unixtime->tm_min;
+       systime->second=unixtime->tm_sec;
+       systime->milliseconds=0;
+
+       return True;
+}
+
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_init_data_block(PERF_DATA_BLOCK *block,
-                                          prs_struct *ps, TDB_CONTEXT *names)
+static bool _reg_perfcount_init_data_block(struct PERF_DATA_BLOCK *block,
+                                          TALLOC_CTX *mem_ctx, TDB_CONTEXT *names,
+                                          bool bigendian_data)
 {
        smb_ucs2_t *temp = NULL;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
        time_t tm;
+       size_t sz;
 
-       if (rpcstr_push_talloc(ps->mem_ctx, &temp, "PERF")==(size_t)-1) {
-               return false;
-       }
-       if (!temp) {
-               return false;
+       sz = rpcstr_push_talloc(tmp_ctx, &temp, "PERF");
+       if ((sz == -1) || (temp == NULL)) {
+               goto err_out;
        }
        memcpy(block->Signature, temp, strlen_w(temp) *2);
 
-       if(ps->bigendian_data == RPC_BIG_ENDIAN)
+       if(bigendian_data)
                block->LittleEndian = 0;
        else
                block->LittleEndian = 1;
@@ -926,33 +951,41 @@ static bool _reg_perfcount_init_data_block(PERF_DATA_BLOCK *block,
        tm = time(NULL);
        make_systemtime(&(block->SystemTime), gmtime(&tm));
        _reg_perfcount_init_data_block_perf(block, names);
-       memset(temp, 0, sizeof(temp));
-       rpcstr_push((void *)temp, global_myname(), sizeof(temp), STR_TERMINATE);
+
+       sz = rpcstr_push_talloc(tmp_ctx, &temp, lp_netbios_name());
+       if ((sz == -1) || (temp == NULL)) {
+               goto err_out;
+       }
        block->SystemNameLength = (strlen_w(temp) * 2) + 2;
-       block->data = TALLOC_ZERO_ARRAY(ps->mem_ctx, uint8, block->SystemNameLength + (8 - (block->SystemNameLength % 8)));
+       block->data = talloc_zero_array(mem_ctx, uint8, block->SystemNameLength + (8 - (block->SystemNameLength % 8)));
        if (block->data == NULL) {
-               return False;
+               goto err_out;
        }
        memcpy(block->data, temp, block->SystemNameLength);
-       block->SystemNameOffset = sizeof(PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data); 
+       block->SystemNameOffset = sizeof(struct PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data);
        block->HeaderLength = block->SystemNameOffset + block->SystemNameLength;
        /* Make sure to adjust for 64-bit alignment for when we finish writing the system name,
           so that the PERF_OBJECT_TYPE struct comes out 64-bit aligned */
        block->HeaderLength += 8 - (block->HeaderLength % 8);
+       talloc_free(tmp_ctx);
 
-       return True;
+       return true;
+
+err_out:
+       talloc_free(tmp_ctx);
+       return false;
 }
 
 /*********************************************************************
 *********************************************************************/
 
-static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_struct *ps)
+static uint32 _reg_perfcount_perf_data_block_fixup(struct PERF_DATA_BLOCK *block, TALLOC_CTX *mem_ctx)
 {
        int obj, cnt, inst, pad, i;
-       PERF_OBJECT_TYPE *object;
-       PERF_INSTANCE_DEFINITION *instance;
-       PERF_COUNTER_DEFINITION *counter;
-       PERF_COUNTER_BLOCK *counter_data;
+       struct PERF_OBJECT_TYPE *object;
+       struct PERF_INSTANCE_DEFINITION *instance;
+       struct PERF_COUNTER_DEFINITION *counter;
+       struct PERF_COUNTER_BLOCK *counter_data;
        char *temp = NULL, *src_addr, *dst_addr;
 
        block->TotalByteLength = 0;
@@ -977,7 +1010,7 @@ static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_s
                                counter_data = &(instance->counter_data);
                                counter = &(object[obj].counters[object[obj].NumCounters - 1]);
                                counter_data->ByteLength = counter->CounterOffset + counter->CounterSize + sizeof(counter_data->ByteLength);
-                               temp = TALLOC_REALLOC_ARRAY(ps->mem_ctx, 
+                               temp = talloc_realloc(mem_ctx,
                                                            temp, 
                                                            char, 
                                                            counter_data->ByteLength- sizeof(counter_data->ByteLength));
@@ -998,7 +1031,7 @@ static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_s
                                {
                                        pad = 8 - pad;
                                }
-                               counter_data->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                               counter_data->data = talloc_realloc(mem_ctx,
                                                                         counter_data->data,
                                                                         uint8,
                                                                         counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
@@ -1018,7 +1051,7 @@ static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_s
                        if((pad = (object[obj].counter_data.ByteLength % 8)))
                        {
                                pad = 8 - pad;
-                               object[obj].counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, 
+                               object[obj].counter_data.data = talloc_realloc(mem_ctx,
                                                                                     object[obj].counter_data.data,
                                                                                     uint8, 
                                                                                     object[obj].counter_data.ByteLength + pad);
@@ -1027,7 +1060,7 @@ static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_s
                        }
                        object[obj].TotalByteLength += object[obj].counter_data.ByteLength;
                }
-               object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(PERF_COUNTER_BLOCK));
+               object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(struct PERF_COUNTER_BLOCK));
                object[obj].TotalByteLength += object[obj].HeaderLength;
                object[obj].DefinitionLength += object[obj].HeaderLength;
 
@@ -1040,10 +1073,11 @@ static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_s
 /*********************************************************************
 *********************************************************************/
 
-uint32 reg_perfcount_get_perf_data_block(uint32 base_index, 
-                                        prs_struct *ps, 
-                                        PERF_DATA_BLOCK *block,
-                                        const char *object_ids)
+static uint32 reg_perfcount_get_perf_data_block(uint32 base_index,
+                                               TALLOC_CTX *mem_ctx,
+                                               struct PERF_DATA_BLOCK *block,
+                                               const char *object_ids,
+                                               bool bigendian_data)
 {
        uint32 buffer_size = 0;
        const char *fname = counters_directory( NAMES_DB );
@@ -1058,7 +1092,7 @@ uint32 reg_perfcount_get_perf_data_block(uint32 base_index,
                return 0;
        }
 
-       if (!_reg_perfcount_init_data_block(block, ps, names)) {
+       if (!_reg_perfcount_init_data_block(block, mem_ctx, names, bigendian_data)) {
                DEBUG(0, ("_reg_perfcount_init_data_block failed\n"));
                tdb_close(names);
                return 0;
@@ -1069,14 +1103,14 @@ uint32 reg_perfcount_get_perf_data_block(uint32 base_index,
        if(object_ids == NULL)
        {
                /* we're getting a request for "Global" here */
-               retval = _reg_perfcount_assemble_global(block, ps, base_index, names);
+               retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names);
        }
        else
        {
                /* we're getting a request for a specific set of PERF_OBJECT_TYPES */
-               retval = _reg_perfcount_assemble_global(block, ps, base_index, names);
+               retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names);
        }
-       buffer_size = _reg_perfcount_perf_data_block_fixup(block, ps);
+       buffer_size = _reg_perfcount_perf_data_block_fixup(block, mem_ctx);
 
        tdb_close(names);
 
@@ -1087,10 +1121,35 @@ uint32 reg_perfcount_get_perf_data_block(uint32 base_index,
        return buffer_size + block->HeaderLength;
 }
 
+/*******************************************************************
+********************************************************************/
+
+static bool smb_io_system_time(const char *desc, prs_struct *ps, int depth, struct SYSTEMTIME *systime)
+{
+       if(!prs_uint16("year", ps, depth, &systime->year))
+               return False;
+       if(!prs_uint16("month", ps, depth, &systime->month))
+               return False;
+       if(!prs_uint16("dayofweek", ps, depth, &systime->dayofweek))
+               return False;
+       if(!prs_uint16("day", ps, depth, &systime->day))
+               return False;
+       if(!prs_uint16("hour", ps, depth, &systime->hour))
+               return False;
+       if(!prs_uint16("minute", ps, depth, &systime->minute))
+               return False;
+       if(!prs_uint16("second", ps, depth, &systime->second))
+               return False;
+       if(!prs_uint16("milliseconds", ps, depth, &systime->milliseconds))
+               return False;
+
+       return True;
+}
+
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_marshall_perf_data_block(prs_struct *ps, PERF_DATA_BLOCK block, int depth)
+static bool _reg_perfcount_marshall_perf_data_block(prs_struct *ps, struct PERF_DATA_BLOCK block, int depth)
 {
        int i;
        prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_data_block");
@@ -1117,7 +1176,7 @@ static bool _reg_perfcount_marshall_perf_data_block(prs_struct *ps, PERF_DATA_BL
                return False;
        if(!prs_uint32("DefaultObject", ps, depth, &block.DefaultObject))
                return False;
-       if(!spoolss_io_system_time("SystemTime", ps, depth, &block.SystemTime))
+       if(!smb_io_system_time("SystemTime", ps, depth, &block.SystemTime))
                return False;
        if(!prs_uint32("Padding", ps, depth, &block.Padding))
                return False;
@@ -1145,11 +1204,11 @@ static bool _reg_perfcount_marshall_perf_data_block(prs_struct *ps, PERF_DATA_BL
 *********************************************************************/
 
 static bool _reg_perfcount_marshall_perf_counters(prs_struct *ps,
-                                                 PERF_OBJECT_TYPE object,
+                                                 struct PERF_OBJECT_TYPE object,
                                                  int depth)
 {
        int cnt;
-       PERF_COUNTER_DEFINITION counter;
+       struct PERF_COUNTER_DEFINITION counter;
 
        prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counters");
        depth++;
@@ -1189,7 +1248,7 @@ static bool _reg_perfcount_marshall_perf_counters(prs_struct *ps,
 *********************************************************************/
 
 static bool _reg_perfcount_marshall_perf_counter_data(prs_struct *ps, 
-                                                     PERF_COUNTER_BLOCK counter_data, 
+                                                     struct PERF_COUNTER_BLOCK counter_data,
                                                      int depth)
 {
        prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counter_data");
@@ -1212,10 +1271,10 @@ static bool _reg_perfcount_marshall_perf_counter_data(prs_struct *ps,
 *********************************************************************/
 
 static bool _reg_perfcount_marshall_perf_instances(prs_struct *ps,
-                                                  PERF_OBJECT_TYPE object, 
+                                                  struct PERF_OBJECT_TYPE object,
                                                   int depth)
 {
-       PERF_INSTANCE_DEFINITION instance;
+       struct PERF_INSTANCE_DEFINITION instance;
        int inst;
 
        prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_instances");
@@ -1252,11 +1311,11 @@ static bool _reg_perfcount_marshall_perf_instances(prs_struct *ps,
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_marshall_perf_objects(prs_struct *ps, PERF_DATA_BLOCK block, int depth)
+static bool _reg_perfcount_marshall_perf_objects(prs_struct *ps, struct PERF_DATA_BLOCK block, int depth)
 {
        int obj;
 
-       PERF_OBJECT_TYPE object;
+       struct PERF_OBJECT_TYPE object;
 
        prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_objects");
        depth++;
@@ -1322,20 +1381,6 @@ static bool _reg_perfcount_marshall_perf_objects(prs_struct *ps, PERF_DATA_BLOCK
 /*********************************************************************
 *********************************************************************/
 
-static bool _reg_perfcount_marshall_hkpd(prs_struct *ps, PERF_DATA_BLOCK block)
-{
-       int depth = 0;
-       if(_reg_perfcount_marshall_perf_data_block(ps, block, depth) == True)
-       {
-               if(_reg_perfcount_marshall_perf_objects(ps, block, depth) == True)
-                       return True;
-       }
-       return False;
-}
-
-/*********************************************************************
-*********************************************************************/
-
 WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32 max_buf_size, uint32 *outbuf_len, const char *object_ids)
 {
        /*
@@ -1346,27 +1391,33 @@ WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32 max_buf_size, uint32 *outbu
         * promising under
         * http://msdn2.microsoft.com/en-us/library/aa373105.aspx -- vl
         */
-       PERF_DATA_BLOCK block;
+       struct PERF_DATA_BLOCK block;
        uint32 buffer_size, base_index; 
 
        buffer_size = 0;
        base_index = reg_perfcount_get_base_index();
        ZERO_STRUCT(block);
 
-       buffer_size = reg_perfcount_get_perf_data_block(base_index, ps, &block, object_ids);
+       buffer_size = reg_perfcount_get_perf_data_block(base_index, ps->mem_ctx, &block, object_ids, ps->bigendian_data);
 
        if(buffer_size < max_buf_size)
        {
                *outbuf_len = buffer_size;
-               if(_reg_perfcount_marshall_hkpd(ps, block) == True)
-                       return WERR_OK;
-               else
+
+               if (!_reg_perfcount_marshall_perf_data_block(ps, block, 0))
+                       return WERR_NOMEM;
+
+               if (!_reg_perfcount_marshall_perf_objects(ps, block, 0))
                        return WERR_NOMEM;
+
+               return WERR_OK;
        }
        else
        {
                *outbuf_len = max_buf_size;
-               _reg_perfcount_marshall_perf_data_block(ps, block, 0);
+               if (!_reg_perfcount_marshall_perf_data_block(ps, block, 0))
+                       return WERR_NOMEM;
+
                return WERR_INSUFFICIENT_BUFFER;
        }
 }