Source code of Windows XP (NT5)
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.

399 lines
8.6 KiB

  1. // esh.cpp: implementation of the CEventScriptHandler class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. //#include "stdafx.h"
  5. #include <esh.h>
  6. #include <scripto.h>
  7. #include <pbag.h>
  8. #include <stags.h>
  9. //////////////////////////////////////////////////////////////////////
  10. // Construction/Destruction
  11. //////////////////////////////////////////////////////////////////////
  12. CEventScriptHandler::CEventScriptHandler()
  13. {
  14. m_cNamedProps = 0;
  15. m_pScripto = NULL;
  16. m_pBag = new CPropBag;
  17. VariantInit(&m_varErrorResponse);
  18. VariantInit(&m_varScriptResponse);
  19. }
  20. CEventScriptHandler::~CEventScriptHandler()
  21. {
  22. if( m_pBag != NULL )
  23. m_pBag->Release();
  24. if( m_pScripto != NULL )
  25. m_pScripto->Release();
  26. }
  27. STDMETHODIMP CEventScriptHandler::SetScript(BSTR bstrFileName)
  28. {
  29. HRESULT hr = NOERROR;
  30. HANDLE hFile = INVALID_HANDLE_VALUE;
  31. CStreamFile* pstmFile = NULL;
  32. if( bstrFileName == NULL )
  33. return E_POINTER;
  34. if( m_pBag == NULL )
  35. return E_OUTOFMEMORY;
  36. hFile = CreateFileW(bstrFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
  37. OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  38. if( hFile == INVALID_HANDLE_VALUE )
  39. {
  40. hr = HRGetLastError();
  41. goto exit;
  42. }
  43. pstmFile = new CStreamFile(hFile,TRUE);
  44. if( pstmFile == NULL )
  45. {
  46. CloseHandle(hFile);
  47. hr = E_OUTOFMEMORY;
  48. goto exit;
  49. }
  50. hr = SetScript((IStream*)pstmFile);
  51. exit:
  52. if( pstmFile != NULL )
  53. pstmFile->Release();
  54. return hr;
  55. }
  56. STDMETHODIMP CEventScriptHandler::SetScript(IStream * pstmScript)
  57. {
  58. HRESULT hr = NOERROR;
  59. VARIANT var;
  60. IUnknown* pUnk = NULL;
  61. if( pstmScript == NULL )
  62. return E_POINTER;
  63. if( m_pBag == NULL )
  64. return E_OUTOFMEMORY;
  65. hr = pstmScript->QueryInterface(IID_IUnknown,(void**)&pUnk);
  66. if(FAILED(hr))
  67. goto exit;
  68. // put the script stream into the bag
  69. V_VT(&var) = VT_UNKNOWN;
  70. V_UNKNOWN(&var) = (IUnknown*)pUnk;
  71. hr = m_pBag->Write(wszScriptTextProp, &var);
  72. VariantClear(&var);
  73. exit:
  74. return hr;
  75. }
  76. STDMETHODIMP CEventScriptHandler::AddGlobalVariable(BSTR bstrName, VARIANT varVariable)
  77. {
  78. HRESULT hr = NOERROR;
  79. WCHAR wszBagProp[64] = {0};
  80. VARIANT var;
  81. if( bstrName == NULL )
  82. return E_POINTER;
  83. if( m_pBag == NULL )
  84. return E_OUTOFMEMORY;
  85. VariantInit(&var);
  86. m_cNamedProps++;
  87. // add the name
  88. V_VT(&var) = VT_BSTR;
  89. V_BSTR(&var) = SysAllocString(bstrName);
  90. wsprintfW(wszBagProp, L"%ls%ld", wszNamedPropIDPrefix, m_cNamedProps);
  91. hr = m_pBag->Write(wszBagProp, &var);
  92. VariantClear(&var);
  93. if(FAILED(hr))
  94. goto exit;
  95. // add the value
  96. wsprintfW(wszBagProp, L"%ls%ld", wszNamedUnkPtrPrefix, m_cNamedProps);
  97. hr = m_pBag->Write(wszBagProp, &varVariable);
  98. if(FAILED(hr))
  99. goto exit;
  100. // not a NamedSource (for connection points)
  101. V_VT(&var) = VT_BOOL;
  102. V_BOOL(&var) = VARIANT_FALSE;
  103. wsprintfW(wszBagProp, L"%ls%ld", wszNamedSourcesPrefix, m_cNamedProps);
  104. hr = m_pBag->Write(wszBagProp, &var);
  105. if(FAILED(hr))
  106. goto exit;
  107. exit:
  108. return hr;
  109. }
  110. STDMETHODIMP CEventScriptHandler::AddConnectionPoint(BSTR bstrName, IConnectionPointContainer * pContainer)
  111. {
  112. HRESULT hr = NOERROR;
  113. WCHAR wszBagProp[64] = {0};
  114. VARIANT var;
  115. if( bstrName == NULL || pContainer == NULL )
  116. return E_POINTER;
  117. if( m_pBag == NULL )
  118. return E_OUTOFMEMORY;
  119. VariantInit(&var);
  120. m_cNamedProps++;
  121. // add the name
  122. V_VT(&var) = VT_BSTR;
  123. V_BSTR(&var) = SysAllocString(bstrName);
  124. wsprintfW(wszBagProp, L"%ls%ld", wszNamedPropIDPrefix, m_cNamedProps);
  125. hr = m_pBag->Write(wszBagProp, &var);
  126. VariantClear(&var);
  127. if(FAILED(hr))
  128. goto exit;
  129. // add the value as IUnknown*
  130. V_VT(&var) = VT_UNKNOWN;
  131. hr = pContainer->QueryInterface(IID_IUnknown, (void**)&V_UNKNOWN(&var));
  132. if(FAILED(hr))
  133. goto exit;
  134. wsprintfW(wszBagProp, L"%ls%ld", wszNamedUnkPtrPrefix, m_cNamedProps);
  135. hr = m_pBag->Write(wszBagProp, &var);
  136. VariantClear(&var);
  137. if(FAILED(hr))
  138. goto exit;
  139. // the object is a NamedSource, so we will connect to
  140. // script functions that look like <Object>_xxx
  141. V_VT(&var) = VT_BOOL;
  142. V_BOOL(&var) = VARIANT_TRUE;
  143. wsprintfW(wszBagProp, L"%ls%ld", wszNamedSourcesPrefix, m_cNamedProps);
  144. hr = m_pBag->Write(wszBagProp, &var);
  145. if(FAILED(hr))
  146. goto exit;
  147. exit:
  148. return hr;
  149. }
  150. STDMETHODIMP CEventScriptHandler::ASPSyntax(BOOL fIsASPSyntax)
  151. {
  152. HRESULT hr = NOERROR;
  153. VARIANT var;
  154. if( m_pBag == NULL )
  155. return E_OUTOFMEMORY;
  156. V_VT(&var) = VT_BOOL;
  157. V_BOOL(&var) = fIsASPSyntax ? VARIANT_TRUE : VARIANT_FALSE ;
  158. hr = m_pBag->Write(wszASPSyntaxProp, &var);
  159. return hr;
  160. }
  161. STDMETHODIMP CEventScriptHandler::AllowCreateObject(BOOL fCreateObjectAllowed)
  162. {
  163. HRESULT hr = NOERROR;
  164. VARIANT var;
  165. if( m_pBag == NULL )
  166. return E_OUTOFMEMORY;
  167. V_VT(&var) = VT_BOOL;
  168. V_BOOL(&var) = fCreateObjectAllowed ? VARIANT_TRUE : VARIANT_FALSE ;
  169. hr = m_pBag->Write(wszEnableCreateObjects, &var);
  170. return hr;
  171. }
  172. STDMETHODIMP CEventScriptHandler::MaxExecutionTime(DWORD dwMaxExecutionTime)
  173. {
  174. HRESULT hr = NOERROR;
  175. VARIANT var;
  176. if( m_pBag == NULL )
  177. return E_OUTOFMEMORY;
  178. V_VT(&var) = VT_UI4;
  179. V_UI4(&var) = dwMaxExecutionTime;
  180. hr = m_pBag->Write(wszMaxExecutionTimeProp, &var);
  181. return hr;
  182. }
  183. STDMETHODIMP CEventScriptHandler::StartScript()
  184. {
  185. HRESULT hr = NOERROR;
  186. VARIANT var;
  187. if( m_pBag == NULL )
  188. return E_OUTOFMEMORY;
  189. if( m_pScripto != NULL )
  190. return RestartScript();
  191. // write the number of named props to pBag
  192. V_VT(&var) = VT_UI4;
  193. V_UI4(&var) = m_cNamedProps;
  194. hr = m_pBag->Write(wszNumNamedPropsProp, &var);
  195. if(FAILED(hr))
  196. goto exit;
  197. // create the scripto object
  198. hr = CoCreateInstance(CLSID_Scripto, NULL, CLSCTX_INPROC_SERVER, IID_IScripto, (void**)&m_pScripto);
  199. if(FAILED(hr))
  200. goto exit;
  201. // init the script
  202. hr = m_pScripto->InitScript(m_pBag);
  203. if( FAILED(hr) )
  204. {
  205. VariantClear(&m_varErrorResponse);
  206. m_pBag->Read(wszErrorResponse, &m_varErrorResponse, NULL);
  207. }
  208. else
  209. {
  210. VariantClear(&m_varScriptResponse);
  211. m_pBag->Read(wszScriptResponse, &m_varScriptResponse, NULL);
  212. }
  213. exit:
  214. return hr;
  215. }
  216. STDMETHODIMP CEventScriptHandler::RestartScript()
  217. {
  218. HRESULT hr = NOERROR;
  219. if( m_pScripto == NULL )
  220. return E_OUTOFMEMORY;
  221. if( !m_fScriptStopped )
  222. StopScript();
  223. hr = m_pScripto->ReInitScript(NULL);
  224. return hr;
  225. }
  226. STDMETHODIMP CEventScriptHandler::StopScript()
  227. {
  228. HRESULT hr = NOERROR;
  229. if( m_pScripto == NULL )
  230. return E_OUTOFMEMORY;
  231. hr = m_pScripto->DeActivateScript(FALSE);
  232. m_fScriptStopped = TRUE;
  233. return hr;
  234. }
  235. STDMETHODIMP CEventScriptHandler::ExecuteConnectionPoint(IConnectionPoint* pConnectionPoint, DISPID dispid)
  236. {
  237. HRESULT hr = NOERROR;
  238. IEnumConnections* pConnections = NULL;
  239. CONNECTDATA ConnectData = {0};
  240. LPDISPATCH pConnection = NULL;
  241. DWORD cConnections = 0;
  242. DISPPARAMS NoArgs = {NULL, NULL, 0, 0};
  243. bool fGotOne = false;
  244. if( pConnectionPoint == NULL )
  245. return E_POINTER;
  246. if( m_pScripto == NULL )
  247. return E_OUTOFMEMORY;
  248. // find out if the script has any connections for this event
  249. hr = pConnectionPoint->EnumConnections(&pConnections);
  250. if(hr == S_FALSE)
  251. {
  252. // No connection points.
  253. hr = DISP_E_UNKNOWNNAME;
  254. goto exit;
  255. }
  256. else if( FAILED(hr) )
  257. goto exit;
  258. hr = pConnections->Reset();
  259. if( FAILED(hr) )
  260. goto exit;
  261. // loop through each connection and execute its associated code
  262. do
  263. {
  264. hr = pConnections->Next(1, &ConnectData, &cConnections);
  265. if(SUCCEEDED(hr))
  266. {
  267. if(cConnections)
  268. {
  269. hr = ConnectData.pUnk->QueryInterface(IID_IDispatch, (void**)&pConnection);
  270. if(SUCCEEDED(hr))
  271. {
  272. // try to invoke - this may fail non-fatally
  273. hr = pConnection->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &NoArgs, NULL, NULL, NULL);
  274. if(hr != DISP_E_UNKNOWNNAME)
  275. {
  276. // we at least got one connection point
  277. fGotOne = true;
  278. if( FAILED(hr) )
  279. {
  280. // event execution failed
  281. VariantClear(&m_varErrorResponse);
  282. m_pBag->Read(wszErrorResponse, &m_varErrorResponse, NULL);
  283. m_pScripto->Abort();
  284. }
  285. else
  286. {
  287. VariantClear(&m_varScriptResponse);
  288. m_pBag->Read(wszScriptResponse, &m_varScriptResponse, NULL);
  289. m_pScripto->Complete();
  290. }
  291. }
  292. pConnection->Release();
  293. pConnection = NULL;
  294. }
  295. ConnectData.pUnk->Release();
  296. ConnectData.pUnk = NULL;
  297. }
  298. else
  299. {
  300. // means we are done - no more connections
  301. // if we got at least one to work then we consider it
  302. // a success
  303. hr = fGotOne ? S_OK : DISP_E_UNKNOWNNAME;
  304. }
  305. }
  306. }
  307. while(SUCCEEDED(hr) && cConnections);
  308. // tell scripto whether we are happy campers or not
  309. if(SUCCEEDED(hr))
  310. {
  311. m_pScripto->Complete();
  312. }
  313. else
  314. {
  315. m_pScripto->Abort();
  316. }
  317. // must leave scripto in the deactived state so that it can be
  318. // called again on another thread
  319. m_pScripto->DeActivateScript(false);
  320. exit:
  321. if( pConnections )
  322. pConnections->Release();
  323. return hr;
  324. }