mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
483 lines
11 KiB
C++
483 lines
11 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include "IEWebGameCtrl.h"
|
|
|
|
#include "../common/webCommon.h"
|
|
|
|
// CIEWebGameCtrl (one and only one instance please)
|
|
CIEWebGameCtrl* CIEWebGameCtrl::sInstance = NULL;
|
|
|
|
// Javascript accessible methods
|
|
|
|
// plugin.getVariable("$MyVariable"); - get a Torque 3D console variable
|
|
STDMETHODIMP CIEWebGameCtrl::getVariable(BSTR name, BSTR* value)
|
|
{
|
|
std::wstring wstr;
|
|
std::string sstr;
|
|
const char* astr;
|
|
|
|
wstr.assign(name);
|
|
sstr = WebCommon::WStringToString(wstr);
|
|
astr = sstr.c_str();
|
|
|
|
const char* avalue = NULL;
|
|
char vinfo[256];
|
|
vinfo[0] = 0;
|
|
|
|
// requesting the version information
|
|
if (!_stricmp(astr, "$version"))
|
|
{
|
|
char plugin[4096];
|
|
|
|
GetModuleFileNameA(WebCommon::gPluginModule, plugin, 4096);
|
|
DWORD dwHandle = 0;
|
|
DWORD dwSize = GetFileVersionInfoSizeA(plugin, &dwHandle);
|
|
if (dwSize >= 0)
|
|
{
|
|
LPBYTE lpInfo = new BYTE[dwSize];
|
|
ZeroMemory(lpInfo, dwSize);
|
|
if(GetFileVersionInfoA(plugin, 0, dwSize, lpInfo))
|
|
{
|
|
UINT valLen = MAX_PATH;
|
|
LPVOID valPtr = NULL;
|
|
if(::VerQueryValue(lpInfo,
|
|
TEXT("\\"),
|
|
&valPtr,
|
|
&valLen))
|
|
{
|
|
VS_FIXEDFILEINFO* pFinfo = (VS_FIXEDFILEINFO*)valPtr;
|
|
|
|
sprintf(vinfo, "%i.%i", (pFinfo->dwProductVersionMS >> 16) & 0xFF, (pFinfo->dwFileVersionMS) & 0xFF);
|
|
|
|
}
|
|
}
|
|
delete[] lpInfo;
|
|
}
|
|
|
|
if (!vinfo[0])
|
|
strcpy(vinfo, "-1");
|
|
|
|
|
|
avalue = vinfo;
|
|
|
|
}
|
|
else
|
|
avalue = WebCommon::GetVariable(astr);
|
|
|
|
sstr = avalue;
|
|
wstr = WebCommon::StringToWString(sstr);
|
|
|
|
*value = SysAllocString(wstr.c_str());
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// plugin.setVariable("$MyVariable", 42); - set a Torque 3D console variable
|
|
STDMETHODIMP CIEWebGameCtrl::setVariable(BSTR name, BSTR value)
|
|
{
|
|
std::wstring wstr;
|
|
std::string nstr, vstr;
|
|
const char* vname;
|
|
const char* vvalue;
|
|
|
|
wstr.assign(name);
|
|
nstr = WebCommon::WStringToString(wstr);
|
|
vname = nstr.c_str();
|
|
|
|
wstr.assign(value);
|
|
vstr = WebCommon::WStringToString(wstr);
|
|
vvalue = vstr.c_str();
|
|
|
|
WebCommon::SetVariable(vname, vvalue);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// plugin.startup(); - called once web page is fully loaded and plugin (including Torque 3D) is initialized
|
|
STDMETHODIMP CIEWebGameCtrl::startup()
|
|
{
|
|
|
|
mInitialized = true;
|
|
std::vector<JavasScriptExport>::iterator i;
|
|
for (i = mJavaScriptExports.begin(); i != mJavaScriptExports.end();i++)
|
|
{
|
|
internalExportFunction(*i);
|
|
}
|
|
|
|
WebCommon::AddSecureFunctions();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// var result = plugin.callScript("mySecureFunction('one', 'two', 'three');"); - call a TorqueScript function marked as secure in webConfig.h with supplied arguments
|
|
// includes function parser
|
|
STDMETHODIMP CIEWebGameCtrl::callScript(BSTR code, BSTR* value)
|
|
{
|
|
std::wstring wcode;
|
|
std::string scode;
|
|
wcode.assign(code);
|
|
scode = WebCommon::WStringToString(wcode);
|
|
const char* sig = scode.c_str();
|
|
|
|
// do not allow large strings which could be used maliciously
|
|
if (scode.length() > 255 || !mInitialized)
|
|
{
|
|
*value = SysAllocString(L"");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// data buffers for laying out data in a Torque 3D console friendly manner
|
|
char nameSpace[256];
|
|
char fname[256];
|
|
char argv[256][256];
|
|
char* argvv[256];
|
|
int argc = 0;
|
|
unsigned int argBegin = 0;
|
|
|
|
memset(nameSpace, 0, 256);
|
|
memset(fname, 0, 256);
|
|
memset(argv, 0, 256 * 256);
|
|
|
|
for (unsigned int i = 0; i < scode.length(); i++)
|
|
{
|
|
if (sig[i] == ')' || sig[i] == ';')
|
|
{
|
|
//scan out last arg is any
|
|
char dummy[256];
|
|
memset(dummy, 0, 256);
|
|
|
|
WebCommon::StringCopy(dummy, &sig[argBegin], i - argBegin);
|
|
|
|
if (strlen(dummy))
|
|
{
|
|
strcpy_s(argv[argc], dummy);
|
|
argvv[argc] = argv[argc];
|
|
argc++;
|
|
}
|
|
|
|
break; // done
|
|
}
|
|
|
|
// namespace
|
|
if (sig[i]==':')
|
|
{
|
|
if (nameSpace[0] || fname[0])
|
|
{
|
|
*value = SysAllocString(L"");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (i > 0 && sig[i-1] == ':')
|
|
{
|
|
if (i - 2 > 0)
|
|
WebCommon::StringCopy(nameSpace, sig, i - 1);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// args begin
|
|
if (sig[i] == '(' )
|
|
{
|
|
if (fname[0] || i < 1)
|
|
{
|
|
*value = SysAllocString(L"");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//everything before this is function name, minus nameSpace
|
|
if (nameSpace[0])
|
|
{
|
|
int nlen = strlen(nameSpace);
|
|
WebCommon::StringCopy(fname, &sig[nlen + 2], i - nlen - 2);
|
|
}
|
|
else
|
|
{
|
|
WebCommon::StringCopy(fname, sig, i);
|
|
}
|
|
|
|
WebCommon::StringCopy(argv[0], fname, strlen(fname)+1);
|
|
argvv[0] = argv[0];
|
|
argc++;
|
|
|
|
argBegin = i + 1;
|
|
}
|
|
|
|
// args
|
|
if (sig[i] == ',' )
|
|
{
|
|
if (argBegin >= i || argc == 255)
|
|
{
|
|
*value = SysAllocString(L"");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
WebCommon::StringCopy(argv[argc], &sig[argBegin], i - argBegin);
|
|
argvv[argc] = argv[argc];
|
|
|
|
argc++;
|
|
argBegin = i + 1;
|
|
}
|
|
|
|
}
|
|
|
|
const char* retVal;
|
|
std::string sretVal;
|
|
std::wstring wretVal;
|
|
|
|
if (fname[0])
|
|
{
|
|
// call into the Torque 3D shared library (console system) and get return value
|
|
retVal = torque_callsecurefunction(nameSpace, fname, argc, (const char **) argvv);
|
|
|
|
sretVal= retVal;
|
|
wretVal = WebCommon::StringToWString(sretVal);
|
|
|
|
*value = SysAllocString(wretVal.c_str());
|
|
}
|
|
else
|
|
{
|
|
*value = SysAllocString(L"");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// the sole entry point for Torque 3D console system into our browser plugin (handed over as a function pointer)
|
|
static const char * MyStringCallback(void *obj, int argc, const char* argv[])
|
|
{
|
|
static char ret[4096];
|
|
strcpy_s(ret,CIEWebGameCtrl::sInstance->callFunction(argv[0], argc, argv));
|
|
return ret;
|
|
}
|
|
|
|
// Get the location we're loading the plugin from (http://, file://) including address
|
|
// this is used by the domain locking feature to ensure that your plugin is only
|
|
// being used from your web site
|
|
bool CIEWebGameCtrl::checkDomain()
|
|
{
|
|
HRESULT hrResult = S_FALSE;
|
|
IMoniker* pMoniker = NULL;
|
|
LPOLESTR sDisplayName;
|
|
|
|
hrResult = m_spClientSite->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
|
|
OLEWHICHMK_CONTAINER,
|
|
&pMoniker);
|
|
|
|
if(SUCCEEDED(hrResult))
|
|
{
|
|
hrResult = pMoniker->GetDisplayName(NULL,
|
|
NULL,
|
|
&sDisplayName);
|
|
pMoniker->Release();
|
|
|
|
std::wstring wstr;
|
|
std::string sstr;
|
|
|
|
wstr.assign(sDisplayName);
|
|
sstr = WebCommon::WStringToString(wstr);
|
|
|
|
return WebCommon::CheckDomain(sstr.c_str());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// handles TorqueScript -> Javascript calling including return value
|
|
const char* CIEWebGameCtrl::callFunction(const char* name, LONG numArguments, const char* argv[])
|
|
{
|
|
|
|
//sanity
|
|
if (numArguments > 200)
|
|
return "";
|
|
|
|
// A bunch of COM'esque stuff to which ultimately boils down to finding a Javascript function on the page
|
|
|
|
HRESULT hr;
|
|
|
|
LPOLECONTAINER pContainer;
|
|
IHTMLDocument* pHTML = NULL;
|
|
CComPtr<IDispatch> pScript;
|
|
CComQIPtr<IHTMLWindow2> pWin;
|
|
|
|
|
|
if (!m_spClientSite)
|
|
return "";
|
|
|
|
hr = m_spClientSite->GetContainer(&pContainer);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return "";
|
|
}
|
|
|
|
hr = pContainer->QueryInterface(IID_IHTMLDocument, (void
|
|
**)&pHTML);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pContainer->Release();
|
|
return "";
|
|
}
|
|
|
|
hr = pHTML->get_Script(&pScript);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pContainer->Release();
|
|
pHTML->Release();
|
|
return "";
|
|
}
|
|
|
|
DISPID idMethod = 0;
|
|
std::string smethod = name;
|
|
std::wstring wmethod = WebCommon::StringToWString(smethod);
|
|
OLECHAR FAR* sMethod = (OLECHAR FAR*)wmethod.c_str();
|
|
hr = pScript->GetIDsOfNames(IID_NULL, &sMethod, 1, LOCALE_SYSTEM_DEFAULT,&idMethod);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pContainer->Release();
|
|
pHTML->Release();
|
|
return "";
|
|
}
|
|
|
|
// setup arguments and return value variants
|
|
|
|
VARIANT pVarRet = {0};
|
|
|
|
VariantInit(&pVarRet);
|
|
|
|
if (numArguments <= 1)
|
|
{
|
|
DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};
|
|
hr = pScript->Invoke(idMethod, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
|
|
&dpNoArgs, &pVarRet, NULL, NULL);
|
|
}
|
|
else
|
|
{
|
|
DISPPARAMS params;
|
|
VARIANTARG args[256];
|
|
std::wstring wargs[256];
|
|
|
|
for (LONG i = 0; i < numArguments - 1; i++ )
|
|
{
|
|
VariantInit(&args[i]);
|
|
// Invoke wants these in reverse order
|
|
std::string s = argv[numArguments - i - 1];
|
|
wargs[i] = WebCommon::StringToWString(s);
|
|
args[i].vt = VT_BSTR;
|
|
args[i].bstrVal = SysAllocString(wargs[i].c_str());
|
|
}
|
|
|
|
params.cArgs = numArguments - 1;
|
|
params.rgdispidNamedArgs = NULL;
|
|
params.cNamedArgs = 0;
|
|
params.rgvarg = args;
|
|
|
|
// whew, actually call the Javascript
|
|
hr = pScript->Invoke(idMethod, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
|
|
¶ms, &pVarRet, NULL, NULL);
|
|
|
|
for (LONG i = 0; i < numArguments - 1; i++ )
|
|
{
|
|
SysFreeString(args[i].bstrVal);
|
|
}
|
|
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pContainer->Release();
|
|
pHTML->Release();
|
|
return "";
|
|
}
|
|
|
|
VariantChangeType(&pVarRet, &pVarRet, 0, VT_BSTR);
|
|
|
|
std::wstring wstr;
|
|
std::string sstr;
|
|
static char ret[4096];
|
|
|
|
wstr.assign(pVarRet.bstrVal);
|
|
sstr = WebCommon::WStringToString(wstr);
|
|
strcpy_s(ret, sstr.c_str());
|
|
|
|
pContainer->Release();
|
|
pHTML->Release();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
// handle the actual export (once we're actually all ready to go)
|
|
void CIEWebGameCtrl::internalExportFunction(const JavasScriptExport& jsexport)
|
|
{
|
|
torque_exportstringcallback(MyStringCallback,"JS",jsexport.jsCallback.c_str(),"",jsexport.numArguments,jsexport.numArguments);
|
|
}
|
|
|
|
// plugin.exportFunction("MyJavascriptFunction",3); - export a Javascript function to the Torque 3D console system via its name and argument count
|
|
// If we haven't initialized Torque 3D yet, cache it
|
|
STDMETHODIMP CIEWebGameCtrl::exportFunction(BSTR callback, LONG numArguments)
|
|
{
|
|
JavasScriptExport jsexport;
|
|
std::wstring wstr;
|
|
|
|
wstr.assign(callback);
|
|
jsexport.jsCallback = WebCommon::WStringToString(wstr);
|
|
jsexport.numArguments = numArguments;
|
|
|
|
if (!mInitialized)
|
|
{
|
|
//queue it up
|
|
mJavaScriptExports.push_back(jsexport);
|
|
}
|
|
else
|
|
{
|
|
internalExportFunction(jsexport);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Our web deployment is installer based, no code signing necessary
|
|
STDMETHODIMP CIEWebGameCtrl::GetInterfaceSafetyOptions(REFIID riid,
|
|
DWORD *pdwSupportedOptions,DWORD *pdwEnabledOptions)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CIEWebGameCtrl::SetInterfaceSafetyOptions(REFIID riid,
|
|
DWORD dwOptionSetMask,DWORD dwEnabledOptions)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|