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();
}
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);

View File

@ -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);

View File

@ -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;

View File

@ -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<QPixmap>().isNull()) {
icon_ = QIcon(icon.value<QPixmap>());
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));

View File

@ -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;

View File

@ -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))

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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()) {

View File

@ -22,70 +22,135 @@
#include <mswmdm.h>
#include <mswmdm_i.c>
#include <QPixmap>
#include <QStringList>
#include <QtDebug>
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<QString, DeviceInfo> 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<QUrl> WmdmLister::MakeDeviceUrls(const QString& id) {

View File

@ -19,19 +19,23 @@
#include "devicelister.h"
struct IWMDMDevice;
struct IWMDeviceManager;
#include <QMap>
#include <QMutex>
#include <QPixmap>
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 <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