From 78db71c02c67b3c4fba801b7f4218ae87a9ebed4 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 15 Aug 2010 23:26:04 +0000 Subject: [PATCH] Semi-working WMDM device lister --- src/devices/devicekitlister.cpp | 5 +- src/devices/devicekitlister.h | 2 +- src/devices/devicelister.h | 2 +- src/devices/devicemanager.cpp | 28 +++++-- src/devices/devicemanager.h | 2 +- src/devices/giolister.cpp | 4 +- src/devices/giolister.h | 2 +- src/devices/ilister.cpp | 4 +- src/devices/ilister.h | 2 +- src/devices/macdevicelister.h | 2 +- src/devices/macdevicelister.mm | 4 +- src/devices/wmdmlister.cpp | 137 ++++++++++++++++++++++++-------- src/devices/wmdmlister.h | 48 +++++++++-- 13 files changed, 182 insertions(+), 60 deletions(-) diff --git a/src/devices/devicekitlister.cpp b/src/devices/devicekitlister.cpp index b4d16d582..0e3abb004 100644 --- a/src/devices/devicekitlister.cpp +++ b/src/devices/devicekitlister.cpp @@ -91,10 +91,9 @@ QStringList DeviceKitLister::DeviceUniqueIDs() { 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]; - QStringList guessed = DeviceLister::GuessIconForPath(path); - return QStringList() + return QVariantList() << GuessIconForPath(path) << GuessIconForModel(DeviceManufacturer(id), DeviceModel(id)) << LockAndGetDeviceInfo(id, &DeviceData::device_presentation_icon_name); diff --git a/src/devices/devicekitlister.h b/src/devices/devicekitlister.h index b11decbc5..005cc4fc8 100644 --- a/src/devices/devicekitlister.h +++ b/src/devices/devicekitlister.h @@ -36,7 +36,7 @@ public: ~DeviceKitLister(); QStringList DeviceUniqueIDs(); - QStringList DeviceIcons(const QString& id); + QVariantList DeviceIcons(const QString& id); QString DeviceManufacturer(const QString& id); QString DeviceModel(const QString& id); quint64 DeviceCapacity(const QString& id); diff --git a/src/devices/devicelister.h b/src/devices/devicelister.h index 10078a2bc..a821d10ab 100644 --- a/src/devices/devicelister.h +++ b/src/devices/devicelister.h @@ -42,7 +42,7 @@ public: // Query information about the devices that are available. Must be thread-safe. 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 DeviceModel(const QString& id) = 0; virtual quint64 DeviceCapacity(const QString& id) = 0; diff --git a/src/devices/devicemanager.cpp b/src/devices/devicemanager.cpp index d5888ff94..df822d38e 100644 --- a/src/devices/devicemanager.cpp +++ b/src/devices/devicemanager.cpp @@ -82,7 +82,14 @@ void DeviceManager::DeviceInfo::InitFromDb(const DeviceDatabaseBackend::Device & database_id_ = dev.id_; friendly_name_ = dev.friendly_name_; 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(','); 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()) { icon_name_ = "drive-removable-media-usb-pendrive"; 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 - foreach (const QString& name, icons) { - icon_ = IconLoader::Load(name); - if (!icon_.isNull()) { - icon_name_ = name; + foreach (const QVariant& icon, icons) { + if (!icon.value().isNull()) { + icon_ = QIcon(icon.value()); 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 // a usb memory stick icon. @@ -581,7 +593,7 @@ void DeviceManager::SetDeviceIdentity(int row, const QString &friendly_name, const QString &icon_name) { DeviceInfo& info = devices_[row]; 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)); diff --git a/src/devices/devicemanager.h b/src/devices/devicemanager.h index 1f260962e..1c905ec53 100644 --- a/src/devices/devicemanager.h +++ b/src/devices/devicemanager.h @@ -132,7 +132,7 @@ private: DeviceDatabaseBackend::Device SaveToDb() const; // 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) const Backend* BestBackend() const; diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp index 4e13f5bab..8c1ed5ea6 100644 --- a/src/devices/giolister.cpp +++ b/src/devices/giolister.cpp @@ -69,8 +69,8 @@ QStringList GioLister::DeviceUniqueIDs() { return mounts_.keys(); } -QStringList GioLister::DeviceIcons(const QString &id) { - QStringList ret; +QVariantList GioLister::DeviceIcons(const QString &id) { + QVariantList ret; QString path = LockAndGetMountInfo(id, &MountInfo::mount_path); ret << DeviceLister::GuessIconForPath(path) << DeviceLister::GuessIconForModel(DeviceManufacturer(id), DeviceModel(id)) diff --git a/src/devices/giolister.h b/src/devices/giolister.h index 99e62ac33..6f2572cc4 100644 --- a/src/devices/giolister.h +++ b/src/devices/giolister.h @@ -34,7 +34,7 @@ public: int priority() const { return 50; } QStringList DeviceUniqueIDs(); - QStringList DeviceIcons(const QString& id); + QVariantList DeviceIcons(const QString& id); QString DeviceManufacturer(const QString& id); QString DeviceModel(const QString& id); quint64 DeviceCapacity(const QString& id); diff --git a/src/devices/ilister.cpp b/src/devices/ilister.cpp index 38db1dc34..6c4323eff 100644 --- a/src/devices/ilister.cpp +++ b/src/devices/ilister.cpp @@ -64,8 +64,8 @@ QStringList iLister::DeviceUniqueIDs() { return devices_.keys(); } -QStringList iLister::DeviceIcons(const QString& id) { - return QStringList() << "ipodtouchicon"; +QVariantList iLister::DeviceIcons(const QString& id) { + return QVariantList() << "ipodtouchicon"; } QString iLister::DeviceManufacturer(const QString& id) { diff --git a/src/devices/ilister.h b/src/devices/ilister.h index bcda33ab8..939f0ca40 100644 --- a/src/devices/ilister.h +++ b/src/devices/ilister.h @@ -16,7 +16,7 @@ class iLister : public DeviceLister { int priority() const { return 120; } virtual QStringList DeviceUniqueIDs(); - virtual QStringList DeviceIcons(const QString& id); + virtual QVariantList DeviceIcons(const QString& id); virtual QString DeviceManufacturer(const QString& id); virtual QString DeviceModel(const QString& id); virtual quint64 DeviceCapacity(const QString& id); diff --git a/src/devices/macdevicelister.h b/src/devices/macdevicelister.h index a72b06db0..db111564a 100644 --- a/src/devices/macdevicelister.h +++ b/src/devices/macdevicelister.h @@ -16,7 +16,7 @@ class MacDeviceLister : public DeviceLister { ~MacDeviceLister(); virtual QStringList DeviceUniqueIDs(); - virtual QStringList DeviceIcons(const QString& id); + virtual QVariantList DeviceIcons(const QString& id); virtual QString DeviceManufacturer(const QString& id); virtual QString DeviceModel(const QString& id); virtual quint64 DeviceCapacity(const QString& id); diff --git a/src/devices/macdevicelister.mm b/src/devices/macdevicelister.mm index 2fddde203..7e0c332ff 100644 --- a/src/devices/macdevicelister.mm +++ b/src/devices/macdevicelister.mm @@ -260,7 +260,7 @@ QStringList MacDeviceLister::DeviceUniqueIDs() { return current_devices_.keys(); } -QStringList MacDeviceLister::DeviceIcons(const QString& serial) { +QVariantList MacDeviceLister::DeviceIcons(const QString& serial) { QString bsd_name = current_devices_[serial]; DASessionRef session = DASessionCreate(kCFAllocatorDefault); DADiskRef disk = DADiskCreateFromBSDName( @@ -279,7 +279,7 @@ QStringList MacDeviceLister::DeviceIcons(const QString& serial) { CFRelease(disk); CFRelease(session); - QStringList ret; + QVariantList ret; ret << GuessIconForPath(path); ret << GuessIconForModel(DeviceManufacturer(serial), DeviceModel(serial)); if (!icon.isEmpty()) { diff --git a/src/devices/wmdmlister.cpp b/src/devices/wmdmlister.cpp index f623b67df..278f450f1 100644 --- a/src/devices/wmdmlister.cpp +++ b/src/devices/wmdmlister.cpp @@ -22,70 +22,135 @@ #include #include +#include #include #include BYTE abPVK[] = {0x00}; BYTE abCert[] = {0x00}; +QString WmdmLister::DeviceInfo::unique_id() const { + // TODO: Serial number? + return name_; +} + WmdmLister::WmdmLister() + : device_manager_(NULL) { } void WmdmLister::Init() { - qDebug() << "Creating IPortableDeviceManager"; - - qDebug() << "CoInitialize says" << CoInitialize(0); + // Initialise COM + CoInitialize(0); + // Authenticate with WMDM IComponentAuthenticate* auth; - HRESULT result = CoCreateInstance( - CLSID_MediaDevMgr, NULL, CLSCTX_ALL, IID_IComponentAuthenticate, (void **)&auth); - qDebug() << "Auth" << result << auth; + if (CoCreateInstance(CLSID_MediaDevMgr, NULL, CLSCTX_ALL, + IID_IComponentAuthenticate, (void**) &auth)) { + qWarning() << "Error creating the IComponentAuthenticate interface"; + return; + } SacHandle sac = CSecureChannelClient_New(); - qDebug() << "SAC is" << sac; - - result = CSecureChannelClient_SetCertificate(sac, - SAC_CERT_V1, - abCert, sizeof(abCert), - abPVK, sizeof(abPVK)); - qDebug() << "SetCertificate" << result << abCert << sizeof(abCert); + if (CSecureChannelClient_SetCertificate( + sac, SAC_CERT_V1, abCert, sizeof(abCert), abPVK, sizeof(abPVK))) { + qWarning() << "Error setting SAC certificate"; + return; + } CSecureChannelClient_SetInterface(sac, auth); + if (CSecureChannelClient_Authenticate(sac, SAC_PROTOCOL_V1)) { + qWarning() << "Error authenticating with SAC"; + return; + } - DWORD* prot; - DWORD prot_count; - result = auth->SACGetProtocols(&prot, &prot_count); - qDebug() << "SACGetProtocols" << result << prot_count; - qDebug() << "Prot is" << prot; - qDebug() << "Prot is" << prot[0]; + // Create the device manager + if (auth->QueryInterface(IID_IWMDeviceManager, (void**)&device_manager_)) { + qWarning() << "Error creating WMDM device manager"; + return; + } - result = CSecureChannelClient_Authenticate(sac, prot[0]); - qDebug() << "Authenticate" << result; + // Fetch the inital list of devices + IWMDMEnumDevice* device_it = NULL; + if (device_manager_->EnumDevices(&device_it)) { + qWarning() << "Error querying WMDM devices"; + return; + } - CoTaskMemFree(prot); + // Iterate through the devices + QMap devices; + forever { + IWMDMDevice* device = NULL; + ULONG fetched = 0; + if (device_it->Next(1, &device, &fetched) || fetched != 1) + break; - IWMDeviceManager* device_manager; - result = auth->QueryInterface(IID_IWMDeviceManager, (void**)device_manager); - qDebug() << "Manager" << result << device_manager; + DeviceInfo info = ReadDeviceInfo(device); + if (info.is_suitable_) + 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() { - return QStringList(); + QMutexLocker l(&mutex_); + return devices_.keys(); } -QStringList WmdmLister::DeviceIcons(const QString& id) { - return QStringList(); +QVariantList WmdmLister::DeviceIcons(const QString& id) { + QPixmap pixmap = LockAndGetDeviceInfo(id, &DeviceInfo::icon_); + + if (pixmap.isNull()) + return QVariantList(); + return QVariantList() << pixmap; } QString WmdmLister::DeviceManufacturer(const QString& id) { - return QString(); + return LockAndGetDeviceInfo(id, &DeviceInfo::manufacturer_); } QString WmdmLister::DeviceModel(const QString& id) { - return QString(); + return LockAndGetDeviceInfo(id, &DeviceInfo::name_); } quint64 WmdmLister::DeviceCapacity(const QString& id) { @@ -101,7 +166,15 @@ QVariantMap WmdmLister::DeviceHardwareInfo(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 WmdmLister::MakeDeviceUrls(const QString& id) { diff --git a/src/devices/wmdmlister.h b/src/devices/wmdmlister.h index f5b678a25..f24a8f949 100644 --- a/src/devices/wmdmlister.h +++ b/src/devices/wmdmlister.h @@ -19,19 +19,23 @@ #include "devicelister.h" +struct IWMDMDevice; +struct IWMDeviceManager; + +#include +#include +#include + class WmdmLister : public DeviceLister { Q_OBJECT public: WmdmLister(); - static uchar* kDRMCert; - static uchar* kDRMPrivateKey; - virtual void Init(); virtual QStringList DeviceUniqueIDs(); - virtual QStringList DeviceIcons(const QString& id); + virtual QVariantList DeviceIcons(const QString& id); virtual QString DeviceManufacturer(const QString& id); virtual QString DeviceModel(const QString& id); virtual quint64 DeviceCapacity(const QString& id); @@ -42,7 +46,41 @@ public: virtual void UnmountDevice(const QString& id); 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 + T LockAndGetDeviceInfo(const QString& id, T DeviceInfo::*field); + +private: + IWMDeviceManager* device_manager_; + + QMutex mutex_; + QMap devices_; }; +template +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