|
|
//
// CActiveScriptEngine.cpp
//
// Contains the definitions for the ActiveScriptEngine used in TBScript.
//
// Copyright (C) 2001 Microsoft Corporation
//
// Author: a-devjen (Devin Jenson)
//
#include "CActiveScriptEngine.h"
#include <crtdbg.h>
// CActiveScriptEngine::CActiveScriptEngine
//
// The constructor, simply grabs references to the dispatch objects
// we are using in this object.
//
// No return value.
CActiveScriptEngine::CActiveScriptEngine(CTBGlobal *TBGlobalPtr, CTBShell *TBShellPtr) { // Start out at a zero reference count
RefCount = 0;
// Grab the pointers
TBGlobal = TBGlobalPtr; TBShell = TBShellPtr;
// Ensure COM has been initialized
CoInitialize(NULL);
// Add a reference to the dispatches
if (TBGlobal != NULL) TBGlobal->AddRef();
if (TBShell != NULL) TBShell->AddRef(); }
// CActiveScriptEngine::~CActiveScriptEngine
//
// The destructor, release pointers from the dispatch objects.
//
// No return value.
CActiveScriptEngine::~CActiveScriptEngine(void) { // Remove a reference from the dispatche
if (TBGlobal != NULL) TBGlobal->Release();
TBGlobal = NULL;
// Remove a reference from the dispatche
if (TBShell != NULL) TBShell->Release();
TBShell = NULL; }
//
//
// Begin the IUnknown inherited interface
//
//
// CActiveScriptEngine::QueryInterface
//
// This is a COM exported method used for retrieving the interface.
//
// Returns S_OK on success, or E_NOINTERFACE on failure.
STDMETHODIMP CActiveScriptEngine::QueryInterface(REFIID RefIID, void **vObject) { // This interface is either IUnknown or IActiveScriptSite - nothing else
if (RefIID == IID_IUnknown || RefIID == IID_IActiveScriptSite) *vObject = (IActiveScriptSite *)this;
// We received an unsupported RefIID
else {
// De-reference the passed in pointer and error out
*vObject = NULL;
return E_NOINTERFACE; }
// Add a reference
if (*vObject != NULL) ((IUnknown*)*vObject)->AddRef();
return S_OK; }
// CActiveScriptEngine::AddRef
//
// Simply increments a number indicating the number of objects that contain
// a reference to this object.
//
// Returns the new reference count.
STDMETHODIMP_(ULONG) CActiveScriptEngine::AddRef(void) { return InterlockedIncrement(&RefCount); }
// CActiveScriptEngine::Release
//
// Simply decrements a number indicating the number of objects that contain
// a reference to this object. If the resulting reference count is zero,
// no objects contain a reference handle, therefore delete itself from
// memory as it is no longer used.
//
// Returns the new reference count.
STDMETHODIMP_(ULONG) CActiveScriptEngine::Release(void) { // Decrememt
if (InterlockedDecrement(&RefCount) != 0)
// Return the new value
return RefCount;
// It is 0, so delete itself
delete this;
return 0; }
//
//
// Begin the IActiveScript inherited interface
//
//
// CActiveScriptEngine::GetItemInfo
//
// Retreives a memory pointer to the specified (local) interface code or
// a reference handle.
//
// Returns S_OK, E_INVALIDARG, E_POINTER, or TYPE_E_ELEMENTNOTFOUND.
STDMETHODIMP CActiveScriptEngine::GetItemInfo(LPCOLESTR Name, DWORD ReturnMask, IUnknown **UnknownItem, ITypeInfo **TypeInfo) { // Initialize
IUnknown *TBInterface = NULL;
// If we are going to handle a specific item, NULL it's destination
// pointer out. We also use this opportunity to validate some
// argument pointers.
__try {
if (ReturnMask & SCRIPTINFO_IUNKNOWN) *UnknownItem = NULL;
if (ReturnMask & SCRIPTINFO_ITYPEINFO) *TypeInfo = NULL;
// This check is to make sure nothing else was passed into the mask
if (ReturnMask & ~(SCRIPTINFO_ITYPEINFO | SCRIPTINFO_IUNKNOWN)) {
// This should never happen, so ASSERT!
_ASSERT(FALSE);
return E_INVALIDARG; } }
// If the handler was executed, we got a bad pointer
__except (EXCEPTION_EXECUTE_HANDLER) {
// This should never happen, so ASSERT!
_ASSERT(FALSE);
return E_POINTER; }
// Freaky things...
_ASSERT(TBGlobal != NULL); _ASSERT(TBShell != NULL);
// Scan which item we are referring to
if (wcscmp(Name, OLESTR("Global")) == 0) {
// Check if the call wants the actual module code
if (ReturnMask & SCRIPTINFO_ITYPEINFO) {
// Check to make sure we have a valid TypeInfo
_ASSERT(TBGlobal->TypeInfo != NULL);
*TypeInfo = TBGlobal->TypeInfo; }
// Check if the call wants the Dispatch
if (ReturnMask & SCRIPTINFO_IUNKNOWN) {
*UnknownItem = TBGlobal;
TBGlobal->AddRef(); } }
else if (wcscmp(Name, OLESTR("TS")) == 0) {
// Check if the call wants the actual module code
if (ReturnMask & SCRIPTINFO_ITYPEINFO) {
// Check to make sure we have a valid TypeInfo
_ASSERT(TBShell->TypeInfo != NULL);
*TypeInfo = TBShell->TypeInfo; }
// Check if the call wants the Dispatch
if (ReturnMask & SCRIPTINFO_IUNKNOWN) {
*UnknownItem = TBShell;
TBShell->AddRef(); } }
else
// We don't have an object by that name!
return TYPE_E_ELEMENTNOTFOUND;
return S_OK; }
// CActiveScriptEngine::OnScriptError
//
// This event is executed when a script error occurs.
//
// Returns S_OK on success or an OLE defined error on failure.
STDMETHODIMP CActiveScriptEngine::OnScriptError(IActiveScriptError *ScriptError) { // Initialize
OLECHAR *ErrorData; OLECHAR *Message; DWORD Cookie; LONG CharPos; ULONG LineNum; BSTR LineError = NULL; EXCEPINFO ExceptInfo = { 0 }; OLECHAR *ScriptText = NULL;
// Get script error data
ScriptError->GetSourcePosition(&Cookie, &LineNum, &CharPos); ScriptError->GetSourceLineText(&LineError); ScriptError->GetExceptionInfo(&ExceptInfo);
ScriptText = LineError ? LineError : (ExceptInfo.bstrHelpFile ? ExceptInfo.bstrHelpFile : NULL);
// Allocate a data buffer for use with our error data
ErrorData = (OLECHAR *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024);
if (ErrorData == NULL) return E_OUTOFMEMORY;
// Format the error code into text
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, ExceptInfo.scode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&Message, 0, NULL) == 0)
Message = NULL;
// Make it pretty for whatever data is provided
if (ExceptInfo.bstrSource != NULL && Message != NULL) wsprintfW(ErrorData, OLESTR("%s\n%s [Line: %d]"), Message, ExceptInfo.bstrSource, LineNum);
else if (Message != NULL) wsprintfW(ErrorData, OLESTR("%s\n[Line: %d]"), Message, LineNum);
else if (ExceptInfo.bstrSource != NULL) wsprintfW(ErrorData, OLESTR("Unknown Exception\n%s [Line: %d]"), ExceptInfo.bstrSource, LineNum);
else wsprintfW(ErrorData, OLESTR("Unknown Exception\n[Line: %d]"), LineNum);
if (ScriptText != NULL) {
// Format a long-readable string
wsprintfW(ErrorData, OLESTR("%s\n\n%s:\n\n%s"), ErrorData, ExceptInfo.bstrDescription, ScriptText); }
else {
// Format a readable string
wsprintfW(ErrorData, OLESTR("%s\n\n%s"), ErrorData, ExceptInfo.bstrDescription); }
// Deallocate temporary strings
SysFreeString(LineError); SysFreeString(ExceptInfo.bstrSource); SysFreeString(ExceptInfo.bstrDescription); SysFreeString(ExceptInfo.bstrHelpFile);
if (Message != NULL) {
LocalFree(Message); Message = NULL; }
// Tell the user about our error
MessageBoxW(GetDesktopWindow(), ErrorData, OLESTR("TBScript Parse Error"), MB_SETFOREGROUND);
// Free the data buffer
HeapFree(GetProcessHeap(), 0, ErrorData);
return S_OK; }
// CActiveScriptEngine::GetLCID
//
// Retreives the LCID of the interface.
//
// Returns S_OK on success or E_POINTER on failure.
STDMETHODIMP CActiveScriptEngine::GetLCID(LCID *Lcid) { // Get the LCID on this user-defined pointer
__try {
*Lcid = GetUserDefaultLCID(); }
// If the handler was executed, we got a bad pointer
__except (EXCEPTION_EXECUTE_HANDLER) {
// This should never happen, so ASSERT!
_ASSERT(FALSE);
return E_POINTER; }
return S_OK; }
// CActiveScriptEngine::GetDocVersionString
//
// Unsupported, returns E_NOTIMPL.
STDMETHODIMP CActiveScriptEngine::GetDocVersionString(BSTR *Version) { // Get the LCID on this user-defined pointer
__try {
*Version = NULL; }
// If the handler was executed, we got a bad pointer
__except (EXCEPTION_EXECUTE_HANDLER) {
// This should never happen, so ASSERT!
_ASSERT(FALSE); }
return E_NOTIMPL; }
// CActiveScriptEngine::OnScriptTerminate
//
// Unsupported, returns S_OK.
STDMETHODIMP CActiveScriptEngine::OnScriptTerminate(const VARIANT *varResult, const EXCEPINFO *ExceptInfo) { return S_OK; }
// CActiveScriptEngine::OnStateChange
//
// Unsupported, returns S_OK.
STDMETHODIMP CActiveScriptEngine::OnStateChange(SCRIPTSTATE ScriptState) { return S_OK; }
// CActiveScriptEngine::OnEnterScript
//
// Unsupported, returns S_OK.
STDMETHODIMP CActiveScriptEngine::OnEnterScript(void) { return S_OK; }
// CActiveScriptEngine::OnLeaveScript
//
// Unsupported, returns S_OK.
STDMETHODIMP CActiveScriptEngine::OnLeaveScript(void) { return S_OK; }
|