mirror of
https://gitea.tendokyu.moe/moegrid/sega-mount.git
synced 2026-09-28 09:48:09 +03:00
121 lines
4.2 KiB
C++
121 lines
4.2 KiB
C++
#define LOG_MODULE "DRIVER"
|
|
#include "driver_service.h"
|
|
#include "resource.h"
|
|
#include "utils/files.h"
|
|
#include "utils/strings.h"
|
|
#include "utils/resource.h"
|
|
#include "utils/log.h"
|
|
|
|
#include <windows.h>
|
|
#include <string>
|
|
|
|
namespace driver {
|
|
|
|
bool ensure_running(std::string *error) {
|
|
SC_HANDLE hScm = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
|
|
if (!hScm) {
|
|
if (error) *error = "OpenSCManager 失败:" + utils::last_error_str();
|
|
return false;
|
|
}
|
|
|
|
// Try to open existing service
|
|
SC_HANDLE hSvc = OpenServiceW(hScm, SERVICE_NAME,SERVICE_ALL_ACCESS);
|
|
|
|
if (!hSvc) {
|
|
DWORD last = GetLastError();
|
|
if (last != ERROR_SERVICE_DOES_NOT_EXIST) {
|
|
if (error) *error = "OpenService 失败:" + utils::last_error_str(last);
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
|
|
// Service does not exist - extract embedded driver to system directory and create service
|
|
// Get system drivers directory (typically C:\Windows\System32\drivers)
|
|
wchar_t sys_dir[MAX_PATH] = {};
|
|
UINT sys_len = GetSystemDirectoryW(sys_dir, MAX_PATH);
|
|
if (sys_len == 0 || sys_len > MAX_PATH) {
|
|
if (error) *error = "GetSystemDirectory 失败:" + utils::last_error_str();
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
std::wstring dst_path = std::wstring(sys_dir) + L"\\drivers\\" + DRIVER_FILENAME;
|
|
|
|
// 从嵌入资源提取驱动文件到系统目录(覆盖已有文件)
|
|
if (!utils::extract_resource_to_file(IDR_DRIVER_SYS, dst_path, error)) {
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
LOG_INFO("驱动已提取到 {}", utils::wstr_to_str(dst_path));
|
|
|
|
hSvc = CreateServiceW(
|
|
hScm, SERVICE_NAME, SERVICE_NAME,
|
|
SERVICE_ALL_ACCESS,
|
|
SERVICE_KERNEL_DRIVER,
|
|
SERVICE_DEMAND_START,
|
|
SERVICE_ERROR_NORMAL,
|
|
dst_path.c_str(),
|
|
nullptr, nullptr, nullptr, nullptr, nullptr
|
|
);
|
|
|
|
if (!hSvc) {
|
|
if (error) *error = "CreateService 失败:" + utils::last_error_str();
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
LOG_INFO("服务已安装:{}", utils::wstr_to_str(dst_path));
|
|
}
|
|
|
|
// Query current state
|
|
SERVICE_STATUS status{};
|
|
if (!QueryServiceStatus(hSvc, &status)) {
|
|
if (error) *error = "QueryServiceStatus 失败:" + utils::last_error_str();
|
|
CloseServiceHandle(hSvc);
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
|
|
if (status.dwCurrentState == SERVICE_RUNNING) {
|
|
CloseServiceHandle(hSvc);
|
|
CloseServiceHandle(hScm);
|
|
return true;
|
|
}
|
|
|
|
// Start the service
|
|
if (!StartServiceW(hSvc, 0, nullptr)) {
|
|
DWORD last = GetLastError();
|
|
if (last != ERROR_SERVICE_ALREADY_RUNNING) {
|
|
if (error) *error = "StartService 失败:" + utils::last_error_str(last);
|
|
CloseServiceHandle(hSvc);
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Wait for it to actually enter RUNNING state
|
|
int tries = 30;
|
|
while (tries-- > 0) {
|
|
if (!QueryServiceStatus(hSvc, &status)) break;
|
|
if (status.dwCurrentState == SERVICE_RUNNING) {
|
|
LOG_INFO("服务已启动");
|
|
CloseServiceHandle(hSvc);
|
|
CloseServiceHandle(hScm);
|
|
return true;
|
|
}
|
|
if (status.dwCurrentState == SERVICE_STOPPED) break;
|
|
Sleep(100);
|
|
}
|
|
|
|
if (status.dwCurrentState != SERVICE_RUNNING) {
|
|
if (error) *error = "服务未能进入运行状态";
|
|
CloseServiceHandle(hSvc);
|
|
CloseServiceHandle(hScm);
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO("服务已启动");
|
|
CloseServiceHandle(hSvc);
|
|
CloseServiceHandle(hScm);
|
|
return true;
|
|
}
|
|
}
|