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.

459 lines
14 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. //
  4. // File: asyncadm.inl
  5. //
  6. // Description:
  7. // Implementation of CAsyncAdminQueue class. See header file for object
  8. // model
  9. //
  10. // Author: Mike Swafford (MikeSwa)
  11. //
  12. // History:
  13. // 12/7/2000 - MikeSwa Created
  14. // (pulled from asyncq.cpp and t-toddc's summer work)
  15. //
  16. // Copyright (C) 2000 Microsoft Corporation
  17. //
  18. //-----------------------------------------------------------------------------
  19. //---[ CAsyncAdminQueue::CAsyncAdminQueue ]------------------------------------
  20. //
  21. //
  22. // Description:
  23. // Constructor for CAsyncRetryAdminMsgRefQueue
  24. // Parameters:
  25. // szDomain Domain name for this queue
  26. // pguid GUID for this queue
  27. // dwID Shedule ID for this queue
  28. // Returns:
  29. // -
  30. // History:
  31. // 2/23/99 - MikeSwa Created
  32. //
  33. //-----------------------------------------------------------------------------
  34. template<class PQDATA, DWORD TEMPLATE_SIG>
  35. CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::CAsyncAdminQueue(
  36. LPCSTR szDomain, LPCSTR szLinkName,
  37. const GUID *pguid, DWORD dwID, CAQSvrInst *paqinst,
  38. typename CFifoQueue<PQDATA>::MAPFNAPI pfnMessageAction)
  39. {
  40. _ASSERT(szDomain);
  41. _ASSERT(pguid);
  42. m_cbDomain = 0;
  43. m_szDomain = NULL;
  44. m_cbLinkName = 0;
  45. m_szLinkName = NULL;
  46. m_pAQNotify = NULL;
  47. m_paqinst = paqinst;
  48. m_pfnMessageAction = pfnMessageAction;
  49. _ASSERT(m_pfnMessageAction);
  50. if (szDomain)
  51. {
  52. m_cbDomain = lstrlen(szDomain);
  53. m_szDomain = (LPSTR) pvMalloc(m_cbDomain+1);
  54. if (m_szDomain)
  55. lstrcpy(m_szDomain, szDomain);
  56. }
  57. if (szLinkName)
  58. {
  59. m_cbLinkName = lstrlen(szLinkName);
  60. m_szLinkName = (LPSTR) pvMalloc(m_cbLinkName+1);
  61. }
  62. if (m_szLinkName)
  63. lstrcpy(m_szLinkName, szLinkName);
  64. if (pguid)
  65. memcpy(&m_guid, pguid, sizeof(GUID));
  66. else
  67. ZeroMemory(&m_guid, sizeof(GUID));
  68. m_dwID = dwID;
  69. }
  70. //---[ CAsyncAdminQueue::~CAsyncAdminQueue ]-----------------------------------
  71. //
  72. //
  73. // Description:
  74. // Destructor for CAsyncAdminQueue
  75. // Parameters:
  76. // -
  77. // Returns:
  78. // -
  79. // History:
  80. // 2/23/99 - MikeSwa Created
  81. //
  82. //-----------------------------------------------------------------------------
  83. template<class PQDATA, DWORD TEMPLATE_SIG>
  84. CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::~CAsyncAdminQueue()
  85. {
  86. if (m_szDomain)
  87. FreePv(m_szDomain);
  88. if (m_szLinkName)
  89. FreePv(m_szLinkName);
  90. }
  91. //---[ CAsyncAdminQueue::HrInitialize ]----------------------------------------
  92. //
  93. //
  94. // Description:
  95. // Wrapper for parent class HrInitialize... used to call set
  96. // CHandleManager
  97. // Parameters:
  98. // -
  99. // Returns:
  100. // -
  101. // History:
  102. // 5/18/2001 - MikeSwa Created
  103. //
  104. //-----------------------------------------------------------------------------
  105. template<class PQDATA, DWORD TEMPLATE_SIG>
  106. HRESULT CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::HrInitialize(
  107. DWORD cMaxSyncThreads,
  108. DWORD cItemsPerATQThread,
  109. DWORD cItemsPerSyncThread,
  110. PVOID pvContext,
  111. QCOMPFN pfnQueueCompletion,
  112. QCOMPFN pfnFailedItem,
  113. typename CFifoQueue<PQDATA>::MAPFNAPI pfnQueueFailure,
  114. DWORD cMaxPendingAsyncCompletions)
  115. {
  116. HRESULT hr = S_OK;
  117. hr = CAsyncRetryQueue<PQDATA, TEMPLATE_SIG>::HrInitialize(cMaxSyncThreads,
  118. cItemsPerATQThread, cItemsPerSyncThread, pvContext,
  119. pfnQueueCompletion, pfnFailedItem, pfnQueueFailure,
  120. cMaxPendingAsyncCompletions);
  121. m_qhmgr.SetMaxConcurrentItems(s_cDefaultMaxAsyncThreads, cMaxSyncThreads);
  122. return hr;
  123. }
  124. //---[ CAsyncAdminQueue::QueryInterface ]---------------------------
  125. //
  126. //
  127. // Description:
  128. // QueryInterface for CAsyncAdminQueue that supports:
  129. // - IQueueAdminAction
  130. // - IUnknown
  131. // - IQueueAdminQueue
  132. // Parameters:
  133. //
  134. // Returns:
  135. //
  136. // History:
  137. // 2/23/99 - MikeSwa Created
  138. // 12/7/2000 - MikeSwa Modified - Made template base class
  139. //
  140. //-----------------------------------------------------------------------------
  141. template<class PQDATA, DWORD TEMPLATE_SIG>
  142. STDMETHODIMP CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::QueryInterface(
  143. REFIID riid, LPVOID *ppvObj)
  144. {
  145. HRESULT hr = S_OK;
  146. if (!ppvObj)
  147. {
  148. hr = E_POINTER;
  149. goto Exit;
  150. }
  151. if (IID_IUnknown == riid)
  152. {
  153. *ppvObj = static_cast<IQueueAdminAction *>(this);
  154. }
  155. else if (IID_IQueueAdminAction == riid)
  156. {
  157. *ppvObj = static_cast<IQueueAdminAction *>(this);
  158. }
  159. else if (IID_IQueueAdminQueue == riid)
  160. {
  161. *ppvObj = static_cast<IQueueAdminQueue *>(this);
  162. }
  163. else
  164. {
  165. *ppvObj = NULL;
  166. hr = E_NOINTERFACE;
  167. goto Exit;
  168. }
  169. static_cast<IUnknown *>(*ppvObj)->AddRef();
  170. Exit:
  171. return hr;
  172. }
  173. //---[ CAsyncAdminQueue::HrApplyQueueAdminFunction ]----------------
  174. //
  175. //
  176. // Description:
  177. // Will call the IQueueAdminMessageFilter::Process message for every
  178. // message in this queue. If the message passes the filter, then
  179. // HrApplyActionToMessage on this object will be called.
  180. // Parameters:
  181. // IN pIQueueAdminMessageFilter
  182. // Returns:
  183. // S_OK on success
  184. // History:
  185. // 2/23/99 - MikeSwa Created
  186. // 12/7/2000 - MikeSwa Modified - Made template base class
  187. //
  188. //-----------------------------------------------------------------------------
  189. template<class PQDATA, DWORD TEMPLATE_SIG>
  190. STDMETHODIMP CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::HrApplyQueueAdminFunction(
  191. IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
  192. {
  193. HRESULT hr = S_OK;
  194. CQueueAdminContext qapictx(m_pAQNotify, m_paqinst);
  195. _ASSERT(pIQueueAdminMessageFilter);
  196. hr = pIQueueAdminMessageFilter->HrSetQueueAdminAction(
  197. (IQueueAdminAction *) this);
  198. //This is an internal interface that should not fail
  199. _ASSERT(SUCCEEDED(hr) && "HrSetQueueAdminAction");
  200. if (FAILED(hr))
  201. goto Exit;
  202. hr = pIQueueAdminMessageFilter->HrSetCurrentUserContext(&qapictx);
  203. //This is an internal interface that should not fail
  204. _ASSERT(SUCCEEDED(hr) && "HrSetCurrentUserContext");
  205. if (FAILED(hr))
  206. goto Exit;
  207. hr = HrMapFn(m_pfnMessageAction, pIQueueAdminMessageFilter);
  208. hr = pIQueueAdminMessageFilter->HrSetCurrentUserContext(NULL);
  209. //This is an internal interface that should not fail
  210. _ASSERT(SUCCEEDED(hr) && "HrSetCurrentUserContext");
  211. if (FAILED(hr))
  212. goto Exit;
  213. //
  214. // If we have thawed any messages we need to kick the retry queue to make sure
  215. // they get processed.
  216. //
  217. if (qapictx.cGetNumThawedMsgs())
  218. StartRetry();
  219. Exit:
  220. return hr;
  221. }
  222. //---[ CAsyncAdminQueue::HrApplyActionToMessage ]-------------------
  223. //
  224. //
  225. // Description:
  226. // Applies an action to this message for this queue. This will be called
  227. // by the IQueueAdminMessageFilter during a queue enumeration function.
  228. // Parameters:
  229. // IN *pIUnknownMsg ptr to message abstraction
  230. // IN ma Message action to perform
  231. // IN pvContext Context set on IQueueAdminFilter
  232. // OUT pfShouldDelete TRUE if the message should be deleted
  233. // Returns:
  234. // S_OK on success
  235. // History:
  236. // 2/23/99 - MikeSwa Created
  237. // 4/2/99 - MikeSwa Added context
  238. // 12/7/2000 - MikeSwa Modified - Made template base class
  239. //
  240. //-----------------------------------------------------------------------------
  241. template<class PQDATA, DWORD TEMPLATE_SIG>
  242. STDMETHODIMP CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::HrApplyActionToMessage(
  243. IUnknown *pIUnknownMsg,
  244. MESSAGE_ACTION ma,
  245. PVOID pvContext,
  246. BOOL *pfShouldDelete)
  247. {
  248. TraceFunctEnterEx((LPARAM) this, "CAsyncAdminQueue::HrApplyActionToMessage");
  249. HRESULT hr = S_OK;
  250. CQueueAdminContext *pqapictx = (CQueueAdminContext *) pvContext;
  251. CAQStats aqstats;
  252. CAQStats *paqstats = &aqstats;
  253. _ASSERT(pIUnknownMsg);
  254. _ASSERT(pfShouldDelete);
  255. //
  256. // If we have a context... it better be valid
  257. //
  258. if (pqapictx && !pqapictx->fIsValid()) {
  259. _ASSERT(FALSE && "CQueueAdminContext is not valid");
  260. pqapictx = NULL; //be defensive... don't use it.
  261. }
  262. *pfShouldDelete = FALSE;
  263. switch (ma)
  264. {
  265. case MA_DELETE:
  266. hr = HrDeleteMsgFromQueueNDR(pIUnknownMsg);
  267. *pfShouldDelete = TRUE;
  268. break;
  269. case MA_DELETE_SILENT:
  270. hr = HrDeleteMsgFromQueueSilent(pIUnknownMsg);
  271. *pfShouldDelete = TRUE;
  272. break;
  273. case MA_FREEZE_GLOBAL:
  274. hr = HrFreezeMsg(pIUnknownMsg);
  275. break;
  276. case MA_THAW_GLOBAL:
  277. hr = HrThawMsg(pIUnknownMsg);
  278. if (pqapictx)
  279. pqapictx->IncThawedMsgs();
  280. break;
  281. case MA_COUNT:
  282. default:
  283. //do nothing for counting and default
  284. break;
  285. }
  286. //
  287. // If we are deleting the message, we need to tell the
  288. // link so we can have accurate stats for the link.
  289. //
  290. if (*pfShouldDelete && SUCCEEDED(hr))
  291. {
  292. if (pqapictx)
  293. {
  294. hr = HrGetStatsForMsg(pIUnknownMsg, &aqstats);
  295. if (FAILED(hr))
  296. {
  297. paqstats = NULL;
  298. ErrorTrace((LPARAM) this, "Unable to get Msg Stats0x%08X", hr);
  299. }
  300. pqapictx->NotifyMessageRemoved(paqstats);
  301. }
  302. }
  303. TraceFunctLeave();
  304. return hr;
  305. }
  306. //---[ CAsyncAdminQueue::HrGetQueueInfo ]---------------------------
  307. //
  308. //
  309. // Description:
  310. // Gets the Queue Admin info for this Queue
  311. // Parameters:
  312. // IN OUT pqiQueueInfo Ptr to Queue Info Stucture to fill
  313. // Returns:
  314. // S_OK on success
  315. // E_OUTOFMEMORY if unable to allocate memory for queue name.
  316. // History:
  317. // 2/23/99 - MikeSwa Created
  318. // 12/7/2000 - MikeSwa Modified - Made template base class
  319. //
  320. //-----------------------------------------------------------------------------
  321. template<class PQDATA, DWORD TEMPLATE_SIG>
  322. HRESULT CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::HrGetQueueInfo(QUEUE_INFO *pqiQueueInfo)
  323. {
  324. HRESULT hr = S_OK;
  325. //Get # of messages
  326. pqiQueueInfo->cMessages = m_cItemsPending+m_cRetryItems;
  327. //Get Link name: Note that this class is used for special links like
  328. //local delivery queue... so there is no destination SMTP domain to
  329. //route to... therefore we need to return a special link name to admin.
  330. pqiQueueInfo->szLinkName = wszQueueAdminConvertToUnicode(m_szLinkName,
  331. m_cbLinkName);
  332. if (m_szDomain)
  333. {
  334. //Get Queue name
  335. pqiQueueInfo->szQueueName = wszQueueAdminConvertToUnicode(m_szDomain,
  336. m_cbDomain);
  337. if (!pqiQueueInfo->szQueueName)
  338. {
  339. hr = E_OUTOFMEMORY;
  340. goto Exit;
  341. }
  342. }
  343. //Currently setting this to zero since we do not calculate it
  344. pqiQueueInfo->cbQueueVolume.QuadPart = 0;
  345. pqiQueueInfo->dwMsgEnumFlagsSupported = AQUEUE_DEFAULT_SUPPORTED_ENUM_FILTERS;
  346. Exit:
  347. return hr;
  348. }
  349. //---[ CAsyncAdminMsgRefQueue::HrGetQueueID ]----------------------------------
  350. //
  351. //
  352. // Description:
  353. // Gets the QueueID for this Queue.
  354. // Parameters:
  355. // IN OUT pQueueID QUEUELINK_ID struct to fill in
  356. // Returns:
  357. // S_OK on success
  358. // E_OUTOFMEMORY if unable to allocate memory for queue name.
  359. // History:
  360. // 2/23/99 - MikeSwa Created
  361. // 12/7/2000 - MikeSwa Modified - Made template base class
  362. //
  363. //-----------------------------------------------------------------------------
  364. template<class PQDATA, DWORD TEMPLATE_SIG>
  365. HRESULT CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::HrGetQueueID(
  366. QUEUELINK_ID *pQueueID)
  367. {
  368. pQueueID->qltType = QLT_QUEUE;
  369. pQueueID->dwId = m_dwID;
  370. memcpy(&pQueueID->uuid, &m_guid, sizeof(GUID));
  371. if (m_szDomain)
  372. {
  373. pQueueID->szName = wszQueueAdminConvertToUnicode(m_szDomain, m_cbDomain);
  374. if (!pQueueID->szName)
  375. return E_OUTOFMEMORY;
  376. }
  377. return S_OK;
  378. }
  379. //---[ CAsyncAdminQueue::fMatchesID ]-------------------------------
  380. //
  381. //
  382. // Description:
  383. // Used to determine if this link matches a given scheduleID/guid pair
  384. // Parameters:
  385. // IN QueueLinkID ID to match against
  386. // Returns:
  387. // TRUE if it matches
  388. // FALSE if it does not
  389. // History:
  390. // 2/23/99 - MikeSwa Created
  391. // 12/7/2000 - MikeSwa Modified - Made template base class
  392. //
  393. //-----------------------------------------------------------------------------
  394. template<class PQDATA, DWORD TEMPLATE_SIG>
  395. BOOL STDMETHODCALLTYPE CAsyncAdminQueue<PQDATA, TEMPLATE_SIG>::fMatchesID(QUEUELINK_ID *pQueueLinkID)
  396. {
  397. _ASSERT(pQueueLinkID);
  398. if (!pQueueLinkID)
  399. return FALSE;
  400. if (0 != memcmp(&m_guid, &(pQueueLinkID->uuid), sizeof(GUID)))
  401. return FALSE;
  402. if (m_dwID != pQueueLinkID->dwId)
  403. return FALSE;
  404. //Don't need to check domain name since there is a special GUID to
  405. //identify the async queues.
  406. return TRUE;
  407. }