/** * @file XTPActiveScriptEngine.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "StdAfx.h" #include "Common/Base/Diagnostic/XTPDisableAdvancedWarnings.h" #include #include #include #include "Common/Base/Diagnostic/XTPEnableAdvancedWarnings.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSynchro.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPResourceManager.h" #include "Common/XTPActiveScriptEngine.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef __IActiveScriptGarbageCollector_INTERFACE_DEFINED__ typedef enum tagSCRIPTGCTYPE { SCRIPTGCTYPE_NORMAL = 0, SCRIPTGCTYPE_EXHAUSTIVE = 1 } SCRIPTGCTYPE; // {6AA2C4A0-2B53-11d4-A2A0-00104BD35090} DEFINE_GUID(XTPIID_IActiveScriptGarbageCollector, 0x6aa2c4a0, 0x2b53, 0x11d4, 0xa2, 0xa0, 0x00, 0x10, 0x4b, 0xd3, 0x50, 0x90); MIDL_INTERFACE("6AA2C4A0-2B53-11d4-A2A0-00104BD35090") IActiveScriptGarbageCollector : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CollectGarbage(SCRIPTGCTYPE scriptgctype) = 0; }; #endif //////////////////////////////////////////////////////////////////////////////// // CXTPActiveScriptObjectContext implementation CXTPActiveScriptObjectContext::CXTPActiveScriptObjectContext(CXTPActiveScriptEngine* pEngine, IDispatch* pObject) : m_nRefs(1) , m_pEngine(pEngine) , m_pObject(pObject) { _ASSERTE(NULL != m_pEngine); _ASSERTE(NULL != m_pObject); m_pEngine->GetControllingUnknown()->AddRef(); m_pObject->AddRef(); } CXTPActiveScriptObjectContext::~CXTPActiveScriptObjectContext() { _ASSERTE(0 == m_nRefs); m_pObject->Release(); m_pEngine->GetControllingUnknown()->Release(); } ULONG CXTPActiveScriptObjectContext::AddRef() { return ++m_nRefs; } ULONG CXTPActiveScriptObjectContext::Release() { _ASSERTE(0 < m_nRefs); ULONG nRefs = --m_nRefs; if (0 == nRefs) delete this; return nRefs; } HRESULT CXTPActiveScriptObjectContext::GetValue(LPCWSTR lpszName, CComVariant* pvtResult) { _ASSERTE(NULL != lpszName); _ASSERTE(NULL != pvtResult); return ProcessNamedItem(lpszName, DISPATCH_PROPERTYGET, NULL, 0, pvtResult); } HRESULT CXTPActiveScriptObjectContext::SetValue(LPCWSTR lpszName, VARIANT vtValue) { _ASSERTE(NULL != lpszName); return ProcessNamedItem(lpszName, DISPATCH_PROPERTYPUT, &vtValue, 1); } HRESULT CXTPActiveScriptObjectContext::InvokeWithArgs(VARIANT* lpArguments /*= NULL*/, UINT nCount /*= 0*/, VARIANT* pvtResult /*= NULL*/) { return ProcessNamedItem(NULL, DISPATCH_METHOD, lpArguments, nCount, pvtResult); } CXTPActiveScriptObjectContext* CXTPActiveScriptObjectContext::GetContext(LPCWSTR lpszName) { CXTPActiveScriptObjectContext* pContext = NULL; CComVariant value; if (SUCCEEDED(GetValue(lpszName, &value))) { _ASSERTE(VT_DISPATCH == value.vt); pContext = new CXTPActiveScriptObjectContext(m_pEngine, value.pdispVal); } return pContext; } HRESULT CXTPActiveScriptObjectContext::ProcessNamedItem(LPCWSTR lpszName, WORD wFlags, VARIANT* lpArguments, UINT nCount, VARIANT* pvtResult /*= NULL*/) { _ASSERTE(NULL != lpArguments ? 0 < nCount : 0 == nCount); DISPID dispId = DISPID_VALUE; HRESULT hr = S_OK; // Obtain named item DISPID. if (NULL != lpszName) { hr = m_pObject->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpszName, 1, LOCALE_SYSTEM_DEFAULT, &dispId); if (S_OK != hr) { CComQIPtr pDispEx = m_pObject; if (!pDispEx) return DISP_E_MEMBERNOTFOUND; hr = pDispEx->GetDispID(CComBSTR(lpszName), fdexNameCaseSensitive, &dispId); if (S_OK != hr) return hr; } } // If arguments specified, build a reversed list of arguments. DISPPARAMS dispParams = { 0 }; CArray vtArgs; if (NULL != lpArguments) { vtArgs.SetSize(XTPToIntPtrChecked(nCount)); for (UINT i = 0; i < nCount; ++i) { vtArgs.SetAt(XTPToIntPtrChecked(nCount - 1 - i), lpArguments[i]); } dispParams.rgvarg = &vtArgs[0]; dispParams.cArgs = nCount; } DISPID dispidNamed = DISPID_PROPERTYPUT; if (wFlags & DISPATCH_PROPERTYPUT) { dispParams.cNamedArgs = 1; dispParams.rgdispidNamedArgs = &dispidNamed; } // Invoke named item with arguments specified. EXCEPINFO exceptionInfo = { 0 }; hr = m_pObject->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, &dispParams, pvtResult, &exceptionInfo, NULL); if (FAILED(hr) && DISP_E_EXCEPTION == hr) m_pEngine->SetExceptionInfo(&exceptionInfo); return hr; } #ifndef _XTP_DISABLE_COMPAREELEMENTS_SPECIALIZATION template<> AFX_INLINE BOOL AFXAPI CompareElements(const LPCWSTR* pElement1, const LPCWSTR* pElement2) { return (pElement1 == pElement2 || wcscmp(*pElement1, *pElement2) == 0); } #endif //////////////////////////////////////////////////////////////////////////////// // CXTPActiveScriptEngine implementation IMPLEMENT_DYNAMIC(CXTPActiveScriptEngine, CXTPCmdTarget); BEGIN_INTERFACE_MAP(CXTPActiveScriptEngine, CXTPCmdTarget) INTERFACE_PART(CXTPActiveScriptEngine, IID_IActiveScriptSite, ActiveScriptSite) END_INTERFACE_MAP() CXTPActiveScriptEngine::CXTPActiveScriptEngine() : m_pSite(NULL) , m_pEngine(NULL) , m_pParser(NULL) , m_pExceptionData(NULL) { } CXTPActiveScriptEngine::~CXTPActiveScriptEngine() { Uninitialize(); } HRESULT CXTPActiveScriptEngine::Initialize(LPCWSTR lpszEngineProgId, IActiveScriptSite* pSite /*= NULL*/) { _ASSERTE(NULL != lpszEngineProgId); Uninitialize(); // Create engine instance. CLSID clsidScriptEngine; HRESULT hr = CLSIDFromProgID(lpszEngineProgId, &clsidScriptEngine); if (FAILED(hr)) return hr; hr = CoCreateInstance(clsidScriptEngine, NULL, CLSCTX_ALL, IID_IActiveScript, (LPVOID*)&m_pEngine); if (FAILED(hr)) { Uninitialize(); return hr; } // Initialize parser. hr = m_pEngine->QueryInterface(&m_pParser); if (FAILED(hr)) { Uninitialize(); return hr; } hr = m_pParser->InitNew(); if (FAILED(hr)) { Uninitialize(); return hr; } hr = m_pEngine->SetScriptSite(&m_xActiveScriptSite); if (FAILED(hr)) { Uninitialize(); return hr; } m_pSite = pSite; // No AddRef is needed return S_OK; } void CXTPActiveScriptEngine::Uninitialize() { SetExceptionInfo(NULL); if (NULL != m_pParser) { m_pParser->Release(); m_pParser = NULL; } if (NULL != m_pEngine) { IActiveScriptSite* site = NULL; site = NULL; CComQIPtr pGC = m_pEngine; if (pGC) { pGC->CollectGarbage(SCRIPTGCTYPE_EXHAUSTIVE); pGC.Release(); } m_pEngine->SetScriptState(SCRIPTSTATE_CLOSED); m_pEngine->Close(); m_pEngine->Release(); m_pEngine = NULL; } m_NamedItemDataMap.RemoveAll(); m_pSite = NULL; } HRESULT CXTPActiveScriptEngine::LoadCode(LPCWSTR lpszCode) { _ASSERTE(NULL != lpszCode); _ASSERTE(NULL != m_pParser); #ifdef _DEBUG m_strLoadedCode = CComBSTR(); #endif HRESULT hr = m_pEngine->SetScriptState(SCRIPTSTATE_INITIALIZED); if (SUCCEEDED(hr)) hr = m_pParser->ParseScriptText(lpszCode, NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISVISIBLE, NULL, NULL); #ifdef _DEBUG if (SUCCEEDED(hr)) m_strLoadedCode = lpszCode; #endif return hr; } HRESULT CXTPActiveScriptEngine::Run() { _ASSERTE(NULL != m_pEngine); return m_pEngine->SetScriptState(SCRIPTSTATE_CONNECTED); } CXTPActiveScriptObjectContext* CXTPActiveScriptEngine::GetGlobalContext() const { _ASSERTE(NULL != m_pEngine); IDispatch* pDispScript = NULL; if (FAILED(m_pEngine->GetScriptDispatch(NULL, &pDispScript))) return NULL; return CreateContext(pDispScript); } CXTPActiveScriptObjectContext* CXTPActiveScriptEngine::CreateContext(LPDISPATCH pDispObject) const { ASSERT(NULL != pDispObject); return new CXTPActiveScriptObjectContext(const_cast(this), pDispObject); } HRESULT CXTPActiveScriptEngine::AddNamedItem(LPCWSTR lpszName, LPVOID lpItemData /*= NULL*/, DWORD dwFlags /*= SCRIPTITEM_ISVISIBLE*/) { _ASSERTE(NULL != lpszName); _ASSERTE(NULL != m_pEngine); HRESULT hr = m_pEngine->AddNamedItem(lpszName, dwFlags); if (SUCCEEDED(hr) && NULL != lpItemData) m_NamedItemDataMap[lpszName] = lpItemData; return hr; } LPVOID CXTPActiveScriptEngine::GetNamedItemData(LPCWSTR lpszName) const { _ASSERTE(NULL != lpszName); LPVOID lpItemData = NULL; m_NamedItemDataMap.Lookup(lpszName, lpItemData); return lpItemData; } void CXTPActiveScriptEngine::SetExceptionInfo(const EXCEPINFO* pExcepInfo /*= NULL*/, BSTR strCodeLine /*= NULL*/, ULONG nLine /*= 0*/, LONG nCharPos /*= 0*/, DWORD dwErrCtx /*= 0*/) { if (NULL != m_pExceptionData) { if (NULL != m_pExceptionData->info.bstrSource) SysFreeString(m_pExceptionData->info.bstrSource); if (NULL != m_pExceptionData->info.bstrDescription) SysFreeString(m_pExceptionData->info.bstrDescription); if (NULL != m_pExceptionData->info.bstrHelpFile) SysFreeString(m_pExceptionData->info.bstrHelpFile); if (NULL != m_pExceptionData->strCodeLine) SysFreeString(m_pExceptionData->strCodeLine); delete m_pExceptionData; m_pExceptionData = NULL; } if (NULL != pExcepInfo) { m_pExceptionData = new ExceptionData; memset(m_pExceptionData, 0, sizeof(ExceptionData)); m_pExceptionData->info = *pExcepInfo; if (NULL != pExcepInfo->bstrSource) m_pExceptionData->info.bstrSource = SysAllocString(pExcepInfo->bstrSource); if (NULL != pExcepInfo->bstrDescription) m_pExceptionData->info.bstrDescription = SysAllocString(pExcepInfo->bstrDescription); if (NULL != pExcepInfo->bstrHelpFile) m_pExceptionData->info.bstrHelpFile = SysAllocString(pExcepInfo->bstrHelpFile); if (NULL != strCodeLine) m_pExceptionData->strCodeLine = strCodeLine; m_pExceptionData->nLine = nLine; m_pExceptionData->nCharPos = nCharPos; m_pExceptionData->dwErrCtx = dwErrCtx; } } #ifdef _DEBUG void CXTPActiveScriptEngine::DumpCode(ULONG nLine) const { const INT_PTR nMax = 10; CList<_bstr_t, const _bstr_t&> lines; LPCWSTR pLine = m_strLoadedCode; UINT nLineCounter = 0; UINT nRemainingLines = nMax + 1; while (NULL != pLine && 0 < nRemainingLines) { LPCWSTR pNext = wcschr(pLine, L'\n'); if (NULL != pNext) { UINT nLen = XTPToUInt(pNext - pLine); if (0 < nLen) { _bstr_t s; s.Assign(::SysAllocStringLen(pLine, nLen)); lines.AddTail(s); } else { lines.AddTail(L""); } pLine = pNext + 1; } else { lines.AddTail(pLine); pLine = NULL; } while (NULL != pLine && L'\r' == *pLine) { ++pLine; if (L'\0' == *pLine) pLine = NULL; } if (nMax < lines.GetCount()) lines.RemoveHead(); if (nRemainingLines <= nMax) { --nRemainingLines; TRACE(_T(" %u:\t%ls\n"), nLineCounter, lines.GetTail().operator BSTR()); } else if (nLineCounter == nLine) { POSITION pos = lines.GetHeadPosition(); UINT nBackCounter = XTPToUInt(lines.GetCount()); while (NULL != pos) { const _bstr_t& strLine = lines.GetNext(pos); --nBackCounter; TRACE(_T("%ls%u:\t%ls\n"), (NULL != pos ? L" " : L"--> "), nLineCounter - nBackCounter, strLine.operator BSTR()); } --nRemainingLines; } ++nLineCounter; } } #endif /////////////////////////////////////////////////////////////////////////////// // IActiveScriptSite implementation XTP_IMPLEMENT_IUNKNOWN(CXTPActiveScriptEngine, ActiveScriptSite) XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::GetLCID(LCID* plcid) { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = E_NOTIMPL; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->GetLCID(plcid); } return hr; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::GetItemInfo(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppiunkItem, ITypeInfo** ppti) { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = TYPE_E_ELEMENTNOTFOUND; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->GetItemInfo(pstrName, dwReturnMask, ppiunkItem, ppti); } return hr; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::GetDocVersionString(BSTR* pbstrVersion) { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = E_NOTIMPL; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->GetDocVersionString(pbstrVersion); } return hr; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::OnScriptTerminate( const VARIANT* pvarResult, const EXCEPINFO* pexcepinfo) { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = S_OK; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->OnScriptTerminate(pvarResult, pexcepinfo); } return hr; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::OnStateChange(SCRIPTSTATE ssScriptState) { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = S_OK; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->OnStateChange(ssScriptState); } return hr; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::OnScriptError(IActiveScriptError* pScriptError) { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); if (NULL == pScriptError) return E_POINTER; DWORD dwErrCtx = 0; ULONG nLine = 0; LONG nPos = 0; pScriptError->GetSourcePosition(&dwErrCtx, &nLine, &nPos); EXCEPINFO exceptionInfo = { 0 }; pScriptError->GetExceptionInfo(&exceptionInfo); CComBSTR strCodeLine; pScriptError->GetSourceLineText(&strCodeLine); TRACE(_T("Script exception detected (code 0x%08X): \"%ls\" at %i:%i (\"%ls\")\n"), exceptionInfo.wCode, (NULL != exceptionInfo.bstrDescription ? exceptionInfo.bstrDescription : L"undefined"), nLine, nPos, (NULL != strCodeLine.m_str ? strCodeLine.m_str : L"undefined")); pThis->SetExceptionInfo(&exceptionInfo, strCodeLine.Detach(), nLine, nPos, dwErrCtx); #ifdef _DEBUG pThis->DumpCode(nLine); #endif if (NULL != pThis->m_pSite) return pThis->m_pSite->OnScriptError(pScriptError); return S_OK; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::OnEnterScript() { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = S_OK; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->OnEnterScript(); } return hr; } XTP_STDMETHODIMP CXTPActiveScriptEngine::XActiveScriptSite::OnLeaveScript() { METHOD_PROLOGUE(CXTPActiveScriptEngine, ActiveScriptSite); HRESULT hr = S_OK; if (NULL != pThis->m_pSite) { hr = pThis->m_pSite->OnLeaveScript(); } return hr; } class CXTPActiveScriptStdRuntime::TimeoutTask { public: TimeoutTask(CXTPActiveScriptStdRuntime& runtime, LPDISPATCH lpDispCallback, UINT nTimeout) : m_lpDispCallback(lpDispCallback) , m_nTimeout(nTimeout) , m_runtime(runtime) { _ASSERTE(NULL != m_lpDispCallback); m_lpDispCallback->AddRef(); } ~TimeoutTask() { m_lpDispCallback->Release(); } LPDISPATCH m_lpDispCallback; UINT m_nTimeout; CXTPActiveScriptStdRuntime& m_runtime; }; class CXTPActiveScriptStdRuntime::TimeoutTaskRegistry : public CXTPSynchronized { friend class CXTPSingleton; public: static TimeoutTaskRegistry* GetInstance() { return &CXTPSingleton::Instance(); } void Add(UINT_PTR nTimeoutId, TimeoutTask* pTask) { _ASSERTE(NULL != pTask); TimeoutTask* pOldTask = Withdraw(nTimeoutId); if (NULL != pOldTask) { delete pOldTask; } m_TimeoutTaskMap[nTimeoutId] = pTask; } TimeoutTask* Withdraw(UINT_PTR nTimeoutId) { TimeoutTask* pTask = NULL; if (m_TimeoutTaskMap.Lookup(nTimeoutId, pTask)) { m_TimeoutTaskMap.RemoveKey(nTimeoutId); } return pTask; } TimeoutTask* WithdrawFirst(CXTPActiveScriptStdRuntime& runtime, UINT_PTR& nTimeoutId) { TimeoutTask* pFirstTask = NULL; POSITION pos = m_TimeoutTaskMap.GetStartPosition(); while (NULL != pos) { TimeoutTask* pTask = NULL; m_TimeoutTaskMap.GetNextAssoc(pos, nTimeoutId, pTask); if (&runtime == &pTask->m_runtime) { m_TimeoutTaskMap.RemoveKey(nTimeoutId); pFirstTask = pTask; break; } } return pFirstTask; } private: TimeoutTaskRegistry() { } public: ~TimeoutTaskRegistry() { _ASSERTE(m_TimeoutTaskMap.IsEmpty()); } private: CMap m_TimeoutTaskMap; }; IMPLEMENT_DYNAMIC(CXTPActiveScriptStdRuntime, CXTPCmdTarget); #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_DISPATCH_MAP(CXTPActiveScriptStdRuntime, CXTPCmdTarget) DISP_FUNCTION(CXTPActiveScriptStdRuntime, "setTimeout", OleSetTimeout, VT_I4, VTS_DISPATCH VTS_I4) DISP_FUNCTION(CXTPActiveScriptStdRuntime, "clearTimeout", OleClearTimeout, VT_EMPTY, VTS_I4) DISP_FUNCTION(CXTPActiveScriptStdRuntime, "debugLog", OleDebugLog, VT_EMPTY, VTS_VARIANT) DISP_FUNCTION(CXTPActiveScriptStdRuntime, "getObject", OleGetObject, VT_DISPATCH, VTS_BSTR) END_DISPATCH_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" CXTPActiveScriptStdRuntime::CXTPActiveScriptStdRuntime() : m_pSite(NULL) , m_bAddSiteRef(FALSE) { EnableAutomation(); } CXTPActiveScriptStdRuntime::CXTPActiveScriptStdRuntime(IActiveScriptSite* pSite, BOOL bAddSiteRef /*= TRUE*/) : m_pSite(pSite) , m_bAddSiteRef(bAddSiteRef) { _ASSERTE(NULL != m_pSite); EnableAutomation(); } CXTPActiveScriptStdRuntime::~CXTPActiveScriptStdRuntime() { Shutdown(); if (NULL != m_pSite && m_bAddSiteRef) m_pSite->Release(); } void CXTPActiveScriptStdRuntime::Shutdown() { UINT_PTR nTimeoutId = 0; TimeoutTask* pTask = NULL; XTP_GUARD_EXCLUSIVE_(TimeoutTaskRegistry, TimeoutTaskRegistry::GetInstance(), pRegistry) { while (NULL != (pTask = pRegistry->WithdrawFirst(*this, nTimeoutId))) { KillTimer(NULL, nTimeoutId); delete pTask; } } } UINT CXTPActiveScriptStdRuntime::OleSetTimeout(LPDISPATCH lpDispCallback, UINT nTimeout) { UINT_PTR nTimeoutId = 0; if (NULL != lpDispCallback) { nTimeoutId = SetTimer(NULL, 0, nTimeout, CXTPActiveScriptStdRuntime::TimeoutProc); if (0 != nTimeoutId) { XTPAccessExclusive(TimeoutTaskRegistry::GetInstance()) ->Add(nTimeoutId, new TimeoutTask(*this, lpDispCallback, nTimeout)); } } return XTPToUInt(nTimeoutId); } void CXTPActiveScriptStdRuntime::OleClearTimeout(UINT nTimeoutId) { TimeoutTask* pTask = XTPAccessExclusive(TimeoutTaskRegistry::GetInstance())->Withdraw(nTimeoutId); if (NULL != pTask) { KillTimer(NULL, nTimeoutId); delete pTask; } } void CALLBACK CXTPActiveScriptStdRuntime::TimeoutProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { UNREFERENCED_PARAMETER(hWnd); UNREFERENCED_PARAMETER(dwTime); UNREFERENCED_PARAMETER(uMsg); TimeoutTask* pTask = XTPAccessExclusive(TimeoutTaskRegistry::GetInstance())->Withdraw(idEvent); if (NULL != pTask) { KillTimer(NULL, idEvent); DISPPARAMS dispParams = { 0 }; HRESULT hr = pTask->m_lpDispCallback->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, NULL, NULL, NULL); if (FAILED(hr)) { TRACE1("ActiveScriptStdRuntime::setTimeout failed: 0x%08X\n", hr); } delete pTask; } } void CXTPActiveScriptStdRuntime::OleDebugLog(const VARIANT& message) { if (VT_BSTR != message.vt) { CComVariant v; CComVariant m(message); if (S_OK == ::VariantChangeType(&v, &m, VARIANT_ALPHABOOL, VT_BSTR)) OleDebugLog(v); return; } if (NULL == message.bstrVal) return; OutputDebugStringW(message.bstrVal); OutputDebugStringW(L"\n"); } LPDISPATCH CXTPActiveScriptStdRuntime::OleGetObject(LPCTSTR lpszName) { if (NULL == lpszName || NULL == m_pSite) return NULL; LPDISPATCH pDisp = NULL; LPUNKNOWN pUnk = NULL; if (S_OK == m_pSite->GetItemInfo(XTP_CT2CW(lpszName), SCRIPTINFO_IUNKNOWN, &pUnk, NULL) && NULL != pUnk) { pUnk->QueryInterface(&pDisp); pUnk->Release(); } return pDisp; }