windows-nt/Source/XPSP1/NT/sdktools/mtscript/inc/script.h
2020-09-26 16:20:57 +08:00

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;
};