天天看點

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,則是CD光牒驅動器;如果是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);

}

繼續閱讀