Detecting Hardware Insertion and/or Removal

 http://www.codeproject.com/KB/system/HwDetect.aspx

Detecting Hardware Insertion and/or Removal

By Sam NG | 19 Jun 2006
A user-mode application to detect hardware add/remove with WM_DEVICECHANGE and RegisterDeviceNotification()
 

Sample Image - HwDetect.png

Introduction

Hot-pluggable device is now a big threat to IT security. In this article, we will try to develop a user-mode application to detect device change on the system, i.e. plug-in a USB drive, iPod, USB wireless network card, etc. The program can also disable any newly plugged devices. We will get a basic idea on how this works and talk about its limitations at the end of this article.

How to detect hardware change?

Well, in fact, Windows OS will post WM_DEVICECHANGE upon device change. All we need to do is to add a handler to handle this event.

BEGIN_MESSAGE_MAP(CHWDetectDlg, CDialog)
    // ... other handlers
    ON_MESSAGE(WM_DEVICECHANGE, OnMyDeviceChange)
END_MESSAGE_MAP()

LRESULT CHWDetectDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
    // for more information, see MSDN help of WM_DEVICECHANGE
    // this part should not be very difficult to understand
    if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam ) {
        PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
        switch( pHdr->dbch_devicetype ) {
            case DBT_DEVTYP_DEVICEINTERFACE:
                PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
                // do something...
                break;

            case DBT_DEVTYP_HANDLE:
                PDEV_BROADCAST_HANDLE pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
                // do something...
                break;

            case DBT_DEVTYP_OEM:
                PDEV_BROADCAST_OEM pDevOem = (PDEV_BROADCAST_OEM)pHdr;
                // do something...
                break;

            case DBT_DEVTYP_PORT:
                PDEV_BROADCAST_PORT pDevPort = (PDEV_BROADCAST_PORT)pHdr;
                // do something...
                break;

            case DBT_DEVTYP_VOLUME:
                PDEV_BROADCAST_VOLUME pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
                // do something...
                break;
        }
    }
    return 0;
}

However, by default, Windows OS will only post WM_DEVICECHANGE to

  1. All applications with a top-level window, and
  2. Only upon port and volume change.
Well, this is not bad, since at least you will know when an extra "disk" is mounted/unmounted, and you can get the affected drive letter by using the DEV_BROADCAST_VOLUME.dbcv_unitmask. The downside is that you won't know what physical device has actually been plugged into the system.

API: RegisterDeviceNotification()

To get notified on other types of device changes, or to get notified if you are running as a service and don't have a top-level window, you have to call RegisterDeviceNotification() API. For example, to get notified upon interface change, you can do the following.

1.  DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
2.  ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
3.  NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
4.  NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
5.  // assume we want to be notified with USBSTOR
6.  // to get notified with all interface on XP or above
7.  // ORed 3rd param with DEVICE_NOTIFY_ALL_INTERFACE_CLASSES and dbcc_classguid will be ignored
8.  NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USBSTOR;
9.  HDEVNOTIFY hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(),
        amp;NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
10. if( !hDevNotify ) {
11.     // error handling...
12.     return FALSE;
13. }

Pay extra attention to line 8, the NotificationFilter.dbcc_classguid. See Doron Holan's blog

A PnP device is typically associated with two different GUIDs, a device interface GUID and a device class GUID.

A device class GUID defines a broad category of devices. If you open up device manager, the default view is "by type." Each type is a device class, where each class is uniquely ID's by the device class GUID. A device class GUID defines the icon for the class, default security settings, install properties (like a user cannot manually install an instance of this class, it must be enumerated by PNP), and other settings. The device class GUID does not define an I/O interface (see Glossary), rather think of it as a grouping of devices. I think a good clarifying example is the Ports class. Both COM and LPT devices are a part of the Ports class, yet each has its own distinct I/O interface which are not compatible with each other. A device can only belong to one device class. The device class GUID is the GUID you see at the top of an INF file.

A device interface GUID defines a particular I/O interface contract. It is expected that every instanceof the interface GUID will support the same basic set of I/Os. The device interface GUID is what the driver will register and enable/disable based on PnP state. A device can register many device interfaces for itself, it is not limited to one interface GUID. If need be, the device can even register multiple instances of the same GUID (assuming each have their own ReferenceString), although I have never seen a real world need for this. A simple I/O interface contract is the keyboard device interface to the raw input thread. Here is the keyboard device contract that each instance of the keyboard device interface GUID must support.

You can see the current list of device classes and device interface classes at the following registries:

  • \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class
  • \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses

A list of common device interface class GUIDs is given below:

Device Interface NameGUID
USB Raw Device{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Disk Device{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
Network Card{ad498944-762f-11d0-8dcb-00c04fc3358c}
Human Interface Device (HID){4d1e55b2-f16f-11cf-88cb-001111000030}
Palm{784126bf-4190-11d4-b5c2-00c04f687a67}

Decoding DEV_BROADCAST_DEVICEINTERFACE

Let's change our handler code OnMyDeviceChange() as follows:

LRESULT CHWDetectDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
    ....
    ....
    if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
    {
        PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
        switch( pHdr->dbch_devicetype )
        {
            case DBT_DEVTYP_DEVICEINTERFACE:
                PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
                UpdateDevice(pDevInf, wParam);
                break;
    ....
    ....
}

And from MSDN, we know

typedef struct _DEV_BROADCAST_DEVICEINTERFACE {
    DWORD dbcc_size;
    DWORD dbcc_devicetype;
    DWORD dbcc_reserved;
    GUID dbcc_classguid;
    TCHAR dbcc_name[1];
} DEV_BROADCAST_DEVICEINTERFACE *PDEV_BROADCAST_DEVICEINTERFACE;

It seems by using the dbcc_name, we can know what device has been plugged into the system. Sadly, the answer is NO, dbcc_name is for OS internal use and is an identity, it is not human readable. A sample of dbcc_name is as follows:

\\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

  • \\?\USB: USB means this is a USB device class
  • Vid_04e8&Pid_053b: Vid/Pid is VendorID and ProductID (but this is device class specific, USB use Vid/Pid, different device classes use different naming conventions)
  • 002F9A9828E0F06: seems to be a unique ID (not sure about how this got generated)
  • {a5dcbf10-6530-11d2-901f-00c04fb951ed}: the device interface class GUID

Now, by using this decoded information, we can get the device description or device friendly name by two methods:

  1. Read the registry directly: for our example dbcc_name, it will be, \\HKLM\SYSTEM\CurrentControlSet\Enum\USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
  2. Use SetupDiXxx

API: SetupDiXxx()

Windows has a set of API to allow an application to retrieve hardware device information programmatically. For example, we can get the device description or device friendly name with the dbcc_name. The flow of the program is roughly as follows:

  1. Use SetupDiGetClassDevs() to get a handle of device info set HDEVINFO, you can think of the handle as a directory handle.
  2. Use SetupDiEnumDeviceInfo() to enumerate all the device in the info set, you can think of this operation as a directory listing. Upon each iteration, we will get a SP_DEVINFO_DATA, you can think of this handle as the file handle.
  3. During the enumeration, use SetupDiGetDeviceInstanceId() to read the instance ID for each device, you can think of this operation as reading file attribute. The instance ID is in the form of "USB\Vid_04e8&Pid_503b\0002F9A9828E0F06", very similar to the dbcc_name.
  4. If the instance ID match the dbcc_name, we call SetupDiGetDeviceRegistryProperty() to retrieve the description or friendly name

The program is listed as follows:

void CHWDetectDlg::UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam)
{
    // dbcc_name:
    // \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    // convert to
    // USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
    ASSERT(lstrlen(pDevInf->dbcc_name) > 4);
    CString szDevId = pDevInf->dbcc_name+4;
    int idx = szDevId.ReverseFind(_T('#'));
    ASSERT( -1 != idx );
    szDevId.Truncate(idx);
    szDevId.Replace(_T('#'), _T('\\'));
    szDevId.MakeUpper();

    CString szClass;
    idx = szDevId.Find(_T('\\'));
    ASSERT(-1 != idx );
    szClass = szDevId.Left(idx);

    // if we are adding device, we only need present devices
    // otherwise, we need all devices
    DWORD dwFlag = DBT_DEVICEARRIVAL != wParam
        ? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT);
    HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, szClass, NULL, dwFlag);
    if( INVALID_HANDLE_VALUE == hDevInfo )
    {
        AfxMessageBox(CString("SetupDiGetClassDevs(): ")
            + _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
        return;
    }

    SP_DEVINFO_DATA* pspDevInfoData =
        (SP_DEVINFO_DATA*)HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
    pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
    for(int i=0; SetupDiEnumDeviceInfo(hDevInfo,i,pspDevInfoData); i++)
    {
        DWORD DataT ;
        DWORD nSize=0 ;
        TCHAR buf[MAX_PATH];

        if ( !SetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
        {
            AfxMessageBox(CString("SetupDiGetDeviceInstanceId(): ")
                + _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
            break;
        }

        if ( szDevId == buf )
        {
            // device found
            if ( SetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData,
                SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize) ) {
                // do nothing
            } else if ( SetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData,
                SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize) ) {
                // do nothing
            } else {
                lstrcpy(buf, _T("Unknown"));
            }
            // update UI
            // .....
            // .....
            break;
        }
    }

    if ( pspDevInfoData ) HeapFree(GetProcessHeap(), 0, pspDevInfoData);
    SetupDiDestroyDeviceInfoList(hDevInfo);
}

Disable a device

Suppose you have the correct HDEVINFO and SP_DEVINFO_DATA (actually, we save the dbcc_name as the tree node extra data and retrieve that data when we right click on the device icon and then call SetupDiGetClassDevs and SetupDiEnumDevicInfo), the flow to disable a device is as follows:

  1. Setup the SP_PROPCHANGE_PARAMS structure properly
  2. Call SetupDiSetClassInstallParams() and pass-in the SP_PROPCHANGE_PARAMS structure
  3. Call SetupDiCallClassInstaller() with DIF_PROPERTYCHANGE

In fact, the DIF codes are a bit complicated, and you will have to call SetupDiSetClassInstallParams() with different structures for different DIF codes. For more information, see MSDN "Handling DIF Codes".

SP_PROPCHANGE_PARAMS spPropChangeParams ;
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE ;
spPropChangeParams.Scope = DICS_FLAG_GLOBAL ;
spPropChangeParams.HwProfile = 0; // current hardware profile
spPropChangeParams.StateChange = DICS_DISABLE

if( !SetupDiSetClassInstallParams(hDevInfo, &spDevInfoData,
    // note we pass spPropChangeParams as SP_CLASSINSTALL_HEADER
    // but set the size as sizeof(SP_PROPCHANGE_PARAMS)
    (SP_CLASSINSTALL_HEADER*)&spPropChangeParams, sizeof(SP_PROPCHANGE_PARAMS)) )
{
    // handle error
}
else if(!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData))
{
    // handle error
}
else
{
    // ok, show disable success dialog
    // note, after that, the OS will post DBT_DEVICEREMOVECOMPLETE for the disabled device
}

Minor Issue

I experience multiple DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE messages on the same insertion/removal of my USB wireless card.

Limitations

  1. Obviously, the program can only detect device changes when the application is running, e.g. device plugged in before the system power-up, or before the application starts up will not be detected. But this can be solved by saving the current state at a remote computer and then checking the difference during application starts up.
  2. We can disable the device, but that is all we can do. We can't access control the device against the logon user, nor we can provide read only access. IMHO, I think this can only be fixed if we re-implement the whole program as a kernel mode filter driver.

History

  • June 19th, 2006: Initial release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Sam NG



Hong Kong Hong Kong

Member
 

loading...
Rate this:  Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
FAQ FAQ 
 
    Noise level   Layout   Per page    
newNew MessageRefreshFirst PrevNext
QuestionImprovement by log file PinmemberMember 83346572:37 22 Oct '11  
Hello Sam,
 
We have daily used this tool and found it very very acurate. Thank yoiu for that.
Nowadays, plus the GUI, we think you could join it a log file. That means log following data to some text/csv file:
volume id;insert/remove;date;time
 
That could completet this wonderfull tool.
 
In case you no longer support this app, could you indicate how to do that ?
 
Regards
GeneralMy vote of 4 PinmemberAdam Roderick J1:42 1 Dec '10  
good article on hardWARE detection.
GeneralDetection USB device connected/disconnected to the computer. PinmemberLukasz from Cracow3:49 4 Feb '10  
If anybody wants to know how to detect that my USB device is connected or disconnected to the computer,
please set DIGCF_PRESENT flag in SetupDiGetClassDevs function. When USB device is connected SetupDiGetDeviceInstanceId function provides You DeviceInstanceId that describes connected device, otherwise SetupDiGetDeviceInstanceId doesn't do it.
Questionproviding read only access PinmemberAmit Vilas Shinde6:40 18 Dec '09  
Hi Sam,
This is a great article.
 
I am trying to implement similar device control capability. But in addition to enable/disable the devices, we also need to control read/write access to devices for specific users. You already mentioned in your post that this can be done at driver level. Can you please point me in right direction on which filter driver I need to write for implemeting this capability?

Any insights into this would be highly appreciated.

Thanks
Amit
GeneralThis demo program NOT will start under Windows 7 Pinmemberpassionfly17:51 3 Nov '09  
when I click on HWDETECT.exe I get an error box that says "The program can't start because MFC71.DLL is missing from your computer. Try Reinstalling the program to fix this problem".
 
The HWDETECT.exe does not have an installer, it just a stand-alone application so where do I get this file and where do I put it to register the DLL?
GeneralRe: This demo program NOT will start under Windows 7 Pinmemberpassionfly17:54 30 Nov '09  
does anyone check these boards still? lol hello is anyone out there? lol
GeneralLicense Pinmemberwsnyder67:38 23 Sep '09  
Hi there,
 
This is very helpful!
 
What is the software-license for this project?
 
Thanks!
 
--Bill
GeneralRe: License PinmemberSam NG17:11 23 Sep '09  
Open license, use at your own risk, enjoy Smile | :)
GeneralPLZ..!!! help me... urgent Pinmemberfana_rb0:08 11 Sep '09  
hai ...
 
i got a problem here for making a button in that project..
the button here is handle for detecting new hardware.. not like the example.. automatically..
 
i want detect new device by my self.. handle by that button..
 
so any body can help me plz...!! Cry | :(( Cry | :((
QuestionHow do I use Button to activate USB device ? Pinmemberanakecil19:51 1 Sep '09  
i have an idea when read this article, i've tried to run this program with adding button to activate the USB device after removing the device happened. so my goal is i wanna activate the USB device without unplug the device, because generally we have to unplug the device and then plug it when we wanna use the device.
 
in this case i've added a button called "Hardware Detection" from the resouce view file .\HWDetect.rc\Dialog\IDD_HWDETECT_DIALOG. like this;
 
void CHWDetectDlg::OnBnClickedButton1()
{
 
}
 
i'm a newbie with this nature. so please help me... what should i do to use the button to detect the device.
 
any help here greatly appreciated
thanks.
AnswerRe: How do I use Button to activate USB device ? Pinmemberfana_rb0:12 11 Sep '09  
ahahah
 
it looks like we have same problem here...
 
yeah.. can any body help..??
GeneralRe: How do I use Button to activate USB device ? Pinmemberanakecil1:00 11 Sep '09  
Subhanallah. ada juga yang problemnya sama dengan saya? kumaha kang.. damang? aieu abi dulur ti lembur? hhe
QuestionHow do I get the drive letter for a USB drive? Pinmembertommygr17:55 20 Aug '09  
I've been working on this for a week now. This code is great for getting the insert and removal but how do I take this information and find the drive letter. Seem like it should be in the hdr information. Is there another completely unrelated windows api that I should be using to find that info??? Any help here is greatly appreciated.
AnswerRe: How do I get the drive letter for a USB drive? Pinmembertommygr13:30 21 Aug '09  
Well.   I got it to work.   It really isn't as hard as I was making it.
 
Basically, PDEV_BROADCAST_VOLUME -> dbcv_unitmask is the bit mask for the drive letter.   Not sure how I overlooked this before.   Once you know that the code is pretty stright forward.
 

Here are the code changes that I added to the sample source.
 
LRESULT CHWDetectDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
.
.
.
               case DBT_DEVTYP_VOLUME:
                    pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
                    UpdateDriveInfo(pDevVolume, wParam);
                    break;
          }
     }
     return 0;
}
 
char
CHWDetectDlg::DriveLetterFromMask (
     ULONG unit_mask
)     
{  
     char i;  
 
     // check each bit one at a time.
     for (i = 0; i < 26; ++i)  
     {  
          // Check to see if the bit is set
          if (unit_mask & 0x1)  
               break;  
         
          // Shift the bit mast
          unit_mask = unit_mask >> 1;  
     }  
    
     // Return uppercase drive letter.
     return (i + 'A');  
}  
 
void
CHWDetectDlg::UpdateDriveInfo(
      PDEV_BROADCAST_VOLUME pDevVolume,
      WPARAM wParam
)
{
     char drive[] = "x:\\";
 
     // Find drive from mask.
     drive[0] = DriveLetterFromMask( pDevVolume->dbcv_unitmask );
 
     CString szLog;
     m_ctrlEdit.GetWindowText(szLog);
    
     CString szTmp;
     if ( DBT_DEVICEARRIVAL == wParam ) {
          szTmp.Format(_T("Adding Device as drive %s\r\n"), drive);
     } else {
          szTmp.Format(_T("Removing drive %s\r\n"), drive);
     }
 
     szLog.Append(szTmp);
     m_ctrlEdit.SetWindowText(szLog);
}
 

 
Great Project.   Thanks for publishing it!
QuestionAdd an OK button and take audio in from the detected device Pinmemberdarshts@gmail.com10:48 30 Jul '09  
I have a query and I need help to do the same. The program (link below) works fine and detects the hardware now once the USB - HID is detected i need to add an OK button to the dialog box and then take the audio in - if the device detected is a microphone or render audio out if device detected is a speaker.
I am new to this please help.
 
Program:
 
Detecting Hardware Insertion and/or Removal[^]
 
Thanks,
D
Generalif i Disable DiskDrive i Get Error BSOD blueScreen while i reboot the system PinmemberMember 37611482:20 7 Jul '09  
hi,
 
I Enumerate Device And Disable the DiskDrive using the SetupDiCallClassInstaller API.While i restart the PC I get Blue Screen BSOD Error like
 
Error : (STOP: 0x0000007B (0xF8A18524, 0xC0000034, 0x00000000, 0x00000000)
 
Anybody give the help its more important.
 
Regards
Arunkumar
 
VC++ ,COM,MFC
QuestionHow to disable a device that is already plugged in? Pinmembersmousavi3:03 21 Jun '09  
Hi , Thank you for your nice article
 
Suppose we run this program when a USB device (for example a flash disk) is already plugged , and we should disable it.
 
How should we do this?
AnswerRe: How to disable a device that is already plugged in? PinmemberMember 37611482:23 7 Jul '09  
when you start PC,you should moniter the Device insert or removing using above topic API.
 
VC++ ,COM,MFC
QuestionHow i can get the name of new usb detected? Pinmemberghanmi04_053:07 12 Jun '09  
Hi,
How i can get the name of new usb detected? or the zise of it(in octet/ko/mo..)
if i can get the lettre of my usb storage device(h: for exemple), i can before that return the size of my device
with GetDiskFreeSpaceEx...
Thx
GeneralLimitations... PinmemberMember 24060983:28 2 Apr '09  
This is one pretty good program. In fact, I wish I found it sooner, cuz i developed a small app, quite like this. The difference was that i open a autorun.inf handle, and keep it, with non-sharing priviledges. I only release the handle when
 
1 ) The App exits by user request, where I would iterate through my doubly-linked-list, containing the existing handles, and release every one.
2 ) Receive the message WM_DEVICEQUERYREMOVE, go to the list, and release the autorun handle, and remove the notification handle.

Now, regarding with your limitations, and issues :
 
"I experience multiple DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE messages on the same insertion/removal of my USB wireless card."
/** C Snippet */
HANDLE openAutorun( DEV_BROADCAST_HDR* device, HANDLE autorunHandle ) {
char autorunPath[] = "x:\\autorun.inf";
if ( device->dbch_devicetype == DBT_DEVTYP_VOLUME ) { /** is it a volume?! */
autorunPath[ 0 ] = getDriveLetter((DEV_BROADCAST_VOLUME*)device );
autorunHandle = CreateFile( autorunPath, ( GENERIC_READ | GENERIC_WRITE ), 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( autorunHandle == INVALID_HANDLE_VALUE ) {
switch ( GetLastError() ) {
case ERROR_INVALID_DRIVE :
case ERROR_PATH_NOT_FOUND :
case ERROR_FILE_NOT_FOUND :
 
return INVALID_HANDLE_VALUE;
default :
return INVALID_HANDLE_VALUE;
}
}
return autorunHandle;
}
return INVALID_HANDLE_VALUE;
}
--------------------------------------------------
"Obviously, the program can only detect device changes when the application is running, e.g. device plugged in before the system power-up, or before the application starts up will not be detected. But this can be solved by saving the current state at a remote computer and then checking the difference during application starts up."
 
This one i haven't coded, and I have not a compiler/IDE on hand, but lets give it a try ...
Lets assume that we have the drive letter... GetLogicalDrives is probably a good way to start...
We could use GetDriveType() and compare the result to the table that msdn gives us, but I found, that QueryDosDevice() gives us a more straight forward result ( for me anyways..)
 
Lets assume my own pc, as example.
I have one hard-drive.
However, my hard-drive is spli onto 2 volumes, identified as "C:" and "D:".
I have, at the moment, 2 thumb-drives with me.
Using QueryDosDevice() onto "C:", and "D:", gives me "Device\HarddiskVolume1", and "Device\HarddiskVolume2" respectively.
Now, connecting my two Usb thumb drives ( I hope this is the correct name, im not an natural english speaker, as you've must have noticed by now ... ) they are granted the drive identifiers "I:" and "H:".
Running QueryDosDevice() gives me "Device\Harddisk1\DP(1)0-0+x", being that x is an hexadecimal number, that does not identify the thumb drive, by any obvious manner.
HOWEVER, every device queried, seems to return the same "Device\Harddisk1\DP(1)0-0+x" format if it is a USB thumb-drive, and as such, we can *safely*(??) presume that every device that returns this format, is a usb-thumb-drive, then, falls into the catagory of device we want.
Lol i really hope you understand what i tried to say...
 
-------------------------------
"We can disable the device, but that is all we can do. We can't access control the device against the logon user, nor we can provide read only access. IMHO, I think this can only be fixed if we re-implement the whole program as a kernel mode filter driver."
 
Well, We can't provide read only access to drives, CreateFile blocks drives, even if they are opened with FILE_SHARE_READ ... Only with FILE_SHARE_WRITE, does the drive became available for reading( and writting ... ). However, i believe that we can use FindFirstChangeNotification( ), to keep an eye on the files created in the drive.
Even though we'll have much more trouble, and we'll also turn ourself in quite a cpu hoggers, we Can use this functions for our benefit, since we can launch a thread, to check the files written, and if we want, i believe we can even use DeleteFile to transform the drive into a semi-ReadOnly drive.
 
Goodluck to you, and thank you for the code. Smile | :)
GeneralwParam is always 7 - doesn't recognize specific device PinmemberMechi Fendel10:03 25 Mar '09  
Hi!
I read the article and followed all the code.
I used the CLASS_GUID that is in the device.inf file.
Still, wParam is always 7.
 
if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
 
Any help would be appreciated.
Thanks,
Mechi
AnswerRe: wParam is always 7 - doesn't recognize specific device PinmemberVasiliy Zverev5:41 2 Apr '09  
ClassGUID in .inf file is device class GUID. But you should use device interface GUID instead.
You can find a list of possible device interface GUIDs here http://msdn.microsoft.com/en-us/library/bb663138.aspx[^]. However I did not find there network devices GUID for WinXP (fortunately its GUID is in this article).
Also you can call RegisterDeviceNotification() with flag DEVICE_NOTIFY_ALL_INTERFACE_CLASSES. In this case you will get notifications for all devices and will be able to find out proper device interface GUID for your device.
Generalit's a great job! Pinmemberlanmanck18:48 13 Feb '09  
now i konw how to dectect my device .thanx Smile | :)
GeneralIn fact, it's simple to crack it! Pinmembergordenisgk19:11 28 Dec '08  
It's simple to crack it, open the device manager and select the disabled usb device and restart,the usb device can work again!
我也在找这方面的资料,还是谢谢啊!
QuestionHow to enable the device which was disabled by user? PinmemberYounger_XMU4:57 3 Dec '08  
as the title.
I disable some device, how to re-enable the device after that?
And how to re-enable the device by code?
thank you.
 
modified on Wednesday, December 3, 2008 10:09 AM

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web24 | 2.5.111121.1 | Last Updated 19 Jun 2006
Article Copyright 2006 by Sam NG
Everything else Copyright © CodeProject, 1999-2011
Terms of Use

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值