用Mistral Large2写了一个驱动程序加载器,代码如下:
#include <windows.h>
#include <iostream>
#include <string>
#include <commdlg.h>
#include <sddl.h>
// 全局变量
// 声明一个 HINSTANCE 类型的变量 hInst,用于存储应用程序的实例句柄
HINSTANCE hInst;
// 声明并初始化一个常量宽字符数组 g_szClassName,用于存储窗口类的名称
const wchar_t g_szClassName[] = L"DriverLoaderWindowClass";
// 声明并初始化一个 std::wstring 类型的变量 driverName,用于存储驱动程序的名称
std::wstring driverName = L"MyDriver";
// 声明一个 std::wstring 类型的变量 driverPath,用于存储驱动程序文件的路径
std::wstring driverPath;
// 声明一个 HWND 类型的变量 hwndFilePathTextBox,用于存储文本框的句柄
HWND hwndFilePathTextBox;
// 声明函数
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void LoadDriver(const std::wstring& driverName, const std::wstring& driverPath);
void UnloadDriver(const std::wstring& driverName);
void OpenFileDialog(HWND hwnd);
void UpdateFilePathTextBox(HWND hwnd, const std::wstring& filePath);
bool IsRunningAsAdmin();
// 添加批注
_Use_decl_annotations_
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (!IsRunningAsAdmin()) {
MessageBox(NULL, L"此应用程序需要管理员权限。", L"错误", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
// 注册窗口类
// 设置窗口类结构体的大小
wc.cbSize = sizeof(WNDCLASSEX);
// 设置窗口类的样式,这里设置为 0,表示没有特殊样式
wc.style = 0;
// 设置窗口过程函数的指针,指向 WndProc 函数
wc.lpfnWndProc = WndProc;
// 设置窗口类的额外内存大小,这里设置为 0,表示没有额外内存
wc.cbClsExtra = 0;
// 设置窗口的额外内存大小,这里设置为 0,表示没有额外内存
wc.cbWndExtra = 0;
// 设置应用程序实例句柄
wc.hInstance = hInstance;
// 设置窗口的图标,使用默认的应用程序图标
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
// 设置窗口的光标,使用默认的箭头光标
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
// 设置窗口的背景画刷,使用系统颜色 COLOR_WINDOW + 1
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
// 设置窗口的菜单名称,这里设置为 NULL,表示没有菜单
wc.lpszMenuName = NULL;
// 设置窗口类的名称,使用全局变量 g_szClassName
wc.lpszClassName = g_szClassName;
// 设置窗口的小图标,使用默认的应用程序图标
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, L"窗口注册失败!", L"错误!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// 创建窗口
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE, // 扩展窗口样式
g_szClassName, // 窗口类名
L"驱动程序加载器", // 窗口标题
WS_OVERLAPPEDWINDOW, // 窗口样式
CW_USEDEFAULT, CW_USEDEFAULT, // 窗口的初始位置
600, 200, // 窗口的宽度和高度
NULL, NULL, // 父窗口句柄和菜单句柄
hInstance, // 应用程序实例句柄
NULL); // 指向窗口创建数据的指针
if (hwnd == NULL) {
MessageBox(NULL, L"窗口创建失败!", L"错误!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 消息循环
while (GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
// 创建加载按钮
// 创建一个按钮控件
HWND hwndLoadButton = CreateWindow(
L"BUTTON", // 窗口类名,指定这是一个按钮控件
L"加载驱动程序", // 窗口标题,即按钮上显示的文本
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // 窗口样式
50, // 按钮的水平位置(相对于父窗口的左上角)
50, // 按钮的垂直位置(相对于父窗口的左上角)
100, // 按钮的宽度
30, // 按钮的高度
hwnd, // 父窗口句柄
(HMENU)1, // 按钮的菜单句柄或子窗口标识符
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), // 应用程序实例句柄
NULL); // 指向窗口创建数据的指针
// 创建卸载按钮
// 创建一个按钮控件
HWND hwndUnloadButton = CreateWindow(
L"BUTTON", // 窗口类名,指定这是一个按钮控件
L"卸载驱动程序", // 窗口标题,即按钮上显示的文本
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // 窗口样式
200, // 按钮的水平位置(相对于父窗口的左上角)
50, // 按钮的垂直位置(相对于父窗口的左上角)
100, // 按钮的宽度
30, // 按钮的高度
hwnd, // 父窗口句柄
(HMENU)2, // 按钮的菜单句柄或子窗口标识符
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), // 应用程序实例句柄
NULL); // 指向窗口创建数据的指针
// 创建选择文件按钮
// 创建一个按钮控件
HWND hwndSelectFileButton = CreateWindow(
L"BUTTON", // 窗口类名,指定这是一个按钮控件
L"选择驱动程序", // 窗口标题,即按钮上显示的文本
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // 窗口样式
50, // 按钮的水平位置(相对于父窗口的左上角)
100, // 按钮的垂直位置(相对于父窗口的左上角)
100, // 按钮的宽度
30, // 按钮的高度
hwnd, // 父窗口句柄
(HMENU)3, // 按钮的菜单句柄或子窗口标识符
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), // 应用程序实例句柄
NULL); // 指向窗口创建数据的指针
// 创建文本框
hwndFilePathTextBox = CreateWindow(
L"EDIT", // 窗口类名
L"", // 窗口标题(文本框的初始文本)
WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY | ES_AUTOHSCROLL, // 窗口样式
200, // 窗口的水平位置
100, // 窗口的垂直位置
350, // 窗口的宽度
30, // 窗口的高度
hwnd, // 父窗口句柄
(HMENU)4, // 窗口的菜单句柄或子窗口标识符
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), // 应用程序实例句柄
NULL); // 指向窗口创建数据的指针
break;
}
case WM_COMMAND: {
// 处理 WM_COMMAND 消息,通常由菜单、按钮等控件触发
if (LOWORD(wParam) == 1) {
// 如果按钮标识符为 1,则加载驱动程序
LoadDriver(driverName, driverPath);
}
else if (LOWORD(wParam) == 2) {
// 如果按钮标识符为 2,则卸载驱动程序
UnloadDriver(driverName);
}
else if (LOWORD(wParam) == 3) {
// 如果按钮标识符为 3,则打开文件选择对话框
OpenFileDialog(hwnd);
}
break;
}
case WM_CLOSE: {
// 处理 WM_CLOSE 消息,通常由用户关闭窗口时触发
DestroyWindow(hwnd); // 销毁窗口
break;
}
case WM_DESTROY: {
// 处理 WM_DESTROY 消息,通常由窗口被销毁时触发
PostQuitMessage(0); // 发送退出消息,结束消息循环
break;
}
default:
// 处理其他消息,调用默认的窗口过程函数
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
void LoadDriver(const std::wstring& driverName, const std::wstring& driverPath) {
// 打开服务控制管理器
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (!hSCManager) {
// 如果打开服务控制管理器失败,显示错误消息并返回
MessageBox(NULL, L"OpenSCManager 失败", L"错误", MB_OK | MB_ICONERROR);
return;
}
// 创建服务
SC_HANDLE hService = CreateService(
hSCManager, // 服务控制管理器句柄
driverName.c_str(), // 服务名称
driverName.c_str(), // 显示名称
SERVICE_START | DELETE | SERVICE_STOP, // 服务访问权限
SERVICE_KERNEL_DRIVER, // 服务类型
SERVICE_DEMAND_START, // 启动类型
SERVICE_ERROR_IGNORE, // 错误控制
driverPath.c_str(), // 服务的二进制文件路径
NULL, NULL, NULL, NULL, NULL); // 其他参数
if (!hService) {
// 如果创建服务失败,显示错误消息并关闭服务控制管理器句柄
MessageBox(NULL, L"CreateService 失败", L"错误", MB_OK | MB_ICONERROR);
CloseServiceHandle(hSCManager);
return;
}
// 启动服务
if (!StartService(hService, 0, NULL)) {
// 如果启动服务失败,显示错误消息并删除服务
MessageBox(NULL, L"StartService 失败", L"错误", MB_OK | MB_ICONERROR);
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return;
}
// 如果服务启动成功,显示成功消息
MessageBox(NULL, L"驱动程序加载成功", L"成功", MB_OK | MB_ICONINFORMATION);
// 关闭服务句柄和服务控制管理器句柄
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
}
void UnloadDriver(const std::wstring& driverName) {
// 打开服务控制管理器
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!hSCManager) {
// 如果打开服务控制管理器失败,显示错误消息并返回
MessageBox(NULL, L"OpenSCManager 失败", L"错误", MB_OK | MB_ICONERROR);
return;
}
// 打开指定的服务
SC_HANDLE hService = OpenService(hSCManager, driverName.c_str(), SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS);
if (!hService) {
// 如果打开服务失败,显示错误消息并关闭服务控制管理器句柄
MessageBox(NULL, L"OpenService 失败", L"错误", MB_OK | MB_ICONERROR);
CloseServiceHandle(hSCManager);
return;
}
// 定义一个 SERVICE_STATUS 结构体,用于存储服务状态
SERVICE_STATUS serviceStatus;
// 停止服务
ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus);
// 删除服务
if (!DeleteService(hService)) {
// 如果删除服务失败,显示错误消息并关闭服务句柄和服务控制管理器句柄
MessageBox(NULL, L"DeleteService 失败", L"错误", MB_OK | MB_ICONERROR);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return;
}
// 如果服务删除成功,显示成功消息
MessageBox(NULL, L"驱动程序卸载成功", L"成功", MB_OK | MB_ICONINFORMATION);
// 关闭服务句柄和服务控制管理器句柄
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
}
void OpenFileDialog(HWND hwnd) {
// 定义一个 OPENFILENAME 结构体,用于配置文件打开对话框
OPENFILENAME ofn;
// 定义一个字符数组,用于存储选择的文件路径
wchar_t szFile[MAX_PATH] = { 0 };
// 初始化 OPENFILENAME 结构体,将所有字段设置为零
ZeroMemory(&ofn, sizeof(ofn));
// 设置 OPENFILENAME 结构体的大小
ofn.lStructSize = sizeof(ofn);
// 设置文件打开对话框的拥有者窗口句柄
ofn.hwndOwner = hwnd;
// 设置用于存储文件路径的缓冲区
ofn.lpstrFile = szFile;
// 设置缓冲区的大小
ofn.nMaxFile = sizeof(szFile);
// 设置文件过滤器,用于在对话框中显示文件类型选项
ofn.lpstrFilter = L"驱动程序文件 (*.sys)\0*.sys\0所有文件 (*.*)\0*.*\0";
// 设置默认的文件过滤器索引
ofn.nFilterIndex = 1;
// 设置用于存储文件标题的缓冲区(这里设置为 NULL,表示不使用)
ofn.lpstrFileTitle = NULL;
// 设置文件标题缓冲区的大小(这里设置为 0,表示不使用)
ofn.nMaxFileTitle = 0;
// 设置初始目录(这里设置为 NULL,表示使用默认目录)
ofn.lpstrInitialDir = NULL;
// 设置文件打开对话框的标志,要求文件和路径必须存在
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// 显示文件打开对话框,并检查用户是否选择了文件
if (GetOpenFileName(&ofn) == TRUE) {
// 如果用户选择了文件,将文件路径存储到 driverPath 变量中
driverPath = szFile;
// 更新文本框,显示选择的文件路径
UpdateFilePathTextBox(hwnd, driverPath);
// 显示成功消息框,提示文件选择成功
MessageBox(hwnd, L"文件选择成功", L"成功", MB_OK | MB_ICONINFORMATION);
}
}
void UpdateFilePathTextBox(HWND hwnd, const std::wstring& filePath) {
SetWindowText(hwndFilePathTextBox, filePath.c_str());
}
bool IsRunningAsAdmin() {
// 定义一个 BOOL 类型的变量 fIsRunAsAdmin,用于存储是否以管理员身份运行的结果
BOOL fIsRunAsAdmin = FALSE;
// 定义一个 PSID 类型的变量 pAdministratorsGroup,用于存储管理员组的 SID
PSID pAdministratorsGroup = NULL;
// 定义一个 SID_IDENTIFIER_AUTHORITY 结构体,用于表示安全标识符的权限
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
// 分配并初始化管理员组的 SID
if (!AllocateAndInitializeSid(
&NtAuthority, // 安全标识符的权限
2, // 子权限的数量
SECURITY_BUILTIN_DOMAIN_RID, // 第一个子权限
DOMAIN_ALIAS_RID_ADMINS, // 第二个子权限
0, 0, 0, 0, 0, 0, // 其他子权限(这里设置为 0)
&pAdministratorsGroup)) { // 输出参数,用于存储分配的 SID
// 如果分配并初始化 SID 失败,跳转到 Cleanup 标签
goto Cleanup;
}
// 检查当前进程的访问令牌是否属于管理员组
if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin)) {
// 如果检查令牌成员关系失败,跳转到 Cleanup 标签
goto Cleanup;
}
Cleanup:
// 如果 pAdministratorsGroup 不为 NULL,释放分配的 SID
if (pAdministratorsGroup) {
FreeSid(pAdministratorsGroup);
}
// 返回是否以管理员身份运行的结果
return (fIsRunAsAdmin == TRUE);
}