Solid

winblock.cpp
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#include "winblock.h"
8
9#include <QDebug>
10#include <QSettings>
11
12using namespace Solid::Backends::Win;
13
14#include <ntddcdrm.h>
15#include <ntddmmc.h>
16
17QMap<QString, QString> WinBlock::m_driveLetters = QMap<QString, QString>();
19QMap<QString, QString> WinBlock::m_virtualDrives = QMap<QString, QString>();
20
21WinBlock::WinBlock(WinDevice *device)
22 : WinInterface(device)
23 , m_major(-1)
24 , m_minor(-1)
25{
26 if (m_device->type() == Solid::DeviceInterface::StorageVolume) {
27 STORAGE_DEVICE_NUMBER info =
28 WinDeviceManager::getDeviceInfo<STORAGE_DEVICE_NUMBER>(driveLetterFromUdi(m_device->udi()), IOCTL_STORAGE_GET_DEVICE_NUMBER);
29 m_major = info.DeviceNumber;
30 m_minor = info.PartitionNumber;
31 } else if (m_device->type() == Solid::DeviceInterface::StorageDrive //
32 || m_device->type() == Solid::DeviceInterface::OpticalDrive //
33 || m_device->type() == Solid::DeviceInterface::OpticalDisc) {
34 m_major = m_device->udi().mid(m_device->udi().length() - 1).toInt();
35 } else {
36 qFatal("Not implemented device type %i", m_device->type());
37 }
38}
39
40WinBlock::~WinBlock()
41{
42}
43
44int WinBlock::deviceMajor() const
45{
46 Q_ASSERT(m_major != -1);
47 return m_major;
48}
49
50int WinBlock::deviceMinor() const
51{
52 return m_minor;
53}
54
55QString WinBlock::device() const
56{
57 return driveLetterFromUdi(m_device->udi());
58}
59
60QStringList WinBlock::drivesFromMask(const DWORD unitmask)
61{
62 QStringList result;
63 DWORD localUnitmask(unitmask);
64 for (int i = 0; i <= 25; ++i) {
65 if (0x01 == (localUnitmask & 0x1)) {
66 result << QString("%1:").arg((char)(i + 'A'));
67 }
68 localUnitmask >>= 1;
69 }
70 return result;
71}
72
73QSet<QString> WinBlock::getUdis()
74{
75 return updateUdiFromBitMask(GetLogicalDrives());
76}
77
78QString WinBlock::driveLetterFromUdi(const QString &udi)
79{
80 if (!m_driveLetters.contains(udi)) {
81 qWarning() << udi << "is not connected to a drive";
82 }
83 return m_driveLetters[udi];
84}
85
86QString WinBlock::udiFromDriveLetter(const QString &drive)
87{
88 QString out;
89 for (QMap<QString, QString>::const_iterator it = m_driveLetters.cbegin(); it != m_driveLetters.cend(); ++it) {
90 if (it.value() == drive) {
91 out = it.key();
92 break;
93 }
94 }
95 return out;
96}
97
98QString WinBlock::resolveVirtualDrive(const QString &drive)
99{
100 return m_virtualDrives[drive];
101}
102
103QSet<QString> WinBlock::updateUdiFromBitMask(const DWORD unitmask)
104{
105 const QStringList drives = drivesFromMask(unitmask);
107 wchar_t driveWCHAR[MAX_PATH];
108 wchar_t bufferOut[MAX_PATH];
109 QString dosPath;
110 for (const QString &drive : drives) {
111 QSet<QString> udis;
112 driveWCHAR[drive.toWCharArray(driveWCHAR)] = 0;
113 if (GetDriveType(driveWCHAR) == DRIVE_REMOTE) { // network drive
114 QSettings settings(QLatin1String("HKEY_CURRENT_USER\\Network\\") + drive.at(0), QSettings::NativeFormat);
115 QString path = settings.value("RemotePath").toString();
116 if (!path.isEmpty()) {
117 QString key = QLatin1String("/org/kde/solid/win/volume.virtual/") + drive.at(0);
118 m_virtualDrives[key] = path;
119 udis << key;
120 }
121
122 } else {
123 QueryDosDeviceW(driveWCHAR, bufferOut, MAX_PATH);
124 dosPath = QString::fromWCharArray(bufferOut);
125 if (dosPath.startsWith("\\??\\")) { // subst junction
126 dosPath = dosPath.mid(4);
127 QString key = QLatin1String("/org/kde/solid/win/volume.virtual/") + drive.at(0);
128 m_virtualDrives[key] = dosPath;
129 udis << key;
130 } else {
131 STORAGE_DEVICE_NUMBER info = WinDeviceManager::getDeviceInfo<STORAGE_DEVICE_NUMBER>(drive, IOCTL_STORAGE_GET_DEVICE_NUMBER);
132
133 switch (info.DeviceType) {
134 case FILE_DEVICE_DISK: {
135 udis << QString("/org/kde/solid/win/volume/disk#%1,partition#%2").arg(info.DeviceNumber).arg(info.PartitionNumber);
136 udis << QString("/org/kde/solid/win/storage/disk#%1").arg(info.DeviceNumber);
137 break;
138 }
139 case FILE_DEVICE_CD_ROM:
140 case FILE_DEVICE_DVD: {
141 udis << QString("/org/kde/solid/win/storage.cdrom/disk#%1").arg(info.DeviceNumber);
142 DISK_GEOMETRY_EX out = WinDeviceManager::getDeviceInfo<DISK_GEOMETRY_EX>(drive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX);
143 if (out.DiskSize.QuadPart != 0) {
144 udis << QString("/org/kde/solid/win/volume.cdrom/disk#%1").arg(info.DeviceNumber);
145 }
146 break;
147 }
148 default:
149 qDebug() << "unknown device" << drive << info.DeviceType << info.DeviceNumber << info.PartitionNumber;
150 }
151 }
152 }
153 m_driveUDIS[drive] = udis;
154 for (const QString &str : std::as_const(udis)) {
155 m_driveLetters[str] = drive;
156 }
157 list += udis;
158 }
159 return list;
160}
161
162QSet<QString> WinBlock::getFromBitMask(const DWORD unitmask)
163{
165 const QStringList drives = drivesFromMask(unitmask);
166 for (const QString &drive : drives) {
167 if (m_driveUDIS.contains(drive)) {
168 list += m_driveUDIS[drive];
169 } else {
170 // we have to update the cache
171 return updateUdiFromBitMask(unitmask);
172 }
173 }
174 return list;
175}
176
177#include "moc_winblock.cpp"
QString path(const QString &relativePath)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const_iterator cbegin() const const
const_iterator cend() const const
bool contains(const Key &key) const const
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
QString fromWCharArray(const wchar_t *string, qsizetype size)
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
qsizetype toWCharArray(wchar_t *array) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:12 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.