516 lines
16 KiB
C++
516 lines
16 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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<CScriptEventSink*, 5> _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<HANDLE, 5> *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<SYNCEVENT, 5> 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;
|
|
|
|
};
|