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.

691 lines
25 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. //
  4. // File: linkmsgq.h
  5. //
  6. // Description:
  7. // This provides a description of one of the external interfaces provided
  8. // by the CMT. CLinkMsgQueue provides Route factoring with an interface
  9. // to get the next message for a given link.
  10. //
  11. // Owner: mikeswa
  12. //
  13. // Copyright (C) 1997 Microsoft Corporation
  14. //
  15. //-----------------------------------------------------------------------------
  16. #ifndef _LINKMSGQ_H_
  17. #define _LINKMSGQ_H_
  18. #include "cmt.h"
  19. #include <rwnew.h>
  20. #include <baseobj.h>
  21. #include <aqueue.h>
  22. #include "domain.h"
  23. #include "aqroute.h"
  24. #include "smproute.h"
  25. #include <listmacr.h>
  26. #include "qwiklist.h"
  27. #include "dcontext.h"
  28. #include "aqstats.h"
  29. #include "aqnotify.h"
  30. #include "aqadmsvr.h"
  31. class CAQSvrInst;
  32. class CDestMsgQueue;
  33. class CConnMgr;
  34. class CSMTPConn;
  35. class CInternalDomainInfo;
  36. #define LINK_MSGQ_SIG ' QML'
  37. //Define private link state flags
  38. //NOTE - Be sure to add new private flags to AssertPrivateLinkStateFlags as well
  39. #define LINK_STATE_PRIV_CONFIG_TURN_ETRN 0x80000000
  40. #define LINK_STATE_PRIV_ETRN_ENABLED 0x40000000
  41. #define LINK_STATE_PRIV_TURN_ENABLED 0x20000000
  42. #define LINK_STATE_PRIV_NO_NOTIFY 0x10000000
  43. #define LINK_STATE_PRIV_NO_CONNECTION 0x08000000
  44. #define LINK_STATE_PRIV_GENERATING_DSNS 0x04000000
  45. #define LINK_STATE_PRIV_IGNORE_DELETE_IF_EMPTY 0x02000000
  46. #define LINK_STATE_PRIV_HAVE_SENT_NOTIFICATION 0x01000000
  47. #define LINK_STATE_PRIV_HAVE_SENT_NO_LONGER_USED 0x00400000
  48. #define EMPTY_LMQ_EXPIRE_TIME_MINUTES 2
  49. //---[ enum LinkFlags ]--------------------------------------------------------
  50. //
  51. //
  52. // Hungarian: lf, pfl
  53. //
  54. // Private link data flags
  55. //-----------------------------------------------------------------------------
  56. typedef enum _LinkFlags
  57. {
  58. eLinkFlagsClear = 0x00000000,
  59. eLinkFlagsSentNewNotification = 0x00000001,
  60. eLinkFlagsRouteChangePending = 0x00000002,
  61. eLinkFlagsFileTimeSpinLock = 0x00000004,
  62. eLinkFlagsDiagnosticSpinLock = 0x00000008,
  63. eLinkFlagsConnectionVerifed = 0x00000010,
  64. eLinkFlagsGetInfoFailed = 0x00000020,
  65. eLinkFlagsAQSpecialLinkInfo = 0x00000040,
  66. eLinkFlagsInternalSMTPLinkInfo = 0x00000080,
  67. eLinkFlagsExternalSMTPLinkInfo = 0x00000100,
  68. eLinkFlagsMarkedAsEmpty = 0x00000200,
  69. eLinkFlagsInvalid = 0x80000000, //link has been tagged as invalid
  70. } LinkFlags, *PLinkFlags;
  71. //inline function to verify that private flags are only using reserved bits
  72. inline void AssertPrivateLinkStateFlags()
  73. {
  74. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_CONFIG_TURN_ETRN));
  75. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_ETRN_ENABLED));
  76. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_TURN_ENABLED));
  77. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_NO_NOTIFY));
  78. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_NO_CONNECTION));
  79. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_GENERATING_DSNS));
  80. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_IGNORE_DELETE_IF_EMPTY));
  81. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_HAVE_SENT_NOTIFICATION));
  82. _ASSERT(!(~LINK_STATE_RESERVED & LINK_STATE_PRIV_HAVE_SENT_NO_LONGER_USED));
  83. }
  84. // {34E2DCCB-C91A-11d2-A6B1-00C04FA3490A}
  85. static const GUID g_sDefaultLinkGuid =
  86. { 0x34e2dccb, 0xc91a, 0x11d2, { 0xa6, 0xb1, 0x0, 0xc0, 0x4f, 0xa3, 0x49, 0xa } };
  87. // Global count of failures : "failed to add queue to link because link was
  88. // marked as no longer in use"
  89. _declspec(selectany) DWORD g_cFailedToAddQueueToRemovedLink = 0;
  90. //---[ CLinkMsgQueue ]---------------------------------------------------------
  91. //
  92. //
  93. // Hungarian: linkq, plinkq
  94. //
  95. //
  96. //-----------------------------------------------------------------------------
  97. class CLinkMsgQueue :
  98. public IQueueAdminAction,
  99. public IQueueAdminLink,
  100. public CBaseObject,
  101. public IAQNotify,
  102. public CQueueAdminRetryNotify
  103. {
  104. protected:
  105. DWORD m_dwSignature;
  106. DWORD m_dwLinkFlags; //private data
  107. DWORD m_dwLinkStateFlags; //Link state flags (private + eLinkStateFlagsf)
  108. CAQSvrInst *m_paqinst; //ptr to the virtual server intance object
  109. DWORD m_cQueues; //Number of queues on Link
  110. CQuickList m_qlstQueues;
  111. CDomainEntry *m_pdentryLink; //Domain Entry for link
  112. DWORD m_cConnections; //Number of current connections
  113. DWORD m_dwRoundRobinIndex; //Used to round-robin through queues
  114. CShareLockInst m_slConnections; //lock to access connections
  115. CShareLockInst m_slInfo; //share lock for link info
  116. CShareLockInst m_slQueues; //lock to access queues
  117. DWORD m_cbSMTPDomain; //byte count of next hop domain name
  118. LPSTR m_szSMTPDomain; //ptr to string of next hop
  119. CInternalDomainInfo *m_pIntDomainInfo; //internal config info for domain
  120. LONG m_lConnMgrCount; //Count used by connection manager
  121. //
  122. // We have 2 failure counts to keep track of the 2 types of failures.
  123. // m_lConsecutiveConnectionFailureCount keeps track of the number consecutive
  124. // failures to make a connection to a remote machine.
  125. // m_lConsecutiveMessageFailureCount tracks the number of failures to actually
  126. // send a message. They will be different if we can connect to a remote
  127. // server but cannot (or have not) sent mail. m_lConsecutiveConnectionFailureCount
  128. // is reported to routing, so that mail will be routed to this link, while
  129. // m_lConsecutiveMessageFailureCount is used to determine the retry interval.
  130. // By doing this, we can avoid resetting our retry times if we successfully
  131. // connect, but cannot actually send a message.
  132. //
  133. LONG m_lConsecutiveConnectionFailureCount;
  134. LONG m_lConsecutiveMessageFailureCount;
  135. LPSTR m_szConnectorName;
  136. IMessageRouterLinkStateNotification *m_pILinkStateNotify;
  137. //Filetimes reported to queue admin
  138. FILETIME m_ftNextRetry;
  139. FILETIME m_ftNextScheduledCallback;
  140. //
  141. // Used by RemoveLinkIfEmpty to make sure that we cache links for
  142. // a period of time after them become empty. This is only
  143. // valid when the eLinkFlagsMarkedAsEmpty bit is set.
  144. //
  145. FILETIME m_ftEmptyExpireTime;
  146. //Message statistics
  147. CAQStats m_aqstats;
  148. CAQScheduleID m_aqsched; //ScheduleID returned by routing
  149. LIST_ENTRY m_liLinks; //linked list of links for this domain
  150. LIST_ENTRY m_liConnections; //linked list of connections for this domain
  151. //Diagnostic information returned by SMTPSVC
  152. HRESULT m_hrDiagnosticError;
  153. CHAR m_szDiagnosticVerb[20]; //failed protocol VERB
  154. CHAR m_szDiagnosticResponse[100]; //response from remote server
  155. //See comments near SetLinkType()/GetLinkType() and
  156. //SetSupportedActions()/fActionIsSupported() functions.
  157. DWORD m_dwSupportedActions;
  158. DWORD m_dwLinkType;
  159. //Gets & verifies internal domain info
  160. HRESULT HrGetInternalInfo(OUT CInternalDomainInfo **ppIntDomainInfo);
  161. static inline BOOL fFlagsAllowConnection(DWORD dwFlags);
  162. HRESULT m_hrLastConnectionFailure;
  163. void InternalUpdateFileTime(FILETIME *pftDest, FILETIME *pftSrc);
  164. void InternalInit();
  165. HRESULT CLinkMsgQueue::HrInternalPrepareDelivery(
  166. IN CMsgRef *pmsgref,
  167. IN BOOL fQueuesLocked,
  168. IN BOOL fLocal,
  169. IN BOOL fDelayDSN,
  170. IN OUT CDeliveryContext *pdcntxt,
  171. OUT DWORD *pcRecips,
  172. OUT DWORD **prgdwRecips);
  173. //Static callback used to restart DSN generation
  174. static BOOL fRestartDSNGenerationIfNecessary(PVOID pvContext,
  175. DWORD dwStatus);
  176. public:
  177. CLinkMsgQueue(GUID guid = g_sDefaultLinkGuid) : m_aqsched(guid, 0)
  178. {InternalInit();};
  179. CLinkMsgQueue(DWORD dwScheduleID,
  180. IMessageRouter *pIMessageRouter,
  181. IMessageRouterLinkStateNotification *pILinkStateNotify);
  182. ~CLinkMsgQueue();
  183. void SetLinkType(DWORD dwLinkType) { m_dwLinkType = dwLinkType; }
  184. DWORD GetLinkType() { return m_dwLinkType; }
  185. //For some links, certain actions are not supported:
  186. //but they use the same class (CLinkMsgQueue) as others for which
  187. //the actions are supported. For example CurrentlyUnreachable does
  188. //not support freeze/thaw. So we need to maintain for the currently
  189. //unreachable object, a list of actions that are supported, so it
  190. //does not set the flags corresponding to an unsupported action
  191. //when that action is commanded.
  192. void SetSupportedActions(DWORD dwSupported) { m_dwSupportedActions = dwSupported; }
  193. DWORD fActionIsSupported(LINK_ACTION la) { return (m_dwSupportedActions & la); }
  194. BOOL fCanSchedule() //Can this link be scheduled
  195. {
  196. HrGetInternalInfo(NULL); //make sure link state flags are up to date
  197. DWORD dwFlags = m_dwLinkStateFlags;
  198. return fFlagsAllowConnection(dwFlags);
  199. }
  200. BOOL fCanSendCmd() //Is this link scheduled to send command on next connection
  201. {
  202. //Logic :
  203. // Every time we see this flag set, the connection that is created also will
  204. // be used to send a command
  205. //
  206. DWORD dwFlags = m_dwLinkStateFlags;
  207. return (dwFlags & LINK_STATE_CMD_ENABLED);
  208. }
  209. BOOL fShouldConnect(IN DWORD cMaxLinkConnections,
  210. IN DWORD cMinMessagesPerConnection);
  211. //returns S_OK if connection is needed, S_FALSE if not.
  212. HRESULT HrCreateConnectionIfNeeded(IN DWORD cMaxLinkConnections,
  213. IN DWORD cMinMessagesPerConnection,
  214. IN DWORD cMaxMessagesPerConnection,
  215. IN CConnMgr *pConnMgr,
  216. OUT CSMTPConn **ppSMTPConn);
  217. LONG IncrementConnMgrCount() {return InterlockedIncrement(&m_lConnMgrCount);}
  218. LONG DecrementConnMgrCount() {return InterlockedDecrement(&m_lConnMgrCount);}
  219. //
  220. // Connection failure API. This is used by the connection manager. We
  221. // will always return the message failure count, since this is what we
  222. // want to pass to the retry sink. However, we will not allow the
  223. // connection manager to reset this count since only we should during
  224. // ack message.
  225. //
  226. LONG IncrementFailureCounts()
  227. {
  228. InterlockedIncrement(&m_lConsecutiveConnectionFailureCount);
  229. return InterlockedIncrement(&m_lConsecutiveMessageFailureCount);
  230. }
  231. LONG cGetMessageFailureCount() {return m_lConsecutiveMessageFailureCount;}
  232. void ResetConnectionFailureCount(){InterlockedExchange(&m_lConsecutiveConnectionFailureCount, 0);}
  233. DWORD cGetConnections() {return m_cConnections;};
  234. HRESULT HrInitialize(IN CAQSvrInst *paqinst,
  235. IN CDomainEntry *pdentryLink,
  236. IN DWORD cbSMTPDomain,
  237. IN LPSTR szSMTPDomain,
  238. IN LinkFlags lf,
  239. IN LPSTR szConnectorName);
  240. HRESULT HrDeinitialize();
  241. void AddConnection(IN CSMTPConn *pSMTPConn); //Add Connection to link
  242. void RemoveConnection(IN CSMTPConn *pSMTPConn,
  243. IN BOOL fForceDSNGeneration);
  244. HRESULT HrGetDomainInfo(OUT DWORD *pcbSMTPDomain,
  245. OUT LPSTR *pszSMTPDomain,
  246. OUT CInternalDomainInfo **ppIntDomainInfo);
  247. HRESULT HrGetSMTPDomain(OUT DWORD *pcbSMTPDomain,
  248. OUT LPSTR *pszSMTPDomain);
  249. //Queue manipulation routines
  250. HRESULT HrAddQueue(IN CDestMsgQueue *pdmqNew);
  251. void RemoveQueue(IN CDestMsgQueue *pdmq, IN CAQStats *paqstats);
  252. HRESULT HrGetQueueListSnapshot(CQuickList **ppql);
  253. void RemoveLinkIfEmpty();
  254. //Called by DMT to signal complete routing change
  255. void RemoveAllQueues();
  256. // Called by DMT when this link is orphaned
  257. void RemovedFromDMT();
  258. // This function dequeues the next available message.The message
  259. // retrieved will be the top one approximatly ordered by quality/class
  260. // and arrival time.
  261. HRESULT HrGetNextMsg(
  262. IN OUT CDeliveryContext *pdcntxt, //delivery context for connection
  263. OUT IMailMsgProperties **ppIMailMsgProperties, //IMsg dequeued
  264. OUT DWORD *pcIndexes, //size of array
  265. OUT DWORD **prgdwRecipIndex); //Array of recipient indexes
  266. //Acknowledge the message ref.
  267. //There should be one Ack for every dequeue from a link.
  268. HRESULT HrAckMsg(IN MessageAck *pMsgAck);
  269. //Gets the next message ref without getting delivery context or
  270. //preparing for delivery
  271. HRESULT HrGetNextMsgRef(IN BOOL fRoutingLockHeld, OUT CMsgRef **ppmsgref);
  272. //Calls CMsgRef prepare delivery for all the messages
  273. HRESULT HrPrepareDelivery(
  274. IN CMsgRef *pmsgref,
  275. IN BOOL fLocal,
  276. IN BOOL fDelayDSN,
  277. IN OUT CDeliveryContext *pdcntxt,
  278. OUT DWORD *pcRecips,
  279. OUT DWORD **prgdwRecips)
  280. {
  281. return HrInternalPrepareDelivery(pmsgref, FALSE, fLocal, fDelayDSN,
  282. pdcntxt, pcRecips, prgdwRecips);
  283. }
  284. //Recieve notifications from contained queues
  285. HRESULT HrNotify(IN CAQStats *paqstats, BOOL fAdd);
  286. HRESULT HrNotifyRetryStatChange(BOOL fAdd);
  287. // Gather statistical information for link mangment
  288. DWORD cGetTotalMsgCount() {return m_aqstats.m_cMsgs;};
  289. DWORD cGetRetryMsgCount() {return m_aqstats.m_cRetryMsgs;};
  290. //functions used to manipulate lists of queues
  291. inline CAQScheduleID *paqschedGetScheduleID();
  292. inline BOOL fIsSameScheduleID(CAQScheduleID *paqsched);
  293. static inline CLinkMsgQueue *plmqIsSameScheduleID(
  294. CAQScheduleID *paqsched,
  295. PLIST_ENTRY pli);
  296. static inline CLinkMsgQueue *plmqGetLinkMsgQueue(PLIST_ENTRY pli);
  297. inline PLIST_ENTRY pliGetNextListEntry();
  298. inline void InsertLinkInList(PLIST_ENTRY pliHead);
  299. inline BOOL fRemoveLinkFromList();
  300. DWORD dwModifyLinkState(IN DWORD dwLinkStateToSet,
  301. IN DWORD dwLinkStateToUnset);
  302. //Used to send notification to routing/scheduling sink
  303. void SendLinkStateNotification();
  304. void SendLinkStateNotificationIfNew() {
  305. if (m_pILinkStateNotify &&
  306. !(m_dwLinkStateFlags & LINK_STATE_PRIV_HAVE_SENT_NOTIFICATION))
  307. SendLinkStateNotification();
  308. }
  309. DWORD dwGetLinkState() {return m_dwLinkStateFlags;};
  310. void SetLastConnectionFailure(HRESULT hrLastConnectionFailure)
  311. {m_hrLastConnectionFailure = hrLastConnectionFailure;};
  312. inline BOOL fRPCCopyName(OUT LPWSTR *pwszLinkName);
  313. DWORD cGetNumQueues() {return m_cQueues;};
  314. virtual void SetNextRetry(FILETIME *pft)
  315. {
  316. _ASSERT(pft);
  317. InternalUpdateFileTime(&m_ftNextRetry, pft);
  318. };
  319. void SetNextScheduledConnection(FILETIME *pft)
  320. {
  321. _ASSERT(pft);
  322. InternalUpdateFileTime(&m_ftNextScheduledCallback, pft);
  323. };
  324. static void ScheduledCallback(PVOID pvContext);
  325. void GenerateDSNsIfNecessary(BOOL fCheckIfEmpty, BOOL fMergeOnly);
  326. void SetDiagnosticInfo(
  327. IN HRESULT hrDiagnosticError,
  328. IN LPCSTR szDiagnosticVerb,
  329. IN LPCSTR szDiagnosticResponse);
  330. void GetDiagnosticInfo(
  331. IN LPSTR szDiagnosticVerb,
  332. IN DWORD cDiagnosticVerb,
  333. IN LPSTR szDiagnosticResponse,
  334. IN DWORD cbDiagnosticResponse,
  335. OUT HRESULT *phrDiagnosticError);
  336. virtual BOOL fIsRemote() {return TRUE;};
  337. //
  338. // Returns the connector name. Used by CSMTPConn. Valid as long
  339. // as the link is valid.
  340. //
  341. LPSTR szGetConnectorName() {return m_szConnectorName;};
  342. public: //IUnknown
  343. STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj);
  344. STDMETHOD_(ULONG, AddRef)(void) { return CBaseObject::AddRef(); };
  345. STDMETHOD_(ULONG, Release)(void) { return CBaseObject::Release(); };
  346. public: //IQueueAdminAction
  347. STDMETHOD(HrApplyQueueAdminFunction)(
  348. IQueueAdminMessageFilter *pIQueueAdminMessageFilter);
  349. STDMETHOD(HrApplyActionToMessage)(
  350. IUnknown *pIUnknownMsg,
  351. MESSAGE_ACTION ma,
  352. PVOID pvContext,
  353. BOOL *pfShouldDelete);
  354. STDMETHOD_(BOOL, fMatchesID)
  355. (QUEUELINK_ID *QueueLinkID);
  356. STDMETHOD(QuerySupportedActions)(DWORD *pdwSupportedActions,
  357. DWORD *pdwSupportedFilterFlags)
  358. {
  359. return QueryDefaultSupportedActions(pdwSupportedActions,
  360. pdwSupportedFilterFlags);
  361. };
  362. public: //IQueueAdminLink
  363. STDMETHOD(HrGetLinkInfo)(
  364. LINK_INFO *pliLinkInfo,
  365. HRESULT *phrLinkDiagnostic);
  366. STDMETHOD(HrApplyActionToLink)(
  367. LINK_ACTION la);
  368. STDMETHOD(HrGetLinkID)(
  369. QUEUELINK_ID *pLinkID);
  370. STDMETHOD(HrGetNumQueues)(
  371. DWORD *pcQueues);
  372. STDMETHOD(HrGetQueueIDs)(
  373. DWORD *pcQueues,
  374. QUEUELINK_ID *rgQueues);
  375. };
  376. //---[ CLinkMsgQueue::paqschedGetScheduleID ]----------------------------------
  377. //
  378. //
  379. // Description:
  380. // Returns the schedule ID for this link
  381. // Parameters:
  382. // -
  383. // Returns:
  384. // ScheduleID for this link
  385. // History:
  386. // 6/9/98 - MikeSwa Created
  387. //
  388. //-----------------------------------------------------------------------------
  389. CAQScheduleID *CLinkMsgQueue::paqschedGetScheduleID()
  390. {
  391. return (&m_aqsched);
  392. }
  393. //---[ CLinkMsgQueue::fIsSameScheduleID ]--------------------------------------
  394. //
  395. //
  396. // Description:
  397. // Checks if a given schedule ID is the same as ours
  398. // Parameters:
  399. // paqsched - ScheduleID to check against
  400. // Returns:
  401. // TRUE if same schedule ID
  402. // History:
  403. // 6/9/98 - MikeSwa Created
  404. //
  405. //-----------------------------------------------------------------------------
  406. BOOL CLinkMsgQueue::fIsSameScheduleID(CAQScheduleID *paqsched)
  407. {
  408. return (m_aqsched.fIsEqual(paqsched));
  409. }
  410. //---[ CLinkMsgQueue::plmqIsSameScheduleID ]-----------------------------------
  411. //
  412. //
  413. // Description:
  414. // Gets the link if it matches the given schedule ID
  415. // Parameters:
  416. // paqsched - ScheduleID to check
  417. // pli - list entry to get link for
  418. // Returns:
  419. // pointer to link if scheduleID matches..
  420. // NULL otherwise
  421. // History:
  422. // 6/9/98 - MikeSwa Created
  423. //
  424. //-----------------------------------------------------------------------------
  425. CLinkMsgQueue *CLinkMsgQueue::plmqIsSameScheduleID(
  426. CAQScheduleID *paqsched,
  427. PLIST_ENTRY pli)
  428. {
  429. CLinkMsgQueue *plmq = CONTAINING_RECORD(pli, CLinkMsgQueue, m_liLinks);
  430. _ASSERT(LINK_MSGQ_SIG == plmq->m_dwSignature);
  431. if (!plmq->fIsSameScheduleID(paqsched))
  432. plmq = NULL;
  433. return plmq;
  434. }
  435. //---[ CLinkMsgQueue::plmqGetLinkMsgQueue ]------------------------------------
  436. //
  437. //
  438. // Description:
  439. // Returns the LinkMsgQueue associated with the given list entry
  440. // Parameters:
  441. // pli - List entry to get Link for
  442. // Returns:
  443. // pointer to link for list entry
  444. // History:
  445. // 6/8/98 - MikeSwa Created
  446. //
  447. //-----------------------------------------------------------------------------
  448. CLinkMsgQueue *CLinkMsgQueue::plmqGetLinkMsgQueue(PLIST_ENTRY pli)
  449. {
  450. _ASSERT(LINK_MSGQ_SIG == (CONTAINING_RECORD(pli, CLinkMsgQueue, m_liLinks))->m_dwSignature);
  451. return (CONTAINING_RECORD(pli, CLinkMsgQueue, m_liLinks));
  452. }
  453. //---[ CLinkMsgQueue::InsertLinkInList ]---------------------------------------
  454. //
  455. //
  456. // Description:
  457. // Inserts link in given linked list
  458. // Parameters:
  459. // pliHead - Head of list to insert in
  460. // Returns:
  461. // -
  462. // History:
  463. // 6/9/98 - MikeSwa Created
  464. //
  465. //-----------------------------------------------------------------------------
  466. void CLinkMsgQueue::InsertLinkInList(PLIST_ENTRY pliHead)
  467. {
  468. _ASSERT(NULL == m_liLinks.Flink);
  469. _ASSERT(NULL == m_liLinks.Blink);
  470. InsertHeadList(pliHead, &m_liLinks);
  471. };
  472. //---[ CLinkMsgQueue::fRemoveLinkFromList ]-------------------------------------
  473. //
  474. //
  475. // Description:
  476. // Remove link from link list
  477. // Parameters:
  478. // -
  479. // Returns:
  480. // -
  481. // History:
  482. // 6/9/98 - MikeSwa Created
  483. // 6/11/99 - MikeSwa Modified to allow multiple calls
  484. //
  485. //-----------------------------------------------------------------------------
  486. BOOL CLinkMsgQueue::fRemoveLinkFromList()
  487. {
  488. if (m_liLinks.Flink && m_liLinks.Blink)
  489. {
  490. RemoveEntryList(&m_liLinks);
  491. m_liLinks.Flink = NULL;
  492. m_liLinks.Blink = NULL;
  493. return TRUE;
  494. } else {
  495. return FALSE;
  496. }
  497. };
  498. //---[ CLinkMsgQueue::pliGetNextListEntry ]----------------------------------
  499. //
  500. //
  501. // Description:
  502. // Gets the pointer to the next list entry for this queue.
  503. // Parameters:
  504. // -
  505. // Returns:
  506. // The Flink of the queues LIST_ENTRY
  507. // History:
  508. // 6/16/98 - Created
  509. //
  510. //---------------------------------------------------------------------------
  511. PLIST_ENTRY CLinkMsgQueue::pliGetNextListEntry()
  512. {
  513. return m_liLinks.Flink;
  514. };
  515. //---[ CLinkMsgQueue::fFlagsAllowConnection ]---------------------------------
  516. //
  517. //
  518. // Description:
  519. // Static helper function that examines if a given set of flags will
  520. // allow a connection. Used by fCanSchedule and the linkstate debugger
  521. // extension.
  522. // Parameters:
  523. // IN dwFlags Flags to check
  524. // Returns:
  525. // TRUE if a connection can be made, FALSE otherwise
  526. // History:
  527. // 9/30/98 - MikeSwa Created (separated out from fCanSchedule)
  528. //
  529. //-----------------------------------------------------------------------------
  530. BOOL CLinkMsgQueue::fFlagsAllowConnection(DWORD dwFlags)
  531. {
  532. //Logic :
  533. // We make a connection for a link, if the admin has not specified an override and
  534. // one of the following conditions is met
  535. // -the force a connection NOW flag has been set
  536. // -the command enable flag has been set
  537. // -the ETRN or TURN enable flag has been set
  538. // -the retry enable as well as the schedule enable flag has been set
  539. // (and domain is not TURN only).
  540. //
  541. BOOL fRet = FALSE;
  542. if (dwFlags & LINK_STATE_ADMIN_HALT)
  543. fRet = FALSE;
  544. else if (dwFlags & LINK_STATE_PRIV_NO_CONNECTION)
  545. fRet = FALSE;
  546. else if (dwFlags & LINK_STATE_PRIV_GENERATING_DSNS)
  547. fRet = FALSE;
  548. else if (dwFlags & LINK_STATE_ADMIN_FORCE_CONN)
  549. fRet = TRUE;
  550. else if (dwFlags & LINK_STATE_PRIV_CONFIG_TURN_ETRN)
  551. {
  552. //Obey retry flag... even for ETRN domains
  553. if ((dwFlags & LINK_STATE_PRIV_ETRN_ENABLED) &&
  554. (dwFlags & LINK_STATE_RETRY_ENABLED))
  555. fRet = TRUE;
  556. else
  557. fRet = FALSE;
  558. }
  559. else if ((dwFlags & LINK_STATE_RETRY_ENABLED) &&
  560. (dwFlags & LINK_STATE_SCHED_ENABLED))
  561. fRet = TRUE;
  562. return fRet;
  563. }
  564. //---[ CLinkMsgQueue::fRPCCopyName ]--------------------------------------------
  565. //
  566. //
  567. // Description:
  568. // Used by Queue admin functions to copy the name of this link
  569. // Parameters:
  570. // IN pszLinkName UNICODE copy of name
  571. // Returns:
  572. // TRUE on success
  573. // FALSE on failure
  574. // History:
  575. // 12/5/98 - MikeSwa Created
  576. // 6/7/99 - MikeSwa Changed to UNICODE
  577. //
  578. //-----------------------------------------------------------------------------
  579. BOOL CLinkMsgQueue::fRPCCopyName(OUT LPWSTR *pwszLinkName)
  580. {
  581. _ASSERT(pwszLinkName);
  582. if (!m_cbSMTPDomain || !m_szSMTPDomain)
  583. return FALSE;
  584. *pwszLinkName = wszQueueAdminConvertToUnicode(m_szSMTPDomain,
  585. m_cbSMTPDomain);
  586. if (!pwszLinkName)
  587. return FALSE;
  588. return TRUE;
  589. }
  590. #endif // _LINKMSGQ_H_