zoukankan      html  css  js  c++  java
  • How to match between physical usb device and its drive letter?

    struct tagDrives
    {
      WCHAR letter;
      WCHAR volume[ BUFFER_SIZE ];
    } g_drives[ 26 ];
    
    //
    WCHAR GetUSBDrive( )
    {
      LPTSTR lpDevID;
      WCHAR cDrive;
      DWORD dwSize = BUFFER_SIZE;
    
      // Get all removable disks on user laptop.
      if ( !GetAllRemovableDisks( ) )
      {
        WRITELOG( "Error - GetAllRemovableDisks failed
    " );
        return 0;
      }
    
      // Alocate memory to device ID
      lpDevID = (LPTSTR) AllocMem( BUFFER_SIZE );
    
      // Get device ID corresponding to USBFM from registry.
      if ( !GetRegValue( lpDevID, DEVICE_ID, dwSize ) )
      {
        WRITELOG( "Error - Registry - USBFMDevID failed
    " );
        FreeMem( lpDevID );
        return 0;
      }
    
      // Get drive corresponding to the registry entry.
      cDrive = GetSpecificDrive( lpDevID );
    
      FreeMem( lpDevID );
    
      // return the drive letter.
      return cDrive;
    }
    
    /******************************************************************************
     * GetAllRemovableDisks - This function retrieves volume information for all 
     removable disks
     *
     * In:        None
     *
     * Out:  TRUE        - Success
     *                FALSE        - Failure
     *
     *******************************************************************************/
    
    BOOL GetAllRemovableDisks( )
    {
      WCHAR caDrive[ 4 ];
      WCHAR volume[ BUFFER_SIZE ];
      int nLoopIndex;
      DWORD dwDriveMask;
    
      caDrive[ 0 ] = 'A';
      caDrive[ 1 ] = ':';
      caDrive[ 2 ] = '\';
      caDrive[ 3 ] = 0;
    
      g_count = 0;
    
      // Get all drives in the system.
      dwDriveMask = GetLogicalDrives( );
    
      if ( dwDriveMask == 0 )
      {
        WRITELOG( "Error - GetLogicalDrives failed
    " );
        return FALSE;
      }
    
      // Loop for all drives (MAX_DRIVES = 26)
    
      for ( nLoopIndex = 0; nLoopIndex < MAX_DRIVES; nLoopIndex++ )
      {
        // if a drive is present, 
        if ( dwDriveMask & 1 )
        {
          caDrive[ 0 ] = 'A' + nLoopIndex;
    
          // If a drive is removable 
          if ( GetDriveType( caDrive ) == DRIVE_REMOVABLE )
          {
            //Get its volume info and store it in the global variable.
            if ( GetVolumeNameForVolumeMountPoint( caDrive, volume, BUFFER_SIZE ) )
            {
              g_drives[ g_count ].letter = caDrive[ 0 ];
              wcscpy( g_drives[ g_count ].volume, volume );
              g_count++;
            }
    
          }
        }
        dwDriveMask >>= 1;
      }
    
      // success if atleast one removable drive is found.
      if ( g_count == 0 )
      {
        return FALSE;
      }
      else
      {
        return TRUE;
      }
    }
    
    /******************************************************************************
     * GetSpecificDrive - This function returns the drive corresponding to the 
     given device ID
     *
     * In        :        lpDevID        - Device ID
     *
     * Return:        Drive letter corresponding to the given device ID.
     *
     *******************************************************************************/
    
    WCHAR GetSpecificDrive( LPTSTR lpDevID )
    {
      HDEVINFO hDevInfo;
      GUID guid;
      BYTE buffer[ BUFFER_SIZE ];
      DWORD dwRequiredSize;
      WCHAR buf[ BUFFER_SIZE ];
      DEVINST devInstParent;
      DWORD dwIndex;
      WCHAR volume[ BUFFER_SIZE ];
      int nLength, nLoopIndex;
    
      SP_DEVICE_INTERFACE_DATA devInterfaceData;
      SP_DEVINFO_DATA devInfoData;
      PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
    
      if ( !lpDevID )
      {
        return 0;
      }
    
      // GUID_DEVINTERFACE_VOLUME is interface Guid for Volume class devices.
      guid = GUID_DEVINTERFACE_VOLUME;
    
      // Get device Information handle for Volume interface
      hDevInfo = SetupDiGetClassDevs( &guid, NULL, NULL,
        DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
    
      if ( hDevInfo == INVALID_HANDLE_VALUE )
      {
        WRITELOG( "Error - SetupDiGetClassDevs failed
    " );
        return 0;
      }
    
      // Loop until device interfaces are found.
      for ( dwIndex = 0;; dwIndex++ )
      {
        ZeroMemory( &devInterfaceData, sizeof( devInterfaceData ) );
        devInterfaceData.cbSize = sizeof( devInterfaceData );
    
        // Get device Interface data.
    
        if ( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, &guid, dwIndex,
          &devInterfaceData ) )
        {
          break;
        }
    
        ZeroMemory( &devInfoData, sizeof( devInfoData ) );
        devInfoData.cbSize = sizeof( devInfoData );
    
        pDevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) buffer;
        pDevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    
        // Get device interface detail data to get 
        //        Device Instance from SP_DEVINFO_DATA and
        //  Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
    
        SetupDiGetDeviceInterfaceDetail( hDevInfo, &devInterfaceData, pDevDetail, // SP_DEVICE_INTERFACE_DETAIL_DATA
          BUFFER_SIZE, &dwRequiredSize, &devInfoData );           // SP_DEVINFO_DATA
    
        // Get the device instance of parent. This points to USBSTOR. 
        CM_Get_Parent( &devInstParent, devInfoData.DevInst, 0 );
    
        // Get the device instance of grand parent. This points to USB root.
        CM_Get_Parent( &devInstParent, devInstParent, 0 );
    
        // Get the device ID of the USB root.
        CM_Get_Device_ID( devInstParent, buf, BUFFER_SIZE, 0 );
    
        // If USB root device matches with the input device ID, it is the target  device.
    
        if ( buf != NULL && wcscmp( lpDevID, buf ) == 0 )
        {
          // Append  to the DevicePath of SP_DEVICE_INTERFACE_DETAIL_DATA
    
          nLength = wcslen( pDevDetail->DevicePath );
          pDevDetail->DevicePath[ nLength ] = '\';
          pDevDetail->DevicePath[ nLength + 1 ] = 0;
    
          // Get Volume mount point for the device path.
          if ( GetVolumeNameForVolumeMountPoint( pDevDetail->DevicePath, volume,
            BUFFER_SIZE ) )
          {
            for ( nLoopIndex = 0; nLoopIndex < g_count; nLoopIndex++ )
            {
              // Compare volume mount point with the one stored earlier.
              // If both match, return the corresponding drive letter.
    
              if ( wcscmp( g_drives[ nLoopIndex ].volume, volume ) == 0 )
              {
                SetupDiDestroyDeviceInfoList( hDevInfo );
                return g_drives[ nLoopIndex ].letter;
              }
            }
          }
        }
      }
    
      SetupDiDestroyDeviceInfoList( hDevInfo );
      WRITELOG( "Error - No drives found in GetSpecificDrives
    " );
      return 0;
    }

    http://www.lvr.com/files/find_drive_letter.txt

    (From Marc Reinig) Look at the code that Devcon.exe (from the DDK) uses in
    Devcon.exe find =diskdrive

    This will give you the instance ID of the disks present on the system, in
    order of their disk number. 0, 1, 2, 3, … . So now you know what the disk
    number is for your device.

    Then, using the code below, loop through all possible 26 logical drives,
    using strings that look like “C:” for szDriveLetter. When you get an
    sdnDevNumber.DeviceNumber that matches the disk number you are looking
    for, you have found your drive letter, szDriveLetter:

    char szDriveLetter[ 3 ];
    char * pszDrive;
    STORAGE_DEVICE_NUMBER sdnDevNumber;
    BOOL fResult;
    
    fResult = GetBasicDiskDriveMapping( szDriveLetter, &sdnDevNumber );
    
    // sdnDevNumber.DeviceNumber will contain the drive number you want 
    // sdnDevNumber.PartitionNumber will contain the partition for your reference 
    
    BOOL GetBasicDiskDriveMapping( LPCSTR pszDrive, STORAGE_DEVICE_NUMBER *psdn )
    
    {
    
      BOOL fResult;
      char szDriveName[ 7 ];
      HANDLE hDrive;
      DWORD dwBytesReturned;
    
      __try
      {
        lstrcpy( szDriveName, "\\.\" );
    
        lstrcat( szDriveName, pszDrive );
    
        // Open the volume to which the drive letter refers and get 
        // the physical drive on which the volume resides. 
    
        hDrive = CreateFile( szDriveName, GENERIC_READ,
    
        FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
    
        OPEN_EXISTING, 0, 0 );
    
        if ( INVALID_HANDLE_VALUE != hDrive )
    
          fResult = DeviceIoControl( hDrive,
    
          IOCTL_STORAGE_GET_DEVICE_NUMBER, 0, 0,
    
          psdn, sizeof(STORAGE_DEVICE_NUMBER),
    
          &dwBytesReturned, 0 );
    
        else
    
          fResult = false;
      }
    
      __except( EXCEPTION_EXECUTE_HANDLER )
    
      {
        // if we get here, one of the arguments probably 
        // points to not enough memory. 
    
        SetLastError( ERROR_INVALID_PARAMETER );
    
        fResult = false;
      }
    
      CloseHandle( hDrive );
    
      return ( fResult );
    }

    How To get the usbdisk's drive letter properly

    http://www.codeproject.com/Articles/6559/How-To-get-the-usbdisk-s-drive-letter-properly

    Introduction

    We know USB disk should be a removable disk just like floppy disk, and be used more and more widely now.
    Because, the USB disk is more faster, reliable, and affordable than old floppy disk.

    So, when we want to check one disk or drive of target system is removable or not,
    we may be thinking of using API function "GetDriveType()".
    Yes, it really works on some USB device, such as 16MB, 32MB, 64MB, and 128MB. ;-)
    Here, how aboutremovable hard disk which is connected to system by USB channel? -
    Windows will report them as 'Fix Disk', and we would get the same result using 'GetDriveType()' function.

    How can we differentiate between these USB ‘Fix Disk’ and Those IDE ‘Fix Disk’?
    Here is the solution for this event.

    Background

    (Why do I want get the USB disks' drive letter properly?
    Because I want to check the virus while one new USB drive is inserted.
    We should not be remiss of the virus which is more and more technical day by day:)

    Since we can get the base information about the disk type
    (using API Function ‘GetDriveType()’),
    we may only want to check the ‘Removable Hard Disk’ to verify its bus-type.
    Well, we’ll have two steps to get the USB disk’s drive letters:

    Code Thoughts

    switch ( GetDriveType( szDrvName ) )
    {
      case 0: // The drive type cannot be determined.
      case 1:// The root directory does not exist.
      drivetype = DRVUNKNOWN;
      break;
      case DRIVE_REMOVABLE:// The drive can be removed from the drive.
      drivetype = DRVREMOVE;
      break;
      case DRIVE_CDROM:// The drive is a CD-ROM drive.
      break;
      case DRIVE_FIXED:// The disk cannot be removed from the drive.
      drivetype = DRVFIXED;
      break;
      case DRIVE_REMOTE:// The drive is a remote (network) drive.
      drivetype = DRVREMOTE;
      break;
      case DRIVE_RAMDISK:// The drive is a RAM disk.
      drivetype = DRVRAM;
      break;
    }

    These codes above are based on ‘Article ID: Q161300 HOWTO:
    Determine the Type of Drive Using Win32’ from MSDN.

    2. Determinate the bus type of the ‘Fix Disk’:

    Now, we may embed our codes at the ‘case = DRIVE_FIXED’:

    Open the drive which we get now:

    hDevice = CreateFile(szBuf, 
      GENERIC_READ, 
      FILE_SHARE_READ | FILE_SHARE_WRITE, 
      NULL, OPEN_EXISTING, NULL, NULL);

    If we opened this drive, check its BUSTYPE, using API GetDisksProperty():

    if(GetDisksProperty(hDevice, pDevDesc))
    {
     if(pDevDesc->BusType == BusTypeUsb) // This is the ‘Check Point’!!! ;-)
     {
      // We store the drive letter here
      szMoveDiskName[k] = chFirstDriveFromMask(temp); 
      szMoveDiskName[0]=k;
      k++;
     }
    }

    Close this drive when we finished our work on it:

    CloseHandle(hDevice);

    3. How does the GetDisksProperty() work?

    /********************************************************
    *
    * FUNCTION: GetDisksProperty(HANDLE hDevice, 
    * PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
    *
    * PURPOSE: get the info of specified device
    *
    ******************************************************/
    BOOL GetDisksProperty(HANDLE hDevice, 
      PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
    {
     STORAGE_PROPERTY_QUERY Query; // input param for query
     DWORD dwOutBytes; // IOCTL output length
     BOOL bResult; // IOCTL return val
    
     // specify the query type
     Query.PropertyId = StorageDeviceProperty;
     Query.QueryType = PropertyStandardQuery;
    
     // Query using IOCTL_STORAGE_QUERY_PROPERTY 
     bResult = ::DeviceIoControl(hDevice, // device handle
     IOCTL_STORAGE_QUERY_PROPERTY, // info of device property
      &Query, sizeof(STORAGE_PROPERTY_QUERY), // input data buffer
      pDevDesc, pDevDesc->Size, // output data buffer
      &dwOutBytes, // out's length
      (LPOVERLAPPED)NULL); 
    
     return bResult;
    }

    Comments

    1. There are some structures not commented, see usbdisks_src for them.;
    2. Floppy drive (A: or B:) is reported as USB Disks by this demo, -And-
      it is easy to correct this, just putting some codes to the ‘case = DRIVE_REMOVABLE:‘;

    History

    • 2004-03-29 - 1st GO

    License

    This article, along with any associated source code and files,
    is licensed underThe Code Project Open License (CPOL)

  • 相关阅读:
    苹果和Google应该如何把二维码变成主流 | 36氪
    成绩换offer,中国版的Smarterer“一问一答”网站帮你把简历推荐给你想去的公司 | 36氪
    读过的一些书
    扫描QR码即可完成移动支付的LevelUp推出集合NFC、QR码等技术的移动支付终端,供商家免费使用 | 36氪
    “消息速递”团队推出“有声照片”,让照片同时拥有拍摄时的现场录音 | 36氪
    css3ps—ps直接生成css3 使用方法
    Google收购的Nik Software将会发力“服务器端图片处理”领域 | 36氪
    收藏本站
    让屏幕抖动一阵
    全中文日期显示
  • 原文地址:https://www.cnblogs.com/shangdawei/p/3139038.html
Copyright © 2011-2022 走看看