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.

853 lines
32 KiB

  1. //---------------------------------------------------------------
  2. // File: perfsmtp.c
  3. //
  4. // Synopsis: This file implements the Extensible Performance
  5. // Objects for the SMTP service.
  6. //
  7. // Copyright (C) 1996 Microsoft Corporation
  8. // All rights reserved.
  9. //
  10. // Authors: toddch - based on rkamicar, keithmo source
  11. //----------------------------------------------------------------
  12. #ifdef THIS_FILE
  13. #undef THIS_FILE
  14. #endif
  15. static char __szTraceSourceFile[] = __FILE__;
  16. #define THIS_FILE __szTraceSourceFile
  17. #define NOTRACE
  18. #define INITGUID
  19. #include <nt.h> // For ntrtl.h
  20. #include <ntrtl.h> // RtlLargeInteger*()
  21. #include <nturtl.h> // For windows.h
  22. #include <windows.h>
  23. #include <winperf.h>
  24. #include <lm.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include "smtpdata.h" // The counter descriptions
  28. #include "smtpctrs.h" // more counter descriptions
  29. #include "perfutil.h" // Perfmon support
  30. #include "smtps.h" // Registry Key strings.
  31. #include "smtpapi.h" // RPC interface wrappers
  32. #include "dbgtrace.h"
  33. //
  34. // Private globals.
  35. //
  36. DWORD cOpens = 0; // Active "opens" reference count.
  37. BOOL fInitOK = FALSE; // TRUE if DLL initialized OK.
  38. //
  39. // Public prototypes.
  40. //
  41. PM_OPEN_PROC OpenSmtpPerformanceData;
  42. PM_COLLECT_PROC CollectSmtpPerformanceData;
  43. PM_CLOSE_PROC CloseSmtpPerformanceData;
  44. //
  45. // Public functions.
  46. //
  47. /*******************************************************************
  48. NAME: OpenSmtpPerformanceData
  49. SYNOPSIS: Initializes the data structures used to communicate
  50. performance counters with the registry.
  51. ENTRY: lpDeviceNames - Pointer to object ID of each device
  52. to be opened.
  53. RETURNS: DWORD - Win32 status code.
  54. HISTORY:
  55. KeithMo 07-Jun-1993 Created.
  56. ********************************************************************/
  57. DWORD APIENTRY
  58. OpenSmtpPerformanceData(LPWSTR lpDeviceNames)
  59. {
  60. PERF_COUNTER_DEFINITION *pctr;
  61. DWORD i;
  62. DWORD dwFirstCounter = 0;
  63. DWORD dwFirstHelp = 0;
  64. DWORD err = NO_ERROR;
  65. HKEY hkey = NULL;
  66. DWORD size;
  67. DWORD type;
  68. BOOL fOpenRegKey = FALSE;
  69. #ifndef NOTRACE
  70. //
  71. // make sure that tracing is enabled
  72. //
  73. InitAsyncTrace();
  74. #endif
  75. //
  76. // we need to have another level of scoping here for TraceFunctEnter()
  77. // to work
  78. //
  79. {
  80. TraceFunctEnter("OpenSmtpPerformanceData");
  81. //
  82. // Since SCREG is multi-threaded and will call this routine in
  83. // order to service remote performance queries, this library
  84. // must keep track of how many times it has been opened (i.e.
  85. // how many threads have accessed it). The registry routines will
  86. // limit access to the initialization routine to only one thread
  87. // at a time so synchronization (i.e. reentrancy) should not be
  88. // a problem.
  89. //
  90. if(!fInitOK)
  91. {
  92. //
  93. // This is the *first* open - update the indicies in
  94. // our table with the offset of our counters within the
  95. // perfmon key.
  96. //
  97. DebugTrace(0, "Initializing.");
  98. //
  99. // Open the service's Performance key and get the
  100. // offsets of our counters within the PerfLib MULTI_SZ.
  101. //
  102. err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  103. SMTP_PERFORMANCE_KEY,
  104. 0,
  105. KEY_READ,
  106. &hkey);
  107. if(err == NO_ERROR) {
  108. fOpenRegKey = TRUE;
  109. size = sizeof(DWORD);
  110. err = RegQueryValueEx(hkey,
  111. "First Counter",
  112. NULL,
  113. &type,
  114. (LPBYTE)&dwFirstCounter,
  115. &size);
  116. } else {
  117. DebugTrace(0, "No 'First Counter' key (err = %d) in '%s'",
  118. err, SMTP_PERFORMANCE_KEY);
  119. }
  120. if(err == NO_ERROR) {
  121. size = sizeof(DWORD);
  122. err = RegQueryValueEx(hkey,
  123. "First Help",
  124. NULL,
  125. &type,
  126. (LPBYTE)&dwFirstHelp,
  127. &size);
  128. } else {
  129. DebugTrace(0, "No 'First Help' key (err = %d) in '%s'",
  130. err, SMTP_PERFORMANCE_KEY);
  131. }
  132. if (NO_ERROR == err)
  133. {
  134. //
  135. // Update the object & counter name & help indicies.
  136. //
  137. SmtpDataDefinition.SmtpObjectType.ObjectNameTitleIndex += dwFirstCounter;
  138. SmtpDataDefinition.SmtpObjectType.ObjectHelpTitleIndex += dwFirstHelp;
  139. pctr = &SmtpDataDefinition.SmtpBytesSentTtl;
  140. for(i = 0; i < NUMBER_OF_SMTP_COUNTERS; i++) {
  141. pctr->CounterNameTitleIndex += dwFirstCounter;
  142. pctr->CounterHelpTitleIndex += dwFirstHelp;
  143. pctr++;
  144. }
  145. //
  146. // Remember that we initialized OK.
  147. //
  148. fInitOK = TRUE;
  149. } else {
  150. DebugTrace(0, "No 'First Help' key (err = %d) in '%s'",
  151. err, SMTP_PERFORMANCE_KEY);
  152. }
  153. if (fOpenRegKey)
  154. {
  155. err = RegCloseKey(hkey);
  156. // This should never fail!
  157. _ASSERT(err == ERROR_SUCCESS);
  158. }
  159. }
  160. //
  161. // Bump open counter.
  162. //
  163. cOpens++;
  164. TraceFunctLeave();
  165. } // end of TraceFunctEnter() scoping
  166. return NO_ERROR;
  167. } // OpenSmtpPerformanceData
  168. /*******************************************************************
  169. NAME: CollectSmtpPerformanceData
  170. SYNOPSIS: Initializes the data structures used to communicate
  171. ENTRY: lpValueName - The name of the value to retrieve.
  172. lppData - On entry contains a pointer to the buffer to
  173. receive the completed PerfDataBlock & subordinate
  174. structures. On exit, points to the first bytes
  175. *after* the data structures added by this routine.
  176. lpcbTotalBytes - On entry contains a pointer to the
  177. size (in BYTEs) of the buffer referenced by lppData.
  178. On exit, contains the number of BYTEs added by this
  179. routine.
  180. lpNumObjectTypes - Receives the number of objects added
  181. by this routine.
  182. RETURNS: DWORD - Win32 status code. MUST be either NO_ERROR
  183. or ERROR_MORE_DATA.
  184. HISTORY:
  185. KeithMo 07-Jun-1993 Created.
  186. ********************************************************************/
  187. DWORD APIENTRY
  188. CollectSmtpPerformanceData(LPWSTR lpValueName,
  189. LPVOID * lppData,
  190. LPDWORD lpcbTotalBytes,
  191. LPDWORD lpNumObjectTypes)
  192. {
  193. DWORD dwQueryType;
  194. ULONG cbRequired;
  195. DWORD * pdwCounter;
  196. DWORD * pdwEndCounter;
  197. unsigned __int64 * pliCounter;
  198. SMTP_COUNTER_BLOCK * pCounterBlock;
  199. SMTP_DATA_DEFINITION * pSmtpDataDefinition;
  200. SMTP_INSTANCE_DEFINITION * pSmtpInstanceDefinition;
  201. SMTP_INSTANCE_DEFINITION * pInstanceTotalDefinition;
  202. PSMTP_STATISTICS_BLOCK_ARRAY pSmtpStatsBlockArray;
  203. PSMTP_STATISTICS_BLOCK pSmtpStatsBlock;
  204. LPSMTP_STATISTICS_0 pSmtpStats;
  205. NET_API_STATUS neterr;
  206. DWORD dwInstance;
  207. DWORD dwInstanceIndex;
  208. DWORD dwInstanceCount;
  209. CHAR temp[INSTANCE_NAME_SIZE];
  210. DWORD ii;
  211. TraceFunctEnter("CollectSmtpPerformanceData");
  212. // DebugTrace(0, " lpValueName = %08lX (%ls)", lpValueName, lpValueName);
  213. DebugTrace(0, " lppData = %08lX (%08lX)", lppData, *lppData);
  214. DebugTrace(0, " lpcbTotalBytes = %08lX (%08lX)",
  215. lpcbTotalBytes, *lpcbTotalBytes);
  216. DebugTrace(0, " lpNumObjectTypes= %08lX (%08lX)",
  217. lpNumObjectTypes, *lpNumObjectTypes);
  218. //
  219. // No need to even try if we failed to open...
  220. //
  221. if(!fInitOK)
  222. {
  223. ErrorTrace(0, "Initialization failed, aborting.");
  224. *lpcbTotalBytes = 0;
  225. *lpNumObjectTypes = 0;
  226. //
  227. // According to the Performance Counter design, this
  228. // is a successful exit. Go figure.
  229. //
  230. TraceFunctLeave();
  231. return NO_ERROR;
  232. }
  233. //
  234. // Determine the query type.
  235. //
  236. dwQueryType = GetQueryType(lpValueName);
  237. if(dwQueryType == QUERY_FOREIGN)
  238. {
  239. ErrorTrace(0, "Foreign queries not supported.");
  240. //
  241. // We don't do foreign queries.
  242. //
  243. *lpcbTotalBytes = 0;
  244. *lpNumObjectTypes = 0;
  245. TraceFunctLeave();
  246. return NO_ERROR;
  247. }
  248. if(dwQueryType == QUERY_ITEMS)
  249. {
  250. //
  251. // The registry is asking for a specific object. Let's
  252. // see if we're one of the chosen.
  253. //
  254. if(!IsNumberInUnicodeList(
  255. SmtpDataDefinition.SmtpObjectType.ObjectNameTitleIndex,
  256. lpValueName))
  257. {
  258. ErrorTrace(0, "%ls not a supported object type.", lpValueName);
  259. *lpcbTotalBytes = 0;
  260. *lpNumObjectTypes = 0;
  261. TraceFunctLeave();
  262. return NO_ERROR;
  263. }
  264. }
  265. //
  266. // Query the statistics and see if there has been enough space allocated.
  267. // The number of instances will be returned in dwInstanceCount
  268. //
  269. neterr = SmtpQueryStatistics( NULL, 0, (LPBYTE *) &pSmtpStatsBlockArray);
  270. if( neterr != NERR_Success )
  271. {
  272. *lpcbTotalBytes = 0;
  273. *lpNumObjectTypes = 0;
  274. TraceFunctLeave();
  275. return NO_ERROR;
  276. }
  277. //
  278. // Check the space requirement add one to the number of instances for the totals.
  279. //
  280. dwInstanceCount = pSmtpStatsBlockArray->cEntries;
  281. if(*lpcbTotalBytes < (sizeof(SMTP_DATA_DEFINITION) +
  282. (dwInstanceCount + 1) * (sizeof(SMTP_INSTANCE_DEFINITION) + SIZE_OF_SMTP_PERFORMANCE_DATA)))
  283. {
  284. ErrorTrace(0, "%lu bytes of buffer insufficient, need %lu.",
  285. *lpcbTotalBytes, cbRequired);
  286. //
  287. // Nope.
  288. //
  289. *lpcbTotalBytes = 0;
  290. *lpNumObjectTypes = 0;
  291. //
  292. // Free the returned buffer
  293. //
  294. NetApiBufferFree((LPBYTE)pSmtpStatsBlockArray);
  295. TraceFunctLeave();
  296. return ERROR_MORE_DATA;
  297. }
  298. //
  299. // Copy the (constant, initialized) Object Type and counter definitions
  300. // to the caller's data buffer
  301. //
  302. pSmtpDataDefinition = (SMTP_DATA_DEFINITION *)*lppData;
  303. CopyMemory(pSmtpDataDefinition, &SmtpDataDefinition,
  304. sizeof(SMTP_DATA_DEFINITION));
  305. //
  306. // Initialize the Total Instance
  307. //
  308. pSmtpInstanceDefinition = (SMTP_INSTANCE_DEFINITION *)(pSmtpDataDefinition + 1);
  309. pInstanceTotalDefinition = pSmtpInstanceDefinition;
  310. CopyMemory(pInstanceTotalDefinition, &SmtpInstanceDefinition, sizeof(SMTP_INSTANCE_DEFINITION));
  311. //
  312. // For the Total Instance update the namelength, insert the name, add 1 for null.
  313. //
  314. sprintf(temp,"_Total");
  315. pInstanceTotalDefinition->PerfInstanceDef.NameLength =
  316. 2 * (MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,temp,-1,
  317. (pInstanceTotalDefinition->InstanceName),INSTANCE_NAME_SIZE)) + 1;
  318. ZeroMemory((PVOID)(pInstanceTotalDefinition + 1),SIZE_OF_SMTP_PERFORMANCE_DATA);
  319. //
  320. // Begin looping through Instances.
  321. //
  322. pSmtpStatsBlock = pSmtpStatsBlockArray->aStatsBlock;
  323. for (ii = 0; ii < dwInstanceCount; ii++)
  324. {
  325. dwInstance = pSmtpStatsBlock->dwInstance;
  326. pSmtpStats = &(pSmtpStatsBlock->Stats_0);
  327. //
  328. // Copy the (constant, initialized) Instance Definition to the block for the instance.
  329. //
  330. pSmtpInstanceDefinition = (SMTP_INSTANCE_DEFINITION *)((DWORD_PTR)pSmtpInstanceDefinition +
  331. sizeof(SMTP_INSTANCE_DEFINITION) + SIZE_OF_SMTP_PERFORMANCE_DATA);
  332. CopyMemory(pSmtpInstanceDefinition, &SmtpInstanceDefinition, sizeof(SMTP_INSTANCE_DEFINITION));
  333. //
  334. // update the namelength, insert the name, add 1 for null.
  335. //
  336. sprintf(temp,"SMTP %u", dwInstance);
  337. pSmtpInstanceDefinition->PerfInstanceDef.NameLength =
  338. 2 * (MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,temp,-1,
  339. (pSmtpInstanceDefinition->InstanceName),INSTANCE_NAME_SIZE)) + 1;
  340. //
  341. // Fill in the counter block.
  342. //
  343. pCounterBlock = (SMTP_COUNTER_BLOCK *)(pSmtpInstanceDefinition + 1);
  344. pCounterBlock->PerfCounterBlock.ByteLength = SIZE_OF_SMTP_PERFORMANCE_DATA;
  345. //
  346. // Get the pointer to the first (unsigned __int64) counter. This
  347. // pointer *must* be quadword aligned.
  348. //
  349. pliCounter = (unsigned __int64 *)(pCounterBlock + 1);
  350. DebugTrace(0, "pSmtpDataDefinition = %08lX", pSmtpDataDefinition);
  351. DebugTrace(0, "pCounterBlock = %08lX", pCounterBlock);
  352. DebugTrace(0, "ByteLength = %08lX",
  353. pCounterBlock->PerfCounterBlock.ByteLength);
  354. DebugTrace(0, "pliCounter = %08lX", pliCounter);
  355. //
  356. // Move the 'unsigned __int64's into the buffer.
  357. //
  358. *pliCounter++ = pSmtpStats->BytesSentTotal;
  359. *pliCounter++ = pSmtpStats->BytesSentTotal;
  360. *pliCounter++ = pSmtpStats->BytesRcvdTotal;
  361. *pliCounter++ = pSmtpStats->BytesRcvdTotal;
  362. *pliCounter++ = pSmtpStats->BytesSentTotal + pSmtpStats->BytesRcvdTotal;
  363. *pliCounter++ = pSmtpStats->BytesSentTotal + pSmtpStats->BytesRcvdTotal;
  364. *pliCounter++ = pSmtpStats->BytesSentMsg;
  365. *pliCounter++ = pSmtpStats->BytesSentMsg;
  366. *pliCounter++ = pSmtpStats->BytesRcvdMsg;
  367. *pliCounter++ = pSmtpStats->BytesRcvdMsg;
  368. *pliCounter++ = pSmtpStats->BytesSentMsg + pSmtpStats->BytesRcvdMsg;
  369. *pliCounter++ = pSmtpStats->BytesSentMsg + pSmtpStats->BytesRcvdMsg;
  370. //
  371. // Now move the DWORDs into the buffer.
  372. //
  373. pdwCounter = (DWORD *)pliCounter;
  374. DebugTrace(0, "pdwCounter = %08lX", pdwCounter);
  375. // Messages Received
  376. *pdwCounter++ = pSmtpStats->NumMsgRecvd;
  377. *pdwCounter++ = pSmtpStats->NumMsgRecvd;
  378. *pdwCounter++ = pSmtpStats->NumRcptsRecvd;
  379. *pdwCounter++ = pSmtpStats->NumMsgRecvd * 100;
  380. *pdwCounter++ = pSmtpStats->NumRcptsRecvdLocal;
  381. *pdwCounter++ = pSmtpStats->NumRcptsRecvd;
  382. *pdwCounter++ = pSmtpStats->NumRcptsRecvdRemote;
  383. *pdwCounter++ = pSmtpStats->NumRcptsRecvd;
  384. *pdwCounter++ = pSmtpStats->MsgsRefusedDueToSize;
  385. *pdwCounter++ = pSmtpStats->MsgsRefusedDueToNoCAddrObjects;
  386. *pdwCounter++ = pSmtpStats->MsgsRefusedDueToNoMailObjects;
  387. // MTA Deliveries
  388. *pdwCounter++ = pSmtpStats->NumMsgsDelivered;
  389. *pdwCounter++ = pSmtpStats->NumMsgsDelivered;
  390. *pdwCounter++ = pSmtpStats->NumDeliveryRetries;
  391. *pdwCounter++ = pSmtpStats->NumDeliveryRetries;
  392. *pdwCounter++ = pSmtpStats->NumMsgsDelivered * 100;
  393. *pdwCounter++ = pSmtpStats->NumMsgsForwarded;
  394. *pdwCounter++ = pSmtpStats->NumMsgsForwarded;
  395. *pdwCounter++ = pSmtpStats->NumNDRGenerated;
  396. *pdwCounter++ = pSmtpStats->LocalQueueLength;
  397. *pdwCounter++ = pSmtpStats->RetryQueueLength;
  398. *pdwCounter++ = pSmtpStats->NumMailFileHandles;
  399. *pdwCounter++ = pSmtpStats->NumQueueFileHandles;
  400. *pdwCounter++ = pSmtpStats->CatQueueLength;
  401. // Messages Sent
  402. *pdwCounter++ = pSmtpStats->NumMsgsSent;
  403. *pdwCounter++ = pSmtpStats->NumMsgsSent;
  404. *pdwCounter++ = pSmtpStats->NumSendRetries;
  405. *pdwCounter++ = pSmtpStats->NumSendRetries;
  406. *pdwCounter++ = pSmtpStats->NumMsgsSent * 100;
  407. *pdwCounter++ = pSmtpStats->NumRcptsSent;
  408. *pdwCounter++ = pSmtpStats->NumMsgsSent * 100;
  409. *pdwCounter++ = pSmtpStats->RemoteQueueLength;
  410. // DNS lookups
  411. *pdwCounter++ = pSmtpStats->NumDnsQueries;
  412. *pdwCounter++ = pSmtpStats->NumDnsQueries;
  413. *pdwCounter++ = pSmtpStats->RemoteRetryQueueLength;
  414. // Connections
  415. *pdwCounter++ = pSmtpStats->NumConnInOpen;
  416. *pdwCounter++ = pSmtpStats->NumConnInOpen - pSmtpStats->NumConnInClose;
  417. *pdwCounter++ = pSmtpStats->NumConnOutOpen;
  418. *pdwCounter++ = pSmtpStats->NumConnOutOpen - pSmtpStats->NumConnOutClose;
  419. *pdwCounter++ = pSmtpStats->NumConnOutRefused;
  420. *pdwCounter++ = pSmtpStats->NumProtocolErrs;
  421. *pdwCounter++ = pSmtpStats->NumProtocolErrs;
  422. *pdwCounter++ = pSmtpStats->DirectoryDrops;
  423. *pdwCounter++ = pSmtpStats->DirectoryDrops;
  424. *pdwCounter++ = pSmtpStats->RoutingTableLookups;
  425. *pdwCounter++ = pSmtpStats->RoutingTableLookups;
  426. *pdwCounter++ = pSmtpStats->ETRNMessages;
  427. *pdwCounter++ = pSmtpStats->ETRNMessages;
  428. // new AQueue counters
  429. *pdwCounter++ = pSmtpStats->MsgsBadmailNoRecipients;
  430. *pdwCounter++ = pSmtpStats->MsgsBadmailHopCountExceeded;
  431. *pdwCounter++ = pSmtpStats->MsgsBadmailFailureGeneral;
  432. *pdwCounter++ = pSmtpStats->MsgsBadmailBadPickupFile;
  433. *pdwCounter++ = pSmtpStats->MsgsBadmailEvent;
  434. *pdwCounter++ = pSmtpStats->MsgsBadmailNdrOfDsn;
  435. *pdwCounter++ = pSmtpStats->MsgsPendingRouting;
  436. *pdwCounter++ = pSmtpStats->MsgsPendingUnreachableLink;
  437. *pdwCounter++ = pSmtpStats->SubmittedMessages;
  438. *pdwCounter++ = pSmtpStats->DSNFailures;
  439. *pdwCounter++ = pSmtpStats->MsgsInLocalDelivery;
  440. // Cat counters
  441. *pdwCounter++ = pSmtpStats->CatPerfBlock.CatSubmissions;
  442. *pdwCounter++ = pSmtpStats->CatPerfBlock.CatCompletions;
  443. *pdwCounter++ = pSmtpStats->CatPerfBlock.CurrentCategorizations;
  444. *pdwCounter++ = pSmtpStats->CatPerfBlock.SucceededCategorizations;
  445. *pdwCounter++ = pSmtpStats->CatPerfBlock.HardFailureCategorizations;
  446. *pdwCounter++ = pSmtpStats->CatPerfBlock.RetryFailureCategorizations;
  447. *pdwCounter++ = pSmtpStats->CatPerfBlock.RetryOutOfMemory;
  448. *pdwCounter++ = pSmtpStats->CatPerfBlock.RetryDSLogon;
  449. *pdwCounter++ = pSmtpStats->CatPerfBlock.RetryDSConnection;
  450. *pdwCounter++ = pSmtpStats->CatPerfBlock.RetryGeneric;
  451. *pdwCounter++ = pSmtpStats->CatPerfBlock.MessagesSubmittedToQueueing;
  452. *pdwCounter++ = pSmtpStats->CatPerfBlock.MessagesCreated;
  453. *pdwCounter++ = pSmtpStats->CatPerfBlock.MessagesAborted;
  454. *pdwCounter++ = pSmtpStats->CatPerfBlock.PreCatRecipients;
  455. *pdwCounter++ = pSmtpStats->CatPerfBlock.PostCatRecipients;
  456. *pdwCounter++ = pSmtpStats->CatPerfBlock.NDRdRecipients;
  457. *pdwCounter++ = pSmtpStats->CatPerfBlock.UnresolvedRecipients;
  458. *pdwCounter++ = pSmtpStats->CatPerfBlock.AmbiguousRecipients;
  459. *pdwCounter++ = pSmtpStats->CatPerfBlock.IllegalRecipients;
  460. *pdwCounter++ = pSmtpStats->CatPerfBlock.LoopRecipients;
  461. *pdwCounter++ = pSmtpStats->CatPerfBlock.GenericFailureRecipients;
  462. *pdwCounter++ = pSmtpStats->CatPerfBlock.RecipsInMemory;
  463. *pdwCounter++ = pSmtpStats->CatPerfBlock.UnresolvedSenders;
  464. *pdwCounter++ = pSmtpStats->CatPerfBlock.AmbiguousSenders;
  465. *pdwCounter++ = pSmtpStats->CatPerfBlock.AddressLookups;
  466. *pdwCounter++ = pSmtpStats->CatPerfBlock.AddressLookupCompletions;
  467. *pdwCounter++ = pSmtpStats->CatPerfBlock.AddressLookupsNotFound;
  468. *pdwCounter++ = pSmtpStats->CatPerfBlock.MailmsgDuplicateCollisions;
  469. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.Connections;
  470. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.ConnectFailures;
  471. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.OpenConnections;
  472. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.Binds;
  473. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.BindFailures;
  474. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.Searches;
  475. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearches;
  476. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.SearchFailures;
  477. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearchFailures;
  478. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.SearchesCompleted;
  479. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearchesCompleted;
  480. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.SearchCompletionFailures;
  481. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearchCompletionFailures;
  482. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.GeneralCompletionFailures;
  483. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.AbandonedSearches;
  484. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PendingSearches;
  485. *pdwCounter++ = 0; // padding
  486. _ASSERT((BYTE *)pdwCounter - (BYTE *)pCounterBlock ==
  487. SIZE_OF_SMTP_PERFORMANCE_DATA);
  488. pdwEndCounter = pdwCounter;
  489. //
  490. // Increment the Total Block.
  491. //
  492. pCounterBlock = (SMTP_COUNTER_BLOCK *)(pInstanceTotalDefinition + 1);
  493. pCounterBlock->PerfCounterBlock.ByteLength = SIZE_OF_SMTP_PERFORMANCE_DATA;
  494. //
  495. // Get the pointer to the first (unsigned __int64) counter. This
  496. // pointer *must* be quadword aligned.
  497. //
  498. pliCounter = (unsigned __int64 *)(pCounterBlock + 1);
  499. //
  500. // Increment the 'unsigned __int64's in the buffer.
  501. //
  502. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentTotal;
  503. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentTotal;
  504. *pliCounter++ = *pliCounter + pSmtpStats->BytesRcvdTotal;
  505. *pliCounter++ = *pliCounter + pSmtpStats->BytesRcvdTotal;
  506. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentTotal + pSmtpStats->BytesRcvdTotal;
  507. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentTotal + pSmtpStats->BytesRcvdTotal;
  508. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentMsg;
  509. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentMsg;
  510. *pliCounter++ = *pliCounter + pSmtpStats->BytesRcvdMsg;
  511. *pliCounter++ = *pliCounter + pSmtpStats->BytesRcvdMsg;
  512. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentMsg + pSmtpStats->BytesRcvdMsg;
  513. *pliCounter++ = *pliCounter + pSmtpStats->BytesSentMsg + pSmtpStats->BytesRcvdMsg;
  514. //
  515. // Increment the DWORDs in the buffer.
  516. //
  517. pdwCounter = (DWORD *)pliCounter;
  518. // Increment the Messages Received
  519. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgRecvd;
  520. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgRecvd;
  521. *pdwCounter++ = *pdwCounter + pSmtpStats->NumRcptsRecvd;
  522. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgRecvd * 100;
  523. *pdwCounter++ = *pdwCounter + pSmtpStats->NumRcptsRecvdLocal;
  524. *pdwCounter++ = *pdwCounter + pSmtpStats->NumRcptsRecvd;
  525. *pdwCounter++ = *pdwCounter + pSmtpStats->NumRcptsRecvdRemote;
  526. *pdwCounter++ = *pdwCounter + pSmtpStats->NumRcptsRecvd;
  527. *pdwCounter++ = *pdwCounter + pSmtpStats->MsgsRefusedDueToSize;
  528. *pdwCounter++ = *pdwCounter + pSmtpStats->MsgsRefusedDueToNoCAddrObjects;
  529. *pdwCounter++ = *pdwCounter + pSmtpStats->MsgsRefusedDueToNoMailObjects;
  530. // Increment the MTA Deliveries
  531. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsDelivered;
  532. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsDelivered;
  533. *pdwCounter++ = *pdwCounter + pSmtpStats->NumDeliveryRetries;
  534. *pdwCounter++ = *pdwCounter + pSmtpStats->NumDeliveryRetries;
  535. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsDelivered * 100;
  536. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsForwarded;
  537. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsForwarded;
  538. *pdwCounter++ = *pdwCounter + pSmtpStats->NumNDRGenerated;
  539. *pdwCounter++ = *pdwCounter + pSmtpStats->LocalQueueLength;
  540. *pdwCounter++ = *pdwCounter + pSmtpStats->RetryQueueLength;
  541. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMailFileHandles;
  542. *pdwCounter++ = *pdwCounter + pSmtpStats->NumQueueFileHandles;
  543. *pdwCounter++ = *pdwCounter + pSmtpStats->CatQueueLength;
  544. // Increment the Messages Sent
  545. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsSent;
  546. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsSent;
  547. *pdwCounter++ = *pdwCounter + pSmtpStats->NumSendRetries;
  548. *pdwCounter++ = *pdwCounter + pSmtpStats->NumSendRetries;
  549. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsSent * 100;
  550. *pdwCounter++ = *pdwCounter + pSmtpStats->NumRcptsSent;
  551. *pdwCounter++ = *pdwCounter + pSmtpStats->NumMsgsSent * 100;
  552. *pdwCounter++ = *pdwCounter + pSmtpStats->RemoteQueueLength;
  553. // Increment the DNS lookups
  554. *pdwCounter++ = *pdwCounter + pSmtpStats->NumDnsQueries;
  555. *pdwCounter++ = *pdwCounter + pSmtpStats->NumDnsQueries;
  556. *pdwCounter++ = *pdwCounter + pSmtpStats->RemoteRetryQueueLength;
  557. // Increment the Connections
  558. *pdwCounter++ = *pdwCounter + pSmtpStats->NumConnInOpen;
  559. *pdwCounter++ = *pdwCounter + pSmtpStats->NumConnInOpen - pSmtpStats->NumConnInClose;
  560. *pdwCounter++ = *pdwCounter + pSmtpStats->NumConnOutOpen;
  561. *pdwCounter++ = *pdwCounter + pSmtpStats->NumConnOutOpen - pSmtpStats->NumConnOutClose;
  562. *pdwCounter++ = *pdwCounter + pSmtpStats->NumConnOutRefused;
  563. *pdwCounter++ = *pdwCounter + pSmtpStats->NumProtocolErrs;
  564. *pdwCounter++ = *pdwCounter + pSmtpStats->NumProtocolErrs;
  565. *pdwCounter++ = *pdwCounter +pSmtpStats->DirectoryDrops;
  566. *pdwCounter++ = *pdwCounter +pSmtpStats->DirectoryDrops;
  567. *pdwCounter++ = *pdwCounter +pSmtpStats->RoutingTableLookups;
  568. *pdwCounter++ = *pdwCounter +pSmtpStats->RoutingTableLookups;
  569. *pdwCounter++ = *pdwCounter +pSmtpStats->ETRNMessages;
  570. *pdwCounter++ = *pdwCounter +pSmtpStats->ETRNMessages;
  571. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsBadmailNoRecipients;
  572. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsBadmailHopCountExceeded;
  573. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsBadmailFailureGeneral;
  574. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsBadmailBadPickupFile;
  575. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsBadmailEvent;
  576. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsBadmailNdrOfDsn;
  577. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsPendingRouting;
  578. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsPendingUnreachableLink;
  579. *pdwCounter++ = *pdwCounter +pSmtpStats->SubmittedMessages;
  580. *pdwCounter++ = *pdwCounter +pSmtpStats->DSNFailures;
  581. *pdwCounter++ = *pdwCounter +pSmtpStats->MsgsInLocalDelivery;
  582. // Cat counters
  583. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.CatSubmissions;
  584. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.CatCompletions;
  585. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.CurrentCategorizations;
  586. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.SucceededCategorizations;
  587. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.HardFailureCategorizations;
  588. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.RetryFailureCategorizations;
  589. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.RetryOutOfMemory;
  590. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.RetryDSLogon;
  591. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.RetryDSConnection;
  592. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.RetryGeneric;
  593. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.MessagesSubmittedToQueueing;
  594. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.MessagesCreated;
  595. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.MessagesAborted;
  596. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.PreCatRecipients;
  597. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.PostCatRecipients;
  598. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.NDRdRecipients;
  599. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.UnresolvedRecipients;
  600. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.AmbiguousRecipients;
  601. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.IllegalRecipients;
  602. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.LoopRecipients;
  603. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.GenericFailureRecipients;
  604. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.RecipsInMemory;
  605. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.UnresolvedSenders;
  606. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.AmbiguousSenders;
  607. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.AddressLookups;
  608. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.AddressLookupCompletions;
  609. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.AddressLookupsNotFound;
  610. *pdwCounter++ = *pdwCounter +pSmtpStats->CatPerfBlock.MailmsgDuplicateCollisions;
  611. //
  612. // LDAP counters are already global
  613. //
  614. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.Connections;
  615. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.ConnectFailures;
  616. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.OpenConnections;
  617. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.Binds;
  618. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.BindFailures;
  619. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.Searches;
  620. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearches;
  621. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.SearchFailures;
  622. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearchFailures;
  623. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.SearchesCompleted;
  624. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearchesCompleted;
  625. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.SearchCompletionFailures;
  626. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PagedSearchCompletionFailures;
  627. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.GeneralCompletionFailures;
  628. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.AbandonedSearches;
  629. *pdwCounter++ = pSmtpStats->CatPerfBlock.LDAPPerfBlock.PendingSearches;
  630. *pdwCounter++ = 0; // padding
  631. _ASSERT((BYTE *)pdwCounter - (BYTE *)pCounterBlock ==
  632. SIZE_OF_SMTP_PERFORMANCE_DATA);
  633. //
  634. // Increment in the returned statistics block
  635. //
  636. pSmtpStatsBlock++;
  637. }
  638. //
  639. // Free the API buffer.
  640. //
  641. //MIDL_user_free((LPBYTE)pSmtpStats);
  642. NetApiBufferFree((LPBYTE)pSmtpStatsBlockArray);
  643. dwInstanceCount++; // for the _Totals instance.
  644. pSmtpDataDefinition->SmtpObjectType.TotalByteLength = sizeof(SMTP_DATA_DEFINITION) +
  645. dwInstanceCount * (sizeof(SMTP_INSTANCE_DEFINITION) + SIZE_OF_SMTP_PERFORMANCE_DATA);
  646. pSmtpDataDefinition->SmtpObjectType.NumInstances = dwInstanceCount;
  647. //
  648. // Update arguments for return.
  649. //
  650. *lppData = (PVOID) pdwEndCounter;
  651. *lpNumObjectTypes = 1;
  652. *lpcbTotalBytes = (DWORD)((BYTE *)pdwEndCounter - (BYTE *)pSmtpDataDefinition);
  653. DebugTrace(0, "pData = %08lX", *lppData);
  654. DebugTrace(0, "NumObjectTypes = %08lX", *lpNumObjectTypes);
  655. DebugTrace(0, "cbTotalBytes = %08lX", *lpcbTotalBytes);
  656. DebugTrace(0, "sizeof *pSmtpStat = %08lX", sizeof *pSmtpStats);
  657. //
  658. // Success! Honest!!
  659. //
  660. TraceFunctLeave();
  661. return NO_ERROR;
  662. } // CollectSmtpPerformanceData
  663. /*******************************************************************
  664. NAME: CloseSmtpPerformanceData
  665. SYNOPSIS: Terminates the performance counters.
  666. RETURNS: DWORD - Win32 status code.
  667. HISTORY:
  668. KeithMo 07-Jun-1993 Created.
  669. ********************************************************************/
  670. DWORD APIENTRY
  671. CloseSmtpPerformanceData(VOID)
  672. {
  673. TraceFunctEnter("CloseSmtpPerformanceData");
  674. //
  675. // No real cleanup to do here.
  676. //
  677. cOpens--;
  678. TraceFunctLeave();
  679. //
  680. // shuts down and flushes all trace statements
  681. //
  682. #ifndef NOTRACE
  683. TermAsyncTrace();
  684. #endif
  685. return NO_ERROR;
  686. }