Убедитесь, что вы используете GUID_DEVINTERFACE_VOLUME
для регистрации уведомления устройства.
Обходной путь (если том (ы) вашего USB принадлежит новому диску) должен использовать GetLogicalDrives
проверка измененной маски устройства после прибытия устройства:
LRESULT message_handler(HWND__* hwnd, UINT uint, WPARAM wparam, LPARAM lparam)
{
static DWORD current_unit_mask = 0;
switch (uint)
{
//...
case WM_CREATE: // the actual creation of the window
{
// you can get your creation params here..like GUID..
LPCREATESTRUCT params = (LPCREATESTRUCT)lparam;
GUID InterfaceClassGuid = *((GUID*)params->lpCreateParams);
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
for (int i = 0; i < sizeof(GuidDevInterfaceList); i++) {
NotificationFilter.dbcc_classguid = GuidDevInterfaceList[i];
HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if (dev_notify == NULL) { // Handle the error by returning correct error in LRESULT format and remove throw...
throw std::runtime_error("Could not register for device Notifications!");
}
}
current_unit_mask = GetLogicalDrives(); //Get the initial value
}
break;
case WM_DEVICECHANGE:
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lparam;
//DBT_DEVTYP_VOLUME
if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
switch (wparam)
{
case DBT_DEVICEARRIVAL:
{
cout << "Device Arrived" << endl;
DWORD tmpmask = GetLogicalDrives();
DWORD changed_mask = tmpmask ^ current_unit_mask; //changed_mask stores the uintmask of the changed device
current_unit_mask = tmpmask; //update current_unit_mask
}break;
}
}
}
}
}
Спасибо, что @RbMm указал, что накопитель может иметь несколько томов, и том можно вставить без добавления в новый диск. Таким образом, вышеприведенная логика c может отслеживать изменения объемов:
#include <windows.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <iterator>
using namespace std;
vector<wstring> GetVolumePaths(vector<wstring> volumes)
{
DWORD ReturnLength = 0;
WCHAR Names[MAX_PATH] = { 0 };
PWCHAR NameIdx = NULL;
BOOL Success = FALSE;
vector<wstring> VolumePaths;
for (int i = 0; i < volumes.size(); i++)
{
for (;;)
{
Success = GetVolumePathNamesForVolumeNameW(volumes[i].c_str(), Names, MAX_PATH, &ReturnLength);
if (Success)
{
break;
}
if (GetLastError() != ERROR_MORE_DATA)
{
break;
}
}
if (Success)
{
for (NameIdx = Names;
NameIdx[0] != L'\0';
NameIdx += wcslen(NameIdx) + 1)
{
wprintf(L" %s", NameIdx);
VolumePaths.push_back(NameIdx);
}
wprintf(L"\n");
}
}
return VolumePaths;
}
vector<wstring> GetDiff(vector<wstring> v1, vector<wstring> v2)
{
vector<wstring> diff;
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(),
std::inserter(diff, diff.begin()));
return diff;
}
vector<wstring> FindVolume()
{
DWORD CharCount = 0;
DWORD Error = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
size_t Index = 0;
BOOL Success = FALSE;
WCHAR VolumeName[MAX_PATH] = L"";
vector<wstring> volumes;
FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);
return volumes;
}
volumes.push_back(VolumeName);
for (;;)
{
//
// Skip the \\?\ prefix and remove the trailing backslash.
Index = wcslen(VolumeName) - 1;
if (VolumeName[0] != L'\\' ||
VolumeName[1] != L'\\' ||
VolumeName[2] != L'?' ||
VolumeName[3] != L'\\' ||
VolumeName[Index] != L'\\')
{
Error = ERROR_BAD_PATHNAME;
wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName);
break;
}
Success = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));
if (!Success)
{
Error = GetLastError();
if (Error != ERROR_NO_MORE_FILES)
{
wprintf(L"FindNextVolumeW failed with error code %d\n", Error);
break;
}
Error = ERROR_SUCCESS;
break;
}
volumes.push_back(VolumeName);
}
FindVolumeClose(FindHandle);
FindHandle = INVALID_HANDLE_VALUE;
return volumes;
}
LRESULT message_handler(HWND__* hwnd, UINT uint, WPARAM wparam, LPARAM lparam)
{
static vector<wstring> current_volumes;
switch (uint)
{
//...
case WM_CREATE: // the actual creation of the window
{
// you can get your creation params here..like GUID..
LPCREATESTRUCT params = (LPCREATESTRUCT)lparam;
GUID InterfaceClassGuid = *((GUID*)params->lpCreateParams);
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
for (int i = 0; i < sizeof(GuidDevInterfaceList); i++) {
NotificationFilter.dbcc_classguid = GuidDevInterfaceList[i];
HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if (dev_notify == NULL) { // Handle the error by returning correct error in LRESULT format and remove throw...
throw std::runtime_error("Could not register for device Notifications!");
}
}
current_unit_mask = FindVolume();
}
break;
case WM_DEVICECHANGE:
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lparam;
//DBT_DEVTYP_VOLUME
if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
switch (wparam)
{
case DBT_DEVICEARRIVAL:
{
cout << "Device Arrived" << endl;
vector<wstring> tmp = FindVolume();
vector<wstring> change_volumes = GetDiff(tmp, current_volumes);
vector<wstring> VolumePaths = GetVolumePaths(change_volumes);
current_volumes = tmp;
for(int i = 0; i < VolumePaths.size(); i++)
{
wprintf(L" %s\n", VolumePaths[i]);
}
}break;
}
}
}
}
}