Perché un solo messaggio WM_DEVICECHANGE quando viene rimosso un dispositivo USB multi-volume?

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

  •  05-07-2019
  •  | 
  •  

Domanda

Sto scrivendo un'applicazione che rileva quando è collegato un determinato dispositivo di archiviazione di massa USB e quando è scollegato, ascoltando messaggi WM_DEVICECHANGE .

Ho anche registrato la mia applicazione per ascoltare i messaggi WM_DEVICECHANGE per DBT_DEVTYP_DEVICEINTERFACE (usando RegisterDeviceNotification API call) e ottengo sia DBT_DEVICEARRIVAL che DBT_DEVICEREMOVECOMPLETE messaggi quando un dispositivo di archiviazione di massa USB è collegato o scollegato.

Ora, il problema si verifica quando un dispositivo USB che ha più volumi viene collegato e quindi scollegato.

Ricevo i seguenti messaggi quando il dispositivo è collegato:

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

E i seguenti messaggi quando è collegato:

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

Quindi, solo un messaggio rimuovi anche se ci sono due volumi . Perchè ??

Ho due domande:

  • Come posso correlare i messaggi DBT_DEVTYP_DEVICEINTERFACE con i messaggi DBT_DEVTYP_VOLUME (essenzialmente, come faccio a sapere quale messaggio VOLUME corrisponde a quale DEVICEINTERFACE - dal momento che li ottengo entrambi per il dispositivo)?
  • C'è un modo per avvisare Windows di entrambe le rimozioni di volume?
È stato utile?

Soluzione

Ok, quindi sono stato in grado di rispondere a una delle mie domande: Esiste un modo per avvisare Windows di entrambe le rimozioni di volume?

- anche se Windows invia solo un DBT_DEVTYP_VOLUME WM_DEVICECHANGE , in realtà ricevi notifiche su entrambe le rimozioni di volume - ma, come sempre, la risposta sta nel profondo sepolto in MSDN :

  

Sebbene il membro dbcv_unitmask possa specificare più di un volume in qualsiasi messaggio, ciò non garantisce che venga generato un solo messaggio per un evento specificato. Più componenti di sistema possono generare in modo indipendente messaggi per volumi logici contemporaneamente.

Quindi, tutto quello che dovevo fare era ignorare funzione di esempio fornita da Microsoft in uno dei loro campioni

char FirstDriveFromMask (ULONG unitmask)
{
   char i;

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

   return (i + 'A');
}

E sostituiscilo con una funzione che interpreta la maschera per tutte le unità interessate. Quindi l'unico messaggio che stavo ricevendo era effettivamente per entrambi i volumi, ed entrambe le lettere di unità del volume erano disponibili nella maschera.

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

Ho ancora l'altra domanda a cui rispondere: come si possono correlare i due messaggi ( DBT_DEVTYP_DEVICEINTERFACE e DBT_DEVTYP_VOLUME )?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top