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.

873 lines
29 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1993 **/
  4. /**********************************************************************/
  5. /*
  6. perfftp.cxx
  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. MuraliK 16-Nov-1995 Modified dependencies and removed NetApi
  12. SophiaC 06-Nov-1996 Supported mutlitiple instances
  13. */
  14. #define INITGUID
  15. #include <windows.h>
  16. #include <winperf.h>
  17. #include <lm.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <ole2.h>
  21. #include "iis64.h"
  22. #include "dbgutil.h"
  23. #include "iisinfo.h"
  24. #include "ftpd.h"
  25. #include "ftpctrs.h"
  26. #include "ftpmsg.h"
  27. #include "iadm.h"
  28. extern "C" {
  29. #include "perfutil.h"
  30. #include "apiutil.h"
  31. #include "ftpdata.h"
  32. } // extern "C"
  33. #define APP_NAME (TEXT("FTPCtrs"))
  34. #define MAX_SIZEOF_INSTANCE_NAME METADATA_MAX_NAME_LEN
  35. #define TOTAL_INSTANCE_NAME L"_Total"
  36. //
  37. // Private globals.
  38. //
  39. DWORD cOpens = 0; // Active "opens" reference count.
  40. BOOL fInitOK = FALSE; // TRUE if DLL initialized OK.
  41. HANDLE hEventLog = NULL; // event log handle
  42. //
  43. // Public prototypes.
  44. //
  45. PM_OPEN_PROC OpenFtpPerformanceData;
  46. PM_COLLECT_PROC CollectFtpPerformanceData;
  47. PM_CLOSE_PROC CloseFtpPerformanceData;
  48. //
  49. // Private prototypes.
  50. //
  51. VOID
  52. CopyStatisticsData(
  53. IN FTP_STATISTICS_0 * pFTPStats,
  54. OUT FTPD_COUNTER_BLOCK * pCounterBlock
  55. );
  56. VOID
  57. Update_TotalStatisticsData(
  58. IN FTPD_COUNTER_BLOCK * pCounterBlock,
  59. OUT FTPD_COUNTER_BLOCK * pTotal
  60. );
  61. //
  62. // Public functions.
  63. //
  64. /*******************************************************************
  65. NAME: OpenFtpPerformanceData
  66. SYNOPSIS: Initializes the data structures used to communicate
  67. performance counters with the registry.
  68. ENTRY: lpDeviceNames - Poitner to object ID of each device
  69. to be opened.
  70. RETURNS: DWORD - Win32 status code.
  71. HISTORY:
  72. KeithMo 07-Jun-1993 Created.
  73. ********************************************************************/
  74. DWORD OpenFtpPerformanceData( LPWSTR lpDeviceNames )
  75. {
  76. DWORD err = NO_ERROR;
  77. HKEY hkey = NULL;
  78. DWORD size;
  79. DWORD type;
  80. DWORD dwFirstCounter;
  81. DWORD dwFirstHelp;
  82. PERF_COUNTER_DEFINITION * pctr;
  83. FTPD_COUNTER_BLOCK ftpc;
  84. DWORD i;
  85. //
  86. // Since WINLOGON is multi-threaded and will call this routine in
  87. // order to service remote performance queries, this library
  88. // must keep track of how many times it has been opened (i.e.
  89. // how many threads have accessed it). The registry routines will
  90. // limit access to the initialization routine to only one thread
  91. // at a time so synchronization (i.e. reentrancy) should not be
  92. // a problem.
  93. //
  94. if( !fInitOK )
  95. {
  96. //
  97. // This is the *first* open.
  98. //
  99. // open event log interface
  100. if (hEventLog == NULL){
  101. hEventLog = RegisterEventSource ((LPTSTR)NULL, // Use Local Machine
  102. APP_NAME); // event log app name to find in registry
  103. if (hEventLog == NULL)
  104. {
  105. return GetLastError();
  106. }
  107. }
  108. //
  109. // Open the FTP Server service's Performance key.
  110. //
  111. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  112. FTPD_PERFORMANCE_KEY,
  113. 0,
  114. KEY_READ,
  115. &hkey );
  116. if( err == NO_ERROR )
  117. {
  118. //
  119. // Read the first counter DWORD.
  120. //
  121. size = sizeof(DWORD);
  122. err = RegQueryValueEx( hkey,
  123. "First Counter",
  124. NULL,
  125. &type,
  126. (LPBYTE)&dwFirstCounter,
  127. &size );
  128. if( err == NO_ERROR )
  129. {
  130. //
  131. // Read the first help DWORD.
  132. //
  133. size = sizeof(DWORD);
  134. err = RegQueryValueEx( hkey,
  135. "First Help",
  136. NULL,
  137. &type,
  138. (LPBYTE)&dwFirstHelp,
  139. &size );
  140. if ( err == NO_ERROR )
  141. {
  142. //
  143. // Update the object & counter name & help indicies.
  144. //
  145. FtpdDataDefinition.FtpdObjectType.ObjectNameTitleIndex
  146. += dwFirstCounter;
  147. FtpdDataDefinition.FtpdObjectType.ObjectHelpTitleIndex
  148. += dwFirstHelp;
  149. FtpdDataDefinition.FtpdBytesSent.CounterNameTitleIndex
  150. += dwFirstCounter;
  151. FtpdDataDefinition.FtpdBytesSent.CounterHelpTitleIndex
  152. += dwFirstHelp;
  153. FtpdDataDefinition.FtpdBytesSent.CounterOffset =
  154. (DWORD)((LPBYTE)&ftpc.BytesSent - (LPBYTE)&ftpc);
  155. FtpdDataDefinition.FtpdBytesReceived.CounterNameTitleIndex
  156. += dwFirstCounter;
  157. FtpdDataDefinition.FtpdBytesReceived.CounterHelpTitleIndex
  158. += dwFirstHelp;
  159. FtpdDataDefinition.FtpdBytesReceived.CounterOffset =
  160. (DWORD)((LPBYTE)&ftpc.BytesReceived - (LPBYTE)&ftpc);
  161. FtpdDataDefinition.FtpdBytesTotal.CounterNameTitleIndex
  162. += dwFirstCounter;
  163. FtpdDataDefinition.FtpdBytesTotal.CounterHelpTitleIndex
  164. += dwFirstHelp;
  165. FtpdDataDefinition.FtpdBytesTotal.CounterOffset =
  166. (DWORD)((LPBYTE)&ftpc.BytesTotal - (LPBYTE)&ftpc);
  167. FtpdDataDefinition.FtpdFilesSent.CounterNameTitleIndex
  168. += dwFirstCounter;
  169. FtpdDataDefinition.FtpdFilesSent.CounterHelpTitleIndex
  170. += dwFirstHelp;
  171. FtpdDataDefinition.FtpdFilesSent.CounterOffset =
  172. (DWORD)((LPBYTE)&ftpc.FilesSent - (LPBYTE)&ftpc);
  173. FtpdDataDefinition.FtpdFilesReceived.CounterNameTitleIndex
  174. += dwFirstCounter;
  175. FtpdDataDefinition.FtpdFilesReceived.CounterHelpTitleIndex
  176. += dwFirstHelp;
  177. FtpdDataDefinition.FtpdFilesReceived.CounterOffset =
  178. (DWORD)((LPBYTE)&ftpc.FilesReceived - (LPBYTE)&ftpc);
  179. FtpdDataDefinition.FtpdFilesTotal.CounterNameTitleIndex
  180. += dwFirstCounter;
  181. FtpdDataDefinition.FtpdFilesTotal.CounterHelpTitleIndex
  182. += dwFirstHelp;
  183. FtpdDataDefinition.FtpdFilesTotal.CounterOffset =
  184. (DWORD)((LPBYTE)&ftpc.FilesTotal - (LPBYTE)&ftpc);
  185. FtpdDataDefinition.FtpdCurrentAnonymous.CounterNameTitleIndex
  186. += dwFirstCounter;
  187. FtpdDataDefinition.FtpdCurrentAnonymous.CounterHelpTitleIndex
  188. += dwFirstHelp;
  189. FtpdDataDefinition.FtpdCurrentAnonymous.CounterOffset =
  190. (DWORD)((LPBYTE)&ftpc.CurrentAnonymous - (LPBYTE)&ftpc);
  191. FtpdDataDefinition.FtpdCurrentNonAnonymous.CounterNameTitleIndex
  192. += dwFirstCounter;
  193. FtpdDataDefinition.FtpdCurrentNonAnonymous.CounterHelpTitleIndex
  194. += dwFirstHelp;
  195. FtpdDataDefinition.FtpdCurrentNonAnonymous.CounterOffset =
  196. (DWORD)((LPBYTE)&ftpc.CurrentNonAnonymous - (LPBYTE)&ftpc);
  197. FtpdDataDefinition.FtpdTotalAnonymous.CounterNameTitleIndex
  198. += dwFirstCounter;
  199. FtpdDataDefinition.FtpdTotalAnonymous.CounterHelpTitleIndex
  200. += dwFirstHelp;
  201. FtpdDataDefinition.FtpdTotalAnonymous.CounterOffset =
  202. (DWORD)((LPBYTE)&ftpc.TotalAnonymous - (LPBYTE)&ftpc);
  203. FtpdDataDefinition.FtpdTotalNonAnonymous.CounterNameTitleIndex
  204. += dwFirstCounter;
  205. FtpdDataDefinition.FtpdTotalNonAnonymous.CounterHelpTitleIndex
  206. += dwFirstHelp;
  207. FtpdDataDefinition.FtpdTotalNonAnonymous.CounterOffset =
  208. (DWORD)((LPBYTE)&ftpc.TotalNonAnonymous - (LPBYTE)&ftpc);
  209. FtpdDataDefinition.FtpdMaxAnonymous.CounterNameTitleIndex
  210. += dwFirstCounter;
  211. FtpdDataDefinition.FtpdMaxAnonymous.CounterHelpTitleIndex
  212. += dwFirstHelp;
  213. FtpdDataDefinition.FtpdMaxAnonymous.CounterOffset =
  214. (DWORD)((LPBYTE)&ftpc.MaxAnonymous - (LPBYTE)&ftpc);
  215. FtpdDataDefinition.FtpdMaxNonAnonymous.CounterNameTitleIndex
  216. += dwFirstCounter;
  217. FtpdDataDefinition.FtpdMaxNonAnonymous.CounterHelpTitleIndex
  218. += dwFirstHelp;
  219. FtpdDataDefinition.FtpdMaxNonAnonymous.CounterOffset =
  220. (DWORD)((LPBYTE)&ftpc.MaxNonAnonymous - (LPBYTE)&ftpc);
  221. FtpdDataDefinition.FtpdCurrentConnections.CounterNameTitleIndex
  222. += dwFirstCounter;
  223. FtpdDataDefinition.FtpdCurrentConnections.CounterHelpTitleIndex
  224. += dwFirstHelp;
  225. FtpdDataDefinition.FtpdCurrentConnections.CounterOffset =
  226. (DWORD)((LPBYTE)&ftpc.CurrentConnections - (LPBYTE)&ftpc);
  227. FtpdDataDefinition.FtpdMaxConnections.CounterNameTitleIndex
  228. += dwFirstCounter;
  229. FtpdDataDefinition.FtpdMaxConnections.CounterHelpTitleIndex
  230. += dwFirstHelp;
  231. FtpdDataDefinition.FtpdMaxConnections.CounterOffset =
  232. (DWORD)((LPBYTE)&ftpc.MaxConnections - (LPBYTE)&ftpc);
  233. FtpdDataDefinition.FtpdConnectionAttempts.CounterNameTitleIndex
  234. += dwFirstCounter;
  235. FtpdDataDefinition.FtpdConnectionAttempts.CounterHelpTitleIndex
  236. += dwFirstHelp;
  237. FtpdDataDefinition.FtpdConnectionAttempts.CounterOffset =
  238. (DWORD)((LPBYTE)&ftpc.ConnectionAttempts - (LPBYTE)&ftpc);
  239. FtpdDataDefinition.FtpdLogonAttempts.CounterNameTitleIndex
  240. += dwFirstCounter;
  241. FtpdDataDefinition.FtpdLogonAttempts.CounterHelpTitleIndex
  242. += dwFirstHelp;
  243. FtpdDataDefinition.FtpdLogonAttempts.CounterOffset =
  244. (DWORD)((LPBYTE)&ftpc.LogonAttempts - (LPBYTE)&ftpc);
  245. FtpdDataDefinition.FtpdServiceUptime.CounterNameTitleIndex
  246. += dwFirstCounter;
  247. FtpdDataDefinition.FtpdServiceUptime.CounterHelpTitleIndex
  248. += dwFirstHelp;
  249. FtpdDataDefinition.FtpdServiceUptime.CounterOffset =
  250. (DWORD)((LPBYTE)&ftpc.ServiceUptime - (LPBYTE)&ftpc);
  251. // These counters are currently meaningless, but should be restored if we
  252. // ever enable per-FTP-instance bandwidth throttling.
  253. /*
  254. FtpdDataDefinition.FtpdBlockedRequests.CounterNameTitleIndex
  255. += dwFirstCounter;
  256. FtpdDataDefinition.FtpdBlockedRequests.CounterHelpTitleIndex
  257. += dwFirstHelp;
  258. FtpdDataDefinition.FtpdBlockedRequests.CounterOffset =
  259. (DWORD)((LPBYTE)&ftpc.BlockedRequests - (LPBYTE)&ftpc);
  260. FtpdDataDefinition.FtpdAllowedRequests.CounterNameTitleIndex
  261. += dwFirstCounter;
  262. FtpdDataDefinition.FtpdAllowedRequests.CounterHelpTitleIndex
  263. += dwFirstHelp;
  264. FtpdDataDefinition.FtpdAllowedRequests.CounterOffset =
  265. (DWORD)((LPBYTE)&ftpc.AllowedRequests - (LPBYTE)&ftpc);
  266. FtpdDataDefinition.FtpdRejectedRequests.CounterNameTitleIndex
  267. += dwFirstCounter;
  268. FtpdDataDefinition.FtpdRejectedRequests.CounterHelpTitleIndex
  269. += dwFirstHelp;
  270. FtpdDataDefinition.FtpdRejectedRequests.CounterOffset =
  271. (DWORD)((LPBYTE)&ftpc.RejectedRequests - (LPBYTE)&ftpc);
  272. FtpdDataDefinition.FtpdCurrentBlockedRequests.CounterNameTitleIndex
  273. += dwFirstCounter;
  274. FtpdDataDefinition.FtpdCurrentBlockedRequests.CounterHelpTitleIndex
  275. += dwFirstHelp;
  276. FtpdDataDefinition.FtpdCurrentBlockedRequests.CounterOffset =
  277. (DWORD)((LPBYTE)&ftpc.CurrentBlockedRequests - (LPBYTE)&ftpc);
  278. FtpdDataDefinition.FtpdMeasuredBandwidth.CounterNameTitleIndex
  279. += dwFirstCounter;
  280. FtpdDataDefinition.FtpdMeasuredBandwidth.CounterHelpTitleIndex
  281. += dwFirstHelp;
  282. FtpdDataDefinition.FtpdMeasuredBandwidth.CounterOffset =
  283. (DWORD)((LPBYTE)&ftpc.MeasuredBandwidth - (LPBYTE)&ftpc);
  284. */
  285. //
  286. // Remember that we initialized OK.
  287. //
  288. fInitOK = TRUE;
  289. } else {
  290. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  291. 0, FTP_UNABLE_QUERY_DATA,
  292. (PSID)NULL, 0,
  293. sizeof(err), NULL,
  294. (PVOID)(&err));
  295. }
  296. } else {
  297. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  298. 0, FTP_UNABLE_QUERY_DATA,
  299. (PSID)NULL, 0,
  300. sizeof(err), NULL,
  301. (PVOID)(&err));
  302. }
  303. //
  304. // Close the registry if we managed to actually open it.
  305. //
  306. if( hkey != NULL )
  307. {
  308. RegCloseKey( hkey );
  309. hkey = NULL;
  310. }
  311. } else {
  312. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  313. 0, FTP_UNABLE_QUERY_DATA,
  314. (PSID)NULL, 0,
  315. sizeof(err), NULL,
  316. (PVOID)(&err));
  317. }
  318. }
  319. //
  320. // Bump open counter.
  321. //
  322. InterlockedIncrement((LPLONG )&cOpens);
  323. return err;
  324. } // OpenFTPPerformanceData
  325. /*******************************************************************
  326. NAME: CollectFtpPerformanceData
  327. SYNOPSIS: Initializes the data structures used to communicate
  328. ENTRY: lpValueName - The name of the value to retrieve.
  329. lppData - On entry contains a pointer to the buffer to
  330. receive the completed PerfDataBlock & subordinate
  331. structures. On exit, points to the first bytes
  332. *after* the data structures added by this routine.
  333. lpcbTotalBytes - On entry contains a pointer to the
  334. size (in BYTEs) of the buffer referenced by lppData.
  335. On exit, contains the number of BYTEs added by this
  336. routine.
  337. lpNumObjectTypes - Receives the number of objects added
  338. by this routine.
  339. RETURNS: DWORD - Win32 status code. MUST be either NO_ERROR
  340. or ERROR_MORE_DATA.
  341. HISTORY:
  342. KeithMo 07-Jun-1993 Created.
  343. ********************************************************************/
  344. DWORD CollectFtpPerformanceData( LPWSTR lpValueName,
  345. LPVOID * lppData,
  346. LPDWORD lpcbTotalBytes,
  347. LPDWORD lpNumObjectTypes )
  348. {
  349. PERF_INSTANCE_DEFINITION * pPerfInstanceDefinition;
  350. DWORD dwInstanceIndex = 0;
  351. DWORD dwInstanceCount = 0;
  352. DWORD i = 0;
  353. DWORD dwQueryType;
  354. ULONG cbRequired;
  355. DWORD * pdwCounter;
  356. LARGE_INTEGER * pliCounter;
  357. FTPD_COUNTER_BLOCK * pCounterBlock;
  358. FTPD_COUNTER_BLOCK * pTotal;
  359. FTPD_DATA_DEFINITION * pFtpdDataDefinition;
  360. FTP_STATISTICS_0 * pFTPStats;
  361. NET_API_STATUS neterr;
  362. HRESULT hresErr;
  363. DWORD dwBufferSize = 0;
  364. LPINET_INFO_SITE_LIST pSites;
  365. //
  366. // No need to even try if we failed to open...
  367. //
  368. if( !fInitOK )
  369. {
  370. *lpcbTotalBytes = 0;
  371. *lpNumObjectTypes = 0;
  372. //
  373. // According to the Performance Counter design, this
  374. // is a successful exit. Go figure.
  375. //
  376. return NO_ERROR;
  377. }
  378. //
  379. // Determine the query type.
  380. //
  381. dwQueryType = GetQueryType( lpValueName );
  382. if (( dwQueryType == QUERY_FOREIGN ) || (dwQueryType == QUERY_COSTLY))
  383. {
  384. //
  385. // We don't do foreign queries.
  386. //
  387. *lpcbTotalBytes = 0;
  388. *lpNumObjectTypes = 0;
  389. return NO_ERROR;
  390. }
  391. if( dwQueryType == QUERY_ITEMS )
  392. {
  393. //
  394. // The registry is asking for a specific object. Let's
  395. // see if we're one of the chosen.
  396. //
  397. if( !IsNumberInUnicodeList(
  398. FtpdDataDefinition.FtpdObjectType.ObjectNameTitleIndex,
  399. lpValueName ) )
  400. {
  401. *lpcbTotalBytes = 0;
  402. *lpNumObjectTypes = 0;
  403. return NO_ERROR;
  404. }
  405. }
  406. //
  407. // Enumerate and get total number of instances count.
  408. //
  409. neterr = InetInfoGetSites(
  410. NULL,
  411. INET_FTP_SVC_ID,
  412. &pSites
  413. );
  414. if( neterr != NERR_Success )
  415. {
  416. //
  417. // Only event log once for each server down
  418. //
  419. // if the server is down, we don't log an error.
  420. if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
  421. neterr == RPC_S_UNKNOWN_IF ||
  422. neterr == ERROR_SERVICE_NOT_ACTIVE ||
  423. neterr == RPC_S_CALL_FAILED_DNE ))
  424. {
  425. //
  426. // Error retrieving statistics.
  427. //
  428. ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE,
  429. 0, FTP_UNABLE_QUERY_DATA,
  430. (PSID)NULL, 0,
  431. sizeof(neterr), NULL,
  432. (PVOID)(&neterr));
  433. }
  434. *lpcbTotalBytes = 0;
  435. *lpNumObjectTypes = 0;
  436. return NO_ERROR;
  437. }
  438. //
  439. // add 1 to dwInstanceCount for _Total instance
  440. //
  441. dwInstanceCount = pSites->cEntries + 1;
  442. //
  443. // always return an "instance sized" buffer after the definition
  444. // blocks to prevent perfmon from reading bogus data. This is strictly
  445. // a hack to accomodate how PERFMON handles the "0" instance case.
  446. // By doing this, perfmon won't choke when there are no instances
  447. // and the counter object & counters will be displayed in the list
  448. // boxes, even though no instances will be listed.
  449. //
  450. pFtpdDataDefinition = (FTPD_DATA_DEFINITION *)*lppData;
  451. cbRequired = sizeof(FTPD_DATA_DEFINITION) +
  452. (dwInstanceCount * (sizeof(PERF_INSTANCE_DEFINITION) +
  453. MAX_SIZEOF_INSTANCE_NAME +
  454. sizeof (FTPD_COUNTER_BLOCK)));
  455. //
  456. // See if there's enough space.
  457. //
  458. if( *lpcbTotalBytes < cbRequired )
  459. {
  460. //
  461. // Nope.
  462. //
  463. *lpcbTotalBytes = 0;
  464. *lpNumObjectTypes = 0;
  465. MIDL_user_free(pSites);
  466. return ERROR_MORE_DATA;
  467. }
  468. //
  469. // Copy the (constant, initialized) Object Type and counter definitions
  470. // to the caller's data buffer
  471. //
  472. memmove( pFtpdDataDefinition,
  473. &FtpdDataDefinition,
  474. sizeof(FTPD_DATA_DEFINITION) );
  475. //
  476. // Create data for return for each instance
  477. //
  478. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  479. &pFtpdDataDefinition[1];
  480. //
  481. // Set first block of Buffer for _Total
  482. //
  483. MonBuildInstanceDefinition(
  484. pPerfInstanceDefinition,
  485. (PVOID *)&pCounterBlock,
  486. 0,
  487. 0,
  488. (DWORD)-1, // use name
  489. TOTAL_INSTANCE_NAME ); // pass in instance name
  490. pTotal = pCounterBlock;
  491. memset( pTotal, 0, sizeof(FTPD_COUNTER_BLOCK ));
  492. pTotal->PerfCounterBlock.ByteLength = sizeof (FTPD_COUNTER_BLOCK);
  493. pPerfInstanceDefinition =
  494. (PERF_INSTANCE_DEFINITION *)((LPBYTE)pCounterBlock +
  495. sizeof(FTPD_COUNTER_BLOCK));
  496. neterr = FtpQueryStatistics2(
  497. NULL,
  498. 0,
  499. 0, // instance id, 0 for global stats
  500. 0,
  501. (LPBYTE *)&pFTPStats );
  502. if( neterr == NERR_Success )
  503. {
  504. pTotal->ServiceUptime = pFTPStats->ServiceUptime;
  505. }
  506. MIDL_user_free( pFTPStats );
  507. for ( i = 0; i < pSites->cEntries; i++)
  508. {
  509. MonBuildInstanceDefinition(
  510. pPerfInstanceDefinition,
  511. (PVOID *)&pCounterBlock,
  512. 0,
  513. 0,
  514. (DWORD)-1, // use name
  515. pSites->aSiteEntry[i].pszComment // pass in instance name
  516. );
  517. //
  518. // query for statistics info
  519. //
  520. neterr = FtpQueryStatistics2(
  521. NULL,
  522. 0,
  523. pSites->aSiteEntry[i].dwInstance, // instance id
  524. 0,
  525. (LPBYTE *)&pFTPStats );
  526. if( neterr != NERR_Success )
  527. {
  528. //
  529. // Only event log once for each server down
  530. //
  531. // if the server is down, we don't log an error.
  532. if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
  533. neterr == RPC_S_UNKNOWN_IF ||
  534. neterr == ERROR_SERVICE_NOT_ACTIVE ||
  535. neterr == RPC_S_CALL_FAILED_DNE ))
  536. {
  537. //
  538. // Error retrieving statistics.
  539. //
  540. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  541. 0, FTP_UNABLE_QUERY_DATA,
  542. (PSID)NULL, 0,
  543. sizeof(neterr), NULL,
  544. (PVOID)(&neterr));
  545. }
  546. *lpcbTotalBytes = 0;
  547. *lpNumObjectTypes = 0;
  548. MIDL_user_free(pSites);
  549. return NO_ERROR;
  550. }
  551. //
  552. // Format the FTP Server data.
  553. //
  554. CopyStatisticsData( pFTPStats,
  555. pCounterBlock );
  556. //
  557. // update _total instance counters
  558. //
  559. Update_TotalStatisticsData( pCounterBlock,
  560. pTotal );
  561. pPerfInstanceDefinition =
  562. (PERF_INSTANCE_DEFINITION *)((LPBYTE)pCounterBlock +
  563. sizeof(FTPD_COUNTER_BLOCK));
  564. //
  565. // Free the API buffer.
  566. //
  567. MIDL_user_free( pFTPStats );
  568. }
  569. if (dwInstanceCount == 1) {
  570. //
  571. // zero fill one instance sized block of data if there's no data
  572. // instances
  573. //
  574. memset (pPerfInstanceDefinition, 0,
  575. (sizeof(PERF_INSTANCE_DEFINITION) +
  576. MAX_SIZEOF_INSTANCE_NAME +
  577. sizeof(FTPD_COUNTER_BLOCK)));
  578. // adjust pointer to point to end of zeroed block
  579. pPerfInstanceDefinition += (sizeof(PERF_INSTANCE_DEFINITION) +
  580. MAX_SIZEOF_INSTANCE_NAME +
  581. sizeof(FTPD_COUNTER_BLOCK));
  582. }
  583. //
  584. // Update arguments for return.
  585. //
  586. *lppData = (PVOID)(pPerfInstanceDefinition);
  587. *lpNumObjectTypes = 1;
  588. pFtpdDataDefinition->FtpdObjectType.NumInstances = dwInstanceCount;
  589. pFtpdDataDefinition->FtpdObjectType.TotalByteLength =
  590. *lpcbTotalBytes = DIFF((PBYTE)pPerfInstanceDefinition -
  591. (PBYTE)pFtpdDataDefinition);
  592. //
  593. // Success! Honest!!
  594. //
  595. MIDL_user_free(pSites);
  596. return NO_ERROR;
  597. } // CollectFTPPerformanceData
  598. /*******************************************************************
  599. NAME: CloseFtpPerformanceData
  600. SYNOPSIS: Terminates the performance counters.
  601. RETURNS: DWORD - Win32 status code.
  602. HISTORY:
  603. KeithMo 07-Jun-1993 Created.
  604. ********************************************************************/
  605. DWORD CloseFtpPerformanceData( VOID )
  606. {
  607. DWORD dwCount = InterlockedDecrement((LPLONG )&cOpens);
  608. if ((dwCount) == 0) {
  609. if (hEventLog != NULL)
  610. {
  611. DeregisterEventSource (hEventLog);
  612. hEventLog = NULL;
  613. };
  614. }
  615. return NO_ERROR;
  616. } // CloseFTPPerformanceData
  617. VOID
  618. CopyStatisticsData(
  619. IN FTP_STATISTICS_0 * pFTPStats,
  620. OUT FTPD_COUNTER_BLOCK * pCounterBlock
  621. )
  622. {
  623. //
  624. // Format the FTP Server data.
  625. //
  626. pCounterBlock->PerfCounterBlock.ByteLength = sizeof (FTPD_COUNTER_BLOCK);
  627. pCounterBlock->BytesSent = pFTPStats->TotalBytesSent.QuadPart;
  628. pCounterBlock->BytesReceived = pFTPStats->TotalBytesReceived.QuadPart;
  629. pCounterBlock->BytesTotal = pFTPStats->TotalBytesSent.QuadPart +
  630. pFTPStats->TotalBytesReceived.QuadPart;
  631. pCounterBlock->FilesSent = pFTPStats->TotalFilesSent;
  632. pCounterBlock->FilesReceived = pFTPStats->TotalFilesReceived;
  633. pCounterBlock->FilesTotal = pFTPStats->TotalFilesSent +
  634. pFTPStats->TotalFilesReceived;
  635. pCounterBlock->CurrentAnonymous = pFTPStats->CurrentAnonymousUsers;
  636. pCounterBlock->CurrentNonAnonymous = pFTPStats->CurrentNonAnonymousUsers;
  637. pCounterBlock->TotalAnonymous = pFTPStats->TotalAnonymousUsers;
  638. pCounterBlock->TotalNonAnonymous = pFTPStats->TotalNonAnonymousUsers;
  639. pCounterBlock->MaxAnonymous = pFTPStats->MaxAnonymousUsers;
  640. pCounterBlock->MaxNonAnonymous = pFTPStats->MaxNonAnonymousUsers;
  641. pCounterBlock->CurrentConnections = pFTPStats->CurrentConnections;
  642. pCounterBlock->MaxConnections = pFTPStats->MaxConnections;
  643. pCounterBlock->ConnectionAttempts = pFTPStats->ConnectionAttempts;
  644. pCounterBlock->LogonAttempts = pFTPStats->LogonAttempts;
  645. pCounterBlock->ServiceUptime = pFTPStats->ServiceUptime;
  646. // These counters are currently meaningless, but should be restored if we
  647. // ever enable per-FTP-instance bandwidth throttling.
  648. /*
  649. pCounterBlock->BlockedRequests = pFTPStats->TotalBlockedRequests;
  650. pCounterBlock->AllowedRequests = pFTPStats->TotalAllowedRequests;
  651. pCounterBlock->RejectedRequests = pFTPStats->TotalRejectedRequests;
  652. pCounterBlock->MeasuredBandwidth= pFTPStats->MeasuredBandwidth;
  653. pCounterBlock->CurrentBlockedRequests = pFTPStats->CurrentBlockedRequests;
  654. */
  655. } // CopyStatisticsData
  656. VOID
  657. Update_TotalStatisticsData(
  658. IN FTPD_COUNTER_BLOCK * pCounterBlock,
  659. OUT FTPD_COUNTER_BLOCK * pTotal
  660. )
  661. {
  662. //
  663. // update _total instance counters
  664. //
  665. pTotal->BytesSent += pCounterBlock->BytesSent;
  666. pTotal->BytesReceived += pCounterBlock->BytesReceived;
  667. pTotal->BytesTotal += pCounterBlock->BytesTotal;
  668. pTotal->FilesSent += pCounterBlock->FilesSent;
  669. pTotal->FilesReceived += pCounterBlock->FilesReceived;
  670. pTotal->FilesTotal += pCounterBlock->FilesTotal;
  671. pTotal->CurrentAnonymous += pCounterBlock->CurrentAnonymous;
  672. pTotal->CurrentNonAnonymous += pCounterBlock->CurrentNonAnonymous;
  673. pTotal->TotalAnonymous += pCounterBlock->TotalAnonymous;
  674. pTotal->TotalNonAnonymous += pCounterBlock->TotalNonAnonymous;
  675. pTotal->MaxAnonymous += pCounterBlock->MaxAnonymous;
  676. pTotal->MaxNonAnonymous += pCounterBlock->MaxNonAnonymous;
  677. pTotal->CurrentConnections += pCounterBlock->CurrentConnections;
  678. pTotal->MaxConnections += pCounterBlock->MaxConnections;
  679. pTotal->ConnectionAttempts = pCounterBlock->ConnectionAttempts;
  680. pTotal->LogonAttempts += pCounterBlock->LogonAttempts;
  681. // These counters are currently meaningless, but should be restored if we
  682. // ever enable per-FTP-instance bandwidth throttling.
  683. /*
  684. pTotal->BlockedRequests += pCounterBlock->BlockedRequests;
  685. pTotal->RejectedRequests += pCounterBlock->RejectedRequests;
  686. pTotal->AllowedRequests += pCounterBlock->AllowedRequests;
  687. pTotal->MeasuredBandwidth += pCounterBlock->MeasuredBandwidth;
  688. pTotal->CurrentBlockedRequests += pCounterBlock->CurrentBlockedRequests;
  689. */
  690. } // Update_TotalStatisticsData