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 : }
|