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.

595 lines
15 KiB

  1. // SMTPServer.cpp : Implementation of CSMTPServer
  2. #define INCL_INETSRV_INCS
  3. #include "smtpinc.h"
  4. #include "stdafx.h"
  5. #include "dbgtrace.h"
  6. #include "filehc.h"
  7. #include "mailmsg.h"
  8. #include "mailmsgi.h"
  9. #include "smtpsvr.h"
  10. //DECLARE_DEBUG_PRINTS_OBJECT();
  11. #define MAILMSG_PROGID L"Exchange.MailMsg"
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CSMTPServer
  14. STDMETHODIMP CSMTPServer::InterfaceSupportsErrorInfo(REFIID riid)
  15. {
  16. static const IID* arr[] =
  17. {
  18. &IID_ISMTPServer,
  19. };
  20. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  21. {
  22. if (InlineIsEqualGUID(*arr[i],riid))
  23. return S_OK;
  24. }
  25. return S_FALSE;
  26. }
  27. BOOL InitExchangeSmtpServer(PVOID Ptr, PVOID Ptr2)
  28. {
  29. CSMTPServer * ThisPtr = (CSMTPServer *) Ptr;
  30. ThisPtr->Init((SMTP_SERVER_INSTANCE *) Ptr2);
  31. return TRUE;
  32. }
  33. //
  34. // Add all your initialization needs here ...
  35. //
  36. HRESULT CSMTPServer::Init(SMTP_SERVER_INSTANCE * pInstance)
  37. {
  38. _ASSERT (pInstance != NULL);
  39. m_pInstance = pInstance;
  40. return(S_OK);
  41. }
  42. STDMETHODIMP CSMTPServer::QueryInterface(
  43. REFIID iid,
  44. void **ppvObject
  45. )
  46. {
  47. if (iid == IID_IUnknown)
  48. {
  49. // Return our identity
  50. *ppvObject = (IUnknown *)(ISMTPServerInternal *)this;
  51. AddRef();
  52. }
  53. else if(iid == IID_ISMTPServer)
  54. {
  55. // Return our identity
  56. *ppvObject = (ISMTPServerInternal *)this;
  57. AddRef();
  58. }
  59. else if(iid == IID_ISMTPServerInternal)
  60. {
  61. // Return our identity
  62. *ppvObject = (ISMTPServerInternal *)this;
  63. AddRef();
  64. }
  65. else if(iid == IID_IMailTransportRouterReset)
  66. {
  67. // Return our identity
  68. *ppvObject = (IMailTransportRouterReset *)this;
  69. AddRef();
  70. }
  71. else if(iid == IID_IMailTransportSetRouterReset)
  72. {
  73. // Return our identity
  74. *ppvObject = (IMailTransportSetRouterReset *)this;
  75. AddRef();
  76. }
  77. else if(iid == IID_IMailTransportRouterSetLinkState)
  78. {
  79. // Return our identity
  80. *ppvObject = (IMailTransportRouterSetLinkState *)this;
  81. AddRef();
  82. }
  83. else if(iid == IID_ISMTPServerEx)
  84. {
  85. // Return our identity
  86. *ppvObject = (ISMTPServerEx *)this;
  87. AddRef();
  88. }
  89. else if(iid == IID_ISMTPServerGetAuxDomainInfoFlags)
  90. {
  91. // Return our identity
  92. *ppvObject = (ISMTPServerGetAuxDomainInfoFlags *)this;
  93. AddRef();
  94. }
  95. else if(iid == IID_ISMTPServerAsync)
  96. {
  97. // Return our identity
  98. *ppvObject = (ISMTPServerAsync *)this;
  99. AddRef();
  100. }
  101. else
  102. {
  103. return(E_NOINTERFACE);
  104. }
  105. return(S_OK);
  106. }
  107. STDMETHODIMP CSMTPServer::AllocMessage(
  108. IMailMsgProperties **ppMsg
  109. )
  110. {
  111. HRESULT hr = S_OK;
  112. // Create a new MailMsg
  113. hr = CoCreateInstance(
  114. CLSID_MsgImp,
  115. NULL,
  116. CLSCTX_INPROC_SERVER,
  117. IID_IMailMsgProperties,
  118. (LPVOID *)ppMsg);
  119. return(hr);
  120. }
  121. STDMETHODIMP CSMTPServer::SubmitMessage(
  122. IMailMsgProperties *pMsg
  123. )
  124. {
  125. HRESULT hr = S_FALSE;
  126. if(m_pInstance)
  127. {
  128. hr = m_pInstance->InsertIntoAdvQueue(pMsg);
  129. }
  130. return(hr);
  131. }
  132. STDMETHODIMP CSMTPServer::TriggerLocalDelivery(
  133. IMailMsgProperties *pMsg, DWORD dwRecipientCount, DWORD * pdwRecipIndexes
  134. )
  135. {
  136. HRESULT hr = S_FALSE;
  137. if(m_pInstance)
  138. {
  139. hr = m_pInstance->TriggerLocalDelivery(pMsg, dwRecipientCount, pdwRecipIndexes, NULL);
  140. }
  141. return(hr);
  142. }
  143. STDMETHODIMP CSMTPServer::TriggerLocalDeliveryAsync(
  144. IMailMsgProperties *pMsg, DWORD dwRecipientCount, DWORD * pdwRecipIndexes, IMailMsgNotify *pNotify
  145. )
  146. {
  147. HRESULT hr = S_FALSE;
  148. if(m_pInstance)
  149. {
  150. hr = m_pInstance->TriggerLocalDelivery(pMsg, dwRecipientCount, pdwRecipIndexes, pNotify);
  151. }
  152. return(hr);
  153. }
  154. STDMETHODIMP CSMTPServer::TriggerServerEvent(
  155. DWORD dwEventID,
  156. PVOID pvContext)
  157. {
  158. HRESULT hr = S_FALSE;
  159. if(m_pInstance)
  160. {
  161. hr = m_pInstance->TriggerServerEvent(dwEventID, pvContext);
  162. }
  163. return(hr);
  164. }
  165. STDMETHODIMP CSMTPServer::ReadMetabaseString(DWORD MetabaseId, LPBYTE Buffer, DWORD * BufferSize, BOOL fSecure)
  166. {
  167. HRESULT hr = S_FALSE;
  168. if(m_pInstance)
  169. {
  170. hr = m_pInstance->SinkReadMetabaseString(MetabaseId, (char *) Buffer, BufferSize, (BOOL) fSecure);
  171. }
  172. return hr;
  173. }
  174. STDMETHODIMP CSMTPServer::ReadMetabaseDword(DWORD MetabaseId, DWORD * dwValue)
  175. {
  176. HRESULT hr = S_FALSE;
  177. if(m_pInstance)
  178. {
  179. hr = m_pInstance->SinkReadMetabaseDword(MetabaseId, dwValue);
  180. }
  181. return hr;
  182. }
  183. STDMETHODIMP CSMTPServer::ServerStartHintFunction()
  184. {
  185. HRESULT hr = S_OK;
  186. if(m_pInstance)
  187. {
  188. m_pInstance->SinkSmtpServerStartHintFunc();
  189. }
  190. return hr;
  191. }
  192. STDMETHODIMP CSMTPServer::ServerStopHintFunction()
  193. {
  194. HRESULT hr = S_OK;
  195. if(m_pInstance)
  196. {
  197. m_pInstance->SinkSmtpServerStopHintFunc();
  198. }
  199. return hr;
  200. }
  201. STDMETHODIMP CSMTPServer::ReadMetabaseData(DWORD MetabaseId, BYTE *Buffer, DWORD *BufferSize)
  202. {
  203. HRESULT hr = S_FALSE;
  204. if(m_pInstance)
  205. {
  206. hr = m_pInstance->SinkReadMetabaseData(MetabaseId, Buffer, BufferSize);
  207. }
  208. return hr;
  209. }
  210. //---[ CSMTPServer::AllocBoundMessage ]----------------------------------------
  211. //
  212. //
  213. // Description:
  214. // Creates a message and binds it to an ATQ Context
  215. // Parameters:
  216. // ppMsg Message to allocate
  217. // phContent Content handle for message
  218. // Returns:
  219. // HRESULT from alloc message event
  220. // E_POINTER if ppMsg or phContent is NULL
  221. // E_FAIL if m_pIstance is NULL
  222. // History:
  223. // 7/11/98 - MikeSwa Created
  224. //
  225. //-----------------------------------------------------------------------------
  226. STDMETHODIMP CSMTPServer::AllocBoundMessage(
  227. OUT IMailMsgProperties **ppMsg,
  228. OUT PFIO_CONTEXT *phContent)
  229. {
  230. TraceFunctEnterEx((LPARAM) this, "CSMTPServer::AllocBoundMessage");
  231. HRESULT hr = S_OK;
  232. SMTP_ALLOC_PARAMS AllocParams;
  233. IMailMsgBind *pBindInterface = NULL;
  234. if (!phContent || !ppMsg)
  235. {
  236. hr = E_POINTER;
  237. goto Exit;
  238. }
  239. //we cannot bind the message without m_pInstance
  240. if (!m_pInstance)
  241. {
  242. hr = E_FAIL;
  243. goto Exit;
  244. }
  245. //CoCreate unbound message object
  246. hr = CoCreateInstance(
  247. CLSID_MsgImp,
  248. NULL,
  249. CLSCTX_INPROC_SERVER,
  250. IID_IMailMsgProperties,
  251. (LPVOID *)ppMsg);
  252. if (FAILED(hr))
  253. goto Exit;
  254. hr = (*ppMsg)->QueryInterface(IID_IMailMsgBind, (void **) &pBindInterface);
  255. if (FAILED(hr))
  256. goto Exit;
  257. AllocParams.BindInterfacePtr = (PVOID) pBindInterface;
  258. AllocParams.IMsgPtr = (PVOID) (*ppMsg);
  259. AllocParams.hContent = NULL;
  260. AllocParams.hr = S_OK;
  261. AllocParams.m_pNotify = NULL;
  262. //For client context pass in something that will stay around the lifetime of the
  263. //atqcontext -
  264. AllocParams.pAtqClientContext = m_pInstance;
  265. if(m_pInstance->AllocNewMessage(&AllocParams))
  266. {
  267. hr = AllocParams.hr;
  268. if (SUCCEEDED(hr) && (AllocParams.hContent != NULL))
  269. *phContent = AllocParams.hContent;
  270. else
  271. hr = E_FAIL;
  272. }
  273. else
  274. {
  275. hr = E_FAIL;
  276. }
  277. Exit:
  278. if (FAILED(hr) && ppMsg && (*ppMsg))
  279. {
  280. (*ppMsg)->Release();
  281. *ppMsg = NULL;
  282. }
  283. if (pBindInterface)
  284. pBindInterface->Release();
  285. TraceFunctLeave();
  286. return hr;
  287. }
  288. //---[ CSMTPSvr::ResetRoutes ]-------------------------------------------------
  289. //
  290. //
  291. // Description:
  292. // Implements IMailTransportRouterReset::ResetRoutes. Acts as a buffer
  293. // between AQ and the routers. On shutdown... AQ can safely destroy
  294. // it's heap by telling ISMTPServer to release its pointer to AQ's
  295. // IMailTransportRouterReset interface
  296. // Parameters:
  297. // dwResetType The type of route reset to perform.
  298. // Returns:
  299. // S_OK on success (or if no m_pIRouterReset)
  300. // Error code from AQUEUE if error occurs.
  301. // History:
  302. // 11/8/98 - MikeSwa Created
  303. //
  304. //-----------------------------------------------------------------------------
  305. STDMETHODIMP CSMTPServer::ResetRoutes(IN DWORD dwResetType)
  306. {
  307. HRESULT hr = S_OK;
  308. m_slRouterReset.ShareLock();
  309. if (m_pIRouterReset)
  310. hr = m_pIRouterReset->ResetRoutes(dwResetType);
  311. m_slRouterReset.ShareUnlock();
  312. return hr;
  313. }
  314. //---[ CSMTPSvr::RegisterResetInterface ]---------------------------------------
  315. //
  316. //
  317. // Description:
  318. // Implements IMailTransportSetRouterReset::RegisterResetInterface. Used
  319. // by AQ to set its IMailTransportRouterReset ptr. Also used at shutdown
  320. // to set its pointer to NULL.
  321. // Parameters:
  322. // IN dwVirtualServerID Virtual server ID
  323. // IN pIRouterReset AQ's IMailTransportRouterReset
  324. // Returns:
  325. // S_OK on success
  326. // History:
  327. // 11/8/98 - MikeSwa Created
  328. // 1/9/99 - MikeSwa Modified to include IMailTransportRouterSetLinkState
  329. //
  330. //-----------------------------------------------------------------------------
  331. STDMETHODIMP CSMTPServer::RegisterResetInterface(
  332. IN DWORD dwVirtualServerID,
  333. IN IMailTransportRouterReset *pIRouterReset)
  334. {
  335. HRESULT hr = S_OK;
  336. _ASSERT(!m_pInstance || (m_pInstance->QueryInstanceId() == dwVirtualServerID));
  337. if (m_pInstance && (m_pInstance->QueryInstanceId() != dwVirtualServerID))
  338. return E_INVALIDARG;
  339. //Grab exclsuive lock so we don't release out from under anyone
  340. m_slRouterReset.ExclusiveLock();
  341. if (m_pIRouterReset)
  342. m_pIRouterReset->Release();
  343. if (m_pIRouterSetLinkState)
  344. {
  345. m_pIRouterSetLinkState->Release();
  346. m_pIRouterSetLinkState = NULL;
  347. }
  348. m_pIRouterReset = pIRouterReset;
  349. if (m_pIRouterReset)
  350. {
  351. m_pIRouterReset->AddRef();
  352. //Get new SetLinkState interface
  353. m_pIRouterReset->QueryInterface(IID_IMailTransportRouterSetLinkState,
  354. (VOID **) &m_pIRouterSetLinkState);
  355. }
  356. m_slRouterReset.ExclusiveUnlock();
  357. return S_OK;
  358. }
  359. STDMETHODIMP CSMTPServer::WriteLog( LPMSG_TRACK_INFO pMsgTrackInfo,
  360. IMailMsgProperties *pMsgProps,
  361. LPEVENT_LOG_INFO pEventLogInfo ,
  362. LPSTR pszProtocolLog )
  363. {
  364. HRESULT hr = S_OK;
  365. if(m_pInstance)
  366. {
  367. m_pInstance->WriteLog( pMsgTrackInfo, pMsgProps, pEventLogInfo, pszProtocolLog );
  368. }
  369. return hr;
  370. }
  371. //---[ CSMTPServer::SetLinkState ]----------------------------------------------
  372. //
  373. //
  374. // Description:
  375. // Acts as a buffer between AQ and the routers. On shutdown... AQ can
  376. // safely destroy it's heap by telling ISMTPServer to release its pointer
  377. // to AQ's IMailTransportRouterSetLinkState interface
  378. // Parameters:
  379. // IN szLinkDomainName The Domain Name of the link (next hop)
  380. // IN guidRouterGUID The GUID ID of the router
  381. // IN dwScheduleID The schedule ID link
  382. // IN szConnectorName The connector name given by the router
  383. // IN dwSetLinkState The link state to set
  384. // IN dwUnsetLinkState The link state to unset
  385. // Returns:
  386. // S_OK always
  387. // History:
  388. // 1/9/99 - MikeSwa Created
  389. //
  390. //-----------------------------------------------------------------------------
  391. STDMETHODIMP CSMTPServer::SetLinkState(
  392. IN LPSTR szLinkDomainName,
  393. IN GUID guidRouterGUID,
  394. IN DWORD dwScheduleID,
  395. IN LPSTR szConnectorName,
  396. IN DWORD dwSetLinkState,
  397. IN DWORD dwUnsetLinkState,
  398. IN FILETIME *pftNextScheduled,
  399. IN IMessageRouter *pMessageRouter)
  400. {
  401. HRESULT hr = S_OK;
  402. m_slRouterReset.ShareLock();
  403. if (m_pIRouterSetLinkState)
  404. hr = m_pIRouterSetLinkState->SetLinkState(szLinkDomainName,
  405. guidRouterGUID,
  406. dwScheduleID,
  407. szConnectorName,
  408. dwSetLinkState,
  409. dwUnsetLinkState,
  410. pftNextScheduled,
  411. pMessageRouter);
  412. m_slRouterReset.ShareUnlock();
  413. return hr;
  414. }
  415. STDMETHODIMP CSMTPServer::TriggerLogEvent(
  416. IN DWORD idMessage,
  417. IN WORD idCategory,
  418. IN WORD cSubstrings,
  419. IN LPCSTR *rgszSubstrings,
  420. IN WORD wType,
  421. IN DWORD errCode,
  422. IN WORD iDebugLevel,
  423. IN LPCSTR szKey,
  424. IN DWORD dwOptions,
  425. IN DWORD iMessageString,
  426. IN HMODULE hModule)
  427. {
  428. HRESULT hr = S_OK;
  429. if(m_pInstance)
  430. {
  431. m_pInstance->TriggerLogEvent(
  432. idMessage,
  433. idCategory,
  434. cSubstrings,
  435. rgszSubstrings,
  436. wType,
  437. errCode,
  438. iDebugLevel,
  439. szKey,
  440. dwOptions,
  441. iMessageString,
  442. hModule);
  443. }
  444. return hr;
  445. }
  446. //---[ CSMTPServer::ResetLogEvent ]------------------------------------------
  447. //
  448. //
  449. // Description:
  450. // Reset any history about events using this message and key,
  451. // so that the next TriggerLogEvent with one-time or periodic logging
  452. // will cause the event to be logged.
  453. // Parameters:
  454. // idMessage :
  455. // szKey :
  456. // Returns:
  457. // S_OK on success
  458. // History:
  459. // 7/20/2000 - created, dbraun
  460. //
  461. //-----------------------------------------------------------------------------
  462. STDMETHODIMP CSMTPServer::ResetLogEvent(
  463. IN DWORD idMessage,
  464. IN LPCSTR szKey)
  465. {
  466. HRESULT hr = S_OK;
  467. if(m_pInstance)
  468. {
  469. m_pInstance->ResetLogEvent(
  470. idMessage,
  471. szKey);
  472. }
  473. return hr;
  474. }
  475. //---[ CSMTPServer::HrTriggerGetAuxDomainInfoFlagsEvent ]----------------------
  476. //
  477. //
  478. // Description:
  479. // Triggers the Get Aux Domain Info Flags event - this is to be used by aqueue to
  480. // query for additional domain info config stored outside the metabase
  481. // Parameters:
  482. // pszDomainName : Name of domain to query flags for
  483. // pdwDomainInfoFlags : DWORD to return domain flags
  484. // Returns:
  485. // S_OK on success
  486. // S_FALSE if no domain found
  487. // History:
  488. // 10/6/2000 - created, dbraun
  489. //
  490. //-----------------------------------------------------------------------------
  491. STDMETHODIMP CSMTPServer::HrTriggerGetAuxDomainInfoFlagsEvent(
  492. IN LPCSTR pszDomainName,
  493. OUT DWORD *pdwDomainInfoFlags )
  494. {
  495. HRESULT hr = S_OK;
  496. if(m_pInstance)
  497. {
  498. hr = m_pInstance->HrTriggerGetAuxDomainInfoFlagsEvent(
  499. pszDomainName,
  500. pdwDomainInfoFlags);
  501. }
  502. return hr;
  503. }