Leaked source code of windows server 2003
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.

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