4
4
5
5
#pragma comment(lib, "Winmm.lib")
6
6
7
- // =======================================================================
8
- // ↓↓↓ 新增的导出函数 ↓↓↓
9
- // =======================================================================
10
- //
11
- // 这个函数是空的,什么也不做。
12
- // 它的唯一目的就是被“导出”,以满足那些要求DLL至少有一个
13
- // 导出函数的注入器。
14
- // extern "C" 确保函数名不会被C++编译器修改。
15
- // __declspec(dllexport) 告诉编译器将此函数放入DLL的导出表中。
16
- //
7
+ // 全局变量,用于线程控制和状态管理
8
+ // volatile 关键字确保多线程访问时的可见性,防止编译器过度优化
9
+ static volatile bool g_runThread = false ; // 控制监控线程运行的标志
10
+ static volatile bool g_isTimerHigh = false ; // 记录当前计时器是否已处于高精度状态
11
+ static HANDLE g_hThread = NULL ; // 监控线程的句柄
12
+
13
+ // 监控线程的主函数
14
+ DWORD WINAPI MonitorThread (LPVOID lpParam)
15
+ {
16
+ // 获取当前进程(即被注入的进程)的ID
17
+ const DWORD currentProcessId = GetCurrentProcessId ();
18
+
19
+ while (g_runThread)
20
+ {
21
+ // 获取当前前台窗口的句柄
22
+ HWND hForegroundWnd = GetForegroundWindow ();
23
+ bool isForeground = false ;
24
+
25
+ if (hForegroundWnd)
26
+ {
27
+ DWORD foregroundProcessId = 0 ;
28
+ GetWindowThreadProcessId (hForegroundWnd, &foregroundProcessId);
29
+ if (foregroundProcessId == currentProcessId)
30
+ {
31
+ isForeground = true ;
32
+ }
33
+ }
34
+
35
+ // 如果当前进程是前台进程...
36
+ if (isForeground)
37
+ {
38
+ // ...并且计时器还不是高精度状态,则设置它
39
+ if (!g_isTimerHigh)
40
+ {
41
+ if (timeBeginPeriod (1 ) == TIMERR_NOERROR)
42
+ {
43
+ g_isTimerHigh = true ;
44
+ }
45
+ }
46
+ }
47
+ // 如果当前进程是后台进程...
48
+ else
49
+ {
50
+ // ...并且计时器当前是高精度状态,则恢复它
51
+ if (g_isTimerHigh)
52
+ {
53
+ if (timeEndPeriod (1 ) == TIMERR_NOERROR)
54
+ {
55
+ g_isTimerHigh = false ;
56
+ }
57
+ }
58
+ }
59
+
60
+ // 等待一小段时间再进行下一次检查,以避免CPU占用过高
61
+ // 250毫秒的检查频率对于前后台切换检测来说绰绰有余
62
+ Sleep (250 );
63
+ }
64
+
65
+ // 线程退出前,最后检查一次,确保恢复计时器精度
66
+ if (g_isTimerHigh)
67
+ {
68
+ timeEndPeriod (1 );
69
+ g_isTimerHigh = false ;
70
+ }
71
+
72
+ return 0 ;
73
+ }
74
+
75
+ // 导出函数,以满足某些注入器的要求
17
76
extern " C" __declspec(dllexport) void PlaceholderExport ()
18
77
{
19
78
// Do nothing.
20
79
}
21
- // =======================================================================
22
80
23
-
24
- // DllMain 是 DLL 的入口点函数
81
+ // DLL入口点
25
82
BOOL APIENTRY DllMain ( HMODULE hModule,
26
83
DWORD ul_reason_for_call,
27
84
LPVOID lpReserved
@@ -30,22 +87,31 @@ BOOL APIENTRY DllMain( HMODULE hModule,
30
87
switch (ul_reason_for_call)
31
88
{
32
89
case DLL_PROCESS_ATTACH:
33
- // DLL被注入到进程时,请求1ms的计时器精度
34
- timeBeginPeriod (1 );
90
+ // 优化:禁止对后续的线程创建/销毁事件调用DllMain,减少开销
91
+ DisableThreadLibraryCalls (hModule);
92
+
93
+ // 设置运行标志并创建监控线程
94
+ g_runThread = true ;
95
+ g_hThread = CreateThread (NULL , 0 , MonitorThread, NULL , 0 , NULL );
35
96
break ;
36
97
37
- case DLL_THREAD_ATTACH:
38
- // 进程创建新线程时执行,我们此处不需要操作
98
+ case DLL_PROCESS_DETACH:
99
+ // 通知监控线程停止
100
+ if (g_hThread)
101
+ {
102
+ g_runThread = false ;
103
+ // 等待线程安全退出(最多等待5秒)
104
+ WaitForSingleObject (g_hThread, 5000 );
105
+ // 关闭线程句柄,释放资源
106
+ CloseHandle (g_hThread);
107
+ g_hThread = NULL ;
108
+ }
39
109
break ;
40
110
111
+ case DLL_THREAD_ATTACH:
41
112
case DLL_THREAD_DETACH:
42
- // 线程退出时执行,我们此处不需要操作
43
- break ;
44
-
45
- case DLL_PROCESS_DETACH:
46
- // DLL从进程卸载时,释放计时器精度请求
47
- timeEndPeriod (1 );
113
+ // 不做任何事
48
114
break ;
49
115
}
50
- return TRUE ; // 操作成功
116
+ return TRUE ;
51
117
}
0 commit comments