Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

920 lines
28 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. perfset.c
  5. Abstract:
  6. This file contains the functions that implement the PerformanceDLL of the
  7. REPLICASET Object.
  8. Author:
  9. Rohan Kumar [rohank] 13-Sept-1998
  10. Environment:
  11. User Mode Service
  12. Revision History:
  13. --*/
  14. #include "REPSET.h"
  15. #include "perfutil.h"
  16. #include "NTFRSREP.h"
  17. //
  18. // Future Cleanup: Really need a struct to encapsulate this state so the same code
  19. // can be used for both the replica set and connection perfmon objects
  20. //
  21. // Should Perfmon return Data ? This boolean is set in the DllMain function.
  22. //
  23. extern BOOLEAN ShouldPerfmonCollectData;
  24. //
  25. // Data Variable definition
  26. //
  27. REPLICASET_DATA_DEFINITION ReplicaSetDataDefinition;
  28. //
  29. // Extern variable definition
  30. //
  31. extern ReplicaSetValues RepSetInitData[FRS_NUMOFCOUNTERS];
  32. //
  33. // Sum of counter sizes + SIZEOFDWORD
  34. //
  35. DWORD SizeOfReplicaSetPerformanceData = 0;
  36. //
  37. // Number of "Open" threads
  38. //
  39. DWORD FRS_dwOpenCount = 0;
  40. //
  41. // Data structure used by the Open RPC Call
  42. //
  43. OpenRpcData *FRS_datapackage = NULL;
  44. //
  45. // Data structure used by the Collect RPC Call
  46. //
  47. CollectRpcData *FRS_collectpakg = NULL;
  48. //
  49. // Used to filter duplicate eventlog messages.
  50. //
  51. BOOLEAN FRS_Op = TRUE, FRS_Cl = TRUE;
  52. //
  53. // Signatures of functions implemented in this file
  54. //
  55. VOID InitializeTheRepSetObjectData(); // Handles the initialization of ReplicaSetDataDefinition
  56. PM_OPEN_PROC OpenReplicaSetPerformanceData; // The Open function
  57. PM_COLLECT_PROC CollectReplicaSetPerformanceData; // The Collect function
  58. PM_CLOSE_PROC CloseReplicaSetPerformanceData; // The Close function
  59. VOID FreeReplicaSetData(); // Frees the allocated memory
  60. PVOID FRSPerfAlloc(IN DWORD Size); // Allocates memory
  61. DWORD
  62. FRC_BindTheRpcHandle (
  63. OUT handle_t *OutHandle
  64. );
  65. VOID
  66. InitializeTheRepSetObjectData (
  67. VOID
  68. )
  69. /*++
  70. Routine Description:
  71. This routine initializes the ReplicaSetDataDefinition data structure.
  72. Arguments:
  73. none
  74. Return Value:
  75. none
  76. --*/
  77. {
  78. LONG i, j;
  79. PPERF_OBJECT_TYPE PerfObject;
  80. PPERF_COUNTER_DEFINITION CounterDef;
  81. //
  82. // Initialization of ReplicaSetObjectType (PERF_OBJECT_TYPE) field. This structure
  83. // is defined in the file winperf.h
  84. //
  85. PerfObject = &ReplicaSetDataDefinition.ReplicaSetObjectType;
  86. PerfObject->TotalByteLength = sizeof(REPLICASET_DATA_DEFINITION);
  87. PerfObject->DefinitionLength = sizeof(REPLICASET_DATA_DEFINITION);
  88. PerfObject->HeaderLength = sizeof(PERF_OBJECT_TYPE);
  89. PerfObject->ObjectNameTitleIndex = OBJREPLICASET;
  90. PerfObject->ObjectNameTitle = 0;
  91. PerfObject->ObjectHelpTitleIndex = OBJREPLICASET;
  92. PerfObject->ObjectHelpTitle = 0;
  93. PerfObject->DetailLevel = PERF_DETAIL_NOVICE;
  94. PerfObject->NumCounters = FRS_NUMOFCOUNTERS;
  95. PerfObject->DefaultCounter = 0;
  96. PerfObject->NumInstances = PERF_NO_INSTANCES;
  97. PerfObject->CodePage = 0;
  98. //
  99. // Initialization of NumStat (PERF_COUNTER_DEFINITION) structures.
  100. //
  101. for (i = 0, j = 2; i < FRS_NUMOFCOUNTERS; i++, j += 2) {
  102. CounterDef = &ReplicaSetDataDefinition.NumStat[i];
  103. CounterDef->ByteLength = sizeof(PERF_COUNTER_DEFINITION);
  104. CounterDef->CounterNameTitleIndex = j;
  105. CounterDef->CounterNameTitle = 0;
  106. CounterDef->CounterHelpTitleIndex = j;
  107. CounterDef->CounterHelpTitle = 0;
  108. CounterDef->DefaultScale = 0;
  109. CounterDef->DetailLevel = PERF_DETAIL_NOVICE;
  110. CounterDef->CounterType = RepSetInitData[i].counterType;
  111. CounterDef->CounterSize = RepSetInitData[i].size;
  112. CounterDef->CounterOffset = RepSetInitData[i].offset +
  113. SSIZEOFDWORD;
  114. }
  115. //
  116. // Set the total size of the counter data types
  117. //
  118. SizeOfReplicaSetPerformanceData = SIZEOF_REPSET_COUNTER_DATA +
  119. SSIZEOFDWORD;
  120. }
  121. DWORD APIENTRY
  122. OpenReplicaSetPerformanceData (
  123. IN LPWSTR lpDeviceNames
  124. )
  125. /*++
  126. Routine Description:
  127. This routine does the following:
  128. 1. Sets up the data structures (field values of structures used by PERFMON)
  129. used for collecting the counter data.
  130. 2. Gets the numerical indices for Instance names from the server using RPC.
  131. Arguments:
  132. lpDeviceNames - Pointer to the Instance list
  133. Return Value:
  134. ERROR_SUCCESS - The Initialization was successful OR
  135. Appropriate DWORD value for the Error status
  136. --*/
  137. {
  138. LONG WStatus, tot = 0, i;
  139. HKEY hKeyDriverPerf;
  140. DWORD size, type;
  141. DWORD dwFirstCounter, dwFirstHelp; // To store the first counter and first help values
  142. //
  143. // Additions for instances
  144. //
  145. size_t len;
  146. PWCHAR p, q;
  147. INT j, namelen = 0;
  148. handle_t Handle;
  149. PPERF_COUNTER_DEFINITION CounterDef;
  150. //
  151. // If InitializeCriticalSection in DllMain raised an exception, no point
  152. // in continuing.
  153. //
  154. if (!ShouldPerfmonCollectData) {
  155. return ERROR_OUTOFMEMORY;
  156. }
  157. //
  158. // Keep track of the number of times open has been called. The Registry
  159. // routines will limit the access to the initialization routine to only
  160. // on thread at a time, so synchronization should not be a problem. The
  161. // FRS_ThrdCounter is used to synchronize between this (Open) and the Close
  162. // functions.
  163. //
  164. EnterCriticalSection(&FRS_ThrdCounter);
  165. if (FRS_dwOpenCount != 0) {
  166. //
  167. // Increment the FRS_dwOpenCount counter which counts the number of
  168. // times Open has been called.
  169. //
  170. FRS_dwOpenCount++;
  171. LeaveCriticalSection(&FRS_ThrdCounter);
  172. return ERROR_SUCCESS;
  173. }
  174. LeaveCriticalSection(&FRS_ThrdCounter);
  175. //
  176. // Perform some preliminary checks.
  177. //
  178. if (FRS_collectpakg != NULL || FRS_datapackage != NULL) {
  179. //
  180. // We seem to have failed (in the last call) in the middle of this
  181. // Open function. For now, just bail.
  182. //
  183. return ERROR_NOT_SUPPORTED;
  184. }
  185. //
  186. // Do the necessary initialization of the PERFMON data structures
  187. //
  188. InitializeTheRepSetObjectData();
  189. //
  190. // Get the counter and help index base values from the registry. Open key
  191. // to registry entry, read the First Counter and First Help values. Update
  192. // the static data structures by adding base to offset value in the structure
  193. //
  194. WStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  195. L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaSet\\Performance",
  196. 0L,
  197. KEY_ALL_ACCESS,
  198. &hKeyDriverPerf);
  199. if (WStatus != ERROR_SUCCESS) {
  200. //
  201. // Fatal error. No point in continuing.
  202. // Clean up and exit.
  203. //
  204. FilterAndPrintToEventLog(FRS_Op, NTFRSPRF_REGISTRY_ERROR_SET);
  205. return WStatus;
  206. }
  207. size = sizeof(DWORD);
  208. WStatus = RegQueryValueEx (hKeyDriverPerf,
  209. L"First Counter",
  210. 0L,
  211. &type,
  212. (LPBYTE)&dwFirstCounter,
  213. &size);
  214. if (WStatus != ERROR_SUCCESS || type != REG_DWORD) {
  215. //
  216. // Fatal error. No point in continuing. Clean up and exit.
  217. //
  218. RegCloseKey (hKeyDriverPerf); // Close the registry key
  219. FilterAndPrintToEventLog(FRS_Op, NTFRSPRF_REGISTRY_ERROR_SET);
  220. return WStatus;
  221. }
  222. size = sizeof(DWORD);
  223. WStatus = RegQueryValueEx (hKeyDriverPerf,
  224. L"First Help",
  225. 0L,
  226. &type,
  227. (LPBYTE)&dwFirstHelp,
  228. &size);
  229. if (WStatus != ERROR_SUCCESS || type != REG_DWORD) {
  230. //
  231. // Fatal error. No point in continuing. Clean up and exit.
  232. //
  233. RegCloseKey (hKeyDriverPerf); // Close the registry key
  234. FilterAndPrintToEventLog(FRS_Op, NTFRSPRF_REGISTRY_ERROR_SET);
  235. return WStatus;
  236. }
  237. //
  238. // Add the offsets to the name and help fields
  239. //
  240. ReplicaSetDataDefinition.ReplicaSetObjectType.ObjectNameTitleIndex += dwFirstCounter;
  241. ReplicaSetDataDefinition.ReplicaSetObjectType.ObjectHelpTitleIndex += dwFirstHelp;
  242. for (i = 0; i < FRS_NUMOFCOUNTERS; i++) {
  243. CounterDef = &ReplicaSetDataDefinition.NumStat[i];
  244. CounterDef->CounterNameTitleIndex += dwFirstCounter;
  245. CounterDef->CounterHelpTitleIndex += dwFirstHelp;
  246. }
  247. RegCloseKey (hKeyDriverPerf); // Close the registry key
  248. //
  249. // Check if there are any instances. If there are, parse and set them in a structure
  250. // to be sent to the server to get the indices for the instance names. These indices
  251. // are used in the collect function to get the data
  252. //
  253. if (lpDeviceNames != NULL) {
  254. //
  255. // yes, there are
  256. //
  257. q = (PWCHAR) lpDeviceNames;
  258. //
  259. // Calculate the number of instances
  260. //
  261. while (TRUE) {
  262. tot++;
  263. p = wcschr(q, L'\0');
  264. if (*(p + 1) == L'\0') {
  265. break;
  266. }
  267. q = p + 1;
  268. }
  269. //
  270. // Set the data structure to be sent to the server using RPC
  271. //
  272. FRS_datapackage = (OpenRpcData *) FRSPerfAlloc (sizeof(OpenRpcData));
  273. NTFRS_MALLOC_TEST(FRS_datapackage, FreeReplicaSetData(), FALSE);
  274. FRS_datapackage->majorver = MAJORVERSION;
  275. FRS_datapackage->minorver = MINORVERSION;
  276. FRS_datapackage->ObjectType = REPSET;
  277. FRS_datapackage->numofinst = tot;
  278. FRS_datapackage->ver = (PLONG) FRSPerfAlloc (sizeof(LONG));
  279. NTFRS_MALLOC_TEST(FRS_datapackage->ver, FreeReplicaSetData(), FALSE);
  280. FRS_datapackage->indices = (inst_index *) FRSPerfAlloc (sizeof(inst_index));
  281. NTFRS_MALLOC_TEST(FRS_datapackage->indices, FreeReplicaSetData(), FALSE);
  282. FRS_datapackage->indices->size = tot;
  283. FRS_datapackage->indices->index = (PLONG) FRSPerfAlloc (FRS_datapackage->numofinst * sizeof(LONG));
  284. NTFRS_MALLOC_TEST(FRS_datapackage->indices->index, FreeReplicaSetData(), FALSE);
  285. FRS_datapackage->instnames = (InstanceNames *) FRSPerfAlloc (sizeof(InstanceNames));
  286. NTFRS_MALLOC_TEST(FRS_datapackage->instnames, FreeReplicaSetData(), FALSE);
  287. FRS_datapackage->instnames->size = tot;
  288. FRS_datapackage->instnames->InstanceNames = (inst_name *) FRSPerfAlloc (tot * sizeof(inst_name));
  289. NTFRS_MALLOC_TEST(FRS_datapackage->instnames->InstanceNames, FreeReplicaSetData(), FALSE);
  290. //
  291. // Copy the instance names and set the corresponding size value used by RPC
  292. //
  293. q = (PWCHAR) lpDeviceNames;
  294. for (j = 0; j < FRS_datapackage->numofinst; j++) {
  295. p = wcschr(q, L'\0');
  296. len = wcslen (q);
  297. FRS_datapackage->instnames->InstanceNames[j].size = len + 1;
  298. FRS_datapackage->instnames->InstanceNames[j].name =
  299. (PWCHAR) FRSPerfAlloc ((len + 1) * sizeof(WCHAR));
  300. NTFRS_MALLOC_TEST(FRS_datapackage->instnames->InstanceNames[j].name, FreeReplicaSetData(), FALSE);
  301. wcscpy(FRS_datapackage->instnames->InstanceNames[j].name, q);
  302. //
  303. // Calculte the total length of all the instance names
  304. // The extra 1 is for the '\0' character. The names are rounded
  305. // upto the next 8 byte boundary.
  306. //
  307. namelen += (((((len + 1) * sizeof(WCHAR)) + 7) >> 3) << 3);
  308. q = p + 1;
  309. }
  310. //
  311. // Set the totalbytelength and NumInstances fields of the PERF_OBJECT_TYPE Data structure,
  312. // now that we know the number of instances and the length of their names
  313. //
  314. ReplicaSetDataDefinition.ReplicaSetObjectType.TotalByteLength +=
  315. namelen +
  316. FRS_datapackage->numofinst *
  317. (SizeOfReplicaSetPerformanceData + SSIZEOFDWORD +
  318. sizeof(PERF_INSTANCE_DEFINITION));
  319. ReplicaSetDataDefinition.ReplicaSetObjectType.NumInstances =
  320. FRS_datapackage->numofinst;
  321. //
  322. // Bind the RPC handle
  323. //
  324. if ( (WStatus = FRC_BindTheRpcHandle(&Handle)) != ERROR_SUCCESS) {
  325. //
  326. // Fatal Error
  327. // Free up the memory and return
  328. //
  329. FilterAndPrintToEventLog(FRS_Op,
  330. NTFRSPRF_OPEN_RPC_BINDING_ERROR_SET);
  331. FreeReplicaSetData();
  332. return WStatus;
  333. }
  334. //
  335. // (RP)Call the server to set the indices of the instance names
  336. //
  337. if ( (WStatus = GetIndicesOfInstancesFromServer(Handle, FRS_datapackage)) != ERROR_SUCCESS) {
  338. //
  339. // Fatal Error
  340. // Free up the memory and return
  341. //
  342. FilterAndPrintToEventLog(FRS_Op,
  343. NTFRSPRF_OPEN_RPC_CALL_ERROR_SET);
  344. RpcBindingFree(&Handle);
  345. FreeReplicaSetData();
  346. return WStatus;
  347. }
  348. //
  349. // Set the data structure used by the RPC call in the Collect function
  350. //
  351. FRS_collectpakg = (CollectRpcData *) FRSPerfAlloc (sizeof(CollectRpcData));
  352. NTFRS_MALLOC_TEST(FRS_collectpakg, FreeReplicaSetData(), TRUE);
  353. FRS_collectpakg->majorver = MAJORVERSION;
  354. FRS_collectpakg->minorver = MINORVERSION;
  355. FRS_collectpakg->ObjectType = REPSET;
  356. FRS_collectpakg->ver = *(FRS_datapackage->ver);
  357. FRS_collectpakg->numofinst = FRS_datapackage->numofinst;
  358. FRS_collectpakg->numofcotrs = FRS_NUMOFCOUNTERS;
  359. FRS_collectpakg->indices = (inst_index *) FRSPerfAlloc (sizeof(inst_index));
  360. NTFRS_MALLOC_TEST(FRS_collectpakg->indices, FreeReplicaSetData(), TRUE);
  361. FRS_collectpakg->indices->size = FRS_datapackage->indices->size;
  362. FRS_collectpakg->indices->index = (PLONG) FRSPerfAlloc (FRS_collectpakg->indices->size * sizeof(LONG));
  363. NTFRS_MALLOC_TEST(FRS_collectpakg->indices->index, FreeReplicaSetData(), TRUE);
  364. //
  365. // Copy the indices got from the server
  366. //
  367. for (j = 0; j < FRS_collectpakg->numofinst; j++) {
  368. FRS_collectpakg->indices->index[j]= FRS_datapackage->indices->index[j];
  369. }
  370. //
  371. // Set the memory blob used to (mem)copy the counter dats from the server
  372. //
  373. FRS_collectpakg->databuff = (DataBuffer *) FRSPerfAlloc (sizeof(DataBuffer));
  374. NTFRS_MALLOC_TEST(FRS_collectpakg->databuff, FreeReplicaSetData(), TRUE);
  375. FRS_collectpakg->databuff->size = FRS_collectpakg->numofinst *
  376. SIZEOF_REPSET_COUNTER_DATA;
  377. //
  378. // Allocate memory for the buffer in which the data gets copied.
  379. //
  380. FRS_collectpakg->databuff->data = (PBYTE) FRSPerfAlloc (FRS_collectpakg->databuff->size * sizeof(BYTE));
  381. NTFRS_MALLOC_TEST(FRS_collectpakg->databuff->data, FreeReplicaSetData(), TRUE);
  382. RpcBindingFree(&Handle);
  383. } else {
  384. //
  385. // There are no instances at this time, so set the PERF_OBJECT_TYPE structure fields accordingly
  386. //
  387. ReplicaSetDataDefinition.ReplicaSetObjectType.TotalByteLength +=
  388. SizeOfReplicaSetPerformanceData + SSIZEOFDWORD;
  389. ReplicaSetDataDefinition.ReplicaSetObjectType.NumInstances =
  390. PERF_NO_INSTANCES;
  391. }
  392. EnterCriticalSection(&FRS_ThrdCounter);
  393. FRS_dwOpenCount++; // increment the open counter
  394. LeaveCriticalSection(&FRS_ThrdCounter);
  395. FRS_Op = TRUE;
  396. return ERROR_SUCCESS;
  397. }
  398. DWORD APIENTRY
  399. CollectReplicaSetPerformanceData (
  400. IN LPWSTR lpValueName,
  401. IN OUT LPVOID *lppData,
  402. IN OUT LPDWORD lpcbTotalBytes,
  403. IN OUT LPDWORD lpNumObjectTypes
  404. )
  405. /*++
  406. Routine Description:
  407. This routine collects the counter data from the server and copies it into
  408. the callers buffer.
  409. Arguments:
  410. lpValueName - Wide character string passed by the registry.
  411. lppData - IN: pointer to the address of the buffer to receive the
  412. completed PerfDataBlock and the subordinate structures.
  413. This routine will append its data to the buffer starting
  414. at the point referenced by *lppData.
  415. OUT: Points to the first byte after the data structure added
  416. by this routine.
  417. lpcbTotalBytes - IN: The address of the DWORD that tells the size in bytes
  418. of the buffer referenced by the lppData argument
  419. OUT: The number of bytes added by this routine is written
  420. to the DWORD pointed to by this argument.
  421. lpNumObjectTypes - IN: The address of the DWORD to receive the number of
  422. Objects added by this routine .
  423. OUT: The number of Objects added by this routine is written
  424. to the buffer pointed by this argument.
  425. Return Value:
  426. ERROR_MORE_DATA - The buffer passed was too small.
  427. ERROR_SUCCESS - Success or any other error
  428. --*/
  429. {
  430. //
  431. // Variables for reformatting data to be sent to perfmon
  432. //
  433. ULONG SpaceNeeded;
  434. PBYTE bte, vd;
  435. PDWORD pdwCounter;
  436. PERF_COUNTER_BLOCK *pPerfCounterBlock;
  437. REPLICASET_DATA_DEFINITION *pReplicaSetDataDefinition;
  438. DWORD dwQueryType;
  439. LONG j, k;
  440. PERF_INSTANCE_DEFINITION *p1;
  441. PWCHAR name;
  442. //
  443. // RPC Additions
  444. //
  445. handle_t Handle;
  446. //
  447. // Check to see that all the pointers that are passed in are fine
  448. //
  449. if (lppData == NULL || *lppData == NULL || lpcbTotalBytes == NULL ||
  450. lpValueName == NULL || lpNumObjectTypes == NULL) {
  451. //
  452. // Fatal error. No point in continuing. Clean up and exit.
  453. //
  454. return ERROR_SUCCESS;
  455. }
  456. //
  457. // Check to see if Open went OK
  458. //
  459. EnterCriticalSection(&FRS_ThrdCounter);
  460. if (FRS_dwOpenCount == 0) {
  461. *lpcbTotalBytes = (DWORD)0;
  462. *lpNumObjectTypes = (DWORD)0;
  463. LeaveCriticalSection(&FRS_ThrdCounter);
  464. //
  465. // Fatal error. No point in continuing.
  466. //
  467. return ERROR_SUCCESS;
  468. }
  469. LeaveCriticalSection(&FRS_ThrdCounter);
  470. //
  471. // Check the query type
  472. //
  473. dwQueryType = GetQueryType (lpValueName);
  474. if (dwQueryType == QUERY_FOREIGN) {
  475. *lpcbTotalBytes = (DWORD)0;
  476. *lpNumObjectTypes = (DWORD)0;
  477. //
  478. // Fatal error. No point in continuing. Clean up and exit.
  479. //
  480. return ERROR_SUCCESS;
  481. }
  482. if (dwQueryType == QUERY_ITEMS) {
  483. if ( !(IsNumberInUnicodeList(ReplicaSetDataDefinition.ReplicaSetObjectType
  484. .ObjectNameTitleIndex, lpValueName)) ) {
  485. *lpcbTotalBytes = (DWORD)0;
  486. *lpNumObjectTypes = (DWORD)0;
  487. //
  488. // Fatal error. No point in continuing. Clean up and exit.
  489. //
  490. return ERROR_SUCCESS;
  491. }
  492. }
  493. //
  494. // The assumption here is that *lppData is aligned on a 8 byte boundary.
  495. // If its not, then some object in front of us messed up.
  496. //
  497. pReplicaSetDataDefinition = (REPLICASET_DATA_DEFINITION *) *lppData;
  498. //
  499. // Check if the buffer space is sufficient
  500. //
  501. SpaceNeeded = (ULONG) ReplicaSetDataDefinition.ReplicaSetObjectType.TotalByteLength;
  502. //
  503. // Check if the buffer space is sufficient
  504. //
  505. if ( *lpcbTotalBytes < SpaceNeeded ) {
  506. //
  507. // Buffer space is insufficient
  508. //
  509. *lpcbTotalBytes = (DWORD)0;
  510. *lpNumObjectTypes = (DWORD)0;
  511. return ERROR_MORE_DATA;
  512. }
  513. //
  514. // Copy the Object Type and counter definitions to the callers buffer
  515. //
  516. memmove (pReplicaSetDataDefinition, &ReplicaSetDataDefinition, sizeof(REPLICASET_DATA_DEFINITION));
  517. //
  518. // Check if the Object has any instances
  519. //
  520. if (FRS_datapackage != NULL) {
  521. //
  522. // Bind the RPC handle
  523. //
  524. if (FRC_BindTheRpcHandle(&Handle) != ERROR_SUCCESS) {
  525. //
  526. // Fatal error. No point in continuing. Clean up and exit.
  527. //
  528. *lpcbTotalBytes = (DWORD)0;
  529. *lpNumObjectTypes = (DWORD)0;
  530. FilterAndPrintToEventLog(FRS_Cl,
  531. NTFRSPRF_COLLECT_RPC_BINDING_ERROR_SET);
  532. return ERROR_SUCCESS;
  533. }
  534. //
  535. // Zero the contents of the data buffer.
  536. //
  537. ZeroMemory(FRS_collectpakg->databuff->data, FRS_collectpakg->databuff->size);
  538. //
  539. // (RP) Call to get the counter data from the server
  540. //
  541. if (GetCounterDataOfInstancesFromServer(Handle, FRS_collectpakg) != ERROR_SUCCESS) {
  542. //
  543. // Fatal error. No point in continuing. Clean up and exit.
  544. //
  545. *lpcbTotalBytes = (DWORD)0;
  546. *lpNumObjectTypes = (DWORD)0;
  547. RpcBindingFree(&Handle);
  548. FilterAndPrintToEventLog(FRS_Cl,
  549. NTFRSPRF_COLLECT_RPC_CALL_ERROR_SET);
  550. return ERROR_SUCCESS;
  551. }
  552. vd = FRS_collectpakg->databuff->data;
  553. p1 = (PERF_INSTANCE_DEFINITION *)&pReplicaSetDataDefinition[1];
  554. //
  555. // Format the data and copy it into the callers buffer
  556. //
  557. for (j = 0; j < FRS_collectpakg->numofinst; j++) {
  558. DWORD RoundedLen;
  559. //
  560. // Name length rounded to the next 8 byte boundary.
  561. //
  562. RoundedLen = (((((1 +
  563. wcslen(FRS_datapackage->instnames->InstanceNames[j].name))
  564. * sizeof(WCHAR)) + 7) >> 3) << 3) + SSIZEOFDWORD;
  565. //
  566. // Set the Instance definition structure
  567. //
  568. p1->ByteLength = sizeof (PERF_INSTANCE_DEFINITION) + RoundedLen;
  569. p1->ParentObjectTitleIndex = 0;
  570. p1->ParentObjectInstance = 0;
  571. p1->UniqueID = PERF_NO_UNIQUE_ID;
  572. p1->NameOffset = sizeof (PERF_INSTANCE_DEFINITION);
  573. p1->NameLength = (1 +
  574. wcslen(FRS_datapackage->instnames->InstanceNames[j].name))
  575. * sizeof(WCHAR);
  576. //
  577. // Set the instance name
  578. //
  579. name = (PWCHAR) (&p1[1]);
  580. wcscpy(name, FRS_datapackage->instnames->InstanceNames[j].name);
  581. //
  582. // Set the PERF_COUNTER_BLOCK structure
  583. //
  584. pPerfCounterBlock = (PERF_COUNTER_BLOCK *)
  585. (name + (RoundedLen/sizeof(WCHAR)));
  586. pPerfCounterBlock->ByteLength = SizeOfReplicaSetPerformanceData;
  587. //
  588. // Finally set the counter data
  589. //
  590. bte = ((PBYTE) (&pPerfCounterBlock[1]));
  591. CopyMemory (bte, vd, SIZEOF_REPSET_COUNTER_DATA);
  592. vd += SIZEOF_REPSET_COUNTER_DATA;
  593. bte += SIZEOF_REPSET_COUNTER_DATA;
  594. p1 = (PERF_INSTANCE_DEFINITION *) bte;
  595. }
  596. //
  597. // Update the arguments for return
  598. //
  599. *lpNumObjectTypes = REPLICASET_NUM_PERF_OBJECT_TYPES;
  600. *lppData = (PVOID) p1;
  601. //
  602. // Set the totalbytes being returned.
  603. //
  604. *lpcbTotalBytes = (DWORD)((PBYTE) p1 - (PBYTE) pReplicaSetDataDefinition);
  605. RpcBindingFree(&Handle);
  606. FRS_Cl = TRUE;
  607. return ERROR_SUCCESS;
  608. }
  609. else {
  610. //
  611. // No instances as of now, so fill zeros for the counter data
  612. //
  613. pPerfCounterBlock = (PERF_COUNTER_BLOCK *)
  614. (((PBYTE)&pReplicaSetDataDefinition[1]) +
  615. SSIZEOFDWORD);
  616. pPerfCounterBlock->ByteLength = SizeOfReplicaSetPerformanceData;
  617. bte = ((PBYTE) (&pPerfCounterBlock[1]));
  618. ZeroMemory (bte, SIZEOF_REPSET_COUNTER_DATA);
  619. bte += SIZEOF_REPSET_COUNTER_DATA;
  620. *lppData = (PVOID) bte;
  621. *lpNumObjectTypes = REPLICASET_NUM_PERF_OBJECT_TYPES;
  622. *lpcbTotalBytes =
  623. (DWORD)((PBYTE) bte - (PBYTE) pReplicaSetDataDefinition);
  624. FRS_Cl = TRUE;
  625. return ERROR_SUCCESS;
  626. }
  627. }
  628. DWORD APIENTRY
  629. CloseReplicaSetPerformanceData (
  630. VOID
  631. )
  632. /*++
  633. Routine Description:
  634. This routine decrements the open count and frees up the memory allocated by
  635. the Open and Collect routines if needed.
  636. Arguments:
  637. none.
  638. Return Value:
  639. ERROR_SUCCESS - Success
  640. --*/
  641. {
  642. EnterCriticalSection(&FRS_ThrdCounter);
  643. //
  644. // Check to see if the open count is zero. This should never happen but
  645. // just in case.
  646. //
  647. if (FRS_dwOpenCount == 0) {
  648. LeaveCriticalSection(&FRS_ThrdCounter);
  649. return ERROR_SUCCESS;
  650. }
  651. //
  652. // Decrement the Open count.
  653. //
  654. FRS_dwOpenCount--;
  655. //
  656. // If the open count becomes zero, free up the memory since no more threads
  657. // are going to collect data.
  658. //
  659. if (FRS_dwOpenCount == 0) {
  660. //
  661. // Call the routine that frees up the memory.
  662. //
  663. FreeReplicaSetData();
  664. LeaveCriticalSection(&FRS_ThrdCounter);
  665. } else {
  666. LeaveCriticalSection(&FRS_ThrdCounter);
  667. }
  668. return ERROR_SUCCESS;
  669. }
  670. VOID
  671. FreeReplicaSetData(
  672. VOID
  673. )
  674. /*++
  675. Routine Description:
  676. This routine frees up the memory allocated by the Open and Collect routines.
  677. Arguments:
  678. None.
  679. Return Value:
  680. ERROR_SUCCESS - Success
  681. --*/
  682. {
  683. LONG j;
  684. //
  685. // Free up the Datapackage strucutre.
  686. //
  687. if (FRS_datapackage != NULL) {
  688. if (FRS_datapackage->ver != NULL) {
  689. free(FRS_datapackage->ver);
  690. }
  691. if (FRS_datapackage->indices != NULL) {
  692. if (FRS_datapackage->indices->index != NULL) {
  693. free(FRS_datapackage->indices->index);
  694. }
  695. free(FRS_datapackage->indices);
  696. }
  697. if (FRS_datapackage->instnames != NULL) {
  698. if (FRS_datapackage->instnames->InstanceNames != NULL) {
  699. for (j = 0; j < FRS_datapackage->numofinst; j++) {
  700. if (FRS_datapackage->instnames->InstanceNames[j].name != NULL) {
  701. free(FRS_datapackage->instnames->InstanceNames[j].name);
  702. }
  703. }
  704. free(FRS_datapackage->instnames->InstanceNames);
  705. }
  706. free(FRS_datapackage->instnames);
  707. }
  708. free(FRS_datapackage);
  709. FRS_datapackage = NULL;
  710. }
  711. //
  712. // Free up the collect package structure.
  713. //
  714. if (FRS_collectpakg != NULL) {
  715. if (FRS_collectpakg->indices != NULL) {
  716. if (FRS_collectpakg->indices->index != NULL) {
  717. free(FRS_collectpakg->indices->index);
  718. }
  719. free(FRS_collectpakg->indices);
  720. }
  721. if (FRS_collectpakg->databuff != NULL) {
  722. if (FRS_collectpakg->databuff->data != NULL) {
  723. free(FRS_collectpakg->databuff->data);
  724. }
  725. free(FRS_collectpakg->databuff);
  726. }
  727. free(FRS_collectpakg);
  728. FRS_collectpakg = NULL;
  729. }
  730. }
  731. PVOID
  732. FRSPerfAlloc(
  733. IN DWORD Size
  734. )
  735. /*++
  736. Routine Description:
  737. Allocate memory and fill it with zeros before returning the pointer.
  738. Arguments:
  739. Size - Size of the memory request in bytes.
  740. Return Value:
  741. Pointer to the allocated memory or NULL if memory wasn't available.
  742. --*/
  743. {
  744. PVOID Node;
  745. if (Size == 0) {
  746. return NULL;
  747. }
  748. Node = (PVOID) malloc (Size);
  749. if (Node == NULL) {
  750. return NULL;
  751. }
  752. ZeroMemory(Node, Size);
  753. return Node;
  754. }
  755. //
  756. // Functions (for memory handling) used by the client stub
  757. //
  758. void *
  759. midl_user_allocate
  760. (
  761. size
  762. )
  763. size_t size;
  764. {
  765. unsigned char *ptr;
  766. ptr = malloc (size);
  767. return ( (void *)ptr );
  768. }
  769. void
  770. midl_user_free
  771. (
  772. object
  773. )
  774. void * object;
  775. {
  776. free (object);
  777. }