580 lines
18 KiB
C
580 lines
18 KiB
C
|
/*===================================================================
|
||
|
Microsoft Denali
|
||
|
|
||
|
Microsoft Confidential.
|
||
|
Copyright 1996 Microsoft Corporation. All Rights Reserved.
|
||
|
|
||
|
Component: Script Manager
|
||
|
|
||
|
File: ScrptMgr.h
|
||
|
|
||
|
Owner: AndrewS
|
||
|
|
||
|
This file contains the declarations for the Script Manager, ie. siting an
|
||
|
ActiveX Scripting engine (in our case VBScript) for Denali.
|
||
|
===================================================================*/
|
||
|
|
||
|
#ifndef __ScrptMgr_h
|
||
|
#define __ScrptMgr_h
|
||
|
|
||
|
#include <dispex.h>
|
||
|
|
||
|
#include "activscp.h"
|
||
|
#include "activdbg.h"
|
||
|
#include "hostinfo.h"
|
||
|
#include "util.h"
|
||
|
#include "HitObj.h"
|
||
|
#include "hashing.h"
|
||
|
#include "memcls.h"
|
||
|
#include "scrpteng.h"
|
||
|
|
||
|
|
||
|
typedef SCRIPTSTATE ENGINESTATE; // Uninited, Loaded, etc
|
||
|
typedef CLSID PROGLANG_ID;
|
||
|
const CBPROGLANG_ID = sizeof(PROGLANG_ID);
|
||
|
|
||
|
class CActiveScriptSite;
|
||
|
class CActiveScriptEngine;
|
||
|
class CASEElem;
|
||
|
class CScriptingNamespace;
|
||
|
class CAppln;
|
||
|
|
||
|
// SMHash depends on stuff in this include file which must be defined first.
|
||
|
#include "SMHash.h"
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*
|
||
|
* C S c r i p t M a n a g e r
|
||
|
*
|
||
|
*
|
||
|
* Manages script engines, potentially caching them for future use,
|
||
|
* hands script engines to callers for use.
|
||
|
*
|
||
|
*/
|
||
|
class CScriptManager
|
||
|
{
|
||
|
private:
|
||
|
// private data members
|
||
|
BOOLB m_fInited; // Are we initialized?
|
||
|
|
||
|
/*
|
||
|
* Script Engines that are not in use can be reused and
|
||
|
* go on the Free Script Queue. It is a queue so we can
|
||
|
* discard the oldest if we need to.
|
||
|
*
|
||
|
* Engines that are in use cant be reused. When an engine
|
||
|
* is handed out to be used, it is removed from the FSQ. When a thread
|
||
|
* is done using an engine, it calls ReturnEngineToCache to put it back on
|
||
|
* the FSQ. If the Queue is at max length, the oldest engine on the queue is
|
||
|
* freed at that point. The one returned is put on the front of the queue.
|
||
|
*
|
||
|
* We also maintain a Running Script List. This is needed so that if we
|
||
|
* are told to flush a given script from our cache, we can "zombify" any
|
||
|
* running scripts that have that script in them (so they will be discarded
|
||
|
* when they are done running.)
|
||
|
*
|
||
|
* Additional note: Though we cant have multiple users of the *same* runing engine
|
||
|
* we can "clone" a running engine. If we get two simulanteous requests for Foo.ASP
|
||
|
* we expect that it will be faster to clone the second one from the first one than
|
||
|
* to create a second engine for the second request. Thus, the RSL will be searched
|
||
|
* for a given engine to clone if no suitable engine is found on the FSQ.
|
||
|
*
|
||
|
* DEBUGGING NOTE:
|
||
|
* Once the debugger asks a script engine for a code context cookie, we cannot
|
||
|
* ever let go of the script engine until the debugger detaches. Therefore, we
|
||
|
* don't cache scripts in the FSQ if debugging is active. Instead, the scripts
|
||
|
* are placed in the template when execution is finished, there to be doled back
|
||
|
* out when that engine is needed by the debugging engine.
|
||
|
*
|
||
|
* CONSIDER:
|
||
|
* We could be smarter about this, and cache scripts UNTIL the debugger either
|
||
|
* a. Asks for a code context from a document context, or
|
||
|
* b. Calls GetDocumentContextFromPosition, in which case, the debugger
|
||
|
* got a code context "behind our virtual backs".
|
||
|
*
|
||
|
* If we don't do this, we could, at the very least, only implement this
|
||
|
* debugging behavior when a debugger attaches to our application.
|
||
|
* (i.e. stop caching on attach, then on detach, resume caching, and also
|
||
|
* free scripts that the template objects are holding onto.)
|
||
|
*/
|
||
|
CSMHash m_htFSQ; // Free Script Queue
|
||
|
CRITICAL_SECTION m_csFSQ; // Serialize access to FSQ
|
||
|
CSMHash m_htRSL; // Running Script List
|
||
|
CRITICAL_SECTION m_csRSL; // Serialize access to RSL
|
||
|
|
||
|
CHashTable m_hTPLL; // Hash table of language engine classid's
|
||
|
CRITICAL_SECTION m_cSPLL; // Serialize access to PLL
|
||
|
|
||
|
DWORD m_idScriptKiller; // Script killer sched workitem id
|
||
|
DWORD m_msecScriptKillerTimeout;// Current script killer timeout
|
||
|
|
||
|
// private methods
|
||
|
HRESULT UnInitASEElems();
|
||
|
HRESULT UnInitPLL();
|
||
|
HRESULT AddProgLangToPLL(CHAR *szProgLangName, PROGLANG_ID progLangId);
|
||
|
|
||
|
// script killer
|
||
|
static VOID WINAPI ScriptKillerSchedulerCallback(VOID *pv);
|
||
|
|
||
|
public:
|
||
|
// public methods
|
||
|
CScriptManager();
|
||
|
~CScriptManager();
|
||
|
|
||
|
HRESULT Init();
|
||
|
HRESULT UnInit();
|
||
|
|
||
|
// Resolves a language name into a prog lang id, adding to engine list (m_hTPLL) if not already there
|
||
|
HRESULT ProgLangIdOfLangName(LPCSTR szProgLang, PROGLANG_ID *pProgLangId);
|
||
|
|
||
|
// Return an engine, preferably filled with the script for the given template/language
|
||
|
HRESULT GetEngine( LCID lcid, // The system language to use
|
||
|
PROGLANG_ID& progLangId, // prog lang id of the script
|
||
|
LPCTSTR szTemplateName, // Template we want an engine for
|
||
|
CHitObj *pHitObj, // Hit obj to use in this engine
|
||
|
CScriptEngine **ppSE, // Returned script engine
|
||
|
ENGINESTATE *pdwState, // Current state of the engine
|
||
|
CTemplate *pTemplate, // template (debug document)
|
||
|
DWORD dwSourceContext); // script engine index
|
||
|
|
||
|
HRESULT ReturnEngineToCache(CScriptEngine **, CAppln *, IASPObjectContextCustom *);
|
||
|
|
||
|
// Throw out any cached engines containing a given template
|
||
|
// (presumably the script changed on disk so the cache is obsolete.)
|
||
|
HRESULT FlushCache(LPCTSTR szTemplateName); // Template to throw out of the cache
|
||
|
|
||
|
HRESULT FlushAll(); // Clear the entire FSQ
|
||
|
|
||
|
HRESULT KillOldEngines(BOOLB fKillNow = FALSE); // Kill expired scripting engines
|
||
|
|
||
|
// Bug 1140: Called prior to shutting down script manager to make sure RSL is empty
|
||
|
HRESULT EmptyRunningScriptList();
|
||
|
|
||
|
// Adjust (shorten) script killer timeout
|
||
|
HRESULT AdjustScriptKillerTimeout(DWORD msecNewTimeout);
|
||
|
|
||
|
// Find running script that corresponds to a template (in one of its script blocks)
|
||
|
IActiveScriptDebug *GetDebugScript(CTemplate *pTemplate, DWORD dwSourceContext);
|
||
|
|
||
|
private:
|
||
|
HRESULT FindEngineInList(LPCTSTR szTemplateName, PROGLANG_ID progLangId, DWORD dwInstanceID, BOOL fFSQ, CASEElem **ppASEElem);
|
||
|
HRESULT FindASEElemInList(CActiveScriptEngine *pASE, BOOL fFSQ, CASEElem **ppASEElem);
|
||
|
|
||
|
// For threading a FIFO queue through the hash table
|
||
|
HRESULT AddToFSQ(CASEElem *pASEElem);
|
||
|
HRESULT CheckFSQLRU();
|
||
|
|
||
|
#ifdef DBG
|
||
|
virtual void AssertValid() const;
|
||
|
#else
|
||
|
virtual void AssertValid() const {}
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
extern CScriptManager g_ScriptManager;
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*
|
||
|
* C A c t i v e S c r i p t E n g i n e
|
||
|
*
|
||
|
* Object defining methods required to host an ActiveXScripting engine &
|
||
|
* service requests to that engine.
|
||
|
*
|
||
|
*/
|
||
|
class CActiveScriptEngine :
|
||
|
public CScriptEngine,
|
||
|
public IActiveScriptSite,
|
||
|
public IActiveScriptSiteDebug,
|
||
|
public IHostInfoProvider
|
||
|
{
|
||
|
private:
|
||
|
// private data members
|
||
|
UINT m_cRef; // Reference count
|
||
|
IDispatch *m_pDisp; // IDispatch interface on script
|
||
|
CHitObj *m_pHitObj; // The hit object contains a list of objects for this run
|
||
|
LPTSTR m_szTemplateName; // The name of the template this engine has loaded
|
||
|
DWORD m_dwInstanceID; // server instance ID of template this engine has loaded
|
||
|
TCHAR m_szTemplateNameBuf[64]; // Buffer for short templates to fit to avoid allocs
|
||
|
PROGLANG_ID m_proglang_id; // What programming language?
|
||
|
LCID m_lcid; // what system language
|
||
|
IActiveScript *m_pAS; // The script object sited here
|
||
|
IActiveScriptParse *m_pASP; // The script object parser
|
||
|
IHostInfoUpdate *m_pHIUpdate;// Interface for advising the script that we have new host info
|
||
|
time_t m_timeStarted; // Time when the script engine was handed out last.
|
||
|
CTemplate *m_pTemplate; // template that acts as debugging document
|
||
|
DWORD m_dwSourceContext; // "Cookie" value which is really script engine
|
||
|
DWORD m_fInited : 1; // Have we been inited?
|
||
|
DWORD m_fZombie : 1; // Do we need to be deleted on last use
|
||
|
DWORD m_fScriptLoaded : 1; // Have we been called with script to load yet? (Used for clone)
|
||
|
DWORD m_fObjectsLoaded : 1; // Have we been called with a set of objects yet? (Used for clone)
|
||
|
DWORD m_fBeingDebugged : 1; // Is this script being debugged now?
|
||
|
DWORD m_fTemplateNameAllocated : 1; // Is name allocated? (need to free?)
|
||
|
|
||
|
/*
|
||
|
* NOTE: ActiveXScripting:
|
||
|
* ActiveXScripting had an undone such that the excepinfo filled in in InteruptScript
|
||
|
* was not passed to OnScriptError. We would have liked to use that mechanism to cause
|
||
|
* correct error loging (or suppression) if we interrupt a script. However,
|
||
|
* since ActiveXScripting wasnt passing the info, we didnt know. We wrote this code to
|
||
|
* handle it ourselves. They have now fixed it, but the mechanism we implemented works very
|
||
|
* well, so we are not going to change it.
|
||
|
*/
|
||
|
DWORD m_fScriptAborted : 1; // The script did a Response.End
|
||
|
DWORD m_fScriptTimedOut : 1; // We killed the script on timeout
|
||
|
DWORD m_fScriptHadError : 1; // The script had an error while running. Transacted script should autoabort
|
||
|
|
||
|
/*
|
||
|
* BUG 1225: If there is a GPF running a script, we shouldnt reuse the engine
|
||
|
*/
|
||
|
DWORD m_fCorrupted : 1; // Might the engine be "unsafe" for reuse?
|
||
|
|
||
|
// handle GetItemInfo() failure
|
||
|
void HandleItemNotFound(LPCOLESTR pcszName);
|
||
|
|
||
|
HRESULT StoreTemplateName(LPCTSTR szTemplateName);
|
||
|
|
||
|
public:
|
||
|
CActiveScriptEngine();
|
||
|
~CActiveScriptEngine();
|
||
|
|
||
|
HRESULT Init(
|
||
|
PROGLANG_ID proglang_id,
|
||
|
LPCTSTR szTemplateName,
|
||
|
LCID lcid,
|
||
|
CHitObj *pHitObj,
|
||
|
CTemplate *pTemplate,
|
||
|
DWORD dwSourceContext);
|
||
|
|
||
|
HRESULT MakeClone(
|
||
|
PROGLANG_ID proglang_id,
|
||
|
LPCTSTR szTemplateName,
|
||
|
LCID lcid,
|
||
|
CHitObj *pHitObj,
|
||
|
CTemplate *pTemplate,
|
||
|
DWORD dwSourceContext,
|
||
|
DWORD dwInstanceID,
|
||
|
IActiveScript *pAS); // The cloned script engine
|
||
|
|
||
|
HRESULT ReuseEngine(
|
||
|
CHitObj *pHitObj,
|
||
|
CTemplate *pTemplate,
|
||
|
DWORD dwSourceContext,
|
||
|
DWORD dwInstanceID
|
||
|
);
|
||
|
|
||
|
time_t TimeStarted();
|
||
|
VOID SetTimeStarted(time_t timeStarted);
|
||
|
|
||
|
BOOL FBeingDebugged(); // Is the script being debugged?
|
||
|
VOID IsBeingDebugged(); // Notify script that it is being debugged
|
||
|
|
||
|
HRESULT ResetToUninitialized(IASPObjectContextCustom *);
|
||
|
HRESULT GetASP();
|
||
|
HRESULT GetIDisp();
|
||
|
HRESULT GetIHostInfoUpdate();
|
||
|
IActiveScript *GetActiveScript();
|
||
|
LPTSTR SzTemplateName();
|
||
|
BOOL FIsZombie();
|
||
|
BOOL FIsCorrupted();
|
||
|
PROGLANG_ID ProgLang_Id();
|
||
|
DWORD DWInstanceID();
|
||
|
BOOL FFullyLoaded();
|
||
|
long GetTimeout();
|
||
|
BOOL FScriptTimedOut();
|
||
|
BOOL FScriptHadError();
|
||
|
void GetDebugDocument(CTemplate **ppTemplate, DWORD *pdwSourceContext);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* C S c r i p t E n g i n e M e t h o d s
|
||
|
*/
|
||
|
HRESULT AddScriptlet(LPCOLESTR wstrScript);
|
||
|
|
||
|
HRESULT AddObjects(BOOL fPersistNames = TRUE);
|
||
|
|
||
|
HRESULT AddAdditionalObject(LPWSTR strObjName, BOOL fPersistNames = TRUE);
|
||
|
|
||
|
HRESULT AddScriptingNamespace();
|
||
|
|
||
|
HRESULT Call(LPCOLESTR strEntryPoint);
|
||
|
|
||
|
HRESULT CheckEntryPoint(LPCOLESTR strEntryPoint);
|
||
|
|
||
|
HRESULT MakeEngineRunnable() { return(Call(NULL)); };
|
||
|
|
||
|
HRESULT ResetScript() { return m_pAS? m_pAS->SetScriptState(SCRIPTSTATE_UNINITIALIZED) : E_FAIL; }
|
||
|
|
||
|
VOID Zombify();
|
||
|
|
||
|
HRESULT InterruptScript(BOOL fAbnormal = TRUE);
|
||
|
|
||
|
HRESULT UpdateLocaleInfo(hostinfo hi);
|
||
|
|
||
|
HRESULT TryCall(LPCOLESTR strEntryPoint);
|
||
|
|
||
|
ULONG FinalRelease();
|
||
|
|
||
|
/*
|
||
|
* I U n k n o w n M e t h o d s
|
||
|
*/
|
||
|
STDMETHOD(QueryInterface)(REFIID riid, PVOID *ppvObject);
|
||
|
STDMETHOD_(ULONG, AddRef)(VOID);
|
||
|
STDMETHOD_(ULONG, Release)(VOID);
|
||
|
|
||
|
/*
|
||
|
* C A c t i v e S c r i p t S i t e M e t h o d s
|
||
|
*/
|
||
|
STDMETHOD(GetLCID)(LCID *plcid);
|
||
|
|
||
|
STDMETHOD(GetItemInfo)(LPCOLESTR pcszName,
|
||
|
DWORD dwReturnMask,
|
||
|
IUnknown **ppiunkItem,
|
||
|
ITypeInfo **ppti);
|
||
|
|
||
|
STDMETHOD(GetDocVersionString)(BSTR *pszVersion);
|
||
|
|
||
|
STDMETHOD(RequestItems)(BOOL fPersistNames = TRUE);
|
||
|
|
||
|
STDMETHOD(RequestTypeLibs)(VOID);
|
||
|
|
||
|
STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult,
|
||
|
const EXCEPINFO *pexcepinfo);
|
||
|
STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState);
|
||
|
|
||
|
STDMETHOD(OnScriptError)(IActiveScriptError __RPC_FAR *pscripterror);
|
||
|
|
||
|
STDMETHOD(OnEnterScript)(VOID);
|
||
|
|
||
|
STDMETHOD(OnLeaveScript)(VOID);
|
||
|
|
||
|
/*
|
||
|
* C A c t i v e S c r i p t S i t e D e b u g M e t h o d s
|
||
|
*/
|
||
|
STDMETHOD(GetDocumentContextFromPosition)(
|
||
|
/* [in] */ DWORD_PTR dwSourceContext,
|
||
|
/* [in] */ ULONG uCharacterOffset,
|
||
|
/* [in] */ ULONG uNumChars,
|
||
|
/* [out] */ IDebugDocumentContext **ppsc);
|
||
|
|
||
|
STDMETHOD(GetApplication)(/* [out] */ IDebugApplication **ppda);
|
||
|
|
||
|
STDMETHOD(GetRootApplicationNode)(/* [out] */ IDebugApplicationNode **);
|
||
|
|
||
|
STDMETHOD(OnScriptErrorDebug)(
|
||
|
/* [in] */ IActiveScriptErrorDebug *pErrorDebug,
|
||
|
/* [out] */ BOOL *pfEnterDebugger,
|
||
|
/* [out] */ BOOL *pfCallOnScriptErrorWhenContinuing);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* IHostInfoProvider methods
|
||
|
*/
|
||
|
|
||
|
STDMETHOD(GetHostInfo)(hostinfo hostinfoRequest, void **ppvInfo);
|
||
|
|
||
|
public:
|
||
|
#ifdef DBG
|
||
|
virtual void AssertValid() const;
|
||
|
#else
|
||
|
virtual void AssertValid() const {}
|
||
|
#endif
|
||
|
|
||
|
// Cache on per-class basis
|
||
|
ACACHE_INCLASS_DEFINITIONS()
|
||
|
};
|
||
|
|
||
|
inline VOID CActiveScriptEngine::Zombify() { m_fZombie = TRUE; }
|
||
|
inline BOOL CActiveScriptEngine::FFullyLoaded() { return(m_fScriptLoaded && m_fObjectsLoaded); }
|
||
|
inline BOOL CActiveScriptEngine::FIsZombie() { return(m_fZombie); }
|
||
|
inline BOOL CActiveScriptEngine::FIsCorrupted() { return(m_fCorrupted); }
|
||
|
inline time_t CActiveScriptEngine::TimeStarted() { return(m_timeStarted); }
|
||
|
inline VOID CActiveScriptEngine::SetTimeStarted(time_t timeStarted) { m_timeStarted = timeStarted; }
|
||
|
inline IActiveScript *CActiveScriptEngine::GetActiveScript() { return(m_pAS); }
|
||
|
inline LPTSTR CActiveScriptEngine::SzTemplateName() { return(m_szTemplateName); }
|
||
|
inline PROGLANG_ID CActiveScriptEngine::ProgLang_Id() { return(m_proglang_id); }
|
||
|
inline DWORD CActiveScriptEngine::DWInstanceID() { return(m_dwInstanceID); }
|
||
|
inline BOOL CActiveScriptEngine::FBeingDebugged() { return(m_fBeingDebugged); } // Is the script being debugged?
|
||
|
inline VOID CActiveScriptEngine::IsBeingDebugged() { m_fBeingDebugged = TRUE; }
|
||
|
inline BOOL CActiveScriptEngine::FScriptTimedOut() { return m_fScriptTimedOut; }
|
||
|
inline BOOL CActiveScriptEngine::FScriptHadError() { return m_fScriptHadError; }
|
||
|
inline long CActiveScriptEngine::GetTimeout() { return m_fBeingDebugged? LONG_MAX : m_pHitObj->GetScriptTimeout(); }
|
||
|
inline void CActiveScriptEngine::GetDebugDocument(CTemplate **ppTemplate, DWORD *pdwSourceContext)
|
||
|
{
|
||
|
if (ppTemplate) *ppTemplate = m_pTemplate;
|
||
|
if (pdwSourceContext) *pdwSourceContext = m_dwSourceContext;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*
|
||
|
* C A S E E l e m
|
||
|
*
|
||
|
* Script element. For keeping lists and queues of script engines
|
||
|
*
|
||
|
*/
|
||
|
class CASEElem : public CLruLinkElem
|
||
|
{
|
||
|
private:
|
||
|
CActiveScriptEngine *m_pASE;
|
||
|
|
||
|
public:
|
||
|
CASEElem() : m_pASE(NULL) {}
|
||
|
~CASEElem();
|
||
|
|
||
|
HRESULT Init(CActiveScriptEngine *pASE);
|
||
|
CActiveScriptEngine *PASE();
|
||
|
|
||
|
// Cache on per-class basis
|
||
|
ACACHE_INCLASS_DEFINITIONS()
|
||
|
};
|
||
|
|
||
|
inline CActiveScriptEngine *CASEElem::PASE() { return(m_pASE); }
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*
|
||
|
* C P L L E l e m
|
||
|
*
|
||
|
* Hash table list element for a Programming Language List.
|
||
|
*
|
||
|
*/
|
||
|
class CPLLElem : public CLinkElem
|
||
|
{
|
||
|
private:
|
||
|
PROGLANG_ID m_ProgLangId; // clsid for the language
|
||
|
|
||
|
public:
|
||
|
CPLLElem() : m_ProgLangId(CLSID_NULL) {};
|
||
|
~CPLLElem();
|
||
|
|
||
|
HRESULT Init(CHAR *szProgLangName, PROGLANG_ID progLangId);
|
||
|
PROGLANG_ID ProgLangId();
|
||
|
};
|
||
|
|
||
|
inline PROGLANG_ID CPLLElem::ProgLangId() { return(m_ProgLangId); }
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*
|
||
|
* C S c r i p t i n g N a m e s p a c e
|
||
|
*
|
||
|
* We need to keep track of all of the names which different engines (and typeinfos)
|
||
|
* contribute to the namespace. All of these names go into this object
|
||
|
* which we give to each engine with the SCRIPTITEM_GLOBALMEMBERS flag. When
|
||
|
* ActiveXScripting calls us back on GetIdsOfNames, we will call the engines
|
||
|
* we have cached until we find the name. When AXS calls us with Invoke,
|
||
|
* we will map the id to the appropriate engine and pass on the invoke
|
||
|
*
|
||
|
* Data structure note:
|
||
|
* We implement the ScriptingNamespace with a linked list of arrays.
|
||
|
* This gives reasonable access time and should minimize heap
|
||
|
* fragmentation. In debug mode, the number of buckets is small to
|
||
|
* excersize the resize code.
|
||
|
*
|
||
|
* NOTE: "ENGDISPMAX" should be a power of two - this will allow the optimizer
|
||
|
* to optimize the integer divide and modulus operations with bit-ands and
|
||
|
* shifts. However, the code does not assume that "ENGDISPMAX" is a power
|
||
|
* of two.
|
||
|
*/
|
||
|
|
||
|
#ifdef DBG
|
||
|
#define ENGDISPMAX 2
|
||
|
#else
|
||
|
#define ENGDISPMAX 32
|
||
|
#endif
|
||
|
|
||
|
typedef struct _engdisp
|
||
|
{
|
||
|
DISPID dispid; // the dispid that the engine really uses
|
||
|
IDispatch *pDisp; // the engine to call for this dispid
|
||
|
IDispatchEx *pDispEx; // the engine to call for this dispid
|
||
|
} ENGDISP;
|
||
|
|
||
|
typedef struct _engdispbucket : CDblLink
|
||
|
{
|
||
|
ENGDISP rgEngDisp[ENGDISPMAX+1];
|
||
|
} ENGDISPBUCKET;
|
||
|
|
||
|
class CEngineDispElem : public CDblLink
|
||
|
{
|
||
|
public:
|
||
|
IDispatch *m_pDisp;
|
||
|
IDispatchEx *m_pDispEx;
|
||
|
|
||
|
// Cache on per-class basis
|
||
|
ACACHE_INCLASS_DEFINITIONS()
|
||
|
};
|
||
|
|
||
|
class CScriptingNamespace : public IDispatchEx
|
||
|
{
|
||
|
private:
|
||
|
ULONG m_cRef; // Reference count
|
||
|
BOOLB m_fInited;
|
||
|
CDblLink m_listSE; // List of scripting engines (list of CSEElem's)
|
||
|
UINT m_cEngDispMac;
|
||
|
CDblLink m_listEngDisp;
|
||
|
|
||
|
HRESULT CacheDispID(CEngineDispElem *pEngine, DISPID dispidEngine, DISPID *pdispidCached);
|
||
|
HRESULT FetchDispID(DISPID dispid, ENGDISP **ppEngDisp);
|
||
|
|
||
|
public:
|
||
|
// public methods
|
||
|
CScriptingNamespace();
|
||
|
~CScriptingNamespace();
|
||
|
|
||
|
HRESULT Init();
|
||
|
HRESULT UnInit();
|
||
|
HRESULT ReInit();
|
||
|
HRESULT AddEngineToNamespace(CActiveScriptEngine *pASE);
|
||
|
|
||
|
// IUnknown
|
||
|
STDMETHODIMP QueryInterface(REFIID, void **);
|
||
|
STDMETHODIMP_(ULONG) AddRef(void);
|
||
|
STDMETHODIMP_(ULONG) Release(void);
|
||
|
// IDispatch
|
||
|
STDMETHODIMP GetTypeInfoCount(UINT *);
|
||
|
STDMETHODIMP GetTypeInfo(UINT, LCID, ITypeInfo **);
|
||
|
STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR **, UINT, LCID, DISPID *);
|
||
|
STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD,
|
||
|
DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *);
|
||
|
// IDispatchEx
|
||
|
STDMETHODIMP DeleteMemberByDispID(DISPID id);
|
||
|
STDMETHODIMP DeleteMemberByName(BSTR bstrName, DWORD grfdex);
|
||
|
STDMETHODIMP GetMemberName(DISPID id, BSTR *pbstrName);
|
||
|
STDMETHODIMP GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex);
|
||
|
STDMETHODIMP GetNameSpaceParent(IUnknown **ppunk);
|
||
|
STDMETHODIMP GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid);
|
||
|
STDMETHODIMP GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid);
|
||
|
STDMETHODIMP InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
|
||
|
VARIANT *pVarRes, EXCEPINFO *pei, IServiceProvider *pspCaller);
|
||
|
|
||
|
public:
|
||
|
#ifdef DBG
|
||
|
VOID AssertValid() const;
|
||
|
#else
|
||
|
VOID AssertValid() const {}
|
||
|
#endif
|
||
|
|
||
|
// Cache on per-class basis
|
||
|
ACACHE_INCLASS_DEFINITIONS()
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*
|
||
|
* U t i l i t i e s
|
||
|
*
|
||
|
* General utility functions
|
||
|
*
|
||
|
*/
|
||
|
HRESULT WrapTypeLibs(ITypeLib **prgpTypeLib, UINT cTypeLibs, IDispatch **ppDisp);
|
||
|
|
||
|
#endif // __ScrptMgr_h
|
||
|
|