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.

157 lines
4.8 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000 - 2000
  6. //
  7. // File: eventlock.cpp
  8. //
  9. // This file contains code needed to fire script event in a safer way
  10. // Locks made on stack will postpone firing the event on particular interface
  11. // as long as the last lock is released.
  12. //--------------------------------------------------------------------------
  13. #include "stdafx.h"
  14. #include <comdef.h>
  15. #include <vector>
  16. #include <queue>
  17. #include "eventlock.h"
  18. #include "mmcobj.h"
  19. // since the templates will be used from outside the library
  20. // we need to instantiale them explicitly in order to get them exported
  21. template class CEventLock<AppEvents>;
  22. /***************************************************************************\
  23. *
  24. * METHOD: CEventBuffer::CEventBuffer
  25. *
  26. * PURPOSE: Constructor
  27. *
  28. \***************************************************************************/
  29. CEventBuffer::CEventBuffer() : m_locks(0)
  30. {
  31. }
  32. /***************************************************************************\
  33. *
  34. * METHOD: CEventBuffer::CEventBuffer
  35. *
  36. * PURPOSE: Destructor
  37. *
  38. \***************************************************************************/
  39. CEventBuffer::~CEventBuffer()
  40. {
  41. }
  42. /***************************************************************************\
  43. *
  44. * METHOD: CEventBuffer::ScEmitOrPostpone
  45. *
  46. * PURPOSE: The method will add methods to the queue. If interface is not locked
  47. * it will emit it immediately, else it will postpone it till appropriate
  48. * call to Unlock()
  49. *
  50. * PARAMETERS:
  51. * IDispatch *pDispatch - sink interface to receive the event
  52. * DISPID dispid - method's disp id
  53. * CComVariant *pVar - array of arguments to method call
  54. * int count - count of arguments in the array
  55. *
  56. * RETURNS:
  57. * SC - result code
  58. *
  59. \***************************************************************************/
  60. SC CEventBuffer::ScEmitOrPostpone(IDispatch *pDispatch, DISPID dispid, CComVariant *pVar, int count)
  61. {
  62. DECLARE_SC(sc, TEXT("CEventBuffer::ScEmitOrPostpone"));
  63. // construct the postponed data
  64. DispCallStr call_data;
  65. call_data.spDispatch = pDispatch;
  66. call_data.dispid = dispid;
  67. call_data.vars.insert(call_data.vars.begin(), pVar, pVar + count);
  68. // store the data for future use
  69. m_postponed.push(call_data);
  70. // emit rigt away if not locked
  71. if (!IsLocked())
  72. sc = ScFlushPostponed();
  73. return sc;
  74. }
  75. /***************************************************************************\
  76. *
  77. * METHOD: CEventBuffer::ScFlushPostponed
  78. *
  79. * PURPOSE: method will invoke all events currently in it's queue
  80. *
  81. * PARAMETERS:
  82. *
  83. * RETURNS:
  84. * SC - result code
  85. *
  86. \***************************************************************************/
  87. SC CEventBuffer::ScFlushPostponed()
  88. {
  89. DECLARE_SC(sc, TEXT("CEventBuffer::ScFlushPostponed"));
  90. SC sc_last_error;
  91. // for each event in queue
  92. while (m_postponed.size())
  93. {
  94. // ectract event from the queue
  95. DispCallStr call_data = m_postponed.front();
  96. m_postponed.pop();
  97. // check the dispatch pointer
  98. sc = ScCheckPointers(call_data.spDispatch, E_POINTER);
  99. if (sc)
  100. {
  101. sc_last_error = sc; // continue even if some calls failed
  102. sc.TraceAndClear();
  103. continue;
  104. }
  105. // construct parameter structure
  106. CComVariant varResult;
  107. DISPPARAMS disp = { call_data.vars.begin(), NULL, call_data.vars.size(), 0 };
  108. // invoke the method on event sink
  109. sc = call_data.spDispatch->Invoke(call_data.dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
  110. if (sc)
  111. {
  112. sc_last_error = sc; // continue even if some calls failed
  113. sc.TraceAndClear();
  114. continue;
  115. }
  116. // event methods should not return any values.
  117. // but even if the do (thru varResult) - we do not care, just ignore that.
  118. }
  119. // will return sc_last_error (not sc - we already traced it)
  120. return sc_last_error;
  121. }
  122. /***************************************************************************\
  123. *
  124. * FUNCTION: GetEventBuffer
  125. *
  126. * PURPOSE: This function provides access to static object created in it's body
  127. * Having it as template allows us to define as many static objects as
  128. * interfaces we have.
  129. *
  130. * PARAMETERS:
  131. *
  132. * RETURNS:
  133. * CEventBuffer& - reference to the static object created inside
  134. *
  135. \***************************************************************************/
  136. MMCBASE_API CEventBuffer& GetEventBuffer()
  137. {
  138. static CEventBuffer buffer;
  139. return buffer;
  140. }