Created
January 2, 2019 07:44
-
-
Save caiorss/32900fc65b3f75a81dc60be1a1660f39 to your computer and use it in GitHub Desktop.
Add scripting capability to your C++ project using Windows Script Host
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <objbase.h> | |
#include <activscp.h> | |
#include <atomic> | |
#include <cassert> | |
#include <cstdio> | |
class ScriptSite : public IActiveScriptSite | |
{ | |
public: | |
HRESULT QueryInterface(REFIID interface_id, void **object) override | |
{ | |
if (object == nullptr) | |
{ | |
return E_POINTER; | |
} | |
if (interface_id == IID_IUnknown || interface_id == IID_IActiveScript) | |
{ | |
*object = this; | |
AddRef(); | |
return S_OK; | |
} | |
return E_NOINTERFACE; | |
} | |
ULONG AddRef() override | |
{ | |
return ++reference_counter; | |
} | |
ULONG Release() override | |
{ | |
if (--reference_counter == 0) | |
{ | |
delete this; | |
return 0; | |
} | |
return reference_counter; | |
} | |
HRESULT STDMETHODCALLTYPE GetLCID(LCID *local_id) override | |
{ | |
(void)local_id; | |
return E_NOTIMPL; | |
} | |
HRESULT STDMETHODCALLTYPE GetItemInfo(LPCOLESTR item_name, | |
DWORD return_mask, | |
IUnknown **item, | |
ITypeInfo **type_info) override | |
{ | |
(void)item_name; | |
(void)return_mask; | |
(void)item; | |
(void)type_info; | |
return TYPE_E_ELEMENTNOTFOUND; | |
} | |
HRESULT STDMETHODCALLTYPE GetDocVersionString(BSTR *document_version) override | |
{ | |
(void)document_version; | |
return S_OK; | |
} | |
HRESULT STDMETHODCALLTYPE OnScriptTerminate(const VARIANT *result, const EXCEPINFO *exception_information) override | |
{ | |
(void)result; | |
(void)exception_information; | |
return S_OK; | |
} | |
HRESULT STDMETHODCALLTYPE OnStateChange(SCRIPTSTATE script_state) override | |
{ | |
(void)script_state; | |
return S_OK; | |
} | |
HRESULT STDMETHODCALLTYPE OnScriptError(IActiveScriptError *script_error) override | |
{ | |
(void)script_error; | |
return S_OK; | |
} | |
HRESULT STDMETHODCALLTYPE OnEnterScript() override | |
{ | |
return S_OK; | |
} | |
HRESULT STDMETHODCALLTYPE OnLeaveScript() override | |
{ | |
return S_OK; | |
} | |
private: | |
virtual ~ScriptSite() = default; | |
std::atomic<DWORD> reference_counter {1}; | |
}; | |
int main() | |
{ | |
HRESULT hr; | |
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); | |
assert(SUCCEEDED(hr)); | |
CLSID script_class_id; | |
hr = CLSIDFromProgID(L"JScript", &script_class_id); | |
assert(SUCCEEDED(hr)); | |
IActiveScript *active_script; | |
hr = CoCreateInstance(script_class_id, nullptr, CLSCTX_SERVER, IID_IActiveScript, reinterpret_cast<void **>(&active_script)); | |
assert(SUCCEEDED(hr)); | |
IActiveScriptSite *active_script_site = new ScriptSite; | |
hr = active_script->SetScriptSite(active_script_site); | |
assert(SUCCEEDED(hr)); | |
active_script_site->Release(); | |
// uuid.lib on MinGW does not export IID_IActiveScriptParse* class IDs | |
#if 1 | |
const GUID IID_IActiveScriptParse64_MingwFix {0xc7ef7658, 0xe1ee, 0x480e, {0x97, 0xea, 0xd5, 0x2c, 0xb4, 0xd7, 0x6d, 0x17}}; | |
#elif 0 | |
const GUID IID_IActiveScriptParse32_MingwFix {0xbb1a2ae2, 0xa4f9, 0x11cf, {0x8f, 0x20, 0x00, 0x80, 0x5f, 0x2c, 0xd0, 0x64}}; | |
#endif | |
IActiveScriptParse *active_script_parse; | |
hr = active_script->QueryInterface(IID_IActiveScriptParse64_MingwFix, reinterpret_cast<void **>(&active_script_parse)); | |
assert(SUCCEEDED(hr)); | |
hr = active_script_parse->InitNew(); | |
assert(SUCCEEDED(hr)); | |
VARIANT result; | |
VariantInit(&result); | |
EXCEPINFO exception_information; | |
hr = active_script_parse->ParseScriptText(L"(function() { (new ActiveXObject('WScript.Shell')).Run('calc.exe'); return 1337; })()", | |
nullptr, | |
nullptr, | |
nullptr, | |
0, | |
0, | |
SCRIPTTEXT_ISEXPRESSION, | |
&result, | |
&exception_information); | |
assert(SUCCEEDED(hr)); | |
assert(V_VT(&result) == VT_I4); | |
std::printf("%ld\n", V_I4(&result)); | |
VariantClear(&result); | |
active_script_parse->Release(); | |
active_script->Release(); | |
CoUninitialize(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment