diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp
index e4a0e365696c166b6141afb64c2657bc2f1abf6c..d17ddff8d22d9d41009307c719114e9f98ffb92b 100644
--- a/src/shared/proparser/ioutils.cpp
+++ b/src/shared/proparser/ioutils.cpp
@@ -44,6 +44,7 @@ using namespace ProFileEvaluatorInternal;
 
 IoUtils::FileType IoUtils::fileType(const QString &fileName)
 {
+    Q_ASSERT(fileName.isEmpty() || isAbsolutePath(fileName));
 #ifdef Q_OS_WIN
     DWORD attr = GetFileAttributesW((WCHAR*)fileName.constData());
     if (attr == INVALID_FILE_ATTRIBUTES)
@@ -86,3 +87,116 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
         return QDir::cleanPath(fileName);
     return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
 }
+
+#ifdef Q_OS_WIN
+
+// FIXME: Without this, quoting is not foolproof. But it needs support in the process setup, etc.
+//#define PERCENT_ESCAPE QLatin1String("%PERCENT_SIGN%")
+
+static QString quoteArgInternal(const QString &arg)
+{
+    // Escape quotes, preceding backslashes are doubled. Surround with quotes.
+    // Note that cmd does not understand quote escapes in quoted strings,
+    // so the quoting needs to be "suspended".
+    const QLatin1Char bs('\\'), dq('"');
+    QString ret;
+    bool inquote = false;
+    int bslashes = 0;
+    for (int p = 0; p < arg.length(); p++) {
+        if (arg[p] == bs) {
+            bslashes++;
+        } else if (arg[p] == dq) {
+            if (inquote) {
+                ret.append(dq);
+                inquote = false;
+            }
+            for (; bslashes; bslashes--)
+                ret.append(QLatin1String("\\\\"));
+            ret.append(QLatin1String("\\^\""));
+        } else {
+            if (!inquote) {
+                ret.append(dq);
+                inquote = true;
+            }
+            for (; bslashes; bslashes--)
+                ret.append(bs);
+            ret.append(arg[p]);
+        }
+    }
+    //ret.replace(QLatin1Char('%'), PERCENT_ESCAPE);
+    if (bslashes) {
+        // Ensure that we don't have directly trailing backslashes,
+        // so concatenating with another string won't cause surprises.
+        if (!inquote)
+            ret.append(dq);
+        for (; bslashes; bslashes--)
+            ret.append(QLatin1String("\\\\"));
+        ret.append(dq);
+    } else if (inquote) {
+        ret.append(dq);
+    }
+    return ret;
+}
+
+inline static bool isSpecialChar(ushort c)
+{
+    // Chars that should be quoted (TM). This includes:
+    // - control chars & space
+    // - the shell meta chars &()<>^|
+    // - the potential separators ,;=
+    static const uchar iqm[] = {
+        0xff, 0xff, 0xff, 0xff, 0x41, 0x13, 0x00, 0x78,
+        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
+    };
+
+    return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+QString IoUtils::shellQuote(const QString &arg)
+{
+    if (arg.isEmpty())
+        return QString::fromLatin1("\"\"");
+
+    // Ensure that we don't have directly trailing backslashes,
+    // so concatenating with another string won't cause surprises.
+    if (arg.endsWith(QLatin1Char('\\')))
+        return quoteArgInternal(arg);
+
+    for (int x = arg.length() - 1; x >= 0; --x)
+        if (isSpecialChar(arg[x].unicode()))
+            return quoteArgInternal(arg);
+
+    // Escape quotes. Preceding backslashes are doubled.
+    // Note that the remaining string is not quoted.
+    QString ret(arg);
+    ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\^\""));
+    //ret.replace('%', PERCENT_ESCAPE);
+    return ret;
+}
+
+#else // Q_OS_WIN
+
+inline static bool isSpecial(const QChar &cUnicode)
+{
+    static const uchar iqm[] = {
+        0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
+        0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
+    }; // 0-32 \'"$`<>|;&(){}*?#!~[]
+
+    uint c = cUnicode.unicode();
+    return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+QString IoUtils::shellQuote(const QString &arg)
+{
+    if (!arg.length())
+        return QString::fromLatin1("''");
+    for (int i = 0; i < arg.length(); i++)
+        if (isSpecial(arg.unicode()[i])) {
+            const QLatin1Char q('\'');
+            return q + QString(arg).replace(q, QLatin1String("'\\''")) + q;
+        }
+    return arg;
+}
+
+#endif // Q_OS_WIN
diff --git a/src/shared/proparser/ioutils.h b/src/shared/proparser/ioutils.h
index 4655649f4e7734bd8c03e4119edacef55d4e8724..402612601eac3f7986b921478108dce9e37c07dd 100644
--- a/src/shared/proparser/ioutils.h
+++ b/src/shared/proparser/ioutils.h
@@ -52,6 +52,7 @@ public:
     static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
     static QStringRef fileName(const QString &fileName); // Requires normalized path
     static QString resolvePath(const QString &baseDir, const QString &fileName);
+    static QString shellQuote(const QString &arg);
 };
 
 }
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 71101e41b9239992bf1c933b3b79db7f61c8dfe7..92776f3d69cc76b53a4e2274166d6b619d91d4a3 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -282,7 +282,6 @@ public:
     bool m_hadCondition; // Nested calls set it on return, so no need for it to be in State
     int m_skipLevel;
     bool m_cumulative;
-    QStack<QString> m_oldPathStack;                 // To restore the current path to the path
     QStack<ProFile*> m_profileStack;                // To handle 'include(a.pri), so we can track back to 'a.pro' when finished with 'a.pri'
     struct ProLoop {
         QString variable;
@@ -1051,12 +1050,6 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProFile(ProFile *pro)
 {
     m_lineNo = pro->lineNumber();
 
-    m_oldPathStack.push(QDir::currentPath());
-    if (!QDir::setCurrent(pro->directoryName())) {
-        m_oldPathStack.pop();
-        return ProItem::ReturnFalse;
-    }
-
     m_profileStack.push(pro);
     if (m_profileStack.count() == 1) {
         // Do this only for the initial profile we visit, since
@@ -1114,7 +1107,8 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProFile(ProFile *pro)
                 }
 
                 if (IoUtils::isRelativePath(qmakespec)) {
-                    if (IoUtils::exists(qmakespec + QLatin1String("/qmake.conf"))) {
+                    if (IoUtils::exists(currentDirectory() + QLatin1Char('/') + qmakespec
+                                        + QLatin1String("/qmake.conf"))) {
                         qmakespec = currentDirectory() + QLatin1Char('/') + qmakespec;
                     } else if (!m_outputDir.isEmpty()
                                && IoUtils::exists(m_outputDir + QLatin1Char('/') + qmakespec
@@ -1199,7 +1193,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProFile(ProFile *pro)
     }
     m_profileStack.pop();
 
-    return returnBool(QDir::setCurrent(m_oldPathStack.pop()));
+    return ProItem::ReturnTrue;
 }
 
 ProItem::ProItemReturn ProFileEvaluator::Private::visitProFunction(ProFunction *func)
@@ -1927,7 +1921,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                 if (args.count() > 1)
                     singleLine = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive));
 
-                QFile qfile(file);
+                QFile qfile(resolvePath(file));
                 if (qfile.open(QIODevice::ReadOnly)) {
                     QTextStream stream(&qfile);
                     while (!stream.atEnd()) {
@@ -1981,7 +1975,9 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                     logMessage(format("system(execute) requires one or two arguments."));
                 } else {
                     char buff[256];
-                    FILE *proc = QT_POPEN(args[0].toLatin1(), "r");
+                    FILE *proc = QT_POPEN((QLatin1String("cd ")
+                                           + IoUtils::shellQuote(currentDirectory())
+                                           + QLatin1String(" && ") + args[0]).toLatin1(), "r");
                     bool singleLine = true;
                     if (args.count() > 1)
                         singleLine = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive));
@@ -2068,20 +2064,20 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                 if (args.count() == 2)
                     recursive = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive) || args[1].toInt());
                 QStringList dirs;
-                QString r = fixPathToLocalOS(args[0]);
+                QString r = fixPathToLocalOS(resolvePath(args[0]));
                 int slash = r.lastIndexOf(QDir::separator());
                 if (slash != -1) {
                     dirs.append(r.left(slash));
                     r = r.mid(slash+1);
                 } else {
-                    dirs.append(QString());
+                    dirs.append(fixPathToLocalOS(currentDirectory()));
                 }
 
                 const QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard);
                 for (int d = 0; d < dirs.count(); d++) {
                     QString dir = dirs[d];
-                    if (!dir.isEmpty() && !dir.endsWith(m_option->dir_sep))
-                        dir += QLatin1Char('/');
+                    if (!dir.endsWith(QDir::separator()))
+                        dir += QDir::separator();
 
                     QDir qdir(dir);
                     for (int i = 0; i < (int)qdir.count(); ++i) {
@@ -2617,7 +2613,9 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 logMessage(format("system(exec) requires one argument."));
                 ProItem::ReturnFalse;
             }
-            return returnBool(system(args.first().toLatin1().constData()) == 0);
+            return returnBool(system((QLatin1String("cd ")
+                                      + IoUtils::shellQuote(currentDirectory())
+                                      + QLatin1String(" && ") + args.first()).toLatin1().constData()) == 0);
         }
 #endif
         case T_ISEMPTY: {
@@ -2641,7 +2639,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 return ProItem::ReturnFalse;
             }
             QString file = args.first();
-            file = fixPathToLocalOS(file);
+            file = fixPathToLocalOS(resolvePath(file));
 
             if (IoUtils::exists(file)) {
                 return ProItem::ReturnTrue;
@@ -2871,7 +2869,7 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
     if (!fn.endsWith(QLatin1String(".prf")))
         fn += QLatin1String(".prf");
 
-    if (!fileName.contains((ushort)'/') || !IoUtils::exists(fn)) {
+    if (!fileName.contains((ushort)'/') || !IoUtils::exists(resolvePath(fn))) {
         if (m_option->feature_roots.isEmpty())
             m_option->feature_roots = qmakeFeaturePaths();
         int start_root = 0;