LCOV - code coverage report
Current view: top level - source3/registry - reg_perfcount.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 0 801 0.0 %
Date: 2024-05-31 13:13:24 Functions: 0 34 0.0 %

          Line data    Source code
       1             : /* 
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  Virtual Windows Registry Layer
       4             :  *
       5             :  *  Copyright (C) Marcin Krzysztof Porwit    2005,
       6             :  *  Copyright (C) Gerald (Jerry) Carter      2005.
       7             :  *  
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *  
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *  
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/filesys.h"
      24             : #include "../librpc/gen_ndr/perfcount.h"
      25             : #include "registry.h"
      26             : #include "reg_perfcount.h"
      27             : #include "../libcli/registry/util_reg.h"
      28             : #include "util_tdb.h"
      29             : 
      30             : #undef DBGC_CLASS
      31             : #define DBGC_CLASS DBGC_REGISTRY
      32             : 
      33             : #define PERFCOUNT_MAX_LEN 256
      34             : 
      35             : #define PERFCOUNTDIR    "perfmon"
      36             : #define NAMES_DB        "names.tdb"
      37             : #define DATA_DB         "data.tdb"
      38             : 
      39             : struct PERF_OBJECT_TYPE *_reg_perfcount_find_obj(struct PERF_DATA_BLOCK *block, int objind);
      40             : 
      41             : /*********************************************************************
      42             : *********************************************************************/
      43             : 
      44             : /* returns perfcount path for dbname allocated on talloc_tos */
      45           0 : static char *counters_directory(const char *dbname)
      46             : {
      47           0 :         char *dir_path = NULL;
      48           0 :         char *db_subpath = NULL;
      49           0 :         char *ret = NULL;
      50             : 
      51           0 :         dir_path = state_path(talloc_tos(), PERFCOUNTDIR);
      52           0 :         if (dir_path == NULL) {
      53           0 :                 return NULL;
      54             :         }
      55             : 
      56           0 :         if (!directory_create_or_exist(dir_path, 0755)) {
      57           0 :                 TALLOC_FREE(dir_path);
      58           0 :                 return NULL;
      59             :         }
      60             : 
      61           0 :         db_subpath = talloc_asprintf(dir_path, "%s/%s", PERFCOUNTDIR, dbname);
      62           0 :         if (db_subpath == NULL) {
      63           0 :                 TALLOC_FREE(dir_path);
      64           0 :                 return NULL;
      65             :         }
      66             : 
      67           0 :         ret = state_path(talloc_tos(), db_subpath);
      68           0 :         TALLOC_FREE(dir_path);
      69           0 :         return ret;
      70             : }
      71             : 
      72             : /*********************************************************************
      73             : *********************************************************************/
      74             : 
      75           0 : uint32_t reg_perfcount_get_base_index(void)
      76             : {
      77           0 :         char *fname;
      78           0 :         TDB_CONTEXT *names;
      79           0 :         TDB_DATA kbuf, dbuf;
      80           0 :         char key[] = "1";
      81           0 :         uint32_t retval = 0;
      82           0 :         char buf[PERFCOUNT_MAX_LEN];
      83             : 
      84           0 :         fname = counters_directory(NAMES_DB);
      85           0 :         if (fname == NULL) {
      86           0 :                 return 0;
      87             :         }
      88             : 
      89           0 :         names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
      90             : 
      91           0 :         if ( !names ) {
      92           0 :                 DEBUG(2, ("reg_perfcount_get_base_index: unable to open [%s].\n", fname));
      93           0 :                 TALLOC_FREE(fname);
      94           0 :                 return 0;
      95             :         }
      96             :         /* needs to read the value of key "1" from the counter_names.tdb file, as that is
      97             :            where the total number of counters is stored. We're assuming no holes in the
      98             :            enumeration.
      99             :            The format for the counter_names.tdb file is:
     100             :            key        value
     101             :            1          num_counters
     102             :            2          perf_counter1
     103             :            3          perf_counter1_help
     104             :            4          perf_counter2
     105             :            5          perf_counter2_help
     106             :            even_num   perf_counter<even_num>
     107             :            even_num+1 perf_counter<even_num>_help
     108             :            and so on.
     109             :            So last_counter becomes num_counters*2, and last_help will be last_counter+1 */
     110           0 :         kbuf = string_tdb_data(key);
     111           0 :         dbuf = tdb_fetch(names, kbuf);
     112           0 :         if(dbuf.dptr == NULL)
     113             :         {
     114           0 :                 DEBUG(1, ("reg_perfcount_get_base_index: failed to find key \'1\' in [%s].\n", fname));
     115           0 :                 tdb_close(names);
     116           0 :                 TALLOC_FREE(fname);
     117           0 :                 return 0;
     118             :         }
     119             : 
     120           0 :         tdb_close(names);
     121           0 :         TALLOC_FREE(fname);
     122           0 :         memset(buf, 0, PERFCOUNT_MAX_LEN);
     123           0 :         memcpy(buf, dbuf.dptr, dbuf.dsize);
     124           0 :         retval = (uint32_t)atoi(buf);
     125           0 :         SAFE_FREE(dbuf.dptr);
     126           0 :         return retval;
     127             : }
     128             : 
     129             : /*********************************************************************
     130             : *********************************************************************/
     131             : 
     132           0 : uint32_t reg_perfcount_get_last_counter(uint32_t base_index)
     133             : {
     134           0 :         uint32_t retval;
     135             : 
     136           0 :         if(base_index == 0)
     137           0 :                 retval = 0;
     138             :         else
     139           0 :                 retval = base_index * 2;
     140             : 
     141           0 :         return retval;
     142             : }
     143             : 
     144             : /*********************************************************************
     145             : *********************************************************************/
     146             : 
     147           0 : uint32_t reg_perfcount_get_last_help(uint32_t last_counter)
     148             : {
     149           0 :         uint32_t retval;
     150             : 
     151           0 :         if(last_counter == 0)
     152           0 :                 retval = 0;
     153             :         else
     154           0 :                 retval = last_counter + 1;
     155             : 
     156           0 :         return retval;
     157             : }
     158             : 
     159             : 
     160             : /*********************************************************************
     161             : *********************************************************************/
     162             : 
     163           0 : static uint32_t _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
     164             :                                                int keyval,
     165             :                                                char **retbuf,
     166             :                                                uint32_t buffer_size)
     167             : {
     168           0 :         TDB_DATA kbuf, dbuf;
     169           0 :         char temp[PERFCOUNT_MAX_LEN] = {0};
     170           0 :         char *buf1 = *retbuf;
     171           0 :         char *p = NULL;
     172           0 :         uint32_t working_size = 0;
     173           0 :         DATA_BLOB name_index, name;
     174           0 :         bool ok;
     175             : 
     176           0 :         snprintf(temp, sizeof(temp), "%d", keyval);
     177           0 :         kbuf = string_tdb_data(temp);
     178           0 :         dbuf = tdb_fetch(tdb, kbuf);
     179           0 :         if(dbuf.dptr == NULL)
     180             :         {
     181             :                 /* If a key isn't there, just bypass it -- this really shouldn't 
     182             :                    happen unless someone's mucking around with the tdb */
     183           0 :                 DEBUG(3, ("_reg_perfcount_multi_sz_from_tdb: failed to find key [%s] in [%s].\n",
     184             :                           temp, tdb_name(tdb)));
     185           0 :                 return buffer_size;
     186             :         }
     187             :         /* First encode the name_index */
     188           0 :         working_size = (kbuf.dsize + 1)*sizeof(uint16_t);
     189             :         /* SMB_REALLOC frees buf1 on error */
     190           0 :         p = (char *)SMB_REALLOC(buf1, buffer_size + working_size);
     191           0 :         if (p == NULL) {
     192           0 :                 buffer_size = 0;
     193           0 :                 return buffer_size;
     194             :         }
     195           0 :         buf1 = p;
     196           0 :         ok = push_reg_sz(talloc_tos(), &name_index, (const char *)kbuf.dptr);
     197           0 :         if (!ok) {
     198           0 :                 SAFE_FREE(buf1);
     199           0 :                 buffer_size = 0;
     200           0 :                 return buffer_size;
     201             :         }
     202           0 :         memcpy(buf1+buffer_size, (char *)name_index.data, working_size);
     203           0 :         buffer_size += working_size;
     204             :         /* Now encode the actual name */
     205           0 :         working_size = (dbuf.dsize + 1)*sizeof(uint16_t);
     206             :         /* SMB_REALLOC frees buf1 on error */
     207           0 :         p = (char *)SMB_REALLOC(buf1, buffer_size + working_size);
     208           0 :         if (p == NULL) {
     209           0 :                 buffer_size = 0;
     210           0 :                 return buffer_size;
     211             :         }
     212           0 :         buf1 = p;
     213           0 :         memset(temp, 0, sizeof(temp));
     214           0 :         memcpy(temp, dbuf.dptr, dbuf.dsize);
     215           0 :         SAFE_FREE(dbuf.dptr);
     216           0 :         ok = push_reg_sz(talloc_tos(), &name, temp);
     217           0 :         if (!ok) {
     218           0 :                 SAFE_FREE(buf1);
     219           0 :                 buffer_size = 0;
     220           0 :                 return buffer_size;
     221             :         }
     222           0 :         memcpy(buf1+buffer_size, (char *)name.data, working_size);
     223           0 :         buffer_size += working_size;
     224             : 
     225           0 :         *retbuf = buf1;
     226             : 
     227           0 :         return buffer_size;
     228             : }
     229             : 
     230             : /*********************************************************************
     231             : *********************************************************************/
     232             : 
     233           0 : uint32_t reg_perfcount_get_counter_help(uint32_t base_index, char **retbuf)
     234             : {
     235           0 :         char *buf1 = NULL;
     236           0 :         uint32_t buffer_size = 0;
     237           0 :         TDB_CONTEXT *names;
     238           0 :         char *fname;
     239           0 :         int i;
     240             : 
     241           0 :         if (base_index == 0) {
     242           0 :                 return 0;
     243             :         }
     244             : 
     245           0 :         fname = counters_directory(NAMES_DB);
     246           0 :         if (fname == NULL) {
     247           0 :                 return 0;
     248             :         }
     249             : 
     250           0 :         names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
     251             : 
     252           0 :         if (names == NULL) {
     253           0 :                 DEBUG(1, ("reg_perfcount_get_counter_help: unable to open [%s].\n", fname));
     254           0 :                 TALLOC_FREE(fname);
     255           0 :                 return 0;
     256             :         }
     257           0 :         TALLOC_FREE(fname);
     258             : 
     259           0 :         for(i = 1; i <= base_index; i++)
     260             :         {
     261           0 :                 buffer_size = _reg_perfcount_multi_sz_from_tdb(names, (i*2)+1, retbuf, buffer_size);
     262             :         }
     263           0 :         tdb_close(names);
     264             : 
     265             :         /* Now terminate the MULTI_SZ with a double unicode NULL */
     266           0 :         buf1 = *retbuf;
     267           0 :         buf1 = (char *)SMB_REALLOC(buf1, buffer_size + 2);
     268           0 :         if(!buf1) {
     269           0 :                 buffer_size = 0;
     270             :         } else {
     271           0 :                 buf1[buffer_size++] = '\0';
     272           0 :                 buf1[buffer_size++] = '\0';
     273             :         }
     274             : 
     275           0 :         *retbuf = buf1;
     276             : 
     277           0 :         return buffer_size;
     278             : }
     279             : 
     280             : /*********************************************************************
     281             : *********************************************************************/
     282             : 
     283           0 : uint32_t reg_perfcount_get_counter_names(uint32_t base_index, char **retbuf)
     284             : {
     285           0 :         char *buf1 = NULL;
     286           0 :         uint32_t buffer_size = 0;
     287           0 :         TDB_CONTEXT *names;
     288           0 :         char *fname;
     289           0 :         int i;
     290             : 
     291           0 :         if (base_index == 0) {
     292           0 :                 return 0;
     293             :         }
     294             : 
     295           0 :         fname = counters_directory(NAMES_DB);
     296           0 :         if (fname == NULL) {
     297           0 :                 return 0;
     298             :         }
     299             : 
     300           0 :         names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
     301             : 
     302           0 :         if (names == NULL) {
     303           0 :                 DEBUG(1, ("reg_perfcount_get_counter_names: unable to open [%s].\n", fname));
     304           0 :                 TALLOC_FREE(fname);
     305           0 :                 return 0;
     306             :         }
     307           0 :         TALLOC_FREE(fname);
     308             : 
     309           0 :         buffer_size = _reg_perfcount_multi_sz_from_tdb(names, 1, retbuf, buffer_size);
     310             : 
     311           0 :         for(i = 1; i <= base_index; i++)
     312             :         {
     313           0 :                 buffer_size = _reg_perfcount_multi_sz_from_tdb(names, i*2, retbuf, buffer_size);
     314             :         }
     315           0 :         tdb_close(names);
     316             : 
     317             :         /* Now terminate the MULTI_SZ with a double unicode NULL */
     318           0 :         buf1 = *retbuf;
     319           0 :         buf1 = (char *)SMB_REALLOC(buf1, buffer_size + 2);
     320           0 :         if(!buf1) {
     321           0 :                 buffer_size = 0;
     322             :         } else {
     323           0 :                 buf1[buffer_size++] = '\0';
     324           0 :                 buf1[buffer_size++] = '\0';
     325             :         }
     326             : 
     327           0 :         *retbuf=buf1;
     328             : 
     329           0 :         return buffer_size;
     330             : }
     331             : 
     332             : /*********************************************************************
     333             : *********************************************************************/
     334             : 
     335           0 : static void _reg_perfcount_make_key(TDB_DATA *key,
     336             :                                     char *buf,
     337             :                                     int buflen,
     338             :                                     int key_part1,
     339             :                                     const char *key_part2)
     340             : {
     341           0 :         memset(buf, 0, buflen);
     342           0 :         if(key_part2 != NULL)
     343           0 :                 snprintf(buf, buflen,"%d%s", key_part1, key_part2);
     344             :         else 
     345           0 :                 snprintf(buf, buflen, "%d", key_part1);
     346             : 
     347           0 :         *key = string_tdb_data(buf);
     348             : 
     349           0 :         return;
     350             : }
     351             : 
     352             : /*********************************************************************
     353             : *********************************************************************/
     354             : 
     355           0 : static bool _reg_perfcount_isparent(TDB_DATA data)
     356             : {
     357           0 :         if(data.dsize > 0)
     358             :         {
     359           0 :                 if(data.dptr[0] == 'p')
     360           0 :                         return True;
     361             :                 else
     362           0 :                         return False;
     363             :         }
     364           0 :         return False;
     365             : }
     366             : 
     367             : /*********************************************************************
     368             : *********************************************************************/
     369             : 
     370           0 : static bool _reg_perfcount_ischild(TDB_DATA data)
     371             : {
     372           0 :         if(data.dsize > 0)
     373             :         {
     374           0 :                 if(data.dptr[0] == 'c')
     375           0 :                         return True;
     376             :                 else
     377           0 :                         return False;
     378             :         }
     379           0 :         return False;
     380             : }
     381             : 
     382             : /*********************************************************************
     383             : *********************************************************************/
     384             : 
     385           0 : static uint32_t _reg_perfcount_get_numinst(int objInd, TDB_CONTEXT *names)
     386             : {
     387           0 :         TDB_DATA key, data;
     388           0 :         char buf[PERFCOUNT_MAX_LEN];
     389             : 
     390           0 :         _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, objInd, "inst");
     391           0 :         data = tdb_fetch(names, key);
     392             : 
     393           0 :         if(data.dptr == NULL)
     394           0 :                 return (uint32_t)PERF_NO_INSTANCES;
     395             : 
     396           0 :         memset(buf, 0, PERFCOUNT_MAX_LEN);
     397           0 :         memcpy(buf, data.dptr, data.dsize);
     398           0 :         SAFE_FREE(data.dptr);
     399           0 :         return (uint32_t)atoi(buf);
     400             : }
     401             : 
     402             : /*********************************************************************
     403             : *********************************************************************/
     404             : 
     405             : static bool _reg_perfcount_add_instance(struct PERF_OBJECT_TYPE *obj,
     406             :                                         TALLOC_CTX *mem_ctx,
     407             :                                         int instInd,
     408             :                                         TDB_CONTEXT *names);
     409             : 
     410           0 : static bool _reg_perfcount_add_object(struct PERF_DATA_BLOCK *block,
     411             :                                       TALLOC_CTX *mem_ctx,
     412             :                                       int num,
     413             :                                       TDB_DATA data,
     414             :                                       TDB_CONTEXT *names)
     415             : {
     416           0 :         int i;
     417           0 :         bool success = True;
     418           0 :         struct PERF_OBJECT_TYPE *obj;
     419             : 
     420           0 :         block->objects = (struct PERF_OBJECT_TYPE *)talloc_realloc(mem_ctx,
     421             :                                                                   block->objects,
     422             :                                                                   struct PERF_OBJECT_TYPE,
     423             :                                                                   block->NumObjectTypes+1);
     424           0 :         if(block->objects == NULL)
     425           0 :                 return False;
     426           0 :         obj = &(block->objects[block->NumObjectTypes]);
     427           0 :         memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(struct PERF_OBJECT_TYPE));
     428           0 :         block->objects[block->NumObjectTypes].ObjectNameTitleIndex = num;
     429           0 :         block->objects[block->NumObjectTypes].ObjectNameTitlePointer = 0;
     430           0 :         block->objects[block->NumObjectTypes].ObjectHelpTitleIndex = num+1;
     431           0 :         block->objects[block->NumObjectTypes].ObjectHelpTitlePointer = 0;
     432           0 :         block->objects[block->NumObjectTypes].NumCounters = 0;
     433           0 :         block->objects[block->NumObjectTypes].DefaultCounter = 0;
     434           0 :         block->objects[block->NumObjectTypes].NumInstances = _reg_perfcount_get_numinst(num, names);
     435           0 :         block->objects[block->NumObjectTypes].counters = NULL;
     436           0 :         block->objects[block->NumObjectTypes].instances = NULL;
     437           0 :         block->objects[block->NumObjectTypes].counter_data.ByteLength = sizeof(uint32_t);
     438           0 :         block->objects[block->NumObjectTypes].counter_data.data = NULL;
     439           0 :         block->objects[block->NumObjectTypes].DetailLevel = PERF_DETAIL_NOVICE;
     440           0 :         block->NumObjectTypes+=1;
     441             : 
     442           0 :         for(i = 0; i < (int)obj->NumInstances; i++) {
     443           0 :                 success = _reg_perfcount_add_instance(obj, mem_ctx, i, names);
     444             :         }
     445             : 
     446           0 :         return success;
     447             : }
     448             : 
     449             : /*********************************************************************
     450             : *********************************************************************/
     451             : 
     452           0 : static bool _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data)
     453             : {
     454           0 :         TDB_CONTEXT *counters;
     455           0 :         char *fname;
     456             : 
     457           0 :         fname = counters_directory(DATA_DB);
     458           0 :         if (fname == NULL) {
     459           0 :                 return false;
     460             :         }
     461             : 
     462           0 :         counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
     463             : 
     464           0 :         if (counters == NULL) {
     465           0 :                 DEBUG(1, ("reg_perfcount_get_counter_data: unable to open [%s].\n", fname));
     466           0 :                 TALLOC_FREE(fname);
     467           0 :                 return False;
     468             :         }
     469           0 :         TALLOC_FREE(fname);
     470             : 
     471           0 :         *data = tdb_fetch(counters, key);
     472             : 
     473           0 :         tdb_close(counters);
     474             : 
     475           0 :         return True;
     476             : }
     477             : 
     478             : /*********************************************************************
     479             : *********************************************************************/
     480             : 
     481           0 : static uint32_t _reg_perfcount_get_size_field(uint32_t CounterType)
     482             : {
     483           0 :         uint32_t retval;
     484             : 
     485           0 :         retval = CounterType;
     486             : 
     487             :         /* First mask out reserved lower 8 bits */
     488           0 :         retval = retval & 0xFFFFFF00;
     489           0 :         retval = retval << 22;
     490           0 :         retval = retval >> 22;
     491             : 
     492           0 :         return retval;
     493             : }
     494             : 
     495             : /*********************************************************************
     496             : *********************************************************************/
     497             : 
     498           0 : static uint32_t _reg_perfcount_compute_scale(int64_t data)
     499             : {
     500           0 :         int scale = 0;
     501           0 :         if(data == 0)
     502           0 :                 return scale;
     503           0 :         while(data > 100)
     504             :         {
     505           0 :                 data /= 10;
     506           0 :                 scale--;
     507             :         }
     508           0 :         while(data < 10)
     509             :         {
     510           0 :                 data *= 10;
     511           0 :                 scale++;
     512             :         }
     513             : 
     514           0 :         return (uint32_t)scale;
     515             : }
     516             : 
     517             : /*********************************************************************
     518             : *********************************************************************/
     519             : 
     520           0 : static bool _reg_perfcount_get_counter_info(struct PERF_DATA_BLOCK *block,
     521             :                                             TALLOC_CTX *mem_ctx,
     522             :                                             int CounterIndex,
     523             :                                             struct PERF_OBJECT_TYPE *obj,
     524             :                                             TDB_CONTEXT *names)
     525             : {
     526           0 :         TDB_DATA key, data;
     527           0 :         char buf[PERFCOUNT_MAX_LEN];
     528           0 :         size_t dsize, padding;
     529           0 :         long int data32, dbuf[2];
     530           0 :         int64_t data64;
     531           0 :         uint32_t counter_size;
     532             : 
     533           0 :         obj->counters[obj->NumCounters].DefaultScale = 0;
     534           0 :         dbuf[0] = dbuf[1] = 0;
     535           0 :         padding = 0;
     536             : 
     537           0 :         _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "type");
     538           0 :         data = tdb_fetch(names, key);
     539           0 :         if(data.dptr == NULL)
     540             :         {
     541           0 :                 DEBUG(3, ("_reg_perfcount_get_counter_info: No type data for counter [%d].\n", CounterIndex));
     542           0 :                 return False;
     543             :         }
     544           0 :         memset(buf, 0, PERFCOUNT_MAX_LEN);
     545           0 :         memcpy(buf, data.dptr, data.dsize);
     546           0 :         obj->counters[obj->NumCounters].CounterType = atoi(buf);
     547           0 :         DEBUG(10, ("_reg_perfcount_get_counter_info: Got type [%d] for counter [%d].\n",
     548             :                    obj->counters[obj->NumCounters].CounterType, CounterIndex));
     549           0 :         SAFE_FREE(data.dptr);
     550             : 
     551             :         /* Fetch the actual data */
     552           0 :         _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "");
     553           0 :         _reg_perfcount_get_counter_data(key, &data);
     554           0 :         if(data.dptr == NULL)
     555             :         {
     556           0 :                 DEBUG(3, ("_reg_perfcount_get_counter_info: No counter data for counter [%d].\n", CounterIndex));
     557           0 :                 return False;
     558             :         }
     559             : 
     560           0 :         counter_size = _reg_perfcount_get_size_field(obj->counters[obj->NumCounters].CounterType);
     561             : 
     562           0 :         if(counter_size == PERF_SIZE_DWORD)
     563             :         {
     564           0 :                 dsize = sizeof(data32);
     565           0 :                 memset(buf, 0, PERFCOUNT_MAX_LEN);
     566           0 :                 memcpy(buf, data.dptr, data.dsize);
     567           0 :                 data32 = strtol(buf, NULL, 0);
     568           0 :                 if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER)
     569           0 :                         obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale((int64_t)data32);
     570             :                 else
     571           0 :                         obj->counters[obj->NumCounters].DefaultScale = 0;
     572           0 :                 dbuf[0] = data32;
     573           0 :                 padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize;
     574             :         }
     575           0 :         else if(counter_size == PERF_SIZE_LARGE)
     576             :         {
     577           0 :                 dsize = sizeof(data64);
     578           0 :                 memset(buf, 0, PERFCOUNT_MAX_LEN);
     579           0 :                 memcpy(buf, data.dptr, data.dsize);
     580           0 :                 data64 = atof(buf);
     581           0 :                 if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER)
     582           0 :                         obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale(data64);
     583             :                 else
     584           0 :                         obj->counters[obj->NumCounters].DefaultScale = 0;
     585           0 :                 memcpy((void *)dbuf, (const void *)&data64, dsize);
     586           0 :                 padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize;
     587             :         }
     588             :         else /* PERF_SIZE_VARIABLE_LEN */
     589             :         {
     590           0 :                 dsize = data.dsize;
     591           0 :                 memset(buf, 0, PERFCOUNT_MAX_LEN);
     592           0 :                 memcpy(buf, data.dptr, data.dsize);
     593             :         }
     594           0 :         SAFE_FREE(data.dptr);
     595             : 
     596           0 :         obj->counter_data.ByteLength += dsize + padding;
     597           0 :         obj->counter_data.data = talloc_realloc(mem_ctx,
     598             :                                                       obj->counter_data.data,
     599             :                                                       uint8_t,
     600             :                                                       obj->counter_data.ByteLength - sizeof(uint32_t));
     601           0 :         if(obj->counter_data.data == NULL)
     602           0 :                 return False;
     603           0 :         if(dbuf[0] != 0 || dbuf[1] != 0)
     604             :         {
     605           0 :                 memcpy((void *)(obj->counter_data.data + 
     606           0 :                                 (obj->counter_data.ByteLength - (sizeof(uint32_t) + dsize))),
     607             :                        (const void *)dbuf, dsize);
     608             :         }
     609             :         else
     610             :         {
     611             :                 /* Handling PERF_SIZE_VARIABLE_LEN */
     612           0 :                 memcpy((void *)(obj->counter_data.data +
     613           0 :                                 (obj->counter_data.ByteLength - (sizeof(uint32_t) + dsize))),
     614             :                        (const void *)buf, dsize);
     615             :         }
     616           0 :         obj->counters[obj->NumCounters].CounterOffset = obj->counter_data.ByteLength - dsize;
     617           0 :         if(obj->counters[obj->NumCounters].CounterOffset % dsize != 0)
     618             :         {
     619           0 :                 DEBUG(3,("Improperly aligned counter [%d]\n", obj->NumCounters));
     620             :         }
     621           0 :         obj->counters[obj->NumCounters].CounterSize = dsize;
     622             : 
     623           0 :         return True;
     624             : }
     625             : 
     626             : /*********************************************************************
     627             : *********************************************************************/
     628             : 
     629           0 : struct PERF_OBJECT_TYPE *_reg_perfcount_find_obj(struct PERF_DATA_BLOCK *block, int objind)
     630             : {
     631           0 :         int i;
     632             : 
     633           0 :         struct PERF_OBJECT_TYPE *obj = NULL;
     634             : 
     635           0 :         for(i = 0; i < block->NumObjectTypes; i++)
     636             :         {
     637           0 :                 if(block->objects[i].ObjectNameTitleIndex == objind)
     638             :                 {
     639           0 :                         obj = &(block->objects[i]);
     640             :                 }
     641             :         }
     642             : 
     643           0 :         return obj;
     644             : }
     645             : 
     646             : /*********************************************************************
     647             : *********************************************************************/
     648             : 
     649           0 : static bool _reg_perfcount_add_counter(struct PERF_DATA_BLOCK *block,
     650             :                                        TALLOC_CTX *mem_ctx,
     651             :                                        int num,
     652             :                                        TDB_DATA data,
     653             :                                        TDB_CONTEXT *names)
     654             : {
     655           0 :         char *begin, *end, *start, *stop;
     656           0 :         int parent;
     657           0 :         struct PERF_OBJECT_TYPE *obj;
     658           0 :         bool success = True;
     659           0 :         char buf[PERFCOUNT_MAX_LEN];
     660             : 
     661           0 :         obj = NULL;
     662           0 :         memset(buf, 0, PERFCOUNT_MAX_LEN);
     663           0 :         memcpy(buf, data.dptr, data.dsize);
     664           0 :         begin = strchr(buf, '[');
     665           0 :         end = strchr(buf, ']');
     666           0 :         if(begin == NULL || end == NULL)
     667           0 :                 return False;
     668           0 :         start = begin+1;
     669             : 
     670           0 :         while(start < end) {
     671           0 :                 stop = strchr(start, ',');
     672           0 :                 if(stop == NULL)
     673           0 :                         stop = end;
     674           0 :                 *stop = '\0';
     675           0 :                 parent = atoi(start);
     676             : 
     677           0 :                 obj = _reg_perfcount_find_obj(block, parent);
     678           0 :                 if(obj == NULL) {
     679             :                         /* At this point we require that the parent object exist.
     680             :                            This can probably be handled better at some later time */
     681           0 :                         DEBUG(3, ("_reg_perfcount_add_counter: Could not find parent object [%d] for counter [%d].\n",
     682             :                                   parent, num));
     683           0 :                         return False;
     684             :                 }
     685           0 :                 obj->counters = (struct PERF_COUNTER_DEFINITION *)talloc_realloc(mem_ctx,
     686             :                                                                                 obj->counters,
     687             :                                                                                 struct PERF_COUNTER_DEFINITION,
     688             :                                                                                 obj->NumCounters+1);
     689           0 :                 if(obj->counters == NULL)
     690           0 :                         return False;
     691           0 :                 memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(struct PERF_COUNTER_DEFINITION));
     692           0 :                 obj->counters[obj->NumCounters].CounterNameTitleIndex=num;
     693           0 :                 obj->counters[obj->NumCounters].CounterHelpTitleIndex=num+1;
     694           0 :                 obj->counters[obj->NumCounters].DetailLevel = PERF_DETAIL_NOVICE;
     695           0 :                 obj->counters[obj->NumCounters].ByteLength = sizeof(struct PERF_COUNTER_DEFINITION);
     696           0 :                 success = _reg_perfcount_get_counter_info(block, mem_ctx, num, obj, names);
     697           0 :                 obj->NumCounters += 1;
     698           0 :                 start = stop + 1;
     699             :         }
     700             : 
     701             :         /* Handle case of Objects/Counters without any counter data, which would suggest
     702             :            that the required instances are not there yet, so change NumInstances from
     703             :            PERF_NO_INSTANCES to 0 */
     704             : 
     705           0 :         return success;
     706             : }
     707             : 
     708             : /*********************************************************************
     709             : *********************************************************************/
     710             : 
     711           0 : static bool _reg_perfcount_get_instance_info(struct PERF_INSTANCE_DEFINITION *inst,
     712             :                                              TALLOC_CTX *mem_ctx,
     713             :                                              int instId,
     714             :                                              struct PERF_OBJECT_TYPE *obj,
     715             :                                              TDB_CONTEXT *names)
     716             : {
     717           0 :         TDB_DATA key, data;
     718           0 :         char buf[PERFCOUNT_MAX_LEN] = {0};
     719           0 :         char temp[32] = {0};
     720           0 :         smb_ucs2_t *name = NULL;
     721           0 :         int pad;
     722             : 
     723             :         /* First grab the instance data from the data file */
     724           0 :         snprintf(temp, sizeof(temp), "i%d", instId);
     725           0 :         _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
     726           0 :         if (!_reg_perfcount_get_counter_data(key, &data)) {
     727           0 :                 DEBUG(3, ("_reg_perfcount_get_counter_data failed\n"));
     728           0 :                 return false;
     729             :         }
     730           0 :         if(data.dptr == NULL)
     731             :         {
     732           0 :                 DEBUG(3, ("_reg_perfcount_get_instance_info: No instance data for instance [%s].\n",
     733             :                           buf));
     734           0 :                 return False;
     735             :         }
     736           0 :         inst->counter_data.ByteLength = data.dsize + sizeof(inst->counter_data.ByteLength);
     737           0 :         inst->counter_data.data = talloc_realloc(mem_ctx,
     738             :                                                        inst->counter_data.data,
     739             :                                                        uint8_t,
     740             :                                                        data.dsize);
     741           0 :         if(inst->counter_data.data == NULL)
     742           0 :                 return False;
     743           0 :         memset(inst->counter_data.data, 0, data.dsize);
     744           0 :         memcpy(inst->counter_data.data, data.dptr, data.dsize);
     745           0 :         SAFE_FREE(data.dptr);
     746             : 
     747             :         /* Fetch instance name */
     748           0 :         snprintf(temp, sizeof(temp), "i%dname", instId);
     749           0 :         _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
     750           0 :         data = tdb_fetch(names, key);
     751           0 :         if(data.dptr == NULL)
     752             :         {
     753             :                 /* Not actually an error, but possibly unintended? -- just logging FYI */
     754           0 :                 DEBUG(3, ("_reg_perfcount_get_instance_info: No instance name for instance [%s].\n",
     755             :                           buf));
     756           0 :                 inst->NameLength = 0;
     757             :         }
     758             :         else
     759             :         {
     760           0 :                 memset(buf, 0, PERFCOUNT_MAX_LEN);
     761           0 :                 memcpy(buf, data.dptr, MIN(PERFCOUNT_MAX_LEN-1,data.dsize));
     762           0 :                 buf[PERFCOUNT_MAX_LEN-1] = '\0';
     763           0 :                 inst->NameLength = rpcstr_push_talloc(mem_ctx, &name, buf);
     764           0 :                 if (inst->NameLength == (uint32_t)-1 || !name) {
     765           0 :                         SAFE_FREE(data.dptr);
     766           0 :                         return False;
     767             :                 }
     768           0 :                 inst->data = talloc_realloc(mem_ctx,
     769             :                                                   inst->data,
     770             :                                                   uint8_t,
     771             :                                                   inst->NameLength);
     772           0 :                 if (inst->data == NULL) {
     773           0 :                         SAFE_FREE(data.dptr);
     774           0 :                         return False;
     775             :                 }
     776           0 :                 memcpy(inst->data, name, inst->NameLength);
     777           0 :                 SAFE_FREE(data.dptr);
     778             :         }
     779             : 
     780           0 :         inst->ParentObjectTitleIndex = 0;
     781           0 :         inst->ParentObjectTitlePointer = 0;
     782           0 :         inst->UniqueID = PERF_NO_UNIQUE_ID;
     783           0 :         inst->NameOffset = 6 * sizeof(uint32_t);
     784             : 
     785           0 :         inst->ByteLength = inst->NameOffset + inst->NameLength;
     786             :         /* Need to be aligned on a 64-bit boundary here for counter_data */
     787           0 :         if((pad = (inst->ByteLength % 8)))
     788             :         {
     789           0 :                 pad = 8 - pad;
     790           0 :                 inst->data = talloc_realloc(mem_ctx,
     791             :                                                   inst->data,
     792             :                                                   uint8_t,
     793             :                                                   inst->NameLength + pad);
     794           0 :                 memset(inst->data + inst->NameLength, 0, pad);
     795           0 :                 inst->ByteLength += pad;
     796             :         }
     797             : 
     798           0 :         return True;
     799             : }
     800             : 
     801             : /*********************************************************************
     802             : *********************************************************************/
     803             : 
     804           0 : static bool _reg_perfcount_add_instance(struct PERF_OBJECT_TYPE *obj,
     805             :                                         TALLOC_CTX *mem_ctx,
     806             :                                         int instInd,
     807             :                                         TDB_CONTEXT *names)
     808             : {
     809           0 :         struct PERF_INSTANCE_DEFINITION *inst;
     810             : 
     811           0 :         if(obj->instances == NULL) {
     812           0 :                 obj->instances = talloc_realloc(mem_ctx,
     813             :                                                       obj->instances,
     814             :                                                       struct PERF_INSTANCE_DEFINITION,
     815             :                                                       obj->NumInstances);
     816             :         }
     817           0 :         if(obj->instances == NULL)
     818           0 :                 return False;
     819             : 
     820           0 :         memset(&(obj->instances[instInd]), 0, sizeof(struct PERF_INSTANCE_DEFINITION));
     821           0 :         inst = &(obj->instances[instInd]);
     822           0 :         return _reg_perfcount_get_instance_info(inst, mem_ctx, instInd, obj, names);
     823             : }
     824             : 
     825             : /*********************************************************************
     826             : *********************************************************************/
     827             : 
     828           0 : static int _reg_perfcount_assemble_global(struct PERF_DATA_BLOCK *block,
     829             :                                           TALLOC_CTX *mem_ctx,
     830             :                                           int base_index,
     831             :                                           TDB_CONTEXT *names)
     832             : {
     833           0 :         bool success;
     834           0 :         int i, j, retval = 0;
     835           0 :         char keybuf[PERFCOUNT_MAX_LEN];
     836           0 :         TDB_DATA key, data;
     837             : 
     838           0 :         for(i = 1; i <= base_index; i++)
     839             :         {
     840           0 :                 j = i*2;
     841           0 :                 _reg_perfcount_make_key(&key, keybuf, PERFCOUNT_MAX_LEN, j, "rel");
     842           0 :                 data = tdb_fetch(names, key);
     843           0 :                 if(data.dptr != NULL)
     844             :                 {
     845           0 :                         if(_reg_perfcount_isparent(data))
     846           0 :                                 success = _reg_perfcount_add_object(block, mem_ctx, j, data, names);
     847           0 :                         else if(_reg_perfcount_ischild(data))
     848           0 :                                 success = _reg_perfcount_add_counter(block, mem_ctx, j, data, names);
     849             :                         else
     850             :                         {
     851           0 :                                 DEBUG(3, ("Bogus relationship [%s] for counter [%d].\n", data.dptr, j));
     852           0 :                                 success = False;
     853             :                         }
     854           0 :                         if(success == False)
     855             :                         {
     856           0 :                                 DEBUG(3, ("_reg_perfcount_assemble_global: Failed to add new relationship for counter [%d].\n", j));
     857           0 :                                 retval = -1;
     858             :                         }
     859           0 :                         SAFE_FREE(data.dptr);
     860             :                 }
     861             :                 else
     862           0 :                         DEBUG(3, ("NULL relationship for counter [%d] using key [%s].\n", j, keybuf));
     863             :         }       
     864           0 :         return retval;
     865             : }
     866             : 
     867             : /*********************************************************************
     868             : *********************************************************************/
     869             : 
     870           0 : static bool _reg_perfcount_get_64(uint64_t *retval,
     871             :                                   TDB_CONTEXT *tdb,
     872             :                                   int key_part1,
     873             :                                   const char *key_part2)
     874             : {
     875           0 :         TDB_DATA key, data;
     876           0 :         char buf[PERFCOUNT_MAX_LEN];
     877             : 
     878           0 :         _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, key_part1, key_part2);
     879             : 
     880           0 :         data = tdb_fetch(tdb, key);
     881           0 :         if(data.dptr == NULL)
     882             :         {
     883           0 :                 DEBUG(3,("_reg_perfcount_get_64: No data found for key [%s].\n", key.dptr));
     884           0 :                 return False;
     885             :         }
     886             : 
     887           0 :         memset(buf, 0, PERFCOUNT_MAX_LEN);
     888           0 :         memcpy(buf, data.dptr, data.dsize);
     889           0 :         SAFE_FREE(data.dptr);
     890             : 
     891           0 :         *retval = atof(buf);
     892             : 
     893           0 :         return True;
     894             : }
     895             : 
     896             : /*********************************************************************
     897             : *********************************************************************/
     898             : 
     899           0 : static bool _reg_perfcount_init_data_block_perf(struct PERF_DATA_BLOCK *block,
     900             :                                                 TDB_CONTEXT *names)
     901             : {
     902           0 :         uint64_t PerfFreq, PerfTime, PerfTime100nSec;
     903           0 :         TDB_CONTEXT *counters;
     904           0 :         bool status = False;
     905           0 :         char *fname;
     906             : 
     907           0 :         fname = counters_directory(DATA_DB);
     908           0 :         if (fname == NULL) {
     909           0 :                 return false;
     910             :         }
     911             : 
     912           0 :         counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
     913             : 
     914           0 :         if (counters == NULL) {
     915           0 :                 DEBUG(1, ("reg_perfcount_init_data_block_perf: unable to open [%s].\n", fname));
     916           0 :                 TALLOC_FREE(fname);
     917           0 :                 return False;
     918             :         }
     919           0 :         TALLOC_FREE(fname);
     920             : 
     921           0 :         status = _reg_perfcount_get_64(&PerfFreq, names, 0, "PerfFreq");
     922           0 :         if(status == False)
     923             :         {
     924           0 :                 tdb_close(counters);
     925           0 :                 return status;
     926             :         }
     927           0 :         memcpy((void *)&(block->PerfFreq), (const void *)&PerfFreq, sizeof(PerfFreq));
     928             : 
     929           0 :         status = _reg_perfcount_get_64(&PerfTime, counters, 0, "PerfTime");
     930           0 :         if(status == False)
     931             :         {
     932           0 :                 tdb_close(counters);
     933           0 :                 return status;
     934             :         }
     935           0 :         memcpy((void *)&(block->PerfTime), (const void *)&PerfTime, sizeof(PerfTime));
     936             : 
     937           0 :         status = _reg_perfcount_get_64(&PerfTime100nSec, counters, 0, "PerfTime100nSec");
     938           0 :         if(status == False)
     939             :         {
     940           0 :                 tdb_close(counters);
     941           0 :                 return status;
     942             :         }
     943           0 :         memcpy((void *)&(block->PerfTime100nSec), (const void *)&PerfTime100nSec, sizeof(PerfTime100nSec));
     944             : 
     945           0 :         tdb_close(counters);
     946           0 :         return True;
     947             : }
     948             : 
     949             : /*******************************************************************
     950             : ********************************************************************/
     951             : 
     952           0 : static bool make_systemtime(struct SYSTEMTIME *systime, struct tm *unixtime)
     953             : {
     954           0 :         systime->year=unixtime->tm_year+1900;
     955           0 :         systime->month=unixtime->tm_mon+1;
     956           0 :         systime->dayofweek=unixtime->tm_wday;
     957           0 :         systime->day=unixtime->tm_mday;
     958           0 :         systime->hour=unixtime->tm_hour;
     959           0 :         systime->minute=unixtime->tm_min;
     960           0 :         systime->second=unixtime->tm_sec;
     961           0 :         systime->milliseconds=0;
     962             : 
     963           0 :         return True;
     964             : }
     965             : 
     966             : /*********************************************************************
     967             : *********************************************************************/
     968             : 
     969           0 : static bool _reg_perfcount_init_data_block(struct PERF_DATA_BLOCK *block,
     970             :                                            TALLOC_CTX *mem_ctx, TDB_CONTEXT *names,
     971             :                                            bool bigendian_data)
     972             : {
     973           0 :         smb_ucs2_t *temp = NULL;
     974           0 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     975           0 :         time_t tm;
     976           0 :         size_t sz;
     977             : 
     978           0 :         sz = rpcstr_push_talloc(tmp_ctx, &temp, "PERF");
     979           0 :         if ((sz == -1) || (temp == NULL)) {
     980           0 :                 goto err_out;
     981             :         }
     982           0 :         memcpy(block->Signature, temp, strlen_w(temp) *2);
     983             : 
     984           0 :         if(bigendian_data)
     985           0 :                 block->LittleEndian = 0;
     986             :         else
     987           0 :                 block->LittleEndian = 1;
     988           0 :         block->Version = 1;
     989           0 :         block->Revision = 1;
     990           0 :         block->TotalByteLength = 0;
     991           0 :         block->NumObjectTypes = 0;
     992           0 :         block->DefaultObject = -1;
     993           0 :         block->objects = NULL;
     994           0 :         tm = time(NULL);
     995           0 :         make_systemtime(&(block->SystemTime), gmtime(&tm));
     996           0 :         _reg_perfcount_init_data_block_perf(block, names);
     997             : 
     998           0 :         sz = rpcstr_push_talloc(tmp_ctx, &temp, lp_netbios_name());
     999           0 :         if ((sz == -1) || (temp == NULL)) {
    1000           0 :                 goto err_out;
    1001             :         }
    1002           0 :         block->SystemNameLength = (strlen_w(temp) * 2) + 2;
    1003           0 :         block->data = talloc_zero_array(mem_ctx, uint8_t, block->SystemNameLength + (8 - (block->SystemNameLength % 8)));
    1004           0 :         if (block->data == NULL) {
    1005           0 :                 goto err_out;
    1006             :         }
    1007           0 :         memcpy(block->data, temp, block->SystemNameLength);
    1008           0 :         block->SystemNameOffset = sizeof(struct PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data);
    1009           0 :         block->HeaderLength = block->SystemNameOffset + block->SystemNameLength;
    1010             :         /* Make sure to adjust for 64-bit alignment for when we finish writing the system name,
    1011             :            so that the PERF_OBJECT_TYPE struct comes out 64-bit aligned */
    1012           0 :         block->HeaderLength += 8 - (block->HeaderLength % 8);
    1013           0 :         talloc_free(tmp_ctx);
    1014             : 
    1015           0 :         return true;
    1016             : 
    1017           0 : err_out:
    1018           0 :         talloc_free(tmp_ctx);
    1019           0 :         return false;
    1020             : }
    1021             : 
    1022             : /*********************************************************************
    1023             : *********************************************************************/
    1024             : 
    1025           0 : static uint32_t _reg_perfcount_perf_data_block_fixup(struct PERF_DATA_BLOCK *block, TALLOC_CTX *mem_ctx)
    1026             : {
    1027           0 :         int obj, cnt, inst, pad, i;
    1028           0 :         struct PERF_OBJECT_TYPE *object;
    1029           0 :         struct PERF_INSTANCE_DEFINITION *instance;
    1030           0 :         struct PERF_COUNTER_DEFINITION *counter;
    1031           0 :         struct PERF_COUNTER_BLOCK *counter_data;
    1032           0 :         char *temp = NULL, *src_addr, *dst_addr;
    1033             : 
    1034           0 :         block->TotalByteLength = 0;
    1035           0 :         object = block->objects;
    1036           0 :         for(obj = 0; obj < block->NumObjectTypes; obj++)
    1037             :         {
    1038           0 :                 object[obj].TotalByteLength = 0;
    1039           0 :                 object[obj].DefinitionLength = 0;
    1040           0 :                 instance = object[obj].instances;
    1041           0 :                 counter = object[obj].counters;
    1042           0 :                 for(cnt = 0; cnt < object[obj].NumCounters; cnt++)
    1043             :                 {
    1044           0 :                         object[obj].TotalByteLength += counter[cnt].ByteLength;
    1045           0 :                         object[obj].DefinitionLength += counter[cnt].ByteLength;
    1046             :                 }
    1047           0 :                 if(object[obj].NumInstances != PERF_NO_INSTANCES)
    1048             :                 {
    1049           0 :                         for(inst = 0; inst < object[obj].NumInstances; inst++)
    1050             :                         {
    1051           0 :                                 instance = &(object[obj].instances[inst]);
    1052           0 :                                 object[obj].TotalByteLength += instance->ByteLength;
    1053           0 :                                 counter_data = &(instance->counter_data);
    1054           0 :                                 counter = &(object[obj].counters[object[obj].NumCounters - 1]);
    1055           0 :                                 counter_data->ByteLength = counter->CounterOffset + counter->CounterSize + sizeof(counter_data->ByteLength);
    1056           0 :                                 temp = talloc_realloc(mem_ctx,
    1057             :                                                             temp, 
    1058             :                                                             char, 
    1059             :                                                             counter_data->ByteLength- sizeof(counter_data->ByteLength));
    1060           0 :                                 if (temp == NULL) {
    1061           0 :                                         return 0;
    1062             :                                 }
    1063           0 :                                 memset(temp, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength));
    1064           0 :                                 src_addr = (char *)counter_data->data;
    1065           0 :                                 for(i = 0; i < object[obj].NumCounters; i++)
    1066             :                                 {
    1067           0 :                                         counter = &(object[obj].counters[i]);
    1068           0 :                                         dst_addr = temp + counter->CounterOffset - sizeof(counter_data->ByteLength);
    1069           0 :                                         memcpy(dst_addr, src_addr, counter->CounterSize);
    1070           0 :                                         src_addr += counter->CounterSize;
    1071             :                                 }
    1072             :                                 /* Make sure to be 64-bit aligned */
    1073           0 :                                 if((pad = (counter_data->ByteLength % 8)))
    1074             :                                 {
    1075           0 :                                         pad = 8 - pad;
    1076             :                                 }
    1077           0 :                                 counter_data->data = talloc_realloc(mem_ctx,
    1078             :                                                                          counter_data->data,
    1079             :                                                                          uint8_t,
    1080             :                                                                          counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
    1081           0 :                                 if (counter_data->data == NULL) {
    1082           0 :                                         return 0;
    1083             :                                 }
    1084           0 :                                 memset(counter_data->data, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
    1085           0 :                                 memcpy(counter_data->data, temp, counter_data->ByteLength - sizeof(counter_data->ByteLength));
    1086           0 :                                 counter_data->ByteLength += pad;
    1087           0 :                                 object[obj].TotalByteLength += counter_data->ByteLength;
    1088             :                         }
    1089             :                 }
    1090             :                 else
    1091             :                 {
    1092             :                         /* Need to be 64-bit aligned at the end of the counter_data block, so pad counter_data to a 64-bit boundary,
    1093             :                            so that the next PERF_OBJECT_TYPE can start on a 64-bit alignment */
    1094           0 :                         if((pad = (object[obj].counter_data.ByteLength % 8)))
    1095             :                         {
    1096           0 :                                 pad = 8 - pad;
    1097           0 :                                 object[obj].counter_data.data = talloc_realloc(mem_ctx,
    1098             :                                                                                      object[obj].counter_data.data,
    1099             :                                                                                      uint8_t,
    1100             :                                                                                      object[obj].counter_data.ByteLength + pad);
    1101           0 :                                 memset((void *)(object[obj].counter_data.data + object[obj].counter_data.ByteLength), 0, pad);
    1102           0 :                                 object[obj].counter_data.ByteLength += pad;
    1103             :                         }
    1104           0 :                         object[obj].TotalByteLength += object[obj].counter_data.ByteLength;
    1105             :                 }
    1106           0 :                 object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(struct PERF_COUNTER_BLOCK));
    1107           0 :                 object[obj].TotalByteLength += object[obj].HeaderLength;
    1108           0 :                 object[obj].DefinitionLength += object[obj].HeaderLength;
    1109             : 
    1110           0 :                 block->TotalByteLength += object[obj].TotalByteLength;
    1111             :         }
    1112             : 
    1113           0 :         return block->TotalByteLength;
    1114             : }
    1115             : 
    1116             : /*********************************************************************
    1117             : *********************************************************************/
    1118             : 
    1119           0 : static uint32_t reg_perfcount_get_perf_data_block(uint32_t base_index,
    1120             :                                                 TALLOC_CTX *mem_ctx,
    1121             :                                                 struct PERF_DATA_BLOCK *block,
    1122             :                                                 const char *object_ids,
    1123             :                                                 bool bigendian_data)
    1124             : {
    1125           0 :         uint32_t buffer_size = 0;
    1126           0 :         char *fname;
    1127           0 :         TDB_CONTEXT *names;
    1128           0 :         int retval = 0;
    1129             : 
    1130           0 :         fname = counters_directory(NAMES_DB);
    1131           0 :         if (fname == NULL) {
    1132           0 :                 return 0;
    1133             :         }
    1134             : 
    1135           0 :         names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
    1136             : 
    1137           0 :         if(names == NULL)
    1138             :         {
    1139           0 :                 DEBUG(1, ("reg_perfcount_get_perf_data_block: unable to open [%s].\n", fname));
    1140           0 :                 TALLOC_FREE(fname);
    1141           0 :                 return 0;
    1142             :         }
    1143           0 :         TALLOC_FREE(fname);
    1144             : 
    1145           0 :         if (!_reg_perfcount_init_data_block(block, mem_ctx, names, bigendian_data)) {
    1146           0 :                 DEBUG(0, ("_reg_perfcount_init_data_block failed\n"));
    1147           0 :                 tdb_close(names);
    1148           0 :                 return 0;
    1149             :         }
    1150             : 
    1151           0 :         retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names);
    1152             : 
    1153           0 :         buffer_size = _reg_perfcount_perf_data_block_fixup(block, mem_ctx);
    1154             : 
    1155           0 :         tdb_close(names);
    1156             : 
    1157           0 :         if (retval == -1) {
    1158           0 :                 return 0;
    1159             :         }
    1160             : 
    1161           0 :         return buffer_size + block->HeaderLength;
    1162             : }
    1163             : 
    1164             : /*******************************************************************
    1165             : ********************************************************************/
    1166             : 
    1167           0 : static bool smb_io_system_time(const char *desc, prs_struct *ps, int depth, struct SYSTEMTIME *systime)
    1168             : {
    1169           0 :         if(!prs_uint16("year", ps, depth, &systime->year))
    1170           0 :                 return False;
    1171           0 :         if(!prs_uint16("month", ps, depth, &systime->month))
    1172           0 :                 return False;
    1173           0 :         if(!prs_uint16("dayofweek", ps, depth, &systime->dayofweek))
    1174           0 :                 return False;
    1175           0 :         if(!prs_uint16("day", ps, depth, &systime->day))
    1176           0 :                 return False;
    1177           0 :         if(!prs_uint16("hour", ps, depth, &systime->hour))
    1178           0 :                 return False;
    1179           0 :         if(!prs_uint16("minute", ps, depth, &systime->minute))
    1180           0 :                 return False;
    1181           0 :         if(!prs_uint16("second", ps, depth, &systime->second))
    1182           0 :                 return False;
    1183           0 :         if(!prs_uint16("milliseconds", ps, depth, &systime->milliseconds))
    1184           0 :                 return False;
    1185             : 
    1186           0 :         return True;
    1187             : }
    1188             : 
    1189             : /*********************************************************************
    1190             : *********************************************************************/
    1191             : 
    1192           0 : static bool _reg_perfcount_marshall_perf_data_block(prs_struct *ps, struct PERF_DATA_BLOCK block, int depth)
    1193             : {
    1194           0 :         int i;
    1195           0 :         prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_data_block");
    1196           0 :         depth++;
    1197             : 
    1198           0 :         if(!prs_align(ps))
    1199           0 :                 return False;
    1200           0 :         for(i = 0; i < 4; i++)
    1201             :         {
    1202           0 :                 if(!prs_uint16("Signature", ps, depth, &block.Signature[i]))
    1203           0 :                         return False;
    1204             :         }
    1205           0 :         if(!prs_uint32("Little Endian", ps, depth, &block.LittleEndian))
    1206           0 :                 return False;
    1207           0 :         if(!prs_uint32("Version", ps, depth, &block.Version))
    1208           0 :                 return False;
    1209           0 :         if(!prs_uint32("Revision", ps, depth, &block.Revision))
    1210           0 :                 return False;
    1211           0 :         if(!prs_uint32("TotalByteLength", ps, depth, &block.TotalByteLength))
    1212           0 :                 return False;
    1213           0 :         if(!prs_uint32("HeaderLength", ps, depth, &block.HeaderLength))
    1214           0 :                 return False;
    1215           0 :         if(!prs_uint32("NumObjectTypes", ps, depth, &block.NumObjectTypes))
    1216           0 :                 return False;
    1217           0 :         if(!prs_uint32("DefaultObject", ps, depth, &block.DefaultObject))
    1218           0 :                 return False;
    1219           0 :         if(!smb_io_system_time("SystemTime", ps, depth, &block.SystemTime))
    1220           0 :                 return False;
    1221           0 :         if(!prs_uint32("Padding", ps, depth, &block.Padding))
    1222           0 :                 return False;
    1223           0 :         if(!prs_align_uint64(ps))
    1224           0 :                 return False;
    1225           0 :         if(!prs_uint64("PerfTime", ps, depth, &block.PerfTime))
    1226           0 :                 return False;
    1227           0 :         if(!prs_uint64("PerfFreq", ps, depth, &block.PerfFreq))
    1228           0 :                 return False;
    1229           0 :         if(!prs_uint64("PerfTime100nSec", ps, depth, &block.PerfTime100nSec))
    1230           0 :                 return False;
    1231           0 :         if(!prs_uint32("SystemNameLength", ps, depth, &block.SystemNameLength))
    1232           0 :                 return False;
    1233           0 :         if(!prs_uint32("SystemNameOffset", ps, depth, &block.SystemNameOffset))
    1234           0 :                 return False;
    1235             :         /* hack to make sure we're 64-bit aligned at the end of this whole mess */
    1236           0 :         if(!prs_uint8s(False, "SystemName", ps, depth, block.data, 
    1237           0 :                        block.HeaderLength - block.SystemNameOffset)) 
    1238           0 :                 return False;
    1239             : 
    1240           0 :         return True;
    1241             : }
    1242             : 
    1243             : /*********************************************************************
    1244             : *********************************************************************/
    1245             : 
    1246           0 : static bool _reg_perfcount_marshall_perf_counters(prs_struct *ps,
    1247             :                                                   struct PERF_OBJECT_TYPE object,
    1248             :                                                   int depth)
    1249             : {
    1250           0 :         int cnt;
    1251           0 :         struct PERF_COUNTER_DEFINITION counter;
    1252             : 
    1253           0 :         prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counters");
    1254           0 :         depth++;
    1255             : 
    1256           0 :         for(cnt = 0; cnt < object.NumCounters; cnt++)
    1257             :         {
    1258           0 :                 counter = object.counters[cnt];
    1259             : 
    1260           0 :                 if(!prs_align(ps))
    1261           0 :                         return False;
    1262           0 :                 if(!prs_uint32("ByteLength", ps, depth, &counter.ByteLength))
    1263           0 :                         return False;
    1264           0 :                 if(!prs_uint32("CounterNameTitleIndex", ps, depth, &counter.CounterNameTitleIndex))
    1265           0 :                         return False;
    1266           0 :                 if(!prs_uint32("CounterNameTitlePointer", ps, depth, &counter.CounterNameTitlePointer))
    1267           0 :                         return False;
    1268           0 :                 if(!prs_uint32("CounterHelpTitleIndex", ps, depth, &counter.CounterHelpTitleIndex))
    1269           0 :                         return False;
    1270           0 :                 if(!prs_uint32("CounterHelpTitlePointer", ps, depth, &counter.CounterHelpTitlePointer))
    1271           0 :                         return False;
    1272           0 :                 if(!prs_uint32("DefaultScale", ps, depth, &counter.DefaultScale))
    1273           0 :                         return False;
    1274           0 :                 if(!prs_uint32("DetailLevel", ps, depth, &counter.DetailLevel))
    1275           0 :                         return False;
    1276           0 :                 if(!prs_uint32("CounterType", ps, depth, &counter.CounterType))
    1277           0 :                         return False;
    1278           0 :                 if(!prs_uint32("CounterSize", ps, depth, &counter.CounterSize))
    1279           0 :                         return False;
    1280           0 :                 if(!prs_uint32("CounterOffset", ps, depth, &counter.CounterOffset))
    1281           0 :                         return False;
    1282             :         }
    1283             : 
    1284           0 :         return True;
    1285             : }
    1286             : 
    1287             : /*********************************************************************
    1288             : *********************************************************************/
    1289             : 
    1290           0 : static bool _reg_perfcount_marshall_perf_counter_data(prs_struct *ps, 
    1291             :                                                       struct PERF_COUNTER_BLOCK counter_data,
    1292             :                                                       int depth)
    1293             : {
    1294           0 :         prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counter_data");
    1295           0 :         depth++;
    1296             : 
    1297           0 :         if(!prs_align_uint64(ps))
    1298           0 :                 return False;
    1299             : 
    1300           0 :         if(!prs_uint32("ByteLength", ps, depth, &counter_data.ByteLength))
    1301           0 :                 return False;
    1302           0 :         if(!prs_uint8s(False, "CounterData", ps, depth, counter_data.data, counter_data.ByteLength - sizeof(uint32_t)))
    1303           0 :                 return False;
    1304           0 :         if(!prs_align_uint64(ps))
    1305           0 :                 return False;
    1306             : 
    1307           0 :         return True;
    1308             : }
    1309             : 
    1310             : /*********************************************************************
    1311             : *********************************************************************/
    1312             : 
    1313           0 : static bool _reg_perfcount_marshall_perf_instances(prs_struct *ps,
    1314             :                                                    struct PERF_OBJECT_TYPE object,
    1315             :                                                    int depth)
    1316             : {
    1317           0 :         struct PERF_INSTANCE_DEFINITION instance;
    1318           0 :         int inst;
    1319             : 
    1320           0 :         prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_instances");
    1321           0 :         depth++;
    1322             : 
    1323           0 :         for(inst = 0; inst < object.NumInstances; inst++)
    1324             :         {
    1325           0 :                 instance = object.instances[inst];
    1326             : 
    1327           0 :                 if(!prs_align(ps))
    1328           0 :                         return False;
    1329           0 :                 if(!prs_uint32("ByteLength", ps, depth, &instance.ByteLength))
    1330           0 :                         return False;
    1331           0 :                 if(!prs_uint32("ParentObjectTitleIndex", ps, depth, &instance.ParentObjectTitleIndex))
    1332           0 :                         return False;
    1333           0 :                 if(!prs_uint32("ParentObjectTitlePointer", ps, depth, &instance.ParentObjectTitlePointer))
    1334           0 :                         return False;
    1335           0 :                 if(!prs_uint32("UniqueID", ps, depth, &instance.UniqueID))
    1336           0 :                         return False;
    1337           0 :                 if(!prs_uint32("NameOffset", ps, depth, &instance.NameOffset))
    1338           0 :                         return False;
    1339           0 :                 if(!prs_uint32("NameLength", ps, depth, &instance.NameLength))
    1340           0 :                         return False;
    1341           0 :                 if(!prs_uint8s(False, "InstanceName", ps, depth, instance.data,
    1342           0 :                                instance.ByteLength - instance.NameOffset))
    1343           0 :                         return False;
    1344           0 :                 if(_reg_perfcount_marshall_perf_counter_data(ps, instance.counter_data, depth) == False)
    1345           0 :                         return False;
    1346             :         }
    1347             : 
    1348           0 :         return True;
    1349             : }
    1350             : 
    1351             : /*********************************************************************
    1352             : *********************************************************************/
    1353             : 
    1354           0 : static bool _reg_perfcount_marshall_perf_objects(prs_struct *ps, struct PERF_DATA_BLOCK block, int depth)
    1355             : {
    1356           0 :         int obj;
    1357             : 
    1358           0 :         struct PERF_OBJECT_TYPE object;
    1359             : 
    1360           0 :         prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_objects");
    1361           0 :         depth++;
    1362             : 
    1363           0 :         for(obj = 0; obj < block.NumObjectTypes; obj++)
    1364             :         {
    1365           0 :                 object = block.objects[obj];
    1366             : 
    1367           0 :                 if(!prs_align(ps))
    1368           0 :                         return False;
    1369             : 
    1370           0 :                 if(!prs_uint32("TotalByteLength", ps, depth, &object.TotalByteLength))
    1371           0 :                         return False;
    1372           0 :                 if(!prs_uint32("DefinitionLength", ps, depth, &object.DefinitionLength))
    1373           0 :                         return False;
    1374           0 :                 if(!prs_uint32("HeaderLength", ps, depth, &object.HeaderLength))
    1375           0 :                         return False;
    1376           0 :                 if(!prs_uint32("ObjectNameTitleIndex", ps, depth, &object.ObjectNameTitleIndex))
    1377           0 :                         return False;
    1378           0 :                 if(!prs_uint32("ObjectNameTitlePointer", ps, depth, &object.ObjectNameTitlePointer))
    1379           0 :                         return False;
    1380           0 :                 if(!prs_uint32("ObjectHelpTitleIndex", ps, depth, &object.ObjectHelpTitleIndex))
    1381           0 :                         return False;
    1382           0 :                 if(!prs_uint32("ObjectHelpTitlePointer", ps, depth, &object.ObjectHelpTitlePointer))
    1383           0 :                         return False;
    1384           0 :                 if(!prs_uint32("DetailLevel", ps, depth, &object.DetailLevel))
    1385           0 :                         return False;
    1386           0 :                 if(!prs_uint32("NumCounters", ps, depth, &object.NumCounters))
    1387           0 :                         return False;
    1388           0 :                 if(!prs_uint32("DefaultCounter", ps, depth, &object.DefaultCounter))
    1389           0 :                         return False;
    1390           0 :                 if(!prs_uint32("NumInstances", ps, depth, &object.NumInstances))
    1391           0 :                         return False;
    1392           0 :                 if(!prs_uint32("CodePage", ps, depth, &object.CodePage))
    1393           0 :                         return False;
    1394           0 :                 if(!prs_align_uint64(ps))
    1395           0 :                         return False;
    1396           0 :                 if(!prs_uint64("PerfTime", ps, depth, &object.PerfTime))
    1397           0 :                         return False;
    1398           0 :                 if(!prs_uint64("PerfFreq", ps, depth, &object.PerfFreq))
    1399           0 :                         return False;
    1400             : 
    1401             :                 /* Now do the counters */
    1402             :                 /* If no instances, encode counter_data */
    1403             :                 /* If instances, encode instance plus counter data for each instance */
    1404           0 :                 if(_reg_perfcount_marshall_perf_counters(ps, object, depth) == False)
    1405           0 :                         return False;
    1406           0 :                 if(object.NumInstances == PERF_NO_INSTANCES)
    1407             :                 {
    1408           0 :                         if(_reg_perfcount_marshall_perf_counter_data(ps, object.counter_data, depth) == False)
    1409           0 :                                 return False;
    1410             :                 }
    1411             :                 else
    1412             :                 {
    1413           0 :                         if(_reg_perfcount_marshall_perf_instances(ps, object, depth) == False)
    1414           0 :                                 return False;
    1415             :                 }
    1416             :         }
    1417             : 
    1418           0 :         return True;
    1419             : }
    1420             : 
    1421             : /*********************************************************************
    1422             : *********************************************************************/
    1423             : 
    1424           0 : WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32_t max_buf_size, uint32_t *outbuf_len, const char *object_ids)
    1425             : {
    1426             :         /*
    1427             :          * For a detailed description of the layout of this structure,
    1428             :          * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/performance_data_format.asp
    1429             :          *
    1430             :          * By 2006-11-23 this link did not work anymore, I found something
    1431             :          * promising under
    1432             :          * http://msdn2.microsoft.com/en-us/library/aa373105.aspx -- vl
    1433             :          */
    1434           0 :         struct PERF_DATA_BLOCK block;
    1435           0 :         uint32_t buffer_size, base_index;
    1436             : 
    1437           0 :         buffer_size = 0;
    1438           0 :         base_index = reg_perfcount_get_base_index();
    1439           0 :         ZERO_STRUCT(block);
    1440             : 
    1441           0 :         buffer_size = reg_perfcount_get_perf_data_block(base_index, ps->mem_ctx, &block, object_ids, ps->bigendian_data);
    1442             : 
    1443           0 :         if(buffer_size < max_buf_size)
    1444             :         {
    1445           0 :                 *outbuf_len = buffer_size;
    1446             : 
    1447           0 :                 if (!_reg_perfcount_marshall_perf_data_block(ps, block, 0))
    1448           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1449             : 
    1450           0 :                 if (!_reg_perfcount_marshall_perf_objects(ps, block, 0))
    1451           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1452             : 
    1453           0 :                 return WERR_OK;
    1454             :         }
    1455             :         else
    1456             :         {
    1457           0 :                 *outbuf_len = max_buf_size;
    1458           0 :                 if (!_reg_perfcount_marshall_perf_data_block(ps, block, 0))
    1459           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1460             : 
    1461           0 :                 return WERR_INSUFFICIENT_BUFFER;
    1462             :         }
    1463             : }    

Generated by: LCOV version 1.14