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.

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