天天看点

USB设备监控深入分析

 当设备被插入/拔出的时候,WINDOWS会向每个窗体发送WM_DEVICECHANGE 消息,当消息的wParam 值等于 DBT_DEVICEARRIVAL 时,表示Media设备被插入并且已经可用;如果wParam值等于DBT_DEVICEREMOVECOMPLETE,表示Media设备已经被移出。

它们的lParam都指向一个 DEV_BROADCAST_HDR结构体,其原形如下:

struct _DEV_BROADCAST_HDR { /* */

DWORD dbch_size;

DWORD dbch_devicetype;

DWORD dbch_reserved;

};

这个结构体仅仅是一个“头”(HDR),其后还有附加数据,dbch_size表示结构体实例的字节数,当其中的dbch_devicetype字段值等于DBT_DEVTYP_VOLUME时,表示当前设备是逻辑驱动器,且lParam实际上指向的应该是DEV_BROADCAST_VOLUME 结构体实例(真佩服这种逻辑),DEV_BROADCAST_VOLUME 结构体原形如下:

struct _DEV_BROADCAST_VOLUME { /* */

DWORD dbcv_size;

DWORD dbcv_devicetype;

DWORD dbcv_reserved;

DWORD dbcv_unitmask;

WORD dbcv_flags;

};

其中dbcv_unitmask 字段表示当前改变的驱动器掩码,第一位表示驱动器号A,第二位表示驱动器号B,第三位表示驱动器号C,以此类推…… dbcv_flags 表示驱动器的类别,如果等于1,则是光盘驱动器;如果是2,则是网络驱动器;如果是硬盘、U盘则都等于0

所以,我只需要在程序中捕捉WM_DEVICECHANGE 消息,然后根据具体情况去处理即可。

下面看我的一段重载WndProc处理WM_DEVICECHANGE的过程。。

void __fastcall TMainForm::WndProc(TMessage &Message)

{

if( wFlag == TRUE)

{

if(Message.Msg == WM_DEVICECHANGE)

{

switch (Message.WParam)

{

case DBT_DEVICEARRIVAL:

{

PDEV_BROADCAST_HDR pstDevHdr = (PDEV_BROADCAST_HDR)Message.LParam;

if(pstDevHdr->dbch_devicetype == DBT_DEVTYP_VOLUME)

{

PDEV_BROADCAST_VOLUME pstDev = (PDEV_BROADCAST_VOLUME)Message.LParam;

if(pstDev->dbcv_flags == 0)

{

mmoMonLog->Lines->Add("USB设备插入");

mmoMonLog->Lines->Add("当前USB盘符为" + AnsiString(ScanUsbDisk())+"盘");

}

}

}

break;

case DBT_DEVICEREMOVECOMPLETE:

{

mmoMonLog->Lines->Add("USB设备移除");

}

break;

default:

break;

}

}

}

TForm::WndProc(Message);

}

继续阅读