(转) 两种自动检测USB设备的添加和移除的方法

原创地址:http://blog.csdn.net/jingzhongrong/archive/2007/01/02/1472440.aspx

 

今天看到一篇文章里面说到的检测U盘插入的方法

文章中使用的是用循环不停检测系统盘符的变化,然后根据盘符对应的类型来判      断。                                                       

下面是大概的方法

 

//检测是否为可移动磁盘 

int CheckDisk(char * disk) 



  
if(GetDriveType(disk)==DRIVE_REMOVABLE)return 0


   
return -1


}


int
 dectect() 

{     
char buf[10
]; 

       DWORD lod
=
GetLogicalDrives();  

       
if (lod!=0


        { 

        
for (int i=0;i<26;i++


               { 

                      
if ((lod & 1)==1


                     { 

 

                           sprintf(buf,
"%c",'A'+
i);  

                            strcat(buf,
":/"
); 

                             
if(!
CheckDisk(buf))  

                            {   

                                    
if(GetVolumeInformation(buf,0,0,0,0,0,0,0
)) 

                                    { 

                                         
//检测到U盘并且驱动器已准备就绪 


 


                                    }    

                            } 

                      }  

                     lod
=lod>>1 ;  

              } 

 } 

        
return 0


 } 

//然后使用

while(1
)

{

    dected();

  
//此处可以添加Sleep函数停止一段时间,以免过高占用CPU


}

 

下面是我的实现,不使用循环,使用C++Builder完成,

原理是当U盘插入或移除的时候

Windows会生成一条信息WM_DEVICECHANGE

处理此消息便可

使用VC的可以定义一个WindowProc的回调函数,其中的实现与下面的WndProc类似

 

void __fastcall TForm1::WndProc(TMessage & Message)
{
 
if
(started)
 {
  
if(Message.Msg ==
 WM_DEVICECHANGE)
  {
   
switch
(Message.WParam)
   {
    
case 0x8000:          //DBT_DEVICEARRIVAL

    {
     ShowMessage(
"U盘插入"
);
     PDEV_BROADCAST_VOLUME dbvDev 
=
 (PDEV_BROADCAST_VOLUME)Message.LParam;
      DWORD vn 
= dbvDev->
dbcv_unitmask;
      
//this->HasAutoRunInFileName(vn);

      break ;
    }
    
case DBT_DEVICEREMOVECOMPLETE:          //0x8004

     ShowMessage("U盘拔出" );
     
break
;
   }
  }
 }
 TForm::WndProc(Message);    //处理其他消息
}

 

 上面代码其实并没有对是否为USB设备进行判断,在MSDN中提到此消息在添加网络驱动器时也会产生

要判断USB设备,可以这样

if (dbvDev->dbcv_flags & DBTF_MEDIA)

 

下面是MSDN中PDEV_BROADCAST_VOLUME的参数dbcv_flags 描述:

dbcv_flags
This parameter can be one of the following values.
ValueMeaning
DBTF_MEDIAChange affects media in drive. If not set, change affects physical device or drive.
DBTF_NETIndicated logical volume is a network volume.

 

 原理已经说完,发挥一下想象,可以写出一个简单的判断U盘中是否有病毒的小程序,

现在很多使用U盘传播的病毒,都会在U盘下生成带有“autorun”的文件,通过判断是否有autorun文件进行判断,提示用户注意。

程序在Windows2003+Borland Developer C++Builder 2006中调试通过

//$$---- Form CPP ----

#include <vcl.h>
#pragma hdrstop

#include 
"Unit1.h"
#include 
<windows.h>
#include 
<dir.h>
#include 
<io.h>
#include 
<fcntl.h>
#include 
<Dbt.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 
* Form1;
//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent*  Owner)
 : TForm(Owner)
{
 started 
= false
;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::WndProc(TMessage & Message)
{
 
if
(started)
 {
  
if(Message.Msg ==
 WM_DEVICECHANGE)
  {
   
switch
(Message.WParam)
   {
    
case 0x8000:          //DBT_DEVICEARRIVAL

    {
     ShowMessage(
"U盘插入"
);
     
//PDEV_BROADCAST_HDR dbhDev = (PDEV_BROADCAST_HDR)Message.LParam;

     PDEV_BROADCAST_VOLUME dbvDev =  (PDEV_BROADCAST_VOLUME)Message.LParam;
     
//
if(dbhDev.dbch_devicetype == DBT_DEVTYP_VOLUME)
     
//{

      DWORD vn = dbvDev-> dbcv_unitmask;
      
this->
HasAutoRunInFileName(vn);
     
//}

     break ;
        }
    
case DBT_DEVICEREMOVECOMPLETE:          //0x8004

     ShowMessage("U盘拔出" );
     
break
;
   }
  }
 }
 TForm::WndProc(Message);
}
//---------------------------------------------------------------------------

bool __fastcall TForm1::HasAutoRunInFileName(unsigned long  area)
{
 
char s =
 FirstDriveFromMask(area);
 
struct
 ffblk ffblk;
 
int
 done;
 AnsiString path 
=
 AnsiString(s);
 path 
+= ":/"
;
 path 
+= "*autorun*"
;
 done 
= findfirst(path.c_str(),&ffblk,0
);
 Memo1
->
Clear();
 
while (!
done)
 {
  Memo1
->Lines->
Add(AnsiString(ffblk.ff_name));
  done 
= findnext(&
ffblk);
 }
 
if(Memo1->Lines->Count != 0
)
 {
  MessageBox(Handle,
"注意,U盘中含有包含"autorun"字样的文件,可能是病毒请不要直接双击打开该U盘","USBAutoRunScan",MB_OK |
 MB_ICONHAND);
  
return true
;
 }
 
return false
;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject * Sender)
{
 started 
= true;  //开始监视

 Button2->Enabled = true ;
 Button1
->Enabled = false
;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject * Sender)
{
 started 
= false;  //停止监视

 Button2->Enabled = false ;
 Button1
->Enabled = true
;
}
//---------------------------------------------------------------------------

char  __fastcall TForm1::FirstDriveFromMask(ULONG unitmask)
{
   
char
 i;

   
for (i = 0; i < 26++
i)
   {
      
if (unitmask & 0x1
)
         
break
;
      unitmask 
= unitmask >> 1
;
   }

  
return (i + 'A'
);
}
//---------------------------------------------------------------------------


 

 

//$$---- Form HDR ----

#ifndef Unit1H
#define Unit1H

//---------------------------------------------------------------------------
#include <Classes.hpp>
#include 
<Controls.hpp>
#include 
<StdCtrls.hpp>
#include 
<Forms.hpp>
#include 
<windows.h>
#include 
<ExtCtrls.hpp>
#include 
<XPMan.hpp>
//---------------------------------------------------------------------------
class TForm1 : public  TForm
{
__published: 
// IDE-managed Components

 TMemo * Memo1;
 TButton 
*
Button1;
 TButton 
*
Button2;
 TXPManifest 
*
XPManifest1;
 TTrayIcon 
*
TrayIcon1;
 
void __fastcall Button1Click(TObject *
Sender);
 
void __fastcall Button2Click(TObject *
Sender);
private// User declarations

 bool __fastcall HasAutoRunInFileName(unsigned long  area);
 
char
 __fastcall FirstDriveFromMask(ULONG unitmask);
 
bool
 started;
public:  // User declarations

 __fastcall TForm1(TComponent*  Owner);
 
void __fastcall WndProc(TMessage &
Message);
};
//---------------------------------------------------------------------------

extern PACKAGE TForm1 * Form1;
//---------------------------------------------------------------------------

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值