00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
#include <nt.h>
00017
#include <ntrtl.h>
00018
#include <nturtl.h>
00019
#include <windows.h>
00020
#include <winuser.h>
00021
#include <winperf.h>
00022
#include <ntprfctr.h>
00023
#include <string.h>
00024
#include <wcstr.h>
00025
#include "userctrs.h"
00026
#include "perfmsg.h"
00027
#include "perfutil.h"
00028
#include "userdata.h"
00029
00030 #define ALL_PROCESSES_STRING L"_All Processes"
00031
00032
00033
00034
00035 #define QUC_PID_TOTAL 0xffffffff
00036 #define QUERYUSER_TYPE_USER 0x1
00037 #define QUERYUSER_TYPE_CS 0x2
00038
00039
00040
00041
00042
00043
00044
00045
00046 typedef struct _tagCSStatistics {
00047 DWORD cExclusive;
00048 DWORD cShared;
00049 __int64
i64TimeExclusive;
00050 }
CSSTATISTICS;
00051
00052 BOOL (WINAPI *QueryUserCounters)(
DWORD,
LPVOID,
DWORD,
LPVOID,
DWORD );
00053
00054
00055
00056
00057 extern USER_DATA_DEFINITION UserDataDefinition;
00058 extern CS_DATA_DEFINITION CSDataDefinition;
00059
00060
00061
00062
00063
00064 typedef struct _tagInstance {
00065 LPWSTR
pName;
00066 DWORD sizeName;
00067 DWORD id;
00068 }
ProcessInstance;
00069
00070 ProcessInstance *
gaInstances;
00071 int gNumInstances;
00072 PDWORD
gpPid;
00073 PDWORD
gpdwResult;
00074 DWORD dwOpenCount;
00075 HANDLE
ghHeap;
00076 BOOL gbInitOK;
00077
00078
00079
00080
00081
00082
00083
DWORD GlobalCollect(
00084 IN LPWSTR lpValueName,
00085 IN OUT LPVOID *lppData,
00086 IN OUT LPDWORD lpcbTotalBytes,
00087 IN OUT LPDWORD lpNumObjectTypes,
00088 IN DWORD dwQueryType);
00089
BOOL FillInstances(VOID);
00090
00091 PM_OPEN_PROC
OpenUserPerformanceData;
00092 PM_COLLECT_PROC
CollectUserPerformanceData;
00093 PM_CLOSE_PROC
CloseUserPerformanceData;
00094
00095
BOOL
00096 __stdcall
00097 DllInit(
00098 IN HANDLE DLLHandle,
00099 IN DWORD Reason,
00100 IN LPVOID ReservedAndUnused
00101 )
00102 {
00103
char szUser32DllPath[
MAX_PATH+15];
00104 HMODULE hUser32Module;
00105 ReservedAndUnused;
00106
00107
00108
00109 DisableThreadLibraryCalls (DLLHandle);
00110
00111
switch(Reason) {
00112
case DLL_PROCESS_ATTACH:
00113
00114
if (!GetSystemDirectory(szUser32DllPath,
MAX_PATH+1)) {
00115
return FALSE;
00116 }
00117 strcat( szUser32DllPath,
"\\user32.dll");
00118
00119 hUser32Module = GetModuleHandle(szUser32DllPath);
00120
if (!hUser32Module) {
00121
return FALSE;
00122 }
00123 QueryUserCounters = (
BOOL (WINAPI *)(
DWORD,
LPVOID,
DWORD,
LPVOID,
DWORD ))
00124 GetProcAddress(hUser32Module,
"QueryUserCounters");
00125
if (!QueryUserCounters) {
00126
return FALSE;
00127 }
00128
break;
00129
00130
case DLL_PROCESS_DETACH:
00131
break;
00132 }
00133
return TRUE;
00134 }
00135
00136 DWORD APIENTRY OpenUserPerformanceData(
00137 LPWSTR lpDeviceNames )
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 {
00152 LONG status;
00153 HKEY hKeyDriverPerf;
00154
DWORD size;
00155
DWORD type;
00156
DWORD dwFirstCounter;
00157
DWORD dwFirstHelp;
00158
00159 PDWORD pCounterNameTitleIndex;
00160 LPWSTR *pCounterNameTitle;
00161 PDWORD pCounterHelpTitleIndex;
00162 LPWSTR *pCounterHelpTitle;
00163
int i;
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
if (!
dwOpenCount) {
00175
00176
hEventLog =
MonOpenEventLog();
00177
00178
00179
00180
00181
00182
00183
00184 status = RegOpenKeyEx (
00185 HKEY_LOCAL_MACHINE,
00186
"SYSTEM\\CurrentControlSet\\Services\\PerfUser\\Performance",
00187 0
L,
00188 KEY_ALL_ACCESS,
00189 &hKeyDriverPerf);
00190
00191
if (status != ERROR_SUCCESS) {
00192
REPORT_ERROR_DATA (USERPERF_UNABLE_OPEN_DRIVER_KEY,
LOG_USER,
00193 &status,
sizeof(status));
00194
00195
00196
00197
00198
00199
00200
goto OpenExitPoint;
00201 }
00202
00203 size =
sizeof (
DWORD);
00204 status = RegQueryValueEx(
00205 hKeyDriverPerf,
00206
"First Counter",
00207 0
L,
00208 &
type,
00209 (LPBYTE)&dwFirstCounter,
00210 &size);
00211
00212
if (status != ERROR_SUCCESS) {
00213
REPORT_ERROR_DATA (USERPERF_UNABLE_READ_FIRST_COUNTER,
LOG_USER,
00214 &status,
sizeof(status));
00215
goto OpenExitPoint;
00216 }
00217
00218 status = RegQueryValueEx(
00219 hKeyDriverPerf,
00220
"First Help",
00221 0
L,
00222 &
type,
00223 (LPBYTE)&dwFirstHelp,
00224 &size);
00225
00226
if (status != ERROR_SUCCESS) {
00227
REPORT_ERROR_DATA (USERPERF_UNABLE_READ_FIRST_HELP,
LOG_USER,
00228 &status,
sizeof(status));
00229
goto OpenExitPoint;
00230 }
00231
00232
UserDataDefinition.
UserObjectType.ObjectNameTitleIndex += dwFirstCounter;
00233
UserDataDefinition.
UserObjectType.ObjectHelpTitleIndex += dwFirstHelp;
00234
00235 pCounterNameTitleIndex = &
UserDataDefinition.
NumTotals.CounterNameTitleIndex;
00236 pCounterHelpTitleIndex = &
UserDataDefinition.
NumTotals.CounterHelpTitleIndex;
00237
00238
for (i = 0; i<
NUM_USER_COUNTERS;
00239 i++,
00240 pCounterNameTitleIndex +=
sizeof(PERF_COUNTER_DEFINITION)/
sizeof(
DWORD),
00241 pCounterHelpTitleIndex +=
sizeof(PERF_COUNTER_DEFINITION)/
sizeof(
DWORD))
00242 {
00243 *pCounterNameTitleIndex += dwFirstCounter;
00244 *pCounterHelpTitleIndex += dwFirstHelp;
00245 }
00246
00247
00248
00249
CSDataDefinition.
CSObjectType.ObjectNameTitleIndex += dwFirstCounter;
00250
CSDataDefinition.
CSObjectType.ObjectHelpTitleIndex += dwFirstHelp;
00251
CSDataDefinition.
CSExEnter.CounterNameTitleIndex += dwFirstCounter;
00252
CSDataDefinition.
CSExEnter.CounterHelpTitleIndex += dwFirstHelp;
00253
CSDataDefinition.
CSShEnter.CounterNameTitleIndex += dwFirstCounter;
00254
CSDataDefinition.
CSShEnter.CounterHelpTitleIndex += dwFirstHelp;
00255
CSDataDefinition.
CSExTime.CounterNameTitleIndex += dwFirstCounter;
00256
CSDataDefinition.
CSExTime.CounterHelpTitleIndex += dwFirstHelp;
00257
00258 RegCloseKey (hKeyDriverPerf);
00259
gbInitOK =
TRUE;
00260 }
00261
00262
dwOpenCount++;
00263 status = ERROR_SUCCESS;
00264
00265 OpenExitPoint:
00266
00267
return status;
00268 }
00269
00270 DWORD APIENTRY CollectUserPerformanceData(
00271 IN LPWSTR lpValueName,
00272 IN OUT LPVOID *lppData,
00273 IN OUT LPDWORD lpcbTotalBytes,
00274 IN OUT LPDWORD lpNumObjectTypes)
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 {
00313
00314
00315 PERF_COUNTER_BLOCK *pPerfCounterBlock;
00316
USER_DATA_DEFINITION *pUserDataDefinition;
00317 ULONG SpaceNeeded;
00318 PDWORD pdwCounter, dwProcList;
00319
DWORD dwQueryType;
00320
DWORD dwObjects;
00321
int i;
00322
00323
00324
00325
00326
if (!
gbInitOK) {
00327
00328 *lpcbTotalBytes = (
DWORD) 0;
00329 *lpNumObjectTypes = (
DWORD) 0;
00330
return ERROR_SUCCESS;
00331 }
00332
00333
00334
00335
00336 dwQueryType =
GetQueryType (lpValueName);
00337
if (dwQueryType ==
QUERY_FOREIGN) {
00338
00339
00340
00341
00342 *lpcbTotalBytes = (
DWORD) 0;
00343 *lpNumObjectTypes = (
DWORD) 0;
00344
return ERROR_SUCCESS;
00345 }
00346
if (dwQueryType ==
QUERY_ITEMS) {
00347
if ( !(dwObjects =
IsNumberInUnicodeList (lpValueName) )) {
00348
00349
00350
00351
00352 *lpcbTotalBytes = (
DWORD) 0;
00353 *lpNumObjectTypes = (
DWORD) 0;
00354
return ERROR_SUCCESS;
00355
00356 }
00357
00358
return GlobalCollect(
00359 lpValueName,
00360 lppData,
00361 lpcbTotalBytes,
00362 lpNumObjectTypes,
00363 dwObjects);
00364 }
00365
else {
00366
00367
00368
00369
00370
return GlobalCollect(
00371 lpValueName,
00372 lppData,
00373 lpcbTotalBytes,
00374 lpNumObjectTypes,
00375
QUERY_NOCOUNTERS);
00376 }
00377
00378
return ERROR_SUCCESS;
00379 }
00380
00381
DWORD APIENTRY
00382 CloseUserPerformanceData()
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 {
00395
int i;
00396
if (!(--
dwOpenCount)) {
00397
MonCloseEventLog();
00398 }
00399
if (
gpdwResult)
00400
FREE(
gpdwResult);
00401
if (
gpPid)
00402
FREE(
gpPid);
00403
if (
gaInstances) {
00404
for (i = 0; i<
gNumInstances; i++) {
00405
FREE(
gaInstances[i].pName);
00406 }
00407
FREE(
gaInstances);
00408 }
00409
return ERROR_SUCCESS;
00410 }
00411
00412
00413
00414
00415
00416
00417 DWORD GlobalCollect(
00418 IN LPWSTR lpValueName,
00419 IN OUT LPVOID *lppData,
00420 IN OUT LPDWORD lpcbTotalBytes,
00421 IN OUT LPDWORD lpNumObjectTypes,
00422 IN DWORD dwQueryType)
00423 {
00424 PERF_COUNTER_BLOCK *pPerfCounterBlock;
00425
USER_DATA_DEFINITION *pUserDataDefinition;
00426
CS_DATA_DEFINITION *pCSDataDefinition;
00427
static CSSTATISTICS PrevCSStatistics;
00428
static __int64 i64Frecv;
00429 PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
00430 PDWORD pdwCounter;
00431
DWORD dwTotal, dwSpaceNeeded;
00432
int i, counter;
00433
00434
00435
00436
00437
00438
00439
00440
00441
if (dwQueryType & (
QUERY_USER |
QUERY_NOCOUNTERS)) {
00442
if (!
FillInstances()) {
00443 *lpcbTotalBytes = (
DWORD) 0;
00444 *lpNumObjectTypes = (
DWORD) 0;
00445
return ERROR_SUCCESS;
00446 }
00447 }
00448
00449
00450
00451
00452 dwSpaceNeeded = 0;
00453
if (dwQueryType & (
QUERY_USER |
QUERY_NOCOUNTERS)) {
00454 dwSpaceNeeded += (
gNumInstances)*(
00455
sizeof(PERF_INSTANCE_DEFINITION) +
00456
MAX_PATH *
sizeof (WCHAR) +
00457
sizeof(PERF_COUNTER_BLOCK) +
SIZE_OF_USER_PERFORMANCE_DATA) +
00458
sizeof(
USER_DATA_DEFINITION);
00459 }
00460
if (dwQueryType & (
QUERY_CS |
QUERY_NOCOUNTERS)) {
00461 dwSpaceNeeded +=
SIZE_OF_CS_PERFORMANCE_DATA
00462 +
sizeof(
CS_DATA_DEFINITION)
00463 +
sizeof(PERF_COUNTER_BLOCK);
00464 }
00465
if (*lpcbTotalBytes < dwSpaceNeeded) {
00466 *lpcbTotalBytes = (
DWORD) 0;
00467 *lpNumObjectTypes = (
DWORD) 0;
00468
return ERROR_MORE_DATA;
00469 }
00470
00471
00472
00473
00474
00475 *lpNumObjectTypes = 0;
00476
00477
00478
00479 pUserDataDefinition = (
USER_DATA_DEFINITION *) *lppData;
00480 pdwCounter = (
DWORD *) *lppData;
00481
00482
if (dwQueryType & (
QUERY_USER |
QUERY_NOCOUNTERS)) {
00483
00484
00485
00486 (*lpNumObjectTypes) ++;
00487
00488
if (dwQueryType &
QUERY_USER) {
00489
if (!
NT_SUCCESS(QueryUserCounters(
QUERYUSER_TYPE_USER,
00490
gpPid,
gNumInstances*
sizeof(
DWORD),
00491
gpdwResult, (
NUM_USER_COUNTERS-1)*
gNumInstances*
sizeof(
DWORD)))) {
00492 *lpcbTotalBytes = (
DWORD) 0;
00493 *lpNumObjectTypes = (
DWORD) 0;
00494
return ERROR_SUCCESS;
00495 }
00496 }
00497
else {
00498 memset(
gpdwResult, 0,
sizeof(
DWORD)*
gNumInstances*
NUM_USER_COUNTERS);
00499 }
00500
00501
00502
00503
00504 memmove(pUserDataDefinition, &
UserDataDefinition,
sizeof(
USER_DATA_DEFINITION));
00505 pUserDataDefinition->
UserObjectType.NumInstances =
gNumInstances;
00506
00507 pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *) &pUserDataDefinition[1];
00508
for (i = 0; i <
gNumInstances; i++) {
00509
00510
00511
00512
00513 pPerfInstanceDefinition->ParentObjectTitleIndex = 0;
00514 pPerfInstanceDefinition->ParentObjectInstance = 0;
00515 pPerfInstanceDefinition->UniqueID = (LONG)
gaInstances[i].
id;
00516 pPerfInstanceDefinition->NameOffset =
sizeof(PERF_INSTANCE_DEFINITION);
00517 pPerfInstanceDefinition->NameLength =
gaInstances[i].
sizeName;
00518
00519 pPerfInstanceDefinition->ByteLength =
sizeof(PERF_INSTANCE_DEFINITION) +
00520 pPerfInstanceDefinition->NameLength;
00521
00522 wcscpy((
wchar_t*)((
PBYTE)pPerfInstanceDefinition +
sizeof(PERF_INSTANCE_DEFINITION)),
00523
gaInstances[i].pName);
00524
00525 pPerfCounterBlock = (PERF_COUNTER_BLOCK *) ((
PBYTE)pPerfInstanceDefinition
00526 + pPerfInstanceDefinition->ByteLength);
00527
00528 pPerfCounterBlock->ByteLength =
SIZE_OF_USER_PERFORMANCE_DATA;
00529 pdwCounter = (PDWORD) (&pPerfCounterBlock[1]);
00530
00531
for (counter = dwTotal = 0; counter<
NUM_USER_COUNTERS-1; counter++) {
00532 dwTotal +=
gpdwResult[i*(
NUM_USER_COUNTERS-1)+counter];
00533 }
00534 *pdwCounter++ = dwTotal;
00535 memmove(pdwCounter,
gpdwResult + i*(
NUM_USER_COUNTERS-1), (
NUM_USER_COUNTERS-1)*
sizeof(
DWORD));
00536 pdwCounter +=
NUM_USER_COUNTERS-1;
00537
00538 pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)pdwCounter;
00539 }
00540
00541 ((
USER_DATA_DEFINITION *)*lppData)->UserObjectType.TotalByteLength =
00542 (ULONG)((
PBYTE)pdwCounter - (
PBYTE)pUserDataDefinition);
00543 }
00544
00545
if (dwQueryType & (
QUERY_CS |
QUERY_NOCOUNTERS)) {
00546
00547
00548
00549 (*lpNumObjectTypes) ++;
00550
00551
00552
00553
00554
00555
00556
00557 pCSDataDefinition = (
CS_DATA_DEFINITION *)pdwCounter;
00558 memmove(pCSDataDefinition, &
CSDataDefinition,
sizeof(
CS_DATA_DEFINITION));
00559
00560 pPerfCounterBlock = (PERF_COUNTER_BLOCK *) &pCSDataDefinition[1];
00561 pPerfCounterBlock->ByteLength =
SIZE_OF_CS_PERFORMANCE_DATA;
00562
00563 pdwCounter = (
DWORD *) &pPerfCounterBlock[1];
00564
00565
if (dwQueryType &
QUERY_NOCOUNTERS) {
00566 memset(pdwCounter, 0,
sizeof(
DWORD)*
NUM_CS_COUNTERS);
00567 }
00568
else {
00569
CSSTATISTICS CSCounters;
00570
00571
00572
00573
00574
00575
if (!PrevCSStatistics.
i64TimeExclusive) {
00576
00577
if (!QueryPerformanceFrequency((LARGE_INTEGER*)&i64Frecv))
00578 i64Frecv = 0;
00579 }
00580
00581
00582
00583
if (!QueryUserCounters(
QUERYUSER_TYPE_CS,
NULL, 0, &CSCounters,
sizeof(
CSSTATISTICS))) {
00584
REPORT_ERROR (USERPERF_CS_CANT_QUERY,
LOG_USER);
00585 }
00586
00587
00588
00589 *pdwCounter = CSCounters.
cExclusive - PrevCSStatistics.
cExclusive;
00590 *(pdwCounter + 1) = CSCounters.
cShared - PrevCSStatistics.
cShared;
00591
00592
if (i64Frecv) {
00593
00594
00595
00596 *(pdwCounter + 2) = (
DWORD)((CSCounters.
i64TimeExclusive-PrevCSStatistics.
i64TimeExclusive)*1000/i64Frecv);
00597 }
00598
else {
00599
00600
00601
00602 *(pdwCounter + 2) = 0;
00603 }
00604
00605 PrevCSStatistics.
cExclusive = CSCounters.
cExclusive;
00606 PrevCSStatistics.
cShared = CSCounters.
cShared;
00607 PrevCSStatistics.
i64TimeExclusive = CSCounters.
i64TimeExclusive;
00608 }
00609 pdwCounter +=
NUM_CS_COUNTERS;
00610 }
00611
00612
00613
00614
00615
00616 *lpcbTotalBytes = (ULONG)((
PBYTE)pdwCounter - (
PBYTE)*lppData);
00617 *lppData = (PVOID) pdwCounter;
00618
00619
return ERROR_SUCCESS;
00620 }
00621
00622
00623 VOID CleanUpInstances(VOID)
00624
00625
00626
00627
00628
00629
00630 {
00631
int i;
00632
00633
if (
gaInstances) {
00634
for (i = 0; i<
gNumInstances; i++) {
00635
FREE(
gaInstances[i].pName);
00636 }
00637
FREE(
gaInstances);
00638
gaInstances =
NULL;
00639 }
00640 }
00641
00642 BOOL FillInstances(VOID)
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 {
00655 PSYSTEM_PROCESS_INFORMATION ProcessInfo;
00656 ULONG TotalOffset = 0, ResultLength;
00657 PWCHAR p, pPeriod;
00658
DWORD status;
00659 UCHAR *pLargeBuffer;
00660
int cNumAllocatedInstances;
00661
int i, oldInstances;
00662
00663 oldInstances =
gNumInstances;
00664
gNumInstances = 0;
00665
00666
CleanUpInstances();
00667
00668
if (!(pLargeBuffer =
ALLOC(
sizeof(UCHAR)*64*1024))) {
00669
REPORT_ERROR_DATA (STATUS_NO_MEMORY,
LOG_USER,
00670 &status,
sizeof(status));
00671
return FALSE;
00672 }
00673
00674 status =
NtQuerySystemInformation(
00675 SystemProcessInformation,
00676 pLargeBuffer,
00677
sizeof(UCHAR)*64*1024,
00678 &ResultLength);
00679
if (!
NT_SUCCESS(status)) {
00680
goto ExitNoMemory;
00681 }
00682
00683 cNumAllocatedInstances = ResultLength/
sizeof(SYSTEM_PROCESS_INFORMATION);
00684
gaInstances =
ALLOC(cNumAllocatedInstances*
sizeof(
ProcessInstance));
00685
if (!
gaInstances) {
00686
00687
REPORT_ERROR_DATA (STATUS_NO_MEMORY,
LOG_USER,
00688 &status,
sizeof(status));
00689
goto ExitNoMemory;
00690 }
00691
00692
00693
00694
00695
00696
gaInstances[
gNumInstances].
sizeName =
sizeof(
ALL_PROCESSES_STRING);
00697
gaInstances[
gNumInstances].
id =
QUC_PID_TOTAL;
00698
gaInstances[
gNumInstances].
pName =
ALLOC(
gaInstances[
gNumInstances].sizeName);
00699
if (!
gaInstances[
gNumInstances].
pName) {
00700
REPORT_ERROR_DATA (STATUS_NO_MEMORY,
LOG_USER,
00701 &status,
sizeof(status));
00702
goto ExitNoMemory;
00703 }
00704 wcscpy(
gaInstances[
gNumInstances].pName,
ALL_PROCESSES_STRING);
00705
gNumInstances++;
00706
00707 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pLargeBuffer;
00708
while (
TRUE) {
00709
if ( ProcessInfo->ImageName.Buffer ) {
00710 p = wcsrchr(ProcessInfo->ImageName.Buffer,
L'\\');
00711
if ( p ) {
00712 p++;
00713 }
00714
else {
00715 p = ProcessInfo->ImageName.Buffer;
00716 }
00717
00718
00719
00720
if (pPeriod = wcsrchr(p,
L'.'))
00721 *pPeriod =
L'\0';
00722 }
00723
else {
00724 p =
L"SystemProc";
00725 }
00726
gaInstances[
gNumInstances].
sizeName = wcslen(p);
00727
00728
00729
00730
gaInstances[
gNumInstances].
sizeName = (
gaInstances[
gNumInstances].
sizeName + 1)
00731 *
sizeof(WCHAR);
00732
gaInstances[
gNumInstances].
pName =
ALLOC(
gaInstances[
gNumInstances].sizeName);
00733
if (!
gaInstances[
gNumInstances].
pName) {
00734
REPORT_ERROR_DATA (STATUS_NO_MEMORY,
LOG_USER,
00735 &status,
sizeof(status));
00736
goto ExitNoMemory;
00737 }
00738 wcscpy(
gaInstances[
gNumInstances].pName, p);
00739
gaInstances[
gNumInstances].
id = (WORD)ProcessInfo->UniqueProcessId;
00740
gNumInstances++;
00741
00742
if (ProcessInfo->NextEntryOffset == 0) {
00743
break;
00744 }
00745 TotalOffset += ProcessInfo->NextEntryOffset;
00746 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((
BYTE*)pLargeBuffer + TotalOffset);
00747 }
00748
00749
FREE(pLargeBuffer);
00750 pLargeBuffer =
NULL;
00751
00752
if (oldInstances !=
gNumInstances) {
00753
00754
00755
00756
if (
gpdwResult)
00757
FREE(
gpdwResult);
00758
if (
gpPid)
00759
FREE(
gpPid);
00760
00761
if (!(
gpdwResult =
ALLOC(
sizeof(
DWORD)*
gNumInstances*
NUM_USER_COUNTERS))) {
00762
gpdwResult =
NULL;
00763
goto ExitNoMemory;
00764 }
00765
00766
if (!(
gpPid =
ALLOC(
sizeof(
DWORD)*
gNumInstances))) {
00767
gpPid =
NULL;
00768
goto ExitNoMemory;
00769 }
00770
for (i = 0; i <
gNumInstances; i++) {
00771
gpPid[i] =
gaInstances[i].
id;
00772 }
00773 }
00774
return TRUE;
00775
00776 ExitNoMemory:
00777
00778
CleanUpInstances();
00779
00780
if (pLargeBuffer) {
00781
FREE(pLargeBuffer);
00782 }
00783
gbInitOK =
FALSE;
00784
return FALSE;
00785
00786 }