Получение буквы диска USB флешки.
От: Serg1983 Россия  
Дата: 03.10.05 10:41
Оценка:
Стоит задача — получить для всех флешек информацию о них (серийный номер, производитель и т.д.) и ее букву диска. Для получения информации я воспользовался стандартным примером из DDK — usbview, но получение буквы диска оказалось сложнее чем я думал. В usbview структура PUSB_NODE_CONNECTION_INFORMATION является единственным идентификатором usb устройства, нет никаких имен и нет хэнделов.
Из полей этой структуры я могу получить имя устройсва usb следующего вида: "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}", которое можно передать в CreateFile и получить хэндл устройства. Но как по этому хэндлу узнать букву диска я к сожалению не нашел

Буду рад любой информации
Re: Получение буквы диска USB флешки.
От: Nocturne  
Дата: 03.10.05 10:52
Оценка:
Здравствуйте, Serg1983, Вы писали:

S>Стоит задача — получить для всех флешек информацию о них (серийный номер, производитель и т.д.) и ее букву диска. Для получения информации я воспользовался стандартным примером из DDK — usbview, но получение буквы диска оказалось сложнее чем я думал. В usbview структура PUSB_NODE_CONNECTION_INFORMATION является единственным идентификатором usb устройства, нет никаких имен и нет хэнделов.

S>Из полей этой структуры я могу получить имя устройсва usb следующего вида: "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}", которое можно передать в CreateFile и получить хэндл устройства. Но как по этому хэндлу узнать букву диска я к сожалению не нашел

S>Буду рад любой информации


На счет любой информации:
Попробуй вызвать GetLogicalDrives для получения всех дисков и в цикле проверять GetDriveType для каждого. Флэшки — DRIVE_REMOVABLE.
Правда как ты это будешь контачить с данными из DDK я не знаю
Re: Получение буквы диска USB флешки.
От: srggal Украина  
Дата: 03.10.05 11:01
Оценка:
Здравствуйте, Serg1983, Вы писали:

S>Из полей этой структуры я могу получить имя устройсва usb следующего вида: "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}", которое можно передать в CreateFile и получить хэндл устройства. Но как по этому хэндлу узнать букву диска я к сожалению не нашел


Думаю, что в MSD: раздел

Naming a Volume


и возможно функция ( возможно потому как я сам не вникал):

GetVolumeInformation


поможет ронять что и как.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Получение буквы диска USB флешки.
От: Serg1983 Россия  
Дата: 03.10.05 11:12
Оценка:
Здравствуйте, Nocturne, Вы писали:

N>На счет любой информации:

N>Попробуй вызвать GetLogicalDrives для получения всех дисков и в цикле проверять GetDriveType для каждого. Флэшки — DRIVE_REMOVABLE.
N>Правда как ты это будешь контачить с данными из DDK я не знаю

Спасибо за ответ.
Я пытался пойти с обратной стороны. Т.е. по букве диска получить что-нибудь, идентифицирующее флешку. Максимум что я получил это номер PhysicalDrive.
Re[2]: Получение буквы диска USB флешки.
От: Serg1983 Россия  
Дата: 03.10.05 11:44
Оценка:
Здравствуйте, srggal, Вы писали:

S>Думаю, что в MSD: раздел


S>

S>Naming a Volume


S>и возможно функция ( возможно потому как я сам не вникал):


S>

S>GetVolumeInformation


S>поможет ронять что и как.


К сожалению, GetVolumeInformation для флешки не выдает ничего
Re[3]: Получение буквы диска USB флешки.
От: srggal Украина  
Дата: 03.10.05 11:53
Оценка:
Здравствуйте, Serg1983, Вы писали:


S>К сожалению, GetVolumeInformation для флешки не выдает ничего


Ок, если я не ошибся в корне и Флышка и есть Volume
ТО может помочь:

Enumerating Mount Points


#define _WIN32_WINNT 0x0501

#include <windows.h>
#include <stdio.h>


#define BUFSIZE MAX_PATH        
#define FILESYSNAMEBUFSIZE MAX_PATH


// Process each mount point found here. This makes maintenance easier 
// than doing it in line. The result indicates whether there is 
// another mount point to be scanned.

// This routine prints out the path to a mount point and its target. 

BOOL ProcessVolumeMountPoint (HANDLE hPt,
                              char *PtBuf, DWORD dwPtBufSize,
                              char *Buf, DWORD dwBufSize)
{
   BOOL bFlag;                   // Boolean result   
   char Path[BUFSIZE];           // construct a complete path here
   HANDLE hFf, hFile;            // file search, file handles
   WIN32_FIND_DATA fd;           // find data for a file search
   DWORD BytesReturned;          // from DeviceIoControl call
   char Target[BUFSIZE];         // target of mount at mount point

   printf ("\tVolume mount point found is \"%s\"\n", PtBuf);

   // Detect the volume mounted there. Unfortunately, there is no 
   // simple way to map a unique volume name to a DOS drive letter. 
   // One way to do that is to build an associative array, which we 
   // will "leave as an exercise for the student." 

   // Build a unique path to the mount point

   strcpy (Path, Buf);
   strcat (Path, PtBuf);

   bFlag = GetVolumeNameForVolumeMountPoint(
                Path, // input volume mount point or directory
              Target, // output volume name buffer
              BUFSIZE // size of volume name buffer
           );

   if (!bFlag)
      printf ("\tAttempt to get volume name for %s failed.\n", Path);
   else 
      printf ("\tTarget of the volume mount point is %s.\n", Target);
  
   // Now, either get the next mount point and return it, or return a 
   // value indicating there are no more mount points.

   bFlag = FindNextVolumeMountPoint(
                     hPt, // handle to scan
                   PtBuf, // pointer to output string
              dwPtBufSize // size of output buffer
           );
  return (bFlag);
}

// Process each volume. This makes maintenance easier than doing it
// in line. The Boolean result indicates whether there is another 
// volume to be scanned. 

BOOL ProcessVolume (HANDLE hVol, char *Buf, int iBufSize)
{
   BOOL bFlag;                  // generic results flag for return
   HANDLE hPt;                  // handle for mount point scan
   char PtBuf[BUFSIZE];         // string buffer for mount points
   DWORD dwSysFlags;            // flags that describe the file system
   char FileSysNameBuf[FILESYSNAMEBUFSIZE];

   printf ("Volume found is \"%s\".\n", Buf);

   // Is this volume NTFS? 
   GetVolumeInformation( Buf, NULL, 0, NULL, NULL,
                         &dwSysFlags, FileSysNameBuf, 
                         FILESYSNAMEBUFSIZE);

   // Detect support for reparse points, and therefore for volume 
   // mount points, which are implemented using reparse points.

   if (! (dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS)) 
   {
      printf ("\tThis file system does not support volume mount points.\n");
   } 
   else 
   {
      // Start processing mount points on this volume. 

      hPt = FindFirstVolumeMountPoint(
                  Buf, // root path of volume to be scanned
                PtBuf, // pointer to output string
               BUFSIZE // size of output buffer
            );

      if (hPt == INVALID_HANDLE_VALUE)
      {
         printf ("\tNo volume mount points found!\n");
      } 
      else 
      {
         // Process the volume mount point.
         bFlag = ProcessVolumeMountPoint (hPt, PtBuf, BUFSIZE, Buf, BUFSIZE); 

         // Do while we have volume mount points to process.
         while (bFlag) 
            bFlag = ProcessVolumeMountPoint (hPt, PtBuf, BUFSIZE, Buf, BUFSIZE);

         FindVolumeMountPointClose(hPt);
       }
   }

  // Stop processing mount points on this volume. 

   bFlag = FindNextVolume(
                hVol, // handle to scan being conducted
                 Buf, // pointer to output
             iBufSize // size of output buffer
           );

   return (bFlag); 
}

int main(void)
{
   char buf[BUFSIZE];            // buffer for unique volume identifiers
   HANDLE hVol;                  // handle for the volume scan
   BOOL bFlag;                   // generic results flag

   // Open a scan for volumes.
   hVol = FindFirstVolume (buf, BUFSIZE );

   if (hVol == INVALID_HANDLE_VALUE)
   {
      printf ("No volumes found!\n");
      return (-1);
   }

   // We have a volume; process it.
   bFlag = ProcessVolume (hVol, buf, BUFSIZE);

   // Do while we have volumes to process.
   while (bFlag) 
   {
      bFlag = ProcessVolume (hVol, buf, BUFSIZE);
   }

   // Close out the volume scan.
   bFlag = FindVolumeClose(
              hVol  // handle to be closed
           );

   return (bFlag);
}


Код любезно предоставлен библиотекой МСДН
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Получение буквы диска USB флешки.
От: Pavel Dvorkin Россия  
Дата: 03.10.05 11:58
Оценка:
S>Из полей этой структуры я могу получить имя устройсва usb следующего вида: "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}", которое можно передать в CreateFile и получить хэндл устройства. Но как по этому хэндлу узнать букву диска я к сожалению не нашел

Не слишком умная идея, но

Попробовать GetFileInformationByHandle. Вопрос — вернет он все что нужно, или нет. Там написано

Depending on the underlying network components of the operating system and the type of server connected to, the GetFileInformationByHandle function may fail, return partial information, or full information for the given file.

А хотелось бы от нее dwVolumeSerialNumber . После этого GetVolumeInformation
для всех подозрительных дисков и найти нужный.
With best regards
Pavel Dvorkin
Re[4]: Получение буквы диска USB флешки.
От: Serg1983 Россия  
Дата: 03.10.05 12:22
Оценка:
Здравствуйте, srggal, Вы писали:

S>Ок, если я не ошибся в корне и Флышка и есть Volume

S>ТО может помочь:

S>Код любезно предоставлен библиотекой МСДН


Для Volume, который является флешкой код выдает "This file system does not support volume mount points."
Re[5]: Получение буквы диска USB флешки.
От: srggal Украина  
Дата: 03.10.05 12:28
Оценка:
Здравствуйте, Serg1983, Вы писали:

S>Здравствуйте, srggal, Вы писали:



S>Для Volume, который является флешкой код выдает "This file system does not support volume mount points."


Что уже можно применять на практике

Но при 2х и более флэшках будем иметь проблему...
Бум думаьт...
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Получение буквы диска USB флешки.
От: Serg1983 Россия  
Дата: 03.10.05 12:33
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Попробовать GetFileInformationByHandle. Вопрос — вернет он все что нужно, или нет. Там написано


PD>Depending on the underlying network components of the operating system and the type of server connected to, the GetFileInformationByHandle function may fail, return partial information, or full information for the given file.


PD>А хотелось бы от нее dwVolumeSerialNumber . После этого GetVolumeInformation

PD> для всех подозрительных дисков и найти нужный.

Для имен файлов на диске (например "c:\\boot.ini") она возвращает правильный серийный номер. Но если передать "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}" результат плачевный . GetLastError() показывает ошибку с номером 1
Re: Получение буквы диска USB флешки.
От: VladKurmaz Украина http://tis-method.org/
Дата: 03.10.05 14:02
Оценка:
Здравствуйте, Serg1983, Вы писали:

S>Стоит задача — получить для всех флешек информацию о них (серийный номер, производитель и т.д.) и ее букву диска. Для получения информации я воспользовался стандартным примером из DDK — usbview, но получение буквы диска оказалось сложнее чем я думал. В usbview структура PUSB_NODE_CONNECTION_INFORMATION является единственным идентификатором usb устройства, нет никаких имен и нет хэнделов.

S>Из полей этой структуры я могу получить имя устройсва usb следующего вида: "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}", которое можно передать в CreateFile и получить хэндл устройства. Но как по этому хэндлу узнать букву диска я к сожалению не нашел

S>Буду рад любой информации


Попробуй использовать IShellFolder и его метод GetAttributesOf().
Сейчас проверил на своём тестовом приложении
флаг SFGAO_REMOVABLE выдал для A: и флешки G:
Под XP этот флаг OS установила и для CD/DVD накопителей — это может быть
проблемой
Re: Получение буквы диска USB флешки.
От: Conr Россия  
Дата: 03.10.05 15:59
Оценка: 5 (2)
Здравствуйте, Serg1983, Вы писали:

S>Стоит задача — получить для всех флешек информацию о них (серийный номер, производитель и т.д.) и ее букву диска. Для получения информации я воспользовался стандартным примером из DDK — usbview, но получение буквы диска оказалось сложнее чем я думал. В usbview структура PUSB_NODE_CONNECTION_INFORMATION является единственным идентификатором usb устройства, нет никаких имен и нет хэнделов.

S>Из полей этой структуры я могу получить имя устройсва usb следующего вида: "USB#Vid_14e4&Pid_1000#5&29899c85&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}", которое можно передать в CreateFile и получить хэндл устройства. Но как по этому хэндлу узнать букву диска я к сожалению не нашел

S>Буду рад любой информации

Вот готовый класс, работает пока без нареканий. Основная идея, как уже подсказывали — использование volume, только все немного сложнее CSimpleMap & CSimpleArray — контейнеры из ATL, но если что переделывается под STL на раз


#include <cfgmgr32.h>
#include <SetupAPI.h>
#pragma comment(lib,"Setupapi.lib")


#pragma once

class UsbDrives
{
    CSimpleMap<CString, TCHAR>    m_map;
    CSimpleArray<TCHAR>            m_drives;

public:
    UsbDrives()
    {
        refresh();
    }


    int count() { return m_drives.GetSize(); }
    TCHAR drive(int index )
    {
        if( m_drives.GetSize() > index )
            return m_drives[index];

        return NULL;
    }    
    bool check(TCHAR ch)
    {
        return -1 != m_drives.Find(ch);
    }

    void refresh()
    {
        m_map.RemoveAll();
        m_drives.RemoveAll();

        if( getAllRemovable() )
        {
            populate();
        }
    }
private:
    const static int bufferSize = 256;

    bool getAllRemovable()
    {
        TCHAR    drive[4] = _T("A:\\");
        TCHAR   volume[bufferSize];        

        DWORD mask = ::GetLogicalDrives();

        if( !mask )
            return false;
        else
        {
            for( int i=0; i<26; i++ )
            {
                if( mask & 1)
                {
                    drive[0] = 'A' + i;

                    if( ::GetDriveType(drive) == DRIVE_REMOVABLE )
                    {
                        if( ::GetVolumeNameForVolumeMountPoint(drive, volume, bufferSize) )
                        {
                            m_map.Add(volume,drive[0]);
                        }
                    }
                }
                mask >>= 1;
            }
        }

        return m_map.GetSize() > 0;
    }
    void populate()
    {
        GUID guid = GUID_DEVINTERFACE_VOLUME;

        //    hDevInfo = SetupDiGetClassDevs(NULL,
        //        _T("USBSTOR"), // Enumerator
        //        0,
        //        DIGCF_PRESENT | DIGCF_ALLCLASSES );

        HDEVINFO info = ::SetupDiGetClassDevs(&guid,NULL,NULL,
            DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
        if( INVALID_HANDLE_VALUE != info )
        {
            SP_DEVICE_INTERFACE_DATA ifaceData;
            SP_DEVINFO_DATA data;
            BYTE    buffer[bufferSize];
            TCHAR    buf[bufferSize];
            TCHAR    volume[bufferSize];

            for( int i=0; ; i++ )
            {
                ZeroMemory(&ifaceData,sizeof(ifaceData));
                ifaceData.cbSize = sizeof(ifaceData);
                ZeroMemory(&data,sizeof(data));
                data.cbSize = sizeof(data);

                if( !::SetupDiEnumDeviceInterfaces(info,NULL,&guid,i,&ifaceData) )
                    break;

                PSP_DEVICE_INTERFACE_DETAIL_DATA detail = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(buffer);
                detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

                DWORD size;
                SetupDiGetDeviceInterfaceDetail(info,&ifaceData,detail,bufferSize,&size,&data);

                DEVINST parent;
                //    Get the device instance of parent. This points to USBSTOR.
                CM_Get_Parent(&parent,data.DevInst, 0);

                // Get the device instance of grand parent. This points to USB root.
                CM_Get_Parent(&parent,parent, 0);

                // Get the device ID of the USB root.
                CM_Get_Device_ID(parent, buf, bufferSize,0);

                if( buf && buf[0] )
                {
                    int len = lstrlen(detail->DevicePath);
                    detail->DevicePath[len] = _T('\\');
                    detail->DevicePath[len+1] = 0;
                    CString tmp = detail->DevicePath;
                    if( 0 == tmp.Find(_T("\\\\?\\storage#removablemedia#")) )
                    {
                        if( ::GetVolumeNameForVolumeMountPoint(detail->DevicePath, volume, bufferSize) )
                        {
                            int idx = m_map.FindKey(volume);
                            if( -1 != idx )
                            {
                                TCHAR drive = m_map.GetValueAt(idx);
                                if( -1 == m_drives.Find(drive) )
                                    m_drives.Add(drive);
                            }
                        }
                    }
                }
            }
        }
    }
};
Re: Получение буквы диска USB флешки.
От: RendeRR Россия nothing
Дата: 03.10.05 19:47
Оценка:
Здравствуйте, Serg1983, Вы писали:

S>Стоит задача — получить для всех флешек информацию о них


Обязательно WinAPI? WMI не подойдёт?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Не знаешь как правильно – делай, как знаешь…
Re[2]: Получение буквы диска USB флешки.
От: Doc Россия http://andrey.moveax.ru
Дата: 19.02.07 16:33
Оценка:
Здравствуйте, Conr, Вы писали:

C>Вот готовый класс, работает пока без нареканий. Основная идея, как уже подсказывали — использование volume, только все немного сложнее


А есть возможность найти не только USB как диски, но и "подключенные как папки"?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Получение буквы диска USB флешки.
От: MShura  
Дата: 19.02.07 17:13
Оценка:
Doc>А есть возможность найти не только USB как диски, но и "подключенные как папки"?

— Перебираешь все тома в системе ( FindFirstVolume, FindNextVolume )
— Для каждого тома перебираешь его MountPoints ( FindFirstVolumeMountPoint, FindNextVolumeMountPoint )
— Для каждого MountPoint вызываешь GetVolumeNameForVolumeMountPoint
— Сравниваешь полученное имя с именем тома, для которого нужно найти все MountPoint "подключенные как папки".
Re[4]: Получение буквы диска USB флешки.
От: MShura  
Дата: 19.02.07 17:15
Оценка:
Пример из одноименного топика
http://www.rsdn.ru/Forum/?mid=1984719
Автор: MShura
Дата: 01.07.06
Re[4]: Получение буквы диска USB флешки.
От: Doc Россия http://andrey.moveax.ru
Дата: 19.02.07 17:45
Оценка:
Здравствуйте, MShura, Вы писали:

MS>- Перебираешь все тома в системе ( FindFirstVolume, FindNextVolume )

MS>- Для каждого тома перебираешь его MountPoints ( FindFirstVolumeMountPoint, FindNextVolumeMountPoint )
MS>- Для каждого MountPoint вызываешь GetVolumeNameForVolumeMountPoint
MS>- Сравниваешь полученное имя с именем тома, для которого нужно найти все MountPoint "подключенные как папки".

Пошел другоим путем
— перебираем тома
— для каждого тома GetVolumePathNamesForVolumeName что бы узнать путь
— для пути GetDriveType что бы узнать является ли том DRIVE_REMOVABLE
— проверить все выбранные данные тома как в populate класса выше.

Минус — XP и выше. Может у GetVolumePathNamesForVolumeName есть аналоги под Win2k и ниже?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.