//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995 // // File: bsscript.h // // Contents: Script engine classes // //---------------------------------------------------------------------------- class CScriptHost; class CProcessThread; // Helper class to make initialization // and freeing of VARIANTARGs foolproof. // Can be used anywhere a VARIANTARG // would be used. class AutoVariant : public VARIANTARG { public: AutoVariant() { VariantInit( (VARIANTARG *) this); } BOOL Set(long value) { V_VT(this) = VT_I4; V_I4(this) = value; return TRUE; } BOOL Set(TCHAR *value) { V_VT(this) = VT_BSTR; V_BSTR(this) = SysAllocString(value); // NULL is a valid value for BSTR if (value && !V_BSTR(this)) return FALSE; return TRUE; } ~AutoVariant() { VariantClear( (VARIANTARG *) this); } }; //+------------------------------------------------------------------------ // // Class: CScriptSite // // Purpose: Active scripting site // //------------------------------------------------------------------------- class CScriptSite : public IActiveScriptSite, public IActiveScriptSiteWindow, public IActiveScriptSiteDebug, public IProvideMultipleClassInfo, public IConnectionPointContainer, public IGlobalMTScript { public: DECLARE_MEMCLEAR_NEW_DELETE(); CScriptSite(CScriptHost * pSH); ~CScriptSite(); HRESULT Init(LPWSTR pszName); void Close(); void Abort(); // IUnknown methods STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); STDMETHOD(QueryInterface)(REFIID, void **); // IActiveScriptSite methods STDMETHOD(GetLCID)(LCID *plcid); STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti); STDMETHOD(GetDocVersionString)(BSTR *pszVersion); STDMETHOD(RequestItems)(void); STDMETHOD(RequestTypeLibs)(void); STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo); STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState); STDMETHOD(OnScriptError)(IActiveScriptError *pscripterror); STDMETHOD(OnEnterScript)(void); STDMETHOD(OnLeaveScript)(void); // IActiveScriptSiteWindow methods STDMETHOD(GetWindow)(HWND *phwnd); STDMETHOD(EnableModeless)(BOOL fEnable); // IActiveScriptSiteDebug methods STDMETHOD(GetDocumentContextFromPosition)(DWORD dwSourceContext, ULONG uCharacterOffset, ULONG uNumChars, IDebugDocumentContext **ppsc); STDMETHOD(GetApplication)(IDebugApplication **ppda); STDMETHOD(GetRootApplicationNode)(IDebugApplicationNode **ppdanRoot); STDMETHOD(OnScriptErrorDebug)(IActiveScriptErrorDebug *pErrorDebug, BOOL *pfEnterDebugger, BOOL *pfCallOnScriptErrorWhenContinuing); // IProvideClassInfo methods STDMETHOD(GetClassInfo)(ITypeInfo **); STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID * pGUID); // IProvideMultipleClassInfo methods STDMETHOD(GetMultiTypeInfoCount)(ULONG *pcti); STDMETHOD(GetInfoOfIndex)(ULONG iti, DWORD dwFlags, ITypeInfo** pptiCoClass, DWORD* pdwTIFlags, ULONG* pcdispidReserved, IID* piidPrimary, IID* piidSource); // IConnectionPointContainer methods STDMETHOD(EnumConnectionPoints)(LPENUMCONNECTIONPOINTS*); STDMETHOD(FindConnectionPoint)(REFIID, LPCONNECTIONPOINT*); // IBServer methods // We need to implement these on a separate identity from // the main pad object in order to prevent ref count loops // with the script engine. STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo); STDMETHOD(GetTypeInfo)( UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo); STDMETHOD(GetIDsOfNames)( REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid); STDMETHOD(Invoke)( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr); STDMETHOD(get_PublicData)(VARIANT *); STDMETHOD(put_PublicData)(VARIANT); STDMETHOD(get_PrivateData)(VARIANT *); STDMETHOD(put_PrivateData)(VARIANT); STDMETHOD(ExitProcess)(); STDMETHOD(Restart)(); STDMETHOD(get_LocalMachine)(BSTR *); STDMETHOD(Include)(BSTR); STDMETHOD(CallScript)(BSTR, VARIANT *); STDMETHOD(SpawnScript)(BSTR, VARIANT *); STDMETHOD(get_ScriptParam)(VARIANT *); STDMETHOD(get_ScriptPath)(BSTR *); STDMETHOD(CallExternal)(BSTR, BSTR, VARIANT *, long *); STDMETHOD(ResetSync)(const BSTR); STDMETHOD(WaitForSync)(BSTR, long, VARIANT_BOOL *); STDMETHOD(WaitForMultipleSyncs)(const BSTR, VARIANT_BOOL, long, long *); STDMETHOD(SignalThreadSync)(BSTR); STDMETHOD(TakeThreadLock)(BSTR); STDMETHOD(ReleaseThreadLock)(BSTR); STDMETHOD(DoEvents)(); STDMETHOD(MessageBoxTimeout)(BSTR, long, BSTR, long, long, VARIANT_BOOL, VARIANT_BOOL, long *); STDMETHOD(RunLocalCommand)(BSTR, BSTR, BSTR, VARIANT_BOOL, VARIANT_BOOL, VARIANT_BOOL, VARIANT_BOOL, VARIANT_BOOL, long *); STDMETHOD(GetLastRunLocalError)(long *); STDMETHOD(GetProcessOutput)(long, BSTR *); STDMETHOD(GetProcessExitCode)(long, long *); STDMETHOD(TerminateProcess)(long); STDMETHOD(SendToProcess)(long, BSTR, BSTR, long *); STDMETHOD(SendMail)(BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, long *); STDMETHOD(SendSMTPMail)(BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, long *); STDMETHOD(ASSERT)(VARIANT_BOOL, BSTR); STDMETHOD(OUTPUTDEBUGSTRING)(BSTR); STDMETHOD(UnevalString)(BSTR, BSTR*); STDMETHOD(CopyOrAppendFile)(BSTR bstrSrc,BSTR bstrDst,long nSrcOffset,long nSrcLength,VARIANT_BOOL fAppend,long *nSrcFilePosition); STDMETHOD(Sleep)(int); STDMETHOD(Reboot)(); STDMETHOD(NotifyScript)(BSTR, VARIANT); STDMETHOD(RegisterEventSource)(IDispatch *pDisp, BSTR bstrProgID); STDMETHOD(UnregisterEventSource)(IDispatch *pDisp); STDMETHOD(get_HostMajorVer)(long *pVer); STDMETHOD(get_HostMinorVer)(long *pVer); STDMETHOD(get_StatusValue)(long nIndex, long *pnStatus); STDMETHOD(put_StatusValue)(long nIndex, long nStatus); // Other methods HRESULT ExecuteScriptStr(TCHAR * pchScript); HRESULT ExecuteScriptFile(TCHAR *pchPath); HRESULT SetScriptState(SCRIPTSTATE ss); CScriptHost * ScriptHost() { return _pSH; } // Member variables CStr _cstrName; ULONG _ulRefs; CScriptSite * _pScriptSitePrev; IActiveScript * _pScript; CScriptHost* _pSH; TCHAR _achPath[MAX_PATH]; VARIANT _varParam; IDispatch * _pDispSink; IDebugDocumentHelper * _pDDH; // Script Debugging helper DWORD _dwSourceContext; BOOL _fInDebugError; private: BOOL _fInScriptError; }; class AutoCriticalSection : public CRITICAL_SECTION { public: AutoCriticalSection() { InitializeCriticalSection(this); } ~AutoCriticalSection() { DeleteCriticalSection(this); } }; class CScriptHost : public CThreadComm, public IGlobalMTScript { friend class CScriptEventSink; public: DECLARE_MEMCLEAR_NEW_DELETE(); CScriptHost(CMTScript * pBS, BOOL fPrimary, BOOL fDispatchOnly); ~CScriptHost(); DECLARE_STANDARD_IUNKNOWN(CScriptHost); // Script management HRESULT LoadTypeLibrary(); HRESULT PushScript(TCHAR *pchType); HRESULT PopScript(); HRESULT CloseScripts(); HRESULT AbortScripts(); HRESULT ExecuteTopLevelScript(TCHAR *pchPath, VARIANT *pvarParams); HRESULT ExecuteTopLevelScriptlet(TCHAR *pchScript); long FireScriptErrorEvent( TCHAR *bstrFile, long nLine, long nChar, TCHAR *bstrText, long sCode, TCHAR *bstrSource, TCHAR *bstrDescription); long FireScriptErrorEvent(TCHAR *szMsg); void FireProcessEvent(THREADMSG mt, CProcessThread *pProc); void FireMachineEvent(MACHPROC_EVENT_DATA *pmed, BOOL fExec); void FireEvent(DISPID, UINT cArg, VARIANTARG *pvararg, VARIANTARG *pvarResult); void FireEvent(DISPID, UINT cArg, VARIANTARG *pvararg); void FireEvent(DISPID, LPCTSTR); void FireEvent(DISPID, BOOL); void FireEvent(DISPID, IDispatch *pDisp); BOOL GetMachineDispatch(LPSTR achName, IConnectedMachine **ppMach); static HRESULT GetSyncEventName(int nEvent, CStr *pCStr, HANDLE *phEvent); static HRESULT GetSyncEvent(LPCTSTR pszName, HANDLE *phEvent); // IDispatch interface STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo); STDMETHOD(GetTypeInfo)( UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo); STDMETHOD(GetIDsOfNames)( REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid); STDMETHOD(Invoke)( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr); // IGlobalMTScript interface STDMETHOD(get_PublicData)(VARIANT *); STDMETHOD(put_PublicData)(VARIANT); STDMETHOD(get_PrivateData)(VARIANT *); STDMETHOD(put_PrivateData)(VARIANT); STDMETHOD(ExitProcess)(); STDMETHOD(Restart)(); STDMETHOD(get_LocalMachine)(BSTR *); STDMETHOD(Include)(BSTR); STDMETHOD(CallScript)(BSTR, VARIANT *); STDMETHOD(SpawnScript)(BSTR, VARIANT *); STDMETHOD(get_ScriptParam)(VARIANT *); STDMETHOD(get_ScriptPath)(BSTR *); STDMETHOD(CallExternal)(BSTR, BSTR, VARIANT *, long *); STDMETHOD(ResetSync)(const BSTR); STDMETHOD(WaitForSync)(BSTR, long, VARIANT_BOOL *); STDMETHOD(WaitForMultipleSyncs)(const BSTR, VARIANT_BOOL, long, long *); STDMETHOD(SignalThreadSync)(BSTR); STDMETHOD(TakeThreadLock)(BSTR); STDMETHOD(ReleaseThreadLock)(BSTR); STDMETHOD(DoEvents)(); STDMETHOD(MessageBoxTimeout)(BSTR, long, BSTR, long, long, VARIANT_BOOL, VARIANT_BOOL, long *); STDMETHOD(RunLocalCommand)(BSTR, BSTR, BSTR, VARIANT_BOOL, VARIANT_BOOL, VARIANT_BOOL, VARIANT_BOOL, VARIANT_BOOL, long *); STDMETHOD(GetLastRunLocalError)(long *); STDMETHOD(GetProcessOutput)(long, BSTR *); STDMETHOD(GetProcessExitCode)(long, long *); STDMETHOD(TerminateProcess)(long); STDMETHOD(SendToProcess)(long, BSTR, BSTR, long *); STDMETHOD(SendMail)(BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, long *); STDMETHOD(SendSMTPMail)(BSTR, BSTR, BSTR, BSTR, BSTR, BSTR, long *); STDMETHOD(ASSERT)(VARIANT_BOOL, BSTR); STDMETHOD(OUTPUTDEBUGSTRING)(BSTR); STDMETHOD(UnevalString)(BSTR, BSTR*); STDMETHOD(CopyOrAppendFile)(BSTR bstrSrc,BSTR bstrDst,long nSrcOffset,long nSrcLength,VARIANT_BOOL fAppend,long *nSrcFilePosition); STDMETHOD(Sleep)(int); STDMETHOD(Reboot)(); STDMETHOD(NotifyScript)(BSTR, VARIANT); STDMETHOD(RegisterEventSource)(IDispatch *pDisp, BSTR bstrProgID); STDMETHOD(UnregisterEventSource)(IDispatch *pDisp); STDMETHOD(get_HostMajorVer)(long *pVer); STDMETHOD(get_HostMinorVer)(long *pVer); STDMETHOD(get_StatusValue)(long nIndex, long *pnStatus); STDMETHOD(put_StatusValue)(long nIndex, long nStatus); CScriptSite * GetSite() { return _pScriptSite; } void GetScriptPath(CStr *pcstrPath); CMTScript * _pMT; CScriptSite * _pScriptSite; BOOL _fIsPrimaryScript; BOOL _fMustExitThread; BOOL _fDontHandleEvents; ITypeInfo * _pTypeInfoIGlobalMTScript; ITypeInfo * _pTypeInfoCMTScript; ITypeLib * _pTypeLibEXE; VARIANT _vPubCache; VARIANT _vPrivCache; DWORD _dwPublicSN; DWORD _dwPrivateSN; long _lTimerInterval; HRESULT _hrLastRunLocalError; CStackPtrAry _aryEvtSinks; protected: virtual DWORD ThreadMain(); void HandleThreadMessage(); enum MEP_RETURN { MEP_TIMEOUT, // Timeout period expired MEP_EXIT, // Thread is terminating MEP_FALLTHROUGH, // No event occurred (fWait==FALSE only) MEP_EVENT_0, // The given event(s) are signaled }; DWORD MessageEventPump(BOOL fWait, UINT cEvents = 0, HANDLE * pEvents = NULL, BOOL fAll = FALSE, DWORD dwTimeout = INFINITE, BOOL fNoEvents = FALSE); HRESULT StringToEventArray(const wchar_t *pszNameList, CStackPtrAry *aryEvents); HRESULT GetLockCritSec(LPTSTR pszName, CRITICAL_SECTION **ppcs, DWORD **ppdwOwner); struct SYNCEVENT { CStr _cstrName; HANDLE _hEvent; }; struct THREADLOCK { CStr _cstrName; CRITICAL_SECTION _csLock; DWORD _dwOwner; }; // MAX_LOCKS is used because you can't move critical section objects // in memory once you've initialized them, thus making it impossible to // use the dynamic array class. #define MAX_LOCKS 10 // The primary thread owns initialization and cleanup of these objects. static CStackDataAry s_arySyncEvents; static THREADLOCK s_aThreadLocks[MAX_LOCKS]; static UINT s_cThreadLocks; static AutoCriticalSection s_csSync; }; //+--------------------------------------------------------------------------- // // Class: CConnectionPoint (ccp) // // Purpose: Implements IConnectionPoint for the script site // //---------------------------------------------------------------------------- class CConnectionPoint : public IConnectionPoint { public: CConnectionPoint(CScriptSite *pSite); ~CConnectionPoint(); DECLARE_STANDARD_IUNKNOWN(CConnectionPoint); STDMETHOD(GetConnectionInterface)(IID * pIID); STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer ** ppCPC); STDMETHOD(Advise)(LPUNKNOWN pUnkSink, DWORD * pdwCookie); STDMETHOD(Unadvise)(DWORD dwCookie); STDMETHOD(EnumConnections)(LPENUMCONNECTIONS * ppEnum); CScriptSite *_pSite; }; //+--------------------------------------------------------------------------- // // Class: CMTEventSink (ces) // // Purpose: Class which sinks events from objects registered with // RegisterEventSource(). // //---------------------------------------------------------------------------- class CScriptEventSink : public IDispatch { public: DECLARE_MEMCLEAR_NEW_DELETE(); CScriptEventSink(CScriptHost *pSH); ~CScriptEventSink(); // IUnknown methods DECLARE_STANDARD_IUNKNOWN(CScriptEventSink); HRESULT Connect(IDispatch *pSource, BSTR bstrProgID); void Disconnect(); BOOL IsThisYourSource(IDispatch * pSource) { return pSource == _pDispSource; } // IDispatch interface STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo); STDMETHOD(GetTypeInfo)( UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo); STDMETHOD(GetIDsOfNames)( REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid); STDMETHOD(Invoke)( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr); private: CScriptHost * _pSH; IDispatch * _pDispSource; DWORD _dwSinkCookie; IID _clsidEvents; };