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.

961 lines
29 KiB

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