diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp
index b79668bdbbb79226689ae330abe26a2f8985819a..a0b5ea65390ce32c9c33a9172ea2f24827a61012 100644
--- a/src/winrtrunner/appxengine.cpp
+++ b/src/winrtrunner/appxengine.cpp
@@ -135,8 +135,10 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
     : d_ptr(dd)
 {
     Q_D(AppxEngine);
+    if (d->hasFatalError)
+        return;
+
     d->runner = runner;
-    d->hasFatalError = false;
     d->processHandle = NULL;
     d->pid = -1;
     d->exitCode = UINT_MAX;
@@ -147,9 +149,7 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
         return;
     }
 
-    HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
-    CHECK_RESULT_FATAL("Failed to initialize COM.", return);
-
+    HRESULT hr;
     hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(),
                                 IID_PPV_ARGS(&d->uriFactory));
     CHECK_RESULT_FATAL("Failed to instantiate URI factory.", return);
@@ -343,3 +343,95 @@ bool AppxEngine::installDependencies()
 
     return true;
 }
+
+bool AppxEngine::createPackage(const QString &packageFileName)
+{
+    Q_D(AppxEngine);
+
+    static QHash<QString, QString> contentTypes;
+    if (contentTypes.isEmpty()) {
+        contentTypes.insert(QStringLiteral("dll"), QStringLiteral("application/x-msdownload"));
+        contentTypes.insert(QStringLiteral("exe"), QStringLiteral("application/x-msdownload"));
+        contentTypes.insert(QStringLiteral("png"), QStringLiteral("image/png"));
+        contentTypes.insert(QStringLiteral("xml"), QStringLiteral("vnd.ms-appx.manifest+xml"));
+    }
+
+    // Check for package map, or create one if needed
+    QDir base = QFileInfo(d->manifest).absoluteDir();
+    QFile packageFile(packageFileName);
+
+    QHash<QString, QString> files;
+    QFile mappingFile(base.absoluteFilePath(QStringLiteral("AppxManifest.map")));
+    if (mappingFile.exists()) {
+        qCWarning(lcWinRtRunner) << "Creating package from mapping file:" << mappingFile.fileName();
+        if (!mappingFile.open(QFile::ReadOnly)) {
+            qCWarning(lcWinRtRunner) << "Unable to read mapping file:" << mappingFile.errorString();
+            return false;
+        }
+
+        QRegExp pattern(QStringLiteral("^\"([^\"]*)\"\\s*\"([^\"]*)\"$"));
+        bool inFileSection = false;
+        while (!mappingFile.atEnd()) {
+            const QString line = QString::fromUtf8(mappingFile.readLine()).trimmed();
+            if (line.startsWith(QLatin1Char('['))) {
+                inFileSection = line == QStringLiteral("[Files]");
+                continue;
+            }
+            if (pattern.cap(2).compare(QStringLiteral("AppxManifest.xml"), Qt::CaseInsensitive) == 0)
+                continue;
+            if (inFileSection && pattern.indexIn(line) >= 0 && pattern.captureCount() == 2) {
+                QString inputFile = pattern.cap(1);
+                if (!QFile::exists(inputFile))
+                    inputFile = base.absoluteFilePath(inputFile);
+                files.insert(QDir::toNativeSeparators(inputFile), QDir::toNativeSeparators(pattern.cap(2)));
+            }
+        }
+    } else {
+        qCWarning(lcWinRtRunner) << "No mapping file exists. Only recognized files will be packaged.";
+        // Add executable
+        files.insert(QDir::toNativeSeparators(d->executable), QFileInfo(d->executable).fileName());
+        // Add potential Qt files
+        const QStringList fileTypes = QStringList()
+                << QStringLiteral("*.dll") << QStringLiteral("*.png") << QStringLiteral("*.qm")
+                << QStringLiteral("*.qml") << QStringLiteral("*.qmldir");
+        QDirIterator dirIterator(base.absolutePath(), fileTypes, QDir::Files, QDirIterator::Subdirectories);
+        while (dirIterator.hasNext()) {
+            const QString filePath = dirIterator.next();
+            files.insert(QDir::toNativeSeparators(filePath), QDir::toNativeSeparators(base.relativeFilePath(filePath)));
+        }
+    }
+
+    ComPtr<IStream> outputStream;
+    HRESULT hr = SHCreateStreamOnFile(wchar(packageFile.fileName()), STGM_WRITE|STGM_CREATE, &outputStream);
+    RETURN_FALSE_IF_FAILED("Failed to create package file output stream");
+
+    ComPtr<IUri> hashMethod;
+    hr = CreateUri(L"http://www.w3.org/2001/04/xmlenc#sha512", Uri_CREATE_CANONICALIZE, 0, &hashMethod);
+    RETURN_FALSE_IF_FAILED("Failed to create the has method URI");
+
+    APPX_PACKAGE_SETTINGS packageSettings = { FALSE, hashMethod.Get() };
+    ComPtr<IAppxPackageWriter> packageWriter;
+    hr = d->packageFactory->CreatePackageWriter(outputStream.Get(), &packageSettings, &packageWriter);
+    RETURN_FALSE_IF_FAILED("Failed to create package writer");
+
+    for (QHash<QString, QString>::const_iterator i = files.begin(); i != files.end(); ++i) {
+        qCDebug(lcWinRtRunner) << "Packaging" << i.key() << i.value();
+        ComPtr<IStream> inputStream;
+        hr = SHCreateStreamOnFile(wchar(i.key()), STGM_READ, &inputStream);
+        RETURN_FALSE_IF_FAILED("Failed to open file");
+        const QString contentType = contentTypes.value(QFileInfo(i.key()).suffix().toLower(),
+                                                       QStringLiteral("application/octet-stream"));
+        hr = packageWriter->AddPayloadFile(wchar(i.value()), wchar(contentType),
+                                           APPX_COMPRESSION_OPTION_NORMAL, inputStream.Get());
+        RETURN_FALSE_IF_FAILED("Failed to add payload file");
+    }
+
+    // Write out the manifest
+    ComPtr<IStream> manifestStream;
+    hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
+    RETURN_FALSE_IF_FAILED("Failed to open manifest for packaging");
+    hr = packageWriter->Close(manifestStream.Get());
+    RETURN_FALSE_IF_FAILED("Failed to finalize package.");
+
+    return true;
+}
diff --git a/src/winrtrunner/appxengine.h b/src/winrtrunner/appxengine.h
index 0390eeaecd11555616b4446269107617c15e4756..2e1b74e1bbaeb11e585528a817b7d922fc1cde8c 100644
--- a/src/winrtrunner/appxengine.h
+++ b/src/winrtrunner/appxengine.h
@@ -67,6 +67,7 @@ protected:
     virtual bool installPackage(IAppxManifestReader *reader, const QString &filePath) = 0;
 
     bool installDependencies();
+    bool createPackage(const QString &packageFileName);
     static bool getManifestFile(const QString &fileName, QString *manifest = 0);
 
     QScopedPointer<AppxEnginePrivate> d_ptr;
diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h
index dde97b73a35260e355be747ee833494316056c6e..c2e4ad524f0e842317e3bd27dca9f833c7d73c6e 100644
--- a/src/winrtrunner/appxengine_p.h
+++ b/src/winrtrunner/appxengine_p.h
@@ -56,7 +56,21 @@ struct IAppxFactory;
 class AppxEnginePrivate
 {
 public:
-    virtual ~AppxEnginePrivate() { }
+    AppxEnginePrivate()
+    {
+        HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+        if (FAILED(hr)) {
+            qCWarning(lcWinRtRunner) << "Failed to initialize COM:" << qt_error_string(hr);
+            hasFatalError = true;
+        }
+        hasFatalError = false;
+    }
+
+    virtual ~AppxEnginePrivate()
+    {
+        CoUninitialize();
+    }
+
     Runner *runner;
     bool hasFatalError;
 
diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b1d246aec7e18a45a3eecca487e04d94de6e09bf
--- /dev/null
+++ b/src/winrtrunner/appxphoneengine.cpp
@@ -0,0 +1,544 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "appxphoneengine.h"
+#include "appxengine_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QHash>
+#include <QtCore/QUuid>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QDateTime>
+
+#include <comdef.h>
+#include <psapi.h>
+
+#include <ShlObj.h>
+#include <Shlwapi.h>
+#include <wsdevlicensing.h>
+#include <AppxPackaging.h>
+#include <xmllite.h>
+#include <wrl.h>
+#include <windows.applicationmodel.h>
+#include <windows.management.deployment.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Management::Deployment;
+using namespace ABI::Windows::ApplicationModel;
+using namespace ABI::Windows::System;
+
+// From Microsoft.Phone.Tools.Deploy assembly
+namespace PhoneTools {
+    enum DeploymentOptions
+    {
+        None = 0,
+        PA = 1,
+        Debug = 2,
+        Infused = 4,
+        Lightup = 8,
+        Enterprise = 16,
+        Sideload = 32,
+        TypeMask = 255,
+        UninstallDisabled = 256,
+        SkipUpdateAppInForeground = 512,
+        DeleteXap = 1024,
+        InstallOnSD = 65536,
+        OptOutSD = 131072
+    };
+    enum PackageType
+    {
+        UnknownAppx = 0,
+        Main = 1,
+        Framework = 2,
+        Resource = 4,
+        Bundle = 8,
+        Xap = 0
+    };
+}
+
+QT_USE_NAMESPACE
+
+#include <corecon.h>
+#include <ccapi_12.h>
+Q_GLOBAL_STATIC_WITH_ARGS(CoreConServer, coreConServer, (12))
+
+#undef RETURN_IF_FAILED
+#define RETURN_IF_FAILED(msg, ret) \
+    if (FAILED(hr)) { \
+        qCWarning(lcWinRtRunner).nospace() << msg << ": 0x" << QByteArray::number(hr, 16).constData() \
+                                           << ' ' << coreConServer->formatError(hr); \
+        ret; \
+    }
+
+// Set a break handler for gracefully breaking long-running ops
+static bool g_ctrlReceived = false;
+static bool g_handleCtrl = false;
+static BOOL WINAPI ctrlHandler(DWORD type)
+{
+    switch (type) {
+    case CTRL_C_EVENT:
+    case CTRL_CLOSE_EVENT:
+    case CTRL_LOGOFF_EVENT:
+        g_ctrlReceived = g_handleCtrl;
+        return g_handleCtrl;
+    case CTRL_BREAK_EVENT:
+    case CTRL_SHUTDOWN_EVENT:
+    default:
+        break;
+    }
+    return false;
+}
+
+class AppxPhoneEnginePrivate : public AppxEnginePrivate
+{
+public:
+    QString productId;
+
+    ComPtr<ICcConnection> connection;
+    CoreConDevice *device;
+    QSet<QString> dependencies;
+};
+
+static ProcessorArchitecture toProcessorArchitecture(APPX_PACKAGE_ARCHITECTURE appxArch)
+{
+    switch (appxArch) {
+    case APPX_PACKAGE_ARCHITECTURE_X86:
+        return ProcessorArchitecture_X86;
+    case APPX_PACKAGE_ARCHITECTURE_ARM:
+        return ProcessorArchitecture_Arm;
+    case APPX_PACKAGE_ARCHITECTURE_X64:
+        return ProcessorArchitecture_X64;
+    case APPX_PACKAGE_ARCHITECTURE_NEUTRAL:
+        // fall-through intended
+    default:
+        return ProcessorArchitecture_Neutral;
+    }
+}
+
+static bool getPhoneProductId(IStream *manifestStream, QString *productId)
+{
+    // Read out the phone product ID (not supported by AppxManifestReader)
+    ComPtr<IXmlReader> xmlReader;
+    HRESULT hr = CreateXmlReader(IID_PPV_ARGS(&xmlReader), NULL);
+    RETURN_FALSE_IF_FAILED("Failed to create XML reader");
+
+    hr = xmlReader->SetInput(manifestStream);
+    RETURN_FALSE_IF_FAILED("Failed to set manifest as input");
+
+    while (!xmlReader->IsEOF()) {
+        XmlNodeType nodeType;
+        hr = xmlReader->Read(&nodeType);
+        RETURN_FALSE_IF_FAILED("Failed to read next node in manifest");
+        if (nodeType == XmlNodeType_Element) {
+            PCWSTR uri;
+            hr = xmlReader->GetNamespaceUri(&uri, NULL);
+            RETURN_FALSE_IF_FAILED("Failed to read namespace URI of current node");
+            if (wcscmp(uri, L"http://schemas.microsoft.com/appx/2014/phone/manifest") == 0) {
+                PCWSTR localName;
+                hr = xmlReader->GetLocalName(&localName, NULL);
+                RETURN_FALSE_IF_FAILED("Failed to get local name of current node");
+                if (wcscmp(localName, L"PhoneIdentity") == 0) {
+                    hr = xmlReader->MoveToAttributeByName(L"PhoneProductId", NULL);
+                    if (hr == S_FALSE)
+                        continue;
+                    RETURN_FALSE_IF_FAILED("Failed to seek to the PhoneProductId attribute");
+                    PCWSTR phoneProductId;
+                    UINT length;
+                    hr = xmlReader->GetValue(&phoneProductId, &length);
+                    RETURN_FALSE_IF_FAILED("Failed to read the value of the PhoneProductId attribute");
+                    *productId = QLatin1Char('{') + QString::fromWCharArray(phoneProductId, length) + QLatin1Char('}');
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool AppxPhoneEngine::canHandle(Runner *runner)
+{
+    return getManifestFile(runner->app());
+}
+
+RunnerEngine *AppxPhoneEngine::create(Runner *runner)
+{
+    QScopedPointer<AppxPhoneEngine> engine(new AppxPhoneEngine(runner));
+    if (engine->d_ptr->hasFatalError)
+        return 0;
+
+    return engine.take();
+}
+
+QStringList AppxPhoneEngine::deviceNames()
+{
+    QStringList deviceNames;
+    foreach (const CoreConDevice *device, coreConServer->devices())
+        deviceNames.append(device->name());
+    return deviceNames;
+}
+
+AppxPhoneEngine::AppxPhoneEngine(Runner *runner)
+    : AppxEngine(runner, new AppxPhoneEnginePrivate)
+{
+    Q_D(AppxPhoneEngine);
+    if (d->hasFatalError)
+        return;
+    d->hasFatalError = true;
+
+    ComPtr<IStream> manifestStream;
+    HRESULT hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
+    RETURN_VOID_IF_FAILED("Failed to open manifest stream");
+
+    if (!getPhoneProductId(manifestStream.Get(), &d->productId)) {
+        qCWarning(lcWinRtRunner) << "Failed to read phone product ID from the manifest.";
+        return;
+    }
+
+    if (!coreConServer->initialize()) {
+        while (!coreConServer.exists())
+            Sleep(1);
+    }
+
+    // Get the device
+    d->device = coreConServer->devices().value(d->runner->deviceIndex());
+    if (!d->device || !d->device->handle()) {
+        d->hasFatalError = true;
+        qCWarning(lcWinRtRunner) << "Invalid device specified:" << d->runner->deviceIndex();
+        return;
+    }
+
+
+
+    // Set a break handler for gracefully exiting from long-running operations
+    SetConsoleCtrlHandler(&ctrlHandler, true);
+    d->hasFatalError = false;
+}
+
+AppxPhoneEngine::~AppxPhoneEngine()
+{
+}
+
+QString AppxPhoneEngine::extensionSdkPath() const
+{
+    HKEY regKey;
+    LONG hr = RegOpenKeyEx(
+                HKEY_LOCAL_MACHINE,
+                L"SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v8.1",
+                0, KEY_READ, &regKey);
+    if (hr != ERROR_SUCCESS) {
+        qCWarning(lcWinRtRunner) << "Failed to open registry key:" << qt_error_string(hr);
+        return QString();
+    }
+
+    wchar_t pathData[MAX_PATH];
+    DWORD pathLength = MAX_PATH;
+    hr = RegGetValue(regKey, L"Install Path", L"Install Path", RRF_RT_REG_SZ, NULL, pathData, &pathLength);
+    if (hr != ERROR_SUCCESS) {
+        qCWarning(lcWinRtRunner) << "Failed to get installation path value:" << qt_error_string(hr);
+        return QString();
+    }
+
+    return QString::fromWCharArray(pathData, (pathLength - 1) / sizeof(wchar_t))
+            + QLatin1String("ExtensionSDKs");
+}
+
+bool AppxPhoneEngine::installPackage(IAppxManifestReader *reader, const QString &filePath)
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__ << filePath;
+
+    ComPtr<ICcConnection3> connection;
+    HRESULT hr = d->connection.As(&connection);
+    RETURN_FALSE_IF_FAILED("Failed to obtain connection object");
+
+    ComPtr<IStream> manifestStream;
+    hr = reader->GetStream(&manifestStream);
+    RETURN_FALSE_IF_FAILED("Failed to get manifest stream from reader");
+
+    QString productIdString;
+    if (!getPhoneProductId(manifestStream.Get(), &productIdString)) {
+        qCWarning(lcWinRtRunner) << "Failed to get phone product ID from manifest reader.";
+        return false;
+    }
+    _bstr_t productId(wchar(productIdString));
+
+    VARIANT_BOOL isInstalled;
+    hr = connection->IsApplicationInstalled(productId, &isInstalled);
+    RETURN_FALSE_IF_FAILED("Failed to determine if package is installed");
+    if (isInstalled) {
+        qCDebug(lcWinRtRunner) << "Package" << productIdString << "is already installed";
+        return true;
+    }
+
+    ComPtr<IAppxManifestProperties> properties;
+    hr = reader->GetProperties(&properties);
+    RETURN_FALSE_IF_FAILED("Failed to get manifest properties");
+
+    BOOL isFramework;
+    hr = properties->GetBoolValue(L"Framework", &isFramework);
+    RETURN_FALSE_IF_FAILED("Failed to determine whether package is a framework");
+
+    const QString deploymentFlags = QString::number(isFramework ? PhoneTools::None : PhoneTools::Sideload);
+    _bstr_t deploymentFlagsAsGenre(wchar(deploymentFlags));
+    const QString packageType = QString::number(isFramework ? PhoneTools::Framework : PhoneTools::Main);
+    _bstr_t packageTypeAsIconPath(wchar(packageType));
+    _bstr_t packagePath(wchar(QDir::toNativeSeparators(filePath)));
+    hr = connection->InstallApplication(productId, productId, deploymentFlagsAsGenre,
+                                        packageTypeAsIconPath, packagePath);
+    RETURN_FALSE_IF_FAILED("Failed to install the package");
+
+    return true;
+}
+
+bool AppxPhoneEngine::connect()
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    HRESULT hr;
+    if (!d->connection) {
+        _bstr_t connectionName;
+        hr = static_cast<ICcServer *>(coreConServer->handle())->GetConnection(
+                    static_cast<ICcDevice *>(d->device->handle()), 5000, NULL, connectionName.GetAddress(), &d->connection);
+        RETURN_FALSE_IF_FAILED("Failed to connect to device");
+    }
+
+    VARIANT_BOOL connected;
+    hr = d->connection->IsConnected(&connected);
+    RETURN_FALSE_IF_FAILED("Failed to determine connection state");
+    if (connected)
+        return true;
+
+    hr = d->connection->ConnectDevice();
+    RETURN_FALSE_IF_FAILED("Failed to connect to device");
+
+    return true;
+}
+
+bool AppxPhoneEngine::install(bool removeFirst)
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    if (!connect())
+        return false;
+
+    ComPtr<ICcConnection3> connection;
+    HRESULT hr = d->connection.As(&connection);
+    RETURN_FALSE_IF_FAILED("Failed to obtain connection object");
+
+    _bstr_t productId(wchar(d->productId));
+    VARIANT_BOOL isInstalled;
+    hr = connection->IsApplicationInstalled(productId, &isInstalled);
+    RETURN_FALSE_IF_FAILED("Failed to obtain the installation status");
+    if (isInstalled) {
+        if (!removeFirst)
+            return true;
+        if (!remove())
+            return false;
+    }
+
+    if (!installDependencies())
+        return false;
+
+    const QDir base = QFileInfo(d->manifest).absoluteDir();
+    const QString packageFileName = base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx"));
+    if (!createPackage(packageFileName))
+        return false;
+
+    ComPtr<IStream> manifestStream;
+    hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
+    RETURN_FALSE_IF_FAILED("Failed to open manifest stream");
+
+    ComPtr<IAppxManifestReader> manifestReader;
+    hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &manifestReader);
+    RETURN_FALSE_IF_FAILED("Failed to create manifest reader for installation");
+
+    return installPackage(manifestReader.Get(), packageFileName);
+}
+
+bool AppxPhoneEngine::remove()
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    if (!connect())
+        return false;
+
+    if (!d->connection)
+        return false;
+
+    ComPtr<ICcConnection3> connection;
+    HRESULT hr = d->connection.As(&connection);
+    RETURN_FALSE_IF_FAILED("Failed to obtain connection object");
+
+    _bstr_t app = wchar(d->productId);
+    hr = connection->UninstallApplication(app);
+    RETURN_FALSE_IF_FAILED("Failed to uninstall the package");
+
+    return true;
+}
+
+bool AppxPhoneEngine::start()
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    if (!connect())
+        return false;
+
+    if (!d->runner->arguments().isEmpty())
+        qCWarning(lcWinRtRunner) << "Arguments are not currently supported for Windows Phone Appx packages.";
+
+    ComPtr<ICcConnection3> connection;
+    HRESULT hr = d->connection.As(&connection);
+    RETURN_FALSE_IF_FAILED("Failed to cast connection object");
+
+    _bstr_t productId(wchar(d->productId));
+    DWORD pid;
+    hr = connection->LaunchApplication(productId, &pid);
+    RETURN_FALSE_IF_FAILED("Failed to start the package");
+
+    d->pid = pid;
+    return true;
+}
+
+bool AppxPhoneEngine::enableDebugging(const QString &debuggerExecutable, const QString &debuggerArguments)
+{
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+    Q_UNUSED(debuggerExecutable);
+    Q_UNUSED(debuggerArguments);
+    return false;
+}
+
+bool AppxPhoneEngine::disableDebugging()
+{
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+    return false;
+}
+
+bool AppxPhoneEngine::suspend()
+{
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+    return false;
+}
+
+bool AppxPhoneEngine::waitForFinished(int secs)
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    ComPtr<ICcConnection3> connection;
+    HRESULT hr = d->connection.As(&connection);
+    RETURN_FALSE_IF_FAILED("Failed to cast connection");
+
+    g_handleCtrl = true;
+    int time = 0;
+    forever {
+        ++time;
+        if ((secs && time > secs) || g_ctrlReceived) {
+            g_handleCtrl = false;
+            return false;
+        }
+
+        Sleep(1000); // Wait one second between checks
+        qCDebug(lcWinRtRunner) << "Waiting for app to quit - msecs to go: " << secs - time;
+    }
+    g_handleCtrl = false;
+    return true;
+}
+
+bool AppxPhoneEngine::stop()
+{
+    Q_D(AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    if (!connect())
+        return false;
+
+    ComPtr<ICcConnection3> connection;
+    HRESULT hr = d->connection.As(&connection);
+    RETURN_FALSE_IF_FAILED("Failed to cast connection object");
+
+    _bstr_t productId(wchar(d->productId));
+    hr = connection->TerminateRunningApplicationInstances(productId);
+    RETURN_FALSE_IF_FAILED("Failed to stop the package");
+
+    return true;
+}
+
+QString AppxPhoneEngine::devicePath(const QString &relativePath) const
+{
+    Q_D(const AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    return QStringLiteral("%FOLDERID_APPID_ISOROOT%\\") + d->productId
+            + QStringLiteral("\\%LOCL%\\") + relativePath;
+}
+
+bool AppxPhoneEngine::sendFile(const QString &localFile, const QString &deviceFile)
+{
+    Q_D(const AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    HRESULT hr = d->connection->SendFile(_bstr_t(wchar(localFile)), _bstr_t(wchar(deviceFile)),
+                                         CREATE_ALWAYS, NULL);
+    RETURN_FALSE_IF_FAILED("Failed to send the file");
+
+    return true;
+}
+
+bool AppxPhoneEngine::receiveFile(const QString &deviceFile, const QString &localFile)
+{
+    Q_D(const AppxPhoneEngine);
+    qCDebug(lcWinRtRunner) << __FUNCTION__;
+
+    HRESULT hr = d->connection->ReceiveFile(_bstr_t(wchar(deviceFile)),
+                                            _bstr_t(wchar(localFile)), uint(2));
+    RETURN_FALSE_IF_FAILED("Failed to receive the file");
+
+    return true;
+}
diff --git a/src/winrtrunner/appxphoneengine.h b/src/winrtrunner/appxphoneengine.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f4933355bc68097540858596a0bd0f0b81ef5f7
--- /dev/null
+++ b/src/winrtrunner/appxphoneengine.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef APPXPHONEENGINE_H
+#define APPXPHONEENGINE_H
+
+#include "appxengine.h"
+#include "runnerengine.h"
+#include "runner.h"
+
+#include <QtCore/QScopedPointer>
+
+QT_USE_NAMESPACE
+
+class AppxPhoneEnginePrivate;
+class AppxPhoneEngine : public AppxEngine
+{
+public:
+    static bool canHandle(Runner *runner);
+    static RunnerEngine *create(Runner *runner);
+    static QStringList deviceNames();
+
+    bool install(bool removeFirst = false) Q_DECL_OVERRIDE;
+    bool remove() Q_DECL_OVERRIDE;
+    bool start() Q_DECL_OVERRIDE;
+    bool enableDebugging(const QString &debuggerExecutable,
+                        const QString &debuggerArguments) Q_DECL_OVERRIDE;
+    bool disableDebugging() Q_DECL_OVERRIDE;
+    bool suspend() Q_DECL_OVERRIDE;
+    bool waitForFinished(int secs) Q_DECL_OVERRIDE;
+    bool stop() Q_DECL_OVERRIDE;
+
+    QString devicePath(const QString &relativePath) const Q_DECL_OVERRIDE;
+    bool sendFile(const QString &localFile, const QString &deviceFile) Q_DECL_OVERRIDE;
+    bool receiveFile(const QString &deviceFile, const QString &localFile) Q_DECL_OVERRIDE;
+
+private:
+    explicit AppxPhoneEngine(Runner *runner);
+    ~AppxPhoneEngine();
+
+    QString extensionSdkPath() const;
+    bool installPackage(IAppxManifestReader *reader, const QString &filePath) Q_DECL_OVERRIDE;
+
+    bool connect();
+
+    friend struct QScopedPointerDeleter<AppxPhoneEngine>;
+    Q_DECLARE_PRIVATE(AppxPhoneEngine)
+};
+
+#endif // APPXPHONEENGINE_H
diff --git a/src/winrtrunner/runner.cpp b/src/winrtrunner/runner.cpp
index 5b472599196cb8a18625e340596d0b86d83d8d39..fa31c30d8055af1241979553d8f9b46c06fb5a5b 100644
--- a/src/winrtrunner/runner.cpp
+++ b/src/winrtrunner/runner.cpp
@@ -43,6 +43,9 @@
 
 #include "runnerengine.h"
 
+#ifndef RTRUNNER_NO_APPXPHONE
+#include "appxphoneengine.h"
+#endif
 #ifndef RTRUNNER_NO_APPXLOCAL
 #include "appxlocalengine.h"
 #endif
@@ -80,6 +83,9 @@ QMap<QString, QStringList> Runner::deviceNames()
 #ifndef RTRUNNER_NO_APPXLOCAL
     deviceNames.insert(QStringLiteral("Appx"), AppxLocalEngine::deviceNames());
 #endif
+#ifndef RTRUNNER_NO_APPXPHONE
+    deviceNames.insert(QStringLiteral("Phone"), AppxPhoneEngine::deviceNames());
+#endif
 #ifndef RTRUNNER_NO_XAP
     deviceNames.insert(QStringLiteral("Xap"), XapEngine::deviceNames());
 #endif
@@ -98,6 +104,22 @@ Runner::Runner(const QString &app, const QStringList &arguments,
 
     bool deviceIndexKnown;
     d->deviceIndex = deviceName.toInt(&deviceIndexKnown);
+#ifndef RTRUNNER_NO_APPXPHONE
+    if (!deviceIndexKnown) {
+        d->deviceIndex = AppxPhoneEngine::deviceNames().indexOf(deviceName);
+        if (d->deviceIndex < 0)
+            d->deviceIndex = 0;
+    }
+    if ((d->profile.isEmpty() || d->profile.toLower() == QStringLiteral("appxphone"))
+            && AppxPhoneEngine::canHandle(this)) {
+        if (RunnerEngine *engine = AppxPhoneEngine::create(this)) {
+            d->engine.reset(engine);
+            d->isValid = true;
+            qCWarning(lcWinRtRunner) << "Using the AppxPhone profile.";
+            return;
+        }
+    }
+#endif
 #ifndef RTRUNNER_NO_APPXLOCAL
     if (!deviceIndexKnown) {
         d->deviceIndex = AppxLocalEngine::deviceNames().indexOf(deviceName);
diff --git a/src/winrtrunner/winrtrunner.pro b/src/winrtrunner/winrtrunner.pro
index eb2fdfcb6a887cdf14302712729b9ebb7b584696..e1b59846a440cbe3cc7447d1adbe3aba5bcbfc52 100644
--- a/src/winrtrunner/winrtrunner.pro
+++ b/src/winrtrunner/winrtrunner.pro
@@ -6,7 +6,7 @@ DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII WINRT_LIBRARY
 SOURCES += main.cpp runner.cpp
 HEADERS += runner.h runnerengine.h
 
-DEFINES += RTRUNNER_NO_APPXLOCAL RTRUNNER_NO_XAP
+DEFINES += RTRUNNER_NO_APPXLOCAL RTRUNNER_NO_APPXPHONE RTRUNNER_NO_XAP
 
 win32-msvc2012|win32-msvc2013 {
     SOURCES += appxengine.cpp appxlocalengine.cpp
@@ -19,6 +19,13 @@ win32-msvc2012|win32-msvc2013 {
     HEADERS += xapengine.h
     DEFINES -= RTRUNNER_NO_XAP
 
+    win32-msvc2013 {
+        LIBS += -lurlmon -lxmllite
+        SOURCES += appxphoneengine.cpp
+        HEADERS += appxphoneengine.h
+        DEFINES -= RTRUNNER_NO_APPXPHONE
+    }
+
     # Use zip class from qtbase
     SOURCES += \
         qzip/qzip.cpp