Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to retrieve data on a removable device using a Windows service in C++

I am trying to detect the insertion of removable devices and retrieve the drive letter of said device using an NT service. I have been successful in detecting insertion and removal of devices, but have been unable to setup a DEV_BROADCAST_VOLUME structure which would allow me to get the drive letter, GUID etc... from the volume.

case SERVICE_CONTROL_DEVICEEVENT:{
            switch(evtype){
            case DBT_DEVICEARRIVAL:{
                    DEV_BROADCAST_VOLUME *hdr = (DEV_BROADCAST_VOLUME*) evdata;
                    ofstream log ("C:\\log.txt", ios::app);
                    log << hdr->dbcv_devicetype;
                    log.close();
                }
                break;

The above code snippet compiles and runs correctly, but when I insert a flash drive,hdr->dbcv_devicetype logs as a value of 55555 and DBT_DEVTYP_VOLUME (which is what a USB drive is) is defined as 2 (hdr->dbcv_devicetype should equal DBT_DEVTYP_VOLUME because I inserted a flash drive). For some reason either the DBT_DEVTYP_VOLUME is not initializing correctly, or something else I am doing is wrong. I am using Windows 7 with Visual Studio 2011 C++.

like image 644
user99545 Avatar asked Nov 13 '22 12:11

user99545


1 Answers

Try this:

  PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)evdata;
  if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
   {
    PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;

    if (lpdbv -> dbcv_flags & DBTF_MEDIA)
     {
      StringCchPrintf( szMsg, sizeof(szMsg)/sizeof(szMsg[0]), 
                       TEXT("Drive %c: Media has arrived.\n"), 
                       FirstDriveFromMask(lpdbv ->dbcv_unitmask) );

      MessageBox( hwnd, szMsg, TEXT("WM_DEVICECHANGE"), MB_OK );
     }
   }

   /*------------------------------------------------------------------
      FirstDriveFromMask( unitmask )

      Description
        Finds the first valid drive letter from a mask of drive letters.
        The mask must be in the format bit 0 = A, bit 1 = B, bit 2 = C, 
        and so on. A valid drive letter is defined when the 
        corresponding bit is set to 1.

      Returns the first drive letter that was found.
   --------------------------------------------------------------------*/

   char FirstDriveFromMask( ULONG unitmask )
    {
     char i;

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

     return( i + 'A' );
   }

Code pulled from Detecting Media Insertion or Removal

like image 185
Julien Lebot Avatar answered Nov 16 '22 00:11

Julien Lebot