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.

165 lines
3.7 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. #include "precomp.h"
  8. #include <assert.h>
  9. #include "multsend.h"
  10. /*****************************************************************
  11. CMsgMultiSendReceive - Implements the list of senders using a circular
  12. list. This allows us to easily advance the current sender when
  13. encountering failures. MultiSendReceive remembers the last good sender.
  14. It will keep using this until it has a problem with it.
  15. ******************************************************************/
  16. CMsgMultiSendReceive::~CMsgMultiSendReceive()
  17. {
  18. if ( m_pTail == NULL )
  19. {
  20. return;
  21. }
  22. SenderNode* pCurr = m_pTail->m_pNext;
  23. while( pCurr != m_pTail )
  24. {
  25. SenderNode* pTmp = pCurr->m_pNext;
  26. delete pCurr;
  27. pCurr = pTmp;
  28. }
  29. delete m_pTail;
  30. }
  31. //
  32. // Later, we could support flags that tell us where to add the sender.
  33. // for now, we always add to the end of the list.
  34. //
  35. HRESULT CMsgMultiSendReceive::Add( DWORD dwFlags,
  36. IWmiMessageSendReceive* pSndRcv)
  37. {
  38. ENTER_API_CALL
  39. HRESULT hr;
  40. SenderNode* pNew = new SenderNode;
  41. if ( pNew == NULL )
  42. {
  43. return WBEM_E_OUT_OF_MEMORY;
  44. }
  45. pNew->m_pVal = pSndRcv;
  46. CInCritSec ics(&m_cs);
  47. if ( m_pTail != NULL )
  48. {
  49. pNew->m_pNext = m_pTail->m_pNext;
  50. m_pTail->m_pNext = pNew;
  51. }
  52. else
  53. {
  54. m_pPrimary = pNew;
  55. pNew->m_pNext = pNew;
  56. }
  57. //
  58. // if the sender is also a multi sender, we handle things differently
  59. // in the send logic.
  60. //
  61. if ( dwFlags & WMIMSG_FLAG_MULTISEND_TERMINATING_SENDER )
  62. {
  63. pNew->m_bTermSender = TRUE;
  64. }
  65. else
  66. {
  67. pNew->m_bTermSender = FALSE;
  68. }
  69. m_pTail = pNew;
  70. return S_OK;
  71. EXIT_API_CALL
  72. }
  73. //
  74. // returns S_FALSE when succeeded but primary is not used.
  75. //
  76. HRESULT CMsgMultiSendReceive::SendReceive( PBYTE pData,
  77. ULONG cData,
  78. PBYTE pAuxData,
  79. ULONG cAuxData,
  80. DWORD dwFlags,
  81. IUnknown* pCtx )
  82. {
  83. ENTER_API_CALL
  84. HRESULT hr;
  85. CInCritSec ics( &m_cs );
  86. if ( m_pTail == NULL )
  87. {
  88. return S_OK;
  89. }
  90. HRESULT hrReturn = S_OK;
  91. SenderNode* pCurr = m_pTail;
  92. SenderNode* pTerm = m_pTail;
  93. do
  94. {
  95. pCurr = pCurr->m_pNext;
  96. hr = pCurr->m_pVal->SendReceive( pData,
  97. cData,
  98. pAuxData,
  99. cAuxData,
  100. dwFlags,
  101. pCtx );
  102. //
  103. // on error we only observe the 'return immediately' flag if we are not
  104. // calling another multi sender. This allows all the terminal primary
  105. // senders to be tried first, before resorting to alternates.
  106. //
  107. if( SUCCEEDED(hr) ||
  108. pCurr->m_bTermSender &&
  109. dwFlags & WMIMSG_FLAG_MULTISEND_RETURN_IMMEDIATELY )
  110. {
  111. hrReturn = hr;
  112. break;
  113. }
  114. else
  115. {
  116. m_pTail = m_pTail->m_pNext;
  117. hrReturn = hr;
  118. }
  119. } while( pCurr != pTerm );
  120. if ( hrReturn != S_OK )
  121. {
  122. return hrReturn;
  123. }
  124. return m_pTail->m_pNext == m_pPrimary ? S_OK : S_FALSE;
  125. EXIT_API_CALL
  126. }