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.

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