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.

389 lines
11 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. //
  4. // File: localq.cpp
  5. //
  6. // Description: Implementation for local admin queues
  7. //
  8. // Author: Mike Swafford (MikeSwa)
  9. //
  10. // History:
  11. // 2/23/99 - MikeSwa Created
  12. //
  13. // Copyright (C) 1999 Microsoft Corporation
  14. //
  15. //-----------------------------------------------------------------------------
  16. #include "aqprecmp.h"
  17. #include "localq.h"
  18. #include "aqadmsvr.h"
  19. #include "asyncq.inl"
  20. //---[ CLocalLinkMsgQueue::CLocalLinkMsgQueue ]---------------------------------
  21. //
  22. //
  23. // Description:
  24. // Default constructor for CLocalLinkMsgQueue
  25. // Parameters:
  26. // IN paradmq Local async queue
  27. // IN guidLink Router GUID to associate with this link
  28. // IN paqinst CAQSvrInst for VSI
  29. // Returns:
  30. // -
  31. // History:
  32. // 2/23/99 - MikeSwa Created
  33. //
  34. //-----------------------------------------------------------------------------
  35. CLocalLinkMsgQueue::CLocalLinkMsgQueue(
  36. CAsyncAdminMsgRefQueue *paradmq,
  37. GUID guidLink, CAQSvrInst *paqinst) : CLinkMsgQueue(guidLink)
  38. {
  39. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::CLocalLinkMsgQueue");
  40. //Initialize superclass with our own special GUID
  41. _ASSERT(paradmq);
  42. m_paradmq = paradmq;
  43. m_dwLocalLinkSig = LOCAL_LINK_MSG_QUEUE_SIG;
  44. m_AQNotify.Init(paqinst, (CLinkMsgQueue *) this);
  45. m_paradmq->SetAQNotify(&m_AQNotify);
  46. TraceFunctLeave();
  47. }
  48. #ifdef NEVER
  49. //---[ CLinkMsgQueue::fSameNextHop ]-------------------------------------------
  50. //
  51. //
  52. // Description:
  53. // Used to determine if this link matches a given scheduleID/link pair
  54. // Parameters:
  55. // IN paqsched ScheduleID to check against
  56. // IN szDomain Domain name to check against
  57. // Returns:
  58. // TRUE if it matches
  59. // FALSE if it does not
  60. // History:
  61. // 2/23/99 - MikeSwa Created
  62. //
  63. //-----------------------------------------------------------------------------
  64. BOOL CLocalLinkMsgQueue::fSameNextHop(CAQScheduleID *paqsched, LPSTR szDomain)
  65. {
  66. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::fSameNextHop");
  67. _ASSERT(paqsched);
  68. if (!paqsched)
  69. return FALSE;
  70. if (!fIsSameScheduleID(paqsched))
  71. return FALSE;
  72. //Don't need to check domain name since there is a special GUID to
  73. //identify the local link. This will allow us to match both
  74. //"LocalLink" (returned in LinkID) and whatever the current value of
  75. //the default domain is (we don't have to worry about the clients
  76. //version becoming outdated).
  77. //Everything matched!
  78. TraceFunctLeave();
  79. return TRUE;
  80. }
  81. #endif //NEVER
  82. //---[ CLocalLinkMsgQueue::fMatchesID ]--------------------------------------
  83. //
  84. //
  85. // Description:
  86. // Used to determine if this link matches a given scheduleID/link pair
  87. // Parameters:
  88. // IN QueueLinkID ID to match against
  89. // Returns:
  90. // TRUE if it matches
  91. // FALSE if it does not
  92. // History:
  93. // 2/23/99 - MikeSwa Created
  94. //
  95. //-----------------------------------------------------------------------------
  96. BOOL STDMETHODCALLTYPE CLocalLinkMsgQueue::fMatchesID(QUEUELINK_ID *pQueueLinkID)
  97. {
  98. _ASSERT(pQueueLinkID);
  99. CAQScheduleID aqsched(pQueueLinkID->uuid, pQueueLinkID->dwId);
  100. if (!fIsSameScheduleID(&aqsched))
  101. return FALSE;
  102. //Don't need to check domain name since there is a special GUID to
  103. //identify the local link. This will allow us to match both
  104. //"LocalLink" (returned in LinkID) and whatever the current value of
  105. //the default domain is (we don't have to worry about the clients
  106. //version becoming outdated).
  107. //Everything matched!
  108. return TRUE;
  109. }
  110. //---[ CLocalLinkMsgQueue::HrApplyQueueAdminFunction ]-------------------------
  111. //
  112. //
  113. // Description:
  114. // Used by queue admin to apply a function all queues on this link
  115. // Parameters:
  116. // IN pIQueueAdminMessageFilter
  117. // Returns:
  118. // S_OK on success
  119. // History:
  120. // 2/23/99 - MikeSwa Created
  121. //
  122. //-----------------------------------------------------------------------------
  123. STDMETHODIMP CLocalLinkMsgQueue::HrApplyQueueAdminFunction(
  124. IQueueAdminMessageFilter *pIQueueAdminMessageFilter)
  125. {
  126. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
  127. HRESULT hr = S_OK;
  128. hr = CLinkMsgQueue::HrApplyQueueAdminFunction(pIQueueAdminMessageFilter);
  129. if (FAILED(hr))
  130. goto Exit;
  131. _ASSERT(m_paradmq);
  132. hr = m_paradmq->HrApplyQueueAdminFunction(pIQueueAdminMessageFilter);
  133. if (FAILED(hr))
  134. goto Exit;
  135. Exit:
  136. TraceFunctLeave();
  137. return hr;
  138. }
  139. //---[ CLocalLinkMsgQueue::HrGetLinkInfo ]-------------------------------------
  140. //
  141. //
  142. // Description:
  143. // Fills in the details for a LINK_INFO struct. RPC is resonsible for
  144. // freeing memory.
  145. // Parameters:
  146. // IN OUT pliLinkInfo Ptr to link info struct to fill
  147. // Returns:
  148. // S_OK if successful
  149. // E_OUTOFMEMORY if unable to allocate memory
  150. // History:
  151. // 2/23/99 - MikeSwa Created
  152. // 7/1/99 - MikeSwa Added LinkDiagnostic
  153. //
  154. //-----------------------------------------------------------------------------
  155. STDMETHODIMP CLocalLinkMsgQueue::HrGetLinkInfo(LINK_INFO *pliLinkInfo,
  156. HRESULT *phrLinkDiagnostic)
  157. {
  158. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
  159. HRESULT hr = S_OK;
  160. CRefCountedString *prstrDefaultDomain = NULL;
  161. hr = CLinkMsgQueue::HrGetLinkInfo(pliLinkInfo, phrLinkDiagnostic);
  162. QUEUE_INFO qi;
  163. FILETIME *pft = NULL;
  164. _ASSERT(m_paradmq);
  165. //
  166. // Get our queue state from our base asyncq implementation
  167. //
  168. pliLinkInfo->fStateFlags = m_paradmq->dwQueueAdminLinkGetLinkState();
  169. //
  170. // If we are in retry, update our next scheduled connection
  171. //
  172. if (LI_RETRY & pliLinkInfo->fStateFlags)
  173. QueueAdminFileTimeToSystemTime(&m_ftNextRetry, &(pliLinkInfo->stNextScheduledConnection));
  174. //This is the local link
  175. pliLinkInfo->fStateFlags |= LI_TYPE_LOCAL_DELIVERY;
  176. if (m_paqinst)
  177. prstrDefaultDomain = m_paqinst->prstrGetDefaultDomain();
  178. //Copy Default local domain name instead of "LocalLink"
  179. if (prstrDefaultDomain &&
  180. prstrDefaultDomain->cbStrlen() &&
  181. prstrDefaultDomain->szStr())
  182. {
  183. if (pliLinkInfo->szLinkName)
  184. {
  185. QueueAdminFree(pliLinkInfo->szLinkName);
  186. pliLinkInfo->szLinkName = NULL;
  187. }
  188. pliLinkInfo->szLinkName = wszQueueAdminConvertToUnicode(
  189. prstrDefaultDomain->szStr(),
  190. prstrDefaultDomain->cbStrlen());
  191. if (!pliLinkInfo->szLinkName)
  192. {
  193. hr = E_OUTOFMEMORY;
  194. goto Exit;
  195. }
  196. pliLinkInfo->szLinkName[prstrDefaultDomain->cbStrlen()] = '\0';
  197. }
  198. //Get the queue info from the local queue for size totals
  199. ZeroMemory(&qi, sizeof(QUEUE_INFO));
  200. hr = m_paradmq->HrGetQueueInfo(&qi);
  201. if (FAILED(hr))
  202. goto Exit;
  203. //Clean up allocated stuff
  204. if (qi.szQueueName)
  205. QueueAdminFree(qi.szQueueName);
  206. if (qi.szLinkName)
  207. QueueAdminFree(qi.szLinkName);
  208. Exit:
  209. if (prstrDefaultDomain)
  210. prstrDefaultDomain->Release();
  211. TraceFunctLeave();
  212. return hr;
  213. }
  214. //---[ CLocalLinkMsgQueue::HrApplyActionToLink ]-------------------------------
  215. //
  216. //
  217. // Description:
  218. // Applies the specified QueueAdmin action to this link
  219. // Parameters:
  220. // IN la Link action to apply
  221. // Returns:
  222. // S_OK on success
  223. // E_INVALIDARG if bogus action is given
  224. // History:
  225. // 2/23/99 - MikeSwa Created
  226. //
  227. //-----------------------------------------------------------------------------
  228. STDMETHODIMP CLocalLinkMsgQueue::HrApplyActionToLink(LINK_ACTION la)
  229. {
  230. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
  231. HRESULT hr = S_OK;
  232. //It is important to release that it does not make sense to re-apply these
  233. //actions back to the LMQ, becuase it is actually the CAsyncRetryQueue
  234. //that affects the state of this.
  235. _ASSERT(m_paradmq);
  236. if (LA_KICK == la)
  237. {
  238. //kick the link
  239. m_paradmq->StartRetry();
  240. }
  241. else if (LA_FREEZE == la)
  242. {
  243. //Admin wants this link to stop sending mail inbound to the store
  244. m_paradmq->FreezeQueue();
  245. }
  246. else if (LA_THAW == la)
  247. {
  248. //Thaw that which was previously frozen
  249. m_paradmq->ThawQueue();
  250. }
  251. else
  252. {
  253. //invalid arg
  254. hr = E_INVALIDARG;
  255. goto Exit;
  256. }
  257. Exit:
  258. TraceFunctLeave();
  259. return hr;
  260. }
  261. //---[ CLocalLinkMsgQueue::HrGetNumQueues ]------------------------------------
  262. //
  263. //
  264. // Description:
  265. // Returns the number of queues on this link
  266. // Parameters:
  267. // OUT pcQueues # numbr of queues
  268. // Returns:
  269. // S_OK on success
  270. // E_POINTER if pcQueues is not valid
  271. // History:
  272. // 2/23/99 - MikeSwa Created
  273. //
  274. //-----------------------------------------------------------------------------
  275. STDMETHODIMP CLocalLinkMsgQueue::HrGetNumQueues(DWORD *pcQueues)
  276. {
  277. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
  278. HRESULT hr = S_OK;
  279. hr = CLinkMsgQueue::HrGetNumQueues(pcQueues);
  280. if (SUCCEEDED(hr))
  281. {
  282. _ASSERT(pcQueues);
  283. (*pcQueues)++; //Add extra count for local async queue
  284. }
  285. TraceFunctLeave();
  286. return hr;
  287. }
  288. //---[ CLinkMsgQueue::HrGetQueueIDs ]--------------------------------------------
  289. //
  290. //
  291. // Description:
  292. // Gets the Queue IDs for DMQs associated with this link. Used by Queue
  293. // Admin.
  294. // Parameters:
  295. // IN OUT pcQueues Sizeof array/ number of queues found
  296. // IN OUT rgQueues Array to dump queue info into
  297. // Returns:
  298. // S_OK on success
  299. // E_OUTOFMEMORY on out of memory failure
  300. // HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) if array is too small
  301. // History:
  302. // 2/23/99 - MikeSwa Created
  303. //
  304. //-----------------------------------------------------------------------------
  305. STDMETHODIMP CLocalLinkMsgQueue::HrGetQueueIDs(
  306. DWORD *pcQueues,
  307. QUEUELINK_ID *rgQueues)
  308. {
  309. TraceFunctEnterEx((LPARAM) this, "CLocalLinkMsgQueue::HrApplyQueueAdminFunction");
  310. _ASSERT(pcQueues);
  311. _ASSERT(rgQueues);
  312. HRESULT hr = S_OK;
  313. //Check to make sure we have room for the additional queue ID
  314. if (*pcQueues < (m_cQueues+1))
  315. {
  316. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  317. goto Exit;
  318. }
  319. //Make sure that thread-safe check in CLinkMsgQueue allows room
  320. //for our local queue.
  321. (*pcQueues)--;
  322. hr = CLinkMsgQueue::HrGetQueueIDs(pcQueues, rgQueues);
  323. if (FAILED(hr))
  324. {
  325. //Tell caller we need room for our queue as well
  326. if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
  327. (*pcQueues)++;
  328. goto Exit;
  329. }
  330. hr = m_paradmq->HrGetQueueID(&rgQueues[*pcQueues]);
  331. if (FAILED(hr))
  332. goto Exit;
  333. (*pcQueues)++;
  334. Exit:
  335. TraceFunctLeave();
  336. return hr;
  337. }