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