首页
社区
课程
招聘
37
[原创]基于MiniFilter的终端管控实现
发表于: 2025-2-7 17:57 6302

[原创]基于MiniFilter的终端管控实现

2025-2-7 17:57
6302

首先啊,我想着就在应用层去做呗,因为驱动层我确实也没接触过,于是乎我就去一股脑去百度看了看有没有前人的案例参考参考,搜了后发现有修改注册表,组策略,还有windows自带的api(setupapi.h),我寻思注册表和组策略肯定不如api来的灵活,老板要求最好是有类似于白名单,根据策略去选择是否禁用这个u盘或者说别的存储设备,后续要是还需要别的拓展也方便一些,我就踏上了试错路。

大概初步我的设计思路就是,我只要可以获取设备插入的信息,我就直接让该设备弹出,最多就是加个白名单去判断一下。因为是踩坑经历,我这里直接上部分代码了,因为多次修改多次测,备注搞忘掉了,有兴趣的可以把代码扔到ai里让它帮你分析一下就可以啦

特意封装成类了,因为需求稍微变动,因为我这个没有界面嘛,所以要和公司内网的网页端通信,这样老板就可以躺在老板椅上打开网页随意管控咯,采用的udp通信哈,这个通信代码我就不贴了,就是单纯的简单通信,想试试的同学可以类调用Initialize方法就可以,采用的是监视WM_DEVICECHANGE消息。

然后这个只解决了弹出u盘,坑的点就来了,如果是移动硬盘,我自己测试时候成功是能成功,但是要好久才能被弹出,部分电脑还弹不出,估计等弹出来机密文件都被带走咯,然后还有个问题就是,进程被结束了怎么搞,我做成服务,服务也可被结束,于是乎我就开始研究怎么样才能不被坏小子结束我的程序,后来我采用守护线程+dll注入的形式,把我的程序直接注入到explorer.exe资源管理器进程里,然后守护线程酷酷干。

由于之前没有接触过驱动这一块,主要老听别人说驱动很难很麻烦就没接触,现在光脚不怕穿鞋,冲就完了!!!
1.首先先搭个双机调试环境,我这虚拟机win7,win10都有,在虚拟机里记得把驱动签名禁用一下,然后就只需要vs弄一下驱动环境,这个就不多说了,百度都有
2.当有了驱动环境之后呢就创建这个
3.虚拟机里要有个DebugView和驱动的加载工具,方便你调试嘛。ok这样准备工作就完成了

在入口注册了MiniFilter后,我们主要关注点是FLT_REGISTRATION的结构体,具体可以看微软的官方文档https://learn.microsoft.com/zh-cn/windows-hardware/drivers/ddi/fltkernel/ns-fltkernel-_flt_registration

我这里用的是InstanceSetupCallback的回调,因为我想拦截移动存储设备的插入,这个回调处理是比较好的,当卷挂载时会响应这个回调。

这里回调里的思路是,首先第一步先获取卷的属性,然后去查看设备路径是否包含HarddiskVolume或者CdRom,这两个是u盘移动硬盘或者光驱等会显示的路径名,当然本地磁盘也会有这个,所以根据DeviceIoRequest去二次确认是否为移动存储设备,如果你需要根据u盘的序列号去做筛查也可以放在这个回调里去做,不过你需要提前通信得到被允许的序列号,此时就可以判断出这个挂载的移动存储设备是不是需要禁用的,你就可以进行选择附加,再去做后续的禁用读写操作,我这里是直接拒绝挂载的操作,直接删除目标卷的盘符符号,IoDeleteSymbolicLink这个函数就可以做到哈

我这里用的是ObRegisterCallbacks是个笨办法,因为我需要通信,就让应用层顺便把自身pid传上来了

剩下的就比较简单啦,就是纯体力活,就是通信既要和驱动层通信,还要和网页后端通信,调试测试也是比较麻烦,但是这个方法比刚开始的写的强很多!我这里就把最后的驱动代码作为附件上传吧,代码没有封装,写的比较乱哈,有兴趣的可以研究研究哈!

#ifndef USB_EJECT_SERVICE_H
#define USB_EJECT_SERVICE_H
#include <windows.h>
#include <dbt.h>
#include <setupapi.h>
#include <winioctl.h>
#include <cfgmgr32.h>
#include <iostream>
#include <string>
#include <thread>
#include <atomic>
#include <mutex>
#include <memory>
#include <chrono>
#include <fstream>
#include <iomanip>
 
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "cfgmgr32.lib")
 
class DeviceEjector {
public:
    DeviceEjector() : stopEjectThread(false), ejectThreadRunning(false), scanDurationMinutes(10) {}
 
    void Shutdown() {
        Log(L"DeviceEjector is shutting down.");
        StopEjectThread(); // 停止 ejection 线程
 
        if (hwnd) {
            UnregisterDeviceNotification(hDevNotify); // 注销设备通知
            DestroyWindow(hwnd); // 销毁窗口
            hwnd = NULL; // 重置窗口句柄
        }
 
        // 确保在这里重置 hwnd
        hwnd = NULL;
 
        PostMessage(hwnd, WM_QUIT, 0, 0); // 退出消息循环
    }
 
    void Initialize() {
        // 如果已经初始化,则返回
        if (hwnd != NULL) {
            Log(L"DeviceEjector is already initialized. Ignoring the request.");
            return;
        }
 
        RegisterWindowClass();
        CreateNotificationWindow();
        RegisterDeviceNotifications();
        EnumerateExistingDevices();
        MessageLoop();
    }
 
private:
    std::atomic<bool> stopEjectThread;
    std::atomic<bool> ejectThreadRunning;
    std::mutex ejectMutex;
    std::thread ejectThread;
    HWND hwnd;
    HDEVNOTIFY hDevNotify;
    const int scanDurationMinutes;
 
    void StartEjectThread() {
        if (!ejectThreadRunning.exchange(true)) {
            Log(L"Starting eject thread.");
            stopEjectThread = false;
            ejectThread = std::thread(&DeviceEjector::EjectRemovableDisksLoop, this);
            ejectThread.detach();
        }
    }
 
    void StopEjectThread() {
        if (ejectThreadRunning.exchange(false)) {
            Log(L"Stopping eject thread.");
            stopEjectThread = true;
 
            if (ejectThread.joinable()) {
                ejectThread.join(); // 等待线程结束
            }
        }
    }
 
    void EnumerateExistingDevices() {
        Log(L"Enumerating existing devices.");
        HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        DWORD error = GetLastError();
        if (hDevInfo == INVALID_HANDLE_VALUE) {
            LogError(L"Failed to get device information set for disks.",error);
            return;
        }
 
        SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
        deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 
        for (int i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++) {
            Log(L"Processing device interface " + std::to_wstring(i));
            DWORD requiredSize = 0;
            if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL)) {
                DWORD error = GetLastError();
                if (error != ERROR_INSUFFICIENT_BUFFER) {
                    LogError(L"Failed to get required buffer size for device interface detail.", error);
                    continue;
                }
            }
 
            std::unique_ptr<BYTE[]> buffer(new BYTE[requiredSize]);
            PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer.get();
            pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 
            if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, pDeviceInterfaceDetailData, requiredSize, NULL, NULL)) {
                LogError(L"Failed to get device interface detail.", GetLastError());
                continue;
            }
 
            std::wstring devicePath = pDeviceInterfaceDetailData->DevicePath;
            WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN];
            SP_DEVINFO_DATA devInfoData;
            devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
            if (!SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData)) {
                LogError(L"Failed to enumerate device info.", GetLastError());
                continue;
            }
 
            if (!SetupDiGetDeviceInstanceId(hDevInfo, &devInfoData, deviceInstanceId, MAX_DEVICE_ID_LEN, NULL)) {
                LogError(L"Failed to get device instance ID.", GetLastError());
                continue;
            }
 
            Log(L"Attempting to safely eject device with instance ID: " + std::wstring(deviceInstanceId));
            SafeEjectDevice(deviceInstanceId, devicePath);
        }
 
        SetupDiDestroyDeviceInfoList(hDevInfo);
    }
 
    void RegisterWindowClass() {
        Log(L"Registering window class.");
        WNDCLASS wc = { 0 };
        wc.lpfnWndProc = [](HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -> LRESULT {
            static DeviceEjector* pEjector = nullptr;
            if (uMsg == WM_CREATE) {
                pEjector = reinterpret_cast<DeviceEjector*>(((LPCREATESTRUCT)lParam)->lpCreateParams);
            }
            else if (uMsg == WM_DEVICECHANGE) {
                if (pEjector) {
                    pEjector->HandleDeviceChange(wParam, lParam);
                }
            }
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        };
        wc.hInstance = GetModuleHandle(NULL);
        wc.lpszClassName = L"USBDetectorClass";
        RegisterClass(&wc);
    }
 
    void CreateNotificationWindow() {
        Log(L"Creating notification window.");
        hwnd = CreateWindow(L"USBDetectorClass", L"USB Detector", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), this);
    }
 
    void RegisterDeviceNotifications() {
        Log(L"Registering device notification.");
        GUID InterfaceClassGuid = GUID_DEVINTERFACE_DISK;
        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = InterfaceClassGuid;
        hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
    }
 
    void MessageLoop() {
        Log(L"Entering message loop.");
        MSG msg;
        while (true) {
            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
                if (msg.message == WM_QUIT) {
                    return;
                }
            }
            // To ensure the message loop remains responsive, add a small sleep.
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
 
    void HandleDeviceChange(WPARAM wParam, LPARAM lParam) {
        if (wParam == DBT_DEVICEARRIVAL) {
            DEV_BROADCAST_HDR* hdr = (DEV_BROADCAST_HDR*)lParam;
            if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
                Log(L"Device arrival detected.");
                std::this_thread::sleep_for(std::chrono::seconds(1)); // Add a delay to allow the device to stabilize
                if (!ejectThreadRunning.load()) {
                    StartEjectThread();
                }
                else {
                    Log(L"Eject thread is already running. Ignoring new device arrival until current scan completes.");
                }
            }
        }
        else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
            DEV_BROADCAST_HDR* hdr = (DEV_BROADCAST_HDR*)lParam;
            if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
                Log(L"Device removal detected.");
                StopEjectThread();
            }
        }
    }
 
    void EjectRemovableDisksLoop() {
        Log(L"Eject removable disks loop started.");
        auto startTime = std::chrono::steady_clock::now();
        while (!stopEjectThread.load()) {
            Log(L"Scanning for removable disks to eject.");
            HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
            DWORD error = GetLastError();
            if (hDevInfo == INVALID_HANDLE_VALUE) {
                LogError(L"Failed to get device information set for disks.", error);
                std::this_thread::sleep_for(std::chrono::seconds(5));
                continue;
            }
 
            SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
            deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 
            for (int i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++) {
                Log(L"Processing device interface " + std::to_wstring(i));
                DWORD requiredSize = 0;
                if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL)) {
                    DWORD error = GetLastError();
                    if (error != ERROR_INSUFFICIENT_BUFFER) {
                        LogError(L"Failed to get required buffer size for device interface detail.", error);
                        continue;
                    }
                }
 
                std::unique_ptr<BYTE[]> buffer(new BYTE[requiredSize]);
                PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer.get();
                pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 
                if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, pDeviceInterfaceDetailData, requiredSize, NULL, NULL)) {
                    LogError(L"Failed to get device interface detail.", GetLastError());
                    continue;
                }
 
                std::wstring devicePath = pDeviceInterfaceDetailData->DevicePath;
                WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN];
                SP_DEVINFO_DATA devInfoData;
                devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                if (!SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData)) {
                    LogError(L"Failed to enumerate device info.", GetLastError());
                    continue;
                }
 
                if (!SetupDiGetDeviceInstanceId(hDevInfo, &devInfoData, deviceInstanceId, MAX_DEVICE_ID_LEN, NULL)) {
                    LogError(L"Failed to get device instance ID.", GetLastError());
                    continue;
                }
 
                Log(L"Attempting to safely eject device with instance ID: " + std::wstring(deviceInstanceId));
                SafeEjectDevice(deviceInstanceId, devicePath);
            }
 
            SetupDiDestroyDeviceInfoList(hDevInfo);
            std::this_thread::sleep_for(std::chrono::seconds(5));
 
            // Check if the scanning duration has exceeded the specified time limit
            auto currentTime = std::chrono::steady_clock::now();
            auto elapsedTime = std::chrono::duration_cast<std::chrono::minutes>(currentTime - startTime);
            if (elapsedTime.count() >= scanDurationMinutes) {
                Log(L"Scan duration exceeded 10 minutes, ending eject loop.");
                break;
            }
        }
        ejectThreadRunning = false;
        Log(L"Eject removable disks loop ended.");
    }
 
    void SafeEjectDevice(const std::wstring& deviceInstanceId, const std::wstring& devicePath) {
        std::lock_guard<std::mutex> lock(ejectMutex);
        Log(L"Ejecting device: " + deviceInstanceId);
 
        DEVINST devInst;
        CONFIGRET cr = CM_Locate_DevNode(&devInst, (DEVINSTID_W)deviceInstanceId.c_str(), CM_LOCATE_DEVNODE_NORMAL);
        if (cr == CR_SUCCESS) {
            cr = CM_Request_Device_Eject(devInst, NULL, NULL, 0, 0);
            if (cr == CR_SUCCESS) {
                Log(L"Device ejected successfully using CM_Request_Device_Eject.");
            }
            else {
                LogError(L"Failed to eject device using CM_Request_Device_Eject.", cr);
                AttemptParentEject(devInst);
            }
        }
        else {
            LogError(L"Failed to locate device node.", cr);
        }
 
        HANDLE hDevice = CreateFile(devicePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        if (hDevice == INVALID_HANDLE_VALUE) {
            LogError(L"Failed to open device.", GetLastError());
        }
        else {
            DWORD bytesReturned;
            if (DeviceIoControl(hDevice, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &bytesReturned, NULL)) {
                Log(L"Device ejected successfully using IOCTL_STORAGE_EJECT_MEDIA.");
            }
            else {
                LogError(L"Failed to eject device using IOCTL_STORAGE_EJECT_MEDIA.", GetLastError());
            }
            CloseHandle(hDevice);
        }
    }
 
    void AttemptParentEject(DEVINST devInst) {
        Log(L"Attempting to eject parent device.");
        DEVINST parentDevInst;
        CONFIGRET cr = CM_Get_Parent(&parentDevInst, devInst, 0);
        if (cr == CR_SUCCESS) {
            cr = CM_Request_Device_Eject(parentDevInst, NULL, NULL, 0, 0);
            if (cr == CR_SUCCESS) {
                Log(L"Parent device ejected successfully.");
            }
            else {
                LogError(L"Failed to eject parent device.", cr);
            }
        }
        else {
            LogError(L"Failed to locate parent device node.", cr);
        }
    }
 
    void LogToFile(const std::wstring& message, WORD type) {
        // 修改路径为 C:\ProgramData\UsbEjectService.log
        std::wstring logPath = L"C:\\ProgramData\\UsbEjectService111.log";
 
        // 确保目录存在
        CreateDirectoryW(L"C:\\ProgramData", NULL);
 
        // 打开日志文件并追加写入
        std::wofstream logFile(logPath, std::ios::app);
        if (!logFile.is_open()) {
            std::wcerr << L"Failed to open log file: " << logPath << L", Error code: " << GetLastError() << std::endl;
            return;
        }
 
        auto now = std::chrono::system_clock::now();
        auto now_c = std::chrono::system_clock::to_time_t(now);
        logFile << L"[" << (type == EVENTLOG_INFORMATION_TYPE ? L"INFO" : L"ERROR") << L"] ["
            << std::put_time(std::localtime(&now_c), L"%Y-%m-%d %H:%M:%S") << L"]: " << message << std::endl;
        logFile.close();
    }
 
    void Log(const std::wstring& message) {
        LogToFile(message, EVENTLOG_INFORMATION_TYPE);
    }
 
    void LogError(const std::wstring& message, DWORD errorCode) {
        std::wstring fullMessage = message;
        if (errorCode != 0) {
            fullMessage += L" Error code: " + std::to_wstring(errorCode);
        }
        LogToFile(fullMessage, EVENTLOG_ERROR_TYPE);
    }
 
};
 
 
#endif // USB_EJECT_SERVICE_H
#ifndef USB_EJECT_SERVICE_H
#define USB_EJECT_SERVICE_H
#include <windows.h>
#include <dbt.h>
#include <setupapi.h>
#include <winioctl.h>
#include <cfgmgr32.h>
#include <iostream>
#include <string>
#include <thread>
#include <atomic>
#include <mutex>
#include <memory>
#include <chrono>
#include <fstream>
#include <iomanip>
 
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "cfgmgr32.lib")
 
class DeviceEjector {
public:
    DeviceEjector() : stopEjectThread(false), ejectThreadRunning(false), scanDurationMinutes(10) {}
 
    void Shutdown() {
        Log(L"DeviceEjector is shutting down.");
        StopEjectThread(); // 停止 ejection 线程
 
        if (hwnd) {
            UnregisterDeviceNotification(hDevNotify); // 注销设备通知
            DestroyWindow(hwnd); // 销毁窗口
            hwnd = NULL; // 重置窗口句柄
        }
 
        // 确保在这里重置 hwnd
        hwnd = NULL;
 
        PostMessage(hwnd, WM_QUIT, 0, 0); // 退出消息循环
    }
 
    void Initialize() {
        // 如果已经初始化,则返回
        if (hwnd != NULL) {
            Log(L"DeviceEjector is already initialized. Ignoring the request.");
            return;
        }
 
        RegisterWindowClass();
        CreateNotificationWindow();
        RegisterDeviceNotifications();
        EnumerateExistingDevices();
        MessageLoop();
    }
 
private:
    std::atomic<bool> stopEjectThread;
    std::atomic<bool> ejectThreadRunning;
    std::mutex ejectMutex;
    std::thread ejectThread;
    HWND hwnd;
    HDEVNOTIFY hDevNotify;
    const int scanDurationMinutes;
 
    void StartEjectThread() {
        if (!ejectThreadRunning.exchange(true)) {
            Log(L"Starting eject thread.");
            stopEjectThread = false;
            ejectThread = std::thread(&DeviceEjector::EjectRemovableDisksLoop, this);
            ejectThread.detach();
        }
    }
 
    void StopEjectThread() {
        if (ejectThreadRunning.exchange(false)) {
            Log(L"Stopping eject thread.");
            stopEjectThread = true;
 
            if (ejectThread.joinable()) {
                ejectThread.join(); // 等待线程结束
            }
        }
    }
 
    void EnumerateExistingDevices() {
        Log(L"Enumerating existing devices.");
        HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        DWORD error = GetLastError();
        if (hDevInfo == INVALID_HANDLE_VALUE) {
            LogError(L"Failed to get device information set for disks.",error);
            return;
        }
 
        SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
        deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 
        for (int i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++) {
            Log(L"Processing device interface " + std::to_wstring(i));
            DWORD requiredSize = 0;
            if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL)) {
                DWORD error = GetLastError();
                if (error != ERROR_INSUFFICIENT_BUFFER) {
                    LogError(L"Failed to get required buffer size for device interface detail.", error);
                    continue;
                }
            }
 
            std::unique_ptr<BYTE[]> buffer(new BYTE[requiredSize]);
            PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer.get();
            pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 
            if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, pDeviceInterfaceDetailData, requiredSize, NULL, NULL)) {
                LogError(L"Failed to get device interface detail.", GetLastError());
                continue;
            }
 
            std::wstring devicePath = pDeviceInterfaceDetailData->DevicePath;
            WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN];
            SP_DEVINFO_DATA devInfoData;
            devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
            if (!SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData)) {
                LogError(L"Failed to enumerate device info.", GetLastError());
                continue;
            }
 
            if (!SetupDiGetDeviceInstanceId(hDevInfo, &devInfoData, deviceInstanceId, MAX_DEVICE_ID_LEN, NULL)) {
                LogError(L"Failed to get device instance ID.", GetLastError());
                continue;
            }
 
            Log(L"Attempting to safely eject device with instance ID: " + std::wstring(deviceInstanceId));
            SafeEjectDevice(deviceInstanceId, devicePath);
        }
 
        SetupDiDestroyDeviceInfoList(hDevInfo);
    }
 
    void RegisterWindowClass() {
        Log(L"Registering window class.");
        WNDCLASS wc = { 0 };
        wc.lpfnWndProc = [](HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -> LRESULT {
            static DeviceEjector* pEjector = nullptr;
            if (uMsg == WM_CREATE) {
                pEjector = reinterpret_cast<DeviceEjector*>(((LPCREATESTRUCT)lParam)->lpCreateParams);
            }
            else if (uMsg == WM_DEVICECHANGE) {
                if (pEjector) {
                    pEjector->HandleDeviceChange(wParam, lParam);
                }
            }
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        };
        wc.hInstance = GetModuleHandle(NULL);
        wc.lpszClassName = L"USBDetectorClass";
        RegisterClass(&wc);
    }
 
    void CreateNotificationWindow() {
        Log(L"Creating notification window.");
        hwnd = CreateWindow(L"USBDetectorClass", L"USB Detector", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), this);
    }
 
    void RegisterDeviceNotifications() {
        Log(L"Registering device notification.");
        GUID InterfaceClassGuid = GUID_DEVINTERFACE_DISK;
        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = InterfaceClassGuid;
        hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
    }
 
    void MessageLoop() {
        Log(L"Entering message loop.");
        MSG msg;
        while (true) {
            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
                if (msg.message == WM_QUIT) {
                    return;
                }
            }
            // To ensure the message loop remains responsive, add a small sleep.
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
 
    void HandleDeviceChange(WPARAM wParam, LPARAM lParam) {
        if (wParam == DBT_DEVICEARRIVAL) {
            DEV_BROADCAST_HDR* hdr = (DEV_BROADCAST_HDR*)lParam;
            if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
                Log(L"Device arrival detected.");
                std::this_thread::sleep_for(std::chrono::seconds(1)); // Add a delay to allow the device to stabilize
                if (!ejectThreadRunning.load()) {
                    StartEjectThread();
                }

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 37
支持
分享
赞赏记录
参与人
雪币
留言
时间
saloyun
感谢你分享这么好的资源!
2025-3-21 17:23
shishichen
你的帖子非常有用,感谢分享!
2025-3-21 06:48
icanoooo
期待更多优质内容的分享,论坛有你更精彩!
2025-3-20 17:34
罗小墨
你的分享对大家帮助很大,非常感谢!
2025-3-20 16:04
大C滑稽
期待更多优质内容的分享,论坛有你更精彩!
2025-3-20 03:51
loopdata
感谢你分享这么好的资源!
2025-3-19 19:08
Swift001
+1
感谢你的贡献,论坛因你而更加精彩!
2025-3-19 11:18
guoxiabin
感谢你的贡献,论坛因你而更加精彩!
2025-3-18 19:53
小调调
你的帖子非常有用,感谢分享!
2025-3-17 15:27
岁月。
你的分享对大家帮助很大,非常感谢!
2025-3-17 14:03
DreamOfJune
为你点赞!
2025-3-17 09:00
mb_shorqiez
期待更多优质内容的分享,论坛有你更精彩!
2025-3-14 15:58
wx_月亮经过
你的分享对大家帮助很大,非常感谢!
2025-3-12 17:30
榆一
你的分享对大家帮助很大,非常感谢!
2025-3-12 14:02
wx_byte
你的帖子非常有用,感谢分享!
2025-3-10 10:28
frankyxu
你的帖子非常有用,感谢分享!
2025-3-10 10:24
btmanbtman
为你点赞!
2025-3-10 10:01
mb_lygdbarj
你的分享对大家帮助很大,非常感谢!
2025-3-7 18:08
mb_dtidoewd
谢谢你的细致分析,受益匪浅!
2025-3-7 17:48
friendkill
感谢你分享这么好的资源!
2025-3-7 16:12
superlover
感谢你的贡献,论坛因你而更加精彩!
2025-3-7 15:48
GloryRef
谢谢你的细致分析,受益匪浅!
2025-3-7 15:15
mb_hxfbgfro
期待更多优质内容的分享,论坛有你更精彩!
2025-3-6 13:56
Kuny
为你点赞!
2025-3-4 10:04
Billraozihan
为你点赞!
2025-2-28 17:07
sandboxie
感谢你分享这么好的资源!
2025-2-27 15:19
mb_qsrraxzt
感谢你分享这么好的资源!
2025-2-27 14:54
dirweb
你的帖子非常有用,感谢分享!
2025-2-14 17:02
zzage
感谢你分享这么好的资源!
2025-2-12 21:58
朱老黑
为你点赞!
2025-2-12 15:27
True丶end
为你点赞!
2025-2-12 14:02
曹操abc
谢谢你的细致分析,受益匪浅!
2025-2-11 17:38
穗之影
你的帖子非常有用,感谢分享!
2025-2-10 17:29
黑的默
感谢你分享这么好的资源!
2025-2-10 16:38
顽劣
非常支持你的观点!
2025-2-8 16:01
disahacker
你的帖子非常有用,感谢分享!
2025-2-8 10:02
huangyalei
感谢你的贡献,论坛因你而更加精彩!
2025-2-7 18:53
最新回复 (41)
雪    币: 3253
活跃值: (4584)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢你的贡献,论坛因你而更加精彩!
2025-2-7 20:09
0
雪    币: 109
活跃值: (455)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢你的贡献,论坛因你而更加精彩!
2025-2-10 16:32
0
雪    币: 779
活跃值: (541)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢你的贡献,论坛因你而更加精彩!
2025-2-11 17:16
0
雪    币: 172
活跃值: (10343)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
5
拥抱cursor可以大大降低试错成本 谢谢分享.
2025-2-11 17:38
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
感谢你的贡献,论坛因你而更加精彩
2025-2-12 00:30
0
雪    币: 1110
活跃值: (1868)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
看看
2025-2-12 14:22
0
雪    币: 7485
活跃值: (3463)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
应用层做过移动存储的管控,效果也还行
2025-2-12 15:07
0
雪    币: 73
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
shuyangzjg 应用层做过移动存储的管控,效果也还行
大佬你的应用层思路是监视消息然后弹出吗?
2025-2-13 08:56
0
雪    币: 161
活跃值: (1107)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢你的贡献,论坛因你而更加精彩!
2025-2-14 13:59
0
雪    币: 13282
活跃值: (4508)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢你的贡献,论坛因你而更加精彩
2025-2-22 22:26
0
雪    币: 13
活跃值: (94)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
感谢你的贡献,论坛因你而更加精彩
2025-2-22 22:39
0
雪    币: 0
活跃值: (315)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
感谢你的贡献,论坛因你而更加精彩
2025-2-24 12:47
0
雪    币: 2504
活跃值: (2350)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
回帖看看
2025-2-24 13:37
0
雪    币: 48
活跃值: (326)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
感谢你的贡献,论坛因你而更加精彩
2025-3-7 14:59
0
雪    币: 1469
活跃值: (1480)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
谢你的贡献,论坛因你而更加精彩
2025-3-7 15:15
0
雪    币: 29
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
谢你的贡献,论坛因你而更加精彩
2025-3-7 16:22
0
雪    币: 12
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
看看
2025-3-7 16:47
0
雪    币: 0
活跃值: (245)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
看看
2025-3-7 20:53
0
雪    币: 57
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
1111111111111
2025-3-10 09:39
0
雪    币: 66
活跃值: (3162)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
看看
2025-3-10 10:40
0
雪    币: 203
活跃值: (318)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
看看
2025-3-10 14:21
0
雪    币: 255
活跃值: (302)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
看看
2025-3-12 13:47
0
雪    币: 226
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
mark
2025-3-12 19:54
0
雪    币: 1365
活跃值: (191)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
mark 
2025-3-12 20:09
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册