1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0.If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5 #include "WebBrowser.h"
6 #include "exdll.h"
7
8 extern WebBrowser* gBrowser;
9 void Init(HWND hWndParent, int string_size, TCHAR* variables,
10 stack_t** stacktop, extra_parameters* extra);
11
CustomFunctionWrapper(void * NSISFunctionAddr,VARIANT jsArg,VARIANT * retVal)12 static void CustomFunctionWrapper(void* NSISFunctionAddr, VARIANT jsArg,
13 VARIANT* retVal) {
14 // Marshal the argument passed to the JavaScript function onto the NSIS stack.
15 switch (jsArg.vt) {
16 case VT_BSTR:
17 pushstring(jsArg.bstrVal);
18 break;
19 case VT_I4: {
20 TCHAR intArgStr[32] = _T("");
21 _itot_s(jsArg.intVal, intArgStr, 10);
22 pushstring(intArgStr);
23 break;
24 }
25 case VT_BOOL:
26 pushstring(jsArg.boolVal == VARIANT_TRUE ? _T("1") : _T("0"));
27 break;
28 default:
29 // No other argument types supported.
30 pushstring(_T(""));
31 break;
32 }
33
34 // Call the NSIS function.
35 int rv = g_executeCodeSegment((int)NSISFunctionAddr, nullptr);
36
37 // Retrieve the return value from the NSIS stack.
38 TCHAR* nsisRetval =
39 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR));
40 popstring(nsisRetval);
41
42 // Pass the return value back to JavaScript, if it asked for one.
43 if (retVal) {
44 VariantInit(retVal);
45 retVal->vt = VT_BSTR;
46 retVal->bstrVal = SysAllocString(nsisRetval);
47 }
48
49 HeapFree(GetProcessHeap(), 0, nsisRetval);
50 }
51
PLUGINFUNCTION(RegisterCustomFunction)52 PLUGINFUNCTION(RegisterCustomFunction) {
53 if (!gBrowser) {
54 Init(hWndParent, string_size, variables, stacktop, extra);
55 }
56
57 TCHAR* funcAddrStr =
58 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR));
59 popstring(funcAddrStr);
60
61 TCHAR* funcName =
62 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR));
63 popstring(funcName);
64
65 if (gBrowser && funcAddrStr && funcName) {
66 // Apparently GetFunctionAddress returnes a 1-indexed offset, but
67 // ExecuteCodeSegment expects a 0-indexed one. Or something.
68 uintptr_t funcAddr = static_cast<uintptr_t>(_ttoi64(funcAddrStr)) - 1;
69 gBrowser->AddCustomFunction(funcName, CustomFunctionWrapper,
70 (void*)funcAddr);
71 }
72
73 HeapFree(GetProcessHeap(), 0, funcName);
74 HeapFree(GetProcessHeap(), 0, funcAddrStr);
75 }
76