6 #include <QtCore/QStringList>
7 #include <QtCore/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 Q_CORE_EXPORT HINSTANCE qWinAppInst();
29 static QStringList drivesFromMask(quint32 driveBits)
32 #if 1 //a disk with multiple partitions removed
33 char driveName[] =
"A:/";
34 driveBits &= 0x3ffffff;
37 ret.append(QString::fromLatin1(driveName));
50 return ret << QString(c) +
":";
54 LRESULT CALLBACK dw_internal_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
56 if (message == WM_DEVICECHANGE) {
57 DEV_BROADCAST_HDR *lpdb = (DEV_BROADCAST_HDR *)lParam;
58 qDebug(
"Device type address: %#x", lpdb);
60 if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
61 qDebug(
"DBT_DEVTYP_VOLUME");
62 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
63 qDebug(
"DBT_DEVTYP_PORT");
64 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
65 qDebug(
"DBT_DEVTYP_DEVICEINTERFACE");
66 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
67 qDebug(
"DBT_DEVTYP_OEM");
69 qDebug(
"Unknow device type");
74 case DBT_DEVNODES_CHANGED:
75 qDebug(
"DBT_DEVNODES_CHANGED message received, no extended info.");
77 case DBT_QUERYCHANGECONFIG:
78 qDebug(
"DBT_QUERYCHANGECONFIG message received, no extended info.");
80 case DBT_CONFIGCHANGED:
81 qDebug(
"DBT_CONFIGCHANGED message received, no extended info.");
83 case DBT_CONFIGCHANGECANCELED:
84 qDebug(
"DBT_CONFIGCHANGECANCELED message received, no extended info.");
87 case DBT_DEVICEARRIVAL:
88 case DBT_DEVICEQUERYREMOVE:
89 case DBT_DEVICEQUERYREMOVEFAILED:
90 case DBT_DEVICEREMOVEPENDING:
91 case DBT_DEVICEREMOVECOMPLETE:
92 if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
93 DEV_BROADCAST_VOLUME *db_volume = (DEV_BROADCAST_VOLUME *)lpdb;
94 QStringList drives = drivesFromMask(db_volume->dbcv_unitmask);
100 QList<QDeviceChangeEvent *> events;
101 QString action_str(
"add");
103 if (wParam == DBT_DEVICEARRIVAL) {
104 }
else if (wParam == DBT_DEVICEQUERYREMOVE) {
105 }
else if (wParam == DBT_DEVICEQUERYREMOVEFAILED) {
106 }
else if (wParam == DBT_DEVICEREMOVEPENDING) {
107 }
else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
108 action_str =
"remove";
111 foreach (
const QString &drive, drives) {
112 if (db_volume->dbcv_flags & DBTF_MEDIA)
113 qDebug(
"Drive %c: Media has been removed.", drive.at(0).toLatin1());
114 else if (db_volume->dbcv_flags & DBTF_NET)
115 qDebug(
"Drive %c: Network share has been removed.", drive.at(0).toLatin1());
117 qDebug(
"Drive %c: Device has been removed.", drive.at(0).toLatin1());
125 QCoreApplication::postEvent(obj, event, Qt::HighEventPriority);
129 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
130 qDebug(
"DBT_DEVTYP_PORT");
131 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
133 qDebug(
"DBT_DEVTYP_DEVICEINTERFACE");
134 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_OEM) {
135 qDebug(
"DBT_DEVTYP_OEM");
136 }
else if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE) {
137 qDebug(
"DBT_DEVTYP_HANDLE");
140 case DBT_DEVICETYPESPECIFIC:
141 qDebug(
"DBT_DEVICETYPESPECIFIC message received, may contain an extended info.");
143 case DBT_CUSTOMEVENT:
144 qDebug(
"DBT_CUSTOMEVENT message received, contains an extended info.");
146 case DBT_USERDEFINED:
147 qDebug(
"WM_DEVICECHANGE user defined message received, can not handle.");
150 qWarning(
"WM_DEVICECHANGE message received, unhandled value %d.", wParam);
155 return DefWindowProc(hwnd, message, wParam, lParam);
158 static QString className()
160 return QLatin1String(
"QDeviceWatcherPrivateWin32_Internal_Widget") + QString::number(quintptr(dw_internal_proc));
163 static HWND dw_create_internal_window(
const void* userData)
165 QString className = ::className();
166 HINSTANCE hi = qWinAppInst();
170 wc.lpfnWndProc = dw_internal_proc;
176 wc.hbrBackground = 0;
177 wc.lpszMenuName =
nullptr;
181 HWND hwnd = CreateWindowW(wc.lpszClassName,
193 qWarning(
"QDeviceWatcherPrivate: Failed to create internal window: %d",
TTKStaticCast(
int, GetLastError()));
194 #if CONFIG_NOTIFICATION
196 DEV_BROADCAST_DEVICEINTERFACE NotificationFilter ;
197 ZeroMemory(&NotificationFilter,
sizeof(NotificationFilter)) ;
198 NotificationFilter.dbcc_size =
sizeof(DEV_BROADCAST_DEVICEINTERFACE);
199 NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
200 NotificationFilter.dbcc_classguid = InterfaceClassGuid;
203 hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
209 }
else if (userData) {
211 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)userData);
213 SetWindowLongW(hwnd, GWL_USERDATA, (LONG)userData);
216 #endif //CONFIG_NOTIFICATION
220 static void dw_destroy_internal_window(HWND hwnd)
225 #if CONFIG_NOTIFICATION
226 UnregisterDeviceNotification(hDevNotify);
228 UnregisterClassW(
TTKReinterpretCast(
const wchar_t *, className().utf16()), qWinAppInst());
241 hwnd = dw_create_internal_window(
this);
244 dw_destroy_internal_window(hwnd);
251 dw_destroy_internal_window(hwnd);
#define TTKStaticCast(x, y)
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