~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/registry/reg_perfcount.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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