¿Por qué solo un mensaje WM_DEVICECHANGE cuando se quita un dispositivo USB de múltiples volúmenes?

StackOverflow https://stackoverflow.com/questions/1608915

  •  05-07-2019
  •  | 
  •  

Pregunta

Estoy escribiendo una aplicación que detecta cuando un determinado dispositivo de almacenamiento masivo USB está enchufado, y cuando está desconectado, escuchando WM_DEVICECHANGE mensajes .

También he registrado mi aplicación para escuchar los mensajes de WM_DEVICECHANGE para los DBT_DEVTYP_DEVICEINTERFACE (usando RegisterDeviceNotification llamada a la API) y obtengo el DBT_DEVICEARRIVAL y DBT_DEVICEREMOVECOMPLETE mensajes cuando un dispositivo de almacenamiento masivo USB está enchufado o desenchufado.

Ahora, el problema se produce cuando un dispositivo USB que tiene varios volúmenes está enchufado y luego desenchufado.

Recibo los siguientes mensajes cuando el dispositivo está conectado:

  • WM_DEVICECHANGE ( DBT_DEVICEARRIVAL de tipo DBT_DEVTYP_DEVICEINTERFACE )
  • WM_DEVICECHANGE ( DBT_DEVICEARRIVAL de tipo DBT_DEVTYP_VOLUME )
  • WM_DEVICECHANGE ( DBT_DEVICEARRIVAL de tipo DBT_DEVTYP_VOLUME )

Y los siguientes mensajes cuando están conectados:

  • WM_DEVICECHANGE ( DBT_DEVICEREMOVECOMPLETE de tipo DBT_DEVTYP_VOLUME )
  • WM_DEVICECHANGE ( DBT_DEVICEREMOVECOMPLETE de tipo DBT_DEVTYP_DEVICEINTERFACE )

Por lo tanto, solo un mensaje de eliminación a pesar de que hay dos volúmenes . ¿Por qué?

Tengo dos preguntas:

  • ¿Cómo puedo correlacionar los mensajes de DBT_DEVTYP_DEVICEINTERFACE con los mensajes de DBT_DEVTYP_VOLUME (esencialmente, cómo puedo saber qué mensaje de VOLUME corresponde a cuál DEVICEINTERFACE mensaje: ¿desde que los recibí para el dispositivo)?
  • ¿Hay alguna forma de hacer que Windows me notifique acerca de la eliminación de ambos volúmenes?
¿Fue útil?

Solución

Bien, así que pude responder una de mis propias preguntas: ¿Hay alguna forma de hacer que Windows me notifique sobre la eliminación de ambos volúmenes?

- a pesar de que Windows envía solo un mensaje DBT_DEVTYP_VOLUME WM_DEVICECHANGE , realmente recibe notificaciones de ambos retiros de volumen - pero, como siempre, la respuesta se encuentra en el fondo enterrado en MSDN :

  

Aunque el miembro dbcv_unitmask puede especificar más de un volumen en cualquier mensaje, esto no garantiza que solo se genere un mensaje para un evento específico. Varios componentes del sistema pueden generar mensajes de forma independiente para volúmenes lógicos al mismo tiempo.

Entonces, todo lo que tuve que hacer fue ignorar el función de ejemplo que Microsoft entrega en una de sus muestras,

char FirstDriveFromMask (ULONG unitmask)
{
   char i;

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

   return (i + 'A');
}

Y reemplácelo con una función que interprete la máscara para todas las unidades afectadas. De modo que el único mensaje que recibí fue, de hecho, para ambos volúmenes, y ambas letras de unidad de volumen estaban disponibles en la máscara.

// [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
}

Todavía tengo la otra pregunta que responder, ¿cómo se pueden correlacionar los dos mensajes ( DBT_DEVTYP_DEVICEINTERFACE y DBT_DEVTYP_VOLUME )?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top