--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qtmobility/tests/auto/support/support_win.cpp Fri Apr 16 15:51:22 2010 +0300
@@ -0,0 +1,1464 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "support.h"
+#include <qmessageaccountid.h>
+#include <qmessagefolderid.h>
+#include <qmessageid.h>
+#include <qmessage_p.h>
+#include <qmessagemanager.h>
+#include <QDataStream>
+#include <QFile>
+#include <QVector>
+#include <QDebug>
+
+#include <mapix.h>
+#include <Mapidefs.h>
+#include <Mapitags.h>
+#include <MAPIUtil.h>
+#ifdef _WIN32_WCE
+#include <cemapi.h>
+#endif
+
+// Missing definitions
+#ifndef PR_PST_CONFIG_FLAGS
+#define PR_PST_CONFIG_FLAGS PROP_TAG( PT_LONG, 0x6770 )
+#endif
+#ifndef PST_CONFIG_UNICODE
+#define PST_CONFIG_UNICODE 0x80000000
+#endif
+#ifndef PR_PST_PATH_A
+#define PR_PST_PATH_A PROP_TAG( PT_STRING8, 0x6700 )
+#endif
+
+namespace {
+
+class Lptstr : public QVector<TCHAR>
+{
+public:
+ Lptstr(int length) : QVector<TCHAR>(length){}
+ operator TCHAR* (){ return QVector<TCHAR>::data(); }
+};
+
+Lptstr LptstrFromQString(const QString &src)
+{
+ uint length(src.length());
+ Lptstr dst(length+1);
+
+ const quint16 *data = src.utf16();
+ const quint16 *it = data, *end = data + length;
+ TCHAR *oit = dst;
+ for ( ; it != end; ++it, ++oit) {
+ *oit = static_cast<TCHAR>(*it);
+ }
+ *oit = TCHAR('\0');
+ return dst;
+}
+
+QString QStringFromLptstr(LPCTSTR data)
+{
+ if (!data)
+ return QString();
+
+ return QString::fromUtf16(reinterpret_cast<const quint16*>(data));
+}
+
+class QueryAllRows
+{
+ static const int BatchSize = 20;
+public:
+ QueryAllRows(LPMAPITABLE ptable,
+ LPSPropTagArray ptaga,
+ LPSRestriction pres,
+ LPSSortOrderSet psos,
+ bool setPosition = true);
+ ~QueryAllRows();
+
+ bool query();
+ LPSRowSet rows() const;
+ QMessageManager::Error error() const;
+
+private:
+ LPMAPITABLE m_table;
+ LPSPropTagArray m_tagArray;
+ LPSRestriction m_restriction;
+ LPSSortOrderSet m_sortOrderSet;
+ LPSRowSet m_rows;
+ QMessageManager::Error m_error;
+};
+
+QueryAllRows::QueryAllRows(LPMAPITABLE ptable,
+ LPSPropTagArray ptaga,
+ LPSRestriction pres,
+ LPSSortOrderSet psos,
+ bool setPosition)
+ :
+ m_table(ptable),
+ m_tagArray(ptaga),
+ m_restriction(pres),
+ m_sortOrderSet(psos),
+ m_rows(0),
+ m_error(QMessageManager::NoError)
+{
+#ifndef _WIN32_WCE
+ const ULONG options(TBL_BATCH);
+#else
+ const ULONG options(0);
+#endif
+
+ bool initFailed = false;
+
+ initFailed |= FAILED(m_table->SetColumns(m_tagArray, options));
+
+ if(m_restriction)
+ initFailed |= FAILED(m_table->Restrict(m_restriction, options));
+
+ if(m_sortOrderSet)
+ initFailed |= FAILED(m_table->SortTable(m_sortOrderSet, options));
+
+ if(setPosition)
+ initFailed |= FAILED(m_table->SeekRow(BOOKMARK_BEGINNING, 0, NULL));
+
+ if(initFailed) m_error = QMessageManager::ContentInaccessible;
+}
+
+QueryAllRows::~QueryAllRows()
+{
+ FreeProws(m_rows);
+ m_rows = 0;
+}
+
+bool QueryAllRows::query()
+{
+ if(m_error != QMessageManager::NoError)
+ return false;
+
+ FreeProws(m_rows);
+ m_rows = 0;
+ m_error = QMessageManager::NoError;
+
+ bool failed = FAILED(m_table->QueryRows( QueryAllRows::BatchSize, NULL, &m_rows));
+
+ if(failed)
+ m_error = QMessageManager::ContentInaccessible;
+
+ if(failed || m_rows && !m_rows->cRows) return false;
+
+ return true;
+}
+
+LPSRowSet QueryAllRows::rows() const
+{
+ return m_rows;
+}
+
+QMessageManager::Error QueryAllRows::error() const
+{
+ return m_error;
+}
+
+#ifndef _WIN32_WCE
+GUID GuidPublicStrings = { 0x00020329, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
+#else
+GUID GuidPSMAPI = { 0x00020328, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
+#endif
+
+void doInit()
+{
+ static QMessageManager manager;
+ Q_UNUSED(manager)
+}
+
+QByteArray binaryResult(const SPropValue &prop)
+{
+ return QByteArray(reinterpret_cast<const char*>(prop.Value.bin.lpb), prop.Value.bin.cb);
+}
+
+#ifndef _WIN32_WCE
+IProfAdmin *openProfileAdmin()
+{
+ IProfAdmin *profAdmin(0);
+ HRESULT rv = MAPIAdminProfiles(0, &profAdmin);
+ if (HR_FAILED(rv)) {
+ qWarning() << "openProfileAdmin: MAPIAdminProfiles failed";
+ }
+
+ return profAdmin;
+}
+
+IMsgServiceAdmin *openServiceAdmin(const QByteArray &profileName, IProfAdmin *profAdmin)
+{
+ IMsgServiceAdmin *svcAdmin(0);
+
+ HRESULT rv = profAdmin->AdminServices(reinterpret_cast<LPTSTR>(const_cast<char*>(profileName.data())), 0, 0, 0, &svcAdmin);
+ if (HR_FAILED(rv)) {
+ qWarning() << "openServiceAdmin: AdminServices failed";
+ }
+
+ return svcAdmin;
+}
+
+typedef QPair<QByteArray, bool> ProfileDetail;
+
+QList<ProfileDetail> profileDetails(LPPROFADMIN profAdmin)
+{
+ QList<ProfileDetail> result;
+
+ LPMAPITABLE profileTable(0);
+ HRESULT rv = profAdmin->GetProfileTable(0, &profileTable);
+ if (HR_SUCCEEDED(rv)) {
+
+ SizedSPropTagArray(2, cols) = {2, {PR_DISPLAY_NAME_A, PR_DEFAULT_PROFILE}};
+
+ QueryAllRows qar(profileTable, reinterpret_cast<LPSPropTagArray>(&cols), NULL, NULL);
+ while(qar.query()) {
+ for (uint n = 0; n < qar.rows()->cRows; ++n) {
+ if (qar.rows()->aRow[n].lpProps[0].ulPropTag == PR_DISPLAY_NAME_A) {
+ QByteArray profileName(qar.rows()->aRow[n].lpProps[0].Value.lpszA);
+ bool defaultProfile(qar.rows()->aRow[n].lpProps[1].Value.b);
+ result.append(qMakePair(profileName, defaultProfile));
+ }
+ }
+ }
+
+ if(qar.error() != QMessageManager::NoError)
+ qWarning() << "profileNames: QueryAllRows failed";
+
+ profileTable->Release();
+
+ } else {
+ qWarning() << "profileNames: GetProfileTable failed";
+ }
+
+ return result;
+}
+
+QByteArray findDefaultProfileName(IProfAdmin *profAdmin)
+{
+ QByteArray defaultProfileName;
+
+ foreach (const ProfileDetail &profile, profileDetails(profAdmin)) {
+ if (profile.second) {
+ defaultProfileName = profile.first;
+ break;
+ }
+ }
+
+ if (defaultProfileName.isEmpty()) {
+ qWarning() << "findDefaultProfileName: no default profile!";
+ }
+
+ return defaultProfileName;
+}
+
+typedef QPair<QPair<QByteArray, QByteArray>, MAPIUID> ServiceDetail;
+
+QList<ServiceDetail> serviceDetails(LPSERVICEADMIN svcAdmin)
+{
+ QList<ServiceDetail> result;
+
+ IMAPITable *svcTable(0);
+ HRESULT rv = svcAdmin->GetMsgServiceTable(0, &svcTable);
+ if (HR_SUCCEEDED(rv)) {
+
+ SizedSPropTagArray(3, cols) = {3, {PR_SERVICE_NAME_A, PR_DISPLAY_NAME_A, PR_SERVICE_UID}};
+
+ QueryAllRows qar(svcTable, reinterpret_cast<LPSPropTagArray>(&cols), 0, 0);
+ while(qar.query()) {
+ for (uint n = 0; n < qar.rows()->cRows; ++n) {
+ if (qar.rows()->aRow[n].lpProps[0].ulPropTag == PR_SERVICE_NAME_A) {
+ QByteArray svcName(qar.rows()->aRow[n].lpProps[0].Value.lpszA);
+ QByteArray displayName;
+ if (qar.rows()->aRow[n].lpProps[1].ulPropTag == PR_DISPLAY_NAME_A) {
+ displayName = QByteArray(qar.rows()->aRow[n].lpProps[1].Value.lpszA);
+ }
+ MAPIUID svcUid(*(reinterpret_cast<MAPIUID*>(qar.rows()->aRow[n].lpProps[2].Value.bin.lpb)));
+ result.append(qMakePair(qMakePair(svcName, displayName), svcUid));
+ }
+ }
+ }
+
+ if(qar.error() != QMessageManager::NoError)
+ qWarning() << "serviceDetails: QueryAllRows failed";
+
+ svcTable->Release();
+
+ } else {
+ qWarning() << "serviceDetails: GetMsgServiceTable failed";
+ }
+
+ return result;
+}
+#endif
+
+#ifndef _WIN32_WCE
+typedef QPair<QByteArray, QPair<QByteArray, QByteArray> > StoreDetail;
+#else
+typedef QPair<QString, QByteArray> StoreDetail;
+#endif
+
+QList<StoreDetail> storeDetails(LPMAPISESSION session)
+{
+ QList<StoreDetail> result;
+
+ IMAPITable *storesTable(0);
+ HRESULT rv = session->GetMsgStoresTable(0, &storesTable);
+ if (HR_SUCCEEDED(rv)) {
+#ifndef _WIN32_WCE
+ SizedSPropTagArray(3, cols) = {3, {PR_DISPLAY_NAME_A, PR_RECORD_KEY, PR_ENTRYID}};
+#else
+ SizedSPropTagArray(2, cols) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}};
+#endif
+
+ QueryAllRows qar(storesTable, reinterpret_cast<LPSPropTagArray>(&cols), 0, 0, false);
+ while(qar.query()) {
+ for (uint n = 0; n < qar.rows()->cRows; ++n) {
+ SPropValue *props(qar.rows()->aRow[n].lpProps);
+ if (props[0].ulPropTag == cols.aulPropTag[0]) {
+#ifndef _WIN32_WCE
+ QByteArray storeName(props[0].Value.lpszA);
+ QByteArray recordKey(binaryResult(props[1]));
+ QByteArray entryId(binaryResult(props[2]));
+ result.append(qMakePair(storeName, qMakePair(recordKey, entryId)));
+#else
+ QString storeName(QStringFromLptstr(props[0].Value.lpszW));
+ QByteArray entryId(binaryResult(props[1]));
+ result.append(qMakePair(storeName, entryId));
+#endif
+ }
+ }
+ }
+
+ if(qar.error() != QMessageManager::NoError)
+ qWarning() << "storeDetails: QueryAllRows failed";
+
+ storesTable->Release();
+ } else {
+ qWarning() << "storeDetails: GetMsgStoresTable failed";
+ }
+
+ return result;
+}
+
+QMessageAccountId accountIdFromRecordKey(const QByteArray &recordKey)
+{
+ QByteArray encodedId;
+ {
+ QDataStream encodedIdStream(&encodedId, QIODevice::WriteOnly);
+ encodedIdStream << recordKey;
+ }
+
+ return QMessageAccountId(encodedId.toBase64());
+}
+
+QMessageFolderId folderIdFromProperties(const QByteArray &recordKey, const QByteArray &entryId, const QByteArray &storeKey)
+{
+ QByteArray encodedId;
+ {
+ QDataStream encodedIdStream(&encodedId, QIODevice::WriteOnly);
+#ifndef _WIN32_WCE
+ encodedIdStream << recordKey << storeKey;
+ if (!entryId.isEmpty()) {
+ encodedIdStream << entryId;
+ }
+#else
+ encodedIdStream << entryId << storeKey;
+ if (!recordKey.isEmpty()) {
+ encodedIdStream << recordKey;
+ }
+#endif
+ }
+
+ return QMessageFolderId(encodedId.toBase64());
+}
+
+QByteArray objectProperty(IMAPIProp *object, ULONG tag)
+{
+ QByteArray result;
+
+ if (object) {
+ SPropValue *prop(0);
+ HRESULT rv = HrGetOneProp(object, tag, &prop);
+ if (HR_SUCCEEDED(rv)) {
+ result = binaryResult(*prop);
+
+ MAPIFreeBuffer(prop);
+ } else {
+ qWarning() << "objectProperty: HrGetOneProp failed";
+ }
+ }
+
+ return result;
+}
+
+QString stringProperty(IMAPIProp *object, ULONG tag)
+{
+ QString result;
+
+ if (object) {
+ SPropValue *prop(0);
+ HRESULT rv = HrGetOneProp(object, tag, &prop);
+ if (HR_SUCCEEDED(rv)) {
+ result = QString::fromUtf16(reinterpret_cast<quint16*>(prop->Value.LPSZ));
+
+ MAPIFreeBuffer(prop);
+ } else if (rv != MAPI_E_NOT_FOUND) {
+ qWarning() << "stringProperty: HrGetOneProp failed";
+ }
+ }
+
+ return result;
+}
+
+ULONG createNamedProperty(IMAPIProp *object, const QString &name)
+{
+ ULONG result = 0;
+
+ if (!name.isEmpty()) {
+ Lptstr nameBuffer = LptstrFromQString(name);
+
+ MAPINAMEID propName = { 0 };
+#ifndef _WIN32_WCE
+ propName.lpguid = &GuidPublicStrings;
+#else
+ propName.lpguid = &GuidPSMAPI;
+#endif
+ propName.ulKind = MNID_STRING;
+ propName.Kind.lpwstrName = nameBuffer;
+
+ LPMAPINAMEID propNames = &propName;
+
+ SPropTagArray *props;
+ HRESULT rv = object->GetIDsFromNames(1, &propNames, MAPI_CREATE, &props);
+ if (HR_SUCCEEDED(rv)) {
+ result = props->aulPropTag[0] | PT_UNICODE;
+
+ MAPIFreeBuffer(props);
+ } else {
+ qWarning() << "createNamedProperty: GetIDsFromNames failed";
+ }
+ }
+
+ return result;
+}
+
+ULONG getNamedPropertyTag(IMAPIProp *object, const QString &name)
+{
+ ULONG result = 0;
+
+ if (!name.isEmpty()) {
+ Lptstr nameBuffer = LptstrFromQString(name);
+
+ MAPINAMEID propName = { 0 };
+#ifndef _WIN32_WCE
+ propName.lpguid = &GuidPublicStrings;
+#else
+ propName.lpguid = &GuidPSMAPI;
+#endif
+ propName.ulKind = MNID_STRING;
+ propName.Kind.lpwstrName = nameBuffer;
+
+ LPMAPINAMEID propNames = &propName;
+
+ SPropTagArray *props;
+ HRESULT rv = object->GetIDsFromNames(1, &propNames, 0, &props);
+ if (HR_SUCCEEDED(rv)) {
+ if (props->aulPropTag[0] != PT_ERROR) {
+ result = props->aulPropTag[0] | PT_UNICODE;
+ }
+
+ MAPIFreeBuffer(props);
+ } else {
+ qWarning() << "getNamedPropertyTag: GetIDsFromNames failed";
+ }
+ }
+
+ return result;
+}
+
+bool setNamedProperty(IMAPIProp *object, ULONG tag, const QString &value)
+{
+ if (object && tag && !value.isEmpty()) {
+ SPropValue prop = { 0 };
+ prop.ulPropTag = tag;
+ prop.Value.LPSZ = reinterpret_cast<LPTSTR>(const_cast<quint16*>(value.utf16()));
+
+ HRESULT rv = object->SetProps(1, &prop, 0);
+ if (HR_SUCCEEDED(rv)) {
+ return true;
+ } else {
+ qWarning() << "setNamedProperty: SetProps failed";
+ }
+ }
+
+ return false;
+}
+
+QString getNamedProperty(IMAPIProp *object, ULONG tag)
+{
+ QString result;
+
+ if (object && tag) {
+ SPropValue *prop(0);
+ HRESULT rv = HrGetOneProp(object, tag, &prop);
+ if (HR_SUCCEEDED(rv)) {
+ result = QString::fromUtf16(reinterpret_cast<quint16*>(prop->Value.LPSZ));
+
+ MAPIFreeBuffer(prop);
+ } else if (rv != MAPI_E_NOT_FOUND) {
+ qWarning() << "getNamedProperty: HrGetOneProp failed";
+ }
+ }
+
+ return result;
+}
+
+#ifndef _WIN32_WCE
+IProviderAdmin *serviceProvider(const MAPIUID &svcUid, LPSERVICEADMIN svcAdmin)
+{
+ IProviderAdmin *provider(0);
+
+ if (svcAdmin) {
+ HRESULT rv = svcAdmin->AdminProviders(const_cast<MAPIUID*>(&svcUid), 0, &provider);
+ if (HR_FAILED(rv)) {
+ provider = 0;
+ qWarning() << "serviceProvider: AdminProviders failed";
+ }
+ }
+
+ return provider;
+}
+
+MAPIUID findProviderUid(const QByteArray &name, IProviderAdmin *providerAdmin)
+{
+ MAPIUID result = { 0 };
+ IMAPITable *providerTable(0);
+ HRESULT rv = providerAdmin->GetProviderTable(0, &providerTable);
+ if (HR_SUCCEEDED(rv)) {
+
+ SizedSPropTagArray(2, cols) = {2, {PR_SERVICE_NAME_A, PR_PROVIDER_UID}};
+
+ QueryAllRows qar(providerTable, reinterpret_cast<LPSPropTagArray>(&cols), 0, 0);
+ while(qar.query()) {
+ for (uint n = 0; n < qar.rows()->cRows; ++n) {
+ SPropValue *props(qar.rows()->aRow[n].lpProps);
+ if (props[0].ulPropTag == PR_SERVICE_NAME_A) {
+ QByteArray serviceName(props[0].Value.lpszA);
+ if (name.isEmpty() || (serviceName.toLower() == name.toLower())) {
+ result = *(reinterpret_cast<MAPIUID*>(props[1].Value.bin.lpb));
+ break;
+ }
+ }
+ }
+ }
+
+ if(qar.error() != QMessageManager::NoError)
+ qWarning() << "findProviderUid: QueryAllRows failed";
+
+ providerTable->Release();
+ } else {
+ qWarning() << "findProviderUid: GetProviderTable failed";
+ }
+
+ return result;
+}
+
+IProfSect *openProfileSection(const MAPIUID &providerUid, IProviderAdmin *providerAdmin)
+{
+ IProfSect *profileSection(0);
+
+ // Bypass the MAPI_E_NO_ACCESS_ERROR, as described at http://support.microsoft.com/kb/822977
+ const ULONG MAPI_FORCE_ACCESS = 0x00080000;
+
+ HRESULT rv = providerAdmin->OpenProfileSection(const_cast<MAPIUID*>(&providerUid), 0, MAPI_FORCE_ACCESS, &profileSection);
+ if (HR_FAILED(rv)) {
+ qWarning() << "openProfileSection: OpenProfileSection failed";
+ profileSection = 0;
+ }
+
+ return profileSection;
+}
+
+template<typename T>
+bool isEmpty(const T &v)
+{
+ const char empty[sizeof(T)] = { 0 };
+ return (memcmp(empty, &v, sizeof(T)) == 0);
+}
+
+bool deleteExistingService(const MAPIUID &svcUid, LPSERVICEADMIN svcAdmin)
+{
+ if (svcAdmin) {
+ QByteArray storePath;
+
+ // Find the Provider for this service
+ IProviderAdmin *provider = serviceProvider(svcUid, svcAdmin);
+ if (provider) {
+ MAPIUID providerUid = findProviderUid("MSUPST MS", provider);
+ if (!isEmpty(providerUid)) {
+ IProfSect *profileSection = openProfileSection(providerUid, provider);
+ if (profileSection) {
+ SPropValue *prop(0);
+ HRESULT rv = HrGetOneProp(profileSection, PR_PST_PATH_A, &prop);
+ if (HR_SUCCEEDED(rv)) {
+ storePath = QByteArray(prop->Value.lpszA);
+
+ MAPIFreeBuffer(prop);
+ } else {
+ qWarning() << "deleteExistingService: HrGetOneProp failed";
+ }
+
+ profileSection->Release();
+ }
+ }
+
+ provider->Release();
+ }
+
+ if (!storePath.isEmpty()) {
+ // Delete the existing service
+ HRESULT rv = svcAdmin->DeleteMsgService(const_cast<MAPIUID*>(&svcUid));
+ if (HR_SUCCEEDED(rv)) {
+ // Delete the storage file
+ if (QFile::exists(storePath)) {
+ if (!QFile::remove(storePath)) {
+ qWarning() << "deleteExistingService: Unable to remove PST file at:" << storePath;
+ }
+ }
+ return true;
+ } else {
+ qWarning() << "deleteExistingService: DeleteMsgService failed";
+ }
+ }
+ }
+
+ return false;
+}
+
+QByteArray defaultProfile()
+{
+ QByteArray result;
+
+ LPPROFADMIN profAdmin(0);
+ HRESULT rv = MAPIAdminProfiles(0, &profAdmin);
+ if (HR_SUCCEEDED(rv)) {
+ // Find the default profile
+ foreach (const ProfileDetail &profile, profileDetails(profAdmin)) {
+ if (profile.second) {
+ result = profile.first;
+ break;
+ }
+ }
+ } else {
+ qWarning() << "defaultProfile: MAPIAdminProfiles failed";
+ }
+ return result;
+}
+
+IMAPISession *profileSession(const QByteArray &profileName)
+{
+ IMAPISession *session(0);
+
+ if (!profileName.isEmpty()) {
+ // Open a session on the profile
+ QByteArray name(profileName);
+ HRESULT rv = MAPILogonEx(0, reinterpret_cast<LPTSTR>(name.data()), 0, MAPI_EXTENDED | MAPI_NEW_SESSION | MAPI_NO_MAIL, &session);
+ if (HR_FAILED(rv)) {
+ session = 0;
+ qWarning() << "profileSession: MAPILogonEx failed";
+ }
+ }
+
+ return session;
+}
+#endif
+
+#ifndef _WIN32_WCE
+IMAPISession *defaultSession() { return profileSession(defaultProfile()); }
+#else
+ICEMAPISession *defaultSession()
+{
+ ICEMAPISession *session(0);
+
+ // Open a session on the profile
+ HRESULT rv = MAPILogonEx(0, 0, 0, 0, reinterpret_cast<LPMAPISESSION*>(&session));
+ if (HR_FAILED(rv)) {
+ session = 0;
+ qWarning() << "defaultSession: MAPILogonEx failed";
+ }
+
+ return session;
+}
+#endif
+
+#ifdef _WIN32_WCE
+bool deleteExistingStore(const QByteArray &entryId, ICEMAPISession *session)
+{
+ if (session) {
+ HRESULT rv = session->DeleteMsgStore(entryId.count(), reinterpret_cast<LPENTRYID>(const_cast<char*>(entryId.data())));
+ if (HR_SUCCEEDED(rv)) {
+ return true;
+ } else {
+ qWarning() << "deleteExistingStore: DeleteMsgStore failed";
+ }
+ }
+
+ return false;
+}
+#endif
+
+IMsgStore *openStore(const QByteArray &entryId, IMAPISession* session)
+{
+ IMsgStore *store(0);
+
+ if (session && !entryId.isEmpty()) {
+ HRESULT rv = session->OpenMsgStore(0, entryId.length(), reinterpret_cast<LPENTRYID>(const_cast<char*>(entryId.data())), 0, MDB_NO_MAIL | MDB_WRITE, reinterpret_cast<LPMDB*>(&store));
+ if (HR_FAILED(rv)) {
+ store = 0;
+ qWarning() << "openStore: OpenMsgStore failed";
+ }
+ }
+
+ return store;
+}
+
+#ifndef _WIN32_WCE
+IMsgStore *openStoreByName(const QByteArray &storeName, IMAPISession* session)
+#else
+IMsgStore *openStoreByName(const QString &storeName, IMAPISession* session)
+#endif
+{
+ IMsgStore *store(0);
+
+ if (session && !storeName.isEmpty()) {
+ QByteArray entryId;
+
+ // Find the store with the specified name
+ IMAPITable *storesTable(0);
+ HRESULT rv = session->GetMsgStoresTable(0, &storesTable);
+ if (HR_SUCCEEDED(rv)) {
+#ifndef _WIN32_WCE
+ SizedSPropTagArray(2, cols) = {2, {PR_DISPLAY_NAME_A, PR_ENTRYID}};
+#else
+ SizedSPropTagArray(2, cols) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}};
+#endif
+
+ QueryAllRows qar(storesTable, reinterpret_cast<LPSPropTagArray>(&cols), 0, 0, false);
+ while(qar.query()) {
+ for (uint n = 0; n < qar.rows()->cRows; ++n) {
+ if (qar.rows()->aRow[n].lpProps[0].ulPropTag == cols.aulPropTag[0]) {
+#ifndef _WIN32_WCE
+ QByteArray name(qar.rows()->aRow[n].lpProps[0].Value.lpszA);
+#else
+ QString name(QStringFromLptstr(qar.rows()->aRow[n].lpProps[0].Value.lpszW));
+#endif
+ if (name.toLower() == storeName.toLower()) {
+ entryId = binaryResult(qar.rows()->aRow[n].lpProps[1]);
+ break;
+ }
+ }
+ }
+ }
+
+ if(qar.error() != QMessageManager::NoError)
+ qWarning() << "openStoreByName: QueryAllRows failed";
+
+ storesTable->Release();
+ } else {
+ qWarning() << "openStoreByName: GetMsgStoresTable failed";
+ }
+
+ if (!entryId.isEmpty()) {
+ store = openStore(entryId, session);
+ }
+ }
+
+ return store;
+}
+
+QByteArray rootFolderEntryId(IMsgStore *store)
+{
+ return objectProperty(store, PR_IPM_SUBTREE_ENTRYID);
+}
+
+IMAPIFolder *openFolder(const QByteArray &entryId, IMsgStore *store)
+{
+ IMAPIFolder *folder(0);
+
+ if (store && !entryId.isEmpty()) {
+ ULONG type(0);
+ QByteArray entry(entryId);
+ HRESULT rv = store->OpenEntry(entry.length(), reinterpret_cast<LPENTRYID>(entry.data()), 0, MAPI_MODIFY, &type, reinterpret_cast<LPUNKNOWN*>(&folder));
+ if (HR_FAILED(rv)) {
+ folder = 0;
+ qWarning() << "openFolder: OpenEntry failed";
+ }
+ }
+
+ return folder;
+}
+
+IMAPIFolder *openFolder(const QByteArray &entryId, IMAPIFolder *container)
+{
+ IMAPIFolder *folder(0);
+
+ if (container && !entryId.isEmpty()) {
+ ULONG type(0);
+ QByteArray entry(entryId);
+ HRESULT rv = container->OpenEntry(entry.length(), reinterpret_cast<LPENTRYID>(entry.data()), 0, MAPI_MODIFY, &type, reinterpret_cast<LPUNKNOWN*>(&folder));
+ if (HR_FAILED(rv)) {
+ folder = 0;
+ qWarning() << "openFolder: OpenEntry failed";
+ }
+ }
+
+ return folder;
+}
+
+QList<QByteArray> subFolderEntryIds(IMAPIFolder *folder)
+{
+ QList<QByteArray> result;
+
+ if (folder) {
+ IMAPITable *hierarchyTable(0);
+ HRESULT rv = folder->GetHierarchyTable(MAPI_UNICODE, &hierarchyTable);
+ if (HR_SUCCEEDED(rv)) {
+#ifndef _WIN32_WCE
+ SizedSPropTagArray(2, cols) = {2, {PR_OBJECT_TYPE, PR_ENTRYID}};
+#else
+ SizedSPropTagArray(1, cols) = {1, {PR_ENTRYID}};
+#endif
+
+ QueryAllRows qar(hierarchyTable, reinterpret_cast<LPSPropTagArray>(&cols), NULL, NULL, false);
+ while(qar.query()) {
+ for (uint n = 0; n < qar.rows()->cRows; ++n) {
+#ifndef _WIN32_WCE
+ if ((qar.rows()->aRow[n].lpProps[0].ulPropTag == PR_OBJECT_TYPE) &&
+ (qar.rows()->aRow[n].lpProps[0].Value.l == MAPI_FOLDER)) {
+ result.append(binaryResult(qar.rows()->aRow[n].lpProps[1]));
+ }
+#else
+ if (qar.rows()->aRow[n].lpProps[0].ulPropTag == PR_ENTRYID) {
+ result.append(binaryResult(qar.rows()->aRow[n].lpProps[0]));
+ }
+#endif
+ }
+ }
+
+ if(qar.error() != QMessageManager::NoError)
+ qWarning() << "subFolderEntryIds: QueryAllRows failed";
+
+ hierarchyTable->Release();
+ }
+ }
+
+ return result;
+}
+
+IMAPIFolder *subFolder(const QString &path, IMAPIFolder *folder, const QString &rootPath)
+{
+ IMAPIFolder *result(0);
+
+ if (folder && !path.isEmpty()) {
+ // Find all folders in the current folder
+ foreach (const QByteArray &entryId, subFolderEntryIds(folder)) {
+ IMAPIFolder *childFolder = openFolder(entryId, folder);
+ if (childFolder) {
+ QString childPath;
+
+#ifndef _WIN32_WCE
+ ULONG tag = getNamedPropertyTag(childFolder, "path");
+ if (tag) {
+ childPath = getNamedProperty(childFolder, tag);
+ }
+#else
+ // Folders do not support named properties on CE...
+ if (!rootPath.isEmpty()) {
+ childPath = rootPath + '/';
+ }
+ childPath += stringProperty(childFolder, PR_DISPLAY_NAME);
+#endif
+
+ if (childPath == path) {
+ // This is the folder we're looking for
+ result = childFolder;
+ } else if (path.startsWith(childPath)) {
+ // This must be a parent of the folder we're looking for
+ result = subFolder(path, childFolder, childPath);
+ }
+
+ if (childFolder != result) {
+ childFolder->Release();
+ }
+ }
+
+ if (result) {
+ break;
+ }
+ }
+ }
+
+ return result;
+
+#ifndef _WIN32_WCE
+ Q_UNUSED(rootPath)
+#endif
+}
+
+IMAPIFolder *createFolder(const QString &name, IMAPIFolder *folder)
+{
+ IMAPIFolder *newFolder(0);
+
+ if (folder && !name.isEmpty()) {
+ HRESULT rv = folder->CreateFolder(FOLDER_GENERIC, reinterpret_cast<LPTSTR>(const_cast<quint16*>(name.utf16())), 0, 0, MAPI_UNICODE, &newFolder);
+ if (HR_FAILED(rv)) {
+ newFolder = 0;
+ qWarning() << "createFolder: CreateFolder failed";
+ }
+ }
+
+ return newFolder;
+}
+
+QByteArray folderRecordKey(IMAPIFolder *folder)
+{
+ return objectProperty(folder, PR_RECORD_KEY);
+}
+
+QByteArray folderEntryId(IMAPIFolder *folder)
+{
+ return objectProperty(folder, PR_ENTRYID);
+}
+
+QByteArray storeRecordKey(IMsgStore *store)
+{
+#ifndef _WIN32_WCE
+ return objectProperty(store, PR_RECORD_KEY);
+#else
+ return objectProperty(store, PR_ENTRYID);
+#endif
+}
+
+}
+
+namespace Support {
+
+void clearMessageStore()
+{
+ // Ensure the store is instantiated
+ doInit();
+
+ // Remove any existing stores that we added previously
+#ifndef _WIN32_WCE
+ IProfAdmin *profAdmin = openProfileAdmin();
+ if (profAdmin) {
+ QByteArray defaultProfileName = findDefaultProfileName(profAdmin);
+ if (!defaultProfileName.isEmpty()) {
+ IMAPISession *session = profileSession(defaultProfileName);
+ if (session) {
+ IMsgServiceAdmin *svcAdmin = openServiceAdmin(defaultProfileName, profAdmin);
+ if (svcAdmin) {
+ char *providerName = "MSUPST MS";
+ QList<MAPIUID> obsoleteUids;
+
+ foreach (const ServiceDetail &svc, serviceDetails(svcAdmin)) {
+ // Find all services that have our provider
+ if (svc.first.first.toLower() == QByteArray(providerName).toLower()) {
+ IMsgStore *store = openStoreByName(svc.first.second, session);
+ if (store) {
+ // Did we create this store
+ ULONG tag = getNamedPropertyTag(store, "origin");
+ if (tag) {
+ if (getNamedProperty(store, tag) == "QMF") {
+ // This is an existing service we need to remove
+ obsoleteUids.append(svc.second);
+ }
+ }
+
+ store->Release();
+ }
+ }
+ }
+
+ foreach (const MAPIUID &uid, obsoleteUids) {
+ deleteExistingService(uid, svcAdmin);
+ }
+
+ svcAdmin->Release();
+ }
+
+ session->Release();
+ }
+ }
+
+ profAdmin->Release();
+ }
+#else
+ ICEMAPISession *session = defaultSession();
+ if (session) {
+ QList<QByteArray> obsoleteEntryIds;
+
+ foreach (const StoreDetail &detail, storeDetails(session)) {
+ IMsgStore *store = openStore(detail.second, session);
+ if (store) {
+ // Did we create this store?
+ ULONG tag = getNamedPropertyTag(store, "origin");
+ if (tag) {
+ if (getNamedProperty(store, tag) == "QMF") {
+ // This is an existing store we need to remove
+ obsoleteEntryIds.append(detail.second);
+ }
+ }
+
+ store->Release();
+ }
+ }
+
+ foreach (const QByteArray &entryId, obsoleteEntryIds) {
+ deleteExistingStore(entryId, session);
+ }
+
+ session->Release();
+ }
+#endif
+}
+
+QMessageAccountId addAccount(const Parameters ¶ms)
+{
+ QMessageAccountId result;
+
+ doInit();
+
+ QString accountName(params["name"]);
+ QString fromAddress(params["fromAddress"]);
+
+ if (!accountName.isEmpty()) {
+ // Profile name must be ASCII
+ QByteArray name(accountName.toAscii());
+
+#ifndef _WIN32_WCE
+ // See if a profile exists with the given name
+ IProfAdmin *profAdmin = openProfileAdmin();
+ if (profAdmin) {
+ QByteArray defaultProfileName = findDefaultProfileName(profAdmin);
+ if (!defaultProfileName.isEmpty()) {
+ IMAPISession *session = profileSession(defaultProfileName);
+ if (session) {
+ IMsgServiceAdmin *svcAdmin = openServiceAdmin(defaultProfileName, profAdmin);
+ if (svcAdmin) {
+ char *providerName = "MSUPST MS";
+ QList<QByteArray> existingServices;
+
+ foreach (const ServiceDetail &svc, serviceDetails(svcAdmin)) {
+ // Find all services that have our provider
+ if (svc.first.first.toLower() == QByteArray(providerName).toLower()) {
+ existingServices.append(QByteArray(reinterpret_cast<const char*>(&svc.second), sizeof(MAPIUID)));
+ }
+ }
+
+ // Create a message service for this profile using the standard provider
+ HRESULT rv = svcAdmin->CreateMsgService(reinterpret_cast<LPTSTR>(providerName), 0, 0, 0);
+ if (HR_SUCCEEDED(rv)) {
+ // Find which of the now-extant services was not in the previous set
+ foreach (const ServiceDetail &svc, serviceDetails(svcAdmin)) {
+ QByteArray uidData(reinterpret_cast<const char*>(&svc.second), sizeof(MAPIUID));
+ if ((svc.first.first.toLower() == QByteArray(providerName).toLower()) &&
+ !existingServices.contains(uidData)) {
+ // Create a .PST message store for this service
+ QByteArray path(QString("%1.pst").arg(name.constData()).toAscii());
+
+ SPropValue props[3] = { 0 };
+ props[0].ulPropTag = PR_DISPLAY_NAME_A;
+ props[0].Value.lpszA = name.data();
+ props[1].ulPropTag = PR_PST_PATH_A;
+ props[1].Value.lpszA = path.data();
+ props[2].ulPropTag = PR_PST_CONFIG_FLAGS;
+ props[2].Value.l = PST_CONFIG_UNICODE;
+
+ MAPIUID svcUid = svc.second;
+ rv = svcAdmin->ConfigureMsgService(&svcUid, 0, 0, 3, props);
+ if (HR_SUCCEEDED(rv)) {
+ foreach (const StoreDetail &store, storeDetails(session)) {
+ if (store.first.toLower() == name.toLower()) {
+ result = accountIdFromRecordKey(store.second.first);
+
+ IMsgStore *newStore = openStore(store.second.second, session);
+ if (newStore) {
+ // Add an origin tag to this store
+ ULONG originTag = createNamedProperty(newStore, "origin");
+ if (originTag) {
+ setNamedProperty(newStore, originTag, "QMF");
+ }
+
+ if (!fromAddress.isEmpty()) {
+ // Try to set the address for this service, as a property of the store
+ ULONG addressTag = createNamedProperty(newStore, "fromAddress");
+ if (addressTag) {
+ setNamedProperty(newStore, addressTag, fromAddress);
+ }
+ }
+
+ newStore->Release();
+ }
+ break;
+ }
+ }
+ } else {
+ qWarning() << "ConfigureMsgService failed";
+ }
+ break;
+ }
+ }
+ } else {
+ qWarning() << "CreateMsgService failed";
+ }
+
+ svcAdmin->Release();
+ }
+
+ session->Release();
+ }
+ }
+
+ profAdmin->Release();
+ }
+#else
+ ICEMAPISession *session(defaultSession());
+ if (session) {
+ QSet<QString> existingStoreNames;
+ foreach (const StoreDetail &detail, storeDetails(session)) {
+ existingStoreNames.insert(detail.first);
+ }
+
+ if (existingStoreNames.contains(accountName)) {
+ qWarning() << "Store name already in use:" << accountName;
+ } else {
+ IMsgStore *newStore(0);
+ HRESULT rv = session->CreateMsgStore(reinterpret_cast<LPCWSTR>(accountName.constData()), &newStore);
+ if (HR_SUCCEEDED(rv)) {
+ // Add an origin tag to this store
+ ULONG originTag = createNamedProperty(newStore, "origin");
+ if (originTag) {
+ setNamedProperty(newStore, originTag, "QMF");
+ }
+
+ if (!fromAddress.isEmpty()) {
+ // Try to set the address for this service, as a property of the store
+ ULONG addressTag = createNamedProperty(newStore, "fromAddress");
+ if (addressTag) {
+ setNamedProperty(newStore, addressTag, fromAddress);
+ }
+ }
+
+ // Create an ID from the record key - actually, the entry ID for CE...
+ result = accountIdFromRecordKey(objectProperty(newStore, PR_ENTRYID));
+
+ newStore->Release();
+ } else {
+ qWarning() << "Unable to create new store:" << name;
+ qDebug() << "rv:" << hex << (ULONG) rv;
+ }
+ }
+
+ session->Release();
+ }
+#endif
+ }
+
+ return result;
+}
+
+QMessageFolderId addFolder(const Parameters ¶ms)
+{
+ QMessageFolderId result;
+
+ doInit();
+
+ QString folderPath(params["path"]);
+ QString folderName(params["name"]);
+ QString parentPath(params["parentFolderPath"]);
+ QByteArray accountName(params["parentAccountName"].toAscii());
+
+ if (folderName.isEmpty()) {
+ int index = folderPath.lastIndexOf('/');
+ folderName = folderPath.mid(index + 1);
+ }
+
+ if (!folderName.isEmpty() && !folderPath.isEmpty() && !accountName.isEmpty()) {
+ // Open a session on the default profile
+ IMAPISession *session(defaultSession());
+ if (session) {
+ // Open the store for modification
+ IMsgStore *store = openStoreByName(accountName, session);
+ if (store) {
+ // Open the root folder for modification
+ IMAPIFolder *folder = openFolder(rootFolderEntryId(store), store);
+ if (folder) {
+ // Find the parent folder for the new folder
+ if (!parentPath.isEmpty()) {
+ IMAPIFolder *parentFolder = subFolder(parentPath, folder, QString());
+ folder->Release();
+ folder = parentFolder;
+ }
+
+ if (folder) {
+ IMAPIFolder *newFolder = createFolder(folderName, folder);
+ if (newFolder) {
+#ifndef _WIN32_WCE
+ // Named properties not supported by folders on CE...
+ ULONG tag = createNamedProperty(newFolder, "path");
+ if (tag) {
+ setNamedProperty(newFolder, tag, folderPath);
+ }
+#endif
+
+#ifndef _WIN32_WCE
+ QByteArray recordKey = folderRecordKey(newFolder);
+#else
+ QByteArray recordKey;
+#endif
+ QByteArray entryId = folderEntryId(newFolder);
+ QByteArray storeKey = storeRecordKey(store);
+ result = folderIdFromProperties(recordKey, entryId, storeKey);
+
+ newFolder->Release();
+ }
+
+ folder->Release();
+ } else {
+ qWarning() << "Unable to locate parent folder for addition";
+ }
+ } else {
+ qWarning() << "Unable to open root folder for addition";
+ }
+
+ store->Release();
+ }
+
+ session->Release();
+ }
+ }
+
+ return result;
+}
+
+}
+
+QTM_BEGIN_NAMESPACE
+
+// The class 'MapiSession' is a friend of QMessageContentContainer - hijack it here
+class QTM_PREPEND_NAMESPACE(MapiSession)
+{
+public:
+ static QMessageId addMessage(const Support::Parameters ¶ms)
+ {
+ QString parentAccountName(params["parentAccountName"]);
+ QString parentFolderPath(params["parentFolderPath"]);
+ QString to(params["to"]);
+ QString cc(params["cc"]);
+ QString from(params["from"]);
+ QString date(params["date"]);
+ QString receivedDate(params["receivedDate"]);
+ QString subject(params["subject"]);
+ QString text(params["text"]);
+ QString mimeType(params["mimeType"]);
+ QString attachments(params["attachments"]);
+ QString priority(params["priority"]);
+ QString size(params["size"]);
+ QString type(params["type"]);
+ QString read(params["status-read"]);
+ QString hasAttachments(params["status-hasAttachments"]);
+
+ QMessageManager manager;
+
+ if (!to.isEmpty() && !from.isEmpty() && !date.isEmpty() && !subject.isEmpty() &&
+ !parentAccountName.isEmpty() && !parentFolderPath.isEmpty()) {
+ // Find the named account
+ QMessageAccountIdList accountIds(manager.queryAccounts(QMessageAccountFilter::byName(parentAccountName)));
+ if (accountIds.count() == 1) {
+ // Find the specified folder
+ QMessageFolderFilter filter(QMessageFolderFilter::byPath(parentFolderPath, QMessageDataComparator::Equal) & QMessageFolderFilter::byParentAccountId(accountIds.first()));
+ QMessageFolderIdList folderIds(manager.queryFolders(filter));
+ if (folderIds.count() == 1) {
+ QMessage message;
+
+ message.setParentAccountId(accountIds.first());
+ message.d_ptr->_parentFolderId = folderIds.first();
+
+ QList<QMessageAddress> toList;
+ foreach (const QString &addr, to.split(",", QString::SkipEmptyParts)) {
+ toList.append(QMessageAddress(QMessageAddress::Email, addr.trimmed()));
+ }
+ message.setTo(toList);
+
+ QList<QMessageAddress> ccList;
+ foreach (const QString &addr, cc.split(",", QString::SkipEmptyParts)) {
+ ccList.append(QMessageAddress(QMessageAddress::Email, addr.trimmed()));
+ }
+ if (!ccList.isEmpty()) {
+ message.setCc(ccList);
+ }
+
+ message.setFrom(QMessageAddress(QMessageAddress::Email, from));
+ message.setSubject(subject);
+
+ QDateTime dt(QDateTime::fromString(date, Qt::ISODate));
+ dt.setTimeSpec(Qt::UTC);
+ message.setDate(dt);
+
+ if (type.isEmpty()) {
+ message.setType(QMessage::Email);
+ } else {
+ if (type.toLower() == "mms") {
+ message.setType(QMessage::Mms);
+ } else if (type.toLower() == "sms") {
+ message.setType(QMessage::Sms);
+ } else if (type.toLower() == "xmpp") {
+ message.setType(QMessage::Xmpp);
+ } else {
+ message.setType(QMessage::Email);
+ }
+ }
+
+ if (!receivedDate.isEmpty()) {
+ QDateTime dt(QDateTime::fromString(receivedDate, Qt::ISODate));
+ dt.setTimeSpec(Qt::UTC);
+ message.setReceivedDate(dt);
+ }
+
+ if (!priority.isEmpty()) {
+ if (priority.toLower() == "high") {
+ message.setPriority(QMessage::HighPriority);
+ } else if (priority.toLower() == "low") {
+ message.setPriority(QMessage::LowPriority);
+ }
+ }
+
+ if (!size.isEmpty()) {
+ message.d_ptr->_size = size.toUInt();
+ }
+
+ if (!text.isEmpty()) {
+ message.setBody(text, mimeType.toAscii());
+ }
+
+ if (!attachments.isEmpty()) {
+ message.appendAttachments(attachments.split("\n"));
+ }
+
+ QMessage::StatusFlags flags(0);
+ if (read.toLower() == "true") {
+ flags |= QMessage::Read;
+ }
+ if (hasAttachments.toLower() == "true") {
+ flags |= QMessage::HasAttachments;
+ }
+ message.setStatus(flags);
+
+ if (!manager.addMessage(&message)) {
+ qWarning() << "Unable to addMessage:" << to << from << date << subject;
+ } else {
+ return message.id();
+ }
+ } else {
+ qWarning() << "Unable to locate parent folder:" << parentFolderPath;
+ }
+ } else {
+ qWarning() << "Unable to locate parent account:" << parentAccountName;
+ }
+ } else {
+ qWarning() << "Necessary information missing";
+ }
+
+ return QMessageId();
+ }
+};
+
+QTM_END_NAMESPACE
+
+namespace Support {
+
+QMessageId addMessage(const Parameters ¶ms)
+{
+ return MapiSession::addMessage(params);
+}
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+/*
+ * Returns true if a MAPI subsystem is available, as per the
+ * information at
+ * http://msdn.microsoft.com/en-us/library/cc815368.aspx
+ *
+ * Returns false if a MAPI subsystem could not be found.
+ */
+bool mapiAvailable()
+{
+ bool mapix = false;
+ LONG res = -1;
+ HKEY key;
+ res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\Windows Messaging Subsystem",
+ 0,
+ KEY_READ,
+ &key);
+
+ if (res == ERROR_SUCCESS) {
+ unsigned long type = REG_SZ;
+ unsigned long size = 512;
+ char ret[512] = "";
+ res = RegQueryValueExW(key,
+ L"MAPIX",
+ 0,
+ &type,
+ (LPBYTE)&ret[0],
+ &size);
+
+ if (res == ERROR_SUCCESS && (QString::fromUtf16((const ushort*)ret).toInt() == 1))
+ mapix = true;
+ }
+
+ RegCloseKey(key);
+
+ return mapix;
+}
+#endif
+
+}