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.

549 lines
14 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1993 **/
  4. /**********************************************************************/
  5. /*
  6. perfwins.c
  7. This file implements the Extensible Performance Objects for
  8. the FTP Server service.
  9. FILE HISTORY:
  10. KeithMo 07-Jun-1993 Created, based on RussBl's sample code.
  11. */
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <winperf.h>
  17. #include <lm.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include "winsctrs.h"
  21. #include "perfmsg.h"
  22. #include "perfutil.h"
  23. #include "winsintf.h"
  24. #include "winsdata.h"
  25. #include "debug.h"
  26. #include "winsevnt.h"
  27. //
  28. // Private globals.
  29. //
  30. DWORD cOpens = 0; // Active "opens" reference count.
  31. BOOL fInitOK = FALSE; // TRUE if DLL initialized OK.
  32. BOOL sfLogOpen; //indicates whether the log is
  33. //open or closed
  34. BOOL sfErrReported; //to prevent the same error from being
  35. //logged continuously
  36. #if DBG
  37. DWORD WinsdDebug = 0; // Debug behaviour flags.
  38. #endif // DBG
  39. //
  40. // Public prototypes.
  41. //
  42. PM_OPEN_PROC OpenWinsPerformanceData;
  43. PM_COLLECT_PROC CollectWinsPerformanceData;
  44. PM_CLOSE_PROC CloseWinsPerformanceData;
  45. //
  46. // Public functions.
  47. //
  48. /*******************************************************************
  49. NAME: OpenWinsPerformanceData
  50. SYNOPSIS: Initializes the data structures used to communicate
  51. performance counters with the registry.
  52. ENTRY: lpDeviceNames - Poitner to object ID of each device
  53. to be opened.
  54. RETURNS: DWORD - Win32 status code.
  55. HISTORY:
  56. Pradeepb 20-July-1993 Created.
  57. ********************************************************************/
  58. DWORD OpenWinsPerformanceData( LPWSTR lpDeviceNames )
  59. {
  60. DWORD err = NO_ERROR;
  61. HKEY hkey = NULL;
  62. // DWORD size;
  63. // DWORD type;
  64. DWORD dwFirstCounter;
  65. DWORD dwFirstHelp;
  66. IF_DEBUG( ENTRYPOINTS )
  67. {
  68. WINSD_PRINT(( "in OpenWinsPerformanceData\n" ));
  69. }
  70. //
  71. // Since SCREG is multi-threaded and will call this routine in
  72. // order to service remote performance queries, this library
  73. // must keep track of how many times it has been opened (i.e.
  74. // how many threads have accessed it). The registry routines will
  75. // limit access to the initialization routine to only one thread
  76. // at a time so synchronization (i.e. reentrancy) should not be
  77. // a problem.
  78. //
  79. if( !fInitOK )
  80. {
  81. PERF_COUNTER_DEFINITION * pctr;
  82. DWORD i;
  83. if(AddSrcToReg() == ERROR_SUCCESS)
  84. {
  85. if (!MonOpenEventLog())
  86. {
  87. sfLogOpen = TRUE;
  88. }
  89. }
  90. //
  91. // This is the *first* open.
  92. //
  93. dwFirstCounter = WINSCTRS_FIRST_COUNTER;
  94. dwFirstHelp = WINSCTRS_FIRST_HELP;
  95. //
  96. // Update the object & counter name & help indicies.
  97. //
  98. WinsDataDataDefinition.ObjectType.ObjectNameTitleIndex
  99. += dwFirstCounter;
  100. WinsDataDataDefinition.ObjectType.ObjectHelpTitleIndex
  101. += dwFirstHelp;
  102. pctr = &WinsDataDataDefinition.UniqueReg;
  103. for( i = 0 ; i < NUMBER_OF_WINSDATA_COUNTERS ; i++ )
  104. {
  105. pctr->CounterNameTitleIndex += dwFirstCounter;
  106. pctr->CounterHelpTitleIndex += dwFirstHelp;
  107. pctr++;
  108. }
  109. //
  110. // Remember that we initialized OK.
  111. //
  112. fInitOK = TRUE;
  113. //
  114. // Close the registry if we managed to actually open it.
  115. //
  116. if( hkey != NULL )
  117. {
  118. RegCloseKey( hkey );
  119. hkey = NULL;
  120. }
  121. IF_DEBUG( OPEN )
  122. {
  123. if( err != NO_ERROR )
  124. {
  125. WINSD_PRINT(( "Cannot read registry data, error %lu\n", err ));
  126. }
  127. }
  128. }
  129. //
  130. // Bump open counter.
  131. //
  132. if( err == NO_ERROR )
  133. {
  134. cOpens++;
  135. }
  136. //
  137. // if sfLogOpen is FALSE, it means that all threads we closed the
  138. // event log in CloseWinsPerformanceData
  139. //
  140. if (!sfLogOpen)
  141. {
  142. MonOpenEventLog();
  143. }
  144. return err;
  145. } // OpenWinsPerformanceData
  146. /*******************************************************************
  147. NAME: CollectWinsPerformanceData
  148. SYNOPSIS: Initializes the data structures used to communicate
  149. ENTRY: lpValueName - The name of the value to retrieve.
  150. lppData - On entry contains a pointer to the buffer to
  151. receive the completed PerfDataBlock & subordinate
  152. structures. On exit, points to the first bytes
  153. *after* the data structures added by this routine.
  154. lpcbTotalBytes - On entry contains a pointer to the
  155. size (in BYTEs) of the buffer referenced by lppData.
  156. On exit, contains the number of BYTEs added by this
  157. routine.
  158. lpNumObjectTypes - Receives the number of objects added
  159. by this routine.
  160. RETURNS: DWORD - Win32 status code. MUST be either NO_ERROR
  161. or ERROR_MORE_DATA.
  162. HISTORY:
  163. KeithMo 07-Jun-1993 Created.
  164. ********************************************************************/
  165. DWORD CollectWinsPerformanceData( LPWSTR lpValueName,
  166. LPVOID * lppData,
  167. LPDWORD lpcbTotalBytes,
  168. LPDWORD lpNumObjectTypes )
  169. {
  170. DWORD dwQueryType;
  171. ULONG cbRequired;
  172. DWORD *pdwCounter;
  173. WINSDATA_COUNTER_BLOCK *pCounterBlock;
  174. WINSDATA_DATA_DEFINITION *pWinsDataDataDefinition;
  175. WINSINTF_RESULTS_NEW_T Results;
  176. #if 0
  177. WINSINTF_RESULTS_T Results;
  178. #endif
  179. WINSINTF_STAT_T *pWinsStats = &Results.WinsStat;
  180. DWORD Status;
  181. IF_DEBUG( ENTRYPOINTS )
  182. {
  183. WINSD_PRINT(( "in CollectWinsPerformanceData\n" ));
  184. WINSD_PRINT(( " lpValueName = %08lX (%ls)\n",
  185. lpValueName,
  186. lpValueName ));
  187. WINSD_PRINT(( " lppData = %08lX (%08lX)\n",
  188. lppData,
  189. *lppData ));
  190. WINSD_PRINT(( " lpcbTotalBytes = %08lX (%08lX)\n",
  191. lpcbTotalBytes,
  192. *lpcbTotalBytes ));
  193. WINSD_PRINT(( " lpNumObjectTypes = %08lX (%08lX)\n",
  194. lpNumObjectTypes,
  195. *lpNumObjectTypes ));
  196. }
  197. //
  198. // No need to even try if we failed to open...
  199. //
  200. if( !fInitOK )
  201. {
  202. IF_DEBUG( COLLECT )
  203. {
  204. WINSD_PRINT(( "Initialization failed, CollectWinsPerformanceData aborting\n" ));
  205. }
  206. *lpcbTotalBytes = 0;
  207. *lpNumObjectTypes = 0;
  208. //
  209. // According to the Performance Counter design, this
  210. // is a successful exit. Go figure.
  211. //
  212. return NO_ERROR;
  213. }
  214. //
  215. // Determine the query type.
  216. //
  217. dwQueryType = GetQueryType( lpValueName );
  218. if( dwQueryType == QUERY_FOREIGN )
  219. {
  220. IF_DEBUG( COLLECT )
  221. {
  222. WINSD_PRINT(( "foreign queries not supported\n" ));
  223. }
  224. //
  225. // We don't do foreign queries.
  226. //
  227. *lpcbTotalBytes = 0;
  228. *lpNumObjectTypes = 0;
  229. return NO_ERROR;
  230. }
  231. if( dwQueryType == QUERY_ITEMS )
  232. {
  233. //
  234. // The registry is asking for a specific object. Let's
  235. // see if we're one of the chosen.
  236. //
  237. if( !IsNumberInUnicodeList(
  238. WinsDataDataDefinition.ObjectType.ObjectNameTitleIndex,
  239. lpValueName ) )
  240. {
  241. IF_DEBUG( COLLECT )
  242. {
  243. WINSD_PRINT(( "%ls not a supported object type\n", lpValueName ));
  244. }
  245. *lpcbTotalBytes = 0;
  246. *lpNumObjectTypes = 0;
  247. return NO_ERROR;
  248. }
  249. }
  250. //
  251. // See if there's enough space.
  252. //
  253. pWinsDataDataDefinition = (WINSDATA_DATA_DEFINITION *)*lppData;
  254. cbRequired = sizeof(WINSDATA_DATA_DEFINITION) +
  255. WINSDATA_SIZE_OF_PERFORMANCE_DATA;
  256. if( *lpcbTotalBytes < cbRequired )
  257. {
  258. IF_DEBUG( COLLECT )
  259. {
  260. WINSD_PRINT(( "%lu bytes of buffer insufficient, %lu needed\n",
  261. *lpcbTotalBytes,
  262. cbRequired ));
  263. }
  264. //
  265. // Nope.
  266. //
  267. *lpcbTotalBytes = 0;
  268. *lpNumObjectTypes = 0;
  269. return ERROR_MORE_DATA;
  270. }
  271. //
  272. // Copy the (constant, initialized) Object Type and counter definitions
  273. // to the caller's data buffer
  274. //
  275. memmove( pWinsDataDataDefinition,
  276. &WinsDataDataDefinition,
  277. sizeof(WINSDATA_DATA_DEFINITION) );
  278. //
  279. // Try to retrieve the data.
  280. //
  281. Results.WinsStat.NoOfPnrs = 0;
  282. Results.WinsStat.pRplPnrs = NULL;
  283. Results.pAddVersMaps = NULL;
  284. {
  285. WINSINTF_BIND_DATA_T BindData;
  286. handle_t BindHdl;
  287. BindData.fTcpIp = FALSE;
  288. BindData.pPipeName = (LPBYTE)TEXT("\\pipe\\WinsPipe");
  289. BindData.pServerAdd = (LPBYTE)TEXT("");
  290. BindHdl = WinsBind(&BindData);
  291. Status = WinsStatusNew(BindHdl, WINSINTF_E_STAT, &Results);
  292. WinsUnbind(&BindData, BindHdl);
  293. }
  294. if( Status != WINSINTF_SUCCESS )
  295. {
  296. IF_DEBUG( COLLECT )
  297. {
  298. WINSD_PRINT(( "cannot retrieve statistics, error %lu\n",
  299. Status ));
  300. }
  301. //
  302. // if we haven't logged the error yet, log it
  303. //
  304. if (!sfErrReported)
  305. {
  306. REPORT_ERROR(WINS_EVT_WINS_STATUS_ERR, LOG_USER);
  307. sfErrReported = TRUE;
  308. }
  309. //
  310. // Error retrieving statistics.
  311. //
  312. *lpcbTotalBytes = 0;
  313. *lpNumObjectTypes = 0;
  314. return NO_ERROR;
  315. }
  316. //
  317. // Ahaa, we got the statistics, reset flag if set
  318. //
  319. if (sfErrReported)
  320. {
  321. sfErrReported = FALSE;
  322. }
  323. //
  324. // Format the WINS Server data.
  325. //
  326. pCounterBlock = (WINSDATA_COUNTER_BLOCK *)( pWinsDataDataDefinition + 1 );
  327. pCounterBlock->PerfCounterBlock.ByteLength =
  328. WINSDATA_SIZE_OF_PERFORMANCE_DATA;
  329. //
  330. // Get the pointer to the first (DWORD) counter. This
  331. // pointer *must* be quadword aligned.
  332. //
  333. pdwCounter = (DWORD *)( pCounterBlock + 1 );
  334. WINSD_ASSERT( ( (DWORD_PTR)pdwCounter & 3 ) == 0 );
  335. IF_DEBUG( COLLECT )
  336. {
  337. WINSD_PRINT(( "pWinsDataDataDefinition = %08lX\n", pWinsDataDataDefinition ));
  338. WINSD_PRINT(( "pCounterBlock = %08lX\n", pCounterBlock ));
  339. WINSD_PRINT(( "ByteLength = %08lX\n", pCounterBlock->PerfCounterBlock.ByteLength ));
  340. WINSD_PRINT(( "pliCounter = %08lX\n", pdwCounter ));
  341. }
  342. //
  343. // Move the DWORDs into the buffer.
  344. //
  345. IF_DEBUG( COLLECT )
  346. {
  347. WINSD_PRINT(( "pdwCounter = %08lX\n", pdwCounter ));
  348. }
  349. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfUniqueReg;
  350. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfGroupReg;
  351. *pdwCounter++ = (DWORD)(pWinsStats->Counters.NoOfUniqueReg +
  352. pWinsStats->Counters.NoOfGroupReg);
  353. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfUniqueRef;
  354. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfGroupRef;
  355. *pdwCounter++ = (DWORD)(pWinsStats->Counters.NoOfUniqueRef +
  356. pWinsStats->Counters.NoOfGroupRef);
  357. *pdwCounter++ = (DWORD)(pWinsStats->Counters.NoOfSuccRel +
  358. pWinsStats->Counters.NoOfFailRel);
  359. *pdwCounter++ = (DWORD)(pWinsStats->Counters.NoOfSuccQueries +
  360. pWinsStats->Counters.NoOfFailQueries);
  361. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfUniqueCnf;
  362. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfGroupCnf;
  363. *pdwCounter++ = (DWORD)(pWinsStats->Counters.NoOfUniqueCnf +
  364. pWinsStats->Counters.NoOfGroupCnf);
  365. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfSuccRel;
  366. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfFailRel;
  367. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfSuccQueries;
  368. *pdwCounter++ = (DWORD)pWinsStats->Counters.NoOfFailQueries;
  369. //
  370. // Update arguments for return.
  371. //
  372. *lppData = (PVOID)pdwCounter;
  373. *lpNumObjectTypes = 1;
  374. *lpcbTotalBytes = (DWORD)((BYTE *)pdwCounter - (BYTE *)pWinsDataDataDefinition);
  375. IF_DEBUG( COLLECT )
  376. {
  377. WINSD_PRINT(( "pData = %08lX\n", *lppData ));
  378. WINSD_PRINT(( "NumObjectTypes = %08lX\n", *lpNumObjectTypes ));
  379. WINSD_PRINT(( "cbTotalBytes = %08lX\n", *lpcbTotalBytes ));
  380. }
  381. //
  382. // Free the API buffer.
  383. //
  384. #if 0
  385. NetApiBufferFree( (LPBYTE)pWinsStats );
  386. #endif
  387. //
  388. // Free the buffers RPC allocates.
  389. //
  390. WinsFreeMem( Results.pAddVersMaps );
  391. WinsFreeMem( Results.WinsStat.pRplPnrs );
  392. //
  393. // Success! Honest!!
  394. //
  395. return NO_ERROR;
  396. } // CollectWinsPerformanceData
  397. /*******************************************************************
  398. NAME: CloseWinsPerformanceData
  399. SYNOPSIS: Terminates the performance counters.
  400. RETURNS: DWORD - Win32 status code.
  401. HISTORY:
  402. KeithMo 07-Jun-1993 Created.
  403. ********************************************************************/
  404. DWORD CloseWinsPerformanceData( VOID )
  405. {
  406. IF_DEBUG( ENTRYPOINTS )
  407. {
  408. WINSD_PRINT(( "in CloseWinsPerformanceData\n" ));
  409. }
  410. //
  411. // No real cleanup to do here.
  412. //
  413. cOpens--;
  414. if (!cOpens)
  415. {
  416. //
  417. // unbind from the nameserver. There could be synch. problems since
  418. // sfLogOpen is changed in both Open and Close functions. This at the
  419. // max. will affect logging. It being unclear at this point whether or
  420. // not Open gets called multiple times (from all looks of it, it is only
  421. // called once), this flag may even not be necessary.
  422. //
  423. MonCloseEventLog();
  424. sfLogOpen = FALSE;
  425. }
  426. return NO_ERROR;
  427. } // CloseWinsPerformanceData