diff options
-rw-r--r-- | src/winrtrunner/appxengine.cpp | 87 | ||||
-rw-r--r-- | src/winrtrunner/appxengine_p.h | 1 | ||||
-rw-r--r-- | src/winrtrunner/appxphoneengine.cpp | 39 |
3 files changed, 80 insertions, 47 deletions
diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp index c74f7c4b4..dfdd7d0db 100644 --- a/src/winrtrunner/appxengine.cpp +++ b/src/winrtrunner/appxengine.cpp @@ -315,7 +315,7 @@ bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest) } // If it looks like an executable, check that manifest is next to it - if (fileName.endsWith(QStringLiteral(".exe"))) { + if (fileName.endsWith(QLatin1String(".exe"))) { QDir appDir = QFileInfo(fileName).absoluteDir(); QString manifestFileName = appDir.absoluteFilePath(QStringLiteral("AppxManifest.xml")); if (!QFile::exists(manifestFileName)) { @@ -328,7 +328,11 @@ bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest) return true; } - // TODO: handle already-built package as well + 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; @@ -375,12 +379,6 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) d->pid = -1; d->exitCode = UINT_MAX; - if (!getManifestFile(runner->app(), &d->manifest)) { - qCWarning(lcWinRtRunner) << "Unable to determine manifest file from" << runner->app(); - d->hasFatalError = true; - return; - } - HRESULT hr; hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), IID_PPV_ARGS(&d->uriFactory)); @@ -390,28 +388,57 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) IID_IAppxFactory, &d->packageFactory); CHECK_RESULT_FATAL("Failed to instantiate package factory.", return); - ComPtr<IStream> manifestStream; - hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); - CHECK_RESULT_FATAL("Failed to open manifest stream.", return); - - ComPtr<IAppxManifestReader> manifestReader; - hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &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"; + 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; } - 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 = manifestReader->GetPackageId(&packageId); + hr = d->manifestReader->GetPackageId(&packageId); CHECK_RESULT_FATAL("Unable to obtain the package ID from the manifest.", return); APPX_PACKAGE_ARCHITECTURE arch; @@ -440,7 +467,7 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) #endif // _MSC_VER >= 1900 ComPtr<IAppxManifestApplicationsEnumerator> applications; - hr = manifestReader->GetApplications(&applications); + hr = d->manifestReader->GetApplications(&applications); CHECK_RESULT_FATAL("Failed to get a list of applications from the manifest.", return); BOOL hasCurrent; @@ -455,12 +482,12 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) LPWSTR executable; application->GetStringValue(L"Executable", &executable); CHECK_RESULT_FATAL("Failed to retrieve the application executable from the manifest.", return); - d->executable = QFileInfo(d->manifest).absoluteDir() + d->executable = QFileInfo(runner->app()).absoluteDir() .absoluteFilePath(QString::fromWCharArray(executable)); CoTaskMemFree(executable); ComPtr<IAppxManifestPackageDependenciesEnumerator> dependencies; - hr = manifestReader->GetPackageDependencies(&dependencies); + hr = d->manifestReader->GetPackageDependencies(&dependencies); CHECK_RESULT_FATAL("Failed to retrieve the package dependencies from the manifest.", return); hr = dependencies->GetHasCurrent(&hasCurrent); diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h index 982c484b2..6ff41fed6 100644 --- a/src/winrtrunner/appxengine_p.h +++ b/src/winrtrunner/appxengine_p.h @@ -84,6 +84,7 @@ public: 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()) diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp index a71d03936..fb78e350b 100644 --- a/src/winrtrunner/appxphoneengine.cpp +++ b/src/winrtrunner/appxphoneengine.cpp @@ -224,8 +224,14 @@ AppxPhoneEngine::AppxPhoneEngine(Runner *runner) d->hasFatalError = true; ComPtr<IStream> manifestStream; - HRESULT hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); - RETURN_VOID_IF_FAILED("Failed to open manifest stream"); + 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."; @@ -393,23 +399,22 @@ bool AppxPhoneEngine::install(bool removeFirst) if (!installDependencies()) return false; - const QDir base = QFileInfo(d->manifest).absoluteDir(); - const QString packageFileName = base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx")); - if (!createPackage(packageFileName)) - return false; - - 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"); + 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; - ComPtr<IAppxManifestReader> manifestReader; - hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &manifestReader); - RETURN_FALSE_IF_FAILED("Failed to create manifest reader for installation"); + if (!sign(packageFileName)) + return false; + } else { + qCDebug(lcWinRtRunner) << "Installing existing package."; + } - return installPackage(manifestReader.Get(), packageFileName); + return installPackage(d->manifestReader.Get(), packageFileName); } bool AppxPhoneEngine::remove() |