Почему только одно сообщение WM_DEVICECHANGE при удалении многотомного USB-устройства? - PullRequest
3 голосов
/ 22 октября 2009

Я пишу приложение, которое определяет, когда определенное USB-устройство хранения данных подключено, а когда оно отключено - прослушивая сообщения WM_DEVICECHANGE .

Я также зарегистрировал свое приложение для прослушивания WM_DEVICECHANGE сообщений для DBT_DEVTYP_DEVICEINTERFACE (используя вызов API RegisterDeviceNotification ), и я получаю сообщения DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE, когда USB Устройство хранения данных подключено или отключено.

Теперь, проблема возникает, когда USB-устройство, которое имеет несколько томов , подключено, а затем отключено.

При подключении устройства появляются следующие сообщения:

  • WM_DEVICECHANGE (DBT_DEVICEARRIVAL типа DBT_DEVTYP_DEVICEINTERFACE)
  • WM_DEVICECHANGE (DBT_DEVICEARRIVAL типа DBT_DEVTYP_VOLUME)
  • WM_DEVICECHANGE (DBT_DEVICEARRIVAL типа DBT_DEVTYP_VOLUME)

И следующие сообщения, когда он отключен:

  • WM_DEVICECHANGE (DBT_DEVICEREMOVECOMPLETE типа DBT_DEVTYP_VOLUME)
  • WM_DEVICECHANGE (DBT_DEVICEREMOVECOMPLETE типа DBT_DEVTYP_DEVICEINTERFACE)

Итак, только одно сообщение об удалении , хотя существует два тома . Почему ??

У меня есть два вопроса:

  • Как соотнести DBT_DEVTYP_DEVICEINTERFACE сообщения с DBT_DEVTYP_VOLUME сообщениями (по сути, как узнать, какому сообщению VOLUME соответствует какое сообщение DEVICEINTERFACE - поскольку я получаю их оба для устройство)?
  • Есть ли способ заставить Windows уведомлять меня об удалении обоих томов?

1 Ответ

6 голосов
/ 23 октября 2009

Хорошо, поэтому я смог ответить на один из моих собственных вопросов: Есть ли способ заставить Windows уведомлять меня об удалении обоих томов?

Да - даже если Windows отправляет только одно DBT_DEVTYP_VOLUME WM_DEVICECHANGE сообщение, вы действительно получаете уведомление об удалении обоих томов - но, как всегда, Ответ лежит в глубине похоронен в MSDN :

Хотя член dbcv_unitmask может указывать более одного тома в любом сообщении, это не гарантирует, что для указанного события будет сгенерировано только одно сообщение. Несколько компонентов системы могут независимо генерировать сообщения для логических томов одновременно.

Итак, все, что мне нужно было сделать, это проигнорировать пример функции , которую Microsoft дает в одном из своих примеров,

char FirstDriveFromMask (ULONG unitmask)
{
   char i;

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

   return (i + 'A');
}

И замените его функцией, которая интерпретирует маску для всех затронутых дисков. Таким образом, единственное сообщение, которое я получал, было действительно для обоих томов, и обе буквы диска тома были доступны в маске.

// [IN] ULONG unitmask
// [IN/OUT] char* outDriveLetters  - an array of characters to be passed in
//                                   that is filled out with the drive letters
//                                   in the mask (this must be 26 bytes to be safe)
// RETURNS the number of drive letters in the mask
int MaskToDriveLetters (ULONG unitmask, char* outDriveLetters)
{
   int cnt = 0;
   for (i = 0; i < 26; ++i)
   {
      if (unitmask & 0x1)
      {
         outDriveLetters[cnt++] = 'A' + i;
         cnt++;
      }
      unitmask = unitmask >> 1;
   }

   outDriveLetters[cnt] = 0; // set the last character to \0 (optional)
   return cnt;  // the number of drives that were set in the mask
}

У меня все еще есть другой вопрос, на который нужно ответить - как можно соотнести два сообщения (DBT_DEVTYP_DEVICEINTERFACE и DBT_DEVTYP_VOLUME)?

...