summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@qt.io>2020-08-05 11:31:58 +0200
committerOliver Wolff <oliver.wolff@qt.io>2020-08-06 07:40:04 +0200
commitc14e73f3c1016a38c8f95de3e9758195a2a4cef7 (patch)
treec7fd82bf2e4e9feb281384c5171f950d315d8de9
parent005f6f0bb3139a9d90daabab06bab2b346eb9de4 (diff)
Remove winrt specific code
Task-number: QTBUG-84434 Change-Id: I9c3a661e490f3dccea893e213939953465d8970e Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> Reviewed-by: André de la Rocha <andre.rocha@qt.io> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--.prev_configure.cmake123
-rw-r--r--configure.cmake8
-rw-r--r--configure.json11
-rw-r--r--src/.prev_CMakeLists.txt5
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/shared/winutils/utils.h3
-rw-r--r--src/src.pro6
-rw-r--r--src/windeployqt/main.cpp44
-rw-r--r--src/winrtrunner/CMakeLists.txt45
-rw-r--r--src/winrtrunner/appxengine.cpp801
-rw-r--r--src/winrtrunner/appxengine.h76
-rw-r--r--src/winrtrunner/appxengine_p.h111
-rw-r--r--src/winrtrunner/appxlocalengine.cpp884
-rw-r--r--src/winrtrunner/appxlocalengine.h88
-rw-r--r--src/winrtrunner/appxphoneengine.cpp565
-rw-r--r--src/winrtrunner/appxphoneengine.h89
-rw-r--r--src/winrtrunner/main.cpp372
-rw-r--r--src/winrtrunner/runner.cpp384
-rw-r--r--src/winrtrunner/runner.h90
-rw-r--r--src/winrtrunner/runnerengine.h70
-rw-r--r--src/winrtrunner/winrtrunner.pro31
-rw-r--r--tests/auto/.prev_CMakeLists.txt2
-rw-r--r--tests/auto/CMakeLists.txt2
-rw-r--r--tests/auto/auto.pro2
24 files changed, 136 insertions, 3681 deletions
diff --git a/.prev_configure.cmake b/.prev_configure.cmake
new file mode 100644
index 000000000..97164e5f6
--- /dev/null
+++ b/.prev_configure.cmake
@@ -0,0 +1,123 @@
+
+
+#### Inputs
+
+
+
+#### Libraries
+
+
+
+#### Tests
+
+# libclang
+qt_find_package(WrapLibClang PROVIDED_TARGETS WrapLibClang::WrapLibClang)
+
+if(TARGET WrapLibClang::WrapLibClang)
+ set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
+endif()
+
+
+
+#### Features
+
+qt_feature("assistant" PRIVATE
+ LABEL "Qt Assistant"
+ PURPOSE "Qt Assistant is a tool for viewing on-line documentation in Qt help file format."
+)
+qt_feature("clang" PRIVATE
+ LABEL "QDoc"
+ CONDITION TEST_libclang
+)
+qt_feature("clangcpp" PRIVATE
+ LABEL "Clang-based lupdate parser"
+ CONDITION QT_FEATURE_clang AND TEST_libclang
+)
+qt_feature("designer" PRIVATE
+ LABEL "Qt Designer"
+ PURPOSE "Qt Designer is the Qt tool for designing and building graphical user interfaces (GUIs) with Qt Widgets. You can compose and customize your windows or dialogs in a what-you-see-is-what-you-get (WYSIWYG) manner, and test them using different styles and resolutions."
+)
+qt_feature("distancefieldgenerator" PRIVATE
+ LABEL "Qt Distance Field Generator"
+ PURPOSE "The Qt Distance Field Generator tool can be used to pregenerate the font cache in order to optimize startup performance."
+)
+qt_feature("kmap2qmap" PRIVATE
+ LABEL "kmap2qmap"
+ PURPOSE "kmap2qmap is a tool to generate keymaps for use on Embedded Linux. The source files have to be in standard Linux kmap format that is e.g. understood by the kernel's loadkeys command."
+)
+qt_feature("linguist" PRIVATE
+ LABEL "Qt Linguist"
+ PURPOSE "Qt Linguist can be used by translator to translate text in Qt applications."
+)
+qt_feature("macdeployqt" PRIVATE
+ LABEL "Mac Deployment Tool"
+ PURPOSE "The Mac deployment tool automates the process of creating a deployable application bundle that contains the Qt libraries as private frameworks."
+ CONDITION APPLE
+)
+qt_feature("makeqpf" PRIVATE
+ LABEL "makeqpf"
+ PURPOSE "makeqpf is a tool to generate pre-rendered fonts in QPF2 format for use on Embedded Linux."
+)
+qt_feature("pixeltool" PRIVATE
+ LABEL "pixeltool"
+ PURPOSE "The Qt Pixel Zooming Tool is a graphical application that magnifies the screen around the mouse pointer so you can look more closely at individual pixels."
+)
+qt_feature("qdbus" PRIVATE
+ LABEL "qdbus"
+ PURPOSE "qdbus is a communication interface for Qt-based applications."
+)
+qt_feature("qev" PRIVATE
+ LABEL "qev"
+ PURPOSE "qev allows introspection of incoming events for a QWidget, similar to the X11 xev tool."
+)
+qt_feature("qtattributionsscanner" PRIVATE
+ LABEL "Qt Attributions Scanner"
+ PURPOSE "Qt Attributions Scanner generates attribution documents for third-party code in Qt."
+)
+qt_feature("qtdiag" PRIVATE
+ LABEL "qtdiag"
+ PURPOSE "qtdiag outputs information about the Qt installation it was built with."
+)
+qt_feature("qtpaths" PRIVATE
+ LABEL "qtpaths"
+ PURPOSE "qtpaths is a command line client to QStandardPaths."
+)
+qt_feature("qtplugininfo" PRIVATE
+ LABEL "qtplugininfo"
+ PURPOSE "qtplugininfo dumps metadata about Qt plugins in JSON format."
+)
+qt_feature("windeployqt" PRIVATE
+ LABEL "Windows deployment tool"
+ PURPOSE "The Windows deployment tool is designed to automate the process of creating a deployable folder containing the Qt-related dependencies (libraries, QML imports, plugins, and translations) required to run the application from that folder. It creates a sandbox for Universal Windows Platform (UWP) or an installation tree for Windows desktop applications, which can be easily bundled into an installation package."
+ CONDITION WIN32
+)
+qt_configure_add_summary_section(NAME "Qt Tools")
+qt_configure_add_summary_entry(ARGS "assistant")
+qt_configure_add_summary_entry(ARGS "clang")
+qt_configure_add_summary_entry(ARGS "clangcpp")
+qt_configure_add_summary_entry(ARGS "designer")
+qt_configure_add_summary_entry(ARGS "distancefieldgenerator")
+qt_configure_add_summary_entry(ARGS "kmap2qmap")
+qt_configure_add_summary_entry(ARGS "linguist")
+qt_configure_add_summary_entry(ARGS "macdeployqt")
+qt_configure_add_summary_entry(ARGS "makeqpf")
+qt_configure_add_summary_entry(ARGS "pixeltool")
+qt_configure_add_summary_entry(ARGS "qdbus")
+qt_configure_add_summary_entry(ARGS "qev")
+qt_configure_add_summary_entry(ARGS "qtattributionsscanner")
+qt_configure_add_summary_entry(ARGS "qtdiag")
+qt_configure_add_summary_entry(ARGS "qtpaths")
+qt_configure_add_summary_entry(ARGS "qtplugininfo")
+qt_configure_add_summary_entry(ARGS "windeployqt")
+qt_configure_end_summary_section() # end of "Qt Tools" section
+qt_configure_add_report_entry(
+ TYPE WARNING
+ MESSAGE "QDoc will not be compiled, probably because libclang could not be located. This means that you cannot build the Qt documentation.
+ Either ensure that llvm-config is in your PATH environment variable, or set LLVM_INSTALL_DIR to the location of your llvm installation. On Linux systems, you may be able to install libclang by installing the libclang-dev or libclang-devel package, depending on your distribution. On macOS, you can use Homebrew's llvm package. On Windows, you must set LLVM_INSTALL_DIR to the installation path."
+ CONDITION NOT QT_FEATURE_clang
+)
+qt_configure_add_report_entry(
+ TYPE WARNING
+ MESSAGE "Clang-based lupdate parser will not be available. LLVM and Clang C++ libraries have not been found."
+ CONDITION NOT QT_FEATURE_clangcpp
+)
diff --git a/configure.cmake b/configure.cmake
index 7b48332f6..5f5d6bd60 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -95,12 +95,7 @@ qt_feature("qtplugininfo" PRIVATE
qt_feature("windeployqt" PRIVATE
LABEL "Windows deployment tool"
PURPOSE "The Windows deployment tool is designed to automate the process of creating a deployable folder containing the Qt-related dependencies (libraries, QML imports, plugins, and translations) required to run the application from that folder. It creates a sandbox for Universal Windows Platform (UWP) or an installation tree for Windows desktop applications, which can be easily bundled into an installation package."
- CONDITION WIN32 OR WINRT
-)
-qt_feature("winrtrunner" PRIVATE
- LABEL "WinRT Runner Tool"
- PURPOSE "The WinRT Runner Tool installs, runs, and collects test results for packages made with Qt."
- CONDITION WINRT
+ CONDITION WIN32
)
qt_configure_add_summary_section(NAME "Qt Tools")
qt_configure_add_summary_entry(ARGS "assistant")
@@ -120,7 +115,6 @@ qt_configure_add_summary_entry(ARGS "qtdiag")
qt_configure_add_summary_entry(ARGS "qtpaths")
qt_configure_add_summary_entry(ARGS "qtplugininfo")
qt_configure_add_summary_entry(ARGS "windeployqt")
-qt_configure_add_summary_entry(ARGS "winrtrunner")
qt_configure_end_summary_section() # end of "Qt Tools" section
qt_configure_add_report_entry(
TYPE WARNING
diff --git a/configure.json b/configure.json
index 2ff580062..3442f8cb5 100644
--- a/configure.json
+++ b/configure.json
@@ -111,13 +111,7 @@
"windeployqt": {
"label": "Windows deployment tool",
"purpose": "The Windows deployment tool is designed to automate the process of creating a deployable folder containing the Qt-related dependencies (libraries, QML imports, plugins, and translations) required to run the application from that folder. It creates a sandbox for Universal Windows Platform (UWP) or an installation tree for Windows desktop applications, which can be easily bundled into an installation package.",
- "condition": "config.win32 || config.winrt",
- "output": [ "privateFeature" ]
- },
- "winrtrunner": {
- "label": "WinRT Runner Tool",
- "purpose": "The WinRT Runner Tool installs, runs, and collects test results for packages made with Qt.",
- "condition": "config.winrt",
+ "condition": "config.win32",
"output": [ "privateFeature" ]
}
},
@@ -157,8 +151,7 @@ On Windows, you must set LLVM_INSTALL_DIR to the installation path."
"qtdiag",
"qtpaths",
"qtplugininfo",
- "windeployqt",
- "winrtrunner"
+ "windeployqt"
]
}
]
diff --git a/src/.prev_CMakeLists.txt b/src/.prev_CMakeLists.txt
index 3f77c0bd9..1747a7d13 100644
--- a/src/.prev_CMakeLists.txt
+++ b/src/.prev_CMakeLists.txt
@@ -39,9 +39,6 @@ endif()
if(WIN32)
add_subdirectory(windeployqt)
endif()
-if(WINRT)
- add_subdirectory(winrtrunner)
-endif()
-if(QT_FEATURE_commandlineparser AND TARGET Qt::Gui AND NOT ANDROID AND NOT QNX AND NOT UIKIT AND NOT WASM AND NOT WINRT)
+if(QT_FEATURE_commandlineparser AND TARGET Qt::Gui AND NOT ANDROID AND NOT QNX AND NOT UIKIT AND NOT WASM)
add_subdirectory(qtdiag)
endif()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3ac2dd38c..770f1cabc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -54,9 +54,6 @@ endif()
if(WIN32)
add_subdirectory(windeployqt)
endif()
-if(WINRT)
- add_subdirectory(winrtrunner)
-endif()
-if(QT_FEATURE_commandlineparser AND TARGET Qt::Gui AND NOT ANDROID AND NOT QNX AND NOT UIKIT AND NOT WASM AND NOT WINRT)
+if(QT_FEATURE_commandlineparser AND TARGET Qt::Gui AND NOT ANDROID AND NOT QNX AND NOT UIKIT AND NOT WASM)
add_subdirectory(qtdiag)
endif()
diff --git a/src/shared/winutils/utils.h b/src/shared/winutils/utils.h
index b15ca01cf..951ebf773 100644
--- a/src/shared/winutils/utils.h
+++ b/src/shared/winutils/utils.h
@@ -46,7 +46,6 @@ enum PlatformFlag {
// OS
WindowsBased = 0x00001,
UnixBased = 0x00002,
- WinRt = 0x00004,
// CPU
IntelBased = 0x00010,
ArmBased = 0x00020,
@@ -60,8 +59,6 @@ enum PlatformFlag {
WindowsDesktopMinGW = WindowsBased + IntelBased + MinGW,
WindowsDesktopClangMsvc = WindowsBased + IntelBased + ClangMsvc,
WindowsDesktopClangMinGW = WindowsBased + IntelBased + ClangMinGW,
- WinRtIntelMsvc = WindowsBased + WinRt + IntelBased + Msvc,
- WinRtArmMsvc = WindowsBased + WinRt + ArmBased + Msvc,
Unix = UnixBased,
UnknownPlatform
};
diff --git a/src/src.pro b/src/src.pro
index 9ecfc82b4..8c75a8cd8 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -40,9 +40,8 @@ macos {
qtHaveModule(dbus): SUBDIRS += qdbus
-win32|winrt:SUBDIRS += windeployqt
-winrt:SUBDIRS += winrtrunner
-qtHaveModule(gui):qtConfig(commandlineparser):!wasm:!android:!uikit:!qnx:!winrt: SUBDIRS += qtdiag
+win32:SUBDIRS += windeployqt
+qtHaveModule(gui):qtConfig(commandlineparser):!wasm:!android:!uikit:!qnx: SUBDIRS += qtdiag
qtNomakeTools( \
distancefieldgenerator \
@@ -54,6 +53,5 @@ qtNomakeTools( \
cross_compile:isEmpty(QMAKE_HOST_CXX.INCDIRS) {
qdoc.depends += qtattributionsscanner
windeployqt.depends += qtattributionsscanner
- winrtrunner.depends += qtattributionsscanner
linguist.depends += qtattributionsscanner
}
diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp
index 47395f628..cc6a3944a 100644
--- a/src/windeployqt/main.cpp
+++ b/src/windeployqt/main.cpp
@@ -212,10 +212,6 @@ static Platform platformFromMkSpec(const QString &xSpec)
return WindowsDesktopClangMsvc;
return xSpec.contains(QLatin1String("g++")) ? WindowsDesktopMinGW : WindowsDesktopMsvc;
}
- if (xSpec.startsWith(QLatin1String("winrt-x")))
- return WinRtIntelMsvc;
- if (xSpec.startsWith(QLatin1String("winrt-arm")))
- return WinRtArmMsvc;
return UnknownPlatform;
}
@@ -278,8 +274,6 @@ struct Options {
bool dryRun = false;
bool patchQt = true;
bool ignoreLibraryErrors = false;
-
- inline bool isWinRt() const { return platform.testFlag(WinRt); }
};
// Return binary from folder
@@ -902,10 +896,6 @@ QStringList findQtPlugins(quint64 *usedQtModules, quint64 disabledQtModules,
case WindowsDesktopMinGW:
filter = QStringLiteral("qwindows");
break;
- case WinRtIntelMsvc:
- case WinRtArmMsvc:
- filter = QStringLiteral("qwinrt");
- break;
case Unix:
filter = QStringLiteral("libqxcb");
break;
@@ -1002,8 +992,7 @@ static bool deployTranslations(const QString &sourcePath, quint64 usedQtModules,
arguments.append(QDir::toNativeSeparators(targetFilePath));
const QFileInfoList &langQmFiles = sourceDir.entryInfoList(translationNameFilters(usedQtModules, prefix));
for (const QFileInfo &langQmFileFi : langQmFiles) {
- // winrt relies on a proper list of deployed files. We cannot cheat an mention files we do not ship here.
- if (options.json && !options.isWinRt()) {
+ if (options.json) {
options.json->addFile(langQmFileFi.absoluteFilePath(),
absoluteTarget);
}
@@ -1418,7 +1407,7 @@ static DeployResult deploy(const Options &options,
if (softwareRasterizer.isFile())
deployedQtLibraries.append(softwareRasterizer.absoluteFilePath());
}
- if (options.systemD3dCompiler && !options.isWinRt() && machineArch != IMAGE_FILE_MACHINE_ARM64) {
+ if (options.systemD3dCompiler && machineArch != IMAGE_FILE_MACHINE_ARM64) {
const QString d3dCompiler = findD3dCompiler(options.platform, qtBinDir, wordSize);
if (d3dCompiler.isEmpty()) {
std::wcerr << "Warning: Cannot find any version of the d3dcompiler DLL.\n";
@@ -1428,33 +1417,6 @@ static DeployResult deploy(const Options &options,
}
} // Windows
- // We need to copy ucrtbased.dll on WinRT as this library is not part of
- // the c runtime package. VS 2015 does the same when deploying to a device
- // or creating an appx.
- if (result.isDebug && options.platform == WinRtArmMsvc
- && qmakeVariables.value(QStringLiteral("QMAKE_XSPEC")).endsWith(QLatin1String("msvc2015"))) {
- const QString extensionPath = QString::fromLocal8Bit(qgetenv("ExtensionSdkDir"));
- const QString ucrtVersion = QString::fromLocal8Bit(qgetenv("UCRTVersion"));
- if (extensionPath.isEmpty() || ucrtVersion.isEmpty()) {
- std::wcerr << "Warning: Cannot find ucrtbased.dll as either "
- << "ExtensionSdkDir or UCRTVersion is not set in "
- << "your environment.\n";
- } else {
- const QString ucrtbasedLib = extensionPath
- + QStringLiteral("/Microsoft.UniversalCRT.Debug/")
- + ucrtVersion
- + QStringLiteral("/Redist/Debug/arm/ucrtbased.dll");
- const QFileInfo ucrtPath(ucrtbasedLib);
- if (ucrtPath.exists() && ucrtPath.isFile()) {
- deployedQtLibraries.append(ucrtPath.absoluteFilePath());
- } else {
- std::wcerr << "Warning: Cannot find ucrtbased.dll at "
- << QDir::toNativeSeparators(ucrtbasedLib)
- << " or it is not a file.\n";
- }
- }
- }
-
// Update libraries
if (options.libraries) {
const QString targetPath = options.libraryDirectory.isEmpty() ?
@@ -1467,7 +1429,7 @@ static DeployResult deploy(const Options &options,
return result;
}
- if (options.patchQt && !options.dryRun && !options.isWinRt()) {
+ if (options.patchQt && !options.dryRun) {
const QString qt5CoreName = QFileInfo(libraryPath(libraryLocation, "Qt6Core", qtLibInfix,
options.platform, result.isDebug)).fileName();
#ifndef QT_RELOCATABLE
diff --git a/src/winrtrunner/CMakeLists.txt b/src/winrtrunner/CMakeLists.txt
deleted file mode 100644
index 304b67e2b..000000000
--- a/src/winrtrunner/CMakeLists.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-# Generated from winrtrunner.pro.
-
-#####################################################################
-## winrtrunner Tool:
-#####################################################################
-
-qt_get_tool_target_name(target_name winrtrunner)
-qt_add_tool(${target_name}
- BOOTSTRAP
- TARGET_DESCRIPTION "Qt WinRT Runner"
- SOURCES
- ../shared/corecon/ccapi.h
- ../shared/corecon/ccapi_11.h
- ../shared/corecon/ccapi_12.h
- ../shared/corecon/corecon.cpp ../shared/corecon/corecon.h
- ../shared/winutils/elfreader.cpp ../shared/winutils/elfreader.h
- ../shared/winutils/qmlutils.cpp ../shared/winutils/qmlutils.h
- ../shared/winutils/utils.cpp ../shared/winutils/utils.h
- appxengine.cpp appxengine.h appxengine_p.h
- appxlocalengine.cpp appxlocalengine.h
- appxphoneengine.cpp appxphoneengine.h
- main.cpp
- runner.cpp runner.h
- runnerengine.h
- DEFINES
- QT_NO_CAST_FROM_ASCII
- QT_NO_CAST_TO_ASCII
- WINRT_LIBRARY
- INCLUDE_DIRECTORIES
- ../shared/corecon
- ../shared/winutils
- PUBLIC_LIBRARIES
- Shlwapi
- crypt32
- runtimeobject
- urlmon
- wsclient
- xmllite
-)
-
-#### Keys ignored in scope 1:.:.:winrtrunner.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt WinRT Runner"
-# QT_FOR_CONFIG = "tools-private"
-# _OPTION = "host_build"
-# _REQUIREMENTS = "qtConfig(winrtrunner)"
diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp
deleted file mode 100644
index 1f2ee5186..000000000
--- a/src/winrtrunner/appxengine.cpp
+++ /dev/null
@@ -1,801 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "appxengine.h"
-#include "appxengine_p.h"
-
-#include <QtCore/QDateTime>
-#include <QtCore/QDir>
-#include <QtCore/QDirIterator>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QStandardPaths>
-#include <QtCore/QRegularExpression>
-
-#include <ShlObj.h>
-#include <Shlwapi.h>
-#include <wsdevlicensing.h>
-#include <AppxPackaging.h>
-#include <wrl.h>
-#include <windows.applicationmodel.h>
-#include <windows.management.deployment.h>
-#include <wincrypt.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;
-
-QT_USE_NAMESPACE
-
-// *********** Taken from MSDN Example code
-// https://msdn.microsoft.com/en-us/library/windows/desktop/jj835834%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
-
-#define SIGNER_SUBJECT_FILE 0x01
-#define SIGNER_NO_ATTR 0x00
-#define SIGNER_CERT_POLICY_CHAIN_NO_ROOT 0x08
-#define SIGNER_CERT_STORE 0x02
-
-typedef struct _SIGNER_FILE_INFO
-{
- DWORD cbSize;
- LPCWSTR pwszFileName;
- HANDLE hFile;
-} SIGNER_FILE_INFO;
-
-typedef struct _SIGNER_BLOB_INFO
-{
- DWORD cbSize;
- GUID *pGuidSubject;
- DWORD cbBlob;
- BYTE *pbBlob;
- LPCWSTR pwszDisplayName;
-} SIGNER_BLOB_INFO;
-
-typedef struct _SIGNER_SUBJECT_INFO
-{
- DWORD cbSize;
- DWORD *pdwIndex;
- DWORD dwSubjectChoice;
- union
- {
- SIGNER_FILE_INFO *pSignerFileInfo;
- SIGNER_BLOB_INFO *pSignerBlobInfo;
- };
-} SIGNER_SUBJECT_INFO, *PSIGNER_SUBJECT_INFO;
-
-typedef struct _SIGNER_ATTR_AUTHCODE
-{
- DWORD cbSize;
- BOOL fCommercial;
- BOOL fIndividual;
- LPCWSTR pwszName;
- LPCWSTR pwszInfo;
-} SIGNER_ATTR_AUTHCODE;
-
-typedef struct _SIGNER_SIGNATURE_INFO
-{
- DWORD cbSize;
- ALG_ID algidHash;
- DWORD dwAttrChoice;
- union
- {
- SIGNER_ATTR_AUTHCODE *pAttrAuthcode;
- };
- PCRYPT_ATTRIBUTES psAuthenticated;
- PCRYPT_ATTRIBUTES psUnauthenticated;
-} SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO;
-
-typedef struct _SIGNER_PROVIDER_INFO
-{
- DWORD cbSize;
- LPCWSTR pwszProviderName;
- DWORD dwProviderType;
- DWORD dwKeySpec;
- DWORD dwPvkChoice;
- union
- {
- LPWSTR pwszPvkFileName;
- LPWSTR pwszKeyContainer;
- };
-} SIGNER_PROVIDER_INFO, *PSIGNER_PROVIDER_INFO;
-
-typedef struct _SIGNER_SPC_CHAIN_INFO
-{
- DWORD cbSize;
- LPCWSTR pwszSpcFile;
- DWORD dwCertPolicy;
- HCERTSTORE hCertStore;
-} SIGNER_SPC_CHAIN_INFO;
-
-typedef struct _SIGNER_CERT_STORE_INFO
-{
- DWORD cbSize;
- PCCERT_CONTEXT pSigningCert;
- DWORD dwCertPolicy;
- HCERTSTORE hCertStore;
-} SIGNER_CERT_STORE_INFO;
-
-typedef struct _SIGNER_CERT
-{
- DWORD cbSize;
- DWORD dwCertChoice;
- union
- {
- LPCWSTR pwszSpcFile;
- SIGNER_CERT_STORE_INFO *pCertStoreInfo;
- SIGNER_SPC_CHAIN_INFO *pSpcChainInfo;
- };
- HWND hwnd;
-} SIGNER_CERT, *PSIGNER_CERT;
-
-typedef struct _SIGNER_CONTEXT
-{
- DWORD cbSize;
- DWORD cbBlob;
- BYTE *pbBlob;
-} SIGNER_CONTEXT, *PSIGNER_CONTEXT;
-
-typedef struct _SIGNER_SIGN_EX2_PARAMS
-{
- DWORD dwFlags;
- PSIGNER_SUBJECT_INFO pSubjectInfo;
- PSIGNER_CERT pSigningCert;
- PSIGNER_SIGNATURE_INFO pSignatureInfo;
- PSIGNER_PROVIDER_INFO pProviderInfo;
- DWORD dwTimestampFlags;
- PCSTR pszAlgorithmOid;
- PCWSTR pwszTimestampURL;
- PCRYPT_ATTRIBUTES pCryptAttrs;
- PVOID pSipData;
- PSIGNER_CONTEXT *pSignerContext;
- PVOID pCryptoPolicy;
- PVOID pReserved;
-} SIGNER_SIGN_EX2_PARAMS, *PSIGNER_SIGN_EX2_PARAMS;
-
-typedef struct _APPX_SIP_CLIENT_DATA
-{
- PSIGNER_SIGN_EX2_PARAMS pSignerParams;
- IUnknown* pAppxSipState;
-} APPX_SIP_CLIENT_DATA, *PAPPX_SIP_CLIENT_DATA;
-
-bool signAppxPackage(PCCERT_CONTEXT signingCertContext, LPCWSTR packageFilePath)
-{
- HRESULT hr = S_OK;
-
- DWORD signerIndex = 0;
-
- SIGNER_FILE_INFO fileInfo = {};
- fileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
- fileInfo.pwszFileName = packageFilePath;
-
- SIGNER_SUBJECT_INFO subjectInfo = {};
- subjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
- subjectInfo.pdwIndex = &signerIndex;
- subjectInfo.dwSubjectChoice = SIGNER_SUBJECT_FILE;
- subjectInfo.pSignerFileInfo = &fileInfo;
-
- SIGNER_CERT_STORE_INFO certStoreInfo = {};
- certStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
- certStoreInfo.dwCertPolicy = SIGNER_CERT_POLICY_CHAIN_NO_ROOT;
- certStoreInfo.pSigningCert = signingCertContext;
-
- SIGNER_CERT cert = {};
- cert.cbSize = sizeof(SIGNER_CERT);
- cert.dwCertChoice = SIGNER_CERT_STORE;
- cert.pCertStoreInfo = &certStoreInfo;
-
- // The algidHash of the signature to be created must match the
- // hash algorithm used to create the app package
- SIGNER_SIGNATURE_INFO signatureInfo = {};
- signatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
- signatureInfo.algidHash = CALG_SHA_512;
- signatureInfo.dwAttrChoice = SIGNER_NO_ATTR;
-
- SIGNER_SIGN_EX2_PARAMS signerParams = {};
- signerParams.pSubjectInfo = &subjectInfo;
- signerParams.pSigningCert = &cert;
- signerParams.pSignatureInfo = &signatureInfo;
-
- APPX_SIP_CLIENT_DATA sipClientData = {};
- sipClientData.pSignerParams = &signerParams;
- signerParams.pSipData = &sipClientData;
-
- // Type definition for invoking SignerSignEx2 via GetProcAddress
- typedef HRESULT (WINAPI *SignerSignEx2Function)(
- DWORD,
- PSIGNER_SUBJECT_INFO,
- PSIGNER_CERT,
- PSIGNER_SIGNATURE_INFO,
- PSIGNER_PROVIDER_INFO,
- DWORD,
- PCSTR,
- PCWSTR,
- PCRYPT_ATTRIBUTES,
- PVOID,
- PSIGNER_CONTEXT *,
- PVOID,
- PVOID);
-
- // Load the SignerSignEx2 function from MSSign32.dll
- HMODULE msSignModule = LoadLibraryEx(
- L"MSSign32.dll",
- NULL,
- LOAD_LIBRARY_SEARCH_SYSTEM32);
-
- if (!msSignModule) {
- qCWarning(lcWinRtRunner) << "LoadLibraryEx failed to load MSSign32.dll.";
- return false;
- }
-
- SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
- GetProcAddress(msSignModule, "SignerSignEx2"));
- if (!SignerSignEx2) {
- qCWarning(lcWinRtRunner) << "Could not resolve SignerSignEx2";
- FreeLibrary(msSignModule);
- return false;
- }
- hr = SignerSignEx2(signerParams.dwFlags,
- signerParams.pSubjectInfo,
- signerParams.pSigningCert,
- signerParams.pSignatureInfo,
- signerParams.pProviderInfo,
- signerParams.dwTimestampFlags,
- signerParams.pszAlgorithmOid,
- signerParams.pwszTimestampURL,
- signerParams.pCryptAttrs,
- signerParams.pSipData,
- signerParams.pSignerContext,
- signerParams.pCryptoPolicy,
- signerParams.pReserved);
-
- FreeLibrary(msSignModule);
-
- RETURN_FALSE_IF_FAILED("Could not sign package.");
-
- if (sipClientData.pAppxSipState)
- sipClientData.pAppxSipState->Release();
-
- return true;
-}
-// ************ MSDN
-
-bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest)
-{
- if (!QFile::exists(fileName)) {
- qCWarning(lcWinRtRunner) << fileName << "does not exist.";
- return false;
- }
-
- // If it looks like an appx manifest, we're done
- if (fileName.endsWith(QStringLiteral("AppxManifest.xml"))) {
-
- if (manifest)
- *manifest = fileName;
- return true;
- }
-
- // If it looks like an executable, check that manifest is next to it
- if (fileName.endsWith(QLatin1String(".exe"))) {
- QDir appDir = QFileInfo(fileName).absoluteDir();
- QString manifestFileName = appDir.absoluteFilePath(QStringLiteral("AppxManifest.xml"));
- if (!QFile::exists(manifestFileName)) {
- qCWarning(lcWinRtRunner) << manifestFileName << "does not exist.";
- return false;
- }
-
- if (manifest)
- *manifest = manifestFileName;
- return true;
- }
-
- if (fileName.endsWith(QLatin1String(".appx"))) {
- // For existing appx packages the manifest reader will be
- // instantiated later.
- return true;
- }
-
- qCWarning(lcWinRtRunner) << "Appx: unable to determine manifest for" << fileName << ".";
- return false;
-}
-
-#define CHECK_RESULT(errorMessage, action)\
- do {\
- if (FAILED(hr)) {\
- qCWarning(lcWinRtRunner).nospace() << errorMessage " (0x"\
- << QByteArray::number(hr, 16).constData()\
- << ' ' << qt_error_string(hr) << ')';\
- action;\
- }\
- } while (false)
-
-#define CHECK_RESULT_FATAL(errorMessage, action)\
- do {CHECK_RESULT(errorMessage, d->hasFatalError = true; action;);} while (false)
-
-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;
- }
-}
-
-AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
- : d_ptr(dd)
-{
- Q_D(AppxEngine);
- if (d->hasFatalError)
- return;
-
- d->runner = runner;
- d->processHandle = NULL;
- d->pid = -1;
- d->exitCode = UINT_MAX;
-
- 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);
-
- hr = CoCreateInstance(CLSID_AppxFactory, nullptr, CLSCTX_INPROC_SERVER,
- IID_IAppxFactory, &d->packageFactory);
- CHECK_RESULT_FATAL("Failed to instantiate package factory.", return);
-
- bool existingPackage = runner->app().endsWith(QLatin1String(".appx"));
-
- if (existingPackage) {
- ComPtr<IStream> appxStream;
- hr = SHCreateStreamOnFile(wchar(runner->app()), STGM_READ, &appxStream);
- CHECK_RESULT_FATAL("Failed to open appx stream.", return);
-
- ComPtr<IAppxPackageReader> packageReader;
- hr = d->packageFactory->CreatePackageReader(appxStream.Get(), &packageReader);
- if (FAILED(hr)) {
- qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate package reader. (0x"
- << QByteArray::number(hr, 16).constData()
- << ' ' << qt_error_string(hr) << ')';
- d->hasFatalError = true;
- return;
- }
-
- hr = packageReader->GetManifest(&d->manifestReader);
- if (FAILED(hr)) {
- qCWarning(lcWinRtRunner).nospace() << "Failed to query manifext reader from package";
- d->hasFatalError = true;
- return;
- }
- } else {
- if (!getManifestFile(runner->app(), &d->manifest)) {
- qCWarning(lcWinRtRunner) << "Unable to determine manifest file from" << runner->app();
- d->hasFatalError = true;
- return;
- }
-
- ComPtr<IStream> manifestStream;
- hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
- CHECK_RESULT_FATAL("Failed to open manifest stream.", return);
-
- hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &d->manifestReader);
- if (FAILED(hr)) {
- qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate manifest reader. (0x"
- << QByteArray::number(hr, 16).constData()
- << ' ' << qt_error_string(hr) << ')';
- // ### TODO: read detailed error from event log directly
- if (hr == APPX_E_INVALID_MANIFEST) {
- qCWarning(lcWinRtRunner) << "More information on the error can "
- "be found in the event log under "
- "Microsoft\\Windows\\AppxPackagingOM";
- }
- d->hasFatalError = true;
- return;
- }
- }
- ComPtr<IAppxManifestPackageId> packageId;
- hr = d->manifestReader->GetPackageId(&packageId);
- CHECK_RESULT_FATAL("Unable to obtain the package ID from the manifest.", return);
-
- APPX_PACKAGE_ARCHITECTURE arch;
- hr = packageId->GetArchitecture(&arch);
- CHECK_RESULT_FATAL("Failed to retrieve the app's architecture.", return);
- d->packageArchitecture = toProcessorArchitecture(arch);
-
- LPWSTR packageFullName;
- hr = packageId->GetPackageFullName(&packageFullName);
- CHECK_RESULT_FATAL("Unable to obtain the package full name from the manifest.", return);
- d->packageFullName = QString::fromWCharArray(packageFullName);
- CoTaskMemFree(packageFullName);
-
- LPWSTR packageFamilyName;
- hr = packageId->GetPackageFamilyName(&packageFamilyName);
- CHECK_RESULT_FATAL("Unable to obtain the package full family name from the manifest.", return);
- d->packageFamilyName = QString::fromWCharArray(packageFamilyName);
- CoTaskMemFree(packageFamilyName);
-
- LPWSTR publisher;
- packageId->GetPublisher(&publisher);
- CHECK_RESULT_FATAL("Failed to retrieve publisher name from package.", return);
- d->publisherName = QString::fromWCharArray(publisher);
- CoTaskMemFree(publisher);
-
- ComPtr<IAppxManifestApplicationsEnumerator> applications;
- hr = d->manifestReader->GetApplications(&applications);
- CHECK_RESULT_FATAL("Failed to get a list of applications from the manifest.", return);
-
- BOOL hasCurrent;
- hr = applications->GetHasCurrent(&hasCurrent);
- CHECK_RESULT_FATAL("Failed to iterate over applications in the manifest.", return);
-
- // For now, we are only interested in the first application
- ComPtr<IAppxManifestApplication> application;
- hr = applications->GetCurrent(&application);
- CHECK_RESULT_FATAL("Failed to access the first application in the manifest.", return);
-
- LPWSTR executable;
- application->GetStringValue(L"Executable", &executable);
- CHECK_RESULT_FATAL("Failed to retrieve the application executable from the manifest.", return);
- d->executable = QFileInfo(runner->app()).absoluteDir()
- .absoluteFilePath(QString::fromWCharArray(executable));
- CoTaskMemFree(executable);
-
- ComPtr<IAppxManifestPackageDependenciesEnumerator> dependencies;
- hr = d->manifestReader->GetPackageDependencies(&dependencies);
- CHECK_RESULT_FATAL("Failed to retrieve the package dependencies from the manifest.", return);
-
- hr = dependencies->GetHasCurrent(&hasCurrent);
- CHECK_RESULT_FATAL("Failed to iterate over dependencies in the manifest.", return);
- while (SUCCEEDED(hr) && hasCurrent) {
- ComPtr<IAppxManifestPackageDependency> dependency;
- hr = dependencies->GetCurrent(&dependency);
- CHECK_RESULT_FATAL("Failed to access dependency in the manifest.", return);
-
- LPWSTR name;
- hr = dependency->GetName(&name);
- CHECK_RESULT_FATAL("Failed to access dependency name.", return);
- d->dependencies.insert(QString::fromWCharArray(name));
- CoTaskMemFree(name);
- hr = dependencies->MoveNext(&hasCurrent);
- }
-}
-
-AppxEngine::~AppxEngine()
-{
- Q_D(const AppxEngine);
- CloseHandle(d->processHandle);
-}
-
-qint64 AppxEngine::pid() const
-{
- Q_D(const AppxEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- return d->pid;
-}
-
-int AppxEngine::exitCode() const
-{
- Q_D(const AppxEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- return d->exitCode == UINT_MAX ? -1 : HRESULT_CODE(d->exitCode);
-}
-
-QString AppxEngine::executable() const
-{
- Q_D(const AppxEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- return d->executable;
-}
-
-bool AppxEngine::installDependencies()
-{
- Q_D(AppxEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- QSet<QString> toInstall;
- for (const QString &dependencyName : qAsConst(d->dependencies)) {
- toInstall.insert(dependencyName);
- qCDebug(lcWinRtRunner).nospace()
- << "dependency to be installed: " << dependencyName;
- }
-
- if (toInstall.isEmpty())
- return true;
-
- const QString extensionSdkDir = extensionSdkPath();
- if (!QFile::exists(extensionSdkDir)) {
- qCWarning(lcWinRtRunner).nospace().noquote()
- << QStringLiteral("The directory \"%1\" does not exist.").arg(
- QDir::toNativeSeparators(extensionSdkDir));
- return false;
- }
- qCDebug(lcWinRtRunner).nospace().noquote()
- << "looking for dependency packages in \""
- << QDir::toNativeSeparators(extensionSdkDir) << '"';
- QDirIterator dit(extensionSdkDir, QStringList() << QStringLiteral("*.appx"),
- QDir::Files,
- QDirIterator::Subdirectories);
- while (dit.hasNext()) {
- dit.next();
-
- HRESULT hr;
- ComPtr<IStream> inputStream;
- forever {
- hr = SHCreateStreamOnFileEx(wchar(dit.filePath()),
- STGM_READ | STGM_SHARE_EXCLUSIVE,
- 0, FALSE, NULL, &inputStream);
- if (HRESULT_CODE(hr) == ERROR_SHARING_VIOLATION) {
- qCWarning(lcWinRtRunner).nospace()
- << "Input stream is locked by another process. Will retry...";
- Sleep(1000);
- } else {
- break;
- }
- }
- CHECK_RESULT("Failed to create input stream for package in ExtensionSdkDir.", continue);
-
- ComPtr<IAppxPackageReader> packageReader;
- hr = d->packageFactory->CreatePackageReader(inputStream.Get(), &packageReader);
- CHECK_RESULT("Failed to create package reader for package in ExtensionSdkDir.", continue);
-
- ComPtr<IAppxManifestReader> manifestReader;
- hr = packageReader->GetManifest(&manifestReader);
- CHECK_RESULT("Failed to create manifest reader for package in ExtensionSdkDir.", continue);
-
- ComPtr<IAppxManifestPackageId> packageId;
- hr = manifestReader->GetPackageId(&packageId);
- CHECK_RESULT("Failed to retrieve package id for package in ExtensionSdkDir.", continue);
-
- LPWSTR sz;
- hr = packageId->GetName(&sz);
- CHECK_RESULT("Failed to retrieve name from package in ExtensionSdkDir.", continue);
- const QString name = QString::fromWCharArray(sz);
- CoTaskMemFree(sz);
-
- if (!toInstall.contains(name))
- continue;
-
- APPX_PACKAGE_ARCHITECTURE arch;
- hr = packageId->GetArchitecture(&arch);
- CHECK_RESULT("Failed to retrieve architecture from package in ExtensionSdkDir.", continue);
- if (d->packageArchitecture != arch)
- continue;
-
- qCDebug(lcWinRtRunner).nospace().noquote()
- << "installing dependency \"" << name << "\" from \""
- << QDir::toNativeSeparators(dit.filePath()) << '"';
- if (!installPackage(manifestReader.Get(), dit.filePath())) {
- qCWarning(lcWinRtRunner) << "Failed to install package:" << name;
- return false;
- }
- }
-
- 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;
- }
-
- QRegularExpression pattern(QStringLiteral("^\"([^\"]*)\"\\s*\"([^\"]*)\"$"));
- QRegularExpressionMatch match;
- bool inFileSection = false;
- while (!mappingFile.atEnd()) {
- const QString line = QString::fromUtf8(mappingFile.readLine()).trimmed();
- if (line.startsWith(QLatin1Char('['))) {
- inFileSection = line == QStringLiteral("[Files]");
- continue;
- }
- if (match.captured(2).compare(QStringLiteral("AppxManifest.xml"), Qt::CaseInsensitive) == 0)
- continue;
- if (inFileSection && (match = pattern.match(line)).hasMatch()) {
- QString inputFile = match.captured(1);
- if (!QFile::exists(inputFile))
- inputFile = base.absoluteFilePath(inputFile);
- files.insert(QDir::toNativeSeparators(inputFile), QDir::toNativeSeparators(match.captured(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 all files but filtered artifacts
- const QStringList excludeFileTypes = QStringList()
- << QStringLiteral("ilk") << QStringLiteral("pdb") << QStringLiteral("obj")
- << QStringLiteral("appx");
-
- QDirIterator dirIterator(base.absolutePath(), QDir::Files, QDirIterator::Subdirectories);
- while (dirIterator.hasNext()) {
- const QString filePath = dirIterator.next();
- if (filePath.endsWith(QLatin1String("AppxManifest.xml"), Qt::CaseInsensitive))
- continue;
- const QFileInfo fileInfo(filePath);
- if (!excludeFileTypes.contains(fileInfo.suffix()))
- 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;
-}
-
-bool AppxEngine::sign(const QString &fileName)
-{
- Q_D(const AppxEngine);
- BYTE buffer[256];
- DWORD bufferSize = 256;
-
- if (!CertStrToName(X509_ASN_ENCODING, wchar(d->publisherName), CERT_X500_NAME_STR, 0, buffer, &bufferSize, 0)) {
- qCWarning(lcWinRtRunner) << "CertStrToName failed";
- return false;
- }
- CERT_NAME_BLOB certBlob;
- certBlob.cbData = bufferSize;
- certBlob.pbData = buffer;
-
- CRYPT_ALGORITHM_IDENTIFIER identifier;
- identifier.pszObjId = strdup(szOID_RSA_SHA256RSA);
- identifier.Parameters.cbData = 0;
- identifier.Parameters.pbData = NULL;
-
- CERT_EXTENSIONS extensions;
- extensions.cExtension = 2;
- extensions.rgExtension = new CERT_EXTENSION[2];
-
- // Basic Constraints
- CERT_BASIC_CONSTRAINTS2_INFO constraintsInfo;
- constraintsInfo.fCA = FALSE;
- constraintsInfo.fPathLenConstraint = FALSE;
- constraintsInfo.dwPathLenConstraint = 0;
-
- BYTE *constraintsEncoded = NULL;
- DWORD encodedSize = 0;
- CryptEncodeObject(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &constraintsInfo,
- constraintsEncoded, &encodedSize);
- constraintsEncoded = new BYTE[encodedSize];
- if (!CryptEncodeObject(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &constraintsInfo,
- constraintsEncoded, &encodedSize)) {
- qCWarning(lcWinRtRunner) << "Could not encode basic constraints.";
- delete [] constraintsEncoded;
- return false;
- }
-
- extensions.rgExtension[0].pszObjId = strdup(szOID_BASIC_CONSTRAINTS2);
- extensions.rgExtension[0].fCritical = TRUE;
- extensions.rgExtension[0].Value.cbData = encodedSize;
- extensions.rgExtension[0].Value.pbData = constraintsEncoded;
-
- // Code Signing
- char *codeSign = strdup(szOID_PKIX_KP_CODE_SIGNING);
- CERT_ENHKEY_USAGE enhancedUsage;
- enhancedUsage.cUsageIdentifier = 1;
- enhancedUsage.rgpszUsageIdentifier = &codeSign;
-
- BYTE *enhancedKeyEncoded = 0;
- encodedSize = 0;
- CryptEncodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &enhancedUsage,
- enhancedKeyEncoded, &encodedSize);
- enhancedKeyEncoded = new BYTE[encodedSize];
- if (!CryptEncodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &enhancedUsage,
- enhancedKeyEncoded, &encodedSize)) {
- qCWarning(lcWinRtRunner) << "Could not encode enhanced key usage.";
- delete [] constraintsEncoded;
- return false;
- }
-
- extensions.rgExtension[1].pszObjId = strdup(szOID_ENHANCED_KEY_USAGE);
- extensions.rgExtension[1].fCritical = TRUE;
- extensions.rgExtension[1].Value.cbData = encodedSize;
- extensions.rgExtension[1].Value.pbData = enhancedKeyEncoded;
-
- PCCERT_CONTEXT context = CertCreateSelfSignCertificate(NULL, &certBlob, NULL, NULL,
- &identifier, NULL, NULL, &extensions);
-
- delete [] constraintsEncoded;
-
- if (!context) {
- qCWarning(lcWinRtRunner) << "Failed to create self sign certificate:" << GetLastError();
- return false;
- }
-
- return signAppxPackage(context, wchar(fileName));
-}
diff --git a/src/winrtrunner/appxengine.h b/src/winrtrunner/appxengine.h
deleted file mode 100644
index c2d235ec6..000000000
--- a/src/winrtrunner/appxengine.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef APPXENGINE_H
-#define APPXENGINE_H
-
-#include "runnerengine.h"
-#include "runner.h"
-
-#include <QtCore/QScopedPointer>
-#include <QtCore/QString>
-
-QT_USE_NAMESPACE
-
-struct IAppxManifestReader;
-class AppxEnginePrivate;
-class AppxEngine : public RunnerEngine
-{
-public:
- qint64 pid() const override;
- int exitCode() const override;
- QString executable() const override;
-
-protected:
- explicit AppxEngine(Runner *runner, AppxEnginePrivate *dd);
- ~AppxEngine();
-
- virtual QString extensionSdkPath() const = 0;
- virtual bool installPackage(IAppxManifestReader *reader, const QString &filePath) = 0;
-
- bool installDependencies();
- bool createPackage(const QString &packageFileName);
- bool sign(const QString &fileName);
- static bool getManifestFile(const QString &fileName, QString *manifest = 0);
-
- QScopedPointer<AppxEnginePrivate> d_ptr;
- Q_DECLARE_PRIVATE(AppxEngine)
-};
-
-#endif // APPXENGINE_H
diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h
deleted file mode 100644
index 5caa2810e..000000000
--- a/src/winrtrunner/appxengine_p.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef APPXENGINE_P_H
-#define APPXENGINE_P_H
-
-#include <QtCore/qt_windows.h>
-#include <QtCore/QSet>
-#include <QtCore/QString>
-
-#include <wrl.h>
-#include <windows.system.h>
-
-QT_USE_NAMESPACE
-
-class Runner;
-struct IAppxFactory;
-class AppxEnginePrivate
-{
-public:
- 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()
- {
- uriFactory.Reset();
- packageFactory.Reset();
- manifestReader.Reset();
- CoUninitialize();
- }
-
- Runner *runner;
- bool hasFatalError;
-
- QString manifest;
- QString packageFullName;
- QString packageFamilyName;
- QString publisherName;
- ABI::Windows::System::ProcessorArchitecture packageArchitecture;
- QString executable;
- qint64 pid;
- HANDLE processHandle;
- DWORD exitCode;
- QSet<QString> dependencies;
- QSet<QString> installedPackages;
-
- Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IUriRuntimeClassFactory> uriFactory;
- Microsoft::WRL::ComPtr<IAppxFactory> packageFactory;
- Microsoft::WRL::ComPtr<IAppxManifestReader> manifestReader;
-};
-
-#define wchar(str) reinterpret_cast<LPCWSTR>(str.utf16())
-#define hStringFromQString(str) HStringReference(reinterpret_cast<const wchar_t *>(str.utf16())).Get()
-#define QStringFromHString(hstr) QString::fromWCharArray(WindowsGetStringRawBuffer(hstr, nullptr))
-
-#define RETURN_IF_FAILED(msg, ret) \
- if (FAILED(hr)) { \
- qCWarning(lcWinRtRunner).nospace() << msg << ": 0x" << QByteArray::number(hr, 16).constData() \
- << ' ' << qt_error_string(hr); \
- ret; \
- }
-
-#define RETURN_HR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return hr)
-#define RETURN_OK_IF_FAILED(msg) RETURN_IF_FAILED(msg, return S_OK)
-#define RETURN_FALSE_IF_FAILED(msg) RETURN_IF_FAILED(msg, return false)
-#define RETURN_VOID_IF_FAILED(msg) RETURN_IF_FAILED(msg, return)
-
-#endif // APPXENGINE_P_H
diff --git a/src/winrtrunner/appxlocalengine.cpp b/src/winrtrunner/appxlocalengine.cpp
deleted file mode 100644
index 69bc39919..000000000
--- a/src/winrtrunner/appxlocalengine.cpp
+++ /dev/null
@@ -1,884 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "appxlocalengine.h"
-#include "appxengine_p.h"
-
-#include "utils.h"
-
-#include <QtCore/QDateTime>
-#include <QtCore/QDir>
-#include <QtCore/QDirIterator>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QLoggingCategory>
-#include <QtCore/QStandardPaths>
-#include <QtCore/QOperatingSystemVersion>
-
-#include <ShlObj.h>
-#include <Shlwapi.h>
-#include <wsdevlicensing.h>
-#include <AppxPackaging.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;
-
-typedef IAsyncOperationWithProgressCompletedHandler<DeploymentResult *, DeploymentProgress> DeploymentResultHandler;
-typedef IAsyncOperationWithProgress<DeploymentResult *, DeploymentProgress> DeploymentOperation;
-
-QT_USE_NAMESPACE
-
-// 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;
-}
-
-QString sidForPackage(const QString &packageFamilyName)
-{
- QString sid;
- HKEY regKey;
- LONG result = RegOpenKeyEx(
- HKEY_CLASSES_ROOT,
- L"Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Mappings",
- 0, KEY_READ, &regKey);
- if (result != ERROR_SUCCESS) {
- qCWarning(lcWinRtRunner) << "Unable to open registry key:" << qt_error_string(result);
- return sid;
- }
-
- DWORD index = 0;
- wchar_t subKey[MAX_PATH];
- const wchar_t *packageFamilyNameW = wchar(packageFamilyName);
- forever {
- result = RegEnumKey(regKey, index++, subKey, MAX_PATH);
- if (result != ERROR_SUCCESS)
- break;
- wchar_t moniker[MAX_PATH];
- DWORD monikerSize = MAX_PATH;
- result = RegGetValue(regKey, subKey, L"Moniker", RRF_RT_REG_SZ, NULL, moniker, &monikerSize);
- if (result != ERROR_SUCCESS)
- continue;
- if (lstrcmp(moniker, packageFamilyNameW) == 0) {
- sid = QString::fromWCharArray(subKey);
- break;
- }
- }
- RegCloseKey(regKey);
- return sid;
-}
-
-class OutputDebugMonitor
-{
-public:
- OutputDebugMonitor()
- : runLock(CreateEvent(NULL, FALSE, FALSE, NULL)), thread(0)
- {
- }
- ~OutputDebugMonitor()
- {
- if (runLock) {
- SetEvent(runLock);
- CloseHandle(runLock);
- }
- if (thread) {
- WaitForSingleObject(thread, INFINITE);
- CloseHandle(thread);
- }
- }
- void start(const QString &packageFamilyName)
- {
- if (thread) {
- qCWarning(lcWinRtRunner) << "OutputDebugMonitor is already running.";
- return;
- }
-
- package = packageFamilyName;
-
- thread = CreateThread(NULL, 0, &monitor, this, NULL, NULL);
- if (!thread) {
- qCWarning(lcWinRtRunner) << "Unable to create thread for app debugging:"
- << qt_error_string(GetLastError());
- return;
- }
-
- return;
- }
-private:
- static DWORD __stdcall monitor(LPVOID param)
- {
- OutputDebugMonitor *that = static_cast<OutputDebugMonitor *>(param);
-
- const QString handleBase = QStringLiteral("Local\\AppContainerNamedObjects\\")
- + sidForPackage(that->package);
- const QString eventName = handleBase + QStringLiteral("\\qdebug-event");
- const QString ackEventName = handleBase + QStringLiteral("\\qdebug-event-ack");
- const QString shmemName = handleBase + QStringLiteral("\\qdebug-shmem");
-
- HANDLE event = CreateEvent(NULL, FALSE, FALSE, reinterpret_cast<LPCWSTR>(eventName.utf16()));
- if (!event) {
- qCWarning(lcWinRtRunner) << "Unable to open shared event for app debugging:"
- << qt_error_string(GetLastError());
- return 1;
- }
-
- HANDLE ackEvent = CreateEvent(NULL, FALSE, FALSE, reinterpret_cast<LPCWSTR>(ackEventName.utf16()));
- if (!ackEvent) {
- qCWarning(lcWinRtRunner) << "Unable to open shared acknowledge event for app debugging:"
- << qt_error_string(GetLastError());
- return 1;
- }
-
- HANDLE shmem = 0;
- DWORD ret = 0;
- quint64 size = 4096;
- const quint32 resizeMessageType = QtInfoMsg + 1;
- HANDLE handles[] = { that->runLock, event };
- forever {
- DWORD result = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
-
- // runLock set; exit thread
- if (result == WAIT_OBJECT_0)
- break;
-
- if (result == WAIT_OBJECT_0 + 1) {
- if (!shmem) {
- shmem = OpenFileMapping(GENERIC_READ, FALSE,
- reinterpret_cast<LPCWSTR>(shmemName.utf16()));
- if (!shmem) {
- qCWarning(lcWinRtRunner) << "Unable to open shared memory for app debugging:"
- << qt_error_string(GetLastError());
- ret = 1;
- break;
- }
- }
-
- const quint32 *data = reinterpret_cast<const quint32 *>(
- MapViewOfFile(shmem, FILE_MAP_READ, 0, 0, size));
- if (!data) {
- qCWarning(lcWinRtRunner) << "Unable to map view of shared memory for app debugging:"
- << qt_error_string(GetLastError());
- ret = 1;
- break;
- }
- const quint32 type = data[0];
- // resize message received; Resize shared memory
- if (type == resizeMessageType) {
- size = (data[2] << 8) + data[1];
- if (!UnmapViewOfFile(data)) {
- qCWarning(lcWinRtRunner) << "Unable to unmap view of shared memory for app debugging:"
- << qt_error_string(GetLastError());
- ret = 1;
- break;
- }
- if (shmem) {
- if (!CloseHandle(shmem)) {
- qCWarning(lcWinRtRunner) << "Unable to close shared memory handle:"
- << qt_error_string(GetLastError());
- ret = 1;
- break;
- }
- shmem = 0;
- }
- SetEvent(ackEvent);
- continue;
- }
-
- // debug event set; print message
- QtMsgType messageType = static_cast<QtMsgType>(type);
- QString message = QString::fromWCharArray(
- reinterpret_cast<const wchar_t *>(data + 1));
- UnmapViewOfFile(data);
- SetEvent(ackEvent);
- switch (messageType) {
- default:
- case QtDebugMsg:
- qCDebug(lcWinRtRunnerApp, qPrintable(message));
- break;
- case QtWarningMsg:
- qCWarning(lcWinRtRunnerApp, qPrintable(message));
- break;
- case QtCriticalMsg:
- case QtFatalMsg:
- qCCritical(lcWinRtRunnerApp, qPrintable(message));
- break;
- }
- continue;
- }
-
- // An error occurred; exit thread
- qCWarning(lcWinRtRunner) << "Debug output monitor error:"
- << qt_error_string(GetLastError());
- ret = 1;
- break;
- }
- if (shmem)
- CloseHandle(shmem);
- if (event)
- CloseHandle(event);
- if (ackEvent)
- CloseHandle(ackEvent);
- return ret;
- }
- HANDLE runLock;
- HANDLE thread;
- QString package;
-};
-Q_GLOBAL_STATIC(OutputDebugMonitor, debugMonitor)
-
-class AppxLocalEnginePrivate : public AppxEnginePrivate
-{
-public:
- ComPtr<IPackageManager> packageManager;
- ComPtr<IApplicationActivationManager> appLauncher;
- ComPtr<IPackageDebugSettings> packageDebug;
-
- Qt::HANDLE loopbackServerProcessHandle = INVALID_HANDLE_VALUE;
-
- void retrieveInstalledPackages();
-};
-
-static bool getManifestFile(const QString &fileName, QString *manifest = 0)
-{
- if (!QFile::exists(fileName)) {
- qCWarning(lcWinRtRunner) << fileName << "does not exist.";
- return false;
- }
-
- // If it looks like an appx manifest, we're done
- if (fileName.endsWith(QStringLiteral("AppxManifest.xml"))) {
-
- if (manifest)
- *manifest = fileName;
- return true;
- }
-
- // If it looks like an executable, check that manifest is next to it
- if (fileName.endsWith(QStringLiteral(".exe"))) {
- QDir appDir = QFileInfo(fileName).absoluteDir();
- QString manifestFileName = appDir.absoluteFilePath(QStringLiteral("AppxManifest.xml"));
- if (!QFile::exists(manifestFileName)) {
- qCWarning(lcWinRtRunner) << manifestFileName << "does not exist.";
- return false;
- }
-
- if (manifest)
- *manifest = manifestFileName;
- return true;
- }
-
- // TODO: handle already-built package as well
-
- qCWarning(lcWinRtRunner) << "Appx: unable to determine manifest for" << fileName << ".";
- return false;
-}
-
-bool AppxLocalEngine::canHandle(Runner *runner)
-{
- return getManifestFile(runner->app());
-}
-
-RunnerEngine *AppxLocalEngine::create(Runner *runner)
-{
- QScopedPointer<AppxLocalEngine> engine(new AppxLocalEngine(runner));
- if (engine->d_ptr->hasFatalError)
- return 0;
-
- return engine.take();
-}
-
-QStringList AppxLocalEngine::deviceNames()
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
- return QStringList(QStringLiteral("local"));
-}
-
-
-
-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;
- }
-}
-
-AppxLocalEngine::AppxLocalEngine(Runner *runner)
- : AppxEngine(runner, new AppxLocalEnginePrivate)
-{
- Q_D(AppxLocalEngine);
- if (d->hasFatalError)
- return;
- d->hasFatalError = true;
-
- HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Management_Deployment_PackageManager).Get(),
- &d->packageManager);
- RETURN_VOID_IF_FAILED("Failed to instantiate package manager");
-
- hr = CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER,
- IID_IApplicationActivationManager, &d->appLauncher);
- RETURN_VOID_IF_FAILED("Failed to instantiate application activation manager");
-
- hr = CoCreateInstance(CLSID_PackageDebugSettings, nullptr, CLSCTX_INPROC_SERVER,
- IID_IPackageDebugSettings, &d->packageDebug);
- RETURN_VOID_IF_FAILED("Failed to instantiate package debug settings");
-
- d->retrieveInstalledPackages();
-
- // Set a break handler for gracefully exiting from long-running operations
- SetConsoleCtrlHandler(&ctrlHandler, true);
- d->hasFatalError = false;
-}
-
-AppxLocalEngine::~AppxLocalEngine()
-{
-}
-
-bool AppxLocalEngine::installPackage(IAppxManifestReader *reader, const QString &filePath)
-{
- Q_D(const AppxLocalEngine);
- qCDebug(lcWinRtRunner).nospace().noquote()
- << __FUNCTION__ << " \"" << QDir::toNativeSeparators(filePath) << '"';
-
- HRESULT hr;
- if (reader) {
- ComPtr<IAppxManifestPackageId> packageId;
- hr = reader->GetPackageId(&packageId);
- RETURN_FALSE_IF_FAILED("Failed to get package ID from reader.");
-
- LPWSTR name;
- hr = packageId->GetName(&name);
- RETURN_FALSE_IF_FAILED("Failed to get package name from package ID.");
-
- const QString packageName = QString::fromWCharArray(name);
- CoTaskMemFree(name);
- if (d->installedPackages.contains(packageName)) {
- qCDebug(lcWinRtRunner) << "The package" << packageName << "is already installed.";
- return true;
- }
- }
-
- const QString nativeFilePath = QDir::toNativeSeparators(QFileInfo(filePath).absoluteFilePath());
- const bool addInsteadOfRegister = nativeFilePath.endsWith(QStringLiteral(".appx"),
- Qt::CaseInsensitive);
- ComPtr<IUriRuntimeClass> uri;
- hr = d->uriFactory->CreateUri(hStringFromQString(nativeFilePath), &uri);
- RETURN_FALSE_IF_FAILED("Failed to create an URI for the package");
-
- ComPtr<DeploymentOperation> deploymentOperation;
- if (addInsteadOfRegister) {
- hr = d->packageManager->AddPackageAsync(uri.Get(), NULL, DeploymentOptions_None,
- &deploymentOperation);
- RETURN_FALSE_IF_FAILED("Failed to add package");
- } else {
- hr = d->packageManager->RegisterPackageAsync(uri.Get(), 0,
- DeploymentOptions_DevelopmentMode,
- &deploymentOperation);
- RETURN_FALSE_IF_FAILED("Failed to start package registration");
- }
-
- HANDLE ev = CreateEvent(NULL, FALSE, FALSE, NULL);
- hr = deploymentOperation->put_Completed(Callback<DeploymentResultHandler>([ev](DeploymentOperation *, AsyncStatus) {
- SetEvent(ev);
- return S_OK;
- }).Get());
- RETURN_FALSE_IF_FAILED("Could not register deployment completed callback.");
- DWORD ret = WaitForSingleObjectEx(ev, 60000, FALSE);
- CloseHandle(ev);
- if (ret != WAIT_OBJECT_0) {
- if (ret == WAIT_TIMEOUT)
- qCWarning(lcWinRtRunner) << "Deployment did not finish within 15 seconds.";
- else
- qCWarning(lcWinRtRunner) << "Deployment finished event was not triggered.";
- return false;
- }
-
- ComPtr<IDeploymentResult> results;
- hr = deploymentOperation->GetResults(&results);
- RETURN_FALSE_IF_FAILED("Failed to retrieve package registration results.");
-
- HRESULT errorCode;
- hr = results->get_ExtendedErrorCode(&errorCode);
- RETURN_FALSE_IF_FAILED("Failed to retrieve extended error code.");
-
- if (FAILED(errorCode)) {
- if (HRESULT_CODE(errorCode) == ERROR_INSTALL_PREREQUISITE_FAILED) {
- qCWarning(lcWinRtRunner) << "Unable to register package: A requirement for installation was not met. "
- "Check that your Windows version matches TargetDeviceFamily's MinVersion set in your AppxManifest.xml.";
- } else {
- HString errorText;
- if (SUCCEEDED(results->get_ErrorText(errorText.GetAddressOf()))) {
- qCWarning(lcWinRtRunner) << "Unable to register package:"
- << QString::fromWCharArray(errorText.GetRawBuffer(NULL));
- }
- }
- if (HRESULT_CODE(errorCode) == ERROR_INSTALL_POLICY_FAILURE) {
- // The user's license has expired. Give them the opportunity to renew it.
- FILETIME expiration;
- hr = AcquireDeveloperLicense(GetForegroundWindow(), &expiration);
- RETURN_FALSE_IF_FAILED("Unable to renew developer license");
- return install(false);
- }
- return false;
- }
-
- return SUCCEEDED(hr);
-}
-
-bool AppxLocalEngine::parseExitCode()
-{
- Q_D(AppxLocalEngine);
- const QString exitFileName(QStringLiteral("exitCode.tmp"));
- bool ok = false;
- QFile exitCodeFile(devicePath(QString::number(pid()).append(QStringLiteral(".pid"))));
- if (exitCodeFile.open(QIODevice::ReadOnly)) {
- d->exitCode = exitCodeFile.readAll().toInt(&ok);
- exitCodeFile.close();
- exitCodeFile.remove();
- }
- if (!ok && !GetExitCodeProcess(d->processHandle, &d->exitCode)) {
- d->exitCode = UINT_MAX;
- qCWarning(lcWinRtRunner).nospace() << "Failed to obtain process exit code.";
- qCDebug(lcWinRtRunner, "GetLastError: 0x%x", GetLastError());
- return false;
- }
- return true;
-}
-
-bool AppxLocalEngine::install(bool removeFirst)
-{
- Q_D(const AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- ComPtr<IPackage> packageInformation;
- HRESULT hr = d->packageManager->FindPackageByUserSecurityIdPackageFullName(
- NULL, hStringFromQString(d->packageFullName), &packageInformation);
- if (SUCCEEDED(hr) && packageInformation) {
- qCWarning(lcWinRtRunner) << "Package already installed.";
- if (removeFirst)
- remove();
- else
- return true;
- }
-
- return installDependencies() && installPackage(nullptr, d->manifest);
-}
-
-bool AppxLocalEngine::remove()
-{
- Q_D(const AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- // ### TODO: use RemovePackageWithOptions to preserve previous state when re-installing
- ComPtr<DeploymentOperation> deploymentOperation;
- HRESULT hr = d->packageManager->RemovePackageAsync(hStringFromQString(d->packageFullName), &deploymentOperation);
- RETURN_FALSE_IF_FAILED("Unable to start package removal");
-
- HANDLE ev = CreateEvent(NULL, FALSE, FALSE, NULL);
- hr = deploymentOperation->put_Completed(Callback<DeploymentResultHandler>([ev](DeploymentOperation *, AsyncStatus) {
- SetEvent(ev);
- return S_OK;
- }).Get());
- RETURN_FALSE_IF_FAILED("Could not register deployment completed callback.");
- DWORD ret = WaitForSingleObjectEx(ev, 60000, FALSE);
- CloseHandle(ev);
- if (ret != WAIT_OBJECT_0) {
- if (ret == WAIT_TIMEOUT)
- qCWarning(lcWinRtRunner) << "Deployment did not finish within 15 seconds.";
- else
- qCWarning(lcWinRtRunner) << "Deployment finished event was not triggered.";
- return false;
- }
-
- ComPtr<IAsyncInfo> asyncInfo;
- hr = deploymentOperation.As(&asyncInfo);
- RETURN_FALSE_IF_FAILED("Failed to cast deployment operation.");
-
- AsyncStatus status;
- hr = asyncInfo->get_Status(&status);
- RETURN_FALSE_IF_FAILED("Failed to retrieve deployment operation's status.");
-
- if (status != Completed) {
- qCWarning(lcWinRtRunner) << "Unable to remove package.";
- return false;
- }
-
- return true;
-}
-
-bool AppxLocalEngine::start()
-{
- Q_D(AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- const QString launchArguments =
- (d->runner->arguments() << QStringLiteral("-qdevel")).join(QLatin1Char(' '));
- DWORD pid;
- const QString activationId = d->packageFamilyName + QStringLiteral("!App");
- HRESULT hr = d->appLauncher->ActivateApplication(wchar(activationId),
- wchar(launchArguments), AO_NONE, &pid);
- RETURN_FALSE_IF_FAILED("Failed to activate application");
- d->pid = qint64(pid);
- CloseHandle(d->processHandle);
- d->processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, pid);
-
- return true;
-}
-
-bool AppxLocalEngine::enableDebugging(const QString &debuggerExecutable, const QString &debuggerArguments)
-{
- Q_D(AppxLocalEngine);
-
- const QString &debuggerCommand = debuggerExecutable + QLatin1Char(' ') + debuggerArguments;
- HRESULT hr = d->packageDebug->EnableDebugging(wchar(d->packageFullName),
- wchar(debuggerCommand),
- NULL);
- RETURN_FALSE_IF_FAILED("Failed to enable debugging for application");
- return true;
-}
-
-bool AppxLocalEngine::disableDebugging()
-{
- Q_D(AppxLocalEngine);
-
- HRESULT hr = d->packageDebug->DisableDebugging(wchar(d->packageFullName));
- RETURN_FALSE_IF_FAILED("Failed to disable debugging for application");
-
- return true;
-}
-
-bool AppxLocalEngine::setLoopbackExemptClientEnabled(bool enabled)
-{
- Q_D(AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__ << enabled;
-
- if (!enabled) {
- PACKAGE_EXECUTION_STATE state;
- HRESULT hr = d->packageDebug->GetPackageExecutionState(wchar(d->packageFullName), &state);
- RETURN_FALSE_IF_FAILED("Failed to get package execution state");
- if (state != PES_TERMINATED && state != PES_UNKNOWN) {
- qCWarning(lcWinRtRunner) << "Cannot unregister loopback exemption for running program."
- << "Please use checknetisolation.exe to check/clean up the exemption list.";
- return false;
- }
- }
-
- QByteArray stdOut;
- QByteArray stdErr;
- unsigned long exitCode = 0;
- QString errorMessage;
- QStringList arguments;
- const QString binary = QStringLiteral("checknetisolation.exe");
- arguments << QStringLiteral("LoopbackExempt")
- << (enabled ? QStringLiteral("-a") : QStringLiteral("-d"))
- << QStringLiteral("-p=") + sidForPackage(d->packageFamilyName);
- if (!runProcess(binary, arguments, QString(), &exitCode, &stdOut, &stdErr, &errorMessage)) {
- qCWarning(lcWinRtRunner) << "Could not run" << binary;
- return false;
- }
- if (exitCode) {
- if (errorMessage.isEmpty()) {
- errorMessage = binary + QStringLiteral(" returned ") + QString::number(exitCode)
- + QStringLiteral(": ") + QString::fromLocal8Bit(stdErr);
- }
- qCWarning(lcWinRtRunner) << errorMessage;
- return false;
- }
- return true;
-}
-
-bool AppxLocalEngine::setLoopbackExemptServerEnabled(bool enabled)
-{
- Q_D(AppxLocalEngine);
- const QOperatingSystemVersion minimal
- = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393);
- if (QOperatingSystemVersion::current() < minimal) {
- qCWarning(lcWinRtRunner) << "Cannot enable loopback exemption for servers. If you want"
- << "to use this feature please update to a Windows version >="
- << minimal;
- return false;
- }
-
- if (enabled) {
- QStringList arguments;
- const QString binary = QStringLiteral("checknetisolation.exe");
- arguments << QStringLiteral("LoopbackExempt") << QStringLiteral("-is")
- << QStringLiteral("-p=") + sidForPackage(d->packageFamilyName);
- if (!runElevatedBackgroundProcess(binary, arguments, &d->loopbackServerProcessHandle)) {
- qCWarning(lcWinRtRunner) << "Could not start" << binary;
- return false;
- }
- } else {
- if (d->loopbackServerProcessHandle != INVALID_HANDLE_VALUE) {
- if (!TerminateProcess(d->loopbackServerProcessHandle, 0)) {
- qCWarning(lcWinRtRunner) << "Could not terminate loopbackexempt debug session";
- return false;
- }
- if (!CloseHandle(d->loopbackServerProcessHandle)) {
- qCWarning(lcWinRtRunner) << "Could not close loopbackexempt debug session process handle";
- return false;
- }
- } else {
- qCWarning(lcWinRtRunner) << "loopbackexempt debug session could not be found";
- return false;
- }
- }
- return true;
-}
-
-bool AppxLocalEngine::setLoggingRules(const QByteArray &rules)
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- QDir loggingIniDir(devicePath(QLatin1String("QtProject")));
- if (!loggingIniDir.exists() && !loggingIniDir.mkpath(QStringLiteral("."))) {
- qCWarning(lcWinRtRunner) << "Could not create" << loggingIniDir;
- return false;
- }
- QFile loggingIniFile(loggingIniDir.absolutePath().append(QLatin1String("/qtlogging.ini")));
- if (loggingIniFile.exists() && !loggingIniFile.remove()) {
- qCWarning(lcWinRtRunner) << loggingIniFile << "already exists.";
- return false;
- }
- if (!loggingIniFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
- qCWarning(lcWinRtRunner) << "Could not open" << loggingIniFile << "for writing.";
- return false;
- }
-
- QTextStream stream(&loggingIniFile);
- stream << "[Rules]\n" << rules;
-
- return true;
-}
-
-
-bool AppxLocalEngine::suspend()
-{
- Q_D(AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- HRESULT hr = d->packageDebug->Suspend(wchar(d->packageFullName));
- RETURN_FALSE_IF_FAILED("Failed to suspend application");
-
- return true;
-}
-
-bool AppxLocalEngine::waitForFinished(int secs)
-{
- Q_D(AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- debugMonitor->start(d->packageFamilyName);
-
- g_handleCtrl = true;
- int time = 0;
- forever {
- PACKAGE_EXECUTION_STATE state;
- HRESULT hr = d->packageDebug->GetPackageExecutionState(wchar(d->packageFullName), &state);
- RETURN_FALSE_IF_FAILED("Failed to get package execution state");
- qCDebug(lcWinRtRunner) << "Current execution state:" << state;
- if (state == PES_TERMINATED || state == PES_UNKNOWN)
- break;
-
- ++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;
-
- if (!GetExitCodeProcess(d->processHandle, &d->exitCode))
- d->exitCode = UINT_MAX;
-
- return true;
-}
-
-bool AppxLocalEngine::stop()
-{
- Q_D(AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- // ### We won't have a process handle if we didn't start the app. We can look it up
- // using a process snapshot, or by calling start if we know the process is already running.
- // For now, simply continue normally, but don't fetch the exit code.
- if (!d->processHandle)
- qCDebug(lcWinRtRunner) << "No handle to the process; the exit code won't be available.";
-
- if (d->processHandle && !parseExitCode()) {
- return false;
- }
-
- if (!d->processHandle || d->exitCode == STILL_ACTIVE) {
- HRESULT hr = d->packageDebug->TerminateAllProcesses(wchar(d->packageFullName));
- RETURN_FALSE_IF_FAILED("Failed to terminate package process");
-
- if (d->processHandle && !GetExitCodeProcess(d->processHandle, &d->exitCode))
- d->exitCode = UINT_MAX;
- }
-
- return true;
-}
-
-QString AppxLocalEngine::devicePath(const QString &relativePath) const
-{
- Q_D(const AppxLocalEngine);
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- // Return a path safe for passing to the application
- QDir localAppDataPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
- const QString path = localAppDataPath.absoluteFilePath(
- QStringLiteral("Packages/") + d->packageFamilyName
- + QStringLiteral("/LocalState/") + relativePath);
- return QDir::toNativeSeparators(path);
-}
-
-bool AppxLocalEngine::sendFile(const QString &localFile, const QString &deviceFile)
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- // Both files are local, just use QFile
- QFile source(localFile);
-
- // Remove the destination, or copy will fail
- if (QFileInfo(source) != QFileInfo(deviceFile))
- QFile::remove(deviceFile);
-
- bool result = source.copy(deviceFile);
- if (!result) {
- qCWarning(lcWinRtRunner).nospace().noquote()
- << "Unable to sendFile: " << source.errorString();
- }
-
- return result;
-}
-
-bool AppxLocalEngine::receiveFile(const QString &deviceFile, const QString &localFile)
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- // Both files are local, so just reverse the sendFile arguments
- return sendFile(deviceFile, localFile);
-}
-
-QString AppxLocalEngine::extensionSdkPath() const
-{
- const QByteArray extensionSdkDirRaw = qgetenv("ExtensionSdkDir");
- if (extensionSdkDirRaw.isEmpty()) {
- qCWarning(lcWinRtRunner) << "The environment variable ExtensionSdkDir is not set.";
- return QString();
- }
- return QString::fromLocal8Bit(extensionSdkDirRaw);
-}
-
-void AppxLocalEnginePrivate::retrieveInstalledPackages()
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- ComPtr<ABI::Windows::Foundation::Collections::IIterable<Package*>> packages;
- HRESULT hr = packageManager->FindPackagesByUserSecurityId(NULL, &packages);
- RETURN_VOID_IF_FAILED("Failed to find packages");
-
- ComPtr<ABI::Windows::Foundation::Collections::IIterator<Package*>> pkgit;
- hr = packages->First(&pkgit);
- RETURN_VOID_IF_FAILED("Failed to get package iterator");
-
- boolean hasCurrent;
- hr = pkgit->get_HasCurrent(&hasCurrent);
- while (SUCCEEDED(hr) && hasCurrent) {
- ComPtr<IPackage> pkg;
- hr = pkgit->get_Current(&pkg);
- RETURN_VOID_IF_FAILED("Failed to get current package");
-
- ComPtr<IPackageId> pkgId;
- hr = pkg->get_Id(&pkgId);
- RETURN_VOID_IF_FAILED("Failed to get package id");
-
- HString name;
- hr = pkgId->get_Name(name.GetAddressOf());
- RETURN_VOID_IF_FAILED("Failed retrieve package name");
-
- ProcessorArchitecture architecture;
- if (packageArchitecture == ProcessorArchitecture_Neutral) {
- architecture = packageArchitecture;
- } else {
- hr = pkgId->get_Architecture(&architecture);
- RETURN_VOID_IF_FAILED("Failed to retrieve package architecture");
- }
-
- const QString pkgName = QStringFromHString(name.Get());
- qCDebug(lcWinRtRunner) << "found installed package" << pkgName;
-
- if (architecture == packageArchitecture)
- installedPackages.insert(pkgName);
-
- hr = pkgit->MoveNext(&hasCurrent);
- }
-}
diff --git a/src/winrtrunner/appxlocalengine.h b/src/winrtrunner/appxlocalengine.h
deleted file mode 100644
index 0049b6ba4..000000000
--- a/src/winrtrunner/appxlocalengine.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef APPXLOCALENGINE_H
-#define APPXLOCALENGINE_H
-
-#include "appxengine.h"
-#include "runner.h"
-
-#include <QtCore/QScopedPointer>
-#include <QtCore/QString>
-
-QT_USE_NAMESPACE
-
-class AppxLocalEnginePrivate;
-class AppxLocalEngine : public AppxEngine
-{
-public:
- static bool canHandle(Runner *runner);
- static RunnerEngine *create(Runner *runner);
- static QStringList deviceNames();
-
- bool install(bool removeFirst = false) override;
- bool remove() override;
- bool start() override;
- bool enableDebugging(const QString &debuggerExecutable,
- const QString &debuggerArguments) override;
- bool disableDebugging() override;
- bool setLoopbackExemptClientEnabled(bool enabled) override;
- bool setLoopbackExemptServerEnabled(bool enabled) override;
- bool setLoggingRules(const QByteArray &rules) override;
- bool suspend() override;
- bool waitForFinished(int secs) override;
- bool stop() override;
-
- QString devicePath(const QString &relativePath) const override;
- bool sendFile(const QString &localFile, const QString &deviceFile) override;
- bool receiveFile(const QString &deviceFile, const QString &localFile) override;
-
-private:
- explicit AppxLocalEngine(Runner *runner);
- ~AppxLocalEngine();
-
- QString extensionSdkPath() const override;
- bool installPackage(IAppxManifestReader *reader, const QString &filePath) override;
-
- bool parseExitCode();
- friend struct QScopedPointerDeleter<AppxLocalEngine>;
- Q_DECLARE_PRIVATE(AppxLocalEngine)
-};
-
-#endif // APPXLOCALENGINE_H
diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp
deleted file mode 100644
index 39c3b2712..000000000
--- a/src/winrtrunner/appxphoneengine.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.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;
-
- const QList<CoreConDevice *> devices = coreConServer->devices();
- for (const CoreConDevice *device : 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;
- if (d->manifestReader) {
- hr = d->manifestReader->GetStream(&manifestStream);
- RETURN_VOID_IF_FAILED("Failed to query manifest stream from manifest reader.");
- } else {
- 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
-{
- const QByteArray extensionSdkDirRaw = qgetenv("ExtensionSdkDir");
- if (extensionSdkDirRaw.isEmpty()) {
- qCWarning(lcWinRtRunner) << "The environment variable ExtensionSdkDir is not set.";
- return QString();
- }
- return QString::fromLocal8Bit(extensionSdkDirRaw);
-}
-
-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);
- if (hr == 0x80073d06) { // No public E_* macro available
- qCWarning(lcWinRtRunner) << "Found a newer version of " << filePath
- << " on the target device, skipping...";
- } else {
- 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->executable).absoluteDir();
- const bool existingPackage = d->runner->app().endsWith(QLatin1String(".appx"));
- const QString packageFileName = existingPackage
- ? d->runner->app()
- : base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx"));
- if (!existingPackage) {
- if (!createPackage(packageFileName))
- return false;
-
- if (!sign(packageFileName))
- return false;
- } else {
- qCDebug(lcWinRtRunner) << "Installing existing package.";
- }
-
- return installPackage(d->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::setLoopbackExemptClientEnabled(bool)
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
- return false;
-}
-
-bool AppxPhoneEngine::setLoopbackExemptServerEnabled(bool)
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
- return false;
-}
-
-bool AppxPhoneEngine::setLoggingRules(const QByteArray &)
-{
- 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()
-{
- qCDebug(lcWinRtRunner) << __FUNCTION__;
-
- if (!connect())
- return false;
-
-#if 0 // This does not actually stop the app - QTBUG-41946
- Q_D(AppxPhoneEngine);
- 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;
-#else
- return remove();
-#endif
-}
-
-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
deleted file mode 100644
index b462e797f..000000000
--- a/src/winrtrunner/appxphoneengine.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.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) override;
- bool remove() override;
- bool start() override;
- bool enableDebugging(const QString &debuggerExecutable,
- const QString &debuggerArguments) override;
- bool disableDebugging() override;
- bool setLoopbackExemptClientEnabled(bool enabled) override;
- bool setLoopbackExemptServerEnabled(bool enabled) override;
- bool setLoggingRules(const QByteArray &rules) override;
- bool suspend() override;
- bool waitForFinished(int secs) override;
- bool stop() override;
-
- QString devicePath(const QString &relativePath) const override;
- bool sendFile(const QString &localFile, const QString &deviceFile) override;
- bool receiveFile(const QString &deviceFile, const QString &localFile) override;
-
-private:
- explicit AppxPhoneEngine(Runner *runner);
- ~AppxPhoneEngine();
-
- QString extensionSdkPath() const;
- bool installPackage(IAppxManifestReader *reader, const QString &filePath) override;
-
- bool connect();
-
- friend struct QScopedPointerDeleter<AppxPhoneEngine>;
- Q_DECLARE_PRIVATE(AppxPhoneEngine)
-};
-
-#endif // APPXPHONEENGINE_H
diff --git a/src/winrtrunner/main.cpp b/src/winrtrunner/main.cpp
deleted file mode 100644
index 77cdbb13f..000000000
--- a/src/winrtrunner/main.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/QCommandLineParser>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDir>
-#include <QtCore/QRegularExpression>
-#include <QtCore/QStringList>
-#include <QtCore/QMap>
-#include <QtCore/QLoggingCategory>
-
-#include <iostream>
-
-#include "runner.h"
-
-QT_USE_NAMESPACE
-
-int main(int argc, char *argv[])
-{
- // If logging rules are set via env variable, we pass these to the application we are running.
- // winrtrunner behaves different from other applications in the regard that its logging rules
- // have to be enabled explicitly. Setting "*=true" will not enable extended logging. Reason is
- // CI setting "*=true" if an auto test fails and additional winrtrunner output might just
- // confuse users.
- const QByteArray loggingRules = qgetenv("QT_LOGGING_RULES");
- const QList<QByteArray> rules = loggingRules.split(';');
- QRegularExpression runnerExp(QLatin1String("^qt\\.winrtrunner.*\\s*=\\s*true\\s*$"));
- bool runnerRuleFound = false;
- for (const QByteArray &rule : rules) {
- if (runnerExp.match(QLatin1String(rule)).hasMatch()) {
- runnerRuleFound = true;
- break;
- }
- }
- if (!runnerRuleFound)
- qunsetenv("QT_LOGGING_RULES");
- QCoreApplication a(argc, argv);
- QCommandLineParser parser;
- parser.setApplicationDescription(QLatin1String("winrtrunner installs, runs, and collects test "
- "results for packages made with Qt."));
- parser.addPositionalArgument(QStringLiteral("package [arguments]"),
- QLatin1String("The executable or package manifest to act upon. "
- "Arguments after the package name will be passed "
- "to the application when it starts."));
-
- QCommandLineOption testOption(QStringLiteral("test"),
- QLatin1String("Install, start, collect output, stop (if needed), "
- "and uninstall the package. This is the "
- "default action of winrtrunner."));
- parser.addOption(testOption);
-
- QCommandLineOption startOption(QStringLiteral("start"),
- QLatin1String("Start the package. The package is installed if "
- "it is not already installed. Pass --install to "
- "force reinstallation."));
- parser.addOption(startOption);
-
- QCommandLineOption debugOption(QStringLiteral("debug"),
- QLatin1String("Start the package with the debugger attached. "
- "The package is installed if it is not already "
- "installed. Pass --install to force "
- "reinstallation."),
- QLatin1String("debugger"));
- parser.addOption(debugOption);
-
- QCommandLineOption debuggerArgumentsOption(QStringLiteral("debugger-arguments"),
- QLatin1String("Arguments that are passed to the "
- "debugger when --debug is used. If no "
- "debugger was provided this option is "
- "ignored."),
- QLatin1String("arguments"));
- parser.addOption(debuggerArgumentsOption);
-
- QCommandLineOption suspendOption(QStringLiteral("suspend"),
- QLatin1String("Suspend a running package. When combined "
- "with --stop or --test, the app will be "
- "suspended before being terminated."));
- parser.addOption(suspendOption);
-
- QCommandLineOption stopOption(QStringLiteral("stop"),
- QLatin1String("Terminate a running package. Can be be "
- "combined with --start and --suspend."));
- parser.addOption(stopOption);
-
- QCommandLineOption waitOption(QStringLiteral("wait"),
- QLatin1String("If the package is running, waits the given "
- "number of seconds before continuing to the next "
- "task. Passing 0 causes the runner to wait "
- "indefinitely."),
- QStringLiteral("seconds"));
- parser.addOption(waitOption);
-
- QCommandLineOption installOption(QStringLiteral("install"),
- QStringLiteral("(Re)installs the package."));
- parser.addOption(installOption);
-
- QCommandLineOption removeOption(QStringLiteral("remove"),
- QStringLiteral("Uninstalls the package."));
- parser.addOption(removeOption);
-
- QCommandLineOption deviceOption(QStringLiteral("device"),
- QLatin1String("Specifies the device to target as a device name "
- "or index. Use --list-devices to find available "
- "devices. The default device is the first device "
- "found for the active run profile."),
- QStringLiteral("name|index"));
- parser.addOption(deviceOption);
-
- QCommandLineOption profileOption(QStringLiteral("profile"),
- QStringLiteral("Force a particular run profile."),
- QStringLiteral("name"));
- parser.addOption(profileOption);
-
- QCommandLineOption listDevicesOption(QStringLiteral("list-devices"),
- QLatin1String("List the available devices "
- "(for use with --device)."));
- parser.addOption(listDevicesOption);
-
- QCommandLineOption verbosityOption(QStringLiteral("verbose"),
- QLatin1String("The verbosity level of the message output "
- "(0 - silent, 1 - info, 2 - debug). Defaults to 1."),
- QStringLiteral("level"), QStringLiteral("1"));
- parser.addOption(verbosityOption);
-
- QCommandLineOption ignoreErrorsOption(QStringLiteral("ignore-errors"),
- QStringLiteral("Always exit with code 0, regardless of the error state."));
- parser.addOption(ignoreErrorsOption);
-
- QCommandLineOption loopbackExemptOption(QStringLiteral("loopbackexempt"),
- QLatin1String("Enables localhost communication for clients,"
- "servers or both. Adding this possibility "
- "for servers needs elevated rights and "
- "might ask for these in a dialog."
- "Possible values: client, server, clientserver"),
- QStringLiteral("mode"));
- parser.addOption(loopbackExemptOption);
-
- parser.addHelpOption();
- parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- QStringList arguments = QCoreApplication::arguments();
- parser.parse(arguments);
-
- QStringList filterRules = QStringList() // Default logging rules
- << QStringLiteral("qt.winrtrunner.warning=true")
- << QStringLiteral("qt.winrtrunner.critical=true")
- << QStringLiteral("qt.winrtrunner.app=true");
- if (parser.isSet(verbosityOption)) {
- bool ok;
- uint verbosity = parser.value(verbosityOption).toUInt(&ok);
- if (!ok || verbosity > 2) {
- qCCritical(lcWinRtRunner) << "Incorrect value specified for verbosity.";
- parser.showHelp(1);
- }
- switch (verbosity) {
- case 2: // Enable debug print
- filterRules.append(QStringLiteral("qt.winrtrunner.debug=true"));
- break;
- case 1: // Remove warnings
- filterRules.removeFirst();
- // fall through
- case 0: // Silent
- filterRules.removeFirst();
- // fall through
- default: // Impossible
- break;
- }
- }
- bool loopbackExemptClient = false;
- bool loopbackExemptServer = false;
- if (parser.isSet(loopbackExemptOption)) {
- const QString value = parser.value(loopbackExemptOption);
- if (value == QStringLiteral("client")) {
- loopbackExemptClient = true;
- } else if (value == QStringLiteral("server")) {
- loopbackExemptServer = true;
- } else if (value == QStringLiteral("clientserver")) {
- loopbackExemptClient = true;
- loopbackExemptServer = true;
- } else {
- qCCritical(lcWinRtRunner) << "Incorrect value specified for loopbackexempt.";
- parser.showHelp(1);
- }
- }
- QLoggingCategory::setFilterRules(filterRules.join(QLatin1Char('\n')));
-
- if (parser.isSet(listDevicesOption)) {
- std::wcout << "Available devices:\n";
- const QMap<QString, QStringList> deviceNames = Runner::deviceNames();
- for (auto it = deviceNames.cbegin(), end = deviceNames.cend(); it != end; ++it) {
- std::wcout << reinterpret_cast<const wchar_t *>(it.key().utf16()) << ":\n";
- int index = 0;
- for (const QString &device : it.value()) {
- std::wcout << " " << index++ << ' '
- << reinterpret_cast<const wchar_t *>(device.utf16()) << '\n';
- }
- }
- std::wcout << std::endl;
- return 0;
- }
-
- // Process front-end args
- if (parser.positionalArguments().count() < 1)
- parser.showHelp(parser.isSet(QStringLiteral("help")) ? 0 : 1);
- const QString app = parser.positionalArguments().first();
- const int appArgsPos = arguments.indexOf(app) + 1;
- const QStringList mainArgs = arguments.mid(0, appArgsPos);
- QStringList appArgs = arguments.mid(appArgsPos);
- parser.process(mainArgs);
-
- // Exit codes:
- // 1 - Bad arguments
- // 2 - Bad package or no backend available
- // 3 - Installation failed
- // 4 - Removal failed
- // 5 - Start failed
- // 6 - Suspend failed
- // 7 - Stop failed
- // 8 - Test setup failed
- // 9 - Test results retrieval failed
- // 10 - Enabling debugging failed
- // In "test" mode, the exit code of the app is returned
-
- bool ignoreErrors = parser.isSet(ignoreErrorsOption);
- bool testEnabled = parser.isSet(testOption);
- bool startEnabled = testEnabled || parser.isSet(startOption) || parser.isSet(debugOption);
- bool suspendEnabled = parser.isSet(suspendOption);
- bool waitEnabled = testEnabled || parser.isSet(waitOption);
- bool stopEnabled = !testEnabled && parser.isSet(stopOption); // test and stop are mutually exclusive
- bool installEnabled = testEnabled || startEnabled || parser.isSet(installOption);
- bool removeBeforeInstall = testEnabled || parser.isSet(installOption);
- bool removeEnabled = testEnabled || parser.isSet(removeOption);
- // Default to test mode if no conflicting arguments were passed
- if (!testEnabled && !installEnabled && !startEnabled && !stopEnabled && !suspendEnabled && !removeEnabled)
- testEnabled = installEnabled = removeBeforeInstall = startEnabled = waitEnabled = stopEnabled = removeEnabled = true;
-
- int waitTime = parser.value(waitOption).toInt();
- if (!waitTime && testEnabled)
- waitTime = 300; // The maximum wait period for test cases is 300 seconds (5 minutes)
-
- // Set up runner
- Runner runner(app, appArgs, parser.value(profileOption), parser.value(deviceOption));
- if (!runner.isValid())
- return ignoreErrors ? 0 : 2;
-
- if (testEnabled && !runner.setupTest()) {
- qCDebug(lcWinRtRunner) << "Test setup failed, exiting with code 8.";
- return ignoreErrors ? 0 : 8;
- }
-
- if (installEnabled && !runner.install(removeBeforeInstall)) {
- qCDebug(lcWinRtRunner) << "Installation failed, exiting with code 3.";
- return ignoreErrors ? 0 : 3;
- }
-
- if (loopbackExemptClient && !runner.setLoopbackExemptClientEnabled(true)) {
- qCDebug(lcWinRtRunner) << "Could not enable loopback exemption for client, "
- "exiting with code 3.";
- return ignoreErrors ? 0 : 3;
- }
-
- if (loopbackExemptServer && !runner.setLoopbackExemptServerEnabled(true)) {
- qCDebug(lcWinRtRunner) << "Could not enable loopback exemption for server, "
- "exiting with code 3.";
- return ignoreErrors ? 0 : 3;
- }
-
- if (!loggingRules.isNull() && !runner.setLoggingRules(loggingRules)) {
- qCDebug(lcWinRtRunner) << "Could not set logging rules, exiting with code 3.";
- return ignoreErrors ? 0 : 3;
- }
-
- if (parser.isSet(debugOption)) {
- const QString &debuggerExecutable = parser.value(debugOption);
- const QString &debuggerArguments = parser.value(debuggerArgumentsOption);
- qCDebug(lcWinRtRunner) << "Debugger: " << debuggerExecutable;
- qCDebug(lcWinRtRunner) << "Debugger Options: " << debuggerArguments;
- if (debuggerExecutable.isEmpty()
- || !runner.enableDebugging(debuggerExecutable, debuggerArguments)) {
- qCDebug(lcWinRtRunner) << "Failed to enable debugging, exiting with code 10.";
- return ignoreErrors ? 0 : 10;
- }
- }
-
- bool startFailed = startEnabled && !runner.start();
-
- if (parser.isSet(debugOption) && !runner.disableDebugging())
- qCDebug(lcWinRtRunner) << "Failed to disable debugging";
-
- if (startFailed) {
- qCDebug(lcWinRtRunner) << "Start failed, exiting with code 5.";
- return ignoreErrors ? 0 : 5;
- }
-
- qint64 pid = runner.pid();
- if (pid != -1)
- qCWarning(lcWinRtRunner) << "App started with process ID" << pid;
-
- if (waitEnabled)
- runner.wait(waitTime);
-
- if (loopbackExemptClient)
- runner.setLoopbackExemptClientEnabled(false);
-
- if (loopbackExemptServer)
- runner.setLoopbackExemptServerEnabled(false);
-
- if (suspendEnabled && !runner.suspend()) {
- qCDebug(lcWinRtRunner) << "Suspend failed, exiting with code 6.";
- return ignoreErrors ? 0 : 6;
- }
-
- if (stopEnabled && !runner.stop()) {
- qCDebug(lcWinRtRunner) << "Stop failed, exiting with code 7.";
- return ignoreErrors ? 0 : 7;
- }
-
- if (testEnabled && !runner.collectTest()) {
- qCDebug(lcWinRtRunner) << "Collect test failed, exiting with code 9.";
- return ignoreErrors ? 0 : 9;
- }
-
- if (removeEnabled && !runner.remove()) {
- qCDebug(lcWinRtRunner) << "Remove failed, exiting with code 4.";
- return ignoreErrors ? 0 : 4;
- }
-
- if (stopEnabled) {
- int exitCode = runner.exitCode();
- if (exitCode == -1)
- return 0; // Exit code unknown; not necessarily an error
- qCWarning(lcWinRtRunner) << "App exited with code" << exitCode;
- return ignoreErrors ? 0 : exitCode;
- }
-
- return 0;
-}
diff --git a/src/winrtrunner/runner.cpp b/src/winrtrunner/runner.cpp
deleted file mode 100644
index d115b584b..000000000
--- a/src/winrtrunner/runner.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "runner.h"
-
-#include "runnerengine.h"
-
-#ifndef RTRUNNER_NO_APPXPHONE
-#include "appxphoneengine.h"
-#endif
-#ifndef RTRUNNER_NO_APPXLOCAL
-#include "appxlocalengine.h"
-#endif
-
-#include <QtCore/QDir>
-#include <QtCore/QStandardPaths>
-#include <QtCore/QLoggingCategory>
-
-QT_USE_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcWinRtRunner, "qt.winrtrunner")
-Q_LOGGING_CATEGORY(lcWinRtRunnerApp, "qt.winrtrunner.app")
-
-class RunnerPrivate
-{
-public:
- bool isValid;
- QString app;
- QString manifest;
- QStringList arguments;
- int deviceIndex;
- struct TestPaths {
- // File path in application bundle
- QString deviceOutputFile;
- // temporary output path (if absolute path or stdout (-) was given
- QString localOutputFile;
- // final output location. Might be equal to localOutputFile or stdout (-)
- QString finalOutputFile;
- };
- QList<TestPaths> testPaths;
-
- QString profile;
- QScopedPointer<RunnerEngine> engine;
-
- QString defaultOutputFileName(const QString &format = QString())
- {
- QString ret = QFileInfo(engine->executable()).baseName() + QStringLiteral("_output");
- if (!format.isEmpty())
- ret += QLatin1Char('_') + format;
- ret += QStringLiteral(".txt");
- return ret;
- }
-};
-
-QMap<QString, QStringList> Runner::deviceNames()
-{
- QMap<QString, QStringList> deviceNames;
-#ifndef RTRUNNER_NO_APPXLOCAL
- deviceNames.insert(QStringLiteral("Appx"), AppxLocalEngine::deviceNames());
-#endif
-#ifndef RTRUNNER_NO_APPXPHONE
- deviceNames.insert(QStringLiteral("Phone"), AppxPhoneEngine::deviceNames());
-#endif
- return deviceNames;
-}
-
-Runner::Runner(const QString &app, const QStringList &arguments,
- const QString &profile, const QString &deviceName)
- : d_ptr(new RunnerPrivate)
-{
- Q_D(Runner);
- d->isValid = false;
- d->app = app;
- d->arguments = arguments;
- d->profile = profile;
-
- bool deviceIndexKnown;
- d->deviceIndex = deviceName.toInt(&deviceIndexKnown);
-#ifndef RTRUNNER_NO_APPXLOCAL
- if (!deviceIndexKnown) {
- d->deviceIndex = AppxLocalEngine::deviceNames().indexOf(deviceName);
- if (d->deviceIndex < 0)
- d->deviceIndex = 0;
- }
- if ((d->profile.isEmpty() || d->profile.toLower() == QStringLiteral("appx"))
- && AppxLocalEngine::canHandle(this)) {
- if (RunnerEngine *engine = AppxLocalEngine::create(this)) {
- d->engine.reset(engine);
- d->isValid = true;
- qCWarning(lcWinRtRunner) << "Using the Appx profile.";
- return;
- }
- }
-#endif
-#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
- // Place other engines here
-
- qCWarning(lcWinRtRunner) << "Unable to find a run profile for" << app << ".";
-}
-
-Runner::~Runner()
-{
-}
-
-bool Runner::isValid() const
-{
- Q_D(const Runner);
- return d->isValid;
-}
-
-QString Runner::app() const
-{
- Q_D(const Runner);
- return d->app;
-}
-
-QStringList Runner::arguments() const
-{
- Q_D(const Runner);
- return d->arguments;
-}
-
-int Runner::deviceIndex() const
-{
- Q_D(const Runner);
- return d->deviceIndex;
-}
-
-bool Runner::install(bool removeFirst)
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->install(removeFirst);
-}
-
-bool Runner::remove()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->remove();
-}
-
-bool Runner::start()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->start();
-}
-
-bool Runner::enableDebugging(const QString &debuggerExecutable, const QString &debuggerArguments)
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->enableDebugging(debuggerExecutable, debuggerArguments);
-}
-
-bool Runner::disableDebugging()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->disableDebugging();
-}
-
-bool Runner::setLoopbackExemptClientEnabled(bool enabled)
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->setLoopbackExemptClientEnabled(enabled);
-}
-
-bool Runner::setLoopbackExemptServerEnabled(bool enabled)
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->setLoopbackExemptServerEnabled(enabled);
-}
-
-bool Runner::setLoggingRules(const QByteArray &rules)
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->setLoggingRules(rules);
-}
-
-bool Runner::suspend()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->suspend();
-}
-
-bool Runner::stop()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->stop();
-}
-
-bool Runner::wait(int maxWaitTime)
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- return d->engine->waitForFinished(maxWaitTime);
-}
-
-bool Runner::setupTest()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- // Fix-up output path
- int outputIndex = d->arguments.indexOf(QStringLiteral("-o"));
- // if no -o was given: Use the default location winrtrunner can read from and write on stdout
- if (outputIndex == -1) {
- RunnerPrivate::TestPaths out;
- out.localOutputFile = d->defaultOutputFileName();
- out.finalOutputFile = QLatin1Char('-');
- d->arguments.append(QStringLiteral("-o"));
- out.deviceOutputFile = d->engine->devicePath(out.localOutputFile);
- d->arguments.append(out.deviceOutputFile);
- d->testPaths.append(out);
- } else {
- while (outputIndex != -1) {
- ++outputIndex;
- QString format;
- RunnerPrivate::TestPaths out;
- if (d->arguments.size() <= outputIndex) {
- qCWarning(lcWinRtRunner) << "-o needs an extra parameter specifying the filename and optional format";
- return false;
- }
-
- QString output = d->arguments.at(outputIndex);
- int commaIndex = output.indexOf(QLatin1Char(','));
- // -o <name>,<format>
- if (commaIndex != -1) {
- format = output.mid(commaIndex + 1);
- output = output.left(commaIndex);
- }
- out.finalOutputFile = output;
- if (QFileInfo(output).isAbsolute() || output == QLatin1Char('-'))
- out.localOutputFile = d->defaultOutputFileName(format);
- else
- out.localOutputFile = output;
- out.deviceOutputFile = d->engine->devicePath(out.localOutputFile);
- d->arguments[outputIndex] = out.deviceOutputFile;
- if (!format.isEmpty())
- d->arguments[outputIndex] += QLatin1Char(',') + format;
- d->testPaths.append(out);
- outputIndex = d->arguments.indexOf(QStringLiteral("-o"), outputIndex);
- }
- }
-
- // Write a qt.conf to the executable directory
- QDir executableDir = QFileInfo(d->engine->executable()).absoluteDir();
- QFile qtConf(executableDir.absoluteFilePath(QStringLiteral("qt.conf")));
- if (!qtConf.exists()) {
- if (!qtConf.open(QFile::WriteOnly)) {
- qCWarning(lcWinRtRunner) << "Could not open qt.conf for writing.";
- return false;
- }
- qtConf.write(QByteArrayLiteral("[Paths]\nPlugins=/"));
- }
-
- return true;
-}
-
-bool Runner::collectTest()
-{
- Q_D(Runner);
- Q_ASSERT(d->engine);
-
- // Fetch test output
- for (RunnerPrivate::TestPaths output : d->testPaths) {
- if (!d->engine->receiveFile(output.deviceOutputFile, output.localOutputFile)) {
- qCWarning(lcWinRtRunner).nospace().noquote()
- << "Unable to copy test output file \""
- << QDir::toNativeSeparators(output.deviceOutputFile)
- << "\" to local file \"" << QDir::toNativeSeparators(output.localOutputFile) << "\".";
- return false;
- }
-
- if (output.finalOutputFile == QLatin1Char('-')) {
- QFile testResults(output.localOutputFile);
- if (!testResults.open(QFile::ReadOnly)) {
- qCWarning(lcWinRtRunner) << "Unable to read test results:" << testResults.errorString();
- return false;
- }
-
- const QByteArray contents = testResults.readAll();
- std::fputs(contents.constData(), stdout);
- } else if (output.localOutputFile != output.finalOutputFile) {
- if (QFile::exists(output.finalOutputFile) && !QFile::remove(output.finalOutputFile)) {
- qCWarning(lcWinRtRunner) << "Could not remove file" << output.finalOutputFile;
- return false;
- }
- if (!QFile(output.localOutputFile).copy(output.finalOutputFile)) {
- qCWarning(lcWinRtRunner) << "Could not copy intermediate file" << output.localOutputFile
- << "to final destination" << output.finalOutputFile;
- return false;
- }
- }
- }
- return true;
-}
-
-qint64 Runner::pid()
-{
- Q_D(Runner);
- if (!d->engine)
- return -1;
-
- return d->engine->pid();
-}
-
-int Runner::exitCode()
-{
- Q_D(Runner);
- if (!d->engine)
- return -1;
-
- return d->engine->exitCode();
-}
diff --git a/src/winrtrunner/runner.h b/src/winrtrunner/runner.h
deleted file mode 100644
index 00b251be8..000000000
--- a/src/winrtrunner/runner.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef RUNNER_H
-#define RUNNER_H
-
-#include <QtCore/QString>
-#include <QtCore/QStringList>
-#include <QtCore/QMap>
-#include <QtCore/QScopedPointer>
-#include <QtCore/QLoggingCategory>
-
-QT_USE_NAMESPACE
-
-class RunnerPrivate;
-class Runner
-{
-public:
- static QMap<QString, QStringList> deviceNames();
-
- Runner(const QString &app, const QStringList &arguments, const QString &profile = QString(),
- const QString &device = QString());
- ~Runner();
-
- bool isValid() const;
- QString app() const;
- QStringList arguments() const;
- int deviceIndex() const;
-
- bool install(bool removeFirst = false);
- bool remove();
- bool start();
- bool enableDebugging(const QString &debuggerExecutable, const QString &debuggerArguments);
- bool disableDebugging();
- bool setLoopbackExemptClientEnabled(bool enabled);
- bool setLoopbackExemptServerEnabled(bool enabled);
- bool setLoggingRules(const QByteArray &rules);
- bool suspend();
- bool stop();
- bool wait(int maxWaitTime = 0);
- bool setupTest();
- bool collectTest();
- qint64 pid();
- int exitCode();
-
-private:
- QScopedPointer<RunnerPrivate> d_ptr;
- Q_DECLARE_PRIVATE(Runner)
-};
-
-Q_DECLARE_LOGGING_CATEGORY(lcWinRtRunner)
-Q_DECLARE_LOGGING_CATEGORY(lcWinRtRunnerApp)
-
-#endif // RUNNER_H
diff --git a/src/winrtrunner/runnerengine.h b/src/winrtrunner/runnerengine.h
deleted file mode 100644
index 44565c46c..000000000
--- a/src/winrtrunner/runnerengine.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef RUNNERENGINE_H
-#define RUNNERENGINE_H
-
-#include <QtCore/QString>
-
-QT_USE_NAMESPACE
-
-class RunnerEngine
-{
-public:
- virtual ~RunnerEngine() { }
- virtual bool install(bool removeFirst = false) = 0;
- virtual bool remove() = 0;
- virtual bool start() = 0;
- virtual bool enableDebugging(const QString &debugger, const QString &debuggerArguments) = 0;
- virtual bool disableDebugging() = 0;
- virtual bool setLoopbackExemptClientEnabled(bool enabled) = 0;
- virtual bool setLoopbackExemptServerEnabled(bool enabled) = 0;
- virtual bool setLoggingRules(const QByteArray &rules) = 0;
- virtual bool suspend() = 0;
- virtual bool waitForFinished(int secs) = 0;
- virtual bool stop() = 0;
- virtual qint64 pid() const = 0;
- virtual int exitCode() const = 0;
- virtual QString executable() const = 0;
- virtual QString devicePath(const QString &relativePath) const = 0;
- virtual bool sendFile(const QString &localFile, const QString &deviceFile) = 0;
- virtual bool receiveFile(const QString &deviceFile, const QString &localFile) = 0;
-};
-
-#endif // RUNNERENGINE_H
diff --git a/src/winrtrunner/winrtrunner.pro b/src/winrtrunner/winrtrunner.pro
deleted file mode 100644
index fb0d58e6e..000000000
--- a/src/winrtrunner/winrtrunner.pro
+++ /dev/null
@@ -1,31 +0,0 @@
-include($$OUT_PWD/../../src/global/qttools-config.pri)
-QT_FOR_CONFIG += tools-private
-requires(qtConfig(winrtrunner))
-
-option(host_build)
-CONFIG += force_bootstrap
-
-DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII WINRT_LIBRARY
-
-SOURCES += \
- main.cpp \
- runner.cpp \
- appxengine.cpp \
- appxlocalengine.cpp \
- appxphoneengine.cpp
-
-HEADERS += \
- runner.h \
- runnerengine.h \
- appxengine.h \
- appxengine_p.h \
- appxlocalengine.h \
- appxphoneengine.h
-
-LIBS += -lruntimeobject -lwsclient -lShlwapi -lurlmon -lxmllite -lcrypt32
-
-include(../shared/corecon/corecon.pri)
-include(../shared/winutils/winutils.pri)
-
-QMAKE_TARGET_DESCRIPTION = "Qt WinRT Runner"
-load(qt_tool)
diff --git a/tests/auto/.prev_CMakeLists.txt b/tests/auto/.prev_CMakeLists.txt
index bdf5c6b16..af1c24b03 100644
--- a/tests/auto/.prev_CMakeLists.txt
+++ b/tests/auto/.prev_CMakeLists.txt
@@ -17,6 +17,6 @@ if(TARGET Qt::Help AND NOT CMAKE_CROSSCOMPILING)
endif()
add_subdirectory(cmake)
add_subdirectory(installed_cmake)
-if(QT_FEATURE_process AND WIN32 AND NOT CMAKE_CROSSCOMPILING AND NOT WINRT)
+if(QT_FEATURE_process AND WIN32 AND NOT CMAKE_CROSSCOMPILING)
add_subdirectory(windeployqt)
endif()
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index ab374e67a..85bbc931d 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -19,6 +19,6 @@ endif()
#add_subdirectory(cmake)
#add_subdirectory(installed_cmake)
# special case end
-if(QT_FEATURE_process AND WIN32 AND NOT CMAKE_CROSSCOMPILING AND NOT WINRT)
+if(QT_FEATURE_process AND WIN32 AND NOT CMAKE_CROSSCOMPILING)
add_subdirectory(windeployqt)
endif()
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 0d3966a7e..486b824bc 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -30,4 +30,4 @@ cross_compile:SUBDIRS -= qhelpcontentmodel qhelpenginecore qhelpindexmodel qhelp
qhelpprojectdata \
!qtConfig(process): SUBDIRS -= qtattributionsscanner linguist qtdiag windeployqt
-!win32|winrt: SUBDIRS -= windeployqt
+!win32: SUBDIRS -= windeployqt