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 <windows.h>
6 #include "exdll.h"
7
TimerCallback(LPVOID NSISFunctionAddr,DWORD,DWORD)8 static void APIENTRY TimerCallback(LPVOID NSISFunctionAddr, DWORD, DWORD) {
9 g_executeCodeSegment((int)NSISFunctionAddr, nullptr);
10 }
11
PLUGINFUNCTION(CreateTimer)12 PLUGINFUNCTION(CreateTimer) {
13 EXDLL_INIT();
14 extra->RegisterPluginCallback(gHInst, NSISPluginCallback);
15
16 TCHAR* funcAddrStr =
17 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR));
18 popstring(funcAddrStr);
19 // Apparently GetFunctionAddress returnes a 1-indexed offset, but
20 // ExecuteCodeSegment expects a 0-indexed one. Or something.
21 uintptr_t funcAddr = static_cast<uintptr_t>(_ttoi64(funcAddrStr)) - 1;
22 HeapFree(GetProcessHeap(), 0, funcAddrStr);
23
24 TCHAR* intervalStr =
25 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR));
26 popstring(intervalStr);
27 long interval = _ttol(intervalStr);
28 HeapFree(GetProcessHeap(), 0, intervalStr);
29
30 HANDLE timer = CreateWaitableTimer(nullptr, FALSE, nullptr);
31 if (!timer) {
32 return;
33 }
34
35 // The interval we were passed is in milliseconds, so we need to convert it
36 // to the 100-nanosecond units that SetWaitableTimer expects. We also need to
37 // make it negative, because that's what signifies a relative offset from now
38 // instead of an epoch-based time stamp.
39 LARGE_INTEGER dueTime;
40 dueTime.QuadPart = -(interval * 10000);
41
42 SetWaitableTimer(timer, &dueTime, interval, TimerCallback, (void*)funcAddr,
43 FALSE);
44
45 TCHAR timerStr[32] = _T("");
46 _ltot_s((long)timer, timerStr, 10);
47 pushstring(timerStr);
48 }
49
PLUGINFUNCTION(CancelTimer)50 PLUGINFUNCTION(CancelTimer) {
51 TCHAR* timerStr =
52 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR));
53 popstring(timerStr);
54 HANDLE timer = reinterpret_cast<HANDLE>(_ttoi(timerStr));
55 HeapFree(GetProcessHeap(), 0, timerStr);
56
57 CancelWaitableTimer(timer);
58 CloseHandle(timer);
59 }
60