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.

221 lines
8.1 KiB

  1. // CMSEventBinder.cpp : Implementation of CMSEventBinder
  2. #include "stdafx.h"
  3. #include "MSVidCtl.h"
  4. #include "CMSEventBinder.h"
  5. #include <dispex.h>
  6. DEFINE_EXTERN_OBJECT_ENTRY(CLSID_MSEventBinder, CMSEventBinder)
  7. /////////////////////////////////////////////////////////////////////////////
  8. // CMSEventBinder
  9. /**********************************************************************
  10. // Function: CMSEventBinder
  11. /**********************************************************************/
  12. STDMETHODIMP CMSEventBinder::InterfaceSupportsErrorInfo(REFIID riid)
  13. {
  14. static const IID* arr[] =
  15. {
  16. &IID_IMSEventBinder,
  17. };
  18. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  19. {
  20. if (InlineIsEqualGUID(*arr[i],riid))
  21. return S_OK;
  22. }
  23. return S_FALSE;
  24. }
  25. /**********************************************************************/
  26. // Function: CleanupConnection
  27. // Description: Unadvises if necessary
  28. /**********************************************************************/
  29. HRESULT CMSEventBinder::CleanupConnection()
  30. {
  31. HRESULT hr = E_FAIL;
  32. try{
  33. // While the map is not empty
  34. while(!m_CancelMap.empty()){
  35. // See if it is bound to an event or an empty map
  36. CMSEventHandler* p(static_cast<CMSEventHandler *>((*m_CancelMap.begin()).second.p));
  37. // If it is not an empty map cancel the eventbinding
  38. if (p) {
  39. p->Cancel((*m_CancelMap.begin()).first);
  40. }
  41. // Delete the mapping
  42. m_CancelMap.erase(m_CancelMap.begin());
  43. }
  44. hr = S_OK;
  45. }
  46. catch(...){
  47. return Error(IDS_CANT_RELEASE_MAP, __uuidof(IMSEventBinder), E_FAIL);
  48. }
  49. return hr;
  50. }/* end of function CleanupConnection */
  51. /**********************************************************************/
  52. // Function: Unbind
  53. // Description: Unbinds an event on an object
  54. /**********************************************************************/
  55. STDMETHODIMP CMSEventBinder::Unbind(DWORD CancelCookie){
  56. HRESULT hr = E_FAIL;
  57. try{
  58. CMSEventHandler* p_Event(static_cast<CMSEventHandler *>((m_CancelMap[CancelCookie]).p));
  59. if(!p_Event){
  60. return Error(IDS_CANT_UNBIND, __uuidof(IMSEventBinder), E_FAIL);
  61. }
  62. hr = p_Event->Cancel(CancelCookie);
  63. if(SUCCEEDED(hr)){
  64. if(!m_CancelMap.erase(CancelCookie)){
  65. return Error(IDS_CANT_UNBIND, __uuidof(IMSEventBinder), E_FAIL);
  66. }
  67. }
  68. }catch(...){
  69. return Error(IDS_CANT_UNBIND, __uuidof(IMSEventBinder), E_FAIL);
  70. }
  71. return hr;
  72. }
  73. /**********************************************************************/
  74. // Function: Bind
  75. // Description: Binds a function to an event on an object
  76. /**********************************************************************/
  77. STDMETHODIMP CMSEventBinder::Bind(LPDISPATCH inPEventObject, BSTR EventName, BSTR EventHandler, LONG *CancelID)
  78. {
  79. try{
  80. HRESULT hr = E_FAIL;
  81. // query eventobject to see if its the dhtml object wrapper rather than the real object
  82. // if so, get its "object" property automatically here to save foolish script programmers from hard to find errors.
  83. CComQIPtr<IDispatch> pEventObject(inPEventObject);
  84. CComQIPtr<IHTMLObjectElement> IHOEle(inPEventObject);
  85. if(IHOEle){
  86. pEventObject.Release();
  87. hr = IHOEle->get_object(&pEventObject);
  88. if(FAILED(hr)){
  89. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  90. }
  91. }
  92. // Get client site
  93. CComQIPtr<IOleClientSite> pSite(m_pSite);
  94. if (!pSite) {
  95. return Error(IDS_EVENT_HTM_SITE, __uuidof(IMSEventBinder), E_FAIL);
  96. }
  97. // Get container
  98. CComQIPtr<IOleContainer> pContainer;
  99. hr = pSite->GetContainer(&pContainer);
  100. if(FAILED(hr)){
  101. return Error(IDS_EVENT_HTM_SITE, __uuidof(IMSEventBinder), E_FAIL);
  102. }
  103. // Get the IHTMLDocumet2 for the container/site
  104. CComQIPtr<IHTMLDocument2> IHDoc(pContainer);
  105. if (!IHDoc) {
  106. return Error(IDS_EVENT_HTM_SITE, __uuidof(IMSEventBinder), E_FAIL);
  107. }
  108. // Get the script which is some object that is not the script engine
  109. CComQIPtr<IDispatch> IDispSite;
  110. hr = IHDoc->get_Script(&IDispSite);
  111. if(FAILED(hr)){
  112. return Error(IDS_EVENT_HTM_SITE, __uuidof(IMSEventBinder), E_FAIL);
  113. }
  114. // Get the function that will be the event handler
  115. DISPID dispidScriptHandler = -1;
  116. hr = IDispSite->GetIDsOfNames(IID_NULL, &EventHandler, 1, LOCALE_SYSTEM_DEFAULT, &dispidScriptHandler);
  117. if(FAILED(hr)){
  118. return Error(IDS_EVENT_HTM_SITE, __uuidof(IMSEventBinder), E_FAIL);
  119. }
  120. // Get info about the object/interface on which the event exsists
  121. CComQIPtr<IProvideClassInfo2> IPCInfo(pEventObject);
  122. if(!IPCInfo){
  123. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  124. }
  125. // Get the guid of the object/interface
  126. GUID gEventObject;
  127. hr = IPCInfo->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, &gEventObject);
  128. if(FAILED(hr)){
  129. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  130. }
  131. // Get type info about the interface/object
  132. CComQIPtr<ITypeInfo> ITInfo;
  133. hr = IPCInfo->GetClassInfo(&ITInfo);
  134. if(FAILED(hr)){
  135. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  136. }
  137. // Get the Type lib
  138. CComQIPtr<ITypeLib> ITLib(ITInfo);
  139. unsigned int uNit;
  140. hr = ITInfo->GetContainingTypeLib(&ITLib, &uNit);
  141. if(FAILED(hr)){
  142. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  143. }
  144. ITInfo.Release();
  145. // Get info about the object/interface's base class
  146. hr = ITLib->GetTypeInfoOfGuid(gEventObject, &ITInfo);
  147. if(FAILED(hr)){
  148. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  149. }
  150. // Get the ID of the event
  151. MEMBERID dispidEvent = 0;
  152. hr = ITInfo->GetIDsOfNames(&EventName, 1, &dispidEvent);
  153. if(FAILED(hr)){
  154. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  155. }
  156. //Create and store the event Handler
  157. CMSEventHandler* pH;
  158. pH = new CMSEventHandler(dispidScriptHandler, dispidEvent, gEventObject, IDispSite);
  159. if(!pH){
  160. return Error(IDS_CANT_GET_EVENTHANDLER, __uuidof(IMSEventBinder), E_FAIL);
  161. }
  162. // Get Connection Point Container
  163. CComQIPtr<IConnectionPointContainer> ICPCon(pEventObject);
  164. if(!ICPCon){
  165. delete pH;
  166. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  167. }
  168. // Find the connection point
  169. CComQIPtr<IConnectionPoint> ICPo;
  170. hr = ICPCon->FindConnectionPoint(gEventObject, &ICPo);
  171. if(FAILED(hr)){
  172. delete pH;
  173. return Error(IDS_EVENT_OBJECT, __uuidof(IMSEventBinder), E_FAIL);
  174. }
  175. // Set the event
  176. DWORD tempCookie;
  177. PQDispatch pdisp(pH); // we have now addref'd and assoc'd ph with a smart pointer, no more deletes necessary
  178. hr = ICPo->Advise(pdisp, &tempCookie);
  179. pH->setCookie(tempCookie);
  180. if(FAILED(hr)){
  181. return Error(IDS_CANT_SET_ADVISE, __uuidof(IMSEventBinder), E_FAIL);
  182. }
  183. // Store all of the needed info
  184. pH->cancelPoint = ICPo;
  185. *CancelID = pH->getCookie();
  186. m_CancelMap[pH->getCookie()] = pH;
  187. }
  188. catch(HRESULT){
  189. return Error(IDS_CANT_SET_ADVISE, __uuidof(IMSEventBinder), E_FAIL);
  190. }
  191. catch(...){
  192. return Error(IDS_CANT_SET_ADVISE, __uuidof(IMSEventBinder), E_UNEXPECTED);
  193. }
  194. // call used to leave a funtion and "return" the value that is the paramater to the calling function
  195. return S_OK;
  196. }