401 lines
11 KiB
C++
401 lines
11 KiB
C++
|
// 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;
|
||
|
}
|
||
|
*/
|