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 33struct PERF_OBJECT_TYPE *_reg_perfcount_find_obj(struct PERF_DATA_BLOCK *block, int objind); 34 35/********************************************************************* 36*********************************************************************/ 37 38static 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 57void 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 72uint32 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 124uint32 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 139uint32 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 155static 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 DATA_BLOB 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 push_reg_sz(talloc_tos(), &name_index, (const char *)kbuf.dptr); 186 memcpy(buf1+buffer_size, (char *)name_index.data, 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 push_reg_sz(talloc_tos(), &name, temp); 199 memcpy(buf1+buffer_size, (char *)name.data, working_size); 200 buffer_size += working_size; 201 202 *retbuf = buf1; 203 204 return buffer_size; 205} 206 207/********************************************************************* 208*********************************************************************/ 209 210uint32 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 253uint32 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 298static 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 318static 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 333static 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 348static 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 368static bool _reg_perfcount_add_instance(struct PERF_OBJECT_TYPE *obj, 369 TALLOC_CTX *mem_ctx, 370 int instInd, 371 TDB_CONTEXT *names); 372 373static bool _reg_perfcount_add_object(struct PERF_DATA_BLOCK *block, 374 TALLOC_CTX *mem_ctx, 375 int num, 376 TDB_DATA data, 377 TDB_CONTEXT *names) 378{ 379 int i; 380 bool success = True; 381 struct PERF_OBJECT_TYPE *obj; 382 383 block->objects = (struct PERF_OBJECT_TYPE *)TALLOC_REALLOC_ARRAY(mem_ctx, 384 block->objects, 385 struct PERF_OBJECT_TYPE, 386 block->NumObjectTypes+1); 387 if(block->objects == NULL) 388 return False; 389 obj = &(block->objects[block->NumObjectTypes]); 390 memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(struct PERF_OBJECT_TYPE)); 391 block->objects[block->NumObjectTypes].ObjectNameTitleIndex = num; 392 block->objects[block->NumObjectTypes].ObjectNameTitlePointer = 0; 393 block->objects[block->NumObjectTypes].ObjectHelpTitleIndex = num+1; 394 block->objects[block->NumObjectTypes].ObjectHelpTitlePointer = 0; 395 block->objects[block->NumObjectTypes].NumCounters = 0; 396 block->objects[block->NumObjectTypes].DefaultCounter = 0; 397 block->objects[block->NumObjectTypes].NumInstances = _reg_perfcount_get_numinst(num, names); 398 block->objects[block->NumObjectTypes].counters = NULL; 399 block->objects[block->NumObjectTypes].instances = NULL; 400 block->objects[block->NumObjectTypes].counter_data.ByteLength = sizeof(uint32); 401 block->objects[block->NumObjectTypes].counter_data.data = NULL; 402 block->objects[block->NumObjectTypes].DetailLevel = PERF_DETAIL_NOVICE; 403 block->NumObjectTypes+=1; 404 405 for(i = 0; i < (int)obj->NumInstances; i++) { 406 success = _reg_perfcount_add_instance(obj, mem_ctx, i, names); 407 } 408 409 return success; 410} 411 412/********************************************************************* 413*********************************************************************/ 414 415static bool _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data) 416{ 417 TDB_CONTEXT *counters; 418 const char *fname = counters_directory( DATA_DB ); 419 420 counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); 421 422 if(counters == NULL) 423 { 424 DEBUG(1, ("reg_perfcount_get_counter_data: unable to open [%s].\n", fname)); 425 return False; 426 } 427 428 *data = tdb_fetch(counters, key); 429 430 tdb_close(counters); 431 432 return True; 433} 434 435/********************************************************************* 436*********************************************************************/ 437 438static uint32 _reg_perfcount_get_size_field(uint32 CounterType) 439{ 440 uint32 retval; 441 442 retval = CounterType; 443 444 /* First mask out reserved lower 8 bits */ 445 retval = retval & 0xFFFFFF00; 446 retval = retval << 22; 447 retval = retval >> 22; 448 449 return retval; 450} 451 452/********************************************************************* 453*********************************************************************/ 454 455static uint32 _reg_perfcount_compute_scale(int64_t data) 456{ 457 int scale = 0; 458 if(data == 0) 459 return scale; 460 while(data > 100) 461 { 462 data /= 10; 463 scale--; 464 } 465 while(data < 10) 466 { 467 data *= 10; 468 scale++; 469 } 470 471 return (uint32)scale; 472} 473 474/********************************************************************* 475*********************************************************************/ 476 477static bool _reg_perfcount_get_counter_info(struct PERF_DATA_BLOCK *block, 478 TALLOC_CTX *mem_ctx, 479 int CounterIndex, 480 struct PERF_OBJECT_TYPE *obj, 481 TDB_CONTEXT *names) 482{ 483 TDB_DATA key, data; 484 char buf[PERFCOUNT_MAX_LEN]; 485 size_t dsize, padding; 486 long int data32, dbuf[2]; 487 int64_t data64; 488 uint32 counter_size; 489 490 obj->counters[obj->NumCounters].DefaultScale = 0; 491 dbuf[0] = dbuf[1] = 0; 492 padding = 0; 493 494 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "type"); 495 data = tdb_fetch(names, key); 496 if(data.dptr == NULL) 497 { 498 DEBUG(3, ("_reg_perfcount_get_counter_info: No type data for counter [%d].\n", CounterIndex)); 499 return False; 500 } 501 memset(buf, 0, PERFCOUNT_MAX_LEN); 502 memcpy(buf, data.dptr, data.dsize); 503 obj->counters[obj->NumCounters].CounterType = atoi(buf); 504 DEBUG(10, ("_reg_perfcount_get_counter_info: Got type [%d] for counter [%d].\n", 505 obj->counters[obj->NumCounters].CounterType, CounterIndex)); 506 SAFE_FREE(data.dptr); 507 508 /* Fetch the actual data */ 509 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, ""); 510 _reg_perfcount_get_counter_data(key, &data); 511 if(data.dptr == NULL) 512 { 513 DEBUG(3, ("_reg_perfcount_get_counter_info: No counter data for counter [%d].\n", CounterIndex)); 514 return False; 515 } 516 517 counter_size = _reg_perfcount_get_size_field(obj->counters[obj->NumCounters].CounterType); 518 519 if(counter_size == PERF_SIZE_DWORD) 520 { 521 dsize = sizeof(data32); 522 memset(buf, 0, PERFCOUNT_MAX_LEN); 523 memcpy(buf, data.dptr, data.dsize); 524 data32 = strtol(buf, NULL, 0); 525 if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER) 526 obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale((int64_t)data32); 527 else 528 obj->counters[obj->NumCounters].DefaultScale = 0; 529 dbuf[0] = data32; 530 padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize; 531 } 532 else if(counter_size == PERF_SIZE_LARGE) 533 { 534 dsize = sizeof(data64); 535 memset(buf, 0, PERFCOUNT_MAX_LEN); 536 memcpy(buf, data.dptr, data.dsize); 537 data64 = atof(buf); 538 if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER) 539 obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale(data64); 540 else 541 obj->counters[obj->NumCounters].DefaultScale = 0; 542 memcpy((void *)dbuf, (const void *)&data64, dsize); 543 padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize; 544 } 545 else /* PERF_SIZE_VARIABLE_LEN */ 546 { 547 dsize = data.dsize; 548 memset(buf, 0, PERFCOUNT_MAX_LEN); 549 memcpy(buf, data.dptr, data.dsize); 550 } 551 SAFE_FREE(data.dptr); 552 553 obj->counter_data.ByteLength += dsize + padding; 554 obj->counter_data.data = TALLOC_REALLOC_ARRAY(mem_ctx, 555 obj->counter_data.data, 556 uint8, 557 obj->counter_data.ByteLength - sizeof(uint32)); 558 if(obj->counter_data.data == NULL) 559 return False; 560 if(dbuf[0] != 0 || dbuf[1] != 0) 561 { 562 memcpy((void *)(obj->counter_data.data + 563 (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))), 564 (const void *)dbuf, dsize); 565 } 566 else 567 { 568 /* Handling PERF_SIZE_VARIABLE_LEN */ 569 memcpy((void *)(obj->counter_data.data + 570 (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))), 571 (const void *)buf, dsize); 572 } 573 obj->counters[obj->NumCounters].CounterOffset = obj->counter_data.ByteLength - dsize; 574 if(obj->counters[obj->NumCounters].CounterOffset % dsize != 0) 575 { 576 DEBUG(3,("Improperly aligned counter [%d]\n", obj->NumCounters)); 577 } 578 obj->counters[obj->NumCounters].CounterSize = dsize; 579 580 return True; 581} 582 583/********************************************************************* 584*********************************************************************/ 585 586struct PERF_OBJECT_TYPE *_reg_perfcount_find_obj(struct PERF_DATA_BLOCK *block, int objind) 587{ 588 int i; 589 590 struct PERF_OBJECT_TYPE *obj = NULL; 591 592 for(i = 0; i < block->NumObjectTypes; i++) 593 { 594 if(block->objects[i].ObjectNameTitleIndex == objind) 595 { 596 obj = &(block->objects[i]); 597 } 598 } 599 600 return obj; 601} 602 603/********************************************************************* 604*********************************************************************/ 605 606static bool _reg_perfcount_add_counter(struct PERF_DATA_BLOCK *block, 607 TALLOC_CTX *mem_ctx, 608 int num, 609 TDB_DATA data, 610 TDB_CONTEXT *names) 611{ 612 char *begin, *end, *start, *stop; 613 int parent; 614 struct PERF_OBJECT_TYPE *obj; 615 bool success = True; 616 char buf[PERFCOUNT_MAX_LEN]; 617 618 obj = NULL; 619 memset(buf, 0, PERFCOUNT_MAX_LEN); 620 memcpy(buf, data.dptr, data.dsize); 621 begin = index(buf, '['); 622 end = index(buf, ']'); 623 if(begin == NULL || end == NULL) 624 return False; 625 start = begin+1; 626 627 while(start < end) { 628 stop = index(start, ','); 629 if(stop == NULL) 630 stop = end; 631 *stop = '\0'; 632 parent = atoi(start); 633 634 obj = _reg_perfcount_find_obj(block, parent); 635 if(obj == NULL) { 636 /* At this point we require that the parent object exist. 637 This can probably be handled better at some later time */ 638 DEBUG(3, ("_reg_perfcount_add_counter: Could not find parent object [%d] for counter [%d].\n", 639 parent, num)); 640 return False; 641 } 642 obj->counters = (struct PERF_COUNTER_DEFINITION *)TALLOC_REALLOC_ARRAY(mem_ctx, 643 obj->counters, 644 struct PERF_COUNTER_DEFINITION, 645 obj->NumCounters+1); 646 if(obj->counters == NULL) 647 return False; 648 memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(struct PERF_COUNTER_DEFINITION)); 649 obj->counters[obj->NumCounters].CounterNameTitleIndex=num; 650 obj->counters[obj->NumCounters].CounterHelpTitleIndex=num+1; 651 obj->counters[obj->NumCounters].DetailLevel = PERF_DETAIL_NOVICE; 652 obj->counters[obj->NumCounters].ByteLength = sizeof(struct PERF_COUNTER_DEFINITION); 653 success = _reg_perfcount_get_counter_info(block, mem_ctx, num, obj, names); 654 obj->NumCounters += 1; 655 start = stop + 1; 656 } 657 658 /* Handle case of Objects/Counters without any counter data, which would suggest 659 that the required instances are not there yet, so change NumInstances from 660 PERF_NO_INSTANCES to 0 */ 661 662 return success; 663} 664 665/********************************************************************* 666*********************************************************************/ 667 668static bool _reg_perfcount_get_instance_info(struct PERF_INSTANCE_DEFINITION *inst, 669 TALLOC_CTX *mem_ctx, 670 int instId, 671 struct PERF_OBJECT_TYPE *obj, 672 TDB_CONTEXT *names) 673{ 674 TDB_DATA key, data; 675 char buf[PERFCOUNT_MAX_LEN], temp[PERFCOUNT_MAX_LEN]; 676 smb_ucs2_t *name = NULL; 677 int pad; 678 679 /* First grab the instance data from the data file */ 680 memset(temp, 0, PERFCOUNT_MAX_LEN); 681 snprintf(temp, PERFCOUNT_MAX_LEN, "i%d", instId); 682 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp); 683 if (!_reg_perfcount_get_counter_data(key, &data)) { 684 DEBUG(3, ("_reg_perfcount_get_counter_data failed\n")); 685 return false; 686 } 687 if(data.dptr == NULL) 688 { 689 DEBUG(3, ("_reg_perfcount_get_instance_info: No instance data for instance [%s].\n", 690 buf)); 691 return False; 692 } 693 inst->counter_data.ByteLength = data.dsize + sizeof(inst->counter_data.ByteLength); 694 inst->counter_data.data = TALLOC_REALLOC_ARRAY(mem_ctx, 695 inst->counter_data.data, 696 uint8, 697 data.dsize); 698 if(inst->counter_data.data == NULL) 699 return False; 700 memset(inst->counter_data.data, 0, data.dsize); 701 memcpy(inst->counter_data.data, data.dptr, data.dsize); 702 SAFE_FREE(data.dptr); 703 704 /* Fetch instance name */ 705 memset(temp, 0, PERFCOUNT_MAX_LEN); 706 snprintf(temp, PERFCOUNT_MAX_LEN, "i%dname", instId); 707 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp); 708 data = tdb_fetch(names, key); 709 if(data.dptr == NULL) 710 { 711 /* Not actually an error, but possibly unintended? -- just logging FYI */ 712 DEBUG(3, ("_reg_perfcount_get_instance_info: No instance name for instance [%s].\n", 713 buf)); 714 inst->NameLength = 0; 715 } 716 else 717 { 718 memset(buf, 0, PERFCOUNT_MAX_LEN); 719 memcpy(buf, data.dptr, MIN(PERFCOUNT_MAX_LEN-1,data.dsize)); 720 buf[PERFCOUNT_MAX_LEN-1] = '\0'; 721 inst->NameLength = rpcstr_push_talloc(mem_ctx, &name, buf); 722 if (inst->NameLength == (uint32_t)-1 || !name) { 723 SAFE_FREE(data.dptr); 724 return False; 725 } 726 inst->data = TALLOC_REALLOC_ARRAY(mem_ctx, 727 inst->data, 728 uint8, 729 inst->NameLength); 730 if (inst->data == NULL) { 731 SAFE_FREE(data.dptr); 732 return False; 733 } 734 memcpy(inst->data, name, inst->NameLength); 735 SAFE_FREE(data.dptr); 736 } 737 738 inst->ParentObjectTitleIndex = 0; 739 inst->ParentObjectTitlePointer = 0; 740 inst->UniqueID = PERF_NO_UNIQUE_ID; 741 inst->NameOffset = 6 * sizeof(uint32); 742 743 inst->ByteLength = inst->NameOffset + inst->NameLength; 744 /* Need to be aligned on a 64-bit boundary here for counter_data */ 745 if((pad = (inst->ByteLength % 8))) 746 { 747 pad = 8 - pad; 748 inst->data = TALLOC_REALLOC_ARRAY(mem_ctx, 749 inst->data, 750 uint8, 751 inst->NameLength + pad); 752 memset(inst->data + inst->NameLength, 0, pad); 753 inst->ByteLength += pad; 754 } 755 756 return True; 757} 758 759/********************************************************************* 760*********************************************************************/ 761 762static bool _reg_perfcount_add_instance(struct PERF_OBJECT_TYPE *obj, 763 TALLOC_CTX *mem_ctx, 764 int instInd, 765 TDB_CONTEXT *names) 766{ 767 struct PERF_INSTANCE_DEFINITION *inst; 768 769 if(obj->instances == NULL) { 770 obj->instances = TALLOC_REALLOC_ARRAY(mem_ctx, 771 obj->instances, 772 struct PERF_INSTANCE_DEFINITION, 773 obj->NumInstances); 774 } 775 if(obj->instances == NULL) 776 return False; 777 778 memset(&(obj->instances[instInd]), 0, sizeof(struct PERF_INSTANCE_DEFINITION)); 779 inst = &(obj->instances[instInd]); 780 return _reg_perfcount_get_instance_info(inst, mem_ctx, instInd, obj, names); 781} 782 783/********************************************************************* 784*********************************************************************/ 785 786static int _reg_perfcount_assemble_global(struct PERF_DATA_BLOCK *block, 787 TALLOC_CTX *mem_ctx, 788 int base_index, 789 TDB_CONTEXT *names) 790{ 791 bool success; 792 int i, j, retval = 0; 793 char keybuf[PERFCOUNT_MAX_LEN]; 794 TDB_DATA key, data; 795 796 for(i = 1; i <= base_index; i++) 797 { 798 j = i*2; 799 _reg_perfcount_make_key(&key, keybuf, PERFCOUNT_MAX_LEN, j, "rel"); 800 data = tdb_fetch(names, key); 801 if(data.dptr != NULL) 802 { 803 if(_reg_perfcount_isparent(data)) 804 success = _reg_perfcount_add_object(block, mem_ctx, j, data, names); 805 else if(_reg_perfcount_ischild(data)) 806 success = _reg_perfcount_add_counter(block, mem_ctx, j, data, names); 807 else 808 { 809 DEBUG(3, ("Bogus relationship [%s] for counter [%d].\n", data.dptr, j)); 810 success = False; 811 } 812 if(success == False) 813 { 814 DEBUG(3, ("_reg_perfcount_assemble_global: Failed to add new relationship for counter [%d].\n", j)); 815 retval = -1; 816 } 817 SAFE_FREE(data.dptr); 818 } 819 else 820 DEBUG(3, ("NULL relationship for counter [%d] using key [%s].\n", j, keybuf)); 821 } 822 return retval; 823} 824 825/********************************************************************* 826*********************************************************************/ 827 828static bool _reg_perfcount_get_64(uint64_t *retval, 829 TDB_CONTEXT *tdb, 830 int key_part1, 831 const char *key_part2) 832{ 833 TDB_DATA key, data; 834 char buf[PERFCOUNT_MAX_LEN]; 835 836 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, key_part1, key_part2); 837 838 data = tdb_fetch(tdb, key); 839 if(data.dptr == NULL) 840 { 841 DEBUG(3,("_reg_perfcount_get_64: No data found for key [%s].\n", key.dptr)); 842 return False; 843 } 844 845 memset(buf, 0, PERFCOUNT_MAX_LEN); 846 memcpy(buf, data.dptr, data.dsize); 847 SAFE_FREE(data.dptr); 848 849 *retval = atof(buf); 850 851 return True; 852} 853 854/********************************************************************* 855*********************************************************************/ 856 857static bool _reg_perfcount_init_data_block_perf(struct PERF_DATA_BLOCK *block, 858 TDB_CONTEXT *names) 859{ 860 uint64_t PerfFreq, PerfTime, PerfTime100nSec; 861 TDB_CONTEXT *counters; 862 bool status = False; 863 const char *fname = counters_directory( DATA_DB ); 864 865 counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); 866 867 if(counters == NULL) 868 { 869 DEBUG(1, ("reg_perfcount_init_data_block_perf: unable to open [%s].\n", fname)); 870 return False; 871 } 872 873 status = _reg_perfcount_get_64(&PerfFreq, names, 0, "PerfFreq"); 874 if(status == False) 875 { 876 tdb_close(counters); 877 return status; 878 } 879 memcpy((void *)&(block->PerfFreq), (const void *)&PerfFreq, sizeof(PerfFreq)); 880 881 status = _reg_perfcount_get_64(&PerfTime, counters, 0, "PerfTime"); 882 if(status == False) 883 { 884 tdb_close(counters); 885 return status; 886 } 887 memcpy((void *)&(block->PerfTime), (const void *)&PerfTime, sizeof(PerfTime)); 888 889 status = _reg_perfcount_get_64(&PerfTime100nSec, counters, 0, "PerfTime100nSec"); 890 if(status == False) 891 { 892 tdb_close(counters); 893 return status; 894 } 895 memcpy((void *)&(block->PerfTime100nSec), (const void *)&PerfTime100nSec, sizeof(PerfTime100nSec)); 896 897 tdb_close(counters); 898 return True; 899} 900 901/******************************************************************* 902********************************************************************/ 903 904static bool make_systemtime(struct SYSTEMTIME *systime, struct tm *unixtime) 905{ 906 systime->year=unixtime->tm_year+1900; 907 systime->month=unixtime->tm_mon+1; 908 systime->dayofweek=unixtime->tm_wday; 909 systime->day=unixtime->tm_mday; 910 systime->hour=unixtime->tm_hour; 911 systime->minute=unixtime->tm_min; 912 systime->second=unixtime->tm_sec; 913 systime->milliseconds=0; 914 915 return True; 916} 917 918/********************************************************************* 919*********************************************************************/ 920 921static bool _reg_perfcount_init_data_block(struct PERF_DATA_BLOCK *block, 922 TALLOC_CTX *mem_ctx, TDB_CONTEXT *names, 923 bool bigendian_data) 924{ 925 smb_ucs2_t *temp = NULL; 926 time_t tm; 927 928 if (rpcstr_push_talloc(mem_ctx, &temp, "PERF")==(size_t)-1) { 929 return false; 930 } 931 if (!temp) { 932 return false; 933 } 934 memcpy(block->Signature, temp, strlen_w(temp) *2); 935 936 if(bigendian_data) 937 block->LittleEndian = 0; 938 else 939 block->LittleEndian = 1; 940 block->Version = 1; 941 block->Revision = 1; 942 block->TotalByteLength = 0; 943 block->NumObjectTypes = 0; 944 block->DefaultObject = -1; 945 block->objects = NULL; 946 tm = time(NULL); 947 make_systemtime(&(block->SystemTime), gmtime(&tm)); 948 _reg_perfcount_init_data_block_perf(block, names); 949 memset(temp, 0, sizeof(temp)); 950 rpcstr_push((void *)temp, global_myname(), sizeof(temp), STR_TERMINATE); 951 block->SystemNameLength = (strlen_w(temp) * 2) + 2; 952 block->data = TALLOC_ZERO_ARRAY(mem_ctx, uint8, block->SystemNameLength + (8 - (block->SystemNameLength % 8))); 953 if (block->data == NULL) { 954 return False; 955 } 956 memcpy(block->data, temp, block->SystemNameLength); 957 block->SystemNameOffset = sizeof(struct PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data); 958 block->HeaderLength = block->SystemNameOffset + block->SystemNameLength; 959 /* Make sure to adjust for 64-bit alignment for when we finish writing the system name, 960 so that the PERF_OBJECT_TYPE struct comes out 64-bit aligned */ 961 block->HeaderLength += 8 - (block->HeaderLength % 8); 962 963 return True; 964} 965 966/********************************************************************* 967*********************************************************************/ 968 969static uint32 _reg_perfcount_perf_data_block_fixup(struct PERF_DATA_BLOCK *block, TALLOC_CTX *mem_ctx) 970{ 971 int obj, cnt, inst, pad, i; 972 struct PERF_OBJECT_TYPE *object; 973 struct PERF_INSTANCE_DEFINITION *instance; 974 struct PERF_COUNTER_DEFINITION *counter; 975 struct PERF_COUNTER_BLOCK *counter_data; 976 char *temp = NULL, *src_addr, *dst_addr; 977 978 block->TotalByteLength = 0; 979 object = block->objects; 980 for(obj = 0; obj < block->NumObjectTypes; obj++) 981 { 982 object[obj].TotalByteLength = 0; 983 object[obj].DefinitionLength = 0; 984 instance = object[obj].instances; 985 counter = object[obj].counters; 986 for(cnt = 0; cnt < object[obj].NumCounters; cnt++) 987 { 988 object[obj].TotalByteLength += counter[cnt].ByteLength; 989 object[obj].DefinitionLength += counter[cnt].ByteLength; 990 } 991 if(object[obj].NumInstances != PERF_NO_INSTANCES) 992 { 993 for(inst = 0; inst < object[obj].NumInstances; inst++) 994 { 995 instance = &(object[obj].instances[inst]); 996 object[obj].TotalByteLength += instance->ByteLength; 997 counter_data = &(instance->counter_data); 998 counter = &(object[obj].counters[object[obj].NumCounters - 1]); 999 counter_data->ByteLength = counter->CounterOffset + counter->CounterSize + sizeof(counter_data->ByteLength); 1000 temp = TALLOC_REALLOC_ARRAY(mem_ctx, 1001 temp, 1002 char, 1003 counter_data->ByteLength- sizeof(counter_data->ByteLength)); 1004 if (temp == NULL) { 1005 return 0; 1006 } 1007 memset(temp, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength)); 1008 src_addr = (char *)counter_data->data; 1009 for(i = 0; i < object[obj].NumCounters; i++) 1010 { 1011 counter = &(object[obj].counters[i]); 1012 dst_addr = temp + counter->CounterOffset - sizeof(counter_data->ByteLength); 1013 memcpy(dst_addr, src_addr, counter->CounterSize); 1014 src_addr += counter->CounterSize; 1015 } 1016 /* Make sure to be 64-bit aligned */ 1017 if((pad = (counter_data->ByteLength % 8))) 1018 { 1019 pad = 8 - pad; 1020 } 1021 counter_data->data = TALLOC_REALLOC_ARRAY(mem_ctx, 1022 counter_data->data, 1023 uint8, 1024 counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad); 1025 if (counter_data->data == NULL) { 1026 return 0; 1027 } 1028 memset(counter_data->data, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad); 1029 memcpy(counter_data->data, temp, counter_data->ByteLength - sizeof(counter_data->ByteLength)); 1030 counter_data->ByteLength += pad; 1031 object[obj].TotalByteLength += counter_data->ByteLength; 1032 } 1033 } 1034 else 1035 { 1036 /* Need to be 64-bit aligned at the end of the counter_data block, so pad counter_data to a 64-bit boundary, 1037 so that the next PERF_OBJECT_TYPE can start on a 64-bit alignment */ 1038 if((pad = (object[obj].counter_data.ByteLength % 8))) 1039 { 1040 pad = 8 - pad; 1041 object[obj].counter_data.data = TALLOC_REALLOC_ARRAY(mem_ctx, 1042 object[obj].counter_data.data, 1043 uint8, 1044 object[obj].counter_data.ByteLength + pad); 1045 memset((void *)(object[obj].counter_data.data + object[obj].counter_data.ByteLength), 0, pad); 1046 object[obj].counter_data.ByteLength += pad; 1047 } 1048 object[obj].TotalByteLength += object[obj].counter_data.ByteLength; 1049 } 1050 object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(struct PERF_COUNTER_BLOCK)); 1051 object[obj].TotalByteLength += object[obj].HeaderLength; 1052 object[obj].DefinitionLength += object[obj].HeaderLength; 1053 1054 block->TotalByteLength += object[obj].TotalByteLength; 1055 } 1056 1057 return block->TotalByteLength; 1058} 1059 1060/********************************************************************* 1061*********************************************************************/ 1062 1063static uint32 reg_perfcount_get_perf_data_block(uint32 base_index, 1064 TALLOC_CTX *mem_ctx, 1065 struct PERF_DATA_BLOCK *block, 1066 const char *object_ids, 1067 bool bigendian_data) 1068{ 1069 uint32 buffer_size = 0; 1070 const char *fname = counters_directory( NAMES_DB ); 1071 TDB_CONTEXT *names; 1072 int retval = 0; 1073 1074 names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); 1075 1076 if(names == NULL) 1077 { 1078 DEBUG(1, ("reg_perfcount_get_perf_data_block: unable to open [%s].\n", fname)); 1079 return 0; 1080 } 1081 1082 if (!_reg_perfcount_init_data_block(block, mem_ctx, names, bigendian_data)) { 1083 DEBUG(0, ("_reg_perfcount_init_data_block failed\n")); 1084 tdb_close(names); 1085 return 0; 1086 } 1087 1088 reg_perfcount_get_last_counter(base_index); 1089 1090 if(object_ids == NULL) 1091 { 1092 /* we're getting a request for "Global" here */ 1093 retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names); 1094 } 1095 else 1096 { 1097 /* we're getting a request for a specific set of PERF_OBJECT_TYPES */ 1098 retval = _reg_perfcount_assemble_global(block, mem_ctx, base_index, names); 1099 } 1100 buffer_size = _reg_perfcount_perf_data_block_fixup(block, mem_ctx); 1101 1102 tdb_close(names); 1103 1104 if (retval == -1) { 1105 return 0; 1106 } 1107 1108 return buffer_size + block->HeaderLength; 1109} 1110 1111/******************************************************************* 1112********************************************************************/ 1113 1114static bool smb_io_system_time(const char *desc, prs_struct *ps, int depth, struct SYSTEMTIME *systime) 1115{ 1116 if(!prs_uint16("year", ps, depth, &systime->year)) 1117 return False; 1118 if(!prs_uint16("month", ps, depth, &systime->month)) 1119 return False; 1120 if(!prs_uint16("dayofweek", ps, depth, &systime->dayofweek)) 1121 return False; 1122 if(!prs_uint16("day", ps, depth, &systime->day)) 1123 return False; 1124 if(!prs_uint16("hour", ps, depth, &systime->hour)) 1125 return False; 1126 if(!prs_uint16("minute", ps, depth, &systime->minute)) 1127 return False; 1128 if(!prs_uint16("second", ps, depth, &systime->second)) 1129 return False; 1130 if(!prs_uint16("milliseconds", ps, depth, &systime->milliseconds)) 1131 return False; 1132 1133 return True; 1134} 1135 1136/********************************************************************* 1137*********************************************************************/ 1138 1139static bool _reg_perfcount_marshall_perf_data_block(prs_struct *ps, struct PERF_DATA_BLOCK block, int depth) 1140{ 1141 int i; 1142 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_data_block"); 1143 depth++; 1144 1145 if(!prs_align(ps)) 1146 return False; 1147 for(i = 0; i < 4; i++) 1148 { 1149 if(!prs_uint16("Signature", ps, depth, &block.Signature[i])) 1150 return False; 1151 } 1152 if(!prs_uint32("Little Endian", ps, depth, &block.LittleEndian)) 1153 return False; 1154 if(!prs_uint32("Version", ps, depth, &block.Version)) 1155 return False; 1156 if(!prs_uint32("Revision", ps, depth, &block.Revision)) 1157 return False; 1158 if(!prs_uint32("TotalByteLength", ps, depth, &block.TotalByteLength)) 1159 return False; 1160 if(!prs_uint32("HeaderLength", ps, depth, &block.HeaderLength)) 1161 return False; 1162 if(!prs_uint32("NumObjectTypes", ps, depth, &block.NumObjectTypes)) 1163 return False; 1164 if(!prs_uint32("DefaultObject", ps, depth, &block.DefaultObject)) 1165 return False; 1166 if(!smb_io_system_time("SystemTime", ps, depth, &block.SystemTime)) 1167 return False; 1168 if(!prs_uint32("Padding", ps, depth, &block.Padding)) 1169 return False; 1170 if(!prs_align_uint64(ps)) 1171 return False; 1172 if(!prs_uint64("PerfTime", ps, depth, &block.PerfTime)) 1173 return False; 1174 if(!prs_uint64("PerfFreq", ps, depth, &block.PerfFreq)) 1175 return False; 1176 if(!prs_uint64("PerfTime100nSec", ps, depth, &block.PerfTime100nSec)) 1177 return False; 1178 if(!prs_uint32("SystemNameLength", ps, depth, &block.SystemNameLength)) 1179 return False; 1180 if(!prs_uint32("SystemNameOffset", ps, depth, &block.SystemNameOffset)) 1181 return False; 1182 /* hack to make sure we're 64-bit aligned at the end of this whole mess */ 1183 if(!prs_uint8s(False, "SystemName", ps, depth, block.data, 1184 block.HeaderLength - block.SystemNameOffset)) 1185 return False; 1186 1187 return True; 1188} 1189 1190/********************************************************************* 1191*********************************************************************/ 1192 1193static bool _reg_perfcount_marshall_perf_counters(prs_struct *ps, 1194 struct PERF_OBJECT_TYPE object, 1195 int depth) 1196{ 1197 int cnt; 1198 struct PERF_COUNTER_DEFINITION counter; 1199 1200 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counters"); 1201 depth++; 1202 1203 for(cnt = 0; cnt < object.NumCounters; cnt++) 1204 { 1205 counter = object.counters[cnt]; 1206 1207 if(!prs_align(ps)) 1208 return False; 1209 if(!prs_uint32("ByteLength", ps, depth, &counter.ByteLength)) 1210 return False; 1211 if(!prs_uint32("CounterNameTitleIndex", ps, depth, &counter.CounterNameTitleIndex)) 1212 return False; 1213 if(!prs_uint32("CounterNameTitlePointer", ps, depth, &counter.CounterNameTitlePointer)) 1214 return False; 1215 if(!prs_uint32("CounterHelpTitleIndex", ps, depth, &counter.CounterHelpTitleIndex)) 1216 return False; 1217 if(!prs_uint32("CounterHelpTitlePointer", ps, depth, &counter.CounterHelpTitlePointer)) 1218 return False; 1219 if(!prs_uint32("DefaultScale", ps, depth, &counter.DefaultScale)) 1220 return False; 1221 if(!prs_uint32("DetailLevel", ps, depth, &counter.DetailLevel)) 1222 return False; 1223 if(!prs_uint32("CounterType", ps, depth, &counter.CounterType)) 1224 return False; 1225 if(!prs_uint32("CounterSize", ps, depth, &counter.CounterSize)) 1226 return False; 1227 if(!prs_uint32("CounterOffset", ps, depth, &counter.CounterOffset)) 1228 return False; 1229 } 1230 1231 return True; 1232} 1233 1234/********************************************************************* 1235*********************************************************************/ 1236 1237static bool _reg_perfcount_marshall_perf_counter_data(prs_struct *ps, 1238 struct PERF_COUNTER_BLOCK counter_data, 1239 int depth) 1240{ 1241 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counter_data"); 1242 depth++; 1243 1244 if(!prs_align_uint64(ps)) 1245 return False; 1246 1247 if(!prs_uint32("ByteLength", ps, depth, &counter_data.ByteLength)) 1248 return False; 1249 if(!prs_uint8s(False, "CounterData", ps, depth, counter_data.data, counter_data.ByteLength - sizeof(uint32))) 1250 return False; 1251 if(!prs_align_uint64(ps)) 1252 return False; 1253 1254 return True; 1255} 1256 1257/********************************************************************* 1258*********************************************************************/ 1259 1260static bool _reg_perfcount_marshall_perf_instances(prs_struct *ps, 1261 struct PERF_OBJECT_TYPE object, 1262 int depth) 1263{ 1264 struct PERF_INSTANCE_DEFINITION instance; 1265 int inst; 1266 1267 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_instances"); 1268 depth++; 1269 1270 for(inst = 0; inst < object.NumInstances; inst++) 1271 { 1272 instance = object.instances[inst]; 1273 1274 if(!prs_align(ps)) 1275 return False; 1276 if(!prs_uint32("ByteLength", ps, depth, &instance.ByteLength)) 1277 return False; 1278 if(!prs_uint32("ParentObjectTitleIndex", ps, depth, &instance.ParentObjectTitleIndex)) 1279 return False; 1280 if(!prs_uint32("ParentObjectTitlePointer", ps, depth, &instance.ParentObjectTitlePointer)) 1281 return False; 1282 if(!prs_uint32("UniqueID", ps, depth, &instance.UniqueID)) 1283 return False; 1284 if(!prs_uint32("NameOffset", ps, depth, &instance.NameOffset)) 1285 return False; 1286 if(!prs_uint32("NameLength", ps, depth, &instance.NameLength)) 1287 return False; 1288 if(!prs_uint8s(False, "InstanceName", ps, depth, instance.data, 1289 instance.ByteLength - instance.NameOffset)) 1290 return False; 1291 if(_reg_perfcount_marshall_perf_counter_data(ps, instance.counter_data, depth) == False) 1292 return False; 1293 } 1294 1295 return True; 1296} 1297 1298/********************************************************************* 1299*********************************************************************/ 1300 1301static bool _reg_perfcount_marshall_perf_objects(prs_struct *ps, struct PERF_DATA_BLOCK block, int depth) 1302{ 1303 int obj; 1304 1305 struct PERF_OBJECT_TYPE object; 1306 1307 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_objects"); 1308 depth++; 1309 1310 for(obj = 0; obj < block.NumObjectTypes; obj++) 1311 { 1312 object = block.objects[obj]; 1313 1314 if(!prs_align(ps)) 1315 return False; 1316 1317 if(!prs_uint32("TotalByteLength", ps, depth, &object.TotalByteLength)) 1318 return False; 1319 if(!prs_uint32("DefinitionLength", ps, depth, &object.DefinitionLength)) 1320 return False; 1321 if(!prs_uint32("HeaderLength", ps, depth, &object.HeaderLength)) 1322 return False; 1323 if(!prs_uint32("ObjectNameTitleIndex", ps, depth, &object.ObjectNameTitleIndex)) 1324 return False; 1325 if(!prs_uint32("ObjectNameTitlePointer", ps, depth, &object.ObjectNameTitlePointer)) 1326 return False; 1327 if(!prs_uint32("ObjectHelpTitleIndex", ps, depth, &object.ObjectHelpTitleIndex)) 1328 return False; 1329 if(!prs_uint32("ObjectHelpTitlePointer", ps, depth, &object.ObjectHelpTitlePointer)) 1330 return False; 1331 if(!prs_uint32("DetailLevel", ps, depth, &object.DetailLevel)) 1332 return False; 1333 if(!prs_uint32("NumCounters", ps, depth, &object.NumCounters)) 1334 return False; 1335 if(!prs_uint32("DefaultCounter", ps, depth, &object.DefaultCounter)) 1336 return False; 1337 if(!prs_uint32("NumInstances", ps, depth, &object.NumInstances)) 1338 return False; 1339 if(!prs_uint32("CodePage", ps, depth, &object.CodePage)) 1340 return False; 1341 if(!prs_align_uint64(ps)) 1342 return False; 1343 if(!prs_uint64("PerfTime", ps, depth, &object.PerfTime)) 1344 return False; 1345 if(!prs_uint64("PerfFreq", ps, depth, &object.PerfFreq)) 1346 return False; 1347 1348 /* Now do the counters */ 1349 /* If no instances, encode counter_data */ 1350 /* If instances, encode instace plus counter data for each instance */ 1351 if(_reg_perfcount_marshall_perf_counters(ps, object, depth) == False) 1352 return False; 1353 if(object.NumInstances == PERF_NO_INSTANCES) 1354 { 1355 if(_reg_perfcount_marshall_perf_counter_data(ps, object.counter_data, depth) == False) 1356 return False; 1357 } 1358 else 1359 { 1360 if(_reg_perfcount_marshall_perf_instances(ps, object, depth) == False) 1361 return False; 1362 } 1363 } 1364 1365 return True; 1366} 1367 1368/********************************************************************* 1369*********************************************************************/ 1370 1371WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32 max_buf_size, uint32 *outbuf_len, const char *object_ids) 1372{ 1373 /* 1374 * For a detailed description of the layout of this structure, 1375 * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/performance_data_format.asp 1376 * 1377 * By 2006-11-23 this link did not work anymore, I found something 1378 * promising under 1379 * http://msdn2.microsoft.com/en-us/library/aa373105.aspx -- vl 1380 */ 1381 struct PERF_DATA_BLOCK block; 1382 uint32 buffer_size, base_index; 1383 1384 buffer_size = 0; 1385 base_index = reg_perfcount_get_base_index(); 1386 ZERO_STRUCT(block); 1387 1388 buffer_size = reg_perfcount_get_perf_data_block(base_index, ps->mem_ctx, &block, object_ids, ps->bigendian_data); 1389 1390 if(buffer_size < max_buf_size) 1391 { 1392 *outbuf_len = buffer_size; 1393 1394 if (!_reg_perfcount_marshall_perf_data_block(ps, block, 0)) 1395 return WERR_NOMEM; 1396 1397 if (!_reg_perfcount_marshall_perf_objects(ps, block, 0)) 1398 return WERR_NOMEM; 1399 1400 return WERR_OK; 1401 } 1402 else 1403 { 1404 *outbuf_len = max_buf_size; 1405 if (!_reg_perfcount_marshall_perf_data_block(ps, block, 0)) 1406 return WERR_NOMEM; 1407 1408 return WERR_INSUFFICIENT_BUFFER; 1409 } 1410} 1411