Click here to Skip to main content
15,892,746 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello!

It was necessary to make own scripting engine (hereinafter Own Script Engine - OSE) for Windows XP and above, meaning it just to pass through all the running scripts (JS, VB, etc.) and send the original script handler with no changes (in the case of JS - jscript.dll). As I understand anti-virus software do the same for the analysis of malicious scripts.
So, I made OSE - it's COM-object that have an implementation of interfaces IActiveScript, IActiveScriptParse, IObjectSafety. OSE registers in the registry in place of the real script engine(hereinafter Real Script Engine - RSE). When you call OSE, it initializes the RSE and get IActiveScript, IActiveScriptParse interfaces:


...
(*realModule) = LoadLibrary( "jscript.dll" );

 if ( NULL != (*realModule) )
 {
  pfnDllGetClassObject = ( m_PFNDLLGETCLASSOBJECT )GetProcAddress( (*realModule), "DllGetClassObject" );

  if ( NULL != pfnDllGetClassObject )
  {
   pfnDllGetClassObject( scriptEngineCLSID, IID_IClassFactory, ( void** )&pFactory );

   if ( NULL != pFactory )
   {
    hr = pFactory->CreateInstance( NULL, IID_IActiveScript, ( void** )realScriptEngine );
    pFactory->Release();

    if ( FAILED( hr ) )
    {
     goto FreeRes;
    }

    hr = (*realScriptEngine)->QueryInterface( IID_IActiveScriptParse, ( void** )realScriptParser );

...


After that in OSE in implementation of methods of IActiveScript, IActiveScriptParse interfaces i simply call interface methods of RSE:

...
STDMETHODIMP CScriptEngineCOM::GetScriptSite( REFIID riid, void** ppv )
{
 return m_gpRealScriptEngine->GetScriptSite( riid, ppv );
}
 
 return E_FAIL;
}
...


So it's just forwarding parameters into RSE methods.

OSE works properly if I call "external" scripts, that is, for example, *. JS files with the script.
The problems begin when the scripts are processed, for example, in IE (tested on version 8). Some scripts are handled properly, and some are crashes the IE (mshtml.dll). Debugging shows that the script is caught with OSE. After that, the unloading of my COM-object begins, and after resources release in OSE the IE is crashing.
Example of crashing info:
<br />
 Problem signature: <br />
 Problem Event Name: APPCRASH <br />
 Application Name: iexplore.exe <br />
 Application Version: 8.0.7600.16385 <br />
 Application Timestamp: 4a5bc69e <br />
 The name of the module with the error: mshtml.dll <br />
 Version of the module with the error: 8.0.7600.16385 <br />
 The time stamp module with the error: 4a5bda8a <br />
 Exception Code: c0000005 <br />
 Exception Offset: 0017d347 <br />
 OS Version: 6.1.7600.2.0.0.256.1 <br />
 Language Code: 1049 <br />
 Additional Information 1: 0a9e <br />
 Additional Information 2: 0a9e372d3b4ad19135b953a78882e789 <br />
 Additional Information 3: 0a9e <br />
 Additional Information 4: 0a9e372d3b4ad19135b953a78882e789<br />


Is anyone faced with similar situations, what could be wrong?
And if there are examples of scripting engines, you'll be very grateful!

Thank you.
Posted
Updated 23-Jan-11 5:12am
v2

1 solution

i have my own scripting engine for a long time - but now i change to jscript engine. its not easy to handle all the interfaces within scripts. thats why very often circular references occur. for the first time you should load jscript by CoCreateInstance to enshure that jscript isnt unexpected unloaded. if you set any interfaces to the scripting engine SetScriptSite or other notification functions you should use zombie-interfaces. zombie means delagate all calls to the owner object if exist.
i.e:
class iZombieScriptSite : public IActiveScriptSite, public IDispatch
{
public: // IUnknown
  virtual HRESULT __stdcall        QueryInterface(REFIID riid,void** ppv);
  virtual unsigned long __stdcall  AddRef();
  virtual unsigned long __stdcall  Release();

public: // IActiveScriptSite
  virtual HRESULT __stdcall GetLCID(LCID *plcid)
    { return _delegate?_delegate->GetLCID(plcid):E_FAIL; }
  virtual HRESULT __stdcall GetItemInfo(LPCOLESTR pstrName,DWORD dwReturnMask,IUnknown **ppiunkItem,ITypeInfo **ppti)
    { return _delegate?_delegate->GetItemInfo(pstrName,dwReturnMask,ppiunkItem,ppti):E_FAIL; }
  virtual HRESULT __stdcall GetDocVersionString(BSTR *pbstrVersion)
    { return _delegate?_delegate->GetDocVersionString(pbstrVersion):E_FAIL; }
  virtual HRESULT __stdcall OnScriptTerminate(const VARIANT *pvarResult,const EXCEPINFO *pexcepinfo)
    { return _delegate?_delegate->OnScriptTerminate(pvarResult,pexcepinfo):E_FAIL; }
  virtual HRESULT __stdcall OnStateChange(SCRIPTSTATE ssScriptState)
    { return _delegate?_delegate->OnStateChange(ssScriptState):E_FAIL; }
  virtual HRESULT __stdcall OnScriptError(IActiveScriptError *pscripterror)
    { return _delegate?_delegate->OnScriptError(pscripterror):E_FAIL; }
  virtual HRESULT __stdcall OnEnterScript()
    { return _delegate?_delegate->OnEnterScript():E_FAIL; }
  virtual HRESULT __stdcall OnLeaveScript()
    { return _delegate?_delegate->OnLeaveScript():E_FAIL; }

public: // IDispatch
  virtual HRESULT __stdcall GetTypeInfoCount(UINT *pctinfo)
    { return _dispatch?_dispatch->GetTypeInfoCount(pctinfo):E_FAIL; }
  virtual HRESULT __stdcall GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)
    { return _dispatch?_dispatch->GetTypeInfo(iTInfo,lcid,ppTInfo):E_FAIL; }
  virtual HRESULT __stdcall GetIDsOfNames(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)
    { return _dispatch?_dispatch->GetIDsOfNames(riid,rgszNames,cNames,lcid,rgDispId):E_FAIL; }
  virtual HRESULT __stdcall Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
    { return _dispatch?_dispatch->Invoke(dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr):E_FAIL; }

public: // IDispatchEx
  virtual HRESULT __stdcall GetDispID(BSTR bstrName,DWORD grfdex,DISPID *pid)
    { return _dispatch?_dispatch->GetDispID(bstrName,grfdex,pid):E_FAIL; }
  virtual HRESULT __stdcall InvokeEx(DISPID id,LCID lcid,WORD wFlags,DISPPARAMS *pdp,VARIANT *pvarRes,EXCEPINFO *pei,IServiceProvider *pspCaller)
    { return _dispatch?_dispatch->InvokeEx(id,lcid,wFlags,pdp,pvarRes,pei,pspCaller):E_FAIL; }
  virtual HRESULT __stdcall DeleteMemberByName(BSTR bstrName,DWORD grfdex)
    { return _dispatch?_dispatch->DeleteMemberByName(bstrName,grfdex):E_FAIL; }
  virtual HRESULT __stdcall DeleteMemberByDispID(DISPID id)
    { return _dispatch?_dispatch->DeleteMemberByDispID(id):E_FAIL; }
  virtual HRESULT __stdcall GetMemberProperties(DISPID id,DWORD grfdexFetch,DWORD *pgrfdex)
    { return _dispatch?_dispatch->GetMemberProperties(id,grfdexFetch,pgrfdex):E_FAIL; }
  virtual HRESULT __stdcall GetMemberName(DISPID id,BSTR *pbstrName)
    { return _dispatch?_dispatch->GetMemberName(id,pbstrName):E_FAIL; }
  virtual HRESULT __stdcall GetNextDispID(DWORD grfdex,DISPID id,DISPID *pid)
    { return _dispatch?_dispatch->GetNextDispID(grfdex,id,pid):E_FAIL; }
  virtual HRESULT __stdcall GetNameSpaceParent(IUnknown **ppunk)
    { return _dispatch?_dispatch->GetNameSpaceParent(ppunk):E_FAIL; }

public:
        iZombieScriptSite(IActiveScriptSite* del,IDispatchEx* disp){ _ref=1; _delegate=del; _dispatch=disp; }
  void  OwnerRelease(){ _delegate=0; _dispatch=0; Release(); }

protected:
  virtual ~iZombieScriptSite()
  {
    _ref=_ref;
  }
private:
  long                _ref;
  IActiveScriptSite*  _delegate;
  IDispatchEx*        _dispatch;
};


so you can everytime disconnect by _zombie->OwnerRelease() without consequences.
close script with:
// IActiveScript*  _script;
_script->Close();

for releasing dependencies.
good luck.
 
Share this answer
 
Comments
ksor 27-Jan-11 10:19am    
Hi, mbue! Thank you very much for your reply. I have tried what you suggest, but it still crashes. Maybe you can give me the whole sources of your script engine? I'll be very grateful. Thank you again, mbue.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900