00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025 #undef DBGC_CLASS
00026 #define DBGC_CLASS DBGC_RPC_SRV
00027
00028 #define PERFCOUNT_MAX_LEN 256
00029
00030 #define PERFCOUNTDIR "perfmon"
00031 #define NAMES_DB "names.tdb"
00032 #define DATA_DB "data.tdb"
00033
00034 PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind);
00035
00036
00037
00038
00039 static char* counters_directory( const char *dbname )
00040 {
00041 static pstring fname;
00042 fstring path;
00043
00044 if ( !dbname )
00045 return NULL;
00046
00047 fstr_sprintf( path, "%s/%s", PERFCOUNTDIR, dbname );
00048
00049 pstrcpy( fname, lock_path( path ) );
00050
00051 return fname;
00052 }
00053
00054
00055
00056
00057 void perfcount_init_keys( void )
00058 {
00059 char *p = lock_path(PERFCOUNTDIR);
00060
00061
00062
00063 if ( !directory_exist( p, NULL ) )
00064 mkdir( p, 0755 );
00065
00066 return;
00067 }
00068
00069
00070
00071
00072 uint32 reg_perfcount_get_base_index(void)
00073 {
00074 const char *fname = counters_directory( NAMES_DB );
00075 TDB_CONTEXT *names;
00076 TDB_DATA kbuf, dbuf;
00077 char key[] = "1";
00078 uint32 retval = 0;
00079 char buf[PERFCOUNT_MAX_LEN];
00080
00081 names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
00082
00083 if ( !names ) {
00084 DEBUG(1, ("reg_perfcount_get_base_index: unable to open [%s].\n", fname));
00085 return 0;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 kbuf.dptr = key;
00102 kbuf.dsize = strlen(key);
00103 dbuf = tdb_fetch(names, kbuf);
00104 if(dbuf.dptr == NULL)
00105 {
00106 DEBUG(1, ("reg_perfcount_get_base_index: failed to find key \'1\' in [%s].\n", fname));
00107 tdb_close(names);
00108 return 0;
00109 }
00110 else
00111 {
00112 tdb_close(names);
00113 memset(buf, 0, PERFCOUNT_MAX_LEN);
00114 memcpy(buf, dbuf.dptr, dbuf.dsize);
00115 retval = (uint32)atoi(buf);
00116 SAFE_FREE(dbuf.dptr);
00117 return retval;
00118 }
00119 return 0;
00120 }
00121
00122
00123
00124
00125 uint32 reg_perfcount_get_last_counter(uint32 base_index)
00126 {
00127 uint32 retval;
00128
00129 if(base_index == 0)
00130 retval = 0;
00131 else
00132 retval = base_index * 2;
00133
00134 return retval;
00135 }
00136
00137
00138
00139
00140 uint32 reg_perfcount_get_last_help(uint32 last_counter)
00141 {
00142 uint32 retval;
00143
00144 if(last_counter == 0)
00145 retval = 0;
00146 else
00147 retval = last_counter + 1;
00148
00149 return retval;
00150 }
00151
00152
00153
00154
00155
00156 static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
00157 int keyval,
00158 char **retbuf,
00159 uint32 buffer_size)
00160 {
00161 TDB_DATA kbuf, dbuf;
00162 char temp[256];
00163 char *buf1 = *retbuf;
00164 uint32 working_size = 0;
00165 UNISTR2 name_index, name;
00166
00167 memset(temp, 0, sizeof(temp));
00168 snprintf(temp, sizeof(temp), "%d", keyval);
00169 kbuf.dptr = temp;
00170 kbuf.dsize = strlen(temp);
00171 dbuf = tdb_fetch(tdb, kbuf);
00172 if(dbuf.dptr == NULL)
00173 {
00174
00175
00176 DEBUG(3, ("_reg_perfcount_multi_sz_from_tdb: failed to find key [%s] in [%s].\n",
00177 temp, tdb_name(tdb)));
00178 return buffer_size;
00179 }
00180
00181 working_size = (kbuf.dsize + 1)*sizeof(uint16);
00182 buf1 = (char *)SMB_REALLOC(buf1, buffer_size + working_size);
00183 if(!buf1) {
00184 buffer_size = 0;
00185 return buffer_size;
00186 }
00187 init_unistr2(&name_index, kbuf.dptr, UNI_STR_TERMINATE);
00188 memcpy(buf1+buffer_size, (char *)name_index.buffer, working_size);
00189 buffer_size += working_size;
00190
00191 working_size = (dbuf.dsize + 1)*sizeof(uint16);
00192 buf1 = (char *)SMB_REALLOC(buf1, buffer_size + working_size);
00193 if(!buf1) {
00194 buffer_size = 0;
00195 return buffer_size;
00196 }
00197 memset(temp, 0, sizeof(temp));
00198 memcpy(temp, dbuf.dptr, dbuf.dsize);
00199 SAFE_FREE(dbuf.dptr);
00200 init_unistr2(&name, temp, UNI_STR_TERMINATE);
00201 memcpy(buf1+buffer_size, (char *)name.buffer, working_size);
00202 buffer_size += working_size;
00203
00204 *retbuf = buf1;
00205
00206 return buffer_size;
00207 }
00208
00209
00210
00211
00212 uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf)
00213 {
00214 char *buf1 = NULL;
00215 uint32 buffer_size = 0;
00216 TDB_CONTEXT *names;
00217 const char *fname = counters_directory( NAMES_DB );
00218 int i;
00219
00220 if(base_index == 0)
00221 return 0;
00222
00223 names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
00224
00225 if(names == NULL)
00226 {
00227 DEBUG(1, ("reg_perfcount_get_counter_help: unable to open [%s].\n", fname));
00228 return 0;
00229 }
00230
00231 for(i = 1; i <= base_index; i++)
00232 {
00233 buffer_size = _reg_perfcount_multi_sz_from_tdb(names, (i*2)+1, retbuf, buffer_size);
00234 }
00235 tdb_close(names);
00236
00237
00238 buf1 = *retbuf;
00239 buf1 = (char *)SMB_REALLOC(buf1, buffer_size + 2);
00240 if(!buf1) {
00241 buffer_size = 0;
00242 } else {
00243 buf1[buffer_size++] = '\0';
00244 buf1[buffer_size++] = '\0';
00245 }
00246
00247 *retbuf = buf1;
00248
00249 return buffer_size;
00250 }
00251
00252
00253
00254
00255 uint32 reg_perfcount_get_counter_names(uint32 base_index, char **retbuf)
00256 {
00257 char *buf1 = NULL;
00258 uint32 buffer_size = 0;
00259 TDB_CONTEXT *names;
00260 const char *fname = counters_directory( NAMES_DB );
00261 int i;
00262
00263 if(base_index == 0)
00264 return 0;
00265
00266 names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
00267
00268 if(names == NULL)
00269 {
00270 DEBUG(1, ("reg_perfcount_get_counter_names: unable to open [%s].\n", fname));
00271 return 0;
00272 }
00273
00274 buffer_size = _reg_perfcount_multi_sz_from_tdb(names, 1, retbuf, buffer_size);
00275
00276 for(i = 1; i <= base_index; i++)
00277 {
00278 buffer_size = _reg_perfcount_multi_sz_from_tdb(names, i*2, retbuf, buffer_size);
00279 }
00280 tdb_close(names);
00281
00282
00283 buf1 = *retbuf;
00284 buf1 = (char *)SMB_REALLOC(buf1, buffer_size + 2);
00285 if(!buf1) {
00286 buffer_size = 0;
00287 } else {
00288 buf1[buffer_size++] = '\0';
00289 buf1[buffer_size++] = '\0';
00290 }
00291
00292 *retbuf=buf1;
00293
00294 return buffer_size;
00295 }
00296
00297
00298
00299
00300 static void _reg_perfcount_make_key(TDB_DATA *key,
00301 char *buf,
00302 int buflen,
00303 int key_part1,
00304 const char *key_part2)
00305 {
00306 memset(buf, 0, buflen);
00307 if(key_part2 != NULL)
00308 snprintf(buf, buflen,"%d%s", key_part1, key_part2);
00309 else
00310 snprintf(buf, buflen, "%d", key_part1);
00311
00312 key->dptr = buf;
00313 key->dsize = strlen(buf);
00314
00315 return;
00316 }
00317
00318
00319
00320
00321 static BOOL _reg_perfcount_isparent(TDB_DATA data)
00322 {
00323 if(data.dsize > 0)
00324 {
00325 if(data.dptr[0] == 'p')
00326 return True;
00327 else
00328 return False;
00329 }
00330 return False;
00331 }
00332
00333
00334
00335
00336 static BOOL _reg_perfcount_ischild(TDB_DATA data)
00337 {
00338 if(data.dsize > 0)
00339 {
00340 if(data.dptr[0] == 'c')
00341 return True;
00342 else
00343 return False;
00344 }
00345 return False;
00346 }
00347
00348
00349
00350
00351 static uint32 _reg_perfcount_get_numinst(int objInd, TDB_CONTEXT *names)
00352 {
00353 TDB_DATA key, data;
00354 char buf[PERFCOUNT_MAX_LEN];
00355
00356 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, objInd, "inst");
00357 data = tdb_fetch(names, key);
00358
00359 if(data.dptr == NULL)
00360 return (uint32)PERF_NO_INSTANCES;
00361
00362 memset(buf, 0, PERFCOUNT_MAX_LEN);
00363 memcpy(buf, data.dptr, data.dsize);
00364 return (uint32)atoi(buf);
00365 }
00366
00367
00368
00369
00370 static BOOL _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
00371 prs_struct *ps,
00372 int num,
00373 TDB_DATA data,
00374 TDB_CONTEXT *names)
00375 {
00376 int i;
00377 BOOL success = True;
00378 PERF_OBJECT_TYPE *obj;
00379
00380 block->objects = (PERF_OBJECT_TYPE *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00381 block->objects,
00382 PERF_OBJECT_TYPE,
00383 block->NumObjectTypes+1);
00384 if(block->objects == NULL)
00385 return False;
00386 obj = &(block->objects[block->NumObjectTypes]);
00387 memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(PERF_OBJECT_TYPE));
00388 block->objects[block->NumObjectTypes].ObjectNameTitleIndex = num;
00389 block->objects[block->NumObjectTypes].ObjectNameTitlePointer = 0;
00390 block->objects[block->NumObjectTypes].ObjectHelpTitleIndex = num+1;
00391 block->objects[block->NumObjectTypes].ObjectHelpTitlePointer = 0;
00392 block->objects[block->NumObjectTypes].NumCounters = 0;
00393 block->objects[block->NumObjectTypes].DefaultCounter = 0;
00394 block->objects[block->NumObjectTypes].NumInstances = _reg_perfcount_get_numinst(num, names);
00395 block->objects[block->NumObjectTypes].counters = NULL;
00396 block->objects[block->NumObjectTypes].instances = NULL;
00397 block->objects[block->NumObjectTypes].counter_data.ByteLength = sizeof(uint32);
00398 block->objects[block->NumObjectTypes].counter_data.data = NULL;
00399 block->objects[block->NumObjectTypes].DetailLevel = PERF_DETAIL_NOVICE;
00400 block->NumObjectTypes+=1;
00401
00402 for(i = 0; i < (int)obj->NumInstances; i++) {
00403 success = _reg_perfcount_add_instance(obj, ps, i, names);
00404 }
00405
00406 return success;
00407 }
00408
00409
00410
00411
00412 BOOL _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data)
00413 {
00414 TDB_CONTEXT *counters;
00415 const char *fname = counters_directory( DATA_DB );
00416
00417 counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
00418
00419 if(counters == NULL)
00420 {
00421 DEBUG(1, ("reg_perfcount_get_counter_data: unable to open [%s].\n", fname));
00422 return False;
00423 }
00424
00425 *data = tdb_fetch(counters, key);
00426
00427 tdb_close(counters);
00428
00429 return True;
00430 }
00431
00432
00433
00434
00435 static uint32 _reg_perfcount_get_size_field(uint32 CounterType)
00436 {
00437 uint32 retval;
00438
00439 retval = CounterType;
00440
00441
00442 retval = retval & 0xFFFFFF00;
00443 retval = retval << 22;
00444 retval = retval >> 22;
00445
00446 return retval;
00447 }
00448
00449
00450
00451
00452 static uint32 _reg_perfcount_compute_scale(SMB_BIG_INT data)
00453 {
00454 int scale = 0;
00455 if(data == 0)
00456 return scale;
00457 while(data > 100)
00458 {
00459 data /= 10;
00460 scale--;
00461 }
00462 while(data < 10)
00463 {
00464 data *= 10;
00465 scale++;
00466 }
00467
00468 return (uint32)scale;
00469 }
00470
00471
00472
00473
00474 static BOOL _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
00475 prs_struct *ps,
00476 int CounterIndex,
00477 PERF_OBJECT_TYPE *obj,
00478 TDB_CONTEXT *names)
00479 {
00480 TDB_DATA key, data;
00481 char buf[PERFCOUNT_MAX_LEN];
00482 size_t dsize, padding;
00483 long int data32, dbuf[2];
00484 SMB_BIG_INT data64;
00485 uint32 counter_size;
00486
00487 obj->counters[obj->NumCounters].DefaultScale = 0;
00488 dbuf[0] = dbuf[1] = 0;
00489 padding = 0;
00490
00491 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "type");
00492 data = tdb_fetch(names, key);
00493 if(data.dptr == NULL)
00494 {
00495 DEBUG(3, ("_reg_perfcount_get_counter_info: No type data for counter [%d].\n", CounterIndex));
00496 return False;
00497 }
00498 memset(buf, 0, PERFCOUNT_MAX_LEN);
00499 memcpy(buf, data.dptr, data.dsize);
00500 obj->counters[obj->NumCounters].CounterType = atoi(buf);
00501 DEBUG(10, ("_reg_perfcount_get_counter_info: Got type [%d] for counter [%d].\n",
00502 obj->counters[obj->NumCounters].CounterType, CounterIndex));
00503 SAFE_FREE(data.dptr);
00504
00505
00506 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "");
00507 _reg_perfcount_get_counter_data(key, &data);
00508 if(data.dptr == NULL)
00509 {
00510 DEBUG(3, ("_reg_perfcount_get_counter_info: No counter data for counter [%d].\n", CounterIndex));
00511 return False;
00512 }
00513
00514 counter_size = _reg_perfcount_get_size_field(obj->counters[obj->NumCounters].CounterType);
00515
00516 if(counter_size == PERF_SIZE_DWORD)
00517 {
00518 dsize = sizeof(data32);
00519 memset(buf, 0, PERFCOUNT_MAX_LEN);
00520 memcpy(buf, data.dptr, data.dsize);
00521 data32 = strtol(buf, NULL, 0);
00522 if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER)
00523 obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale((SMB_BIG_INT)data32);
00524 else
00525 obj->counters[obj->NumCounters].DefaultScale = 0;
00526 dbuf[0] = data32;
00527 padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize;
00528 }
00529 else if(counter_size == PERF_SIZE_LARGE)
00530 {
00531 dsize = sizeof(data64);
00532 memset(buf, 0, PERFCOUNT_MAX_LEN);
00533 memcpy(buf, data.dptr, data.dsize);
00534 data64 = atof(buf);
00535 if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER)
00536 obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale(data64);
00537 else
00538 obj->counters[obj->NumCounters].DefaultScale = 0;
00539 memcpy((void *)dbuf, (const void *)&data64, dsize);
00540 padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize;
00541 }
00542 else
00543 {
00544 dsize = data.dsize;
00545 memset(buf, 0, PERFCOUNT_MAX_LEN);
00546 memcpy(buf, data.dptr, data.dsize);
00547 }
00548 SAFE_FREE(data.dptr);
00549
00550 obj->counter_data.ByteLength += dsize + padding;
00551 obj->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00552 obj->counter_data.data,
00553 uint8,
00554 obj->counter_data.ByteLength - sizeof(uint32));
00555 if(obj->counter_data.data == NULL)
00556 return False;
00557 if(dbuf[0] != 0 || dbuf[1] != 0)
00558 {
00559 memcpy((void *)(obj->counter_data.data +
00560 (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))),
00561 (const void *)dbuf, dsize);
00562 }
00563 else
00564 {
00565
00566 memcpy((void *)(obj->counter_data.data +
00567 (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))),
00568 (const void *)buf, dsize);
00569 }
00570 obj->counters[obj->NumCounters].CounterOffset = obj->counter_data.ByteLength - dsize;
00571 if(obj->counters[obj->NumCounters].CounterOffset % dsize != 0)
00572 {
00573 DEBUG(3,("Improperly aligned counter [%d]\n", obj->NumCounters));
00574 }
00575 obj->counters[obj->NumCounters].CounterSize = dsize;
00576
00577 return True;
00578 }
00579
00580
00581
00582
00583 PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind)
00584 {
00585 int i;
00586
00587 PERF_OBJECT_TYPE *obj = NULL;
00588
00589 for(i = 0; i < block->NumObjectTypes; i++)
00590 {
00591 if(block->objects[i].ObjectNameTitleIndex == objind)
00592 {
00593 obj = &(block->objects[i]);
00594 }
00595 }
00596
00597 return obj;
00598 }
00599
00600
00601
00602
00603 static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
00604 prs_struct *ps,
00605 int num,
00606 TDB_DATA data,
00607 TDB_CONTEXT *names)
00608 {
00609 char *begin, *end, *start, *stop;
00610 int parent;
00611 PERF_OBJECT_TYPE *obj;
00612 BOOL success = True;
00613 char buf[PERFCOUNT_MAX_LEN];
00614
00615 obj = NULL;
00616 memset(buf, 0, PERFCOUNT_MAX_LEN);
00617 memcpy(buf, data.dptr, data.dsize);
00618 begin = index(buf, '[');
00619 end = index(buf, ']');
00620 if(begin == NULL || end == NULL)
00621 return False;
00622 start = begin+1;
00623
00624 while(start < end) {
00625 stop = index(start, ',');
00626 if(stop == NULL)
00627 stop = end;
00628 *stop = '\0';
00629 parent = atoi(start);
00630
00631 obj = _reg_perfcount_find_obj(block, parent);
00632 if(obj == NULL) {
00633
00634
00635 DEBUG(3, ("_reg_perfcount_add_counter: Could not find parent object [%d] for counter [%d].\n",
00636 parent, num));
00637 return False;
00638 }
00639 obj->counters = (PERF_COUNTER_DEFINITION *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00640 obj->counters,
00641 PERF_COUNTER_DEFINITION,
00642 obj->NumCounters+1);
00643 if(obj->counters == NULL)
00644 return False;
00645 memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(PERF_COUNTER_DEFINITION));
00646 obj->counters[obj->NumCounters].CounterNameTitleIndex=num;
00647 obj->counters[obj->NumCounters].CounterHelpTitleIndex=num+1;
00648 obj->counters[obj->NumCounters].DetailLevel = PERF_DETAIL_NOVICE;
00649 obj->counters[obj->NumCounters].ByteLength = sizeof(PERF_COUNTER_DEFINITION);
00650 success = _reg_perfcount_get_counter_info(block, ps, num, obj, names);
00651 obj->NumCounters += 1;
00652 start = stop + 1;
00653 }
00654
00655
00656
00657
00658
00659 return success;
00660 }
00661
00662
00663
00664
00665 BOOL _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
00666 prs_struct *ps,
00667 int instId,
00668 PERF_OBJECT_TYPE *obj,
00669 TDB_CONTEXT *names)
00670 {
00671 TDB_DATA key, data;
00672 char buf[PERFCOUNT_MAX_LEN], temp[PERFCOUNT_MAX_LEN];
00673 wpstring name;
00674 int pad;
00675
00676
00677 memset(temp, 0, PERFCOUNT_MAX_LEN);
00678 snprintf(temp, PERFCOUNT_MAX_LEN, "i%d", instId);
00679 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
00680 _reg_perfcount_get_counter_data(key, &data);
00681 if(data.dptr == NULL)
00682 {
00683 DEBUG(3, ("_reg_perfcount_get_instance_info: No instance data for instance [%s].\n",
00684 buf));
00685 return False;
00686 }
00687 inst->counter_data.ByteLength = data.dsize + sizeof(inst->counter_data.ByteLength);
00688 inst->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00689 inst->counter_data.data,
00690 uint8,
00691 data.dsize);
00692 if(inst->counter_data.data == NULL)
00693 return False;
00694 memset(inst->counter_data.data, 0, data.dsize);
00695 memcpy(inst->counter_data.data, data.dptr, data.dsize);
00696 SAFE_FREE(data.dptr);
00697
00698
00699 memset(temp, 0, PERFCOUNT_MAX_LEN);
00700 snprintf(temp, PERFCOUNT_MAX_LEN, "i%dname", instId);
00701 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
00702 data = tdb_fetch(names, key);
00703 if(data.dptr == NULL)
00704 {
00705
00706 DEBUG(3, ("_reg_perfcount_get_instance_info: No instance name for instance [%s].\n",
00707 buf));
00708 inst->NameLength = 0;
00709 }
00710 else
00711 {
00712 memset(buf, 0, PERFCOUNT_MAX_LEN);
00713 memcpy(buf, data.dptr, data.dsize);
00714 rpcstr_push((void *)name, buf, sizeof(name), STR_TERMINATE);
00715 inst->NameLength = (strlen_w(name) * 2) + 2;
00716 inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00717 inst->data,
00718 uint8,
00719 inst->NameLength);
00720 if (inst->data == NULL) {
00721 SAFE_FREE(data.dptr);
00722 return False;
00723 }
00724 memcpy(inst->data, name, inst->NameLength);
00725 SAFE_FREE(data.dptr);
00726 }
00727
00728 inst->ParentObjectTitleIndex = 0;
00729 inst->ParentObjectTitlePointer = 0;
00730 inst->UniqueID = PERF_NO_UNIQUE_ID;
00731 inst->NameOffset = 6 * sizeof(uint32);
00732
00733 inst->ByteLength = inst->NameOffset + inst->NameLength;
00734
00735 if((pad = (inst->ByteLength % 8)))
00736 {
00737 pad = 8 - pad;
00738 inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00739 inst->data,
00740 uint8,
00741 inst->NameLength + pad);
00742 memset(inst->data + inst->NameLength, 0, pad);
00743 inst->ByteLength += pad;
00744 }
00745
00746 return True;
00747 }
00748
00749
00750
00751
00752 BOOL _reg_perfcount_add_instance(PERF_OBJECT_TYPE *obj,
00753 prs_struct *ps,
00754 int instInd,
00755 TDB_CONTEXT *names)
00756 {
00757 PERF_INSTANCE_DEFINITION *inst;
00758
00759 if(obj->instances == NULL) {
00760 obj->instances = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00761 obj->instances,
00762 PERF_INSTANCE_DEFINITION,
00763 obj->NumInstances);
00764 }
00765 if(obj->instances == NULL)
00766 return False;
00767
00768 memset(&(obj->instances[instInd]), 0, sizeof(PERF_INSTANCE_DEFINITION));
00769 inst = &(obj->instances[instInd]);
00770 return _reg_perfcount_get_instance_info(inst, ps, instInd, obj, names);
00771 }
00772
00773
00774
00775
00776 static int _reg_perfcount_assemble_global(PERF_DATA_BLOCK *block,
00777 prs_struct *ps,
00778 int base_index,
00779 TDB_CONTEXT *names)
00780 {
00781 BOOL success;
00782 int i, j, retval = 0;
00783 char keybuf[PERFCOUNT_MAX_LEN];
00784 TDB_DATA key, data;
00785
00786 for(i = 1; i <= base_index; i++)
00787 {
00788 j = i*2;
00789 _reg_perfcount_make_key(&key, keybuf, PERFCOUNT_MAX_LEN, j, "rel");
00790 data = tdb_fetch(names, key);
00791 if(data.dptr != NULL)
00792 {
00793 if(_reg_perfcount_isparent(data))
00794 success = _reg_perfcount_add_object(block, ps, j, data, names);
00795 else if(_reg_perfcount_ischild(data))
00796 success = _reg_perfcount_add_counter(block, ps, j, data, names);
00797 else
00798 {
00799 DEBUG(3, ("Bogus relationship [%s] for counter [%d].\n", data.dptr, j));
00800 success = False;
00801 }
00802 if(success == False)
00803 {
00804 DEBUG(3, ("_reg_perfcount_assemble_global: Failed to add new relationship for counter [%d].\n", j));
00805 retval = -1;
00806 }
00807 SAFE_FREE(data.dptr);
00808 }
00809 else
00810 DEBUG(3, ("NULL relationship for counter [%d] using key [%s].\n", j, keybuf));
00811 }
00812 return retval;
00813 }
00814
00815
00816
00817
00818 static BOOL _reg_perfcount_get_64(SMB_BIG_UINT *retval,
00819 TDB_CONTEXT *tdb,
00820 int key_part1,
00821 const char *key_part2)
00822 {
00823 TDB_DATA key, data;
00824 char buf[PERFCOUNT_MAX_LEN];
00825
00826 _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, key_part1, key_part2);
00827
00828 data = tdb_fetch(tdb, key);
00829 if(data.dptr == NULL)
00830 {
00831 DEBUG(3,("_reg_perfcount_get_64: No data found for key [%s].\n", key.dptr));
00832 return False;
00833 }
00834
00835 memset(buf, 0, PERFCOUNT_MAX_LEN);
00836 memcpy(buf, data.dptr, data.dsize);
00837 SAFE_FREE(data.dptr);
00838
00839 *retval = atof(buf);
00840
00841 return True;
00842 }
00843
00844
00845
00846
00847 static BOOL _reg_perfcount_init_data_block_perf(PERF_DATA_BLOCK *block,
00848 TDB_CONTEXT *names)
00849 {
00850 SMB_BIG_UINT PerfFreq, PerfTime, PerfTime100nSec;
00851 TDB_CONTEXT *counters;
00852 BOOL status = False;
00853 const char *fname = counters_directory( DATA_DB );
00854
00855 counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
00856
00857 if(counters == NULL)
00858 {
00859 DEBUG(1, ("reg_perfcount_init_data_block_perf: unable to open [%s].\n", fname));
00860 return False;
00861 }
00862
00863 status = _reg_perfcount_get_64(&PerfFreq, names, 0, "PerfFreq");
00864 if(status == False)
00865 {
00866 tdb_close(counters);
00867 return status;
00868 }
00869 memcpy((void *)&(block->PerfFreq), (const void *)&PerfFreq, sizeof(PerfFreq));
00870
00871 status = _reg_perfcount_get_64(&PerfTime, counters, 0, "PerfTime");
00872 if(status == False)
00873 {
00874 tdb_close(counters);
00875 return status;
00876 }
00877 memcpy((void *)&(block->PerfTime), (const void *)&PerfTime, sizeof(PerfTime));
00878
00879 status = _reg_perfcount_get_64(&PerfTime100nSec, counters, 0, "PerfTime100nSec");
00880 if(status == False)
00881 {
00882 tdb_close(counters);
00883 return status;
00884 }
00885 memcpy((void *)&(block->PerfTime100nSec), (const void *)&PerfTime100nSec, sizeof(PerfTime100nSec));
00886
00887 tdb_close(counters);
00888 return True;
00889 }
00890
00891
00892
00893
00894 static BOOL _reg_perfcount_init_data_block(PERF_DATA_BLOCK *block,
00895 prs_struct *ps, TDB_CONTEXT *names)
00896 {
00897 wpstring temp;
00898 time_t tm;
00899
00900 memset(temp, 0, sizeof(temp));
00901 rpcstr_push((void *)temp, "PERF", sizeof(temp), STR_TERMINATE);
00902 memcpy(block->Signature, temp, strlen_w(temp) *2);
00903
00904 if(ps->bigendian_data == RPC_BIG_ENDIAN)
00905 block->LittleEndian = 0;
00906 else
00907 block->LittleEndian = 1;
00908 block->Version = 1;
00909 block->Revision = 1;
00910 block->TotalByteLength = 0;
00911 block->NumObjectTypes = 0;
00912 block->DefaultObject = -1;
00913 block->objects = NULL;
00914 tm = time(NULL);
00915 make_systemtime(&(block->SystemTime), gmtime(&tm));
00916 _reg_perfcount_init_data_block_perf(block, names);
00917 memset(temp, 0, sizeof(temp));
00918 rpcstr_push((void *)temp, global_myname(), sizeof(temp), STR_TERMINATE);
00919 block->SystemNameLength = (strlen_w(temp) * 2) + 2;
00920 block->data = TALLOC_ZERO_ARRAY(ps->mem_ctx, uint8, block->SystemNameLength + (8 - (block->SystemNameLength % 8)));
00921 if (block->data == NULL) {
00922 return False;
00923 }
00924 memcpy(block->data, temp, block->SystemNameLength);
00925 block->SystemNameOffset = sizeof(PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data);
00926 block->HeaderLength = block->SystemNameOffset + block->SystemNameLength;
00927
00928
00929 block->HeaderLength += 8 - (block->HeaderLength % 8);
00930
00931 return True;
00932 }
00933
00934
00935
00936
00937 static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_struct *ps)
00938 {
00939 int obj, cnt, inst, pad, i;
00940 PERF_OBJECT_TYPE *object;
00941 PERF_INSTANCE_DEFINITION *instance;
00942 PERF_COUNTER_DEFINITION *counter;
00943 PERF_COUNTER_BLOCK *counter_data;
00944 char *temp = NULL, *src_addr, *dst_addr;
00945
00946 block->TotalByteLength = 0;
00947 object = block->objects;
00948 for(obj = 0; obj < block->NumObjectTypes; obj++)
00949 {
00950 object[obj].TotalByteLength = 0;
00951 object[obj].DefinitionLength = 0;
00952 instance = object[obj].instances;
00953 counter = object[obj].counters;
00954 for(cnt = 0; cnt < object[obj].NumCounters; cnt++)
00955 {
00956 object[obj].TotalByteLength += counter[cnt].ByteLength;
00957 object[obj].DefinitionLength += counter[cnt].ByteLength;
00958 }
00959 if(object[obj].NumInstances != PERF_NO_INSTANCES)
00960 {
00961 for(inst = 0; inst < object[obj].NumInstances; inst++)
00962 {
00963 instance = &(object[obj].instances[inst]);
00964 object[obj].TotalByteLength += instance->ByteLength;
00965 counter_data = &(instance->counter_data);
00966 counter = &(object[obj].counters[object[obj].NumCounters - 1]);
00967 counter_data->ByteLength = counter->CounterOffset + counter->CounterSize + sizeof(counter_data->ByteLength);
00968 temp = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00969 temp,
00970 char,
00971 counter_data->ByteLength- sizeof(counter_data->ByteLength));
00972 if (temp == NULL) {
00973 return 0;
00974 }
00975 memset(temp, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength));
00976 src_addr = (char *)counter_data->data;
00977 for(i = 0; i < object[obj].NumCounters; i++)
00978 {
00979 counter = &(object[obj].counters[i]);
00980 dst_addr = temp + counter->CounterOffset - sizeof(counter_data->ByteLength);
00981 memcpy(dst_addr, src_addr, counter->CounterSize);
00982 src_addr += counter->CounterSize;
00983 }
00984
00985 if((pad = (counter_data->ByteLength % 8)))
00986 {
00987 pad = 8 - pad;
00988 }
00989 counter_data->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
00990 counter_data->data,
00991 uint8,
00992 counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
00993 if (counter_data->data == NULL) {
00994 return 0;
00995 }
00996 memset(counter_data->data, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
00997 memcpy(counter_data->data, temp, counter_data->ByteLength - sizeof(counter_data->ByteLength));
00998 counter_data->ByteLength += pad;
00999 object[obj].TotalByteLength += counter_data->ByteLength;
01000 }
01001 }
01002 else
01003 {
01004
01005
01006 if((pad = (object[obj].counter_data.ByteLength % 8)))
01007 {
01008 pad = 8 - pad;
01009 object[obj].counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
01010 object[obj].counter_data.data,
01011 uint8,
01012 object[obj].counter_data.ByteLength + pad);
01013 memset((void *)(object[obj].counter_data.data + object[obj].counter_data.ByteLength), 0, pad);
01014 object[obj].counter_data.ByteLength += pad;
01015 }
01016 object[obj].TotalByteLength += object[obj].counter_data.ByteLength;
01017 }
01018 object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(PERF_COUNTER_BLOCK));
01019 object[obj].TotalByteLength += object[obj].HeaderLength;
01020 object[obj].DefinitionLength += object[obj].HeaderLength;
01021
01022 block->TotalByteLength += object[obj].TotalByteLength;
01023 }
01024
01025 return block->TotalByteLength;
01026 }
01027
01028
01029
01030
01031 uint32 reg_perfcount_get_perf_data_block(uint32 base_index,
01032 prs_struct *ps,
01033 PERF_DATA_BLOCK *block,
01034 char *object_ids)
01035 {
01036 uint32 buffer_size = 0;
01037 const char *fname = counters_directory( NAMES_DB );
01038 TDB_CONTEXT *names;
01039 int retval = 0;
01040
01041 names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
01042
01043 if(names == NULL)
01044 {
01045 DEBUG(1, ("reg_perfcount_get_perf_data_block: unable to open [%s].\n", fname));
01046 return 0;
01047 }
01048
01049 if (!_reg_perfcount_init_data_block(block, ps, names)) {
01050 DEBUG(0, ("_reg_perfcount_init_data_block failed\n"));
01051 tdb_close(names);
01052 return 0;
01053 }
01054
01055 reg_perfcount_get_last_counter(base_index);
01056
01057 if(object_ids == NULL)
01058 {
01059
01060 retval = _reg_perfcount_assemble_global(block, ps, base_index, names);
01061 }
01062 else
01063 {
01064
01065 retval = _reg_perfcount_assemble_global(block, ps, base_index, names);
01066 }
01067 buffer_size = _reg_perfcount_perf_data_block_fixup(block, ps);
01068
01069 tdb_close(names);
01070
01071 if (retval == -1) {
01072 return 0;
01073 }
01074
01075 return buffer_size + block->HeaderLength;
01076 }
01077
01078
01079
01080
01081 static BOOL _reg_perfcount_marshall_perf_data_block(prs_struct *ps, PERF_DATA_BLOCK block, int depth)
01082 {
01083 int i;
01084 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_data_block");
01085 depth++;
01086
01087 if(!prs_align(ps))
01088 return False;
01089 for(i = 0; i < 4; i++)
01090 {
01091 if(!prs_uint16("Signature", ps, depth, &block.Signature[i]))
01092 return False;
01093 }
01094 if(!prs_uint32("Little Endian", ps, depth, &block.LittleEndian))
01095 return False;
01096 if(!prs_uint32("Version", ps, depth, &block.Version))
01097 return False;
01098 if(!prs_uint32("Revision", ps, depth, &block.Revision))
01099 return False;
01100 if(!prs_uint32("TotalByteLength", ps, depth, &block.TotalByteLength))
01101 return False;
01102 if(!prs_uint32("HeaderLength", ps, depth, &block.HeaderLength))
01103 return False;
01104 if(!prs_uint32("NumObjectTypes", ps, depth, &block.NumObjectTypes))
01105 return False;
01106 if(!prs_uint32("DefaultObject", ps, depth, &block.DefaultObject))
01107 return False;
01108 if(!spoolss_io_system_time("SystemTime", ps, depth, &block.SystemTime))
01109 return False;
01110 if(!prs_uint32("Padding", ps, depth, &block.Padding))
01111 return False;
01112 if(!prs_align_uint64(ps))
01113 return False;
01114 if(!prs_uint64("PerfTime", ps, depth, &block.PerfTime))
01115 return False;
01116 if(!prs_uint64("PerfFreq", ps, depth, &block.PerfFreq))
01117 return False;
01118 if(!prs_uint64("PerfTime100nSec", ps, depth, &block.PerfTime100nSec))
01119 return False;
01120 if(!prs_uint32("SystemNameLength", ps, depth, &block.SystemNameLength))
01121 return False;
01122 if(!prs_uint32("SystemNameOffset", ps, depth, &block.SystemNameOffset))
01123 return False;
01124
01125 if(!prs_uint8s(False, "SystemName", ps, depth, block.data,
01126 block.HeaderLength - block.SystemNameOffset))
01127 return False;
01128
01129 return True;
01130 }
01131
01132
01133
01134
01135 static BOOL _reg_perfcount_marshall_perf_counters(prs_struct *ps,
01136 PERF_OBJECT_TYPE object,
01137 int depth)
01138 {
01139 int cnt;
01140 PERF_COUNTER_DEFINITION counter;
01141
01142 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counters");
01143 depth++;
01144
01145 for(cnt = 0; cnt < object.NumCounters; cnt++)
01146 {
01147 counter = object.counters[cnt];
01148
01149 if(!prs_align(ps))
01150 return False;
01151 if(!prs_uint32("ByteLength", ps, depth, &counter.ByteLength))
01152 return False;
01153 if(!prs_uint32("CounterNameTitleIndex", ps, depth, &counter.CounterNameTitleIndex))
01154 return False;
01155 if(!prs_uint32("CounterNameTitlePointer", ps, depth, &counter.CounterNameTitlePointer))
01156 return False;
01157 if(!prs_uint32("CounterHelpTitleIndex", ps, depth, &counter.CounterHelpTitleIndex))
01158 return False;
01159 if(!prs_uint32("CounterHelpTitlePointer", ps, depth, &counter.CounterHelpTitlePointer))
01160 return False;
01161 if(!prs_uint32("DefaultScale", ps, depth, &counter.DefaultScale))
01162 return False;
01163 if(!prs_uint32("DetailLevel", ps, depth, &counter.DetailLevel))
01164 return False;
01165 if(!prs_uint32("CounterType", ps, depth, &counter.CounterType))
01166 return False;
01167 if(!prs_uint32("CounterSize", ps, depth, &counter.CounterSize))
01168 return False;
01169 if(!prs_uint32("CounterOffset", ps, depth, &counter.CounterOffset))
01170 return False;
01171 }
01172
01173 return True;
01174 }
01175
01176
01177
01178
01179 static BOOL _reg_perfcount_marshall_perf_counter_data(prs_struct *ps,
01180 PERF_COUNTER_BLOCK counter_data,
01181 int depth)
01182 {
01183 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counter_data");
01184 depth++;
01185
01186 if(!prs_align_uint64(ps))
01187 return False;
01188
01189 if(!prs_uint32("ByteLength", ps, depth, &counter_data.ByteLength))
01190 return False;
01191 if(!prs_uint8s(False, "CounterData", ps, depth, counter_data.data, counter_data.ByteLength - sizeof(uint32)))
01192 return False;
01193 if(!prs_align_uint64(ps))
01194 return False;
01195
01196 return True;
01197 }
01198
01199
01200
01201
01202 static BOOL _reg_perfcount_marshall_perf_instances(prs_struct *ps,
01203 PERF_OBJECT_TYPE object,
01204 int depth)
01205 {
01206 PERF_INSTANCE_DEFINITION instance;
01207 int inst;
01208
01209 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_instances");
01210 depth++;
01211
01212 for(inst = 0; inst < object.NumInstances; inst++)
01213 {
01214 instance = object.instances[inst];
01215
01216 if(!prs_align(ps))
01217 return False;
01218 if(!prs_uint32("ByteLength", ps, depth, &instance.ByteLength))
01219 return False;
01220 if(!prs_uint32("ParentObjectTitleIndex", ps, depth, &instance.ParentObjectTitleIndex))
01221 return False;
01222 if(!prs_uint32("ParentObjectTitlePointer", ps, depth, &instance.ParentObjectTitlePointer))
01223 return False;
01224 if(!prs_uint32("UniqueID", ps, depth, &instance.UniqueID))
01225 return False;
01226 if(!prs_uint32("NameOffset", ps, depth, &instance.NameOffset))
01227 return False;
01228 if(!prs_uint32("NameLength", ps, depth, &instance.NameLength))
01229 return False;
01230 if(!prs_uint8s(False, "InstanceName", ps, depth, instance.data,
01231 instance.ByteLength - instance.NameOffset))
01232 return False;
01233 if(_reg_perfcount_marshall_perf_counter_data(ps, instance.counter_data, depth) == False)
01234 return False;
01235 }
01236
01237 return True;
01238 }
01239
01240
01241
01242
01243 static BOOL _reg_perfcount_marshall_perf_objects(prs_struct *ps, PERF_DATA_BLOCK block, int depth)
01244 {
01245 int obj;
01246
01247 PERF_OBJECT_TYPE object;
01248
01249 prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_objects");
01250 depth++;
01251
01252 for(obj = 0; obj < block.NumObjectTypes; obj++)
01253 {
01254 object = block.objects[obj];
01255
01256 if(!prs_align(ps))
01257 return False;
01258
01259 if(!prs_uint32("TotalByteLength", ps, depth, &object.TotalByteLength))
01260 return False;
01261 if(!prs_uint32("DefinitionLength", ps, depth, &object.DefinitionLength))
01262 return False;
01263 if(!prs_uint32("HeaderLength", ps, depth, &object.HeaderLength))
01264 return False;
01265 if(!prs_uint32("ObjectNameTitleIndex", ps, depth, &object.ObjectNameTitleIndex))
01266 return False;
01267 if(!prs_uint32("ObjectNameTitlePointer", ps, depth, &object.ObjectNameTitlePointer))
01268 return False;
01269 if(!prs_uint32("ObjectHelpTitleIndex", ps, depth, &object.ObjectHelpTitleIndex))
01270 return False;
01271 if(!prs_uint32("ObjectHelpTitlePointer", ps, depth, &object.ObjectHelpTitlePointer))
01272 return False;
01273 if(!prs_uint32("DetailLevel", ps, depth, &object.DetailLevel))
01274 return False;
01275 if(!prs_uint32("NumCounters", ps, depth, &object.NumCounters))
01276 return False;
01277 if(!prs_uint32("DefaultCounter", ps, depth, &object.DefaultCounter))
01278 return False;
01279 if(!prs_uint32("NumInstances", ps, depth, &object.NumInstances))
01280 return False;
01281 if(!prs_uint32("CodePage", ps, depth, &object.CodePage))
01282 return False;
01283 if(!prs_align_uint64(ps))
01284 return False;
01285 if(!prs_uint64("PerfTime", ps, depth, &object.PerfTime))
01286 return False;
01287 if(!prs_uint64("PerfFreq", ps, depth, &object.PerfFreq))
01288 return False;
01289
01290
01291
01292
01293 if(_reg_perfcount_marshall_perf_counters(ps, object, depth) == False)
01294 return False;
01295 if(object.NumInstances == PERF_NO_INSTANCES)
01296 {
01297 if(_reg_perfcount_marshall_perf_counter_data(ps, object.counter_data, depth) == False)
01298 return False;
01299 }
01300 else
01301 {
01302 if(_reg_perfcount_marshall_perf_instances(ps, object, depth) == False)
01303 return False;
01304 }
01305 }
01306
01307 return True;
01308 }
01309
01310
01311
01312
01313 static BOOL _reg_perfcount_marshall_hkpd(prs_struct *ps, PERF_DATA_BLOCK block)
01314 {
01315 int depth = 0;
01316 if(_reg_perfcount_marshall_perf_data_block(ps, block, depth) == True)
01317 {
01318 if(_reg_perfcount_marshall_perf_objects(ps, block, depth) == True)
01319 return True;
01320 }
01321 return False;
01322 }
01323
01324
01325
01326
01327 WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32 max_buf_size, uint32 *outbuf_len, char *object_ids)
01328 {
01329
01330
01331
01332
01333 PERF_DATA_BLOCK block;
01334 uint32 buffer_size, base_index;
01335
01336 buffer_size = 0;
01337 base_index = reg_perfcount_get_base_index();
01338 ZERO_STRUCT(block);
01339
01340 buffer_size = reg_perfcount_get_perf_data_block(base_index, ps, &block, object_ids);
01341
01342 if(buffer_size < max_buf_size)
01343 {
01344 *outbuf_len = buffer_size;
01345 if(_reg_perfcount_marshall_hkpd(ps, block) == True)
01346 return WERR_OK;
01347 else
01348 return WERR_NOMEM;
01349 }
01350 else
01351 {
01352 *outbuf_len = max_buf_size;
01353 _reg_perfcount_marshall_perf_data_block(ps, block, 0);
01354 return WERR_INSUFFICIENT_BUFFER;
01355 }
01356 }