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.

3288 lines
93 KiB

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