Semi-working WMDM device lister

This commit is contained in:
David Sansome 2010-08-15 23:26:04 +00:00
parent 164d4f6f6f
commit 78db71c02c
13 changed files with 182 additions and 60 deletions

View File

@ -91,10 +91,9 @@ QStringList DeviceKitLister::DeviceUniqueIDs() {
return device_data_.keys(); return device_data_.keys();
} }
QStringList DeviceKitLister::DeviceIcons(const QString &id) { QVariantList DeviceKitLister::DeviceIcons(const QString &id) {
QString path = LockAndGetDeviceInfo(id, &DeviceData::device_mount_paths)[0]; QString path = LockAndGetDeviceInfo(id, &DeviceData::device_mount_paths)[0];
QStringList guessed = DeviceLister::GuessIconForPath(path); return QVariantList()
return QStringList()
<< GuessIconForPath(path) << GuessIconForPath(path)
<< GuessIconForModel(DeviceManufacturer(id), DeviceModel(id)) << GuessIconForModel(DeviceManufacturer(id), DeviceModel(id))
<< LockAndGetDeviceInfo(id, &DeviceData::device_presentation_icon_name); << LockAndGetDeviceInfo(id, &DeviceData::device_presentation_icon_name);

View File

@ -36,7 +36,7 @@ public:
~DeviceKitLister(); ~DeviceKitLister();
QStringList DeviceUniqueIDs(); QStringList DeviceUniqueIDs();
QStringList DeviceIcons(const QString& id); QVariantList DeviceIcons(const QString& id);
QString DeviceManufacturer(const QString& id); QString DeviceManufacturer(const QString& id);
QString DeviceModel(const QString& id); QString DeviceModel(const QString& id);
quint64 DeviceCapacity(const QString& id); quint64 DeviceCapacity(const QString& id);

View File

@ -42,7 +42,7 @@ public:
// Query information about the devices that are available. Must be thread-safe. // Query information about the devices that are available. Must be thread-safe.
virtual QStringList DeviceUniqueIDs() = 0; virtual QStringList DeviceUniqueIDs() = 0;
virtual QStringList DeviceIcons(const QString& id) = 0; virtual QVariantList DeviceIcons(const QString& id) = 0;
virtual QString DeviceManufacturer(const QString& id) = 0; virtual QString DeviceManufacturer(const QString& id) = 0;
virtual QString DeviceModel(const QString& id) = 0; virtual QString DeviceModel(const QString& id) = 0;
virtual quint64 DeviceCapacity(const QString& id) = 0; virtual quint64 DeviceCapacity(const QString& id) = 0;

View File

@ -82,7 +82,14 @@ void DeviceManager::DeviceInfo::InitFromDb(const DeviceDatabaseBackend::Device &
database_id_ = dev.id_; database_id_ = dev.id_;
friendly_name_ = dev.friendly_name_; friendly_name_ = dev.friendly_name_;
size_ = dev.size_; size_ = dev.size_;
LoadIcon(dev.icon_name_.split(','), friendly_name_);
QStringList icon_names = dev.icon_name_.split(',');
QVariantList icons;
foreach (const QString& icon_name, icon_names) {
icons << icon_name;
}
LoadIcon(icons, friendly_name_);
QStringList unique_ids = dev.unique_id_.split(','); QStringList unique_ids = dev.unique_id_.split(',');
foreach (const QString& id, unique_ids) { foreach (const QString& id, unique_ids) {
@ -90,7 +97,7 @@ void DeviceManager::DeviceInfo::InitFromDb(const DeviceDatabaseBackend::Device &
} }
} }
void DeviceManager::DeviceInfo::LoadIcon(const QStringList& icons, const QString& name_hint) { void DeviceManager::DeviceInfo::LoadIcon(const QVariantList& icons, const QString& name_hint) {
if (icons.isEmpty()) { if (icons.isEmpty()) {
icon_name_ = "drive-removable-media-usb-pendrive"; icon_name_ = "drive-removable-media-usb-pendrive";
icon_ = IconLoader::Load(icon_name_); icon_ = IconLoader::Load(icon_name_);
@ -98,15 +105,20 @@ void DeviceManager::DeviceInfo::LoadIcon(const QStringList& icons, const QString
} }
// Try to load the icon with that exact name first // Try to load the icon with that exact name first
foreach (const QString& name, icons) { foreach (const QVariant& icon, icons) {
icon_ = IconLoader::Load(name); if (!icon.value<QPixmap>().isNull()) {
if (!icon_.isNull()) { icon_ = QIcon(icon.value<QPixmap>());
icon_name_ = name;
return; return;
} else {
icon_ = IconLoader::Load(icon.toString());
if (!icon_.isNull()) {
icon_name_ = icon.toString();
return;
}
} }
} }
QString hint = QString(icons.first() + name_hint).toLower(); QString hint = QString(icons.first().toString() + name_hint).toLower();
// If that failed than try to guess if it's a phone or ipod. Fall back on // If that failed than try to guess if it's a phone or ipod. Fall back on
// a usb memory stick icon. // a usb memory stick icon.
@ -581,7 +593,7 @@ void DeviceManager::SetDeviceIdentity(int row, const QString &friendly_name,
const QString &icon_name) { const QString &icon_name) {
DeviceInfo& info = devices_[row]; DeviceInfo& info = devices_[row];
info.friendly_name_ = friendly_name; info.friendly_name_ = friendly_name;
info.LoadIcon(QStringList() << icon_name, friendly_name); info.LoadIcon(QVariantList() << icon_name, friendly_name);
emit dataChanged(index(row, 0), index(row, 0)); emit dataChanged(index(row, 0), index(row, 0));

View File

@ -132,7 +132,7 @@ private:
DeviceDatabaseBackend::Device SaveToDb() const; DeviceDatabaseBackend::Device SaveToDb() const;
// Tries to load a good icon for the device. Sets icon_name_ and icon_. // Tries to load a good icon for the device. Sets icon_name_ and icon_.
void LoadIcon(const QStringList& icons, const QString& name_hint); void LoadIcon(const QVariantList& icons, const QString& name_hint);
// Gets the best backend available (the one with the highest priority) // Gets the best backend available (the one with the highest priority)
const Backend* BestBackend() const; const Backend* BestBackend() const;

View File

@ -69,8 +69,8 @@ QStringList GioLister::DeviceUniqueIDs() {
return mounts_.keys(); return mounts_.keys();
} }
QStringList GioLister::DeviceIcons(const QString &id) { QVariantList GioLister::DeviceIcons(const QString &id) {
QStringList ret; QVariantList ret;
QString path = LockAndGetMountInfo(id, &MountInfo::mount_path); QString path = LockAndGetMountInfo(id, &MountInfo::mount_path);
ret << DeviceLister::GuessIconForPath(path) ret << DeviceLister::GuessIconForPath(path)
<< DeviceLister::GuessIconForModel(DeviceManufacturer(id), DeviceModel(id)) << DeviceLister::GuessIconForModel(DeviceManufacturer(id), DeviceModel(id))

View File

@ -34,7 +34,7 @@ public:
int priority() const { return 50; } int priority() const { return 50; }
QStringList DeviceUniqueIDs(); QStringList DeviceUniqueIDs();
QStringList DeviceIcons(const QString& id); QVariantList DeviceIcons(const QString& id);
QString DeviceManufacturer(const QString& id); QString DeviceManufacturer(const QString& id);
QString DeviceModel(const QString& id); QString DeviceModel(const QString& id);
quint64 DeviceCapacity(const QString& id); quint64 DeviceCapacity(const QString& id);

View File

@ -64,8 +64,8 @@ QStringList iLister::DeviceUniqueIDs() {
return devices_.keys(); return devices_.keys();
} }
QStringList iLister::DeviceIcons(const QString& id) { QVariantList iLister::DeviceIcons(const QString& id) {
return QStringList() << "ipodtouchicon"; return QVariantList() << "ipodtouchicon";
} }
QString iLister::DeviceManufacturer(const QString& id) { QString iLister::DeviceManufacturer(const QString& id) {

View File

@ -16,7 +16,7 @@ class iLister : public DeviceLister {
int priority() const { return 120; } int priority() const { return 120; }
virtual QStringList DeviceUniqueIDs(); virtual QStringList DeviceUniqueIDs();
virtual QStringList DeviceIcons(const QString& id); virtual QVariantList DeviceIcons(const QString& id);
virtual QString DeviceManufacturer(const QString& id); virtual QString DeviceManufacturer(const QString& id);
virtual QString DeviceModel(const QString& id); virtual QString DeviceModel(const QString& id);
virtual quint64 DeviceCapacity(const QString& id); virtual quint64 DeviceCapacity(const QString& id);

View File

@ -16,7 +16,7 @@ class MacDeviceLister : public DeviceLister {
~MacDeviceLister(); ~MacDeviceLister();
virtual QStringList DeviceUniqueIDs(); virtual QStringList DeviceUniqueIDs();
virtual QStringList DeviceIcons(const QString& id); virtual QVariantList DeviceIcons(const QString& id);
virtual QString DeviceManufacturer(const QString& id); virtual QString DeviceManufacturer(const QString& id);
virtual QString DeviceModel(const QString& id); virtual QString DeviceModel(const QString& id);
virtual quint64 DeviceCapacity(const QString& id); virtual quint64 DeviceCapacity(const QString& id);

View File

@ -260,7 +260,7 @@ QStringList MacDeviceLister::DeviceUniqueIDs() {
return current_devices_.keys(); return current_devices_.keys();
} }
QStringList MacDeviceLister::DeviceIcons(const QString& serial) { QVariantList MacDeviceLister::DeviceIcons(const QString& serial) {
QString bsd_name = current_devices_[serial]; QString bsd_name = current_devices_[serial];
DASessionRef session = DASessionCreate(kCFAllocatorDefault); DASessionRef session = DASessionCreate(kCFAllocatorDefault);
DADiskRef disk = DADiskCreateFromBSDName( DADiskRef disk = DADiskCreateFromBSDName(
@ -279,7 +279,7 @@ QStringList MacDeviceLister::DeviceIcons(const QString& serial) {
CFRelease(disk); CFRelease(disk);
CFRelease(session); CFRelease(session);
QStringList ret; QVariantList ret;
ret << GuessIconForPath(path); ret << GuessIconForPath(path);
ret << GuessIconForModel(DeviceManufacturer(serial), DeviceModel(serial)); ret << GuessIconForModel(DeviceManufacturer(serial), DeviceModel(serial));
if (!icon.isEmpty()) { if (!icon.isEmpty()) {

View File

@ -22,70 +22,135 @@
#include <mswmdm.h> #include <mswmdm.h>
#include <mswmdm_i.c> #include <mswmdm_i.c>
#include <QPixmap>
#include <QStringList> #include <QStringList>
#include <QtDebug> #include <QtDebug>
BYTE abPVK[] = {0x00}; BYTE abPVK[] = {0x00};
BYTE abCert[] = {0x00}; BYTE abCert[] = {0x00};
QString WmdmLister::DeviceInfo::unique_id() const {
// TODO: Serial number?
return name_;
}
WmdmLister::WmdmLister() WmdmLister::WmdmLister()
: device_manager_(NULL)
{ {
} }
void WmdmLister::Init() { void WmdmLister::Init() {
qDebug() << "Creating IPortableDeviceManager"; // Initialise COM
CoInitialize(0);
qDebug() << "CoInitialize says" << CoInitialize(0);
// Authenticate with WMDM
IComponentAuthenticate* auth; IComponentAuthenticate* auth;
HRESULT result = CoCreateInstance( if (CoCreateInstance(CLSID_MediaDevMgr, NULL, CLSCTX_ALL,
CLSID_MediaDevMgr, NULL, CLSCTX_ALL, IID_IComponentAuthenticate, (void **)&auth); IID_IComponentAuthenticate, (void**) &auth)) {
qDebug() << "Auth" << result << auth; qWarning() << "Error creating the IComponentAuthenticate interface";
return;
}
SacHandle sac = CSecureChannelClient_New(); SacHandle sac = CSecureChannelClient_New();
qDebug() << "SAC is" << sac; if (CSecureChannelClient_SetCertificate(
sac, SAC_CERT_V1, abCert, sizeof(abCert), abPVK, sizeof(abPVK))) {
result = CSecureChannelClient_SetCertificate(sac, qWarning() << "Error setting SAC certificate";
SAC_CERT_V1, return;
abCert, sizeof(abCert), }
abPVK, sizeof(abPVK));
qDebug() << "SetCertificate" << result << abCert << sizeof(abCert);
CSecureChannelClient_SetInterface(sac, auth); CSecureChannelClient_SetInterface(sac, auth);
if (CSecureChannelClient_Authenticate(sac, SAC_PROTOCOL_V1)) {
qWarning() << "Error authenticating with SAC";
return;
}
DWORD* prot; // Create the device manager
DWORD prot_count; if (auth->QueryInterface(IID_IWMDeviceManager, (void**)&device_manager_)) {
result = auth->SACGetProtocols(&prot, &prot_count); qWarning() << "Error creating WMDM device manager";
qDebug() << "SACGetProtocols" << result << prot_count; return;
qDebug() << "Prot is" << prot; }
qDebug() << "Prot is" << prot[0];
result = CSecureChannelClient_Authenticate(sac, prot[0]); // Fetch the inital list of devices
qDebug() << "Authenticate" << result; IWMDMEnumDevice* device_it = NULL;
if (device_manager_->EnumDevices(&device_it)) {
qWarning() << "Error querying WMDM devices";
return;
}
CoTaskMemFree(prot); // Iterate through the devices
QMap<QString, DeviceInfo> devices;
forever {
IWMDMDevice* device = NULL;
ULONG fetched = 0;
if (device_it->Next(1, &device, &fetched) || fetched != 1)
break;
IWMDeviceManager* device_manager; DeviceInfo info = ReadDeviceInfo(device);
result = auth->QueryInterface(IID_IWMDeviceManager, (void**)device_manager); if (info.is_suitable_)
qDebug() << "Manager" << result << device_manager; devices[info.unique_id()] = info;
CoUninitialize(); device->Release();
}
device_it->Release();
// Update the internal cache
{
QMutexLocker l(&mutex_);
devices_ = devices;
}
// Notify about the changes
foreach (const QString& id, devices.keys()) {
emit DeviceAdded(id);
}
}
WmdmLister::DeviceInfo WmdmLister::ReadDeviceInfo(IWMDMDevice* device) {
DeviceInfo ret;
// Get text strings
wchar_t buf[MAX_PATH];
device->GetName(buf, MAX_PATH);
ret.name_ = QString::fromWCharArray(buf);
device->GetManufacturer(buf, MAX_PATH);
ret.manufacturer_ = QString::fromWCharArray(buf);
// Get the type and check whether it has storage
DWORD type = 0;
device->GetType(&type);
if (type & WMDM_DEVICE_TYPE_STORAGE)
ret.is_suitable_ = true;
// Get the icon
HICON icon;
device->GetDeviceIcon((ULONG*)&icon);
ret.icon_ = QPixmap::fromWinHICON(icon);
DestroyIcon(icon);
return ret;
} }
QStringList WmdmLister::DeviceUniqueIDs() { QStringList WmdmLister::DeviceUniqueIDs() {
return QStringList(); QMutexLocker l(&mutex_);
return devices_.keys();
} }
QStringList WmdmLister::DeviceIcons(const QString& id) { QVariantList WmdmLister::DeviceIcons(const QString& id) {
return QStringList(); QPixmap pixmap = LockAndGetDeviceInfo(id, &DeviceInfo::icon_);
if (pixmap.isNull())
return QVariantList();
return QVariantList() << pixmap;
} }
QString WmdmLister::DeviceManufacturer(const QString& id) { QString WmdmLister::DeviceManufacturer(const QString& id) {
return QString(); return LockAndGetDeviceInfo(id, &DeviceInfo::manufacturer_);
} }
QString WmdmLister::DeviceModel(const QString& id) { QString WmdmLister::DeviceModel(const QString& id) {
return QString(); return LockAndGetDeviceInfo(id, &DeviceInfo::name_);
} }
quint64 WmdmLister::DeviceCapacity(const QString& id) { quint64 WmdmLister::DeviceCapacity(const QString& id) {
@ -101,7 +166,15 @@ QVariantMap WmdmLister::DeviceHardwareInfo(const QString& id) {
} }
QString WmdmLister::MakeFriendlyName(const QString& id) { QString WmdmLister::MakeFriendlyName(const QString& id) {
return QString(); QMutexLocker l(&mutex_);
if (!devices_.contains(id))
return QString();
const DeviceInfo& info = devices_[id];
if (info.manufacturer_.isEmpty() || info.manufacturer_ == "Unknown")
return info.name_;
return info.manufacturer_ + " " + info.name_;
} }
QList<QUrl> WmdmLister::MakeDeviceUrls(const QString& id) { QList<QUrl> WmdmLister::MakeDeviceUrls(const QString& id) {

View File

@ -19,19 +19,23 @@
#include "devicelister.h" #include "devicelister.h"
struct IWMDMDevice;
struct IWMDeviceManager;
#include <QMap>
#include <QMutex>
#include <QPixmap>
class WmdmLister : public DeviceLister { class WmdmLister : public DeviceLister {
Q_OBJECT Q_OBJECT
public: public:
WmdmLister(); WmdmLister();
static uchar* kDRMCert;
static uchar* kDRMPrivateKey;
virtual void Init(); virtual void Init();
virtual QStringList DeviceUniqueIDs(); virtual QStringList DeviceUniqueIDs();
virtual QStringList DeviceIcons(const QString& id); virtual QVariantList DeviceIcons(const QString& id);
virtual QString DeviceManufacturer(const QString& id); virtual QString DeviceManufacturer(const QString& id);
virtual QString DeviceModel(const QString& id); virtual QString DeviceModel(const QString& id);
virtual quint64 DeviceCapacity(const QString& id); virtual quint64 DeviceCapacity(const QString& id);
@ -42,7 +46,41 @@ public:
virtual void UnmountDevice(const QString& id); virtual void UnmountDevice(const QString& id);
public slots: public slots:
virtual void UpdateDeviceFreeSpace(const QString& id); virtual void UpdateDeviceFreeSpace(const QString& id);
private:
struct DeviceInfo {
DeviceInfo() : is_suitable_(false) {}
QString unique_id() const;
bool is_suitable_;
QString name_;
QString manufacturer_;
QPixmap icon_;
};
DeviceInfo ReadDeviceInfo(IWMDMDevice* device);
template <typename T>
T LockAndGetDeviceInfo(const QString& id, T DeviceInfo::*field);
private:
IWMDeviceManager* device_manager_;
QMutex mutex_;
QMap<QString, DeviceInfo> devices_;
}; };
template <typename T>
T WmdmLister::LockAndGetDeviceInfo(const QString& id, T DeviceInfo::*field) {
QMutexLocker l(&mutex_);
if (!devices_.contains(id))
return T();
return devices_[id].*field;
}
#endif // WMDMLISTER_H #endif // WMDMLISTER_H