7 #include <QCoreApplication>
10 #define _WIN32_WINNT 0x0500
13 #ifndef DBT_CUSTOMEVENT
14 # define DBT_CUSTOMEVENT 0x8006
17 #define CONFIG_NOTIFICATION 0
19 #if CONFIG_NOTIFICATION
20 static HDEVNOTIFY hDevNotify = 0;
21 #define HID_CLASSGUID {0x4d1e55b2, 0xf16f, 0x11cf,{ 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}}
22 static const GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };
23 static const GUID GUID_DEVINTERFACE_USBSTOR = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
24 static const GUID InterfaceClassGuid = GUID_DEVINTERFACE_USBSTOR;
25 #endif //CONFIG_NOTIFICATION
27 static QStringList drivesFromMask(quint32 driveBits)
30 #if 1 //a disk with multiple partitions removed
31 char driveName[] =
"A:/";
32 driveBits &= 0x3ffffff;
35 ret.append(QString::fromLatin1(driveName));
48 return ret << QString(c) +
":";
52 LRESULT CALLBACK dw_internal_proc(HWND hwnd, UINT
message, WPARAM wParam, LPARAM lParam)
54 if (message == WM_DEVICECHANGE) {
55 DEV_BROADCAST_HDR *lpdb = (DEV_BROADCAST_HDR *)lParam;
56 qDebug(
"Device type address: %#x", lpdb);
58 if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
59 qDebug(
"DBT_DEVTYP_VOLUME");
60 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
61 qDebug(
"DBT_DEVTYP_PORT");
62 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
63 qDebug(
"DBT_DEVTYP_DEVICEINTERFACE");
64 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
65 qDebug(
"DBT_DEVTYP_OEM");
67 qDebug(
"Unknow device type");
72 case DBT_DEVNODES_CHANGED:
73 qDebug(
"DBT_DEVNODES_CHANGED message received, no extended info.");
75 case DBT_QUERYCHANGECONFIG:
76 qDebug(
"DBT_QUERYCHANGECONFIG message received, no extended info.");
78 case DBT_CONFIGCHANGED:
79 qDebug(
"DBT_CONFIGCHANGED message received, no extended info.");
81 case DBT_CONFIGCHANGECANCELED:
82 qDebug(
"DBT_CONFIGCHANGECANCELED message received, no extended info.");
85 case DBT_DEVICEARRIVAL:
86 case DBT_DEVICEQUERYREMOVE:
87 case DBT_DEVICEQUERYREMOVEFAILED:
88 case DBT_DEVICEREMOVEPENDING:
89 case DBT_DEVICEREMOVECOMPLETE:
90 if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
91 DEV_BROADCAST_VOLUME *db_volume = (DEV_BROADCAST_VOLUME *)lpdb;
92 QStringList drives = drivesFromMask(db_volume->dbcv_unitmask);
98 QList<QDeviceChangeEvent *> events;
99 QString action_str(
"add");
101 if (wParam == DBT_DEVICEARRIVAL) {
102 }
else if (wParam == DBT_DEVICEQUERYREMOVE) {
103 }
else if (wParam == DBT_DEVICEQUERYREMOVEFAILED) {
104 }
else if (wParam == DBT_DEVICEREMOVEPENDING) {
105 }
else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
106 action_str =
"remove";
109 foreach (
const QString &drive, drives) {
110 if (db_volume->dbcv_flags & DBTF_MEDIA)
111 qDebug(
"Drive %c: Media has been removed.", drive.at(0).toLatin1());
112 else if (db_volume->dbcv_flags & DBTF_NET)
113 qDebug(
"Drive %c: Network share has been removed.", drive.at(0).toLatin1());
115 qDebug(
"Drive %c: Device has been removed.", drive.at(0).toLatin1());
123 QCoreApplication::postEvent(obj, event, Qt::HighEventPriority);
127 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
128 qDebug(
"DBT_DEVTYP_PORT");
129 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
131 qDebug(
"DBT_DEVTYP_DEVICEINTERFACE");
132 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
133 qDebug(
"DBT_DEVTYP_OEM");
134 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE) {
135 qDebug(
"DBT_DEVTYP_HANDLE");
138 case DBT_DEVICETYPESPECIFIC:
139 qDebug(
"DBT_DEVICETYPESPECIFIC message received, may contain an extended info.");
141 case DBT_CUSTOMEVENT:
142 qDebug(
"DBT_CUSTOMEVENT message received, contains an extended info.");
144 case DBT_USERDEFINED:
145 qDebug(
"WM_DEVICECHANGE user defined message received, can not handle.");
148 qWarning(
"WM_DEVICECHANGE message received, unhandled value %d.", wParam);
153 return DefWindowProc(hwnd, message, wParam, lParam);
156 static QString className()
158 return QLatin1String(
"QDeviceWatcherPrivateWin32_Internal_Widget") + QString::number(quintptr(dw_internal_proc));
161 static HWND dw_create_internal_window(
const void* userData)
163 QString className = ::className();
164 HINSTANCE hi = GetModuleHandle(
nullptr);
168 wc.lpfnWndProc = dw_internal_proc;
174 wc.hbrBackground = 0;
175 wc.lpszMenuName =
nullptr;
179 HWND hwnd = CreateWindowW(wc.lpszClassName,
191 qWarning(
"QDeviceWatcherPrivate: Failed to create internal window: %d",
TTKStaticCast(
int, GetLastError()));
192 #if CONFIG_NOTIFICATION
194 DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
195 ZeroMemory(&NotificationFilter,
sizeof(NotificationFilter));
196 NotificationFilter.dbcc_size =
sizeof(DEV_BROADCAST_DEVICEINTERFACE);
197 NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
198 NotificationFilter.dbcc_classguid = InterfaceClassGuid;
201 hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
207 }
else if (userData) {
209 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)userData);
211 SetWindowLongW(hwnd, GWL_USERDATA, (LONG)userData);
214 #endif //CONFIG_NOTIFICATION
218 static void dw_destroy_internal_window(HWND hwnd)
223 #if CONFIG_NOTIFICATION
224 UnregisterDeviceNotification(hDevNotify);
226 UnregisterClassW(
TTKReinterpretCast(
const wchar_t *, className().utf16()), GetModuleHandle(
nullptr));
239 hwnd = dw_create_internal_window(
this);
242 dw_destroy_internal_window(hwnd);
249 dw_destroy_internal_window(hwnd);
#define TTKStaticCast(x, y)
static QString message(const TTK::Attribute attr)
The class of the device watcher event.
void emitDeviceAction(const QString &dev, const QString &action)
The class of the device watcher private.
#define TTKReinterpretCast(x, y)
QObjectList event_receivers