-
Notifications
You must be signed in to change notification settings - Fork 0
/
openInCurrentScreenService.c
152 lines (125 loc) · 5.61 KB
/
openInCurrentScreenService.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// 创建Windows服务涉及到Windows API的使用,以下是一个基本的步骤:
// 创建一个函数来处理服务的命令。这个函数需要符合LPHANDLER_FUNCTION_EX类型的要求。
// 在main函数中,使用RegisterServiceCtrlHandlerEx函数来注册你的服务处理函数。
// 创建一个无限循环来模拟服务的运行。在这个循环中,你可以检查服务的状态,并根据需要执行相应的操作。
// 使用CreateService函数来创建服务。你需要提供服务的名称,显示名称,访问权限,服务类型,启动类型,错误控制类型,二进制路径名,加载顺序组,标记,依赖关系,服务启动账户和密码。
// 使用StartServiceCtrlDispatcher函数来连接服务控制程序。
#include <windows.h>
#include <stdio.h>
#include "service.h"
SERVICE_STATUS_HANDLE serviceStatusHandler;
SERVICE_STATUS serviceStatus;
HHOOK hHook; // 全局变量,用于在ServiceMain和ServiceHandlerEx之间共享钩子句柄
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
DWORD WINAPI ServiceHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext);
LRESULT CALLBACK HookProc4WhCbt(int nCode, WPARAM wParam, LPARAM lParam);
int main()
{
FILE* fp = fopen(".\\log.txt", "a");
fprintf(fp, "->main()\n");
fclose(fp);
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{ SERVICE_NAME, ServiceMain },
{ NULL, NULL }
};
// 启动服务的控制分发器,连接服务控制程序
if (!StartServiceCtrlDispatcher(ServiceTable))
{
return 1;
}
return 0;
}
// 服务的主函数:这是服务的入口点,当服务控制管理器启动服务时,会调用这个函数。这个函数需要符合LPSERVICE_MAIN_FUNCTION类型的要求。
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
FILE* fp = fopen("log.txt", "a");
fprintf(fp, "->ServiceMain()\n");
//注册服务的控制处理程序
serviceStatusHandler = RegisterServiceCtrlHandlerEx(SERVICE_NAME, ServiceHandlerEx, NULL);
if (serviceStatusHandler == NULL)
{
fprintf(fp, "ERROR: RegisterServiceCtrlHandlerEx failed\n");
return;
}
fprintf(fp, "->RegisterServiceCtrlHandlerEx()\n");
ZeroMemory(&serviceStatus, sizeof(serviceStatus));
serviceStatus.dwServiceType = SERVICE_WIN32;
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus(serviceStatusHandler, &serviceStatus);
fprintf(fp, "->SetServiceStatus()\n");
// 安装钩子
hHook = SetWindowsHookEx(WH_CBT, HookProc4WhCbt, NULL, 0);
if (hHook == NULL)
{
fprintf(fp, "ERROR: SetWindowsHookEx failed\n");
return;
}
fprintf(fp, "->SetWindowsHookEx()\n");
serviceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(serviceStatusHandler, &serviceStatus);
while (1)
{
}
}
// 服务的控制处理程序:用于处理来自服务控制管理器的控制请求,如停止、暂停、继续和关机等。这个函数需要符合LPHANDLER_FUNCTION_EX类型的要求。
DWORD WINAPI ServiceHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(serviceStatusHandler, &serviceStatus);
// 卸载钩子
UnhookWindowsHookEx(hHook);
serviceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(serviceStatusHandler, &serviceStatus);
return NO_ERROR;
}
return ERROR_CALL_NOT_IMPLEMENTED;
}
LRESULT CALLBACK HookProc4WhCbt(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_CREATEWND)
{
/*
* 此时wParam为被创建的窗口的句柄,
* lParam为指向CBT_CREATEWND结构的指针
* CBT_CREATEWND结构定义如下:
* typedef struct tagCBT_CREATEWNDA
* {
* struct tagCREATESTRUCTA *lpcs;
* HWND hwndInsertAfter; //窗口句柄,表示新窗口将被插入到哪个窗口之后。
* } CBT_CREATEWNDA, *LPCBT_CREATEWNDA;
*/
HWND hWnd = (HWND)wParam;
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(hMonitor, &monitorInfo);
// 获取鼠标当前所在屏幕的工作区域
POINT cursorPos;
GetCursorPos(&cursorPos);
HMONITOR hMonitorCursor = MonitorFromPoint(cursorPos, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfoCursor;
monitorInfoCursor.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(hMonitorCursor, &monitorInfoCursor);
// 判断触发事件的窗口是否在当前屏幕
if (hMonitor != hMonitorCursor)
{
// 获取窗口位置
RECT windowRect;
GetWindowRect(hWnd, &windowRect);
// 计算窗口在当前屏幕的位置
int offsetX = monitorInfoCursor.rcWork.left - monitorInfo.rcWork.left;
int offsetY = monitorInfoCursor.rcWork.top - monitorInfo.rcWork.top;
int newLeft = windowRect.left + offsetX;
int newTop = windowRect.top + offsetY;
// 移动窗口到当前屏幕
SetWindowPos(hWnd, NULL, newLeft, newTop, SWP_NOSIZE, SWP_NOSIZE, SWP_NOSIZE | SWP_NOZORDER);
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}