Perché un solo messaggio WM_DEVICECHANGE quando viene rimosso un dispositivo USB multi-volume?
-
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 tipoDBT_DEVTYP_DEVICEINTERFACE
) -
WM_DEVICECHANGE
(DBT_DEVICEARRIVAL
di tipoDBT_DEVTYP_VOLUME
) -
WM_DEVICECHANGE
(DBT_DEVICEARRIVAL
di tipoDBT_DEVTYP_VOLUME
)
E i seguenti messaggi quando è collegato:
-
WM_DEVICECHANGE
(DBT_DEVICEREMOVECOMPLETE
di tipoDBT_DEVTYP_VOLUME
) -
WM_DEVICECHANGE
(DBT_DEVICEREMOVECOMPLETE
di tipoDBT_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 messaggiDBT_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?
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?
Sì - 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
)?