summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-02-19 18:37:26 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-02-19 18:37:26 +0100
commit852f4e4cf87d7db0eaa87384b1589e151f76e6cd (patch)
tree73bc838da6bde8b66e26c2e1a34ff319584edf82
parent863a6621d14caf67adcf3f30cb955a268765f0f1 (diff)
parent98eebb2dc1830b262d72e748817aee25e54d0d35 (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7v5.7.0-alpha1
Conflicts: .qmake.conf Change-Id: Ibd5f6052bd07152fbe344505308563d9857771e9
-rw-r--r--src/assistant/help/qhelpsearchindexwriter_clucene.cpp10
-rw-r--r--src/designer/src/components/formeditor/formwindow.cpp5
-rw-r--r--src/macdeployqt/shared/shared.cpp82
-rw-r--r--src/macdeployqt/shared/shared.h4
-rw-r--r--src/qdoc/cppcodemarker.cpp15
-rw-r--r--src/qdoc/cppcodeparser.cpp46
-rw-r--r--src/qdoc/cppcodeparser.h2
-rw-r--r--src/qdoc/generator.cpp22
-rw-r--r--src/qdoc/htmlgenerator.cpp2
-rw-r--r--src/qdoc/main.cpp5
-rw-r--r--src/qdoc/node.cpp33
-rw-r--r--src/qdoc/node.h18
-rw-r--r--src/qdoc/qdocindexfiles.cpp20
-rw-r--r--src/qdoc/qdoctagfiles.cpp10
-rw-r--r--src/qdoc/tokenizer.cpp2
-rw-r--r--src/qdoc/tokenizer.h3
-rw-r--r--src/qtdiag/main.cpp4
-rw-r--r--src/qtdiag/qtdiag.cpp51
-rw-r--r--src/qtdiag/qtdiag.h3
-rw-r--r--src/winrtrunner/appxengine.cpp332
-rw-r--r--src/winrtrunner/appxengine.h1
-rw-r--r--src/winrtrunner/appxengine_p.h1
-rw-r--r--src/winrtrunner/appxphoneengine.cpp12
-rw-r--r--src/winrtrunner/winrtrunner.pro3
24 files changed, 641 insertions, 45 deletions
diff --git a/src/assistant/help/qhelpsearchindexwriter_clucene.cpp b/src/assistant/help/qhelpsearchindexwriter_clucene.cpp
index 96d46e0a4..f2a757f2e 100644
--- a/src/assistant/help/qhelpsearchindexwriter_clucene.cpp
+++ b/src/assistant/help/qhelpsearchindexwriter_clucene.cpp
@@ -331,6 +331,16 @@ static bool operator<(const QTextHtmlEntity &entity, const QString &entityStr)
return QLatin1String(entity.name) < entityStr;
}
+static bool operator<(const QString &entityStr, const QTextHtmlEntity &entity)
+{
+ return entityStr < QLatin1String(entity.name);
+}
+
+static bool operator<(const QTextHtmlEntity &entity, const QTextHtmlEntity &entity2)
+{
+ return QLatin1String(entity.name) < QLatin1String(entity2.name);
+}
+
static QChar resolveEntity(const QString &entity)
{
const QTextHtmlEntity *start = &entities[0];
diff --git a/src/designer/src/components/formeditor/formwindow.cpp b/src/designer/src/components/formeditor/formwindow.cpp
index d51090553..3d09740ad 100644
--- a/src/designer/src/components/formeditor/formwindow.cpp
+++ b/src/designer/src/components/formeditor/formwindow.cpp
@@ -2182,8 +2182,6 @@ void FormWindow::layoutContainer(QWidget *w, int type)
w = core()->widgetFactory()->containerOfWidget(w);
const QObjectList l = w->children();
- if (l.isEmpty())
- return;
// find managed widget children
QWidgetList widgets;
const QObjectList::const_iterator ocend = l.constEnd();
@@ -2194,6 +2192,9 @@ void FormWindow::layoutContainer(QWidget *w, int type)
widgets.append(widget);
}
+ if (widgets.isEmpty()) // QTBUG-50563, observed when using hand-edited forms.
+ return;
+
LayoutCommand *cmd = new LayoutCommand(this);
cmd->init(mainContainer(), widgets, static_cast<LayoutInfo::Type>(type), w);
clearSelection(false);
diff --git a/src/macdeployqt/shared/shared.cpp b/src/macdeployqt/shared/shared.cpp
index 3cd98fc2c..f92110276 100644
--- a/src/macdeployqt/shared/shared.cpp
+++ b/src/macdeployqt/shared/shared.cpp
@@ -351,6 +351,19 @@ QStringList findAppFrameworkNames(const QString &appBundlePath)
return frameworks;
}
+QStringList findAppFrameworkPaths(const QString &appBundlePath)
+{
+ QStringList frameworks;
+ QString searchPath = appBundlePath + "/Contents/Frameworks/";
+ QDirIterator iter(searchPath, QStringList() << QString::fromLatin1("*.framework"), QDir::Dirs);
+ while (iter.hasNext()) {
+ iter.next();
+ frameworks << iter.fileInfo().filePath();
+ }
+
+ return frameworks;
+}
+
QStringList findAppLibraries(const QString &appBundlePath)
{
QStringList result;
@@ -1241,7 +1254,7 @@ void codesignFile(const QString &identity, const QString &filePath)
LogNormal() << "codesign" << filePath;
QProcess codesign;
- codesign.start("codesign", QStringList() << "--preserve-metadata=identifier,entitlements,resource-rules"
+ codesign.start("codesign", QStringList() << "--preserve-metadata=identifier,entitlements"
<< "--force" << "-s" << identity << filePath);
codesign.waitForFinished(-1);
@@ -1254,7 +1267,7 @@ void codesignFile(const QString &identity, const QString &filePath)
}
}
-void codesign(const QString &identity, const QString &appBundlePath)
+QSet<QString> codesignBundle(const QString &identity, const QString &appBundlePath)
{
// Code sign all binaries in the app bundle. This needs to
// be done inside-out, e.g sign framework dependencies
@@ -1280,10 +1293,37 @@ void codesign(const QString &identity, const QString &appBundlePath)
foreach (const QString &binary, foundPluginBinaries)
pendingBinaries.push(binary);
- QStringList foundLibraries = findAppBundleFiles(appBundlePath + "/Contents/Frameworks/");
- foreach (const QString &binary, foundLibraries)
- pendingBinaries.push(binary);
+ // Add frameworks for processing.
+ QStringList frameworkPaths = findAppFrameworkPaths(appBundlePath);
+ foreach (const QString &frameworkPath, frameworkPaths) {
+
+ // Add all files for a framework as a catch all.
+ QStringList bundleFiles = findAppBundleFiles(frameworkPath);
+ foreach (const QString &binary, bundleFiles)
+ pendingBinaries.push(binary);
+ // Prioritise first to sign any additional inner bundles found in the Helpers folder (e.g
+ // used by QtWebEngine).
+ QDirIterator helpersIterator(frameworkPath, QStringList() << QString::fromLatin1("Helpers"), QDir::Dirs | QDir::NoSymLinks, QDirIterator::Subdirectories);
+ while (helpersIterator.hasNext()) {
+ helpersIterator.next();
+ QString helpersPath = helpersIterator.filePath();
+ QStringList innerBundleNames = QDir(helpersPath).entryList(QStringList() << "*.app", QDir::Dirs);
+ foreach (const QString &innerBundleName, innerBundleNames)
+ signedBinaries += codesignBundle(identity, helpersPath + "/" + innerBundleName);
+ }
+
+ // Also make sure to sign any libraries that will not be found by otool because they
+ // are not linked and won't be seen as a dependency.
+ QDirIterator librariesIterator(frameworkPath, QStringList() << QString::fromLatin1("Libraries"), QDir::Dirs | QDir::NoSymLinks, QDirIterator::Subdirectories);
+ while (librariesIterator.hasNext()) {
+ librariesIterator.next();
+ QString librariesPath = librariesIterator.filePath();
+ bundleFiles = findAppBundleFiles(librariesPath);
+ foreach (const QString &binary, bundleFiles)
+ pendingBinaries.push(binary);
+ }
+ }
// Sign all binares; use otool to find and sign dependencies first.
while (!pendingBinaries.isEmpty()) {
@@ -1293,17 +1333,39 @@ void codesign(const QString &identity, const QString &appBundlePath)
// Check if there are unsigned dependencies, sign these first
QStringList dependencies = getBinaryDependencies(rootBinariesPath, binary).toSet().subtract(signedBinaries).toList();
+
if (!dependencies.isEmpty()) {
pendingBinaries.push(binary);
- foreach (const QString &dependency, dependencies)
+ int dependenciesSkipped = 0;
+ foreach (const QString &dependency, dependencies) {
+ // Skip dependencies that are outside the current app bundle, because this might
+ // cause a codesign error if the current bundle is part of the dependency (e.g.
+ // a bundle is part of a framework helper, and depends on that framework).
+ // The dependencies will be taken care of after the current bundle is signed.
+ if (!dependency.startsWith(appBundlePath)) {
+ ++dependenciesSkipped;
+ LogNormal() << "Skipping outside dependency: " << dependency;
+ continue;
+ }
pendingBinaries.push(dependency);
- continue;
+ }
+
+ // If all dependencies were skipped, make sure the binary is actually signed, instead
+ // of going into an infinite loop.
+ if (dependenciesSkipped == dependencies.size()) {
+ pendingBinaries.pop();
+ } else {
+ continue;
+ }
}
+
// All dependencies are signed, now sign this binary
codesignFile(identity, binary);
signedBinaries.insert(binary);
}
+ LogNormal() << "Finished codesigning " << appBundlePath << "with identity" << identity;
+
// Verify code signature
QProcess codesign;
codesign.start("codesign", QStringList() << "--deep" << "-v" << appBundlePath);
@@ -1315,6 +1377,12 @@ void codesign(const QString &identity, const QString &appBundlePath)
} else if (!err.isEmpty()) {
LogDebug() << err;
}
+
+ return signedBinaries;
+}
+
+void codesign(const QString &identity, const QString &appBundlePath) {
+ codesignBundle(identity, appBundlePath);
}
void createDiskImage(const QString &appBundlePath)
diff --git a/src/macdeployqt/shared/shared.h b/src/macdeployqt/shared/shared.h
index d94033b54..2368b370d 100644
--- a/src/macdeployqt/shared/shared.h
+++ b/src/macdeployqt/shared/shared.h
@@ -36,6 +36,7 @@
#include <QString>
#include <QStringList>
#include <QDebug>
+#include <QSet>
extern int logLevel;
#define LogError() if (logLevel < 0) {} else qDebug() << "ERROR:"
@@ -86,7 +87,6 @@ public:
bool isFramework;
};
-
inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info);
void changeQtFrameworks(const QString appPath, const QString &qtPath, bool useDebugLibs);
@@ -108,7 +108,9 @@ void runStrip(const QString &binaryPath);
void stripAppBinary(const QString &bundlePath);
QString findAppBinary(const QString &appBundlePath);
QStringList findAppFrameworkNames(const QString &appBundlePath);
+QStringList findAppFrameworkPaths(const QString &appBundlePath);
void codesignFile(const QString &identity, const QString &filePath);
+QSet<QString> codesignBundle(const QString &identity, const QString &appBundlePath);
void codesign(const QString &identity, const QString &appBundlePath);
void createDiskImage(const QString &appBundlePath);
void fixupFramework(const QString &appBundlePath);
diff --git a/src/qdoc/cppcodemarker.cpp b/src/qdoc/cppcodemarker.cpp
index b0e4e823d..0f413c7f5 100644
--- a/src/qdoc/cppcodemarker.cpp
+++ b/src/qdoc/cppcodemarker.cpp
@@ -179,8 +179,14 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node,
if (style == Summary || style == Accessors) {
if (func->virtualness() != FunctionNode::NonVirtual)
synopsis.prepend("virtual ");
+ if (func->isFinal())
+ synopsis.append(" final");
if (func->virtualness() == FunctionNode::PureVirtual)
synopsis.append(" = 0");
+ else if (func->isDeleted())
+ synopsis.append(" = delete");
+ else if (func->isDefaulted())
+ synopsis.append(" = default");
}
else if (style == Subpage) {
if (!func->returnType().isEmpty() && func->returnType() != "void")
@@ -190,8 +196,13 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node,
QStringList bracketed;
if (func->isStatic()) {
bracketed += "static";
- }
- else if (func->virtualness() != FunctionNode::NonVirtual) {
+ } else if (func->isDeleted()) {
+ bracketed += "delete";
+ } else if (func->isDefaulted()) {
+ bracketed += "default";
+ } else if (func->virtualness() != FunctionNode::NonVirtual) {
+ if (func->isFinal())
+ bracketed += "final";
if (func->virtualness() == FunctionNode::PureVirtual)
bracketed += "pure";
bracketed += "virtual";
diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp
index 0405cc2c2..03b74b83e 100644
--- a/src/qdoc/cppcodeparser.cpp
+++ b/src/qdoc/cppcodeparser.cpp
@@ -1179,7 +1179,7 @@ bool CppCodeParser::matchTemplateHeader()
return matchTemplateAngles();
}
-bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
+bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var, bool qProp)
{
/*
This code is really hard to follow... sorry. The loop is there to match
@@ -1255,7 +1255,7 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
}
while (match(Tok_Ampersand) || match(Tok_Aster) || match(Tok_const) ||
- match(Tok_Caret))
+ match(Tok_Caret) || match(Tok_Ellipsis))
dataType->append(previousLexeme());
if (match(Tok_LeftParenAster)) {
@@ -1305,6 +1305,10 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
if (varComment.exactMatch(previousLexeme()))
*var = varComment.cap(1);
}
+ else if (qProp && (match(Tok_default) || match(Tok_final))) {
+ // Hack to make 'default' and 'final' work again in Q_PROPERTY
+ *var = previousLexeme();
+ }
}
if (tok == Tok_LeftBracket) {
@@ -1512,7 +1516,7 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
}
if (parent && (tok == Tok_Semicolon ||
tok == Tok_LeftBracket ||
- tok == Tok_Colon)
+ tok == Tok_Colon || tok == Tok_Equal)
&& access != Node::Private) {
if (tok == Tok_LeftBracket) {
returnType.appendHotspot();
@@ -1528,7 +1532,7 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
return false;
}
}
- else if (tok == Tok_Colon) {
+ else if (tok == Tok_Colon || tok == Tok_Equal) {
returnType.appendHotspot();
while (tok != Tok_Semicolon && tok != Tok_Eoi) {
@@ -1570,11 +1574,18 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
// look for const
bool matchedConst = match(Tok_const);
+ bool matchFinal = match(Tok_final);
- // look for 0 indicating pure virtual
- if (match(Tok_Equal) && match(Tok_Number))
- virtuality = FunctionNode::PureVirtual;
-
+ bool isDeleted = false;
+ bool isDefaulted = false;
+ if (match(Tok_Equal)) {
+ if (match(Tok_Number)) // look for 0 indicating pure virtual
+ virtuality = FunctionNode::PureVirtual;
+ else if (match(Tok_delete))
+ isDeleted = true;
+ else if (match(Tok_default))
+ isDefaulted = true;
+ }
// look for colon indicating ctors which must be skipped
if (match(Tok_Colon)) {
while (tok != Tok_LeftBrace && tok != Tok_Eoi)
@@ -1644,6 +1655,9 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
func->setStatic(matched_static);
func->setConst(matchedConst);
func->setVirtualness(virtuality);
+ func->setIsDeleted(isDeleted);
+ func->setIsDefaulted(isDefaulted);
+ func->setFinal(matchFinal);
if (isQPrivateSignal)
func->setPrivateSignal();
if (!pvect.isEmpty()) {
@@ -1732,6 +1746,9 @@ bool CppCodeParser::matchClassDecl(Aggregate *parent,
}
}
}
+
+ const QString className = previousLexeme();
+ match(Tok_final); // ignore C++11 final class-virt-specifier
if (tok != Tok_Colon && tok != Tok_LeftBrace)
return false;
@@ -1739,7 +1756,7 @@ bool CppCodeParser::matchClassDecl(Aggregate *parent,
So far, so good. We have 'class Foo {' or 'class Foo :'.
This is enough to recognize a class definition.
*/
- ClassNode *classe = new ClassNode(parent, previousLexeme());
+ ClassNode *classe = new ClassNode(parent, className);
classe->setAccess(access);
classe->setLocation(location());
if (compat)
@@ -1931,8 +1948,15 @@ bool CppCodeParser::matchEnumDecl(Aggregate *parent)
if (!match(Tok_enum))
return false;
+ if (tok == Tok_struct || tok == Tok_class)
+ readToken(); // ignore C++11 struct or class attribute
if (match(Tok_Ident))
name = previousLexeme();
+ if (match(Tok_Colon)) { // ignore C++11 enum-base
+ CodeChunk dataType;
+ if (!matchDataType(&dataType))
+ return false;
+ }
if (tok != Tok_LeftBrace)
return false;
@@ -1995,7 +2019,7 @@ bool CppCodeParser::matchProperty(Aggregate *parent)
QString name;
CodeChunk dataType;
- if (!matchDataType(&dataType, &name))
+ if (!matchDataType(&dataType, &name, true))
return false;
PropertyNode *property = new PropertyNode(parent, name);
@@ -2004,7 +2028,7 @@ bool CppCodeParser::matchProperty(Aggregate *parent)
property->setDataType(dataType.toString());
while (tok != Tok_RightParen && tok != Tok_Eoi) {
- if (!match(Tok_Ident))
+ if (!match(Tok_Ident) && !match(Tok_default) && !match(Tok_final))
return false;
QString key = previousLexeme();
QString value;
diff --git a/src/qdoc/cppcodeparser.h b/src/qdoc/cppcodeparser.h
index ec0448232..7c110d2bb 100644
--- a/src/qdoc/cppcodeparser.h
+++ b/src/qdoc/cppcodeparser.h
@@ -117,7 +117,7 @@ protected:
bool matchModuleQualifier(QString& name);
bool matchTemplateAngles(CodeChunk *type = 0);
bool matchTemplateHeader();
- bool matchDataType(CodeChunk *type, QString *var = 0);
+ bool matchDataType(CodeChunk *type, QString *var = 0, bool qProp = false);
bool matchParameter(QVector<Parameter>& pvect, bool& isQPrivateSignal);
bool matchFunctionDecl(Aggregate *parent,
QStringList *parentPathPtr,
diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp
index 81ad2a94b..c8c2ecefd 100644
--- a/src/qdoc/generator.cpp
+++ b/src/qdoc/generator.cpp
@@ -752,8 +752,26 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
}
if (node->doc().isEmpty()) {
- if (!node->isWrapper() && !quiet && !node->isReimplemented()) { // ### might be unnecessary
- node->location().warning(tr("No documentation for '%1'").arg(node->plainFullName()));
+ /*
+ Test for special function, like a destructor or copy constructor,
+ that has no documentation.
+ */
+ if (node->type() == Node::Function) {
+ const FunctionNode* func = static_cast<const FunctionNode*>(node);
+ if (func->isDtor()) {
+ Text text;
+ text << "Destroys the instance of ";
+ text << func->parent()->name() << ".";
+ if (func->isVirtual())
+ text << " The destructor is virtual.";
+ generateText(text, node, marker);
+ }
+ else if (!node->isWrapper() && !quiet && !node->isReimplemented()) {
+ node->location().warning(tr("No documentation for '%1'").arg(node->plainSignature()));
+ }
+ }
+ else if (!node->isWrapper() && !quiet && !node->isReimplemented()) {
+ node->location().warning(tr("No documentation for '%1'").arg(node->plainSignature()));
}
}
else {
diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp
index 6b43cc653..74b93b14d 100644
--- a/src/qdoc/htmlgenerator.cpp
+++ b/src/qdoc/htmlgenerator.cpp
@@ -3218,7 +3218,7 @@ void HtmlGenerator::generateList(const Node* relative, CodeMarker* marker, const
comment where the topic is \group, \module,
\qmlmodule, or \jsmodule
*/
- if (!relative || !relative->isCollectionNode()) {
+ if (relative && !relative->isCollectionNode()) {
relative->doc().location().warning(tr("\\generatelist {%1} is only allowed in \\group, "
"\\module, \\qmlmodule, and \\jsmodule comments.").arg(selector));
return;
diff --git a/src/qdoc/main.cpp b/src/qdoc/main.cpp
index 8ebebda79..500a085cc 100644
--- a/src/qdoc/main.cpp
+++ b/src/qdoc/main.cpp
@@ -728,8 +728,11 @@ int main(int argc, char **argv)
Generator::setQDocPass(Generator::Prepare);
if (parser.isSet(generateOption))
Generator::setQDocPass(Generator::Generate);
- if (parser.isSet(singleExecOption))
+ if (parser.isSet(singleExecOption)) {
Generator::setSingleExec();
+ if (parser.isSet(indexDirOption))
+ qDebug() << "WARNING: -indexdir option ignored: Index files are not used in -single-exec mode.";
+ }
if (parser.isSet(writeQaPagesOption))
Generator::setWriteQaPages();
if (parser.isSet(logProgressOption))
diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp
index 9740f984f..d91d473ce 100644
--- a/src/qdoc/node.cpp
+++ b/src/qdoc/node.cpp
@@ -165,6 +165,29 @@ QString Node::plainFullName(const Node* relative) const
}
/*!
+ Constructs and returns the node's fully qualified signature
+ by recursively ascending the parent links and prepending each
+ parent name + "::" to the plain signature. The return type is
+ not included.
+ */
+QString Node::plainSignature() const
+{
+ if (name_.isEmpty())
+ return QLatin1String("global");
+
+ QString fullName;
+ const Node* node = this;
+ while (node) {
+ fullName.prepend(node->signature(false, true));
+ if (node->parent()->name().isEmpty())
+ break;
+ fullName.prepend(QLatin1String("::"));
+ node = node->parent();
+ }
+ return fullName;
+}
+
+/*!
Constructs and returns this node's full name.
*/
QString Node::fullName(const Node* relative) const
@@ -1951,6 +1974,9 @@ FunctionNode::FunctionNode(Aggregate *parent, const QString& name)
attached_(false),
privateSignal_(false),
overload_(false),
+ isDeleted_(false),
+ isDefaulted_(false),
+ isFinal_(false),
reimplementedFrom_(0)
{
setGenus(Node::CPP);
@@ -1974,6 +2000,9 @@ FunctionNode::FunctionNode(NodeType type, Aggregate *parent, const QString& name
attached_(attached),
privateSignal_(false),
overload_(false),
+ isDeleted_(false),
+ isDefaulted_(false),
+ isFinal_(false),
reimplementedFrom_(0)
{
setGenus(Node::QML);
@@ -2133,10 +2162,10 @@ QStringList FunctionNode::reconstructParameters(bool values) const
is true, the default values of the parameters are included, if
present.
*/
-QString FunctionNode::signature(bool values) const
+QString FunctionNode::signature(bool values, bool noReturnType) const
{
QString s;
- if (!returnType().isEmpty())
+ if (!noReturnType && !returnType().isEmpty())
s = returnType() + QLatin1Char(' ');
s += name() + QLatin1Char('(');
QStringList reconstructedParameters = reconstructParameters(values);
diff --git a/src/qdoc/node.h b/src/qdoc/node.h
index 945bc2187..9df3dd70a 100644
--- a/src/qdoc/node.h
+++ b/src/qdoc/node.h
@@ -159,7 +159,9 @@ public:
QString plainName() const;
QString plainFullName(const Node* relative = 0) const;
+ QString plainSignature() const;
QString fullName(const Node* relative=0) const;
+ virtual QString signature(bool , bool ) const { return plainName(); }
const QString& fileNameBase() const { return fileNameBase_; }
bool hasFileNameBase() const { return !fileNameBase_.isEmpty(); }
@@ -894,6 +896,8 @@ public:
bool isOverload() const { return overload_; }
bool isReimplemented() const Q_DECL_OVERRIDE { return reimplemented_; }
bool isFunction() const Q_DECL_OVERRIDE { return true; }
+ bool isDtor() const { return (metaness_ == Dtor); }
+ bool isVirtual() const { return (virtualness_ == NormalVirtual); }
virtual bool isQmlSignal() const Q_DECL_OVERRIDE {
return (type() == Node::QmlSignal) && (genus() == Node::QML);
}
@@ -926,7 +930,7 @@ public:
bool hasActiveAssociatedProperty() const;
QStringList reconstructParameters(bool values = false) const;
- QString signature(bool values = false) const;
+ virtual QString signature(bool values, bool noReturnType = false) const;
virtual QString element() const Q_DECL_OVERRIDE { return parent()->name(); }
virtual bool isAttached() const Q_DECL_OVERRIDE { return attached_; }
virtual bool isQtQuickNode() const Q_DECL_OVERRIDE { return parent()->isQtQuickNode(); }
@@ -945,6 +949,15 @@ public:
void debug() const;
+ bool isDeleted() const { return isDeleted_; }
+ void setIsDeleted(bool b) { isDeleted_ = b; }
+
+ bool isDefaulted() const { return isDefaulted_; }
+ void setIsDefaulted(bool b) { isDefaulted_ = b; }
+
+ void setFinal(bool b) { isFinal_ = b; }
+ bool isFinal() const { return isFinal_; }
+
private:
void addAssociatedProperty(PropertyNode* property);
@@ -961,6 +974,9 @@ private:
bool attached_: 1;
bool privateSignal_: 1;
bool overload_ : 1;
+ bool isDeleted_ : 1;
+ bool isDefaulted_ : 1;
+ bool isFinal_ : 1;
unsigned char overloadNumber_;
QVector<Parameter> parameters_;
const FunctionNode* reimplementedFrom_;
diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp
index b3bf064fa..f588638fe 100644
--- a/src/qdoc/qdocindexfiles.cpp
+++ b/src/qdoc/qdocindexfiles.cpp
@@ -523,6 +523,9 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader,
functionNode->setMetaness(meta);
functionNode->setConst(attributes.value(QLatin1String("const")) == QLatin1String("true"));
functionNode->setStatic(attributes.value(QLatin1String("static")) == QLatin1String("true"));
+ functionNode->setIsDeleted(attributes.value(QLatin1String("delete")) == QLatin1String("true"));
+ functionNode->setIsDefaulted(attributes.value(QLatin1String("default")) == QLatin1String("true"));
+ functionNode->setFinal(attributes.value(QLatin1String("final")) == QLatin1String("true"));
if (attributes.value(QLatin1String("overload")) == QLatin1String("true")) {
functionNode->setOverloadFlag(true);
functionNode->setOverloadNumber(attributes.value(QLatin1String("overload-number")).toUInt());
@@ -1245,6 +1248,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("const", functionNode->isConst()?"true":"false");
writer.writeAttribute("static", functionNode->isStatic()?"true":"false");
writer.writeAttribute("overload", functionNode->isOverload()?"true":"false");
+ writer.writeAttribute("delete", functionNode->isDeleted() ? "true" : "false");
+ writer.writeAttribute("default", functionNode->isDefaulted() ? "true" : "false");
+ writer.writeAttribute("final", functionNode->isFinal() ? "true" : "false");
if (functionNode->isOverload())
writer.writeAttribute("overload-number", QString::number(functionNode->overloadNumber()));
if (functionNode->relates()) {
@@ -1267,9 +1273,17 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
Note: The "signature" attribute is written to the
index file, but it is not read back in. Is that ok?
*/
- QString signature = functionNode->signature();
+ QString signature = functionNode->signature(false);
if (functionNode->isConst())
signature += " const";
+ if (functionNode->isFinal())
+ signature += " final";
+ if (functionNode->virtualness() == FunctionNode::PureVirtual)
+ signature += " = 0";
+ else if (functionNode->isDeleted())
+ signature += " = delete";
+ else if (functionNode->isDefaulted())
+ signature += " = default";
writer.writeAttribute("signature", signature);
for (int i = 0; i < functionNode->parameters().size(); ++i) {
@@ -1483,9 +1497,9 @@ bool compareNodes(const Node* n1, const Node* n2)
else if (f1->isConst() > f2->isConst())
return false;
- if (f1->signature() < f2->signature())
+ if (f1->signature(false) < f2->signature(false))
return true;
- else if (f1->signature() > f2->signature())
+ else if (f1->signature(false) > f2->signature(false))
return false;
}
diff --git a/src/qdoc/qdoctagfiles.cpp b/src/qdoc/qdoctagfiles.cpp
index 1210ac7c3..cc5b30c8e 100644
--- a/src/qdoc/qdoctagfiles.cpp
+++ b/src/qdoc/qdoctagfiles.cpp
@@ -271,7 +271,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const Aggreg
writer.writeAttribute("virtualness", "virtual");
break;
case FunctionNode::PureVirtual:
- writer.writeAttribute("virtual", "pure");
+ writer.writeAttribute("virtualness", "pure");
break;
default:
break;
@@ -287,12 +287,18 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const Aggreg
QStringList pieces = gen_->fullDocumentLocation(node, false).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
- QString signature = functionNode->signature();
+ QString signature = functionNode->signature(false);
signature = signature.mid(signature.indexOf(QChar('('))).trimmed();
if (functionNode->isConst())
signature += " const";
+ if (functionNode->isFinal())
+ signature += " final";
if (functionNode->virtualness() == FunctionNode::PureVirtual)
signature += " = 0";
+ else if (functionNode->isDeleted())
+ signature += " = delete";
+ else if (functionNode->isDefaulted())
+ signature += " = default";
writer.writeTextElement("arglist", signature);
}
writer.writeEndElement(); // member
diff --git a/src/qdoc/tokenizer.cpp b/src/qdoc/tokenizer.cpp
index 987fff548..f723debe7 100644
--- a/src/qdoc/tokenizer.cpp
+++ b/src/qdoc/tokenizer.cpp
@@ -59,7 +59,7 @@ static const char *kwords[] = {
"private", "protected", "public", "short", "signals", "signed",
"slots", "static", "struct", "template", "typedef", "typename",
"union", "unsigned", "using", "virtual", "void", "volatile",
- "__int64",
+ "__int64", "default", "delete", "final",
"Q_OBJECT",
"Q_OVERRIDE",
"Q_PROPERTY",
diff --git a/src/qdoc/tokenizer.h b/src/qdoc/tokenizer.h
index 41a3ffd93..2f293379f 100644
--- a/src/qdoc/tokenizer.h
+++ b/src/qdoc/tokenizer.h
@@ -66,7 +66,8 @@ enum { Tok_Eoi, Tok_Ampersand, Tok_Aster, Tok_Caret, Tok_LeftParen,
Tok_public, Tok_short, Tok_signals, Tok_signed, Tok_slots,
Tok_static, Tok_struct, Tok_template, Tok_typedef,
Tok_typename, Tok_union, Tok_unsigned, Tok_using, Tok_virtual,
- Tok_void, Tok_volatile, Tok_int64, Tok_Q_OBJECT, Tok_Q_OVERRIDE,
+ Tok_void, Tok_volatile, Tok_int64, Tok_default, Tok_delete, Tok_final,
+ Tok_Q_OBJECT, Tok_Q_OVERRIDE,
Tok_Q_PROPERTY, Tok_Q_PRIVATE_PROPERTY, Tok_Q_DECLARE_SEQUENTIAL_ITERATOR,
Tok_Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR,
Tok_Q_DECLARE_ASSOCIATIVE_ITERATOR,
diff --git a/src/qtdiag/main.cpp b/src/qtdiag/main.cpp
index 6bc42bc2c..7e304d401 100644
--- a/src/qtdiag/main.cpp
+++ b/src/qtdiag/main.cpp
@@ -53,14 +53,18 @@ int main(int argc, char **argv)
QCommandLineParser commandLineParser;
const QCommandLineOption noGlOption(QStringLiteral("no-gl"), QStringLiteral("Do not output GL information"));
const QCommandLineOption glExtensionOption(QStringLiteral("gl-extensions"), QStringLiteral("List GL extensions"));
+ const QCommandLineOption fontOption(QStringLiteral("fonts"), QStringLiteral("Output list of fonts"));
commandLineParser.setApplicationDescription(QStringLiteral("Prints diagnostic output about the Qt library."));
commandLineParser.addOption(noGlOption);
commandLineParser.addOption(glExtensionOption);
+ commandLineParser.addOption(fontOption);
commandLineParser.addHelpOption();
commandLineParser.process(app);
unsigned flags = commandLineParser.isSet(noGlOption) ? 0u : unsigned(QtDiagGl);
if (commandLineParser.isSet(glExtensionOption))
flags |= QtDiagGlExtensions;
+ if (commandLineParser.isSet(fontOption))
+ flags |= QtDiagFonts;
std::wcout << qtDiag(flags).toStdWString();
return 0;
diff --git a/src/qtdiag/qtdiag.cpp b/src/qtdiag/qtdiag.cpp
index 4e9a25f28..310cbea08 100644
--- a/src/qtdiag/qtdiag.cpp
+++ b/src/qtdiag/qtdiag.cpp
@@ -113,6 +113,16 @@ QTextStream &operator<<(QTextStream &str, const QFont &f)
return str;
}
+QTextStream &operator<<(QTextStream &str, QPlatformScreen::SubpixelAntialiasingType st)
+{
+ static const char *enumValues[] = {
+ "Subpixel_None", "Subpixel_RGB", "Subpixel_BGR", "Subpixel_VRGB", "Subpixel_VBGR"
+ };
+ str << (size_t(st) < sizeof(enumValues) / sizeof(enumValues[0])
+ ? enumValues[st] : "<Unknown>");
+ return str;
+}
+
#ifndef QT_NO_OPENGL
QTextStream &operator<<(QTextStream &str, const QSurfaceFormat &format)
@@ -222,6 +232,18 @@ static QString formatQDebug(T t)
return result;
}
+// Helper to format a type via QDebug, stripping the class name.
+template <class T>
+static QString formatValueQDebug(T t)
+{
+ QString result = formatQDebug(t).trimmed();
+ if (result.endsWith(QLatin1Char(')'))) {
+ result.chop(1);
+ result.remove(0, result.indexOf(QLatin1Char('(')) + 1);
+ }
+ return result;
+}
+
static inline QByteArrayList qtFeatures()
{
QByteArrayList result;
@@ -445,11 +467,7 @@ QString qtDiag(unsigned flags)
<< " from " << platformTheme->themeHint(QPlatformTheme::IconThemeSearchPaths).toStringList() << '\n';
}
if (const QFont *systemFont = platformTheme->font())
- str << " System font : " << *systemFont<< '\n';
- str << " General font : " << QFontDatabase::systemFont(QFontDatabase::GeneralFont) << '\n'
- << " Fixed font : " << QFontDatabase::systemFont(QFontDatabase::FixedFont) << '\n'
- << " Title font : " << QFontDatabase::systemFont(QFontDatabase::TitleFont) << '\n'
- << " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << '\n';
+ str << "\n System font : " << *systemFont<< '\n';
if (platformTheme->usePlatformNativeDialog(QPlatformTheme::FileDialog))
str << " Native file dialog\n";
@@ -460,6 +478,27 @@ QString qtDiag(unsigned flags)
if (platformTheme->usePlatformNativeDialog(QPlatformTheme::MessageDialog))
str << " Native message dialog\n";
+ str << "\nFonts:\n General font : " << QFontDatabase::systemFont(QFontDatabase::GeneralFont) << '\n'
+ << " Fixed font : " << QFontDatabase::systemFont(QFontDatabase::FixedFont) << '\n'
+ << " Title font : " << QFontDatabase::systemFont(QFontDatabase::TitleFont) << '\n'
+ << " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << '\n';
+ if (flags & QtDiagFonts) {
+ QFontDatabase fontDatabase;
+ const QStringList families = fontDatabase.families();
+ str << "\n Families (" << families.size() << "):\n";
+ for (int i = 0, count = families.size(); i < count; ++i)
+ str << " " << families.at(i) << '\n';
+
+ const QList<int> standardSizes = QFontDatabase::standardSizes();
+ str << "\n Standard Sizes:";
+ for (int i = 0, count = standardSizes.size(); i < count; ++i)
+ str << ' ' << standardSizes.at(i);
+ QList<QFontDatabase::WritingSystem> writingSystems = fontDatabase.writingSystems();
+ str << "\n\n Writing systems:\n";
+ for (int i = 0, count = writingSystems.size(); i < count; ++i)
+ str << " " << formatValueQDebug(writingSystems.at(i)) << '\n';
+ }
+
const QList<QScreen*> screens = QGuiApplication::screens();
const int screenCount = screens.size();
str << "\nScreens: " << screenCount << ", High DPI scaling: "
@@ -490,7 +529,7 @@ QString qtDiag(unsigned flags)
<< " Logical DPI: " << dpi;
if (dpi != nativeDpi)
str << " (native: " << nativeDpi << ')';
- str << "\n ";
+ str << ' ' << platformScreen->subpixelAntialiasingTypeHint() << "\n ";
if (QHighDpiScaling::isActive())
str << "High DPI scaling factor: " << QHighDpiScaling::factor(screen) << ' ';
str << "DevicePixelRatio: " << screen->devicePixelRatio()
diff --git a/src/qtdiag/qtdiag.h b/src/qtdiag/qtdiag.h
index 9076c9b7e..3729a53a4 100644
--- a/src/qtdiag/qtdiag.h
+++ b/src/qtdiag/qtdiag.h
@@ -40,7 +40,8 @@ QT_BEGIN_NAMESPACE
enum QtDiagFlags {
QtDiagGl = 0x1,
- QtDiagGlExtensions = 0x2
+ QtDiagGlExtensions = 0x2,
+ QtDiagFonts = 0x4
};
QString qtDiag(unsigned flags = 0);
diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp
index eacf52db9..c74f7c4b4 100644
--- a/src/winrtrunner/appxengine.cpp
+++ b/src/winrtrunner/appxengine.cpp
@@ -52,6 +52,9 @@
#include <wrl.h>
#include <windows.applicationmodel.h>
#include <windows.management.deployment.h>
+#if _MSC_VER >= 1900
+#include <wincrypt.h>
+#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@@ -62,6 +65,240 @@ using namespace ABI::Windows::System;
QT_USE_NAMESPACE
+#if _MSC_VER >= 1900
+// *********** 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
+#endif // MSC_VER >= 1900
+
bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest)
{
if (!QFile::exists(fileName)) {
@@ -194,6 +431,14 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
d->packageFamilyName = QString::fromWCharArray(packageFamilyName);
CoTaskMemFree(packageFamilyName);
+#if _MSC_VER >= 1900
+ LPWSTR publisher;
+ packageId->GetPublisher(&publisher);
+ CHECK_RESULT_FATAL("Failed to retrieve publisher name from package.", return);
+ d->publisherName = QString::fromWCharArray(publisher);
+ CoTaskMemFree(publisher);
+#endif // _MSC_VER >= 1900
+
ComPtr<IAppxManifestApplicationsEnumerator> applications;
hr = manifestReader->GetApplications(&applications);
CHECK_RESULT_FATAL("Failed to get a list of applications from the manifest.", return);
@@ -441,3 +686,90 @@ bool AppxEngine::createPackage(const QString &packageFileName)
return true;
}
+
+bool AppxEngine::sign(const QString &fileName)
+{
+#if _MSC_VER >= 1900
+ 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));
+#else // _MSC_VER < 1900
+ Q_UNUSED(fileName);
+ return true;
+#endif // _MSC_VER < 1900
+}
diff --git a/src/winrtrunner/appxengine.h b/src/winrtrunner/appxengine.h
index 30b03fe07..4aec67588 100644
--- a/src/winrtrunner/appxengine.h
+++ b/src/winrtrunner/appxengine.h
@@ -63,6 +63,7 @@ protected:
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;
diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h
index 4d20acf91..982c484b2 100644
--- a/src/winrtrunner/appxengine_p.h
+++ b/src/winrtrunner/appxengine_p.h
@@ -73,6 +73,7 @@ public:
QString manifest;
QString packageFullName;
QString packageFamilyName;
+ QString publisherName;
ABI::Windows::System::ProcessorArchitecture packageArchitecture;
QString executable;
qint64 pid;
diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp
index e7cbf6709..edbb58ea5 100644
--- a/src/winrtrunner/appxphoneengine.cpp
+++ b/src/winrtrunner/appxphoneengine.cpp
@@ -258,6 +258,14 @@ AppxPhoneEngine::~AppxPhoneEngine()
QString AppxPhoneEngine::extensionSdkPath() const
{
+#if _MSC_VER >= 1900
+ const QByteArray extensionSdkDirRaw = qgetenv("ExtensionSdkDir");
+ if (extensionSdkDirRaw.isEmpty()) {
+ qCWarning(lcWinRtRunner) << "The environment variable ExtensionSdkDir is not set.";
+ return QString();
+ }
+ return QString::fromLocal8Bit(extensionSdkDirRaw);
+#else // _MSC_VER < 1900
HKEY regKey;
LONG hr = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
@@ -278,6 +286,7 @@ QString AppxPhoneEngine::extensionSdkPath() const
return QString::fromWCharArray(pathData, (pathLength - 1) / sizeof(wchar_t))
+ QLatin1String("ExtensionSDKs");
+#endif // _MSC_VER < 1900
}
bool AppxPhoneEngine::installPackage(IAppxManifestReader *reader, const QString &filePath)
@@ -384,6 +393,9 @@ bool AppxPhoneEngine::install(bool removeFirst)
if (!createPackage(packageFileName))
return false;
+ if (!sign(packageFileName))
+ return false;
+
ComPtr<IStream> manifestStream;
hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
RETURN_FALSE_IF_FAILED("Failed to open manifest stream");
diff --git a/src/winrtrunner/winrtrunner.pro b/src/winrtrunner/winrtrunner.pro
index c98f0df70..73ca2cdd4 100644
--- a/src/winrtrunner/winrtrunner.pro
+++ b/src/winrtrunner/winrtrunner.pro
@@ -17,4 +17,7 @@ win32-msvc2013|win32-msvc2015 {
include(../shared/corecon/corecon.pri)
}
+# Windows 10 requires signing
+*msvc2015: LIBS += -lcrypt32
+
load(qt_tool)