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.

400 lines
11 KiB

  1. // Copyright (c) 1999 Microsoft Corporation. All rights reserved.
  2. //
  3. // Declaration of CSingleThreadedActiveScriptManager.
  4. //
  5. #include "stdinc.h"
  6. #include "scriptthread.h"
  7. #include "activescript.h"
  8. #include "workthread.h"
  9. #define S_STD_PARAMS ScriptManager *pmgr; HRESULT *phr;
  10. CWorkerThread CSingleThreadedScriptManager::ms_Thread(true, true);
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction
  13. struct S_Create
  14. {
  15. CSingleThreadedScriptManager *_this;
  16. bool fUseOleAut;
  17. const WCHAR *pwszLanguage;
  18. const WCHAR *pwszSource;
  19. CDirectMusicScript *pParentScript;
  20. HRESULT *phr;
  21. DMUS_SCRIPT_ERRORINFO *pErrorInfo;
  22. };
  23. void F_Create(void *pvParams)
  24. {
  25. S_Create *pS = reinterpret_cast<S_Create*>(pvParams);
  26. pS->_this->m_pScriptManager = new CActiveScriptManager(pS->fUseOleAut, pS->pwszLanguage, pS->pwszSource, pS->pParentScript, pS->phr, pS->pErrorInfo);
  27. }
  28. CSingleThreadedScriptManager::CSingleThreadedScriptManager(
  29. bool fUseOleAut,
  30. const WCHAR *pwszLanguage,
  31. const WCHAR *pwszSource,
  32. CDirectMusicScript *pParentScript,
  33. HRESULT *phr,
  34. DMUS_SCRIPT_ERRORINFO *pErrorInfo)
  35. : m_pScriptManager(NULL)
  36. {
  37. S_Create S = { this, fUseOleAut, pwszLanguage, pwszSource, pParentScript, phr, pErrorInfo };
  38. HRESULT hr = ms_Thread.Create();
  39. if (SUCCEEDED(hr))
  40. {
  41. hr = ms_Thread.Call(F_Create, &S, sizeof(S), true);
  42. }
  43. if (FAILED(hr)) // Only overwrite phr if the call itself failed. Otherwise the call itself sets phr via struct S.
  44. *phr = hr;
  45. }
  46. //////////////////////////////////////////////////////////////////////
  47. // Start
  48. struct S_Start
  49. {
  50. S_STD_PARAMS
  51. DMUS_SCRIPT_ERRORINFO *pErrorInfo;
  52. };
  53. void F_Start(void *pvParams)
  54. {
  55. S_Start *pS = reinterpret_cast<S_Start*>(pvParams);
  56. *pS->phr = pS->pmgr->Start(pS->pErrorInfo);
  57. }
  58. HRESULT
  59. CSingleThreadedScriptManager ::Start(DMUS_SCRIPT_ERRORINFO *pErrorInfo)
  60. {
  61. HRESULT hr = E_FAIL;
  62. S_Start S = { m_pScriptManager, &hr, pErrorInfo };
  63. HRESULT hrThreadCall = ms_Thread.Call(F_Start, &S, sizeof(S), true);
  64. if (FAILED(hrThreadCall))
  65. return hrThreadCall;
  66. return hr;
  67. }
  68. //////////////////////////////////////////////////////////////////////
  69. // CallRoutine
  70. struct S_CallRoutine
  71. {
  72. S_STD_PARAMS
  73. const WCHAR *pwszRoutineName;
  74. DMUS_SCRIPT_ERRORINFO *pErrorInfo;
  75. };
  76. void F_CallRoutine(void *pvParams)
  77. {
  78. S_CallRoutine *pS = reinterpret_cast<S_CallRoutine*>(pvParams);
  79. *pS->phr = pS->pmgr->CallRoutine(pS->pwszRoutineName, pS->pErrorInfo);
  80. }
  81. HRESULT CSingleThreadedScriptManager::CallRoutine(const WCHAR *pwszRoutineName, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
  82. {
  83. HRESULT hr = E_FAIL;
  84. S_CallRoutine S = { m_pScriptManager, &hr, pwszRoutineName, pErrorInfo };
  85. HRESULT hrThreadCall = ms_Thread.Call(F_CallRoutine, &S, sizeof(S), true);
  86. if (FAILED(hrThreadCall))
  87. return hrThreadCall;
  88. return hr;
  89. }
  90. //////////////////////////////////////////////////////////////////////
  91. // ScriptTrackCallRoutine
  92. struct S_ScriptTrackCallRoutine
  93. {
  94. S_STD_PARAMS
  95. IDirectMusicSegmentState *pSegSt;
  96. DWORD dwVirtualTrackID;
  97. bool fErrorPMsgsEnabled;
  98. __int64 i64IntendedStartTime;
  99. DWORD dwIntendedStartTimeFlags;
  100. WCHAR wszRoutineName[1]; // dynamically allocate extra space to hold the actual string within this structure
  101. };
  102. void F_ScriptTrackCallRoutine(void *pvParams)
  103. {
  104. S_ScriptTrackCallRoutine *pS = reinterpret_cast<S_ScriptTrackCallRoutine*>(pvParams);
  105. pS->pmgr->ScriptTrackCallRoutine(
  106. pS->wszRoutineName,
  107. pS->pSegSt,
  108. pS->dwVirtualTrackID,
  109. pS->fErrorPMsgsEnabled,
  110. pS->i64IntendedStartTime,
  111. pS->dwIntendedStartTimeFlags);
  112. pS->pSegSt->Release(); // release the interface held in CSingleThreadedScriptManager::ScriptTrackCallRoutine
  113. }
  114. HRESULT CSingleThreadedScriptManager::ScriptTrackCallRoutine(
  115. const WCHAR *pwszRoutineName,
  116. IDirectMusicSegmentState *pSegSt,
  117. DWORD dwVirtualTrackID,
  118. bool fErrorPMsgsEnabled,
  119. __int64 i64IntendedStartTime,
  120. DWORD dwIntendedStartTimeFlags)
  121. {
  122. // We need to allocate the structure with extra space to hold the routine name. This is because
  123. // the call is asynchonous so a copy of the text will be needed because copying the pwszRoutineName
  124. // would fail because we can't be sure the string it points to will remain be allocated.
  125. int cbS = sizeof(S_ScriptTrackCallRoutine) + (sizeof(WCHAR) * wcslen(pwszRoutineName));
  126. S_ScriptTrackCallRoutine *pS = reinterpret_cast<S_ScriptTrackCallRoutine *>(new char[cbS]);
  127. if (!pS)
  128. return E_OUTOFMEMORY;
  129. pS->pmgr = m_pScriptManager;
  130. pS->phr = NULL;
  131. pS->pSegSt = pSegSt;
  132. pS->pSegSt->AddRef(); // hold a ref because the call is asynchronous and the interface we were passed may be released
  133. pS->dwVirtualTrackID = dwVirtualTrackID;
  134. pS->fErrorPMsgsEnabled = fErrorPMsgsEnabled;
  135. pS->i64IntendedStartTime = i64IntendedStartTime;
  136. pS->dwIntendedStartTimeFlags = dwIntendedStartTimeFlags;
  137. wcscpy(pS->wszRoutineName, pwszRoutineName);
  138. // Call asynchronously. Needed to avoid deadlocks between the VBScript thread and
  139. // performance or to avoid blocking the performance if the VBScript routine goes into
  140. // a long loop. VVVVV
  141. HRESULT hrThreadCall = ms_Thread.Call(F_ScriptTrackCallRoutine, pS, cbS, false);
  142. delete [] reinterpret_cast<char *>(pS);
  143. return hrThreadCall;
  144. }
  145. //////////////////////////////////////////////////////////////////////
  146. // SetVariable
  147. struct S_SetVariable
  148. {
  149. S_STD_PARAMS
  150. const WCHAR *pwszVariableName;
  151. VARIANT *pvarValue; // pass struct by reference
  152. bool fSetRef;
  153. DMUS_SCRIPT_ERRORINFO *pErrorInfo;
  154. };
  155. void F_SetVariable(void *pvParams)
  156. {
  157. S_SetVariable *pS = reinterpret_cast<S_SetVariable*>(pvParams);
  158. *pS->phr = pS->pmgr->SetVariable(pS->pwszVariableName, *pS->pvarValue, pS->fSetRef, pS->pErrorInfo);
  159. }
  160. HRESULT CSingleThreadedScriptManager::SetVariable(const WCHAR *pwszVariableName, VARIANT varValue, bool fSetRef, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
  161. {
  162. HRESULT hr = E_FAIL;
  163. S_SetVariable S = { m_pScriptManager, &hr, pwszVariableName, &varValue, fSetRef, pErrorInfo };
  164. HRESULT hrThreadCall = ms_Thread.Call(F_SetVariable, &S, sizeof(S), true);
  165. if (FAILED(hrThreadCall))
  166. return hrThreadCall;
  167. return hr;
  168. }
  169. //////////////////////////////////////////////////////////////////////
  170. // GetVariable
  171. struct S_GetVariable
  172. {
  173. S_STD_PARAMS
  174. const WCHAR *pwszVariableName;
  175. VARIANT *pvarValue;
  176. DMUS_SCRIPT_ERRORINFO *pErrorInfo;
  177. };
  178. void F_GetVariable(void *pvParams)
  179. {
  180. S_GetVariable *pS = reinterpret_cast<S_GetVariable*>(pvParams);
  181. *pS->phr = pS->pmgr->GetVariable(pS->pwszVariableName, pS->pvarValue, pS->pErrorInfo);
  182. }
  183. HRESULT CSingleThreadedScriptManager::GetVariable(const WCHAR *pwszVariableName, VARIANT *pvarValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
  184. {
  185. HRESULT hr = E_FAIL;
  186. S_GetVariable S = { m_pScriptManager, &hr, pwszVariableName, pvarValue, pErrorInfo };
  187. HRESULT hrThreadCall = ms_Thread.Call(F_GetVariable, &S, sizeof(S), true);
  188. if (FAILED(hrThreadCall))
  189. return hrThreadCall;
  190. return hr;
  191. }
  192. //////////////////////////////////////////////////////////////////////
  193. // EnumRoutine
  194. struct S_EnumItem
  195. {
  196. S_STD_PARAMS
  197. bool fRoutine;
  198. DWORD dwIndex;
  199. WCHAR *pwszName;
  200. int *pcItems;
  201. };
  202. void F_EnumItem(void *pvParams)
  203. {
  204. S_EnumItem *pS = reinterpret_cast<S_EnumItem*>(pvParams);
  205. *pS->phr = pS->pmgr->EnumItem(pS->fRoutine, pS->dwIndex, pS->pwszName, pS->pcItems);
  206. }
  207. HRESULT CSingleThreadedScriptManager::EnumItem(bool fRoutine, DWORD dwIndex, WCHAR *pwszName, int *pcItems)
  208. {
  209. HRESULT hr = E_FAIL;
  210. S_EnumItem S = { m_pScriptManager, &hr, fRoutine, dwIndex, pwszName, pcItems };
  211. HRESULT hrThreadCall = ms_Thread.Call(F_EnumItem, &S, sizeof(S), true);
  212. if (FAILED(hrThreadCall))
  213. return hrThreadCall;
  214. return hr;
  215. }
  216. //////////////////////////////////////////////////////////////////////
  217. // DispGetIDsOfNames
  218. struct S_DispGetIDsOfNames
  219. {
  220. S_STD_PARAMS
  221. const IID *piid; // use pointer instead of reference to leave struct as simple aggregate type
  222. LPOLESTR __RPC_FAR *rgszNames;
  223. UINT cNames;
  224. LCID lcid;
  225. DISPID *rgDispId;
  226. };
  227. void F_DispGetIDsOfNames(void *pvParams)
  228. {
  229. S_DispGetIDsOfNames *pS = reinterpret_cast<S_DispGetIDsOfNames*>(pvParams);
  230. *pS->phr = pS->pmgr->DispGetIDsOfNames(*pS->piid, pS->rgszNames, pS->cNames, pS->lcid, pS->rgDispId);
  231. }
  232. HRESULT CSingleThreadedScriptManager::DispGetIDsOfNames(REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId)
  233. {
  234. HRESULT hr = E_FAIL;
  235. S_DispGetIDsOfNames S = { m_pScriptManager, &hr, &riid, rgszNames, cNames, lcid, rgDispId };
  236. HRESULT hrThreadCall = ms_Thread.Call(F_DispGetIDsOfNames, &S, sizeof(S), true);
  237. if (FAILED(hrThreadCall))
  238. return hrThreadCall;
  239. return hr;
  240. }
  241. //////////////////////////////////////////////////////////////////////
  242. // DispInvoke
  243. struct S_DispInvoke
  244. {
  245. S_STD_PARAMS
  246. DISPID dispIdMember;
  247. const IID *piid; // use pointer instead of reference to leave struct as simple aggregate type
  248. LCID lcid;
  249. WORD wFlags;
  250. DISPPARAMS __RPC_FAR *pDispParams;
  251. VARIANT __RPC_FAR *pVarResult;
  252. EXCEPINFO __RPC_FAR *pExcepInfo;
  253. UINT __RPC_FAR *puArgErr;
  254. };
  255. void F_DispInvoke(void *pvParams)
  256. {
  257. S_DispInvoke *pS = reinterpret_cast<S_DispInvoke*>(pvParams);
  258. *pS->phr = pS->pmgr->DispInvoke(pS->dispIdMember, *pS->piid, pS->lcid, pS->wFlags, pS->pDispParams, pS->pVarResult, pS->pExcepInfo, pS->puArgErr);
  259. }
  260. HRESULT CSingleThreadedScriptManager::DispInvoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS __RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr)
  261. {
  262. HRESULT hr = E_FAIL;
  263. S_DispInvoke S = { m_pScriptManager, &hr, dispIdMember, &riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr };
  264. HRESULT hrThreadCall = ms_Thread.Call(F_DispInvoke, &S, sizeof(S), true);
  265. if (FAILED(hrThreadCall))
  266. return hrThreadCall;
  267. return hr;
  268. }
  269. //////////////////////////////////////////////////////////////////////
  270. // Close
  271. struct S_Close
  272. {
  273. ScriptManager *pmgr;
  274. };
  275. void F_Close(void *pvParams)
  276. {
  277. S_Close *pS = reinterpret_cast<S_Close*>(pvParams);
  278. pS->pmgr->Close();
  279. }
  280. void CSingleThreadedScriptManager::Close()
  281. {
  282. S_Close S = { m_pScriptManager };
  283. ms_Thread.Call(F_Close, &S, sizeof(S), true);
  284. }
  285. //////////////////////////////////////////////////////////////////////
  286. // Release
  287. struct S_Release
  288. {
  289. ScriptManager *pmgr;
  290. DWORD *pdw;
  291. };
  292. void F_Release(void *pvParams)
  293. {
  294. S_Release *pS = reinterpret_cast<S_Release*>(pvParams);
  295. *pS->pdw = pS->pmgr->Release();
  296. }
  297. STDMETHODIMP_(ULONG)
  298. CSingleThreadedScriptManager::Release()
  299. {
  300. DWORD dw = 1;
  301. S_Release S = { m_pScriptManager, &dw };
  302. if (m_pScriptManager) // if creation failed, release will be called when m_pScriptManager hasn't been set
  303. {
  304. ms_Thread.Call(F_Release, &S, sizeof(S), true);
  305. }
  306. if (!dw)
  307. delete this;
  308. return dw;
  309. }
  310. /*
  311. Template I used to stamp these things out...
  312. //////////////////////////////////////////////////////////////////////
  313. // XXX
  314. struct S_XXX
  315. {
  316. S_STD_PARAMS
  317. YYY
  318. };
  319. void F_XXX(void *pvParams)
  320. {
  321. S_XXX *pS = reinterpret_cast<S_XXX*>(pvParams);
  322. *pS->phr = pS->pmgr->XXX(YYY);
  323. }
  324. HRESULT
  325. CSingleThreadedScriptManager::XXX(YYY)
  326. {
  327. HRESULT hr = E_FAIL;
  328. S_XXX S = { m_pScriptManager, &hr, YYY };
  329. HRESULT hrThreadCall = ms_Thread.Call(F_XXX, &S, sizeof(S), true);
  330. if (FAILED(hrThreadCall))
  331. return hrThreadCall;
  332. return hr;
  333. }
  334. */