Solid

windevicemanager.h
1/*
2 SPDX-FileCopyrightText: 2013 Patrick von Reth <vonreth@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#ifndef WINDEVICEMANAGER_H
8#define WINDEVICEMANAGER_H
9
10#include <solid/devices/ifaces/devicemanager.h>
11
12#include <QDebug>
13#include <QSet>
14
15#include <qt_windows.h>
16#include <winioctl.h>
17
18inline QString qGetLastError(ulong errorNummber = GetLastError())
19{
20 LPVOID error = NULL;
21 size_t len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
22 NULL,
23 errorNummber,
24 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
25 (LPWSTR)&error,
26 0,
27 NULL);
28 QString out = QString::fromWCharArray((wchar_t *)error, (int)len).trimmed().append(QStringLiteral(" %1")).arg(errorNummber);
29 LocalFree(error);
30 return out;
31}
32
33namespace Solid
34{
35namespace Backends
36{
37namespace Win
38{
39class WinDeviceManager : public Solid::Ifaces::DeviceManager
40{
42public:
43 WinDeviceManager(QObject *parent = 0);
44 ~WinDeviceManager();
45
46 virtual QString udiPrefix() const;
47
48 virtual QSet<Solid::DeviceInterface::Type> supportedInterfaces() const;
49
50 virtual QStringList allDevices();
51
52 virtual QStringList devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type = Solid::DeviceInterface::Unknown);
53
54 virtual QObject *createDevice(const QString &udi);
55
56 static const WinDeviceManager *instance();
57
58 template<class INFO>
59 static INFO getDeviceInfo(const QString &devName, int code)
60 {
61 return getDeviceInfo<INFO, void *>(devName, code);
62 }
63
64 template<class INFO, class QUERY>
65 static INFO getDeviceInfo(const QString &devName, int code, QUERY *query = NULL)
66 {
67 INFO info;
68 ZeroMemory(&info, sizeof(INFO));
69 getDeviceInfoPrivate(devName, code, &info, sizeof(INFO), query);
70 return info;
71 }
72
73 template<class BUFFER_TYPE, class QUERY>
74 static void getDeviceInfo(const QString &devName, int code, BUFFER_TYPE *out, DWORD outSize, QUERY *query = NULL)
75 {
76 ZeroMemory(out, sizeof(BUFFER_TYPE) * outSize);
77 getDeviceInfoPrivate(devName, code, out, outSize, query);
78 }
79
80 static void deviceAction(const QString &devName, int code)
81 {
82 getDeviceInfoPrivate<void, void *>(devName, code, NULL, 0, NULL);
83 }
84
86 void powerChanged();
87
88private Q_SLOTS:
89 void updateDeviceList();
90 void slotDeviceAdded(const QSet<QString> &udi);
91 void slotDeviceRemoved(const QSet<QString> &udi);
92
93private:
94 friend class SolidWinEventFilter;
95
96 QSet<QString> m_devices;
97 QStringList m_devicesList;
98 QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
99
100 template<class INFO, class QUERY>
101 static void getDeviceInfoPrivate(const QString &devName, int code, INFO *info, DWORD size, QUERY *query = NULL)
102 {
103 Q_ASSERT(!devName.isNull());
104 wchar_t deviceNameBuffer[MAX_PATH];
105 QString dev = devName;
106 if (!dev.startsWith(QLatin1String("\\"))) {
107 dev = QLatin1String("\\\\?\\") + dev;
108 }
109 deviceNameBuffer[dev.toWCharArray(deviceNameBuffer)] = 0;
110 DWORD bytesReturned = 0;
111
112 ulong err = NO_ERROR;
113 HANDLE handle = ::CreateFileW(deviceNameBuffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
114 if (handle == INVALID_HANDLE_VALUE) {
115 err = GetLastError();
116 if (err == ERROR_ACCESS_DENIED) {
117 // we would need admin rights for GENERIC_READ on systenm drives and volumes
118 handle = ::CreateFileW(deviceNameBuffer, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
119 err = GetLastError();
120 }
121 if (handle == INVALID_HANDLE_VALUE) {
122 qWarning() << "Invalid Handle" << dev << "reason:" << qGetLastError(err) << "this should not happen.";
123 return;
124 }
125 }
126 if (::DeviceIoControl(handle, code, query, sizeof(QUERY), info, size, &bytesReturned, NULL)) {
127 ::CloseHandle(handle);
128 return;
129 }
130
131 if (handle == INVALID_HANDLE_VALUE) {
132 qWarning() << "Invalid Handle" << devName << "reason:" << qGetLastError() << "is probaply a subst path or more seriously there is bug!";
133 return;
134 }
135
136 err = GetLastError();
137 switch (err) {
138 case ERROR_NOT_READY:
139 // the drive is a cd drive with no disk
140 break;
141 case ERROR_INVALID_FUNCTION:
142 // in most cases this means that the device doesn't support this method, like temperature for some batteries
143 break;
144 default:
145 qWarning() << "Failed to query" << dev << "reason:" << qGetLastError(err);
146 // DebugBreak();
147 }
148 ::CloseHandle(handle);
149 }
150};
151
152}
153}
154}
155#endif // WINDEVICEMANAGER_H
Type
This enum type defines the type of device interface that a Device can have.
This class specifies the interface a backend will have to implement in order to be used in the system...
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
Q_SLOTSQ_SLOTS
QObject * parent() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
QString fromWCharArray(const wchar_t *string, qsizetype size)
bool isNull() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
qsizetype toWCharArray(wchar_t *array) const const
QString trimmed() const const
typedef HANDLE
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:01:49 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.