|
|
// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
//
// Declaration of CSingleThreadedActiveScriptManager.
//
#include "stdinc.h"
#include "scriptthread.h"
#include "activescript.h"
#include "workthread.h"
#define S_STD_PARAMS ScriptManager *pmgr; HRESULT *phr;
CWorkerThread CSingleThreadedScriptManager::ms_Thread(true, true);
//////////////////////////////////////////////////////////////////////
// Construction
struct S_Create { CSingleThreadedScriptManager *_this; bool fUseOleAut; const WCHAR *pwszLanguage; const WCHAR *pwszSource; CDirectMusicScript *pParentScript; HRESULT *phr; DMUS_SCRIPT_ERRORINFO *pErrorInfo; };
void F_Create(void *pvParams) { S_Create *pS = reinterpret_cast<S_Create*>(pvParams); pS->_this->m_pScriptManager = new CActiveScriptManager(pS->fUseOleAut, pS->pwszLanguage, pS->pwszSource, pS->pParentScript, pS->phr, pS->pErrorInfo); }
CSingleThreadedScriptManager::CSingleThreadedScriptManager( bool fUseOleAut, const WCHAR *pwszLanguage, const WCHAR *pwszSource, CDirectMusicScript *pParentScript, HRESULT *phr, DMUS_SCRIPT_ERRORINFO *pErrorInfo) : m_pScriptManager(NULL) { S_Create S = { this, fUseOleAut, pwszLanguage, pwszSource, pParentScript, phr, pErrorInfo }; HRESULT hr = ms_Thread.Create(); if (SUCCEEDED(hr)) { hr = ms_Thread.Call(F_Create, &S, sizeof(S), true); } if (FAILED(hr)) // Only overwrite phr if the call itself failed. Otherwise the call itself sets phr via struct S.
*phr = hr; }
//////////////////////////////////////////////////////////////////////
// Start
struct S_Start { S_STD_PARAMS
DMUS_SCRIPT_ERRORINFO *pErrorInfo; };
void F_Start(void *pvParams) { S_Start *pS = reinterpret_cast<S_Start*>(pvParams); *pS->phr = pS->pmgr->Start(pS->pErrorInfo); }
HRESULT CSingleThreadedScriptManager ::Start(DMUS_SCRIPT_ERRORINFO *pErrorInfo) { HRESULT hr = E_FAIL; S_Start S = { m_pScriptManager, &hr, pErrorInfo }; HRESULT hrThreadCall = ms_Thread.Call(F_Start, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// CallRoutine
struct S_CallRoutine { S_STD_PARAMS
const WCHAR *pwszRoutineName; DMUS_SCRIPT_ERRORINFO *pErrorInfo; };
void F_CallRoutine(void *pvParams) { S_CallRoutine *pS = reinterpret_cast<S_CallRoutine*>(pvParams); *pS->phr = pS->pmgr->CallRoutine(pS->pwszRoutineName, pS->pErrorInfo); }
HRESULT CSingleThreadedScriptManager::CallRoutine(const WCHAR *pwszRoutineName, DMUS_SCRIPT_ERRORINFO *pErrorInfo) { HRESULT hr = E_FAIL; S_CallRoutine S = { m_pScriptManager, &hr, pwszRoutineName, pErrorInfo }; HRESULT hrThreadCall = ms_Thread.Call(F_CallRoutine, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// ScriptTrackCallRoutine
struct S_ScriptTrackCallRoutine { S_STD_PARAMS
IDirectMusicSegmentState *pSegSt; DWORD dwVirtualTrackID; bool fErrorPMsgsEnabled; __int64 i64IntendedStartTime; DWORD dwIntendedStartTimeFlags; WCHAR wszRoutineName[1]; // dynamically allocate extra space to hold the actual string within this structure
};
void F_ScriptTrackCallRoutine(void *pvParams) { S_ScriptTrackCallRoutine *pS = reinterpret_cast<S_ScriptTrackCallRoutine*>(pvParams); pS->pmgr->ScriptTrackCallRoutine( pS->wszRoutineName, pS->pSegSt, pS->dwVirtualTrackID, pS->fErrorPMsgsEnabled, pS->i64IntendedStartTime, pS->dwIntendedStartTimeFlags); pS->pSegSt->Release(); // release the interface held in CSingleThreadedScriptManager::ScriptTrackCallRoutine
}
HRESULT CSingleThreadedScriptManager::ScriptTrackCallRoutine( const WCHAR *pwszRoutineName, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualTrackID, bool fErrorPMsgsEnabled, __int64 i64IntendedStartTime, DWORD dwIntendedStartTimeFlags) { // We need to allocate the structure with extra space to hold the routine name. This is because
// the call is asynchonous so a copy of the text will be needed because copying the pwszRoutineName
// would fail because we can't be sure the string it points to will remain be allocated.
int cbS = sizeof(S_ScriptTrackCallRoutine) + (sizeof(WCHAR) * wcslen(pwszRoutineName)); S_ScriptTrackCallRoutine *pS = reinterpret_cast<S_ScriptTrackCallRoutine *>(new char[cbS]); if (!pS) return E_OUTOFMEMORY; pS->pmgr = m_pScriptManager; pS->phr = NULL; pS->pSegSt = pSegSt; pS->pSegSt->AddRef(); // hold a ref because the call is asynchronous and the interface we were passed may be released
pS->dwVirtualTrackID = dwVirtualTrackID; pS->fErrorPMsgsEnabled = fErrorPMsgsEnabled; pS->i64IntendedStartTime = i64IntendedStartTime; pS->dwIntendedStartTimeFlags = dwIntendedStartTimeFlags; wcscpy(pS->wszRoutineName, pwszRoutineName);
// Call asynchronously. Needed to avoid deadlocks between the VBScript thread and
// performance or to avoid blocking the performance if the VBScript routine goes into
// a long loop. VVVVV
HRESULT hrThreadCall = ms_Thread.Call(F_ScriptTrackCallRoutine, pS, cbS, false); delete [] reinterpret_cast<char *>(pS); return hrThreadCall; }
//////////////////////////////////////////////////////////////////////
// SetVariable
struct S_SetVariable { S_STD_PARAMS
const WCHAR *pwszVariableName; VARIANT *pvarValue; // pass struct by reference
bool fSetRef; DMUS_SCRIPT_ERRORINFO *pErrorInfo; };
void F_SetVariable(void *pvParams) { S_SetVariable *pS = reinterpret_cast<S_SetVariable*>(pvParams); *pS->phr = pS->pmgr->SetVariable(pS->pwszVariableName, *pS->pvarValue, pS->fSetRef, pS->pErrorInfo); }
HRESULT CSingleThreadedScriptManager::SetVariable(const WCHAR *pwszVariableName, VARIANT varValue, bool fSetRef, DMUS_SCRIPT_ERRORINFO *pErrorInfo) { HRESULT hr = E_FAIL; S_SetVariable S = { m_pScriptManager, &hr, pwszVariableName, &varValue, fSetRef, pErrorInfo }; HRESULT hrThreadCall = ms_Thread.Call(F_SetVariable, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// GetVariable
struct S_GetVariable { S_STD_PARAMS
const WCHAR *pwszVariableName; VARIANT *pvarValue; DMUS_SCRIPT_ERRORINFO *pErrorInfo; };
void F_GetVariable(void *pvParams) { S_GetVariable *pS = reinterpret_cast<S_GetVariable*>(pvParams); *pS->phr = pS->pmgr->GetVariable(pS->pwszVariableName, pS->pvarValue, pS->pErrorInfo); }
HRESULT CSingleThreadedScriptManager::GetVariable(const WCHAR *pwszVariableName, VARIANT *pvarValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo) { HRESULT hr = E_FAIL; S_GetVariable S = { m_pScriptManager, &hr, pwszVariableName, pvarValue, pErrorInfo }; HRESULT hrThreadCall = ms_Thread.Call(F_GetVariable, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// EnumRoutine
struct S_EnumItem { S_STD_PARAMS
bool fRoutine; DWORD dwIndex; WCHAR *pwszName; int *pcItems; };
void F_EnumItem(void *pvParams) { S_EnumItem *pS = reinterpret_cast<S_EnumItem*>(pvParams); *pS->phr = pS->pmgr->EnumItem(pS->fRoutine, pS->dwIndex, pS->pwszName, pS->pcItems); }
HRESULT CSingleThreadedScriptManager::EnumItem(bool fRoutine, DWORD dwIndex, WCHAR *pwszName, int *pcItems) { HRESULT hr = E_FAIL; S_EnumItem S = { m_pScriptManager, &hr, fRoutine, dwIndex, pwszName, pcItems }; HRESULT hrThreadCall = ms_Thread.Call(F_EnumItem, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// DispGetIDsOfNames
struct S_DispGetIDsOfNames { S_STD_PARAMS
const IID *piid; // use pointer instead of reference to leave struct as simple aggregate type
LPOLESTR __RPC_FAR *rgszNames; UINT cNames; LCID lcid; DISPID *rgDispId; };
void F_DispGetIDsOfNames(void *pvParams) { S_DispGetIDsOfNames *pS = reinterpret_cast<S_DispGetIDsOfNames*>(pvParams); *pS->phr = pS->pmgr->DispGetIDsOfNames(*pS->piid, pS->rgszNames, pS->cNames, pS->lcid, pS->rgDispId); }
HRESULT CSingleThreadedScriptManager::DispGetIDsOfNames(REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId) { HRESULT hr = E_FAIL; S_DispGetIDsOfNames S = { m_pScriptManager, &hr, &riid, rgszNames, cNames, lcid, rgDispId }; HRESULT hrThreadCall = ms_Thread.Call(F_DispGetIDsOfNames, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// DispInvoke
struct S_DispInvoke { S_STD_PARAMS
DISPID dispIdMember; const IID *piid; // use pointer instead of reference to leave struct as simple aggregate type
LCID lcid; WORD wFlags; DISPPARAMS __RPC_FAR *pDispParams; VARIANT __RPC_FAR *pVarResult; EXCEPINFO __RPC_FAR *pExcepInfo; UINT __RPC_FAR *puArgErr; };
void F_DispInvoke(void *pvParams) { S_DispInvoke *pS = reinterpret_cast<S_DispInvoke*>(pvParams); *pS->phr = pS->pmgr->DispInvoke(pS->dispIdMember, *pS->piid, pS->lcid, pS->wFlags, pS->pDispParams, pS->pVarResult, pS->pExcepInfo, pS->puArgErr); }
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) { HRESULT hr = E_FAIL; S_DispInvoke S = { m_pScriptManager, &hr, dispIdMember, &riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr }; HRESULT hrThreadCall = ms_Thread.Call(F_DispInvoke, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; }
//////////////////////////////////////////////////////////////////////
// Close
struct S_Close { ScriptManager *pmgr; };
void F_Close(void *pvParams) { S_Close *pS = reinterpret_cast<S_Close*>(pvParams); pS->pmgr->Close(); }
void CSingleThreadedScriptManager::Close() { S_Close S = { m_pScriptManager }; ms_Thread.Call(F_Close, &S, sizeof(S), true); }
//////////////////////////////////////////////////////////////////////
// Release
struct S_Release { ScriptManager *pmgr; DWORD *pdw; };
void F_Release(void *pvParams) { S_Release *pS = reinterpret_cast<S_Release*>(pvParams); *pS->pdw = pS->pmgr->Release(); }
STDMETHODIMP_(ULONG) CSingleThreadedScriptManager::Release() { DWORD dw = 1; S_Release S = { m_pScriptManager, &dw }; if (m_pScriptManager) // if creation failed, release will be called when m_pScriptManager hasn't been set
{ ms_Thread.Call(F_Release, &S, sizeof(S), true); }
if (!dw) delete this;
return dw; }
/*
Template I used to stamp these things out...
//////////////////////////////////////////////////////////////////////
// XXX
struct S_XXX { S_STD_PARAMS
YYY };
void F_XXX(void *pvParams) { S_XXX *pS = reinterpret_cast<S_XXX*>(pvParams); *pS->phr = pS->pmgr->XXX(YYY); }
HRESULT CSingleThreadedScriptManager::XXX(YYY) { HRESULT hr = E_FAIL; S_XXX S = { m_pScriptManager, &hr, YYY }; HRESULT hrThreadCall = ms_Thread.Call(F_XXX, &S, sizeof(S), true); if (FAILED(hrThreadCall)) return hrThreadCall; return hr; } */
|