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.

3205 lines
92 KiB

  1. //#define INCL_INETSRV_INCS
  2. //#include "smtpinc.h"
  3. #include <atq.h>
  4. #include <pudebug.h>
  5. #include <inetcom.h>
  6. #include <inetinfo.h>
  7. #include <tcpdll.hxx>
  8. #include <tsunami.hxx>
  9. #include <tchar.h>
  10. #include <iistypes.hxx>
  11. #include <iisendp.hxx>
  12. #include <metacach.hxx>
  13. #include <cpool.h>
  14. #include <address.hxx>
  15. #include <mailmsgprops.h>
  16. extern "C" {
  17. #include <rpc.h>
  18. #define SECURITY_WIN32
  19. #include <wincrypt.h>
  20. #include <sspi.h>
  21. #include <spseal.h>
  22. #include <issperr.h>
  23. #include <ntlmsp.h>
  24. }
  25. #include <tcpproc.h>
  26. #include <tcpcons.h>
  27. #include <rdns.hxx>
  28. #include <simauth2.h>
  29. #include "dbgtrace.h"
  30. #include "imd.h"
  31. #include "mb.hxx"
  32. #include <stdio.h>
  33. #define _ATL_NO_DEBUG_CRT
  34. #define _ATL_STATIC_REGISTRY 1
  35. #define _ASSERTE _ASSERT
  36. #define _WINDLL
  37. #include "atlbase.h"
  38. extern CComModule _Module;
  39. #include "atlcom.h"
  40. #undef _WINDLL
  41. #include "filehc.h"
  42. #include "seo.h"
  43. #include "seolib.h"
  44. #include "smtpdisp_i.c"
  45. #include "mailmsgi.h"
  46. #include <smtpevent.h>
  47. #include "cdo.h"
  48. #include "cdo_i.c"
  49. #include "cdoconstimsg.h"
  50. #include "seomgr.h"
  51. #define MAX_RULE_LENGTH 4096
  52. //
  53. // Message object
  54. //
  55. #define MAILMSG_PROGID L"Exchange.MailMsg"
  56. #define INITGUID
  57. #include "initguid.h"
  58. #include "smtpguid.h"
  59. #include "wildmat.h"
  60. #include "smtpdisp.h"
  61. #include "seodisp.h"
  62. #include "evntwrap.h"
  63. // {0xCD000080,0x8B95,0x11D1,{0x82,0xDB,0x00,0xC0,0x4F,0xB1,0x62,0x5D}}
  64. DEFINE_GUID(IID_IConstructIMessageFromIMailMsg, 0xCD000080,0x8B95,0x11D1,0x82,
  65. 0xDB,0x00,0xC0,0x4F,0xB1,0x62,0x5D);
  66. extern VOID
  67. ServerEventCompletion(
  68. PVOID pvContext,
  69. DWORD cbWritten,
  70. DWORD dwCompletionStatus,
  71. OVERLAPPED * lpo
  72. );
  73. #define SKIPSINK_CALL_NO_MORE_SINKS 0xffffffff
  74. class CStoreCreateOptions : public CEventCreateOptionsBase
  75. {
  76. public:
  77. CStoreCreateOptions( SMTP_ALLOC_PARAMS * pContext)
  78. {
  79. _ASSERT (pContext != NULL);
  80. m_Context = pContext;
  81. }
  82. private:
  83. HRESULT STDMETHODCALLTYPE Init(REFIID iidDesired, IUnknown **ppUnkObject, IEventBinding *, IUnknown *)
  84. {
  85. ISMTPStoreDriver *pSink = NULL;
  86. IUnknown * ThisUnknown = NULL;
  87. IUnknown * NewUnknown = NULL;
  88. HRESULT hrRes = S_OK;
  89. TraceFunctEnterEx((LPARAM)this, "Calling create options");
  90. ThisUnknown = *ppUnkObject;
  91. hrRes = ThisUnknown->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
  92. if (hrRes == E_NOINTERFACE) {
  93. return (E_NOTIMPL);
  94. }
  95. if (FAILED(hrRes))
  96. return(hrRes);
  97. DebugTrace((LPARAM)this, "Calling startup events on sinks ...");
  98. hrRes = pSink->Init(m_Context->m_InstanceId,
  99. NULL,
  100. (IUnknown *) m_Context->m_EventSmtpServer,
  101. m_Context->m_dwStartupType,
  102. &NewUnknown);
  103. pSink->Release();
  104. if (FAILED(hrRes) && (hrRes != E_NOTIMPL)) {
  105. return (hrRes);
  106. }
  107. if(NewUnknown)
  108. {
  109. hrRes = NewUnknown->QueryInterface(iidDesired, (void **)ppUnkObject);
  110. NewUnknown->Release();
  111. if (!SUCCEEDED(hrRes)) {
  112. return (hrRes);
  113. }
  114. ThisUnknown->Release();
  115. }
  116. return (E_NOTIMPL);
  117. };
  118. public:
  119. SMTP_ALLOC_PARAMS * m_Context;
  120. };
  121. CStoreDispatcher::CStoreAllocParams::CStoreAllocParams()
  122. {
  123. m_hContent = NULL;
  124. }
  125. CStoreDispatcher::CStoreAllocParams::~CStoreAllocParams()
  126. {
  127. }
  128. //+------------------------------------------------------------
  129. //
  130. // Function: CStoreDispatcher::CreateCParams
  131. //
  132. // Synopsis: Based on dwEventType, create the appropriate Params object
  133. //
  134. // Arguments:
  135. // dwEventType - specifies SMTP event
  136. // pContext - context to pass into Init function
  137. //
  138. // Returns:
  139. // S_OK: Success
  140. // E_OUTOFMEMORY
  141. // or error from InitParamData
  142. //
  143. // History:
  144. // jstamerj 980610 18:30:20: Created.
  145. //
  146. //-------------------------------------------------------------
  147. HRESULT CStoreDispatcher::CreateCParams(
  148. DWORD dwEventType,
  149. LPVOID pContext,
  150. IMailTransportNotify *pINotify,
  151. REFIID rGuidEventType,
  152. CStoreBaseParams **ppCParams)
  153. {
  154. _ASSERT(ppCParams);
  155. HRESULT hr;
  156. switch(dwEventType) {
  157. case SMTP_STOREDRV_STARTUP_EVENT:
  158. if (!SUCCEEDED(GetData(NULL,NULL))) {
  159. hr = SetData(((SMTP_ALLOC_PARAMS *) pContext)->m_EventSmtpServer,
  160. ((SMTP_ALLOC_PARAMS *) pContext)->m_InstanceId);
  161. _ASSERT(SUCCEEDED(hr));
  162. }
  163. // fall through
  164. case SMTP_MAIL_DROP_EVENT:
  165. case SMTP_STOREDRV_ENUMMESS_EVENT:
  166. case SMTP_STOREDRV_DELIVERY_EVENT:
  167. case SMTP_STOREDRV_ALLOC_EVENT:
  168. case SMTP_STOREDRV_PREPSHUTDOWN_EVENT:
  169. case SMTP_STOREDRV_SHUTDOWN_EVENT:
  170. *ppCParams = new CStoreParams();
  171. break;
  172. case SMTP_MAILTRANSPORT_SUBMISSION_EVENT:
  173. *ppCParams = new CMailTransportSubmissionParams();
  174. break;
  175. case SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT:
  176. *ppCParams = new CMailTransportPreCategorizeParams();
  177. break;
  178. case SMTP_MAILTRANSPORT_CATEGORIZE_REGISTER_EVENT:
  179. *ppCParams = new CMailTransportCatRegisterParams();
  180. break;
  181. case SMTP_MAILTRANSPORT_CATEGORIZE_BEGIN_EVENT:
  182. *ppCParams = new CMailTransportCatBeginParams();
  183. break;
  184. case SMTP_MAILTRANSPORT_CATEGORIZE_END_EVENT:
  185. *ppCParams = new CMailTransportCatEndParams();
  186. break;
  187. case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERY_EVENT:
  188. *ppCParams = new CMailTransportCatBuildQueryParams();
  189. break;
  190. case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERIES_EVENT:
  191. *ppCParams = new CMailTransportCatBuildQueriesParams();
  192. break;
  193. case SMTP_MAILTRANSPORT_CATEGORIZE_SENDQUERY_EVENT:
  194. *ppCParams = new CMailTransportCatSendQueryParams();
  195. break;
  196. case SMTP_MAILTRANSPORT_CATEGORIZE_SORTQUERYRESULT_EVENT:
  197. *ppCParams = new CMailTransportCatSortQueryResultParams();
  198. break;
  199. case SMTP_MAILTRANSPORT_CATEGORIZE_PROCESSITEM_EVENT:
  200. *ppCParams = new CMailTransportCatProcessItemParams();
  201. break;
  202. case SMTP_MAILTRANSPORT_CATEGORIZE_EXPANDITEM_EVENT:
  203. *ppCParams = new CMailTransportCatExpandItemParams();
  204. break;
  205. case SMTP_MAILTRANSPORT_CATEGORIZE_COMPLETEITEM_EVENT:
  206. *ppCParams = new CMailTransportCatCompleteItemParams();
  207. break;
  208. case SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT:
  209. *ppCParams = new CMailTransportPostCategorizeParams();
  210. break;
  211. case SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT:
  212. *ppCParams = new CMailTransportRouterParams();
  213. break;
  214. case SMTP_MSGTRACKLOG_EVENT:
  215. *ppCParams = new CMsgTrackLogParams();
  216. break;
  217. case SMTP_DNSRESOLVERRECORDSINK_EVENT:
  218. *ppCParams = new CDnsResolverRecordParams();
  219. break;
  220. case SMTP_MAXMSGSIZE_EVENT:
  221. *ppCParams = new CSmtpMaxMsgSizeParams();
  222. break;
  223. case SMTP_LOG_EVENT:
  224. *ppCParams = new CSmtpLogParams();
  225. break;
  226. case SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT:
  227. *ppCParams = new CSmtpGetAuxDomainInfoFlagsParams();
  228. break;
  229. default:
  230. _ASSERT(0 && "Unknown server event");
  231. *ppCParams = NULL;
  232. break;
  233. }
  234. if(*ppCParams == NULL) {
  235. return E_OUTOFMEMORY;
  236. }
  237. hr = (*ppCParams)->InitParamData(
  238. pContext,
  239. dwEventType,
  240. pINotify,
  241. this,
  242. rGuidEventType);
  243. if(FAILED(hr)) {
  244. (*ppCParams)->Release();
  245. *ppCParams = NULL;
  246. return hr;
  247. }
  248. return S_OK;
  249. }
  250. //+------------------------------------------------------------
  251. //
  252. // Function: CStoreDispatcher::CStoreBaseParams::CStoreBaseParams
  253. //
  254. // Synopsis: Sets member data to pre-initialized values
  255. //
  256. // Arguments: NONE
  257. //
  258. // Returns: NOTHING
  259. //
  260. // History:
  261. // jstamerj 1998/06/23 13:58:01: Created.
  262. //
  263. //-------------------------------------------------------------
  264. CStoreDispatcher::CStoreBaseParams::CStoreBaseParams() :
  265. m_rguidEventType(CATID_SMTP_STORE_DRIVER)
  266. {
  267. m_dwSignature = SIGNATURE_VALID_CSTOREPARAMS;
  268. m_dwIdx_SinkSkip = 0;
  269. m_fDefaultProcessingCalled = FALSE;
  270. m_pINotify = NULL;
  271. m_pIUnknownSink = NULL;
  272. m_pDispatcher = NULL;
  273. }
  274. //+------------------------------------------------------------
  275. //
  276. // Function: CStoreDispatcher::CStoreBaseParams::~CStoreBaseParams
  277. //
  278. // Synopsis: Release the IMailTransportNotify reference if held
  279. //
  280. // Arguments: NONE
  281. //
  282. // Returns: NOTHING
  283. //
  284. // History:
  285. // jstamerj 1998/06/23 13:58:51: Created.
  286. //
  287. //-------------------------------------------------------------
  288. CStoreDispatcher::CStoreBaseParams::~CStoreBaseParams()
  289. {
  290. if(m_pINotify)
  291. m_pINotify->Release();
  292. _ASSERT(m_dwSignature == SIGNATURE_VALID_CSTOREPARAMS);
  293. m_dwSignature = SIGNATURE_INVALID_CSTOREPARAMS;
  294. }
  295. //+------------------------------------------------------------
  296. //
  297. // Function: InitParamData
  298. //
  299. // Synopsis: Initializes object. This includes calling Init() which
  300. // is implemented in dervied objects.
  301. //
  302. // Arguments:
  303. // pContext: Context passed in - specific for server event
  304. // dwEventType: Specifies which server event we are for
  305. // pINotify: IMailTransportNotify interface for async completion
  306. // rguidEventType: guid for event type binding
  307. //
  308. // Returns:
  309. // S_OK: Success
  310. // Error from Init()
  311. //
  312. // History:
  313. // jstamerj 980615 19:16:55: Created.
  314. //
  315. //-------------------------------------------------------------
  316. HRESULT CStoreDispatcher::CStoreBaseParams::InitParamData(
  317. PVOID pContext,
  318. DWORD dwEventType,
  319. IMailTransportNotify *pINotify,
  320. CStoreDispatcher *pDispatcher,
  321. REFIID rguidEventType)
  322. {
  323. TraceFunctEnterEx((LPARAM)this, "CStoreBaseParams::InitParamData");
  324. HRESULT hr;
  325. m_dwEventType = dwEventType;
  326. m_dwIdx_SinkSkip = 0;
  327. m_fDefaultProcessingCalled = FALSE;
  328. m_pINotify = pINotify;
  329. m_pINotify->AddRef();
  330. m_rguidEventType = rguidEventType;
  331. m_pDispatcher = pDispatcher;
  332. hr = Init(pContext);
  333. if(FAILED(hr)) {
  334. ErrorTrace((LPARAM)this, "Init() failed, hr = %08lx", hr);
  335. TraceFunctLeaveEx((LPARAM)this);
  336. return hr;
  337. }
  338. return S_OK;
  339. }
  340. //+------------------------------------------------------------
  341. //
  342. // Function: CStoreDispatcher::CStoreBaseParams::CallObject
  343. //
  344. // Synopsis: Called by the dispatcher when time to call a sink. This
  345. // implements some default functionality -- create the sink with a
  346. // null CCreateOptions
  347. //
  348. // Arguments:
  349. // IEventManager
  350. // CBinding
  351. //
  352. // Returns:
  353. // S_OK: Success
  354. // or error from CreateSink/CallObject
  355. //
  356. // History:
  357. // jstamerj 1998/06/23 13:53:57: Created.
  358. //
  359. //-------------------------------------------------------------
  360. HRESULT CStoreDispatcher::CStoreBaseParams::CallObject(
  361. IEventManager *pManager,
  362. CBinding& bBinding)
  363. {
  364. HRESULT hrRes;
  365. CComPtr<IUnknown> pUnkSink;
  366. if (!pManager) {
  367. return (E_POINTER);
  368. }
  369. hrRes = pManager->CreateSink(bBinding.m_piBinding,NULL,&pUnkSink);
  370. if (!SUCCEEDED(hrRes)) {
  371. return (hrRes);
  372. }
  373. return (CallObject(bBinding,pUnkSink));
  374. }
  375. //+------------------------------------------------------------
  376. //
  377. // Function: CStoreDispatcher::CStoreBaseParams::CheckMailMsgRule
  378. //
  379. // Synopsis: Determines if a mailmsg string rule passes or fails given
  380. // the mailmsg and the CBinding object
  381. //
  382. // Arguments:
  383. // pBinding: CBinding object for this sink
  384. // pMsgProps: IMailMsgProperteries of the message to check
  385. //
  386. // Returns:
  387. // S_OK: Success, call this sink
  388. // S_FALSE: Success, don't call this sink
  389. //
  390. // History:
  391. // jstamerj 1999/01/11 17:04:01: Created.
  392. //
  393. //-------------------------------------------------------------
  394. HRESULT CStoreDispatcher::CStoreBaseParams::CheckMailMsgRule(
  395. CBinding *pBinding,
  396. IMailMsgProperties *pIMsgProps)
  397. {
  398. HRESULT hr;
  399. BOOL fDomainLoaded = FALSE;
  400. BOOL fSenderLoaded = FALSE;
  401. CHAR szDomain[MAX_INTERNET_NAME + 2];
  402. CHAR szSender[MAX_INTERNET_NAME + 2];
  403. LPSTR szRule;
  404. CStoreBinding *pStoreBinding = (CStoreBinding *)pBinding;
  405. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CStoreBaseParams::CheckMailMsgRule");
  406. _ASSERT(pStoreBinding);
  407. _ASSERT(pIMsgProps);
  408. // Get the cached rule from the binding
  409. szRule = pStoreBinding->GetRuleString();
  410. DebugTrace((LPARAM)this, "Rule string: %s", (szRule)?szRule:"NULL (No rule)");
  411. // If the rule is NULL, we will don't have a rule
  412. // string and we will return a match
  413. if (!szRule)
  414. {
  415. TraceFunctLeaveEx((LPARAM)this);
  416. return(S_OK);
  417. }
  418. // try each comma delimited rule in the header patterns list
  419. char *pszHeader = (char *) _alloca(lstrlen(szRule)+1);
  420. if (!pszHeader) {
  421. return (E_OUTOFMEMORY);
  422. }
  423. lstrcpy(pszHeader,szRule);
  424. while (pszHeader != NULL && *pszHeader != 0)
  425. {
  426. // find the next semicolon in the string and turn it into a 0
  427. // if it exists
  428. char *pszSemiColon = strchr(pszHeader, ';');
  429. if (pszSemiColon != NULL)
  430. *pszSemiColon = 0;
  431. // set pszContents to point to the text which must be matched
  432. // in the header. if pszContents == NULL then just having
  433. // the header exist is good enough.
  434. char *pszPatterns = strchr(pszHeader, '=');
  435. if (pszPatterns != NULL)
  436. {
  437. *pszPatterns = 0;
  438. (pszPatterns++);
  439. }
  440. // we now have the header that we are looking for in
  441. // pszHeader and the list of patterns that we are interested
  442. // in pszPatterns. Make the lookup into the header
  443. // data structure
  444. hr = S_FALSE;
  445. DebugTrace((LPARAM)this, "Processing Header <%s> with pattern <%s>",
  446. pszHeader, pszPatterns);
  447. if (!lstrcmpi(pszHeader, "EHLO")) {
  448. // Process a client domain rule ...
  449. if (!fDomainLoaded) {
  450. hr = pIMsgProps->GetStringA(
  451. IMMPID_MP_HELO_DOMAIN,
  452. sizeof(szDomain),
  453. szDomain);
  454. if (hr == S_OK) {
  455. fDomainLoaded = TRUE;
  456. }
  457. }
  458. if (fDomainLoaded) {
  459. hr = MatchEmailOrDomainName(szDomain, pszPatterns, FALSE);
  460. }
  461. } else if (!lstrcmpi(pszHeader, "MAIL FROM")) {
  462. // Process a sender name rule ...
  463. if (!fSenderLoaded) {
  464. hr = pIMsgProps->GetStringA(
  465. IMMPID_MP_SENDER_ADDRESS_SMTP,
  466. sizeof(szSender),
  467. szSender);
  468. if (hr == S_OK)
  469. {
  470. fSenderLoaded = TRUE;
  471. }
  472. }
  473. if (fSenderLoaded) {
  474. hr = MatchEmailOrDomainName(szSender, pszPatterns, TRUE);
  475. }
  476. }
  477. else if (!lstrcmpi(pszHeader, "RCPT TO"))
  478. {
  479. hr = CheckMailMsgRecipientsRule(
  480. pIMsgProps,
  481. pszPatterns);
  482. }
  483. // We don't want to destroy the rule string so we restore all the
  484. // semicolons and equal signs
  485. if (pszSemiColon)
  486. *pszSemiColon = ';';
  487. if (pszPatterns)
  488. *(pszPatterns - 1) = '=';
  489. // Exit immediately if we found a match!
  490. if (hr == S_OK)
  491. goto Cleanup;
  492. // the next pattern is the one past the end of the semicolon
  493. pszHeader = (pszSemiColon == NULL) ? NULL : pszSemiColon + 1;
  494. }
  495. Cleanup:
  496. DebugTrace((LPARAM)this, "Returning hr %08lx", hr);
  497. TraceFunctLeaveEx((LPARAM)this);
  498. return(hr);
  499. }
  500. //+------------------------------------------------------------
  501. //
  502. // Function: CStoreDispatcher::CStoreBaseParams::CheckMailMsgRecipientsRule
  503. //
  504. // Synopsis: Determines if a mailmsg pattern string matches mailmsg
  505. // recipients or not
  506. //
  507. // Arguments:
  508. // pIMsg: An interface to a mailmsg object
  509. // pszPatterns: The sink rule to check
  510. //
  511. // Returns:
  512. // S_OK: Success, call this sink
  513. // S_FALSE: Success, don't call this sink
  514. // error from mailmsg
  515. //
  516. // History:
  517. // jstamerj 1999/01/12 15:25:55: Copied from MCIS2 and modified for Platinum
  518. //
  519. //-------------------------------------------------------------
  520. HRESULT CStoreDispatcher::CStoreBaseParams::CheckMailMsgRecipientsRule(
  521. IUnknown *pIMsg,
  522. LPSTR pszPattern)
  523. {
  524. HRESULT hr;
  525. DWORD dwNumRecips;
  526. IMailMsgRecipients *pIRecips = NULL;
  527. BOOL fMatch = FALSE;
  528. DWORD dwCount;
  529. CHAR szRecip [MAX_INTERNET_NAME + 2];
  530. TraceFunctEnterEx((LPARAM)this,
  531. "CStoreDispatcher::CStoreBaseParams::CheckMailMsgRecipientsRule");
  532. hr = pIMsg->QueryInterface(
  533. IID_IMailMsgRecipients,
  534. (LPVOID *)&pIRecips);
  535. if(FAILED(hr))
  536. goto CLEANUP;
  537. hr = pIRecips->Count(&dwNumRecips);
  538. if(FAILED(hr))
  539. goto CLEANUP;
  540. DebugTrace((LPARAM)this, "Checking rule \"%s\" for %d recipients",
  541. pszPattern, pIMsg);
  542. for(dwCount = 0;
  543. (fMatch == FALSE) && (dwCount < dwNumRecips);
  544. dwCount++) {
  545. hr = pIRecips->GetStringA(
  546. dwCount,
  547. IMMPID_RP_ADDRESS_SMTP,
  548. sizeof(szRecip),
  549. szRecip);
  550. if(FAILED(hr) && (hr != MAILMSG_E_PROPNOTFOUND))
  551. goto CLEANUP;
  552. if(hr != MAILMSG_E_PROPNOTFOUND) {
  553. hr = MatchEmailOrDomainName(szRecip,pszPattern,TRUE);
  554. if(hr == S_OK)
  555. fMatch = TRUE;
  556. else if(FAILED(hr))
  557. goto CLEANUP;
  558. }
  559. }
  560. hr = (fMatch) ? S_OK : S_FALSE;
  561. CLEANUP:
  562. if(pIRecips)
  563. pIRecips->Release();
  564. DebugTrace((LPARAM)this, "Returning hr %08lx", hr);
  565. TraceFunctLeaveEx((LPARAM)this);
  566. return hr;
  567. }
  568. //+------------------------------------------------------------
  569. //
  570. // Function: CStoreDispatcher::CStoreBaseparams::MatchEmailOrDomainName
  571. //
  572. // Synopsis: Given an email/domain name and a pattern, determine if
  573. // the pattern matches or not
  574. //
  575. // Arguments:
  576. // szEmail: The email address or domain name
  577. // szPattern: The pattern to check
  578. // fIsEmail: TRUE if szEmail is an email address, FALSE if szEmail is
  579. // a domain
  580. //
  581. // Returns:
  582. // S_OK: Success, match
  583. // S_FALSE: Success, no match
  584. // E_INVALIDARG
  585. //
  586. // History:
  587. // jstamerj 1999/01/12 15:25:36: Copied from MCIS2 and modified for Platinum
  588. //
  589. //-------------------------------------------------------------
  590. HRESULT CStoreDispatcher::CStoreBaseParams::MatchEmailOrDomainName(
  591. LPSTR szEmail,
  592. LPSTR szPattern,
  593. BOOL fIsEmail)
  594. {
  595. CAddr *pEmailAddress = NULL;
  596. LPSTR szEmailDomain = NULL;
  597. HRESULT hrRes;
  598. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CStoreBaseParams::MatchEmailOrDomainName");
  599. DebugTrace((LPARAM)NULL, "Matching <%s> against <%s>", szEmail, szPattern);
  600. if (!szEmail || !szPattern)
  601. return(E_INVALIDARG);
  602. // This validates that it is a good email name
  603. pEmailAddress = CAddr::CreateAddress(szEmail, fIsEmail?FROMADDR:CLEANDOMAIN);
  604. if (!pEmailAddress)
  605. return(E_INVALIDARG);
  606. szEmail = pEmailAddress->GetAddress();
  607. szEmailDomain = pEmailAddress->GetDomainOffset();
  608. hrRes = ::MatchEmailOrDomainName(szEmail, szEmailDomain, szPattern, fIsEmail);
  609. // Free the CAddr objects ...
  610. if (pEmailAddress)
  611. delete pEmailAddress;
  612. TraceFunctLeaveEx((LPARAM)this);
  613. return(hrRes);
  614. }
  615. CStoreDispatcher::CStoreBinding::CStoreBinding()
  616. {
  617. m_szRule = NULL;
  618. }
  619. CStoreDispatcher::CStoreBinding::~CStoreBinding()
  620. {
  621. if(m_szRule)
  622. delete [] m_szRule;
  623. }
  624. //
  625. // initialize a new binding. we cache information from the binding database
  626. // here
  627. // jstamerj 1999/01/12 16:25:59: Copied MCIS2 code to get the rule string
  628. //
  629. HRESULT CStoreDispatcher::CStoreBinding::Init(IEventBinding *piBinding)
  630. {
  631. HRESULT hr;
  632. CComPtr<IEventPropertyBag> piEventProperties;
  633. CComVariant vRule;
  634. // get the parent initialized
  635. hr = CBinding::Init(piBinding);
  636. if (FAILED(hr))
  637. return hr;
  638. // get the binding database
  639. hr = m_piBinding->get_SourceProperties(&piEventProperties);
  640. if (FAILED(hr))
  641. return hr;
  642. // get the rule from the binding database
  643. hr = piEventProperties->Item(&CComVariant("Rule"), &vRule);
  644. if (FAILED(hr))
  645. return hr;
  646. // Process the rule string, the result code is not important
  647. // since it will NULL our the string
  648. if (hr == S_OK)
  649. hr = GetAnsiStringFromVariant(vRule, &m_szRule);
  650. return hr;
  651. }
  652. HRESULT CStoreDispatcher::CStoreBinding::GetAnsiStringFromVariant(
  653. CComVariant &vString, LPSTR *ppszString)
  654. {
  655. HRESULT hr = S_OK;
  656. _ASSERT(ppszString);
  657. if (!ppszString)
  658. return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  659. // Default to NULL
  660. *ppszString = NULL;
  661. if (vString.vt == VT_BSTR)
  662. {
  663. DWORD dwLength = lstrlenW(vString.bstrVal) + 1;
  664. // Convert to an ANSI string and store it as a member
  665. *ppszString = new char[dwLength];
  666. if (!*ppszString)
  667. return HRESULT_FROM_WIN32(GetLastError());
  668. // copy the rule into an ascii string
  669. if (WideCharToMultiByte(CP_ACP, 0, vString.bstrVal,
  670. -1, (*ppszString), dwLength, NULL, NULL) <= 0)
  671. {
  672. delete [] (*ppszString);
  673. *ppszString = NULL;
  674. return HRESULT_FROM_WIN32(GetLastError());
  675. }
  676. }
  677. else
  678. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  679. return(hr);
  680. }
  681. #if 1
  682. //
  683. // create and call the child object
  684. //
  685. HRESULT CStoreDispatcher::CStoreParams::CallObject(IEventManager *pManager, CBinding& bBinding)
  686. {
  687. CStoreCreateOptions opt (m_pContext);
  688. HRESULT hrRes;
  689. CComPtr<IUnknown> pUnkSink;
  690. if (!pManager) {
  691. return (E_POINTER);
  692. }
  693. hrRes = pManager->CreateSink(bBinding.m_piBinding,&opt,&pUnkSink);
  694. if (!SUCCEEDED(hrRes)) {
  695. return (hrRes);
  696. }
  697. return (CallObject(bBinding,pUnkSink));
  698. }
  699. #endif
  700. //
  701. // call the child object
  702. //
  703. HRESULT CStoreDispatcher::CStoreParams::CallObject(CBinding& bBinding, IUnknown *punkObject)
  704. {
  705. HRESULT hrRes = S_OK;
  706. HRESULT hrTmp = S_OK;
  707. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CServerParams::CallObject");
  708. // We do this for different types of SMTP events
  709. switch (m_dwEventType)
  710. {
  711. case SMTP_STOREDRV_STARTUP_EVENT:
  712. break;
  713. case SMTP_STOREDRV_ALLOC_EVENT:
  714. {
  715. IMailMsgStoreDriver *pSink = NULL;
  716. IMailMsgProperties * pMsg = (IMailMsgProperties *)m_pContext->IMsgPtr;
  717. IMailMsgBind *pBindInterface = NULL;
  718. IMailMsgPropertyStream *pStream = NULL;
  719. PATQ_CONTEXT pAtqFileContext = NULL;
  720. DebugTrace((LPARAM)this, "Calling bind on sinks ...");
  721. /*IID_ISMTPStoreDriver*/
  722. hrRes = punkObject->QueryInterface(IID_IMailMsgStoreDriver, (void **)&pSink);
  723. if (FAILED(hrRes))
  724. return(hrRes);
  725. // Allocate a new message
  726. hrRes = pSink->AllocMessage(pMsg, NULL, &pStream, &m_pContext->hContent, NULL);
  727. if(!FAILED(hrRes))
  728. {
  729. pBindInterface = (IMailMsgBind *)m_pContext->BindInterfacePtr;
  730. #if 0
  731. hrRes = pBindInterface->BindToStore(pStream, pSink, m_pContext->hContent,
  732. m_pContext->pAtqClientContext, ServerEventCompletion,
  733. INFINITE,
  734. &m_pContext->pAtqContext,
  735. AtqAddAsyncHandle,
  736. AtqFreeContext);
  737. #endif
  738. hrRes = pBindInterface->BindToStore(pStream,
  739. pSink,
  740. m_pContext->hContent);
  741. if (pStream)
  742. {
  743. pStream->Release();
  744. pStream = NULL;
  745. }
  746. m_pContext->hr = hrRes;
  747. if(FAILED(hrRes))
  748. {
  749. ErrorTrace((LPARAM)this, "pBindAtqInterface->BindToStore failed with %x", hrRes);
  750. // Close the content handle
  751. HRESULT myRes = pSink->CloseContentFile(
  752. pMsg,
  753. m_pContext->hContent);
  754. if (FAILED(myRes))
  755. {
  756. FatalTrace((LPARAM)this, "Unable to close content file (%08x)", myRes);
  757. _ASSERT(FALSE);
  758. }
  759. m_pContext->hContent = NULL;
  760. hrTmp = pSink->Delete(pMsg, NULL);
  761. _ASSERT(SUCCEEDED(hrTmp));
  762. }
  763. else
  764. {
  765. //Skip all sinks - temporary
  766. hrRes = S_FALSE;
  767. }
  768. }
  769. else
  770. {
  771. DebugTrace((LPARAM)this, "pSink->AllocMessage failed with %x", hrRes);
  772. m_pContext->hr = hrRes;
  773. }
  774. pSink->Release();
  775. }
  776. break;
  777. case SMTP_STOREDRV_DELIVERY_EVENT:
  778. {
  779. ISMTPStoreDriver *pSink;
  780. IMailMsgNotify *pNotify;
  781. hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
  782. if (FAILED(hrRes))
  783. return(hrRes);
  784. // if the caller has async notify support then pass in our
  785. // notification class.
  786. if (m_pContext->m_pNotify) {
  787. // the sink might return async, so we need to keep local
  788. // copies of our context data
  789. hrRes = this->CopyContext();
  790. if (FAILED(hrRes))
  791. return hrRes;
  792. hrRes = this->QueryInterface(IID_IMailMsgNotify,
  793. (LPVOID *) &pNotify);
  794. if (FAILED(hrRes))
  795. return hrRes;
  796. } else {
  797. pNotify = NULL;
  798. }
  799. //
  800. // Remember the sink so we can release this sink later if it
  801. // returns pending
  802. //
  803. _ASSERT(m_pIUnknownSink == NULL);
  804. m_pIUnknownSink = (IUnknown*)pSink;
  805. m_pIUnknownSink->AddRef();
  806. DebugTrace((LPARAM)this, "Calling local delivery sink sink ...");
  807. hrRes = pSink->LocalDelivery(
  808. (IMailMsgProperties *) m_pContext->IMsgPtr,
  809. m_pContext->m_RecipientCount,
  810. m_pContext->pdwRecipIndexes,
  811. (IMailMsgNotify *) pNotify);
  812. pSink->Release();
  813. if(hrRes != MAILTRANSPORT_S_PENDING) {
  814. //
  815. // We completed synchronously, so release the sink
  816. //
  817. m_pIUnknownSink->Release();
  818. m_pIUnknownSink = NULL;
  819. }
  820. // if LocalDelivery was going to do an async return then it
  821. // should have AddRef'd pNotify
  822. if (pNotify) pNotify->Release();
  823. //
  824. // jstamerj 1998/08/04 17:31:07:
  825. // If the store driver sink returns this specific error
  826. // code, we want to stop calling sinks and return from
  827. // TriggerLocalDelivery
  828. //
  829. if(hrRes == STOREDRV_E_RETRY) {
  830. DebugTrace((LPARAM)this, "Sink returned STOREDRV_E_RETRY on LocalDelivery");
  831. m_pContext->hr = hrRes;
  832. hrRes = S_FALSE;
  833. }
  834. }
  835. break;
  836. case SMTP_MAIL_DROP_EVENT:
  837. // ISMTPStoreDriver *pSink;
  838. // hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
  839. // if (FAILED(hrRes))
  840. // return(hrRes);
  841. // DebugTrace((LPARAM)this, "Calling mail drop sink ...");
  842. // hrRes = pSink->DirectoryDrop((IMailMsgProperties *) m_pContext->IMsgPtr, m_pContext->m_RecipientCount, m_pContext->pdwRecipIndexes, m_pContext->m_DropDirectory, NULL);
  843. // pSink->Release();
  844. //}
  845. break;
  846. case SMTP_STOREDRV_PREPSHUTDOWN_EVENT:
  847. {
  848. ISMTPStoreDriver *pSink;
  849. hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
  850. if (FAILED(hrRes))
  851. return(hrRes);
  852. DebugTrace((LPARAM)this, "Calling prepare to shutdown on sinks ...");
  853. hrRes = pSink->PrepareForShutdown(0);
  854. pSink->Release();
  855. hrRes = S_OK;
  856. }
  857. break;
  858. case SMTP_STOREDRV_SHUTDOWN_EVENT:
  859. {
  860. ISMTPStoreDriver *pSink;
  861. hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
  862. if (FAILED(hrRes))
  863. return(hrRes);
  864. DebugTrace((LPARAM)this, "Calling shutdown on sinks ...");
  865. hrRes = pSink->Shutdown(0);
  866. pSink->Release();
  867. hrRes = S_OK;
  868. }
  869. break;
  870. case SMTP_STOREDRV_ENUMMESS_EVENT:
  871. {
  872. ISMTPStoreDriver *pSink;
  873. hrRes = punkObject->QueryInterface(IID_ISMTPStoreDriver, (void **)&pSink);
  874. if (FAILED(hrRes))
  875. return(hrRes);
  876. DebugTrace((LPARAM)this, "Calling Enumerate on sinks ...");
  877. hrRes = pSink->EnumerateAndSubmitMessages(NULL);
  878. pSink->Release();
  879. hrRes = S_OK;
  880. }
  881. break;
  882. default:
  883. DebugTrace((LPARAM)this, "Invalid sink interface");
  884. hrRes = E_NOINTERFACE;
  885. }
  886. TraceFunctLeaveEx((LPARAM)this);
  887. return(hrRes);
  888. }
  889. //+------------------------------------------------------------
  890. //
  891. // Function: CStoreDispatcher::CStoreParams::CallDefault
  892. //
  893. // Synopsis: CStoreDispatcher::Dispatcher will call this routine when
  894. // the default sink priority has been reached.
  895. //
  896. // Arguments: NONE
  897. //
  898. // Returns:
  899. // S_OK: Success
  900. //
  901. // History:
  902. // jstamerj 980611 14:19:57: Created.
  903. //
  904. //-------------------------------------------------------------
  905. HRESULT CStoreDispatcher::CStoreParams::CallDefault()
  906. {
  907. return S_OK;
  908. }
  909. //+------------------------------------------------------------
  910. //
  911. // Function: CStoreDriver::CStoreParams::CallCompletion
  912. //
  913. // Synopsis: The dispatcher will call this routine after all sinks
  914. // have been called
  915. //
  916. // Arguments:
  917. // hrStatus: Status server event sinks have returned
  918. //
  919. // Returns:
  920. // S_OK: Success
  921. //
  922. // History:
  923. // jstamerj 980611 14:17:51: Created.
  924. //
  925. //-------------------------------------------------------------
  926. HRESULT CStoreDispatcher::CStoreParams::CallCompletion(HRESULT hrStatus) {
  927. // call the caller's completion method if there is one
  928. IMailMsgNotify *pNotify = (IMailMsgNotify *) (m_pContext->m_pNotify);
  929. if (pNotify) {
  930. pNotify->Notify(m_pContext->hr);
  931. pNotify->Release();
  932. }
  933. // do the normal call completion work
  934. CStoreBaseParams::CallCompletion(hrStatus);
  935. return S_OK;
  936. }
  937. //
  938. // call the child object
  939. //
  940. HRESULT CStoreDispatcher::CStoreAllocParams::CallObject(CBinding& bBinding, IUnknown *punkObject)
  941. {
  942. HRESULT hrRes = S_OK;
  943. #if 0
  944. IMailMsgStoreDriver *pStoreDriver = NULL;
  945. IMailMsgProperties *pMsg = NULL;
  946. IMailMsgPropertyStream *pStream = NULL;
  947. IMailMsgBindATQ *pBindInterface = NULL;
  948. CLSID clsidMailMsg;
  949. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CStoreAllocParams::CallObject");
  950. hrRes = CLSIDFromProgID(MAILMSG_PROGID, &clsidMailMsg);
  951. if (FAILED(hrRes))
  952. {
  953. DebugTrace((LPARAM)this, "CoCreateInstance IID_IMailMsgProperties failed, %X", hrRes);
  954. return(hrRes);
  955. }
  956. // Create a new MailMsg
  957. hrRes = CoCreateInstance(
  958. clsidMailMsg,
  959. NULL,
  960. CLSCTX_INPROC_SERVER,
  961. IID_IMailMsgProperties,
  962. (LPVOID *)&pMsg);
  963. if (FAILED(hrRes))
  964. {
  965. DebugTrace((LPARAM)this, "CoCreateInstance IID_IMailMsgProperties failed, %X", hrRes);
  966. return(hrRes);
  967. }
  968. hrRes = punkObject->QueryInterface(IID_IMailMsgStoreDriver, (void **)&pStoreDriver);
  969. if (FAILED(hrRes))
  970. {
  971. DebugTrace((LPARAM)this, "QueryInterface() on IID_IMailMsgStoreDriver failed, %X", hrRes);
  972. goto Exit;
  973. }
  974. // Allocate a new message
  975. hrRes = pStoreDriver->AllocMessage(
  976. pMsg,
  977. NULL,
  978. &pStream,
  979. &m_hContent,
  980. NULL);
  981. if (FAILED(hrRes))
  982. {
  983. DebugTrace((LPARAM)this, "pDriver->AllocMessage failed, %X", hrRes);
  984. goto Exit;
  985. }
  986. hrRes = pMsg->QueryInterface(IID_IMailMsgBindATQ, (void **)&pBindInterface);
  987. if (FAILED(hrRes))
  988. {
  989. DebugTrace((LPARAM)this, "QueryInterface() on IID_IMailMsgStoreDriver failed, %X", hrRes);
  990. goto Exit;
  991. }
  992. hrRes = pBindInterface->SetATQInfo (NULL, NULL, NULL, INFINITE, NULL);
  993. if (FAILED(hrRes))
  994. {
  995. DebugTrace((LPARAM)this, "QueryInterface() on IID_IMailMsgStoreDriver failed, %X", hrRes);
  996. goto Exit;
  997. }
  998. Exit:
  999. if(pStoreDriver)
  1000. {
  1001. pStoreDriver->Release();
  1002. }
  1003. if(pMsg)
  1004. {
  1005. pMsg->Release();
  1006. }
  1007. if(pBindInterface)
  1008. {
  1009. pBindInterface->Release();
  1010. }
  1011. TraceFunctLeaveEx((LPARAM)this);
  1012. #endif
  1013. return(hrRes);
  1014. }
  1015. #if 0
  1016. HRESULT STDMETHODCALLTYPE CStoreDispatcher::OnEvent(REFIID iidEvent,
  1017. DWORD dwEventType,
  1018. LPVOID pvContext)
  1019. {
  1020. HRESULT hr = S_OK;
  1021. // create the params object, and pass it into the dispatcher
  1022. CStoreParams ServerParams;
  1023. ServerParams.Init(dwEventType, pvContext);
  1024. hr = Dispatcher(iidEvent, &ServerParams);
  1025. return hr;
  1026. }
  1027. #endif
  1028. //+------------------------------------------------------------
  1029. //
  1030. // Function: CStoreDispatcher::OnEvent
  1031. //
  1032. // Synopsis: Prepares for server event
  1033. //
  1034. // Arguments:
  1035. // iidEvent: guid for event
  1036. // dwEventType: specifies the event
  1037. // pvContext: context for the params object
  1038. //
  1039. // Returns:
  1040. // S_OK: Success
  1041. //
  1042. // History:
  1043. // jstamerj 980616 13:27:55: Created.
  1044. //
  1045. //-------------------------------------------------------------
  1046. HRESULT STDMETHODCALLTYPE CStoreDispatcher::OnEvent(
  1047. REFIID iidEvent,
  1048. DWORD dwEventType,
  1049. LPVOID pvContext)
  1050. {
  1051. HRESULT hr;
  1052. IMailTransportNotify *pINotify = NULL;
  1053. //
  1054. // Call into ATL internals to get the interface we need to pass out
  1055. //
  1056. hr = _InternalQueryInterface(
  1057. IID_IMailTransportNotify,
  1058. (LPVOID *)&pINotify);
  1059. if(FAILED(hr))
  1060. return hr;
  1061. //
  1062. // create the CParams object on the heap -- the object will be
  1063. // needed after this call may be out of here (when a sink returns
  1064. // MAILTRANSPORT_S_PENDING and there are more sinks to call)
  1065. //
  1066. CStoreBaseParams *pCParams;
  1067. hr = CreateCParams(
  1068. dwEventType,
  1069. pvContext,
  1070. pINotify,
  1071. iidEvent,
  1072. &pCParams);
  1073. //
  1074. // The params object should addref pINotify
  1075. //
  1076. pINotify->Release();
  1077. if(FAILED(hr))
  1078. return hr;
  1079. //
  1080. // Start calling sinks
  1081. //
  1082. hr = Dispatcher(iidEvent, pCParams);
  1083. return hr;
  1084. }
  1085. //+------------------------------------------------------------
  1086. //
  1087. // Function: GuidForEvent
  1088. //
  1089. // Synopsis: Given dwEventType, return the appropriate GUID for the
  1090. // event binding
  1091. //
  1092. // Arguments:
  1093. // dwEventType: type of SMTP event
  1094. //
  1095. // Returns:
  1096. // REFIID of GUID for the event
  1097. //
  1098. // History:
  1099. // jstamerj 980610 18:24:24: Created.
  1100. //
  1101. //-------------------------------------------------------------
  1102. REFIID GuidForEvent(DWORD dwEventType)
  1103. {
  1104. switch(dwEventType) {
  1105. case SMTP_MAIL_DROP_EVENT:
  1106. case SMTP_STOREDRV_ENUMMESS_EVENT:
  1107. case SMTP_STOREDRV_DELIVERY_EVENT:
  1108. case SMTP_STOREDRV_ALLOC_EVENT:
  1109. case SMTP_STOREDRV_STARTUP_EVENT:
  1110. case SMTP_STOREDRV_PREPSHUTDOWN_EVENT:
  1111. case SMTP_STOREDRV_SHUTDOWN_EVENT:
  1112. default:
  1113. return CATID_SMTP_STORE_DRIVER;
  1114. case SMTP_MAILTRANSPORT_SUBMISSION_EVENT:
  1115. return CATID_SMTP_TRANSPORT_SUBMISSION;
  1116. case SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT:
  1117. return CATID_SMTP_TRANSPORT_PRECATEGORIZE;
  1118. case SMTP_MAILTRANSPORT_CATEGORIZE_REGISTER_EVENT:
  1119. case SMTP_MAILTRANSPORT_CATEGORIZE_BEGIN_EVENT:
  1120. case SMTP_MAILTRANSPORT_CATEGORIZE_END_EVENT:
  1121. case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERY_EVENT:
  1122. case SMTP_MAILTRANSPORT_CATEGORIZE_BUILDQUERIES_EVENT:
  1123. case SMTP_MAILTRANSPORT_CATEGORIZE_SENDQUERY_EVENT:
  1124. case SMTP_MAILTRANSPORT_CATEGORIZE_SORTQUERYRESULT_EVENT:
  1125. case SMTP_MAILTRANSPORT_CATEGORIZE_PROCESSITEM_EVENT:
  1126. case SMTP_MAILTRANSPORT_CATEGORIZE_EXPANDITEM_EVENT:
  1127. case SMTP_MAILTRANSPORT_CATEGORIZE_COMPLETEITEM_EVENT:
  1128. return CATID_SMTP_TRANSPORT_CATEGORIZE;
  1129. case SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT:
  1130. return CATID_SMTP_TRANSPORT_POSTCATEGORIZE;
  1131. case SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT:
  1132. return CATID_SMTP_TRANSPORT_ROUTER;
  1133. case SMTP_MSGTRACKLOG_EVENT:
  1134. return CATID_SMTP_MSGTRACKLOG;
  1135. case SMTP_DNSRESOLVERRECORDSINK_EVENT:
  1136. return CATID_SMTP_DNSRESOLVERRECORDSINK;
  1137. case SMTP_MAXMSGSIZE_EVENT:
  1138. return CATID_SMTP_MAXMSGSIZE;
  1139. case SMTP_LOG_EVENT:
  1140. return CATID_SMTP_LOG;
  1141. case SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT:
  1142. return CATID_SMTP_GET_AUX_DOMAIN_INFO_FLAGS;
  1143. }
  1144. }
  1145. //
  1146. // this function performs instance level server events registration
  1147. //
  1148. HRESULT RegisterPlatSEOInstance(DWORD dwInstanceID)
  1149. {
  1150. HRESULT hr;
  1151. //
  1152. // find the SMTP source type in the event manager
  1153. //
  1154. CComPtr<IEventManager> pEventManager;
  1155. hr = CoCreateInstance(CLSID_CEventManager, NULL, CLSCTX_ALL,
  1156. IID_IEventManager, (LPVOID *) &pEventManager);
  1157. if (hr != S_OK)
  1158. return hr;
  1159. CComPtr<IEventSourceTypes> pSourceTypes;
  1160. hr = pEventManager->get_SourceTypes(&pSourceTypes);
  1161. if (FAILED(hr))
  1162. return hr;
  1163. CComPtr<IEventSourceType> pSourceType;
  1164. CComBSTR bstrSourceTypeGUID = (LPCOLESTR) CStringGUID(GUID_SMTP_SOURCE_TYPE);
  1165. hr = pSourceTypes->Item(&CComVariant(bstrSourceTypeGUID), &pSourceType);
  1166. _ASSERT(hr != S_OK || pSourceType != NULL);
  1167. if (hr != S_OK)
  1168. return hr;
  1169. //
  1170. // generate a GUID for this source, which is based on GUID_SMTPSVC
  1171. // mangled by the instance ID
  1172. //
  1173. CComPtr<IEventUtil> pEventUtil;
  1174. hr = CoCreateInstance(CLSID_CEventUtil, NULL, CLSCTX_ALL,
  1175. IID_IEventUtil, (LPVOID *) &pEventUtil);
  1176. if (hr != S_OK)
  1177. return hr;
  1178. CComBSTR bstrSMTPSvcGUID = (LPCOLESTR) CStringGUID(GUID_SMTPSVC_SOURCE);
  1179. CComBSTR bstrSourceGUID;
  1180. hr = pEventUtil->GetIndexedGUID(bstrSMTPSvcGUID, dwInstanceID, &bstrSourceGUID);
  1181. if (FAILED(hr))
  1182. return hr;
  1183. //
  1184. // see if this source is registered with the list of sources for the
  1185. // SMTP source type
  1186. //
  1187. CComPtr<IEventSources> pEventSources;
  1188. hr = pSourceType->get_Sources(&pEventSources);
  1189. if (FAILED(hr))
  1190. return hr;
  1191. CComPtr<IEventSource> pEventSource;
  1192. hr = pEventSources->Item(&CComVariant(bstrSourceGUID), &pEventSource);
  1193. if (FAILED(hr))
  1194. return hr;
  1195. //
  1196. // if the source guid doesn't exist then we need to register a new
  1197. // source for the SMTP source type and add directory drop as a binding
  1198. //
  1199. if (hr == S_FALSE)
  1200. {
  1201. // register the SMTPSvc source
  1202. hr = pEventSources->Add(bstrSourceGUID, &pEventSource);
  1203. if (FAILED(hr))
  1204. return hr;
  1205. char szSourceDisplayName[50];
  1206. _snprintf(szSourceDisplayName, 50, "smtpsvc %lu", dwInstanceID);
  1207. CComBSTR bstrSourceDisplayName = szSourceDisplayName;
  1208. hr = pEventSource->put_DisplayName(bstrSourceDisplayName);
  1209. if (FAILED(hr))
  1210. return hr;
  1211. // create the event database for this source
  1212. CComPtr<IEventDatabaseManager> pDatabaseManager;
  1213. hr = CoCreateInstance(CLSID_CEventMetabaseDatabaseManager, NULL, CLSCTX_ALL,
  1214. IID_IEventDatabaseManager, (LPVOID *) &pDatabaseManager);
  1215. if (hr != S_OK)
  1216. return hr;
  1217. CComBSTR bstrEventPath;
  1218. CComBSTR bstrService = "smtpsvc";
  1219. hr = pDatabaseManager->MakeVServerPath(bstrService, dwInstanceID, &bstrEventPath);
  1220. if (FAILED(hr))
  1221. return hr;
  1222. CComPtr<IUnknown> pDatabaseMoniker;
  1223. hr = pDatabaseManager->CreateDatabase(bstrEventPath, &pDatabaseMoniker);
  1224. if (FAILED(hr))
  1225. return hr;
  1226. hr = pEventSource->put_BindingManagerMoniker(pDatabaseMoniker);
  1227. if (FAILED(hr))
  1228. return hr;
  1229. // save everything we've done so far
  1230. hr = pEventSource->Save();
  1231. if (FAILED(hr))
  1232. return hr;
  1233. hr = pSourceType->Save();
  1234. if (FAILED(hr))
  1235. return hr;
  1236. }
  1237. return S_OK;
  1238. }
  1239. //
  1240. // this function performs instance level unregistration
  1241. //
  1242. HRESULT UnregisterPlatSEOInstance(DWORD dwInstanceID)
  1243. {
  1244. HRESULT hr = S_OK;
  1245. //
  1246. // find the SMTP source type in the event manager
  1247. //
  1248. CComPtr<IEventManager> pEventManager;
  1249. hr = CoCreateInstance(CLSID_CEventManager, NULL, CLSCTX_ALL,
  1250. IID_IEventManager, (LPVOID *) &pEventManager);
  1251. if (hr != S_OK)
  1252. return hr;
  1253. CComPtr<IEventSourceTypes> pSourceTypes;
  1254. hr = pEventManager->get_SourceTypes(&pSourceTypes);
  1255. if (FAILED(hr))
  1256. return hr;
  1257. CComPtr<IEventSourceType> pSourceType;
  1258. CComBSTR bstrSourceTypeGUID = (LPCOLESTR) CStringGUID(GUID_SMTP_SOURCE_TYPE);
  1259. hr = pSourceTypes->Item(&CComVariant(bstrSourceTypeGUID), &pSourceType);
  1260. _ASSERT(hr != S_OK || pSourceType != NULL);
  1261. if (hr != S_OK)
  1262. return hr;
  1263. //
  1264. // generate a GUID for this source, which is based on GUID_SMTPSVC
  1265. // mangled by the instance ID
  1266. //
  1267. CComPtr<IEventUtil> pEventUtil;
  1268. hr = CoCreateInstance(CLSID_CEventUtil, NULL, CLSCTX_ALL,
  1269. IID_IEventUtil, (LPVOID *) &pEventUtil);
  1270. if (hr != S_OK)
  1271. return hr;
  1272. CComBSTR bstrSMTPSvcGUID = (LPCOLESTR) CStringGUID(GUID_SMTPSVC_SOURCE);
  1273. CComBSTR bstrSourceGUID;
  1274. hr = pEventUtil->GetIndexedGUID(bstrSMTPSvcGUID, dwInstanceID, &bstrSourceGUID);
  1275. if (FAILED(hr))
  1276. return hr;
  1277. //
  1278. // remove this source from the list of registered sources
  1279. //
  1280. CComPtr<IEventSources> pEventSources;
  1281. hr = pSourceType->get_Sources(&pEventSources);
  1282. if (FAILED(hr))
  1283. return hr;
  1284. CComPtr<IEventSource> pEventSource;
  1285. hr = pEventSources->Remove(&CComVariant(bstrSourceGUID));
  1286. if (FAILED(hr))
  1287. return hr;
  1288. return S_OK;
  1289. }
  1290. //+------------------------------------------------------------
  1291. //
  1292. // Function: CStoreDispatcher::Dispatcher
  1293. //
  1294. // Synopsis: Override the default functionality in seolib.cpp to
  1295. // provide some extra features (default functionality
  1296. //
  1297. // Arguments:
  1298. // rguidEventType: Guid specifying a server event
  1299. // pParams: CStoreBaseParams -- contains async info
  1300. //
  1301. // Returns:
  1302. // S_OK: Success, at least one sink called
  1303. // S_FALSE: No sinks were called
  1304. // otherwise error from CallObject
  1305. //
  1306. // History:
  1307. // jstamerj 980603 19:23:06: Created.
  1308. //
  1309. //-------------------------------------------------------------
  1310. HRESULT STDMETHODCALLTYPE CStoreDispatcher::Dispatcher(
  1311. REFIID rguidEventType,
  1312. CStoreBaseParams *pParams)
  1313. {
  1314. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::Dispatcher");
  1315. _ASSERT(pParams);
  1316. //
  1317. // This code based on %STAXPT%\src\core\seo\lib\seolib.cpp
  1318. //
  1319. HRESULT hrRes = S_OK;
  1320. CETData *petdData;
  1321. BOOL bObjectCalled = (pParams->m_dwIdx_SinkSkip > 0);
  1322. //
  1323. // AddRef pParams here, release at the end of the function
  1324. // This way, if a sink returns MAILTRANSPORT_S_PENDING and does
  1325. // async completion before this function exits, we wont AV
  1326. // accessing pParams
  1327. //
  1328. pParams->AddRef();
  1329. petdData = m_Data.Find(rguidEventType);
  1330. if (pParams->m_dwIdx_SinkSkip != SKIPSINK_CALL_NO_MORE_SINKS) {
  1331. if(petdData) {
  1332. for(DWORD dwIdx = pParams->m_dwIdx_SinkSkip;
  1333. dwIdx < petdData->Count();
  1334. dwIdx++) {
  1335. if(!petdData->Index(dwIdx)->m_bIsValid) {
  1336. continue;
  1337. }
  1338. if(bObjectCalled && petdData->Index(dwIdx)->m_bExclusive) {
  1339. continue;
  1340. }
  1341. if(pParams->Abort() == S_OK) {
  1342. break;
  1343. }
  1344. //
  1345. // Call default processing method if the priority of the sink
  1346. // we're looking at is less than default priority
  1347. //
  1348. if((pParams->m_fDefaultProcessingCalled == FALSE) &&
  1349. (petdData->Index(dwIdx)->m_dwPriority >
  1350. SMTP_TRANSPORT_DEFAULT_PRIORITY)) {
  1351. // This is needed so we don't call the default
  1352. // processing again if the default processing returns
  1353. // MAILTRANSPORT_S_PENDING (and we reenter Dispatcher)
  1354. pParams->m_fDefaultProcessingCalled = TRUE;
  1355. //
  1356. // Set the correct index in our async structure -- our
  1357. // current index.
  1358. //
  1359. pParams->m_dwIdx_SinkSkip = dwIdx;
  1360. hrRes = pParams->CallDefault();
  1361. if((hrRes == MAILTRANSPORT_S_PENDING) ||
  1362. (hrRes == S_FALSE)) {
  1363. break;
  1364. }
  1365. }
  1366. //
  1367. // Now proceed with calling a real sink
  1368. //
  1369. hrRes = pParams->CheckRule(*petdData->Index(dwIdx));
  1370. if(hrRes == S_OK) {
  1371. if(pParams->Abort() == S_OK) {
  1372. break;
  1373. }
  1374. //
  1375. // jstamerj 980603 19:37:17: Set the correct index in our
  1376. // async structure -- this index plus one to skip the
  1377. // sink we are about to call
  1378. //
  1379. pParams->m_dwIdx_SinkSkip = dwIdx+1;
  1380. hrRes = pParams->CallObject(
  1381. m_piEventManager,
  1382. *petdData->Index(dwIdx));
  1383. if(!SUCCEEDED(hrRes)) {
  1384. continue;
  1385. }
  1386. bObjectCalled = TRUE;
  1387. if((hrRes == MAILTRANSPORT_S_PENDING) ||
  1388. (hrRes == S_FALSE) ||
  1389. (petdData->Index(dwIdx)->m_bExclusive)) {
  1390. break;
  1391. }
  1392. }
  1393. }
  1394. }
  1395. //
  1396. // It is possible we haven't called our default processing sink
  1397. // yet. Check for this case here. Make sure that a sink above in
  1398. // the loop isn't indicating async completion or skip (PENDING or
  1399. // S_FALSE)
  1400. //
  1401. if((pParams->m_fDefaultProcessingCalled == FALSE) &&
  1402. (hrRes != MAILTRANSPORT_S_PENDING) &&
  1403. (hrRes != S_FALSE)) {
  1404. // Make sure we don't call default again on async completion...
  1405. pParams->m_fDefaultProcessingCalled = TRUE;
  1406. //
  1407. // Set the index in our async structure so we don't reenter
  1408. // the above loop on async completion
  1409. //
  1410. pParams->m_dwIdx_SinkSkip = (petdData ? petdData->Count() : 0);
  1411. hrRes = pParams->CallDefault();
  1412. }
  1413. } else {
  1414. // bObjectCalled should always be set if SKIPSINK_CALL_NO_MORE_SINKS
  1415. // was set
  1416. _ASSERT(bObjectCalled);
  1417. }
  1418. if(hrRes != MAILTRANSPORT_S_PENDING) {
  1419. //
  1420. // It is time to call the completion processing
  1421. //
  1422. hrRes = pParams->CallCompletion(bObjectCalled ? S_OK : S_FALSE);
  1423. if(FAILED(hrRes)) {
  1424. goto CLEANUP;
  1425. }
  1426. hrRes = (bObjectCalled) ? S_OK : S_FALSE;
  1427. }
  1428. CLEANUP:
  1429. pParams->Release();
  1430. DebugTrace((LPARAM)this, "returning hr %08lx", hrRes);
  1431. TraceFunctLeaveEx((LPARAM)this);
  1432. return hrRes;
  1433. }
  1434. //+------------------------------------------------------------
  1435. //
  1436. // Function: CStoreDispatcher::Notify
  1437. //
  1438. // Synopsis: Handles async completions of sinks
  1439. //
  1440. // Arguments: pvContext - context passed into sink
  1441. //
  1442. // Returns:
  1443. // S_OK: Success
  1444. // E_INVALIDARG:
  1445. //
  1446. // History:
  1447. // jstamerj 980608 15:50:57: Created.
  1448. //
  1449. //-------------------------------------------------------------
  1450. HRESULT STDMETHODCALLTYPE CStoreDispatcher::Notify(
  1451. HRESULT hrStatus,
  1452. PVOID pvContext)
  1453. {
  1454. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::Notify");
  1455. _ASSERT(pvContext);
  1456. if((pvContext == NULL) ||
  1457. IsBadReadPtr(
  1458. pvContext,
  1459. sizeof(CStoreBaseParams))) {
  1460. ErrorTrace((LPARAM)this, "Sink called Notify with bogus pvContext");
  1461. return E_INVALIDARG;
  1462. }
  1463. CStoreBaseParams *pParams = (CStoreBaseParams *)pvContext;
  1464. if(FAILED(pParams->CheckSignature())) {
  1465. ErrorTrace((LPARAM)this, "Sink called Notify with invalid pvContext");
  1466. return E_INVALIDARG;
  1467. }
  1468. //
  1469. // Release the sink that called us
  1470. // m_pIUnknownSink could be NULL if default processing returned pending
  1471. //
  1472. if(pParams->m_pIUnknownSink) {
  1473. pParams->m_pIUnknownSink->Release();
  1474. pParams->m_pIUnknownSink = NULL;
  1475. }
  1476. if (hrStatus == S_FALSE) {
  1477. // prevent the dispatcher from calling any more sinks.
  1478. pParams->m_dwIdx_SinkSkip = SKIPSINK_CALL_NO_MORE_SINKS;
  1479. }
  1480. Dispatcher(pParams->m_rguidEventType, pParams);
  1481. TraceFunctLeaveEx((LPARAM)this);
  1482. return S_OK;
  1483. }
  1484. //+------------------------------------------------------------
  1485. //
  1486. // Function: CStoreDispatcher::CStoreBaseParams::Notify
  1487. //
  1488. // Synopsis: Handles async completions of sinks using mailmsg notify
  1489. //
  1490. // Arguments: hrStatus - hresult from async operation
  1491. //
  1492. // Returns:
  1493. // S_OK: Success
  1494. // E_INVALIDARG:
  1495. //
  1496. // History:
  1497. // jstamerj 980608 15:50:57: Created.
  1498. //
  1499. //-------------------------------------------------------------
  1500. HRESULT STDMETHODCALLTYPE CStoreDispatcher::CStoreParams::Notify(
  1501. HRESULT hrStatus)
  1502. {
  1503. TraceFunctEnter("CStoreDispatcher::CStoreBaseParams::Notify");
  1504. //
  1505. // Release the sink that called us
  1506. // m_pIUnknownSink could be NULL if default processing returned pending
  1507. //
  1508. if(m_pIUnknownSink) {
  1509. m_pIUnknownSink->Release();
  1510. m_pIUnknownSink = NULL;
  1511. }
  1512. // this guy can either be STOREDRV_E_RETRY or S_OK. If he was ever
  1513. // set to STOREDRV_E_RETRY then we shouldn't be getting back to this
  1514. // point in the code because we never would have called another sink
  1515. _ASSERT(m_pContext->hr == S_OK);
  1516. if (hrStatus == STOREDRV_E_RETRY) {
  1517. DebugTrace((LPARAM)this, "Sink returned STOREDRV_E_RETRY on LocalDelivery");
  1518. m_pContext->hr = hrStatus;
  1519. hrStatus = S_FALSE;
  1520. }
  1521. if (hrStatus == S_FALSE) {
  1522. // prevent the dispatcher from calling any more sinks.
  1523. m_dwIdx_SinkSkip = SKIPSINK_CALL_NO_MORE_SINKS;
  1524. }
  1525. m_pDispatcher->Dispatcher(m_rguidEventType, this);
  1526. TraceFunctLeaveEx((LPARAM)this);
  1527. return S_OK;
  1528. }
  1529. //
  1530. // CMailTransportSubmissionParams:
  1531. //
  1532. //+------------------------------------------------------------
  1533. //
  1534. // Function: CStoreDispatcher::CMailTransportSubmissionParams::CallObject
  1535. //
  1536. // Synopsis: Create and call the child object
  1537. //
  1538. // Arguments:
  1539. // CBinding
  1540. // punkObject
  1541. //
  1542. // Returns:
  1543. // S_OK: Success
  1544. //
  1545. // History:
  1546. // jstamerj 980610 19:04:59: Created.
  1547. //
  1548. //-------------------------------------------------------------
  1549. HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallObject(
  1550. CBinding& bBinding,
  1551. IUnknown *punkObject)
  1552. {
  1553. HRESULT hrRes = S_OK;
  1554. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportSubmissionParams::CallObject");
  1555. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_SUBMISSION_EVENT);
  1556. IMailTransportSubmission *pSink;
  1557. hrRes = punkObject->QueryInterface(IID_IMailTransportSubmission,
  1558. (PVOID *)&pSink);
  1559. if(hrRes == E_NOINTERFACE) {
  1560. //
  1561. // See if we can get the interfaces we need for a CDO sink
  1562. //
  1563. hrRes = CallCDOSink(punkObject);
  1564. //
  1565. // Success or failure, return here
  1566. //
  1567. TraceFunctLeaveEx((LPARAM)this);
  1568. return hrRes;
  1569. } else if(FAILED(hrRes)) {
  1570. TraceFunctLeaveEx((LPARAM)this);
  1571. return(hrRes);
  1572. }
  1573. //
  1574. // Remember the sink so we can release this sink later if it
  1575. // returns pending
  1576. //
  1577. _ASSERT(m_pIUnknownSink == NULL);
  1578. m_pIUnknownSink = (IUnknown*)pSink;
  1579. m_pIUnknownSink->AddRef();
  1580. DebugTrace((LPARAM)this, "Calling submission event on this sink");
  1581. hrRes = pSink->OnMessageSubmission(
  1582. m_Context.pIMailMsgProperties,
  1583. m_pINotify,
  1584. (PVOID)this);
  1585. //
  1586. // We are done with pSink so release it
  1587. // In case of async completion, we hold a reference to the sink in
  1588. // m_pIUnknownSink
  1589. //
  1590. pSink->Release();
  1591. if(hrRes != MAILTRANSPORT_S_PENDING) {
  1592. //
  1593. // We completed synchronously, so release the sink
  1594. //
  1595. m_pIUnknownSink->Release();
  1596. m_pIUnknownSink = NULL;
  1597. }
  1598. TraceFunctLeaveEx((LPARAM)this);
  1599. return(hrRes);
  1600. }
  1601. //+------------------------------------------------------------
  1602. //
  1603. // Function: CStoreDispatcher::CMailTransportSubmissionParams::CallCDOSink
  1604. //
  1605. // Synopsis: Call the CDO Sink
  1606. //
  1607. // Arguments:
  1608. // pSink: IUnknown of the sink
  1609. //
  1610. // Returns:
  1611. // S_OK: Success
  1612. //
  1613. // History:
  1614. // jstamerj 1998/07/02 10:31:47: Created.
  1615. //
  1616. //-------------------------------------------------------------
  1617. HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallCDOSink(
  1618. IUnknown *pSink)
  1619. {
  1620. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportSubmissionParams::CallCDOSink");
  1621. _ASSERT(pSink);
  1622. HRESULT hr;
  1623. ISMTPOnArrival *pCDOSink = NULL;
  1624. IConstructIMessageFromIMailMsg *pIConstruct = NULL;
  1625. CdoEventStatus eStatus = cdoRunNextSink;
  1626. hr = pSink->QueryInterface(IID_ISMTPOnArrival,
  1627. (PVOID *)&pCDOSink);
  1628. if(FAILED(hr))
  1629. goto CLEANUP;
  1630. if(m_pCDOMessage == NULL) {
  1631. //
  1632. // Yay. Create a CDO message
  1633. //
  1634. hr = CoCreateInstance(
  1635. CLSID_Message,
  1636. NULL,
  1637. CLSCTX_INPROC_SERVER,
  1638. IID_IMessage,
  1639. (LPVOID *)&m_pCDOMessage);
  1640. if(FAILED(hr))
  1641. goto CLEANUP;
  1642. //
  1643. // Fill in properties based on MailMsg
  1644. //
  1645. hr = m_pCDOMessage->QueryInterface(
  1646. IID_IConstructIMessageFromIMailMsg,
  1647. (LPVOID *)&pIConstruct);
  1648. if(FAILED(hr)) {
  1649. m_pCDOMessage->Release();
  1650. m_pCDOMessage = NULL;
  1651. goto CLEANUP;
  1652. }
  1653. hr = pIConstruct->Construct(
  1654. cdoSMTPOnArrival,
  1655. m_Context.pIMailMsgProperties);
  1656. if(FAILED(hr)) {
  1657. m_pCDOMessage->Release();
  1658. m_pCDOMessage = NULL;
  1659. goto CLEANUP;
  1660. }
  1661. }
  1662. //
  1663. // Call the sink
  1664. //
  1665. hr = pCDOSink->OnArrival(
  1666. m_pCDOMessage,
  1667. &eStatus);
  1668. CLEANUP:
  1669. //
  1670. // Release interfaces
  1671. //
  1672. if(pIConstruct)
  1673. pIConstruct->Release();
  1674. if(pCDOSink)
  1675. pCDOSink->Release();
  1676. DebugTrace((LPARAM)this, "CallCDOSink returning hr %08lx eStatus %d", hr, eStatus);
  1677. TraceFunctLeaveEx((LPARAM)this);
  1678. return FAILED(hr) ? hr :
  1679. ((eStatus == cdoSkipRemainingSinks) ? S_FALSE : S_OK);
  1680. }
  1681. //+------------------------------------------------------------
  1682. //
  1683. // Function: CStoreDispatcher::CMailTransportSubmissionParams
  1684. //
  1685. // Synopsis: The dispatcher will call this routine when it the default
  1686. // sink processing priority is reached
  1687. //
  1688. // Arguments: NONE
  1689. //
  1690. // Returns:
  1691. // S_OK: Success, continueing calling sinks
  1692. // S_FALSE: Stop calling sinks
  1693. // MAILTRANSPORT_S_PENDING: Will call IMailTransportNotify::Notify
  1694. // when we are done.
  1695. //
  1696. // History:
  1697. // jstamerj 980611 14:15:43: Created.
  1698. //
  1699. //-------------------------------------------------------------
  1700. HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallDefault()
  1701. {
  1702. //
  1703. // No sinks need default processing yet..
  1704. //
  1705. return S_OK;
  1706. }
  1707. //+------------------------------------------------------------
  1708. //
  1709. // Function: CStoreDriver::CMailTransportSubmissionParams::CallCompletion
  1710. //
  1711. // Synopsis: The dispatcher will call this routine after all sinks
  1712. // have been called
  1713. //
  1714. // Arguments:
  1715. // hrStatus: Status server event sinks have returned
  1716. //
  1717. // Returns:
  1718. // S_OK: Success
  1719. //
  1720. // History:
  1721. // jstamerj 980611 14:17:51: Created.
  1722. //
  1723. //-------------------------------------------------------------
  1724. HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CallCompletion(
  1725. HRESULT hrStatus)
  1726. {
  1727. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_SUBMISSION_EVENT);
  1728. (*m_Context.pfnCompletion)(hrStatus, &m_Context);
  1729. CStoreBaseParams::CallCompletion(hrStatus);
  1730. return S_OK;
  1731. }
  1732. //+------------------------------------------------------------
  1733. //
  1734. // Function: CStoreDispatcher::CMailTransportSubmissionParams::CheckRule
  1735. //
  1736. // Synopsis: Check to see if this sink should be called or not
  1737. //
  1738. // Arguments:
  1739. // bBinding: CBinding object for this sink
  1740. //
  1741. // Returns:
  1742. // S_OK: Success, call the sink
  1743. // S_FALSE: Success, do not call the sink
  1744. // or error from mailmsg (sink will not be called)
  1745. //
  1746. // History:
  1747. // jstamerj 1999/01/12 16:55:29: Created.
  1748. //
  1749. //-------------------------------------------------------------
  1750. HRESULT CStoreDispatcher::CMailTransportSubmissionParams::CheckRule(
  1751. CBinding &bBinding)
  1752. {
  1753. HRESULT hr;
  1754. TraceFunctEnterEx((LPARAM)this,
  1755. "CStoreDispatcher::CMailTransportSubmissionParams::CheckRule");
  1756. //
  1757. // Call the generic function to check a mailmsg rule
  1758. //
  1759. hr = CheckMailMsgRule(
  1760. &bBinding,
  1761. m_Context.pIMailMsgProperties);
  1762. DebugTrace((LPARAM)this, "returning hr %08lx", hr);
  1763. TraceFunctLeaveEx((LPARAM)this);
  1764. return hr;
  1765. }
  1766. //
  1767. // CMailTransportPreCategorizeParams:
  1768. //
  1769. //+------------------------------------------------------------
  1770. //
  1771. // Function: CStoreDispatcher::CMailTransportPreCategorizeParams::CallObject
  1772. //
  1773. // Synopsis: Create and call the child object
  1774. //
  1775. // Arguments:
  1776. // CBinding
  1777. // punkObject
  1778. //
  1779. // Returns:
  1780. // S_OK: Success
  1781. //
  1782. // History:
  1783. // jstamerj 980610 19:04:59: Created.
  1784. //
  1785. //-------------------------------------------------------------
  1786. HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CallObject(
  1787. CBinding& bBinding,
  1788. IUnknown *punkObject)
  1789. {
  1790. HRESULT hrRes = S_OK;
  1791. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportPreCategorizeParams::CallObject");
  1792. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT);
  1793. IMailTransportOnPreCategorize *pSink;
  1794. hrRes = punkObject->QueryInterface(IID_IMailTransportOnPreCategorize,
  1795. (PVOID *)&pSink);
  1796. if(FAILED(hrRes))
  1797. return(hrRes);
  1798. //
  1799. // Remember the sink so we can release this sink later if it
  1800. // returns pending
  1801. //
  1802. _ASSERT(m_pIUnknownSink == NULL);
  1803. m_pIUnknownSink = (IUnknown*)pSink;
  1804. m_pIUnknownSink->AddRef();
  1805. DebugTrace((LPARAM)this, "Calling precategorize event on this sink");
  1806. hrRes = pSink->OnSyncMessagePreCategorize(
  1807. m_Context.pIMailMsgProperties,
  1808. m_pINotify,
  1809. (PVOID)this);
  1810. //
  1811. // We are done with pSink so release it
  1812. // In case of async completion, we hold a reference to the sink in
  1813. // m_pIUnknownSink
  1814. //
  1815. pSink->Release();
  1816. if(hrRes != MAILTRANSPORT_S_PENDING) {
  1817. //
  1818. // We completed synchronously, so release the sink
  1819. //
  1820. m_pIUnknownSink->Release();
  1821. m_pIUnknownSink = NULL;
  1822. }
  1823. TraceFunctLeaveEx((LPARAM)this);
  1824. return(hrRes);
  1825. }
  1826. //+------------------------------------------------------------
  1827. //
  1828. // Function: CStoreDispatcher::CMailTransportPreCategorizeParams
  1829. //
  1830. // Synopsis: The dispatcher will call this routine when it the default
  1831. // sink processing priority is reached
  1832. //
  1833. // Arguments: NONE
  1834. //
  1835. // Returns:
  1836. // S_OK: Success, continueing calling sinks
  1837. // S_FALSE: Stop calling sinks
  1838. // MAILTRANSPORT_S_PENDING: Will call IMailTransportNotify::Notify
  1839. // when we are done.
  1840. //
  1841. // History:
  1842. // jstamerj 980611 14:15:43: Created.
  1843. //
  1844. //-------------------------------------------------------------
  1845. HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CallDefault()
  1846. {
  1847. //
  1848. // No sinks need default processing yet..
  1849. //
  1850. return S_OK;
  1851. }
  1852. //+------------------------------------------------------------
  1853. //
  1854. // Function: CStoreDriver::CMailTransportPreCategorizeParams::CallCompletion
  1855. //
  1856. // Synopsis: The dispatcher will call this routine after all sinks
  1857. // have been called
  1858. //
  1859. // Arguments:
  1860. // hrStatus: Status server event sinks have returned
  1861. //
  1862. // Returns:
  1863. // S_OK: Success
  1864. //
  1865. // History:
  1866. // jstamerj 980611 14:17:51: Created.
  1867. //
  1868. //-------------------------------------------------------------
  1869. HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CallCompletion(
  1870. HRESULT hrStatus)
  1871. {
  1872. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_PRECATEGORIZE_EVENT);
  1873. (*m_Context.pfnCompletion)(hrStatus, &m_Context);
  1874. CStoreBaseParams::CallCompletion(hrStatus);
  1875. return S_OK;
  1876. }
  1877. //+------------------------------------------------------------
  1878. //
  1879. // Function: CStoreDispatcher::CMailTransportPreCategorizeParams::CheckRule
  1880. //
  1881. // Synopsis: Check to see if this sink should be called or not
  1882. //
  1883. // Arguments:
  1884. // bBinding: CBinding object for this sink
  1885. //
  1886. // Returns:
  1887. // S_OK: Success, call the sink
  1888. // S_FALSE: Success, do not call the sink
  1889. // or error from mailmsg (sink will not be called)
  1890. //
  1891. // History:
  1892. // jstamerj 1999/01/12 16:59:59: Created
  1893. //
  1894. //-------------------------------------------------------------
  1895. HRESULT CStoreDispatcher::CMailTransportPreCategorizeParams::CheckRule(
  1896. CBinding &bBinding)
  1897. {
  1898. HRESULT hr;
  1899. TraceFunctEnterEx((LPARAM)this,
  1900. "CStoreDispatcher::CMailTransportPreCategorizeParams::CheckRule");
  1901. //
  1902. // Call the generic function to check a mailmsg rule
  1903. //
  1904. hr = CheckMailMsgRule(
  1905. &bBinding,
  1906. m_Context.pIMailMsgProperties);
  1907. DebugTrace((LPARAM)this, "returning hr %08lx", hr);
  1908. TraceFunctLeaveEx((LPARAM)this);
  1909. return hr;
  1910. }
  1911. //
  1912. // CMailTransportPostCategorizeParams:
  1913. //
  1914. //+------------------------------------------------------------
  1915. //
  1916. // Function: CStoreDispatcher::CMailTransportPostCategorizeParams::CallObject
  1917. //
  1918. // Synopsis: Create and call the child object
  1919. //
  1920. // Arguments:
  1921. // CBinding
  1922. // punkObject
  1923. //
  1924. // Returns:
  1925. // S_OK: Success
  1926. //
  1927. // History:
  1928. // jstamerj 980610 19:04:59: Created.
  1929. //
  1930. //-------------------------------------------------------------
  1931. HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CallObject(
  1932. CBinding& bBinding,
  1933. IUnknown *punkObject)
  1934. {
  1935. HRESULT hrRes = S_OK;
  1936. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportPostCategorizeParams::CallObject");
  1937. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT);
  1938. IMailTransportOnPostCategorize *pSink;
  1939. hrRes = punkObject->QueryInterface(IID_IMailTransportOnPostCategorize,
  1940. (PVOID *)&pSink);
  1941. if(FAILED(hrRes))
  1942. return(hrRes);
  1943. //
  1944. // Remember the sink so we can release this sink later if it
  1945. // returns pending
  1946. //
  1947. _ASSERT(m_pIUnknownSink == NULL);
  1948. m_pIUnknownSink = (IUnknown*)pSink;
  1949. m_pIUnknownSink->AddRef();
  1950. DebugTrace((LPARAM)this, "Calling submission event on this sink");
  1951. hrRes = pSink->OnMessagePostCategorize(
  1952. m_Context.pIMailMsgProperties,
  1953. m_pINotify,
  1954. (PVOID)this);
  1955. //
  1956. // We are done with pSink so release it
  1957. // In case of async completion, we hold a reference to the sink in
  1958. // m_pIUnknownSink
  1959. //
  1960. pSink->Release();
  1961. if(hrRes != MAILTRANSPORT_S_PENDING) {
  1962. //
  1963. // We completed synchronously, so release the sink
  1964. //
  1965. m_pIUnknownSink->Release();
  1966. m_pIUnknownSink = NULL;
  1967. }
  1968. TraceFunctLeaveEx((LPARAM)this);
  1969. return(hrRes);
  1970. }
  1971. //+------------------------------------------------------------
  1972. //
  1973. // Function: CStoreDispatcher::CMailTransportPostCategorizeParams
  1974. //
  1975. // Synopsis: The dispatcher will call this routine when it the default
  1976. // sink processing priority is reached
  1977. //
  1978. // Arguments: NONE
  1979. //
  1980. // Returns:
  1981. // S_OK: Success, continueing calling sinks
  1982. // S_FALSE: Stop calling sinks
  1983. // MAILTRANSPORT_S_PENDING: Will call IMailTransportNotify::Notify
  1984. // when we are done.
  1985. //
  1986. // History:
  1987. // jstamerj 980611 14:15:43: Created.
  1988. //
  1989. //-------------------------------------------------------------
  1990. HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CallDefault()
  1991. {
  1992. //
  1993. // No sinks need default processing yet..
  1994. //
  1995. return S_OK;
  1996. }
  1997. //+------------------------------------------------------------
  1998. //
  1999. // Function: CStoreDriver::CMailTransportPostCategorizeParams::CallCompletion
  2000. //
  2001. // Synopsis: The dispatcher will call this routine after all sinks
  2002. // have been called
  2003. //
  2004. // Arguments:
  2005. // hrStatus: Status server event sinks have returned
  2006. //
  2007. // Returns:
  2008. // S_OK: Success
  2009. //
  2010. // History:
  2011. // jstamerj 980611 14:17:51: Created.
  2012. //
  2013. //-------------------------------------------------------------
  2014. HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CallCompletion(
  2015. HRESULT hrStatus)
  2016. {
  2017. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_POSTCATEGORIZE_EVENT);
  2018. (*m_Context.pfnCompletion)(hrStatus, &m_Context);
  2019. CStoreBaseParams::CallCompletion(hrStatus);
  2020. return S_OK;
  2021. }
  2022. //+------------------------------------------------------------
  2023. //
  2024. // Function: CStoreDispatcher::CMailTransportPostCategorizeParams::CheckRule
  2025. //
  2026. // Synopsis: Check to see if this sink should be called or not
  2027. //
  2028. // Arguments:
  2029. // bBinding: CBinding object for this sink
  2030. //
  2031. // Returns:
  2032. // S_OK: Success, call the sink
  2033. // S_FALSE: Success, do not call the sink
  2034. // or error from mailmsg (sink will not be called)
  2035. //
  2036. // History:
  2037. // jstamerj 1999/01/12 17:01:40: Created
  2038. //
  2039. //-------------------------------------------------------------
  2040. HRESULT CStoreDispatcher::CMailTransportPostCategorizeParams::CheckRule(
  2041. CBinding &bBinding)
  2042. {
  2043. HRESULT hr;
  2044. TraceFunctEnterEx((LPARAM)this,
  2045. "CStoreDispatcher::CMailTransportPostCategorizeParams::CheckRule");
  2046. //
  2047. // Call the generic function to check a mailmsg rule
  2048. //
  2049. hr = CheckMailMsgRule(
  2050. &bBinding,
  2051. m_Context.pIMailMsgProperties);
  2052. DebugTrace((LPARAM)this, "returning hr %08lx", hr);
  2053. TraceFunctLeaveEx((LPARAM)this);
  2054. return hr;
  2055. }
  2056. //+------------------------------------------------------------
  2057. //
  2058. // Function: CStoreDispatcher::CRouterCreateOptions::Init
  2059. //
  2060. // Synopsis: This is called right after we CoCreate any routing sink
  2061. // -- so call routing's initialize function (RegisterRouterReset)
  2062. //
  2063. // Arguments:
  2064. // iidDesired: not used
  2065. // ppUnkObject: IUnknown of newly created sink object
  2066. // IEventBinding: not used
  2067. // IUnknown: not used
  2068. //
  2069. // Returns:
  2070. // E_NOTIMPL: Success, please do the regular Init thing
  2071. // otherwise error from QI or sink function
  2072. //
  2073. // History:
  2074. // jstamerj 1998/07/10 18:09:04: Created.
  2075. //
  2076. //-------------------------------------------------------------
  2077. HRESULT STDMETHODCALLTYPE CStoreDispatcher::CRouterCreateOptions::Init(
  2078. REFIID iidDesired,
  2079. IUnknown **ppUnkObject,
  2080. IEventBinding *,
  2081. IUnknown *)
  2082. {
  2083. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CRouterCreateOptions::Init");
  2084. IMailTransportSetRouterReset *pSink = NULL;
  2085. HRESULT hr;
  2086. hr = (*ppUnkObject)->QueryInterface(
  2087. IID_IMailTransportSetRouterReset,
  2088. (PVOID *)&pSink);
  2089. if(hr == E_NOINTERFACE) {
  2090. //
  2091. // It's okay; this sink just doesn't care about hooking
  2092. // the router reset interface
  2093. //
  2094. DebugTrace((LPARAM)this, "Router sink doesn't support IMailTransportSetRouterReset");
  2095. TraceFunctLeaveEx((LPARAM)this);
  2096. return E_NOTIMPL;
  2097. } else if(FAILED(hr)) {
  2098. ErrorTrace((LPARAM)this,
  2099. "QI for IMailTransportSetRouterReset failed with hr %08lx", hr);
  2100. TraceFunctLeaveEx((LPARAM)this);
  2101. return hr;
  2102. }
  2103. DebugTrace((LPARAM)this, "Calling RegisterRouterReset event onSink");
  2104. hr = pSink->RegisterResetInterface(
  2105. m_pContext->dwVirtualServerID,
  2106. m_pContext->pIRouterReset);
  2107. pSink->Release();
  2108. if(FAILED(hr) && (hr != E_NOTIMPL)) {
  2109. //
  2110. // A real failure occured
  2111. //
  2112. ErrorTrace((LPARAM)this, "RegisterResetInterface failed with hr %08lx", hr);
  2113. return hr;
  2114. }
  2115. //
  2116. // Return E_NOTIMPL so the real work of Init will be done
  2117. //
  2118. return E_NOTIMPL;
  2119. }
  2120. //
  2121. // CMailTransportRoutingParams:
  2122. //
  2123. //+------------------------------------------------------------
  2124. //
  2125. // Function: CStoreDispatcher::CMailTransportRouterParams::CallObject
  2126. //
  2127. // Synopsis: Creates (if necessary) and calls the sink object
  2128. //
  2129. // Arguments:
  2130. // pManager: IEventManager passed in from dispatcher
  2131. // bBinding: CBinding for this event
  2132. //
  2133. // Returns:
  2134. // S_OK: Success
  2135. // E_POINTER: bad pManager
  2136. // or error from CreateSink/CallObject
  2137. //
  2138. // History:
  2139. // jstamerj 1998/07/10 18:15:09: Created.
  2140. //
  2141. //-------------------------------------------------------------
  2142. //
  2143. // create and call the child object
  2144. //
  2145. HRESULT CStoreDispatcher::CMailTransportRouterParams::CallObject(
  2146. IEventManager *pManager,
  2147. CBinding& bBinding)
  2148. {
  2149. CRouterCreateOptions opt (m_pContext);
  2150. CComPtr<IUnknown> pUnkSink;
  2151. HRESULT hr;
  2152. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportRotuerParams::CallObject");
  2153. if (pManager == NULL) {
  2154. ErrorTrace((LPARAM)this, "Invalid (NULL) pManager");
  2155. TraceFunctLeaveEx((LPARAM)this);
  2156. return (E_POINTER);
  2157. }
  2158. hr = pManager->CreateSink(bBinding.m_piBinding,&opt,&pUnkSink);
  2159. if (FAILED(hr)) {
  2160. ErrorTrace((LPARAM)this, "CreateSink returned error hr %08lx",
  2161. hr);
  2162. TraceFunctLeaveEx((LPARAM)this);
  2163. return hr;
  2164. }
  2165. hr = CallObject(bBinding,pUnkSink);
  2166. DebugTrace((LPARAM)this, "CallObject child returned error %08lx", hr);
  2167. TraceFunctLeaveEx((LPARAM)this);
  2168. return hr;
  2169. }
  2170. //+------------------------------------------------------------
  2171. //
  2172. // Function: CStoreDispatcher::CMailTransportRoutingParams::CallObject
  2173. //
  2174. // Synopsis: Create and call the child object
  2175. //
  2176. // Arguments:
  2177. // CBinding
  2178. // punkObject
  2179. //
  2180. // Returns:
  2181. // Error from QI or return code from sink function
  2182. //
  2183. // History:
  2184. // jstamerj 980610 19:04:59: Created.
  2185. //
  2186. //-------------------------------------------------------------
  2187. HRESULT CStoreDispatcher::CMailTransportRouterParams::CallObject(
  2188. CBinding& bBinding,
  2189. IUnknown *punkObject)
  2190. {
  2191. HRESULT hrRes = S_OK;
  2192. IMailTransportRoutingEngine *pSink;
  2193. IMessageRouter *pIMessageRouterNew = NULL;
  2194. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportRouterParams::CallObject");
  2195. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT);
  2196. //
  2197. // If they pass in a pIMailMsgProperties of NULL it means that they
  2198. // just want to create a router object, but not actually do the
  2199. // get message router call.
  2200. //
  2201. if (m_pContext->pIMailMsgProperties == NULL) {
  2202. DebugTrace((LPARAM) this, "Skipping GetMessageRouter call");
  2203. TraceFunctLeaveEx((LPARAM)this);
  2204. return S_OK;
  2205. }
  2206. hrRes = punkObject->QueryInterface(IID_IMailTransportRoutingEngine,
  2207. (PVOID *)&pSink);
  2208. if(FAILED(hrRes))
  2209. return(hrRes);
  2210. DebugTrace((LPARAM)this, "Calling GetMessageRouter event on this sink");
  2211. hrRes = pSink->GetMessageRouter(
  2212. m_pContext->pIMailMsgProperties,
  2213. m_pContext->pIMessageRouter,
  2214. &(pIMessageRouterNew));
  2215. //
  2216. // This sink is not allowed to complete async
  2217. //
  2218. _ASSERT(hrRes != MAILTRANSPORT_S_PENDING);
  2219. //
  2220. // We are done with pSink so release it
  2221. //
  2222. pSink->Release();
  2223. //
  2224. // If GetMessageRouter succeeded AND it returned a new
  2225. // IMessageRouter, release the old one and save the new one.
  2226. //
  2227. if(SUCCEEDED(hrRes) && (pIMessageRouterNew != NULL)) {
  2228. if(m_pContext->pIMessageRouter) {
  2229. m_pContext->pIMessageRouter->Release();
  2230. }
  2231. m_pContext->pIMessageRouter = pIMessageRouterNew;
  2232. }
  2233. DebugTrace((LPARAM)this, "Sink GetMessageRouter returned hr %08lx", hrRes);
  2234. TraceFunctLeaveEx((LPARAM)this);
  2235. return(hrRes);
  2236. }
  2237. //+------------------------------------------------------------
  2238. //
  2239. // Function: CStoreDispatcher::CMailTransportRouterParams
  2240. //
  2241. // Synopsis: The dispatcher will call this routine when it the default
  2242. // sink processing priority is reached
  2243. //
  2244. // Arguments: NONE
  2245. //
  2246. // Returns:
  2247. // S_OK: Success, continueing calling sinks
  2248. // S_FALSE: Stop calling sinks
  2249. //
  2250. // History:
  2251. // jstamerj 980611 14:15:43: Created.
  2252. //
  2253. //-------------------------------------------------------------
  2254. HRESULT CStoreDispatcher::CMailTransportRouterParams::CallDefault()
  2255. {
  2256. HRESULT hrRes;
  2257. IMessageRouter *pIMessageRouterNew = NULL;
  2258. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CMailTransportRouterParams::CallDefault");
  2259. _ASSERT(m_dwEventType == SMTP_MAILTRANSPORT_GET_ROUTER_FOR_MESSAGE_EVENT);
  2260. if (m_pContext->pIMailMsgProperties == NULL) {
  2261. DebugTrace((LPARAM) this, "Skipping GetMessageRouter call");
  2262. TraceFunctLeaveEx((LPARAM)this);
  2263. return S_OK;
  2264. }
  2265. //
  2266. // Call the default IMailTransportRoutingEngine (CatMsgQueue)
  2267. // just like any other sink except SEO didn't CoCreate it for us
  2268. //
  2269. DebugTrace((LPARAM)this, "Calling GetMessageRouter event on default sink");
  2270. hrRes = m_pContext->pIRoutingEngineDefault->GetMessageRouter(
  2271. m_pContext->pIMailMsgProperties,
  2272. m_pContext->pIMessageRouter,
  2273. &pIMessageRouterNew);
  2274. //
  2275. // This sink is not allowed to complete async
  2276. //
  2277. _ASSERT(hrRes != MAILTRANSPORT_S_PENDING);
  2278. //
  2279. // If GetMessageRouter succeeded AND it returned a new
  2280. // IMessageRouter, release the old one.
  2281. //
  2282. if(SUCCEEDED(hrRes) && (pIMessageRouterNew != NULL)) {
  2283. if(m_pContext->pIMessageRouter) {
  2284. m_pContext->pIMessageRouter->Release();
  2285. }
  2286. m_pContext->pIMessageRouter = pIMessageRouterNew;
  2287. }
  2288. TraceFunctLeaveEx((LPARAM)this);
  2289. DebugTrace((LPARAM)this, "Default processing returned hr %08lx", hrRes);
  2290. TraceFunctLeaveEx((LPARAM)this);
  2291. return hrRes;
  2292. }
  2293. //////////////////////////////////////////////////////////////////////////////
  2294. HRESULT CStoreDispatcher::CMsgTrackLogParams::CallObject(
  2295. CBinding& bBinding,
  2296. IUnknown *punkObject )
  2297. {
  2298. IMsgTrackLog *pSink = NULL;
  2299. HRESULT hr = punkObject->QueryInterface(IID_IMsgTrackLog, (void **)&pSink);
  2300. if( FAILED( hr ) )
  2301. {
  2302. return( hr );
  2303. }
  2304. hr = pSink->OnSyncLogMsgTrackInfo(
  2305. m_pContext->pIServer,
  2306. m_pContext->pIMailMsgProperties,
  2307. m_pContext->pMsgTrackInfo );
  2308. pSink->Release();
  2309. return( hr );
  2310. }
  2311. //////////////////////////////////////////////////////////////////////////////
  2312. HRESULT CStoreDispatcher::CMsgTrackLogParams::CallDefault()
  2313. {
  2314. return S_OK;
  2315. }
  2316. //////////////////////////////////////////////////////////////////////////////
  2317. HRESULT CStoreDispatcher::CDnsResolverRecordParams::CallObject(
  2318. CBinding& bBinding,
  2319. IUnknown *punkObject )
  2320. {
  2321. HRESULT hr = S_OK;
  2322. IDnsInfoSink *pAdvancedSink = NULL;
  2323. IDnsResolverRecordSink *pSink = NULL;
  2324. hr = punkObject->QueryInterface(IID_IDnsInfoSink, (void **)&pAdvancedSink);
  2325. if(hr == S_OK)
  2326. {
  2327. //
  2328. // Use the advanced interface. This extends the functionality
  2329. // of OnSyncGetDnsResolverRecord by adding the option for the
  2330. // sink to return ppDnsServerInfo.
  2331. //
  2332. hr = pAdvancedSink->OnSyncGetDnsInfo(
  2333. m_pContext->pszHostName,
  2334. m_pContext->pszFQDN,
  2335. m_pContext->dwVirtualServerId,
  2336. m_pContext->ppDnsServerInfo,
  2337. m_pContext->ppIDnsResolverRecord);
  2338. pAdvancedSink->Release();
  2339. return hr;
  2340. }
  2341. //
  2342. // If the QI for the IDnsSinkInfo failed, this sink does not support
  2343. // the newer interface. We need to call the older interface.
  2344. //
  2345. hr = punkObject->QueryInterface(IID_IDnsResolverRecordSink, (void **)&pSink);
  2346. if( FAILED( hr ) )
  2347. {
  2348. return( hr );
  2349. }
  2350. hr = pSink->OnSyncGetResolverRecord( m_pContext->pszHostName,
  2351. m_pContext->pszFQDN,
  2352. m_pContext->dwVirtualServerId,
  2353. m_pContext->ppIDnsResolverRecord );
  2354. pSink->Release();
  2355. return( hr );
  2356. }
  2357. //////////////////////////////////////////////////////////////////////////////
  2358. HRESULT CStoreDispatcher::CDnsResolverRecordParams::CallDefault()
  2359. {
  2360. return S_OK;
  2361. }
  2362. //////////////////////////////////////////////////////////////////////////////
  2363. HRESULT CStoreDispatcher::CSmtpMaxMsgSizeParams::CallObject(
  2364. CBinding& bBinding,
  2365. IUnknown *punkObject )
  2366. {
  2367. ISmtpMaxMsgSize *pSink = NULL;
  2368. HRESULT hr = punkObject->QueryInterface(IID_ISmtpMaxMsgSize, (void **)&pSink);
  2369. if( FAILED( hr ) )
  2370. {
  2371. return( hr );
  2372. }
  2373. hr = pSink->OnSyncMaxMsgSize( m_pContext->pIUnknown, m_pContext->pIMailMsg, m_pContext->pfShouldImposeLimit );
  2374. pSink->Release();
  2375. return( hr );
  2376. }
  2377. //////////////////////////////////////////////////////////////////////////////
  2378. HRESULT CStoreDispatcher::CSmtpMaxMsgSizeParams::CallDefault()
  2379. {
  2380. return S_OK;
  2381. }
  2382. //////////////////////////////////////////////////////////////////////////////
  2383. HRESULT CStoreDispatcher::CSmtpLogParams::CallObject(
  2384. CBinding& bBinding,
  2385. IUnknown *punkObject )
  2386. {
  2387. ISmtpLog *pSink = NULL;
  2388. HRESULT hr = punkObject->QueryInterface(IID_ISmtpLog, (void **)&pSink);
  2389. if( FAILED( hr ) )
  2390. {
  2391. return( hr );
  2392. }
  2393. hr = pSink->OnSyncLog(m_pContext->pSmtpEventLogInfo );
  2394. pSink->Release();
  2395. return( hr );
  2396. }
  2397. //////////////////////////////////////////////////////////////////////////////
  2398. HRESULT CStoreDispatcher::CSmtpLogParams::CallDefault()
  2399. {
  2400. HRESULT hrRes = S_OK;
  2401. SMTP_LOG_EVENT_INFO *pLogEventInfo;
  2402. CEventLogWrapper *pEventLog;
  2403. TraceFunctEnterEx((LPARAM)this, "CStoreDispatcher::CSmtpLogParams::CallDefault");
  2404. _ASSERT(m_dwEventType == SMTP_LOG_EVENT);
  2405. if ((m_pContext->pSmtpEventLogInfo == NULL) ||
  2406. (m_pContext->pDefaultEventLogHandler == NULL))
  2407. {
  2408. DebugTrace((LPARAM) this, "Skipping LogEvent call");
  2409. TraceFunctLeaveEx((LPARAM)this);
  2410. return S_OK;
  2411. }
  2412. // Params are m_pContext->pSmtpEventLogInfo
  2413. pLogEventInfo = m_pContext->pSmtpEventLogInfo;
  2414. // filter out events that the user isn't interested in
  2415. if (m_pContext->iSelectedDebugLevel < pLogEventInfo->iDebugLevel) {
  2416. return S_OK;
  2417. }
  2418. // Handler is m_pContext->pDefaultEventLogHandler
  2419. pEventLog = (CEventLogWrapper*)m_pContext->pDefaultEventLogHandler;
  2420. // Call into default logging handler
  2421. pEventLog->LogEvent(
  2422. pLogEventInfo->idMessage,
  2423. // pLogEventInfo->idCategory, // Not used by default handler
  2424. pLogEventInfo->cSubstrings,
  2425. pLogEventInfo->rgszSubstrings,
  2426. pLogEventInfo->wType,
  2427. pLogEventInfo->errCode,
  2428. pLogEventInfo->iDebugLevel,
  2429. pLogEventInfo->szKey,
  2430. pLogEventInfo->dwOptions,
  2431. pLogEventInfo->iMessageString,
  2432. pLogEventInfo->hModule);
  2433. TraceFunctLeaveEx((LPARAM)this);
  2434. return hrRes;
  2435. }
  2436. //////////////////////////////////////////////////////////////////////////////
  2437. HRESULT CStoreDispatcher::CSmtpGetAuxDomainInfoFlagsParams::CallObject(
  2438. CBinding& bBinding,
  2439. IUnknown *punkObject )
  2440. {
  2441. ISmtpGetAuxDomainInfoFlags *pSink = NULL;
  2442. HRESULT hr = punkObject->QueryInterface(IID_ISmtpGetAuxDomainInfoFlags, (void **)&pSink);
  2443. if( FAILED( hr ) )
  2444. {
  2445. return( hr );
  2446. }
  2447. hr = pSink->OnGetAuxDomainInfoFlags(m_pContext->pIServer,
  2448. m_pContext->pszDomainName,
  2449. m_pContext->pdwDomainInfoFlags );
  2450. pSink->Release();
  2451. return( hr );
  2452. }
  2453. //////////////////////////////////////////////////////////////////////////////
  2454. HRESULT CStoreDispatcher::CSmtpGetAuxDomainInfoFlagsParams::CallDefault()
  2455. {
  2456. return S_OK;
  2457. }
  2458. //////////////////////////////////////////////////////////////////////////////
  2459. //+------------------------------------------------------------
  2460. //
  2461. // Function: CStoreDriver::Setprevious
  2462. //
  2463. // Synopsis: Method of IEventDispatcherChain - gets calle dy the
  2464. // dispatcher, when binding changes happen.
  2465. //
  2466. // Arguments:
  2467. // pUnkPrevious: [in] Pointer to the previous dispatcher
  2468. // ppUnkPreload: [out] Receives an object which implements
  2469. // IEnumGUID, in order to tell the router
  2470. // which event types to pre-load.
  2471. //
  2472. // Returns:
  2473. // S_OK: Success
  2474. //
  2475. // History:
  2476. // dondu 06/22/98 Created
  2477. //
  2478. //-------------------------------------------------------------
  2479. const GUID* g_apStoreDispEventTypes[] = {&CATID_SMTP_STORE_DRIVER,&GUID_NULL};
  2480. HRESULT STDMETHODCALLTYPE CStoreDispatcher::SetPrevious(IUnknown *pUnkPrevious, IUnknown **ppUnkPreload) {
  2481. HRESULT hrRes;
  2482. if (ppUnkPreload) {
  2483. *ppUnkPreload = NULL;
  2484. }
  2485. if (!ppUnkPreload) {
  2486. return (E_POINTER);
  2487. }
  2488. _ASSERT(pUnkPrevious);
  2489. if (pUnkPrevious) {
  2490. CComQIPtr<CStoreDispatcherData,&__uuidof(CStoreDispatcherData)> pData;
  2491. LPVOID pvServer;
  2492. DWORD dwServerInstance;
  2493. pData = pUnkPrevious;
  2494. _ASSERT(pData);
  2495. if (pData) {
  2496. hrRes = pData->GetData(&pvServer,&dwServerInstance);
  2497. if (SUCCEEDED(hrRes)) {
  2498. hrRes = SetData(pvServer,dwServerInstance);
  2499. _ASSERT(SUCCEEDED(hrRes));
  2500. }
  2501. }
  2502. }
  2503. hrRes = CEDEnumGUID::CreateNew(ppUnkPreload,g_apStoreDispEventTypes);
  2504. return (hrRes);
  2505. };
  2506. HRESULT STDMETHODCALLTYPE CStoreDispatcher::SetContext(REFGUID guidEventType,
  2507. IEventRouter *piRouter,
  2508. IEventBindings *pBindings) {
  2509. HRESULT hrRes;
  2510. hrRes = CEventBaseDispatcher::SetContext(guidEventType,piRouter,pBindings);
  2511. if (SUCCEEDED(hrRes) && (guidEventType == CATID_SMTP_STORE_DRIVER)) {
  2512. HRESULT hrResTmp;
  2513. LPVOID pvServer;
  2514. DWORD dwServerInstance;
  2515. SMTP_ALLOC_PARAMS AllocParams;
  2516. hrResTmp = GetData(&pvServer,&dwServerInstance);
  2517. if (SUCCEEDED(hrResTmp)) {
  2518. ZeroMemory(&AllocParams, sizeof(AllocParams));
  2519. AllocParams.m_EventSmtpServer = (LPVOID *) pvServer;
  2520. AllocParams.m_InstanceId = dwServerInstance;
  2521. AllocParams.m_dwStartupType = SMTP_INIT_BINDING_CHANGE;
  2522. hrResTmp = OnEvent(CATID_SMTP_STORE_DRIVER,SMTP_STOREDRV_STARTUP_EVENT,&AllocParams);
  2523. _ASSERT(SUCCEEDED(hrResTmp));
  2524. }
  2525. }
  2526. return (hrRes);
  2527. }
  2528. //+------------------------------------------------------------
  2529. //
  2530. // Function: CSMTPSeoMgr::CSMTPSeoMgr
  2531. //
  2532. // Synopsis: Initialize member data
  2533. //
  2534. // Arguments: NONE
  2535. //
  2536. // Returns: NOTHING
  2537. //
  2538. // History:
  2539. // jstamerj 1999/06/25 19:24:18: Created.
  2540. //
  2541. //-------------------------------------------------------------
  2542. CSMTPSeoMgr::CSMTPSeoMgr()
  2543. {
  2544. TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::CSMTPSeoMgr");
  2545. m_dwSignature = SIGNATURE_CSMTPSEOMGR;
  2546. m_pIEventRouter = NULL;
  2547. m_pICatDispatcher = NULL;
  2548. TraceFunctLeaveEx((LPARAM)this);
  2549. } // CSMTPSeoMgr::CSMTPSeoMgr
  2550. //+------------------------------------------------------------
  2551. //
  2552. // Function: CSMTPSeoMgr::~CSMTPSeoMgr
  2553. //
  2554. // Synopsis: Deinitialize if necessary
  2555. //
  2556. // Arguments: NONE
  2557. //
  2558. // Returns: NOTHING
  2559. //
  2560. // History:
  2561. // jstamerj 1999/06/25 19:26:09: Created.
  2562. //
  2563. //-------------------------------------------------------------
  2564. CSMTPSeoMgr::~CSMTPSeoMgr()
  2565. {
  2566. TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::~CSMTPSeoMgr");
  2567. Deinit();
  2568. _ASSERT(m_dwSignature == SIGNATURE_CSMTPSEOMGR);
  2569. m_dwSignature = SIGNATURE_CSMTPSEOMGR_INVALID;
  2570. TraceFunctLeaveEx((LPARAM)this);
  2571. } // CSMTPSeoMgr::~CSMTPSeoMgr
  2572. //+------------------------------------------------------------
  2573. //
  2574. // Function: CSMTPSeoMgr::HrInit
  2575. //
  2576. // Synopsis: Initialize
  2577. //
  2578. // Arguments:
  2579. // dwVSID: The virtual server ID
  2580. //
  2581. // Returns:
  2582. // S_OK: Success
  2583. // error from SEO
  2584. //
  2585. // History:
  2586. // jstamerj 1999/06/25 19:27:30: Created.
  2587. //
  2588. //-------------------------------------------------------------
  2589. HRESULT CSMTPSeoMgr::HrInit(
  2590. DWORD dwVSID)
  2591. {
  2592. HRESULT hr = S_OK;
  2593. CStoreDispatcherClassFactory cf;
  2594. TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::HrInit");
  2595. _ASSERT(m_pIEventRouter == NULL);
  2596. hr = SEOGetRouter(
  2597. GUID_SMTP_SOURCE_TYPE,
  2598. (REFGUID) CStringGUID(GUID_SMTPSVC_SOURCE, dwVSID),
  2599. &m_pIEventRouter);
  2600. if(FAILED(hr) || (hr == S_FALSE)) {
  2601. //
  2602. // Map S_FALSE to file not found -- this happens when the
  2603. // source type is not registered
  2604. //
  2605. if(hr == S_FALSE)
  2606. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  2607. ErrorTrace((LPARAM)this, "SEOGetRouter failed hr %08lx", hr);
  2608. m_pIEventRouter = NULL;
  2609. goto CLEANUP;
  2610. }
  2611. //
  2612. // Grab the dispatcher for the categorizer
  2613. //
  2614. _ASSERT(m_pICatDispatcher == NULL);
  2615. hr = m_pIEventRouter->GetDispatcherByClassFactory(
  2616. CLSID_CStoreDispatcher,
  2617. &cf,
  2618. CATID_SMTP_TRANSPORT_CATEGORIZE,
  2619. IID_IServerDispatcher,
  2620. (IUnknown **) &m_pICatDispatcher);
  2621. if(FAILED(hr)) {
  2622. ErrorTrace((LPARAM)this, "GetDispatcherByClassFactory failed hr %08lx", hr);
  2623. m_pICatDispatcher = NULL;
  2624. goto CLEANUP;
  2625. }
  2626. CLEANUP:
  2627. if(FAILED(hr))
  2628. Deinit();
  2629. DebugTrace((LPARAM)this, "returning %08lx", hr);
  2630. TraceFunctLeaveEx((LPARAM)this);
  2631. return hr;
  2632. } // CSMTPSeoMgr::HrInit
  2633. //+------------------------------------------------------------
  2634. //
  2635. // Function: CSMTPSeoMgr::Deinit
  2636. //
  2637. // Synopsis: Deinitialize member variables
  2638. //
  2639. // Arguments: NONE
  2640. //
  2641. // Returns: NOTHING
  2642. //
  2643. // History:
  2644. // jstamerj 1999/06/25 19:41:20: Created.
  2645. //
  2646. //-------------------------------------------------------------
  2647. VOID CSMTPSeoMgr::Deinit()
  2648. {
  2649. TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::Deinit");
  2650. if(m_pICatDispatcher) {
  2651. m_pICatDispatcher->Release();
  2652. m_pICatDispatcher = NULL;
  2653. }
  2654. if(m_pIEventRouter) {
  2655. m_pIEventRouter->Release();
  2656. m_pIEventRouter = NULL;
  2657. }
  2658. TraceFunctLeaveEx((LPARAM)this);
  2659. } // CSMTPSeoMgr::Deinit
  2660. //+------------------------------------------------------------
  2661. //
  2662. // Function: CSMTPSeoMgr::HrTriggerServerEvent
  2663. //
  2664. // Synopsis: Trigger a server event
  2665. //
  2666. // Arguments:
  2667. // dwEventType: event type to trigger
  2668. // pvContext: structure specific to event type (see smtpseo.h)
  2669. //
  2670. // Returns:
  2671. // S_OK: Success, called one or more sinks
  2672. // S_FALSE: Success, no sinks called
  2673. // MAILTRANSPORT_S_PENDING: Proccessing events async
  2674. // E_OUTOFMEMORY
  2675. // error from SEO
  2676. //
  2677. // History:
  2678. // jstamerj 1999/06/25 19:43:00: Created.
  2679. //
  2680. //-------------------------------------------------------------
  2681. HRESULT CSMTPSeoMgr::HrTriggerServerEvent(
  2682. DWORD dwEventType,
  2683. PVOID pvContext)
  2684. {
  2685. HRESULT hr = S_OK;
  2686. CComPtr<IServerDispatcher> pEventDispatcher;
  2687. CStoreDispatcherClassFactory cf;
  2688. REFIID iidBindingPoint = GuidForEvent(dwEventType);
  2689. TraceFunctEnterEx((LPARAM)this, "CSMTPSeoMgr::HrTriggerServerEvent");
  2690. if(m_pIEventRouter == NULL)
  2691. return E_POINTER;
  2692. if(iidBindingPoint == CATID_SMTP_TRANSPORT_CATEGORIZE) {
  2693. //
  2694. // Use the cached Categorizer dispatcher
  2695. //
  2696. pEventDispatcher = m_pICatDispatcher;
  2697. } else {
  2698. //
  2699. // Get the latest dispatcher with all changes
  2700. //
  2701. hr = m_pIEventRouter->GetDispatcherByClassFactory(
  2702. CLSID_CStoreDispatcher,
  2703. &cf,
  2704. iidBindingPoint,
  2705. IID_IServerDispatcher,
  2706. (IUnknown **) &pEventDispatcher);
  2707. if (FAILED(hr)) {
  2708. ErrorTrace((LPARAM)this, "GetDispatcherByClassFactory failed hr %08lx", hr);
  2709. goto CLEANUP;
  2710. }
  2711. }
  2712. hr = pEventDispatcher->OnEvent(
  2713. iidBindingPoint,
  2714. dwEventType,
  2715. pvContext);
  2716. CLEANUP:
  2717. DebugTrace((LPARAM)this, "returning %08lx", hr);
  2718. TraceFunctLeaveEx((LPARAM)this);
  2719. return hr;
  2720. } // CSMTPSeoMgr::HrTriggerServerEvent