// Copyright (c) 1999 Microsoft Corporation. All rights reserved. // // Declaration of CActiveScriptManager. // // CActiveScriptManager handles interfacing with VBScript or any activeX scripting // language. It intializes an IActiveScript object, sends it code, and sets and gets // the values of variables. Used by CDirectMusicScript. #pragma once #include "ole2.h" #include "activscp.h" #include "scriptthread.h" #include "..\shared\dmusicp.h" // forward declaration class CDirectMusicScript; // little helper class to cache routine and variable names for EnumItem class ScriptNames { public: ScriptNames() : m_prgbstr(NULL) {} ~ScriptNames() { Clear(); } HRESULT Init(bool fUseOleAut, DWORD cNames); operator bool() { return !!m_prgbstr; } DWORD size() { return m_dwSize; } void Clear(); BSTR &operator[](DWORD dwIndex) { assert(m_prgbstr && dwIndex < m_dwSize); return m_prgbstr[dwIndex]; } private: bool m_fUseOleAut; DWORD m_dwSize; BSTR *m_prgbstr; }; class CActiveScriptManager : public IActiveScriptSite, public ScriptManager { public: CActiveScriptManager( bool fUseOleAut, const WCHAR *pwszLanguage, const WCHAR *pwszSource, CDirectMusicScript *pParentScript, HRESULT *phr, DMUS_SCRIPT_ERRORINFO *pErrorInfo); HRESULT Start(DMUS_SCRIPT_ERRORINFO *pErrorInfo); HRESULT CallRoutine(const WCHAR *pwszRoutineName, DMUS_SCRIPT_ERRORINFO *pErrorInfo); HRESULT ScriptTrackCallRoutine( const WCHAR *pwszRoutineName, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualTrackID, bool fErrorPMsgsEnabled, __int64 i64IntendedStartTime, DWORD dwIntendedStartTimeFlags); HRESULT SetVariable(const WCHAR *pwszVariableName, VARIANT varValue, bool fSetRef, DMUS_SCRIPT_ERRORINFO *pErrorInfo); HRESULT GetVariable(const WCHAR *pwszVariableName, VARIANT *pvarValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo); HRESULT EnumItem(bool fRoutine, DWORD dwIndex, WCHAR *pwszName, int *pcItems); HRESULT DispGetIDsOfNames(REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId); HRESULT 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); void Close(); // Releases all references in preparation for shutdown // IUnknown STDMETHOD(QueryInterface)(const IID &iid, void **ppv); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // IActiveScriptSite STDMETHOD(GetLCID)(/* [out] */ LCID __RPC_FAR *plcid); STDMETHOD(GetItemInfo)( /* [in] */ LPCOLESTR pstrName, /* [in] */ DWORD dwReturnMask, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppiunkItem, /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppti); STDMETHOD(GetDocVersionString)(/* [out] */ BSTR __RPC_FAR *pbstrVersion); STDMETHOD(OnScriptTerminate)( /* [in] */ const VARIANT __RPC_FAR *pvarResult, /* [in] */ const EXCEPINFO __RPC_FAR *pexcepinfo); STDMETHOD(OnStateChange)(/* [in] */ SCRIPTSTATE ssScriptState); STDMETHOD(OnScriptError)(/* [in] */ IActiveScriptError __RPC_FAR *pscripterror); STDMETHOD(OnEnterScript)(); STDMETHOD(OnLeaveScript)(); // Retrieve context for the currently running script. // Some automation model functions need access to the context from which the // currently running routine was called. For example, they may need to operate // on the implied global performance. // Be sure to addref the returned pointer if holding onto it. static IDirectMusicPerformance8 *GetCurrentPerformanceNoAssertWEAK(); static IDirectMusicPerformance8 *GetCurrentPerformanceWEAK() { IDirectMusicPerformance8 *pPerf = CActiveScriptManager::GetCurrentPerformanceNoAssertWEAK(); if (!pPerf) {assert(false);} return pPerf; } static IDirectMusicObject *GetCurrentScriptObjectWEAK(); static IDirectMusicComposer8 *GetComposerWEAK(); static void GetCurrentTimingContext(__int64 *pi64IntendedStartTime, DWORD *pdwIntendedStartTimeFlags); private: // Functions HRESULT GetIDOfName(const WCHAR *pwszName, DISPID *pdispid); // returns S_FALSE for unknown name void ClearErrorInfo(); void SetErrorInfo(ULONG ulLineNumber, LONG ichCharPosition, BSTR bstrSourceLine, const EXCEPINFO &excepinfo); void ContributeErrorInfo(const WCHAR *pwszActivity, const WCHAR *pwszSubject, const EXCEPINFO &excepinfo); HRESULT ReturnErrorInfo(HRESULT hr, DMUS_SCRIPT_ERRORINFO *pErrorInfo); static CActiveScriptManager *GetCurrentContext(); static HRESULT SetCurrentContext(CActiveScriptManager *pActiveScriptManager, CActiveScriptManager **ppActiveScriptManagerPrevious); // remember to restore the previous pointer after the call HRESULT EnsureEnumItemsCached(bool fRoutine); // Data long m_cRef; // Pointer back to the containing script object CDirectMusicScript *m_pParentScript; // Active Scripting bool m_fUseOleAut; IActiveScript *m_pActiveScript; IDispatch *m_pDispatchScript; // Errors (managed via ClearErrorInfo, SetErrorInfo, and ContributeErrorInfo) bool m_fError; HRESULT m_hrError; ULONG m_ulErrorLineNumber; LONG m_ichErrorCharPosition; BSTR m_bstrErrorSourceComponent; BSTR m_bstrErrorDescription; BSTR m_bstrErrorSourceLineText; BSTR m_bstrHelpFile; // Context struct ThreadContextPair { DWORD dwThreadId; CActiveScriptManager *pActiveScriptManager; }; static SmartRef::Vector ms_svecContext; // Timing context for a routine call from a script track. (Sets the play/stop time of segments, songs, and playingsegments // to the time of the routine in the script track.) __int64 m_i64IntendedStartTime; DWORD m_dwIntendedStartTimeFlags; // cached names from enum methods ScriptNames m_snamesRoutines; ScriptNames m_snamesVariables; };