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