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.

1599 lines
48 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. //
  4. // File: mailadmq.cpp
  5. //
  6. // Description: Implementation for CMailMsgAdminLink
  7. //
  8. // Author: Gautam Pulla (GPulla)
  9. //
  10. // History:
  11. // 6/24/1999 - GPulla Created
  12. //
  13. // Copyright (C) 1999 Microsoft Corporation
  14. //
  15. //-----------------------------------------------------------------------------
  16. #include "aqprecmp.h"
  17. #include "linkmsgq.h"
  18. #include "mailadmq.h"
  19. #include "dcontext.h"
  20. #include "dsnevent.h"
  21. #include "asyncq.inl"
  22. #include "asyncadm.inl"
  23. //---[ CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueNDR ]-----------------------
  24. //
  25. //
  26. // Description:
  27. // Wraps call to NDR MailMsg
  28. // Parameters:
  29. // *pIUnknown - IUnkown of MailMsg
  30. // Returns:
  31. // S_OK on success
  32. // History:
  33. // 12/7/2000 - MikeSwa Created
  34. //
  35. //-----------------------------------------------------------------------------
  36. HRESULT CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueNDR(
  37. IUnknown *pIUnknownMsg)
  38. {
  39. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueNDR");
  40. HRESULT hr = S_OK;
  41. IMailMsgProperties *pIMailMsgProperties = NULL;
  42. CDSNParams dsnparams;
  43. _ASSERT(pIUnknownMsg);
  44. _ASSERT(m_paqinst);
  45. hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
  46. (void **) &pIMailMsgProperties);
  47. _ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
  48. if (FAILED(hr))
  49. {
  50. ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
  51. goto Exit;
  52. }
  53. //
  54. // Initialize DSN params
  55. //
  56. SET_DEBUG_DSN_CONTEXT(dsnparams, __LINE__);
  57. dsnparams.dwStartDomain = 0;
  58. dsnparams.dwDSNActions = DSN_ACTION_FAILURE_ALL;
  59. dsnparams.pIMailMsgProperties = pIMailMsgProperties;
  60. dsnparams.hrStatus = AQUEUE_E_QADMIN_NDR;
  61. //
  62. // Attempt to NDR message
  63. //
  64. hr = HrLinkAllDomains(pIMailMsgProperties);
  65. if (FAILED(hr))
  66. {
  67. ErrorTrace((LPARAM) this,
  68. "Unable to link all domains for DSN generation", hr);
  69. goto Exit;
  70. }
  71. //
  72. // Fire DSN Generation event
  73. //
  74. hr = m_paqinst->HrTriggerDSNGenerationEvent(&dsnparams, FALSE);
  75. if (FAILED(hr))
  76. {
  77. ErrorTrace((LPARAM) this,
  78. "Unable to NDR message via QAPI 0x%08X", hr);
  79. goto Exit;
  80. }
  81. //
  82. // Now that we have generated an NDR... we need to delete the
  83. // Message.
  84. //
  85. hr = HrDeleteMsgFromQueueSilent(pIUnknownMsg);
  86. if (FAILED(hr))
  87. goto Exit;
  88. Exit:
  89. if (pIMailMsgProperties)
  90. pIMailMsgProperties->Release();
  91. TraceFunctLeave();
  92. return hr;
  93. }
  94. //---[ CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueSilent ]--------------------
  95. //
  96. //
  97. // Description:
  98. // Wrapper function to silently delete a message from a queue
  99. // Parameters:
  100. // *pIUnknown - IUnkown of MailMsg
  101. // Returns:
  102. // S_OK on success
  103. // History:
  104. // 12/7/2000 - MikeSwa Created
  105. //
  106. //-----------------------------------------------------------------------------
  107. HRESULT CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueSilent(
  108. IUnknown *pIUnknownMsg)
  109. {
  110. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrDeleteMsgFromQueueSilent");
  111. HRESULT hr = S_OK;
  112. IMailMsgQueueMgmt *pIMailMsgQueueMgmt = NULL;
  113. _ASSERT(pIUnknownMsg);
  114. hr = pIUnknownMsg->QueryInterface(IID_IMailMsgQueueMgmt,
  115. (void **) &pIMailMsgQueueMgmt);
  116. _ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
  117. if (FAILED(hr))
  118. {
  119. ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
  120. goto Exit;
  121. }
  122. //
  123. // Attempt to delete the message
  124. //
  125. hr = pIMailMsgQueueMgmt->Delete(NULL);
  126. if (FAILED(hr))
  127. ErrorTrace((LPARAM) this, "Unable to delete msg 0x%08X", hr);
  128. Exit:
  129. if (pIMailMsgQueueMgmt)
  130. pIMailMsgQueueMgmt->Release();
  131. TraceFunctLeave();
  132. return hr;
  133. }
  134. //---[ CAsyncAdminMailMsgQueue::HrFreezeMsg ]-----------------------------------
  135. //
  136. //
  137. // Description:
  138. // Wrapper to freeze a pIMailMsgProperties
  139. // Parameters:
  140. // *pIUnknown - IUnkown of MailMsg
  141. // Returns:
  142. // S_OK on success
  143. // History:
  144. // 12/7/2000 - MikeSwa Created
  145. //
  146. //-----------------------------------------------------------------------------
  147. HRESULT CAsyncAdminMailMsgQueue::HrFreezeMsg(IUnknown *pIUnknownMsg)
  148. {
  149. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrFreezeMsg");
  150. HRESULT hr = S_OK;
  151. IMailMsgProperties *pIMailMsgProperties = NULL;
  152. _ASSERT(pIUnknownMsg);
  153. hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
  154. (void **) &pIMailMsgProperties);
  155. _ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
  156. if (FAILED(hr))
  157. {
  158. ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
  159. goto Exit;
  160. }
  161. //
  162. // $$TODO - Attempt to freeze the message -- Not supported for this type of queue
  163. //
  164. Exit:
  165. if (pIMailMsgProperties)
  166. pIMailMsgProperties->Release();
  167. TraceFunctLeave();
  168. return hr;
  169. }
  170. //---[ CAsyncAdminMailMsgQueue::HrThawMsg ]-------------------------------------
  171. //
  172. //
  173. // Description:
  174. // Wrapper function to thaw a message
  175. // Parameters:
  176. // *pIUnknown - IUnkown of MailMsg
  177. // Returns:
  178. // S_OK on success
  179. // History:
  180. // 12/7/2000 - MikeSwa Created
  181. //
  182. //-----------------------------------------------------------------------------
  183. HRESULT CAsyncAdminMailMsgQueue::HrThawMsg(IUnknown *pIUnknownMsg)
  184. {
  185. TraceFunctEnterEx((LPARAM) this, "AsyncAdminMailMsgQueue::HrThawMsg");
  186. HRESULT hr = S_OK;
  187. IMailMsgProperties *pIMailMsgProperties = NULL;
  188. _ASSERT(pIUnknownMsg);
  189. hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
  190. (void **) &pIMailMsgProperties);
  191. _ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
  192. if (FAILED(hr))
  193. {
  194. ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
  195. goto Exit;
  196. }
  197. //
  198. // $$TODO - Attempt to thaw message -- Not supported for this type of queue
  199. //
  200. Exit:
  201. if (pIMailMsgProperties)
  202. pIMailMsgProperties->Release();
  203. TraceFunctLeave();
  204. return hr;
  205. }
  206. //---[ CAsyncAdminMailMsgQueue::HrGetStatsForMsg ]------------------------------
  207. //
  208. //
  209. // Description:
  210. // Wrapper function to fill in the CAQStats struct for a message
  211. // Parameters:
  212. // *pIUnknown - IUnkown of MailMsg
  213. // *paqstats - Ptr to aqstats struction to fill in.
  214. // Returns:
  215. // S_OK on success
  216. // History:
  217. // 12/7/2000 - MikeSwa Created
  218. //
  219. //-----------------------------------------------------------------------------
  220. HRESULT CAsyncAdminMailMsgQueue::HrGetStatsForMsg(
  221. IUnknown *pIUnknownMsg,
  222. CAQStats *paqstats)
  223. {
  224. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrGetStatsForMsg");
  225. HRESULT hr = S_OK;
  226. IMailMsgProperties *pIMailMsgProperties = NULL;
  227. _ASSERT(pIUnknownMsg);
  228. _ASSERT(paqstats);
  229. hr = pIUnknownMsg->QueryInterface(IID_IMailMsgProperties,
  230. (void **) &pIMailMsgProperties);
  231. _ASSERT(SUCCEEDED(hr) && "IUnknownMsg Must be a MailMsg!!");
  232. if (FAILED(hr))
  233. {
  234. ErrorTrace((LPARAM) this, "QI for MailMsg failed with hr 0x%08X", hr);
  235. goto Exit;
  236. }
  237. //
  238. // $$TODO - GetStats for Msg -- Not supported for this type of queue
  239. //
  240. Exit:
  241. if (pIMailMsgProperties)
  242. pIMailMsgProperties->Release();
  243. TraceFunctLeave();
  244. return hr;
  245. }
  246. //---[ CAsyncAdminMailMsgQueue::HrSendDelayOrNDR ]-----------------------------
  247. //
  248. //
  249. // Description:
  250. // Checks the MailMsg to see if it has expired or needs a delay DSN sent
  251. // and acts accordingly
  252. // Parameters:
  253. // IMailMsgProperties - The MailMsg that needs to be checked
  254. // Returns:
  255. // S_OK : OK, may have sent delay NDR
  256. // S_FALSE : OK, MailMsg handled (NDR'd or nothing left to do)
  257. // Or returns error from called fnct.
  258. // History:
  259. // 5/15/2001 - dbraun Created
  260. //
  261. //-----------------------------------------------------------------------------
  262. HRESULT CAsyncAdminMailMsgQueue::HrSendDelayOrNDR(IMailMsgProperties *pIMailMsgProperties)
  263. {
  264. HRESULT hr = S_OK;
  265. DWORD cbProp = 0;
  266. DWORD dwTimeContext = 0;
  267. CDSNParams dsnparams;
  268. BOOL fSentDelay = FALSE;
  269. BOOL fSentNDR = FALSE;
  270. FILETIME ftExpireTimeNDR;
  271. FILETIME ftExpireTimeDelay;
  272. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrSendDelayOrNDR");
  273. _ASSERT(m_paqinst);
  274. // Try to get the expire time from the message, otherwise calculate it
  275. // from the file time
  276. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_LOCAL_EXPIRE_NDR,
  277. sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeNDR);
  278. if (MAILMSG_E_PROPNOTFOUND == hr)
  279. {
  280. // Prop not set ... calculate it from the file time
  281. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
  282. sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeNDR);
  283. if (FAILED(hr))
  284. {
  285. // Message should not make it this far without being stamped
  286. _ASSERT(MAILMSG_E_PROPNOTFOUND != hr);
  287. // Prop not set or other failure, we cannot expire this message
  288. goto Exit;
  289. }
  290. m_paqinst->CalcExpireTimeNDR(ftExpireTimeNDR, TRUE, &ftExpireTimeNDR);
  291. }
  292. else if (FAILED(hr))
  293. {
  294. goto Exit;
  295. }
  296. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_LOCAL_EXPIRE_DELAY,
  297. sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeDelay);
  298. if (MAILMSG_E_PROPNOTFOUND == hr)
  299. {
  300. // Prop not set ... calculate it from the file time
  301. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
  302. sizeof(FILETIME), &cbProp, (BYTE *) &ftExpireTimeDelay);
  303. if (FAILED(hr))
  304. {
  305. // Message should not make it this far without being stamped
  306. _ASSERT(MAILMSG_E_PROPNOTFOUND != hr);
  307. // Prop not set or other failure, we cannot expire this message
  308. goto Exit;
  309. }
  310. m_paqinst->CalcExpireTimeDelay(ftExpireTimeDelay, TRUE, &ftExpireTimeDelay);
  311. }
  312. else if (FAILED(hr))
  313. {
  314. goto Exit;
  315. }
  316. //
  317. // Initialize DSN params
  318. //
  319. SET_DEBUG_DSN_CONTEXT(dsnparams, __LINE__);
  320. dsnparams.dwStartDomain = 0;
  321. dsnparams.dwDSNActions = 0;
  322. dsnparams.pIMailMsgProperties = pIMailMsgProperties;
  323. dsnparams.hrStatus = 0;
  324. // Check if we have passed either expire time
  325. if (m_paqinst->fInPast(&ftExpireTimeNDR, &dwTimeContext))
  326. {
  327. dsnparams.dwDSNActions |= DSN_ACTION_FAILURE_ALL;
  328. dsnparams.hrStatus = AQUEUE_E_MSG_EXPIRED;
  329. fSentNDR = TRUE;
  330. }
  331. else if (m_paqinst->fInPast(&ftExpireTimeDelay, &dwTimeContext))
  332. {
  333. dsnparams.dwDSNActions |= DSN_ACTION_DELAYED;
  334. dsnparams.hrStatus = AQUEUE_E_MSG_EXPIRED;
  335. fSentDelay = TRUE;
  336. }
  337. // If we are going to generate an NDR
  338. if (dsnparams.hrStatus)
  339. {
  340. //
  341. // Attempt to NDR message
  342. //
  343. hr = HrLinkAllDomains(pIMailMsgProperties);
  344. if (FAILED(hr))
  345. {
  346. ErrorTrace((LPARAM) this,
  347. "Unable to link all domains for DSN generation", hr);
  348. goto Exit;
  349. }
  350. //
  351. // Fire DSN Generation event
  352. //
  353. hr = m_paqinst->HrTriggerDSNGenerationEvent(&dsnparams, FALSE);
  354. if (FAILED(hr))
  355. {
  356. ErrorTrace((LPARAM) this,
  357. "Unable to NDR message via QAPI 0x%08X", hr);
  358. goto Exit;
  359. }
  360. // Return based on what we did
  361. if (fSentNDR)
  362. {
  363. // This message has been handled, delete it
  364. hr = HrDeleteMsgFromQueueSilent(pIMailMsgProperties);
  365. if (FAILED(hr))
  366. {
  367. ErrorTrace((LPARAM) this,
  368. "Failed to delete message after sending NDR", hr);
  369. goto Exit;
  370. }
  371. // NDR'd and successfully deleted message
  372. hr = S_FALSE;
  373. }
  374. else if (fSentDelay)
  375. {
  376. hr = S_OK;
  377. }
  378. }
  379. Exit:
  380. TraceFunctLeave();
  381. return hr;
  382. }
  383. //---[ CAsyncAdminMailMsgQueue::fHandleCompletionFailure ]---------------------
  384. //
  385. //
  386. // Description:
  387. // Overrides base class and checks to see if message has expired before
  388. // putting it on the retry queue
  389. // Parameters:
  390. // IMailMsgProperties - The MailMsg that triggered failure
  391. // Returns:
  392. // -
  393. // History:
  394. // 5/15/2001 - dbraun Created
  395. //
  396. //-----------------------------------------------------------------------------
  397. BOOL CAsyncAdminMailMsgQueue::fHandleCompletionFailure(IMailMsgProperties *pIMailMsgProperties)
  398. {
  399. HRESULT hr = S_OK;
  400. // Has this message expired?
  401. hr = HrSendDelayOrNDR (pIMailMsgProperties);
  402. if (hr == S_FALSE)
  403. {
  404. // This message was NDR'd, we are done
  405. return TRUE;
  406. }
  407. else
  408. {
  409. return CAsyncAdminQueue<IMailMsgProperties *, ASYNC_QUEUE_MAILMSG_SIG>::fHandleCompletionFailure(pIMailMsgProperties);
  410. }
  411. }
  412. //---[ CAsyncAdminMailMsgQueue::HrQueueRequest ]-------------------------------
  413. //
  414. //
  415. // Description:
  416. // Function that will queue a request to the async queue and close
  417. // the handles associated with a message if we are above our simple
  418. // "throttle" limit.
  419. // Parameters:
  420. // pIMailMsgProperties The IMailMsgProperties interface to queue
  421. // fRetry TRUE - if this message is being retried
  422. // FALSE - otherwise
  423. // cMsgsInSystem The total number of messages in the system
  424. // Returns:
  425. // S_OK on success
  426. // Error code from async queue on failure.
  427. // History:
  428. // 10/7/1999 - MikeSwa Created
  429. // 12/7/2000 - MikeSwa Moved to CAsyncAdminMailMsgQueue from asyncq.cpp
  430. // 4/6/2001 - MikeSwa Modified to take into account queue length
  431. //
  432. //-----------------------------------------------------------------------------
  433. HRESULT CAsyncAdminMailMsgQueue::HrQueueRequest(IMailMsgProperties *pIMailMsgProperties,
  434. BOOL fRetry,
  435. DWORD cMsgsInSystem)
  436. {
  437. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrQueueRequest");
  438. IMailMsgQueueMgmt *pIMailMsgQueueMgmt = NULL;
  439. HRESULT hr = S_OK;
  440. DWORD cThresholdUsed = g_cMaxIMsgHandlesThreshold;
  441. DWORD cItemsPending = dwGetTotalThreads()+m_cItemsPending;
  442. if (m_qhmgr.fShouldCloseHandle(cItemsPending, m_cPendingAsyncCompletions,
  443. cMsgsInSystem))
  444. {
  445. DebugTrace((LPARAM) this,
  446. "INFO: Closing IMsg Content - %d messsages in system", cMsgsInSystem);
  447. hr = pIMailMsgProperties->QueryInterface(IID_IMailMsgQueueMgmt,
  448. (void **) &pIMailMsgQueueMgmt);
  449. if (SUCCEEDED(hr))
  450. {
  451. //bounce usage count off of zero
  452. pIMailMsgQueueMgmt->ReleaseUsage();
  453. pIMailMsgQueueMgmt->AddUsage();
  454. pIMailMsgQueueMgmt->Release();
  455. }
  456. else
  457. {
  458. ErrorTrace((LPARAM) this,
  459. "Unable to QI for IMailMsgQueueMgmt - hr 0x%08X", hr);
  460. }
  461. }
  462. TraceFunctLeave();
  463. return CAsyncAdminQueue<IMailMsgProperties *, ASYNC_QUEUE_MAILMSG_SIG>::HrQueueRequest(pIMailMsgProperties, fRetry);
  464. }
  465. //---[ CAsyncAdminMailMsgQueue::HrQueueRequest ]-------------------------------
  466. //
  467. //
  468. // Description:
  469. // Since we inherit from AsyncQueue who implmenents this, we should assert
  470. // so that a dev adding a new call to this class later on, will use the
  471. // version that closes handles.
  472. //
  473. // In RTL this will force the handles closed and queue the request
  474. // Parameters:
  475. // pIMailMsgProperties The IMailMsgProperties interface to queue
  476. // fRetry TRUE - if this message is being retried
  477. // FALSE - otherwise
  478. // Returns:
  479. // returns return value from proper version of HrQueueRequest
  480. // History:
  481. // 10/7/1999 - MikeSwa Created
  482. // 12/7/2000 - MikeSwa Moved to CAsyncAdminMailMsgQueue from asyncq.cpp
  483. //
  484. //-----------------------------------------------------------------------------
  485. HRESULT CAsyncAdminMailMsgQueue::HrQueueRequest(IMailMsgProperties *pIMailMsgProperties,
  486. BOOL fRetry)
  487. {
  488. _ASSERT(0 && "Should use HrQueueRequest with 3 parameters");
  489. return HrQueueRequest(pIMailMsgProperties, fRetry,
  490. g_cMaxIMsgHandlesThreshold+1);
  491. }
  492. //---[ CAsyncAdminMailMsgQueue::HrApplyQueueAdminFunction ]--------------------
  493. //
  494. //
  495. // Description:
  496. // Will call the IQueueAdminMessageFilter::Process message for every
  497. // message in this queue. If the message passes the filter, then
  498. // HrApplyActionToMessage on this object will be called.
  499. //
  500. // This is different from other implemenentations in that the
  501. // location of the message implies something about the state of the
  502. // message. Messages in the retry... or frozen queue are considered
  503. // failed or frozen.
  504. //
  505. // We do this instead of writing a mailmsg property, because of the
  506. // *huge* perf hit (we would ruin our async message flow by blocking
  507. // to check if a message is frozen). We already have the retry
  508. // queue, so it makes sense to use it in a similar manner
  509. //
  510. // Parameters:
  511. // IN pIQueueAdminMessageFilter
  512. // Returns:
  513. // S_OK on success
  514. // History:
  515. // 2/23/99 - MikeSwa Created
  516. // 12/7/2000 - MikeSwa Modified - Made template base class
  517. // 12/13/2000 - MikeSwa Modified from CAsyncAdminQueue
  518. //
  519. //-----------------------------------------------------------------------------
  520. STDMETHODIMP CAsyncAdminMailMsgQueue::HrApplyQueueAdminFunction(
  521. IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
  522. {
  523. HRESULT hr = S_OK;
  524. CQueueAdminContext qapictx(m_pAQNotify, m_paqinst);
  525. _ASSERT(pIQueueAdminMessageFilter);
  526. hr = pIQueueAdminMessageFilter->HrSetQueueAdminAction(
  527. (IQueueAdminAction *) this);
  528. //This is an internal interface that should not fail
  529. _ASSERT(SUCCEEDED(hr) && "HrSetQueueAdminAction");
  530. if (FAILED(hr))
  531. goto Exit;
  532. hr = pIQueueAdminMessageFilter->HrSetCurrentUserContext(&qapictx);
  533. //This is an internal interface that should not fail
  534. _ASSERT(SUCCEEDED(hr) && "HrSetCurrentUserContext");
  535. if (FAILED(hr))
  536. goto Exit;
  537. //
  538. // Iterate over messages in the base queue
  539. //
  540. qapictx.SetQueueState(LI_READY);
  541. hr = HrMapFnBaseQueue(m_pfnMessageAction, pIQueueAdminMessageFilter);
  542. //
  543. // Iterate over messages in the retry queue
  544. //
  545. qapictx.SetQueueState(LI_RETRY);
  546. hr = HrMapFnRetryQueue(m_pfnMessageAction, pIQueueAdminMessageFilter);
  547. hr = pIQueueAdminMessageFilter->HrSetCurrentUserContext(NULL);
  548. //This is an internal interface that should not fail
  549. _ASSERT(SUCCEEDED(hr) && "HrSetCurrentUserContext");
  550. if (FAILED(hr))
  551. goto Exit;
  552. Exit:
  553. return hr;
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Description:
  557. // Used to query the admin interfaces for CMailMsgAdminLink
  558. // Parameters:
  559. // IN REFIID riid GUID for interface
  560. // OUT LPVOID *ppvObj Ptr to Interface.
  561. //
  562. // Returns:
  563. // S_OK Interface supported by this class.
  564. // E_POINTER NULL parameter.
  565. // E_NOINTERFACE No such interface exists.
  566. // History:
  567. // 6/25/1999 - GPulla Created
  568. //-----------------------------------------------------------------------------
  569. STDMETHODIMP CMailMsgAdminLink::QueryInterface(REFIID riid, LPVOID *ppvObj)
  570. {
  571. HRESULT hr = S_OK;
  572. if (!ppvObj)
  573. {
  574. hr = E_POINTER;
  575. goto Exit;
  576. }
  577. if (IID_IUnknown == riid)
  578. {
  579. *ppvObj = static_cast<IQueueAdminAction *>(this);
  580. }
  581. else if (IID_IQueueAdminAction == riid)
  582. {
  583. *ppvObj = static_cast<IQueueAdminAction *>(this);
  584. }
  585. else if (IID_IQueueAdminLink == riid)
  586. {
  587. *ppvObj = static_cast<IQueueAdminLink *>(this);
  588. }
  589. else
  590. {
  591. *ppvObj = NULL;
  592. hr = E_NOINTERFACE;
  593. goto Exit;
  594. }
  595. static_cast<IUnknown *>(*ppvObj)->AddRef();
  596. Exit:
  597. return hr;
  598. }
  599. //---[ CMailMsgAdminLink::CMailMsgAdminLink]---------------------------------
  600. //
  601. //
  602. // Description:
  603. // Default constructor for CMailMsgAdminLink
  604. // Parameters:
  605. // IN guidLink GUID to associate with this object
  606. // IN szQueueName Name to associate with admin object
  607. // IN *pasyncmmq Async MailMsg queue for precat or prerouting
  608. // IN dwLinkType Bit-Field identifying this admin object
  609. // IN paqinst CAQSvrInst object
  610. //
  611. // Returns:
  612. // -
  613. // History:
  614. // 6/25/1999 - GPulla Created
  615. //
  616. //-----------------------------------------------------------------------------
  617. CMailMsgAdminLink::CMailMsgAdminLink(
  618. GUID guid,
  619. LPSTR szQueueName,
  620. CAsyncAdminMailMsgQueue *pasyncmmq,
  621. DWORD dwLinkType,
  622. CAQSvrInst *paqinst
  623. )
  624. : m_aqsched(guid, 0)
  625. {
  626. _ASSERT(pasyncmmq);
  627. _ASSERT(szQueueName);
  628. _ASSERT(paqinst);
  629. m_guid = guid;
  630. m_cbQueueName = lstrlen(szQueueName);
  631. m_szQueueName = (LPSTR) pvMalloc(m_cbQueueName+1);
  632. _ASSERT(m_szQueueName);
  633. if(m_szQueueName)
  634. lstrcpy(m_szQueueName, szQueueName);
  635. m_pasyncmmq = pasyncmmq;
  636. m_dwLinkType = dwLinkType;
  637. m_dwSignature = MAIL_MSG_ADMIN_QUEUE_VALID_SIGNATURE;
  638. if (m_pasyncmmq)
  639. m_pasyncmmq->SetAQNotify((IAQNotify *) this);
  640. m_paqinst = paqinst;
  641. ZeroMemory(&m_ftRetry, sizeof(m_ftRetry));
  642. }
  643. //---[CMailMsgAdminLink::~CMailMsgAdminLink]---------------------------------
  644. // Description:
  645. // Destructor.
  646. // Parameters:
  647. // -
  648. // Returns:
  649. // -
  650. // History:
  651. // 6/24/1999 - GPulla created
  652. //-----------------------------------------------------------------------------
  653. CMailMsgAdminLink::~CMailMsgAdminLink()
  654. {
  655. if (m_szQueueName)
  656. FreePv(m_szQueueName);
  657. m_dwSignature = MAIL_MSG_ADMIN_QUEUE_INVALID_SIGNATURE;
  658. }
  659. //---[ CMailMsgAdminLink::HrApplyQueueAdminFunction ]---------------------------
  660. //
  661. //
  662. // Description:
  663. // Wrapper to call into underlying queue's implementation
  664. // Parameters:
  665. // IN pIQueueAdminMessageFilter
  666. // Returns:
  667. // S_OK on success
  668. // S_FALSE if no contained queue (will assert as well)
  669. // History:
  670. // 12/11/2000 - MikeSwa Created
  671. //
  672. //-----------------------------------------------------------------------------
  673. STDMETHODIMP CMailMsgAdminLink::HrApplyQueueAdminFunction(
  674. IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
  675. {
  676. HRESULT hr = S_FALSE;
  677. _ASSERT(m_pasyncmmq);
  678. if (m_pasyncmmq)
  679. hr = m_pasyncmmq->HrApplyQueueAdminFunction(pIQueueAdminMessageFilter);
  680. return hr;
  681. }
  682. //---[ CMailMsgAdminLink::HrApplyActionToMessage ]-----------------------------
  683. //
  684. //
  685. // Description:
  686. // Wrapper function to pass call on to queue implementation
  687. // Parameters:
  688. // IN *pIUnknownMsg ptr to message abstraction
  689. // IN ma Message action to perform
  690. // IN pvContext Context set on IQueueAdminFilter
  691. // OUT pfShouldDelete TRUE if the message should be deleted
  692. // Returns:
  693. // S_OK on success
  694. // S_FALSE if no contained queue (will assert as well)
  695. // History:
  696. // 12/11/2000 - MikeSwa Created
  697. //
  698. //-----------------------------------------------------------------------------
  699. STDMETHODIMP CMailMsgAdminLink::HrApplyActionToMessage(
  700. IUnknown *pIUnknownMsg,
  701. MESSAGE_ACTION ma,
  702. PVOID pvContext,
  703. BOOL *pfShouldDelete)
  704. {
  705. HRESULT hr = S_FALSE;
  706. _ASSERT(m_pasyncmmq);
  707. if (m_pasyncmmq)
  708. {
  709. hr = m_pasyncmmq->HrApplyActionToMessage(pIUnknownMsg, ma,
  710. pvContext, pfShouldDelete);
  711. }
  712. return hr;
  713. }
  714. //---[CMailMsgAdminLink::HrGetLinkInfo]---------------------------------------
  715. // Description:
  716. // Gets information about this admin object. Note that the diagnostic error
  717. // is not implemented for this object but the parameter is supported purely
  718. // to support the IQueueAction interface.
  719. // Parameters:
  720. // OUT LINK_INFO *pliLinkInfo Struct to fill information into.
  721. // OUT HRESULT *phrDiagnosticError Diagnostic error if any, for this link
  722. // Returns:
  723. // S_OK on success
  724. // E_POINTER if argument is NULL
  725. // E_OUTOFMEMORY if unable to allocate memory for returning information.
  726. // History:
  727. // 6/24/1999 - GPulla created
  728. //-----------------------------------------------------------------------------
  729. STDMETHODIMP CMailMsgAdminLink::HrGetLinkInfo(LINK_INFO *pliLinkInfo, HRESULT *phrDiagnosticError)
  730. {
  731. TraceFunctEnterEx((LPARAM) this, "CMailMsgAdminLink::HrGetLinkInfo");
  732. HRESULT hr = S_OK;
  733. _ASSERT(m_pasyncmmq);
  734. _ASSERT(pliLinkInfo);
  735. if(!m_pasyncmmq)
  736. {
  737. hr = S_FALSE;
  738. goto Exit;
  739. }
  740. if(!pliLinkInfo)
  741. {
  742. hr = E_POINTER;
  743. goto Exit;
  744. }
  745. //
  746. // Get the link state from our base queue implementation
  747. //
  748. pliLinkInfo->fStateFlags = m_pasyncmmq->dwQueueAdminLinkGetLinkState();
  749. //
  750. // If we are in retry... try to report the time
  751. //
  752. if (LI_RETRY & pliLinkInfo->fStateFlags)
  753. QueueAdminFileTimeToSystemTime(&m_ftRetry, &(pliLinkInfo->stNextScheduledConnection));
  754. pliLinkInfo->fStateFlags |= GetLinkType();
  755. pliLinkInfo->szLinkName = wszQueueAdminConvertToUnicode(m_szQueueName, m_cbQueueName);
  756. if (!pliLinkInfo->szLinkName)
  757. {
  758. hr = E_OUTOFMEMORY;
  759. goto Exit;
  760. }
  761. //We return 0 since size statistics are not calculated
  762. pliLinkInfo->cbLinkVolume.QuadPart = 0;
  763. //
  764. // Include the items queued for retry in the total count
  765. //
  766. pliLinkInfo->cMessages = m_pasyncmmq->cQueueAdminGetNumItems();
  767. pliLinkInfo->dwSupportedLinkActions = LA_KICK | LA_THAW | LA_FREEZE;
  768. //Write diagnostic
  769. *phrDiagnosticError = S_OK;
  770. Exit:
  771. TraceFunctLeave();
  772. return hr;
  773. }
  774. //---[CMailMsgAdminLink::HrGetNumQueues]-------------------------------------
  775. // Description:
  776. // Used to query number of queues in object. Since this class does not
  777. // expose the one queue it contains, 0 is returned,
  778. // Parameters:
  779. // OUT DWORD *pcQueues # of queues (0) written to this.
  780. // Returns:
  781. // S_OK unless...
  782. // E_POINTER parameter is not allocated
  783. // History:
  784. // 6/24/1999 - GPulla created
  785. // 12/11/2000 - MikeSwa Updated to support sub-queues
  786. //-----------------------------------------------------------------------------
  787. STDMETHODIMP CMailMsgAdminLink::HrGetNumQueues(DWORD *pcQueues)
  788. {
  789. _ASSERT (pcQueues);
  790. if (!pcQueues)
  791. return E_POINTER;
  792. *pcQueues = 1;
  793. return S_OK;
  794. }
  795. //---[CMailMsgAdminLink::HrApplyActionToLink]---------------------------------
  796. // Description:
  797. // Applies action to the embedded queue. Only kicking the queue is supported.
  798. // Parameters:
  799. // IN LINK_ACTION la Action to apply.
  800. // Returns:
  801. // S_OK Action was successfully applied.
  802. // S_FALSE Action not supported or severe error.
  803. // History:
  804. // 6/24/1999 - GPulla created
  805. //-----------------------------------------------------------------------------
  806. STDMETHODIMP CMailMsgAdminLink::HrApplyActionToLink(LINK_ACTION la)
  807. {
  808. HRESULT hr = S_OK;
  809. _ASSERT(m_pasyncmmq);
  810. if (!m_pasyncmmq)
  811. {
  812. hr = S_FALSE;
  813. goto Exit;
  814. }
  815. if (LA_KICK == la)
  816. m_pasyncmmq->StartRetry(); //kick off processing
  817. else if (LA_FREEZE == la)
  818. m_pasyncmmq->FreezeQueue();
  819. else if (LA_THAW == la)
  820. m_pasyncmmq->ThawQueue();
  821. else
  822. hr = S_FALSE;
  823. Exit:
  824. return hr;
  825. }
  826. //---[CMailMsgAdminLink::HrGetQueueIDs]---------------------------------------
  827. // Description:
  828. // Returns an enumeration of embedded queues in this object. Since the one
  829. // emmbedded queue is not exposed, zero queues are returned.
  830. // Parameters:
  831. // OUT DWORD *pcQueues Number of queues (0)
  832. // OUT QUEUELINK_ID *rgQueues Array into which queueIDs are returned.
  833. // Returns:
  834. // S_OK Success
  835. // E_POINTER pcQueues is NULL
  836. // History:
  837. // 6/24/1999 - GPulla created
  838. // 12/11/2000 - MikeSwa Modified to expose queues
  839. //-----------------------------------------------------------------------------
  840. STDMETHODIMP CMailMsgAdminLink::HrGetQueueIDs(DWORD *pcQueues, QUEUELINK_ID *rgQueues)
  841. {
  842. TraceFunctEnterEx((LPARAM) this, "CMailMsgAdminLink::HrGetQueueIDs");
  843. _ASSERT(pcQueues);
  844. _ASSERT(rgQueues);
  845. HRESULT hr = S_OK;
  846. QUEUELINK_ID* pCurrentQueueID = rgQueues;
  847. if(!pcQueues)
  848. {
  849. hr = E_POINTER;
  850. goto Exit;
  851. }
  852. if (*pcQueues < 1)
  853. {
  854. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  855. goto Exit;
  856. }
  857. *pcQueues = 0;
  858. _ASSERT(m_pasyncmmq);
  859. hr = m_pasyncmmq->HrGetQueueID(pCurrentQueueID);
  860. if (FAILED(hr))
  861. goto Exit;
  862. *pcQueues = 1;
  863. Exit:
  864. TraceFunctLeave();
  865. return hr;
  866. }
  867. //---[CMailMsgAdminLink::fMatchesID]------------------------------------------
  868. // Description:
  869. // Checks if this admin object matches a specified ID.
  870. // Parameters:
  871. // IN QUEUELINK_ID *pQueueLinkID Ptr to ID to be matched against.
  872. // Returns:
  873. // TRUE on match.
  874. // FALSE if did not matched or unrecoverable error (m_szQueueName not alloced)
  875. // History:
  876. // 6/24/1999 - GPulla created
  877. //-----------------------------------------------------------------------------
  878. BOOL STDMETHODCALLTYPE CMailMsgAdminLink::fMatchesID(QUEUELINK_ID *pQueueLinkID)
  879. {
  880. _ASSERT(pQueueLinkID);
  881. _ASSERT(pQueueLinkID->szName);
  882. _ASSERT(m_szQueueName);
  883. if(!m_szQueueName)
  884. return FALSE;
  885. CAQScheduleID aqsched(pQueueLinkID->uuid, pQueueLinkID->dwId);
  886. if (!fIsSameScheduleID(&aqsched))
  887. return FALSE;
  888. if (!fBiStrcmpi(m_szQueueName, pQueueLinkID->szName))
  889. return FALSE;
  890. //Everything matched!
  891. return TRUE;
  892. }
  893. //---[ CMailMsgAdminLink::QuerySupportedActions ]------------------------------
  894. //
  895. //
  896. // Description:
  897. // Returns the actions and filters that this implementation supports
  898. // Parameters:
  899. // pdwSupportedActions - QAPI MsgActions that this queue suppprts
  900. // pdwSupportedFilterFlags - QAPI filter flags that this queue supports
  901. // Returns:
  902. // S_OK on success
  903. // History:
  904. // 12/12/2000 - MikeSwa Created
  905. //
  906. //-----------------------------------------------------------------------------
  907. STDMETHODIMP CMailMsgAdminLink::QuerySupportedActions(
  908. DWORD *pdwSupportedActions,
  909. DWORD *pdwSupportedFilterFlags)
  910. {
  911. HRESULT hr = S_OK;
  912. _ASSERT(m_pasyncmmq);
  913. if (m_pasyncmmq)
  914. {
  915. hr = m_pasyncmmq->QuerySupportedActions(pdwSupportedActions,
  916. pdwSupportedFilterFlags);
  917. }
  918. return hr;
  919. }
  920. //---[CMailMsgAdminLink::fIsSameScheduleID]-----------------------------------
  921. // Description:
  922. // Helper function for fMatchesID()
  923. // Parameters:
  924. // Returns:
  925. // TRUE if schedule IDs are identical
  926. // FALSE otherwise.
  927. // History:
  928. // 6/24/1999 - GPulla created
  929. //-----------------------------------------------------------------------------
  930. BOOL CMailMsgAdminLink::fIsSameScheduleID(CAQScheduleID *paqsched)
  931. {
  932. return (m_aqsched.fIsEqual(paqsched));
  933. }
  934. //---[CMailMsgAdminLink::HrGetLinkID]-----------------------------------------
  935. // Description:
  936. // Get the ID for this admin object.
  937. // Parameters:
  938. // OUT QUEUELINK_ID *pLinkID struct into which to put ID.
  939. // Returns:
  940. // S_OK Successfully copied out ID.
  941. // E_POINTER out struct is NULL.
  942. // E_OUTOFMEMORY Cannot allocate memory for output of ID name.
  943. // History:
  944. // 6/24/1999 - GPulla created
  945. //-----------------------------------------------------------------------------
  946. HRESULT CMailMsgAdminLink::HrGetLinkID(QUEUELINK_ID *pLinkID)
  947. {
  948. HRESULT hr = S_OK;
  949. _ASSERT(pLinkID);
  950. if(!pLinkID)
  951. {
  952. hr = E_POINTER;
  953. goto Exit;
  954. }
  955. pLinkID->qltType = QLT_LINK;
  956. pLinkID->dwId = m_aqsched.dwGetScheduleID();
  957. m_aqsched.GetGUID(&pLinkID->uuid);
  958. if (!fRPCCopyName(&pLinkID->szName))
  959. hr = E_OUTOFMEMORY;
  960. else
  961. hr = S_OK;
  962. Exit:
  963. return hr;
  964. }
  965. //---[CMailMsgAdminLink::fRPCCopyName]----------------------------------------
  966. // Description:
  967. // Helper function to create a unicode copy of the string identifying
  968. // this admin object. The unicode string is de-allocated by RPC.
  969. // Parameters:
  970. // OUT LPWSTR *pwszLinkName Ptr to wchar string allocated and written
  971. // into by this function.
  972. // Returns:
  973. // TRUE On success.
  974. // FALSE if there is no name for this object
  975. // FALSE if memory cannot be allocated for unicode string.
  976. // History:
  977. // 6/24/1999 - GPulla created
  978. //-----------------------------------------------------------------------------
  979. BOOL CMailMsgAdminLink::fRPCCopyName(OUT LPWSTR *pwszLinkName)
  980. {
  981. _ASSERT(pwszLinkName);
  982. if (!m_cbQueueName || !m_szQueueName)
  983. return FALSE;
  984. *pwszLinkName = wszQueueAdminConvertToUnicode(m_szQueueName,
  985. m_cbQueueName);
  986. if (!*pwszLinkName)
  987. return FALSE;
  988. return TRUE;
  989. }
  990. //---[ CAsyncAdminMailMsgLink::HrNotify ]--------------------------------------
  991. //
  992. //
  993. // Description:
  994. // Notification for stats purposes
  995. // Parameters:
  996. //
  997. // Returns:
  998. //
  999. // History:
  1000. // 1/10/2001 - MikeSwa Created
  1001. //
  1002. //-----------------------------------------------------------------------------
  1003. HRESULT CMailMsgAdminLink::HrNotify(CAQStats *aqstats, BOOL fAdd)
  1004. {
  1005. UpdateCountersForLinkType(m_paqinst, m_dwLinkType);
  1006. return S_OK;
  1007. }
  1008. //---[ CMailMsgAdminLink::SetNextRetry ]---------------------------------------
  1009. //
  1010. //
  1011. // Description:
  1012. // Updates internal retry time
  1013. // Parameters:
  1014. // pft Filetime to update to
  1015. // Returns:
  1016. // -
  1017. // History:
  1018. // 1/16/2001 - MikeSwa Created
  1019. //
  1020. //-----------------------------------------------------------------------------
  1021. void CMailMsgAdminLink::SetNextRetry(FILETIME *pft)
  1022. {
  1023. if (pft)
  1024. memcpy(&m_ftRetry, pft, sizeof(FILETIME));
  1025. }
  1026. //--------[ CAsyncAdminMailMsgQueue::fMatchesQueueAdminFilter ]-----------------
  1027. //
  1028. // Description:
  1029. // Checks a message against a queue admin message filter to see if it
  1030. // is a match
  1031. // Parameters:
  1032. // IN pIMailMsgProperties mail msg object to perform check on
  1033. // IN paqmf Message Filter to check against
  1034. // Returns:
  1035. // TRUE if it matches
  1036. // FALSE if it does not
  1037. // History:
  1038. // 8/8/00 - t-toddc created
  1039. // 12/11/2000 - MikeSwa Merged for checkin
  1040. //
  1041. //-----------------------------------------------------------------------------
  1042. BOOL CAsyncAdminMailMsgQueue::fMatchesQueueAdminFilter(
  1043. IN IMailMsgProperties* pIMailMsgProperties,
  1044. IN CAQAdminMessageFilter* paqmf)
  1045. {
  1046. TraceFunctEnterEx((LPARAM) pIMailMsgProperties,
  1047. "CAsyncAdminMailMsgQueue::fMatchesQueueAdminFilter");
  1048. BOOL fMatch = TRUE;
  1049. DWORD dwFilterFlags = 0;
  1050. DWORD cbMsgSize = 0;
  1051. DWORD cbProp = 0;
  1052. FILETIME ftQueueEntry = {0, 0};
  1053. LPSTR szSender = NULL;
  1054. LPSTR szMsgId = NULL;
  1055. LPSTR szRecip = NULL;
  1056. BOOL fFoundRecipString = FALSE;
  1057. HRESULT hr = S_OK;
  1058. DWORD cOpenHandlesForMsg = 1; //don't close by default
  1059. _ASSERT(pIMailMsgProperties);
  1060. _ASSERT(paqmf);
  1061. dwFilterFlags = paqmf->dwGetMsgFilterFlags();
  1062. if (!dwFilterFlags)
  1063. {
  1064. fMatch = FALSE;
  1065. goto Exit;
  1066. }
  1067. if (AQ_MSG_FILTER_ALL & dwFilterFlags)
  1068. {
  1069. fMatch = TRUE;
  1070. goto Exit;
  1071. }
  1072. // check size.
  1073. if (AQ_MSG_FILTER_LARGER_THAN & dwFilterFlags)
  1074. {
  1075. //Get the size of the message
  1076. hr = HrQADMGetMsgSize(pIMailMsgProperties, &cbMsgSize);
  1077. if (FAILED(hr))
  1078. {
  1079. fMatch = FALSE;
  1080. goto Exit;
  1081. }
  1082. fMatch = paqmf->fMatchesSize(cbMsgSize);
  1083. if (!fMatch)
  1084. goto Exit;
  1085. }
  1086. if (AQ_MSG_FILTER_OLDER_THAN & dwFilterFlags)
  1087. {
  1088. //Get time message was queued
  1089. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
  1090. sizeof(FILETIME),
  1091. &cbProp,
  1092. (BYTE *) &ftQueueEntry);
  1093. if (FAILED(hr))
  1094. {
  1095. ErrorTrace((LPARAM) pIMailMsgProperties,
  1096. "Unable to get arrival time 0x%08X", hr);
  1097. fMatch = FALSE;
  1098. goto Exit;
  1099. }
  1100. fMatch = paqmf->fMatchesTime(&ftQueueEntry);
  1101. if (!fMatch)
  1102. goto Exit;
  1103. }
  1104. if (AQ_MSG_FILTER_FROZEN & dwFilterFlags)
  1105. {
  1106. // obtaining state information about freezing/thawing not supported yet.
  1107. fMatch = FALSE;
  1108. if (AQ_MSG_FILTER_INVERTSENSE & dwFilterFlags)
  1109. fMatch = !fMatch;
  1110. if (!fMatch)
  1111. goto Exit;
  1112. }
  1113. if (AQ_MSG_FILTER_FAILED & dwFilterFlags)
  1114. {
  1115. // fMatch was originally set to TRUE
  1116. // currently, no information about failures is available
  1117. // for IMailMsgProperties mail msg objects
  1118. fMatch = FALSE;
  1119. if (AQ_MSG_FILTER_INVERTSENSE & dwFilterFlags)
  1120. fMatch = !fMatch;
  1121. if (!fMatch)
  1122. goto Exit;
  1123. }
  1124. //If we haven't failed by this point, we may need to AddUsage and read
  1125. //props from the mailmsg. Double-check to make sure that we need to
  1126. //add usage.
  1127. if (!((AQ_MSG_FILTER_MESSAGEID | AQ_MSG_FILTER_SENDER | AQ_MSG_FILTER_RECIPIENT) &
  1128. dwFilterFlags))
  1129. goto Exit;
  1130. //
  1131. // Check to see if the message is already open
  1132. //
  1133. hr = pIMailMsgProperties->GetDWORD(
  1134. IMMPID_MPV_MESSAGE_OPEN_HANDLES,
  1135. &cOpenHandlesForMsg);
  1136. if (FAILED(hr))
  1137. {
  1138. ErrorTrace((LPARAM) pIMailMsgProperties, "Not running SP1 of W2K");
  1139. cOpenHandlesForMsg = 0;
  1140. hr = S_OK;
  1141. }
  1142. if (AQ_MSG_FILTER_MESSAGEID & dwFilterFlags)
  1143. {
  1144. hr = HrQueueAdminGetStringProp(pIMailMsgProperties,
  1145. IMMPID_MP_RFC822_MSG_ID,
  1146. &szMsgId);
  1147. if (FAILED(hr))
  1148. szMsgId = NULL;
  1149. fMatch = paqmf->fMatchesId(szMsgId);
  1150. if (!fMatch)
  1151. goto Exit;
  1152. }
  1153. if (AQ_MSG_FILTER_SENDER & dwFilterFlags)
  1154. {
  1155. fMatch = paqmf->fMatchesMailMsgSender(pIMailMsgProperties);
  1156. if (!fMatch)
  1157. goto Exit;
  1158. }
  1159. if (AQ_MSG_FILTER_RECIPIENT & dwFilterFlags)
  1160. {
  1161. fMatch = paqmf->fMatchesMailMsgRecipient(pIMailMsgProperties);
  1162. if (!fMatch)
  1163. goto Exit;
  1164. }
  1165. Exit:
  1166. //
  1167. // If this operation resulted in opening the message, we should close it
  1168. // The message is not dirty (we did not write anything), so it should not
  1169. // need to commit
  1170. //
  1171. if (!cOpenHandlesForMsg)
  1172. {
  1173. HRESULT hrTmp = S_OK;
  1174. hrTmp = HrReleaseIMailMsgUsageCount(pIMailMsgProperties);
  1175. if (SUCCEEDED(hrTmp))
  1176. HrIncrementIMailMsgUsageCount(pIMailMsgProperties);
  1177. }
  1178. if (szMsgId)
  1179. QueueAdminFree(szMsgId);
  1180. TraceFunctLeave();
  1181. return fMatch;
  1182. }
  1183. //---[ CAsyncAdminMailMsgQueue::HrGetQueueAdminMsgInfo ]-----------------------
  1184. //
  1185. // Description:
  1186. // Fills out a queue admin MESSAGE_INFO structure. All allocations are
  1187. // done with pvQueueAdminAlloc to be freed by the RPC code
  1188. // Parameters:
  1189. // IN pIMailMsgProperties mail msg object to get info from
  1190. // IN OUT pMsgInfo MESSAGE_INFO struct to dump data to
  1191. // Returns:
  1192. // S_OK on success
  1193. // AQUEUE_E_MESSAGE_HANDLED if the underlying message has been deleted
  1194. // E_OUTOFMEMORY if an allocation failure
  1195. // History:
  1196. // 8/8/00 - t-toddc created
  1197. // 12/11/2000 - MikeSwa Merged for checkin
  1198. //
  1199. //-----------------------------------------------------------------------------
  1200. HRESULT CAsyncAdminMailMsgQueue::HrGetQueueAdminMsgInfo(
  1201. IMailMsgProperties* pIMailMsgProperties,
  1202. MESSAGE_INFO* pMsgInfo,
  1203. PVOID pvContext)
  1204. {
  1205. TraceFunctEnterEx((LPARAM) pIMailMsgProperties,
  1206. "CAsyncAdminMailMsgQueue::HrGetQueueAdminMsgInfo");
  1207. HRESULT hr = S_OK;
  1208. DWORD cbProp = 0;
  1209. DWORD cOpenHandlesForMsg = 0;
  1210. LPSTR szRecipients = NULL;
  1211. LPSTR szCCRecipients = NULL;
  1212. LPSTR szBCCRecipients = NULL;
  1213. FILETIME ftSubmitted = {0,0}; //Origination time property buffer
  1214. FILETIME ftQueueEntry = {0,0};
  1215. FILETIME ftExpire = {0,0};
  1216. DWORD cbMsgSize = 0;
  1217. CQueueAdminContext *pqapictx = (CQueueAdminContext *) pvContext;
  1218. _ASSERT(pIMailMsgProperties);
  1219. _ASSERT(pMsgInfo);
  1220. _ASSERT(pqapictx);
  1221. _ASSERT(pqapictx->fIsValid());
  1222. //
  1223. // If we have a context... it better be valid
  1224. //
  1225. if (pqapictx && !pqapictx->fIsValid()) {
  1226. _ASSERT(FALSE && "CQueueAdminContext is not valid");
  1227. pqapictx = NULL; //be defensive... don't use it.
  1228. }
  1229. //
  1230. // Check to see if the message is already open
  1231. //
  1232. hr = pIMailMsgProperties->GetDWORD(
  1233. IMMPID_MPV_MESSAGE_OPEN_HANDLES,
  1234. &cOpenHandlesForMsg);
  1235. if (FAILED(hr))
  1236. {
  1237. ErrorTrace((LPARAM) pIMailMsgProperties, "Not running SP1 of W2K");
  1238. cOpenHandlesForMsg = 0;
  1239. hr = S_OK;
  1240. }
  1241. //
  1242. // Extract properties that are stored only on mailmsg (this is shared
  1243. // with all QAPI code).
  1244. //
  1245. hr = HrGetMsgInfoFromIMailMsgProperty(pIMailMsgProperties,
  1246. pMsgInfo);
  1247. if (FAILED(hr))
  1248. goto Exit;
  1249. //can't report the number of failures from IMailMsgProperties
  1250. pMsgInfo->cFailures = 0;
  1251. //Get the size of the message
  1252. hr = HrQADMGetMsgSize(pIMailMsgProperties, &cbMsgSize);
  1253. if (FAILED(hr))
  1254. goto Exit;
  1255. pMsgInfo->cbMessageSize = cbMsgSize;
  1256. //Get time message was queued
  1257. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ARRIVAL_FILETIME,
  1258. sizeof(FILETIME),
  1259. &cbProp,
  1260. (BYTE *) &ftQueueEntry);
  1261. if (FAILED(hr))
  1262. {
  1263. // there is a possibility that the msg will not have entry time
  1264. // (i.e. presubmission queue)
  1265. if (MAILMSG_E_PROPNOTFOUND == hr)
  1266. {
  1267. ZeroMemory(&ftQueueEntry, sizeof(FILETIME));
  1268. hr = S_OK;
  1269. }
  1270. else
  1271. goto Exit;
  1272. }
  1273. //Get submission and expiration times
  1274. QueueAdminFileTimeToSystemTime(&ftQueueEntry,
  1275. &pMsgInfo->stReceived);
  1276. //Get the time the message entered the org
  1277. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_ORIGINAL_ARRIVAL_TIME,
  1278. sizeof(FILETIME), &cbProp, (BYTE *) &ftSubmitted);
  1279. if (FAILED(hr))
  1280. {
  1281. //Time was not written... use entry time.
  1282. hr = S_OK;
  1283. memcpy(&ftSubmitted, &ftQueueEntry, sizeof(FILETIME));
  1284. }
  1285. QueueAdminFileTimeToSystemTime(&ftSubmitted, &pMsgInfo->stSubmission);
  1286. // Try to get the expire time from the message, otherwise calculate it
  1287. // from the file time
  1288. hr = pIMailMsgProperties->GetProperty(IMMPID_MP_LOCAL_EXPIRE_NDR,
  1289. sizeof(FILETIME), &cbProp, (BYTE *) &ftExpire);
  1290. if (MAILMSG_E_PROPNOTFOUND == hr)
  1291. {
  1292. if (pqapictx->paqinstGetAQ())
  1293. {
  1294. // Prop not set ... calculate it from the file time
  1295. pqapictx->paqinstGetAQ()->CalcExpireTimeNDR(ftQueueEntry, TRUE, &ftExpire);
  1296. // This is OK
  1297. hr = S_OK;
  1298. }
  1299. else
  1300. {
  1301. // This shouldn't happen but we don't want to crash in RTL over it
  1302. _ASSERT(FALSE && "AQInst was not set in context!");
  1303. // We can return this field blank
  1304. ZeroMemory(&ftExpire, sizeof(FILETIME));
  1305. hr = S_OK;
  1306. }
  1307. }
  1308. else if (FAILED(hr))
  1309. {
  1310. goto Exit;
  1311. }
  1312. QueueAdminFileTimeToSystemTime(&ftExpire, &pMsgInfo->stExpiry);
  1313. //
  1314. // Get the state of the message
  1315. //
  1316. pMsgInfo->fMsgFlags = MP_NORMAL;
  1317. if (pqapictx)
  1318. {
  1319. if (LI_RETRY == pqapictx->lfGetQueueState())
  1320. pMsgInfo->fMsgFlags |= MP_MSG_RETRY;
  1321. else if (LI_FROZEN == pqapictx->lfGetQueueState())
  1322. pMsgInfo->fMsgFlags |= MP_MSG_FROZEN;
  1323. }
  1324. Exit:
  1325. //
  1326. // If this operation resulted in opening the message, we should close it
  1327. // The message is not dirty (we did not write anything), so it should not
  1328. // need to commit
  1329. //
  1330. if (!cOpenHandlesForMsg)
  1331. {
  1332. HRESULT hrTmp = S_OK;
  1333. hrTmp = HrReleaseIMailMsgUsageCount(pIMailMsgProperties);
  1334. if (SUCCEEDED(hrTmp))
  1335. HrIncrementIMailMsgUsageCount(pIMailMsgProperties);
  1336. }
  1337. TraceFunctLeave();
  1338. return hr;
  1339. }
  1340. //---[ CAsyncAdminMailMsgQueue::HrInternalQuerySupportedActions ]---------------
  1341. //
  1342. //
  1343. // Description:
  1344. // Returns the actions and filters that this implementation supports
  1345. // Parameters:
  1346. // pdwSupportedActions - QAPI MsgActions that this queue suppprts
  1347. // pdwSupportedFilterFlags - QAPI filter flags that this queue supports
  1348. // Returns:
  1349. // S_OK on success
  1350. // History:
  1351. // 12/12/2000 - MikeSwa Created
  1352. //
  1353. //-----------------------------------------------------------------------------
  1354. HRESULT CAsyncAdminMailMsgQueue::HrInternalQuerySupportedActions(
  1355. DWORD *pdwSupportedActions,
  1356. DWORD *pdwSupportedFilterFlags)
  1357. {
  1358. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminMailMsgQueue::HrInternalQuerySupportedActions");
  1359. HRESULT hr = S_OK;
  1360. hr = QueryDefaultSupportedActions(pdwSupportedActions, pdwSupportedFilterFlags);
  1361. if (FAILED(hr))
  1362. goto Exit;
  1363. //
  1364. // This queue implementation does not support all of the default flags.
  1365. //
  1366. _ASSERT(pdwSupportedActions);
  1367. _ASSERT(pdwSupportedFilterFlags);
  1368. //
  1369. // We don't support:
  1370. // - Freeze global - No status to set on a mailmsg
  1371. // - Thaw global - can't freeze... therefore cannot thaw
  1372. //
  1373. *pdwSupportedActions &= ~(MA_FREEZE_GLOBAL | MA_THAW_GLOBAL);
  1374. //
  1375. // We don't support
  1376. // - Checking for frozen messages (we have no status to indicate
  1377. // that a message is frozen)
  1378. //
  1379. *pdwSupportedFilterFlags &= ~(MF_FROZEN);
  1380. Exit:
  1381. return hr;
  1382. }