Split win7MsixInstaller in 2 parts: a standalone library and a .exe providing the UI. (#69)

* Split win7MsixInstaller in 2 parts

* Add 2 synchronous method: AddPackage and RemovePackage

* add callback to AddPackageAsync and RemovePackageAsync and convert all pointers to unique_ptr/shared_ptr

* rename GetPackageInfoMsix to GetMsixPackageInfo
add MsixResponse::SetErrorStatus

* merge PackageBase::SetExecutableAndAppIdFromManifestElement and PackageBase::SetDisplayNameFromManifestElement + use package->GetPublisherDisplayName() instead of recomputing it in AddRemovePrograms
This commit is contained in:
Rudy Huyn 2019-04-24 11:07:10 -07:00 коммит произвёл wcheng-msft
Родитель 4497f4dab8
Коммит f23aa1268b
61 изменённых файлов: 1978 добавлений и 1085 удалений

Просмотреть файл

@ -4,9 +4,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 15.0.27703.2026
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win7MSIXInstaller", "Win7MSIXInstaller\Win7MSIXInstaller.vcxproj", "{AAD31763-5E65-47FD-958A-08E35AB83025}"
ProjectSection(ProjectDependencies) = postProject
{46BE19BD-72E0-4452-9919-33A1F8A5F064} = {46BE19BD-72E0-4452-9919-33A1F8A5F064}
EndProjectSection
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Win7MSIXInstallerSetup", "Win7MSIXInstallerSetup\Win7MSIXInstallerSetup.vdproj", "{C79C79A4-00CE-40C8-BCCE-A5C8F28A4E8D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win7MSIXInstallerLib", "Win7MSIXInstallerLib\Win7MSIXInstallerLib.vcxproj", "{46BE19BD-72E0-4452-9919-33A1F8A5F064}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B0C6E315-832B-4665-B979-4111A8C2F93B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
@ -36,6 +41,14 @@ Global
{C79C79A4-00CE-40C8-BCCE-A5C8F28A4E8D}.Debug|x86.ActiveCfg = Debug
{C79C79A4-00CE-40C8-BCCE-A5C8F28A4E8D}.Release|x64.ActiveCfg = Release
{C79C79A4-00CE-40C8-BCCE-A5C8F28A4E8D}.Release|x86.ActiveCfg = Release
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Debug|x64.ActiveCfg = Debug|x64
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Debug|x64.Build.0 = Debug|x64
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Debug|x86.ActiveCfg = Debug|Win32
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Debug|x86.Build.0 = Debug|Win32
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Release|x64.ActiveCfg = Release|x64
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Release|x64.Build.0 = Release|x64
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Release|x86.ActiveCfg = Release|Win32
{46BE19BD-72E0-4452-9919-33A1F8A5F064}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -8,6 +8,7 @@
#include "GeneralUtil.hpp"
#include <TraceLoggingProvider.h>
#include "Constants.hpp"
using namespace Win7MsixInstallerLib;
const PCWSTR AddRemovePrograms::HandlerName = L"AddRemovePrograms";
@ -18,7 +19,7 @@ HRESULT AddRemovePrograms::ExecuteForAddRequest()
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
auto packageInfo = m_msixRequest->GetPackageInfo();
std::wstring packageFullName = packageInfo->GetPackageFullName();
RegistryKey uninstallKey;
@ -30,7 +31,7 @@ HRESULT AddRemovePrograms::ExecuteForAddRequest()
std::wstring displayName = packageInfo->GetDisplayName();
RETURN_IF_FAILED(packageKey.SetStringValue(L"DisplayName", displayName));
std::wstring directoryPath = packageInfo->GetPackageDirectoryPath();
std::wstring directoryPath = m_msixRequest->GetPackageDirectoryPath();
RETURN_IF_FAILED(packageKey.SetStringValue(L"InstallLocation", directoryPath));
WCHAR filePath[MAX_PATH];
@ -43,15 +44,12 @@ HRESULT AddRemovePrograms::ExecuteForAddRequest()
std::wstring uninstallCommand = filePath + std::wstring(L" -RemovePackage ") + packageFullName;
RETURN_IF_FAILED(packageKey.SetStringValue(L"UninstallString", uninstallCommand));
std::wstring publisherString(packageInfo->GetPublisher());
auto publisherCommonName = publisherString.substr(publisherString.find_first_of(L"=") + 1,
publisherString.find_first_of(L",") - publisherString.find_first_of(L"=") - 1);
RETURN_IF_FAILED(packageKey.SetStringValue(L"Publisher", publisherCommonName));
RETURN_IF_FAILED(packageKey.SetStringValue(L"Publisher", packageInfo->GetPublisherDisplayName()));
std::wstring versionString(ConvertVersionToString(packageInfo->GetVersion()));
auto versionString = packageInfo->GetVersion();
RETURN_IF_FAILED(packageKey.SetStringValue(L"DisplayVersion", versionString));
std::wstring packageIconString = packageInfo->GetExecutableFilePath();
std::wstring packageIconString = m_msixRequest->GetPackageDirectoryPath() + L"\\" + packageInfo->GetRelativeExecutableFilePath();
RETURN_IF_FAILED(packageKey.SetStringValue(L"DisplayIcon", packageIconString));
TraceLoggingWrite(g_MsixTraceLoggingProvider,
@ -60,7 +58,7 @@ HRESULT AddRemovePrograms::ExecuteForAddRequest()
TraceLoggingValue(uninstallCommand.c_str(), "uninstallString"),
TraceLoggingValue(displayName.c_str(), "displayName"),
TraceLoggingValue(directoryPath.c_str(), "installLocation"),
TraceLoggingValue(publisherString.c_str(), "publisher"),
TraceLoggingValue(packageInfo->GetPublisher().c_str(), "publisher"),
TraceLoggingValue(versionString.c_str(), "displayVersion"),
TraceLoggingValue(packageIconString.c_str(), "displayIcon"));

Просмотреть файл

@ -2,7 +2,10 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Handles adding/removing the entry that allows an app to show up in AddRemovePrograms in the Control Panel (appwiz.cpl)
class AddRemovePrograms : IPackageHandler
{
@ -24,3 +27,4 @@ private:
AddRemovePrograms(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
};
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "GeneralUtil.hpp"
#include "Constants.hpp"
#include <TraceLoggingProvider.h>
using namespace Win7MsixInstallerLib;
const PCWSTR ComInterface::HandlerName = L"ComInterface";
@ -85,7 +86,7 @@ HRESULT ComInterface::ProcessTypeLibForAddRequest(TypeLib& typeLib)
RegistryKey win32Key;
RETURN_IF_FAILED(localeIdKey.CreateSubKey(win32KeyName.c_str(), KEY_WRITE, &win32Key));
std::wstring win32FullPath = m_msixRequest->GetFilePathMappings()->GetExecutablePath(version->win32Path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
std::wstring win32FullPath = FilePathMappings::GetInstance().GetExecutablePath(version->win32Path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
RETURN_IF_FAILED(win32Key.SetStringValue(L"", win32FullPath));
}
@ -94,7 +95,7 @@ HRESULT ComInterface::ProcessTypeLibForAddRequest(TypeLib& typeLib)
RegistryKey win64Key;
RETURN_IF_FAILED(localeIdKey.CreateSubKey(win64KeyName.c_str(), KEY_WRITE, &win64Key));
std::wstring win64FullPath = m_msixRequest->GetFilePathMappings()->GetExecutablePath(version->win64Path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
std::wstring win64FullPath = FilePathMappings::GetInstance().GetExecutablePath(version->win64Path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
RETURN_IF_FAILED(win64Key.SetStringValue(L"", win64FullPath));
}
@ -110,7 +111,7 @@ HRESULT ComInterface::ProcessTypeLibForAddRequest(TypeLib& typeLib)
RegistryKey helpDirKey;
RETURN_IF_FAILED(versionNumberKey.CreateSubKey(helpDirKeyName.c_str(), KEY_WRITE, &helpDirKey));
std::wstring helpDirFullPath = m_msixRequest->GetFilePathMappings()->GetExecutablePath(version->helpDirectory, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
std::wstring helpDirFullPath = FilePathMappings::GetInstance().GetExecutablePath(version->helpDirectory, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
RETURN_IF_FAILED(helpDirKey.SetStringValue(L"", helpDirFullPath));
}
}
@ -325,4 +326,4 @@ HRESULT ComInterface::CreateHandler(MsixRequest * msixRequest, IPackageHandler *
*instance = localInstance.release();
return S_OK;
}
}

Просмотреть файл

@ -2,8 +2,11 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "RegistryKey.hpp"
#include "MsixRequest.hpp"
#include <vector>
namespace Win7MsixInstallerLib
{
class ComInterface : IPackageHandler
{
public:
@ -90,3 +93,4 @@ private:
ComInterface(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
};
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "GeneralUtil.hpp"
#include "Constants.hpp"
#include <TraceLoggingProvider.h>
using namespace Win7MsixInstallerLib;
const PCWSTR ComServer::HandlerName = L"ComServer";
@ -52,7 +53,7 @@ HRESULT ComServer::ProcessExeServerForAdd(ExeServer& exeServer)
RETURN_IF_FAILED(clsidKey.CreateSubKey(exeServerClass->id.c_str(), KEY_WRITE, &classIdKey));
RETURN_IF_FAILED(classIdKey.SetStringValue(L"", exeServerClass->displayName));
std::wstring executableFullPath = m_msixRequest->GetFilePathMappings()->GetExecutablePath(exeServer.executable, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
std::wstring executableFullPath = FilePathMappings::GetInstance().GetExecutablePath(exeServer.executable, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
RegistryKey localServerKey;
RETURN_IF_FAILED(classIdKey.CreateSubKey(localServerKeyName.c_str(), KEY_WRITE, &localServerKey));
RETURN_IF_FAILED(localServerKey.SetStringValue(L"", executableFullPath));
@ -652,7 +653,7 @@ HRESULT ComServer::ParseDefaultIcon(IMsixElement * classElement, ExeServerClass
std::wstring resourceIndex;
RETURN_IF_FAILED(GetAttributeValueFromElement(defaultIconElement.Get(), resourceIndexAttribute, resourceIndex));
std::wstring resolvedPath = m_msixRequest->GetFilePathMappings()->GetExecutablePath(path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
std::wstring resolvedPath = FilePathMappings::GetInstance().GetExecutablePath(path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
exeServerClass.defaultIcon = std::wstring(L"\"") + resolvedPath + std::wstring(L"\",") + resourceIndex;
}
@ -677,7 +678,7 @@ HRESULT ComServer::ParseToolboxBitmap(IMsixElement * classElement, ExeServerClas
std::wstring resourceIndex;
RETURN_IF_FAILED(GetAttributeValueFromElement(toolboxBitmapElement.Get(), resourceIndexAttribute, resourceIndex));
std::wstring resolvedPath = m_msixRequest->GetFilePathMappings()->GetExecutablePath(path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
std::wstring resolvedPath = FilePathMappings::GetInstance().GetExecutablePath(path, m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str());
exeServerClass.toolboxBitmap = std::wstring(L"\"") + resolvedPath + std::wstring(L"\",") + resourceIndex;
}
@ -700,4 +701,4 @@ HRESULT ComServer::CreateHandler(MsixRequest * msixRequest, IPackageHandler ** i
*instance = localInstance.release();
return S_OK;
}
}

Просмотреть файл

@ -2,8 +2,10 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "RegistryKey.hpp"
#include "MsixRequest.hpp"
#include <vector>
namespace Win7MsixInstallerLib
{
class ComServer : IPackageHandler
{
public:
@ -169,4 +171,4 @@ private:
ComServer(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
};
}

Просмотреть файл

@ -1,10 +1,13 @@
#include <iostream>
#include <iomanip>
#include "CommandLineInterface.hpp"
#include "Win7MSIXInstallerLogger.hpp"
#include <TraceLoggingProvider.h>
#include "GeneralUtil.hpp"
#include "Util.hpp"
#include "resource.h"
using namespace Win7MsixInstallerLib;
std::map<std::wstring, Option, CaseInsensitiveLess> CommandLineInterface::s_options =
{
{
@ -40,7 +43,7 @@ std::map<std::wstring, Option, CaseInsensitiveLess> CommandLineInterface::s_opti
Option(false, IDS_STRING_HELP_OPTION_QUIETMODE,
[&](CommandLineInterface* commandLineInterface, const std::string&)
{
commandLineInterface->m_flags |= Flags::QuietUX;
commandLineInterface->m_quietMode = true;
return S_OK;
})
},
@ -98,11 +101,11 @@ void CommandLineInterface::DisplayHelp()
}
}
HRESULT CommandLineInterface::CreateRequest(MsixRequest** msixRequest)
HRESULT CommandLineInterface::Init()
{
for (int i = 0; i < m_argc; i++)
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
TraceLoggingWrite(g_MsixUITraceLoggingProvider,
"CommandLineArguments",
TraceLoggingValue(i, "index"),
TraceLoggingValue(m_argv[i], "arg"));
@ -126,7 +129,7 @@ HRESULT CommandLineInterface::CreateRequest(MsixRequest** msixRequest)
auto option = s_options.find(optionString);
if (option == s_options.end())
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
TraceLoggingWrite(g_MsixUITraceLoggingProvider,
"Unknown Argument",
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingValue(m_argv[index], "arg"));
@ -146,16 +149,5 @@ HRESULT CommandLineInterface::CreateRequest(MsixRequest** msixRequest)
++index;
}
AutoPtr<MsixRequest> localRequest;
RETURN_IF_FAILED(MsixRequest::Make(
m_operationType,
m_flags,
m_packageFilePath,
m_packageFullName,
m_validationOptions,
&localRequest)
);
*msixRequest = localRequest.Detach();
return S_OK;
}

Просмотреть файл

@ -2,7 +2,16 @@
#include <map>
#include <functional>
#include "MsixRequest.hpp"
#include <IPackage.hpp>
#include <AppxPackaging.hpp>
enum OperationType
{
Undefined = 0,
Add = 1,
Remove = 2,
FindPackage = 3,
FindAllPackages = 4,
};
class CommandLineInterface;
/// Describes an option to a command that the user may specify used for the command line tool
@ -50,9 +59,11 @@ public:
/// Displays contextual formatted help to the user used for command line tool
void DisplayHelp();
HRESULT CreateRequest(_Outptr_ MsixRequest** msixRequest);
HRESULT Init();
bool IsQuietMode() { return m_quietMode; }
std::wstring GetPackageFilePathToInstall() { return m_packageFilePath; }
std::wstring GetPackageFullName() { return m_packageFullName; }
OperationType GetOperationType() { return m_operationType; }
private:
int m_argc = 0;
char ** m_argv = nullptr;
@ -62,9 +73,8 @@ private:
std::wstring m_packageFilePath;
std::wstring m_packageFullName;
bool m_quietMode;
MSIX_VALIDATION_OPTION m_validationOptions = MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL;
Flags m_flags = NoFlags;
OperationType m_operationType = OperationType::Undefined;
CommandLineInterface() {}

Просмотреть файл

@ -7,6 +7,7 @@
#include <TraceLoggingProvider.h>
#include "ErrorHandler.hpp"
#include "MsixRequest.hpp"
using namespace Win7MsixInstallerLib;
const PCWSTR ErrorHandler::HandlerName = L"ErrorHandler";
@ -19,7 +20,7 @@ HRESULT ErrorHandler::ExecuteForAddRequest()
HRESULT ErrorHandler::RemovePackage(std::wstring packageFullName)
{
AutoPtr<MsixRequest> removePackageRequest;
RETURN_IF_FAILED(MsixRequest::Make(OperationType::Remove, Flags::NoFlags, std::wstring(), packageFullName,
RETURN_IF_FAILED(MsixRequest::Make(OperationType::Remove, std::wstring(), packageFullName,
MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &removePackageRequest));
const HRESULT hrCancelRequest = removePackageRequest->ProcessRequest();

Просмотреть файл

@ -1,10 +1,13 @@
#pragma once
#include <windows.h>
#include <string>
#include <windows.h>
#include <string>
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
class ErrorHandler : IPackageHandler
{
public:
@ -25,4 +28,5 @@ private:
/// Prepares and sends msixrequest to uninstall the package in case cancel button was clicked during installation
HRESULT RemovePackage(std::wstring packageFullName);
};
};
}

Просмотреть файл

@ -9,9 +9,9 @@
#include "FilePaths.hpp"
#include "Constants.hpp"
#include "InstallUI.hpp"
#include "RegistryDevirtualizer.hpp"
#include <TraceLoggingProvider.h>
using namespace Win7MsixInstallerLib;
const PCWSTR Extractor::HandlerName = L"Extractor";
@ -93,7 +93,10 @@ HRESULT Extractor::ExtractFile(IAppxFile* file)
ComPtr<IStream> fileStream;
RETURN_IF_FAILED(file->GetStream(&fileStream));
ComPtr<IStream> outputStream;
RETURN_IF_FAILED(GetOutputStream(m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath().c_str(), fileName.Get(), &outputStream));
auto packageDirectoryPath = m_msixRequest->GetPackageDirectoryPath();
RETURN_IF_FAILED(GetOutputStream(packageDirectoryPath.c_str(), fileName.Get(), &outputStream));
RETURN_IF_FAILED(fileStream->CopyTo(outputStream.Get(), fileSizeLargeInteger, nullptr, nullptr));
return S_OK;
}
@ -102,6 +105,8 @@ HRESULT Extractor::ExtractFootprintFiles()
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Extracting footprint files from the package");
auto packageToInstall = std::dynamic_pointer_cast<Package>(m_msixRequest->GetPackageInfo());
for (int i = 0; i < FootprintFilesCount; i++)
{
@ -110,18 +115,21 @@ HRESULT Extractor::ExtractFootprintFiles()
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
ComPtr<IAppxFile> footprintFile;
HRESULT hr = m_msixRequest->GetPackageInfo()->GetPackageReader()->GetFootprintFile(g_footprintFilesType[i].fileType, &footprintFile);
if (SUCCEEDED(hr) && footprintFile.Get())
if (packageToInstall != nullptr)
{
RETURN_IF_FAILED(ExtractFile(footprintFile.Get()));
}
else if (g_footprintFilesType[i].isRequired)
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Missing required Footprintfile",
TraceLoggingValue(g_footprintFilesType[i].description, "File Description"));
return hr;
ComPtr<IAppxFile> footprintFile;
HRESULT hr = packageToInstall->GetPackageReader()->GetFootprintFile(g_footprintFilesType[i].fileType, &footprintFile);
if (SUCCEEDED(hr) && footprintFile.Get())
{
RETURN_IF_FAILED(ExtractFile(footprintFile.Get()));
}
else if (g_footprintFilesType[i].isRequired)
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Missing required Footprintfile",
TraceLoggingValue(g_footprintFilesType[i].description, "File Description"));
return hr;
}
}
}
return S_OK;
@ -133,12 +141,19 @@ HRESULT Extractor::ExtractPayloadFiles()
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Extracting payload files from the package");
RETURN_IF_FAILED(m_msixRequest->GetPackageInfo()->GetPackageReader()->GetPayloadFiles(&files));
auto packageToInstall = std::dynamic_pointer_cast<Package>(m_msixRequest->GetPackageInfo());
if (packageToInstall == nullptr)
{
return E_FAIL;
}
RETURN_IF_FAILED(packageToInstall->GetPackageReader()->GetPayloadFiles(&files));
BOOL hasCurrent = FALSE;
RETURN_IF_FAILED(files->GetHasCurrent(&hasCurrent));
AutoPtr<UI> ui;
unsigned int totalNumberFiles = m_msixRequest->GetPackageInfo()->GetNumberOfPayloadFiles();
unsigned int nbrFilesExtracted = 0;
while (hasCurrent)
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
@ -160,7 +175,10 @@ HRESULT Extractor::ExtractPayloadFiles()
}
RETURN_IF_FAILED(files->MoveNext(&hasCurrent));
ui->UpdateProgressBar();
++nbrFilesExtracted;
float progress = 100.0f * nbrFilesExtracted / totalNumberFiles;
m_msixRequest->GetMsixResponse()->Update(InstallationStep::InstallationStepExtraction, progress);
}
return S_OK;
@ -168,7 +186,7 @@ HRESULT Extractor::ExtractPayloadFiles()
HRESULT Extractor::CreatePackageRoot()
{
std::wstring packagePath = m_msixRequest->GetFilePathMappings()->GetMsix7Directory();
std::wstring packagePath = FilePathMappings::GetInstance().GetMsix7Directory();
if (!CreateDirectory(packagePath.c_str(), nullptr))
{
DWORD lastError = GetLastError();
@ -178,7 +196,7 @@ HRESULT Extractor::CreatePackageRoot()
}
}
if (!CreateDirectory(m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath().c_str(), nullptr))
if (!CreateDirectory((FilePathMappings::GetInstance().GetMsix7Directory() + m_msixRequest->GetPackageInfo()->GetPackageFullName()).c_str(), nullptr))
{
DWORD lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS)
@ -200,12 +218,12 @@ HRESULT Extractor::ExecuteForAddRequest()
HRESULT Extractor::RemoveVfsFiles()
{
std::wstring blockMapPath = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath() + blockMapFile;
std::wstring blockMapPath = m_msixRequest->GetPackageDirectoryPath() + blockMapFile;
ComPtr<IStream> stream;
RETURN_IF_FAILED(CreateStreamOnFileUTF16(blockMapPath.c_str(), true /*forRead*/, &stream));
ComPtr<IAppxFactory> appxFactory;
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(MyAllocate, MyFree, m_msixRequest->GetValidationOptions(), &appxFactory));
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(Win7MsixInstallerLib_MyAllocate, Win7MsixInstallerLib_MyFree, m_msixRequest->GetValidationOptions(), &appxFactory));
ComPtr<IAppxBlockMapReader> blockMapReader;
RETURN_IF_FAILED(appxFactory->CreateBlockMapReader(stream.Get(), &blockMapReader));
@ -260,11 +278,12 @@ HRESULT Extractor::ExecuteForRemoveRequest()
m_msixRequest->GetPackageInfo()->ReleaseManifest();
std::error_code error;
uintmax_t numRemoved = std::experimental::filesystem::remove_all(m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath(), error);
auto packageDirectoryPath = m_msixRequest->GetPackageDirectoryPath();
uintmax_t numRemoved = std::experimental::filesystem::remove_all(packageDirectoryPath, error);
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Removed directory",
TraceLoggingValue(m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath().c_str(), "PackageDirectoryPath"),
TraceLoggingValue(packageDirectoryPath.c_str(), "PackageDirectoryPath"),
TraceLoggingValue(error.value(), "Error"),
TraceLoggingValue(numRemoved, "NumRemoved"));
@ -386,8 +405,8 @@ HRESULT Extractor::NeedToCopyFile(std::wstring sourceFullPath, std::wstring targ
bool sourceFileIsUnversioned = false;
RETURN_IF_FAILED(GetFileVersion(sourceFullPath, sourceFileVersion, sourceFileIsUnversioned));
std::wstring targetVersionString = ConvertVersionToString(targetFileVersion);
std::wstring sourceVersionString = ConvertVersionToString(sourceFileVersion);
std::wstring targetVersionString = Win7MsixInstallerLib_ConvertVersionToString(targetFileVersion);
std::wstring sourceVersionString = Win7MsixInstallerLib_ConvertVersionToString(sourceFileVersion);
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Target Exists, file versioning information",
@ -480,7 +499,7 @@ HRESULT Extractor::RemoveVfsFile(std::wstring fileName)
TraceLoggingValue(GetLastError(), "error"));
}
GetPathParent(fullPath);
Win7MsixInstallerLib_GetPathParent(fullPath);
// instead of checking if the directory is empty, just try to delete it.
// if it's not empty it'll fail with expected error code that we can ignore
@ -504,14 +523,14 @@ HRESULT Extractor::ConvertVfsNameToFullPath(std::wstring fileName, std::wstring&
{
//The following code gets remainingFilePath from "VFS\FirstDir\...\file.ext" to "\...\file.ext"
std::wstring remainingFilePath = fileName;
GetPathChild(remainingFilePath); // remove the VFS directory
Win7MsixInstallerLib_GetPathChild(remainingFilePath); // remove the VFS directory
std::map<std::wstring, std::wstring> map = m_msixRequest->GetFilePathMappings()->GetMap();
std::map<std::wstring, std::wstring> map = FilePathMappings::GetInstance().GetMap();
for (auto& pair : map)
{
if (remainingFilePath.find(pair.first) != std::wstring::npos)
{
GetPathChild(remainingFilePath); // remove the FirstDir directory.
Win7MsixInstallerLib_GetPathChild(remainingFilePath); // remove the FirstDir directory.
// Pre-pend the VFS target directory to obtain the full path for the target location
fileFullPath = pair.second + std::wstring(L"\\") + remainingFilePath;
@ -535,7 +554,7 @@ HRESULT Extractor::CopyVfsFileToLocal(std::wstring fileName)
"CopyVfsFileToLocal",
TraceLoggingValue(fileName.c_str(), "FileName"));
std::wstring sourceFullPath = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath().c_str() + std::wstring(L"\\") + fileName;
std::wstring sourceFullPath = m_msixRequest->GetPackageDirectoryPath() + std::wstring(L"\\") + fileName;
std::wstring targetFullPath;
if (FAILED(ConvertVfsNameToFullPath(fileName, targetFullPath)))
@ -550,7 +569,7 @@ HRESULT Extractor::CopyVfsFileToLocal(std::wstring fileName)
HRESULT Extractor::ExtractRegistry(bool remove)
{
std::wstring registryFilePath = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath().c_str() + registryDatFile;
std::wstring registryFilePath = m_msixRequest->GetPackageDirectoryPath() + registryDatFile;
AutoPtr<RegistryDevirtualizer> registryDevirtualizer;
RETURN_IF_FAILED(RegistryDevirtualizer::Create(registryFilePath, m_msixRequest, &registryDevirtualizer));

Просмотреть файл

@ -2,7 +2,10 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Extractor extracts the files and registry settings from the package to the file system and registry.
class Extractor : IPackageHandler
{
@ -101,3 +104,4 @@ private:
/// Removes all VFS files in the package
HRESULT RemoveVfsFiles();
};
}

Просмотреть файл

@ -3,7 +3,9 @@
#include <shlobj_core.h>
#include <KnownFolders.h>
void GetPathChild(std::wstring &path)
using namespace Win7MsixInstallerLib;
void Win7MsixInstallerLib_GetPathChild(std::wstring &path)
{
while (path.front() != '\\')
{
@ -12,7 +14,7 @@ void GetPathChild(std::wstring &path)
path.erase(0, 1);
}
void GetPathParent(std::wstring &path)
void Win7MsixInstallerLib_GetPathParent(std::wstring &path)
{
while (!path.empty() && path.back() != '\\')
{
@ -32,6 +34,12 @@ void GetPathParent(std::wstring &path)
}
}
FilePathMappings& FilePathMappings::GetInstance()
{
static FilePathMappings s_selfInstance;
return s_selfInstance;
}
std::wstring FilePathMappings::GetExecutablePath(std::wstring packageExecutablePath, PCWSTR packageFullName)
{
// make a local copy so we can modify in place
@ -40,7 +48,7 @@ std::wstring FilePathMappings::GetExecutablePath(std::wstring packageExecutableP
//Checks if the executable is inside the VFS
if (executionPathWSTR.find(L"VFS") != std::wstring::npos)
{
GetPathChild(executionPathWSTR);
Win7MsixInstallerLib_GetPathChild(executionPathWSTR);
//Checks if the executable is in one of the known folders
for (auto pair : m_map)
{
@ -49,7 +57,7 @@ std::wstring FilePathMappings::GetExecutablePath(std::wstring packageExecutableP
//The executable exists in an unpacked directory
std::wstring executablePath = pair.second;
GetPathChild(executionPathWSTR);
Win7MsixInstallerLib_GetPathChild(executionPathWSTR);
executablePath.push_back(L'\\');
executablePath.append(executionPathWSTR);
return executablePath;
@ -65,7 +73,7 @@ std::wstring FilePathMappings::GetExecutablePath(std::wstring packageExecutableP
return executablePath;
}
HRESULT FilePathMappings::Initialize()
HRESULT FilePathMappings::InitializePaths()
{
TextOle<WCHAR> systemX86Path;
TextOle<WCHAR> systemPath;
@ -101,7 +109,7 @@ HRESULT FilePathMappings::Initialize()
appVSystem32SpoolPath.append(L"\\spool");
std::wstring systemDrive = std::wstring(windowsPath.Get());
GetPathParent(systemDrive);
Win7MsixInstallerLib_GetPathParent(systemDrive);
m_map[L"AppVPackageDrive"] = systemDrive;
m_map[L"SystemX86"] = std::wstring(systemX86Path.Get());
m_map[L"System"] = std::wstring(systemPath.Get());

Просмотреть файл

@ -2,13 +2,14 @@
#include <map>
#include <string>
#include "GeneralUtil.hpp"
namespace Win7MsixInstallerLib
{
/// FilePath Mappings maps the VFS tokens to the actual folder on disk.
/// For instance, VFS token: Windows, actual folder: C:\windows
class FilePathMappings
{
public:
HRESULT Initialize();
static FilePathMappings& GetInstance();
std::map < std::wstring, std::wstring > GetMap() { return m_map; }
@ -22,16 +23,25 @@ public:
/// @param packageFullName - The packageFullName
/// @return the resolved full path to the executable
std::wstring GetExecutablePath(std::wstring packageExecutablePath, PCWSTR packageFullName);
private:
HRESULT GetInitializationResult() { return m_initializationResult; }
private:
// Disallow creating an instance of this object
HRESULT InitializePaths();
FilePathMappings()
{
m_initializationResult = InitializePaths();
}
private:
std::map < std::wstring, std::wstring > m_map;
std::wstring m_msix7Directory;
bool m_isInitialized = false;
HRESULT m_initializationResult = E_NOT_SET;
};
}
/// Removes the first directory from a path.
/// @param path - A path that contains at least one parent directory
void GetPathChild(std::wstring &path);
void Win7MsixInstallerLib_GetPathChild(std::wstring &path);
/// Removes the innermost child file from a path
/// @param path - A file path
void GetPathParent(std::wstring &path);
void Win7MsixInstallerLib_GetPathParent(std::wstring &path);

Просмотреть файл

@ -8,6 +8,7 @@
#include "GeneralUtil.hpp"
#include "Constants.hpp"
#include <TraceLoggingProvider.h>
using namespace Win7MsixInstallerLib;
const PCWSTR FileTypeAssociation::HandlerName = L"FileTypeAssociation";
@ -65,7 +66,7 @@ HRESULT FileTypeAssociation::ParseFtaElement(IMsixElement* ftaElement)
Text<wchar_t> logoPath;
RETURN_IF_FAILED(logoElement->GetText(&logoPath));
fta.logo = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath() + std::wstring(L"\\") + logoPath.Get();
fta.logo = m_msixRequest->GetPackageDirectoryPath() + std::wstring(L"\\") + logoPath.Get();
}
ComPtr<IMsixElementEnumerator> verbsEnum;
@ -210,7 +211,8 @@ HRESULT FileTypeAssociation::ProcessFtaForAdd(Fta& fta)
RegistryKey commandKey;
RETURN_IF_FAILED(openKey.CreateSubKey(commandKeyName.c_str(), KEY_WRITE, &commandKey));
std::wstring command = m_msixRequest->GetPackageInfo()->GetExecutableFilePath() + commandArgument;
std::wstring executablePath = m_msixRequest->GetPackageDirectoryPath() + L"\\" + m_msixRequest->GetPackageInfo()->GetRelativeExecutableFilePath();
std::wstring command = executablePath + commandArgument;
RETURN_IF_FAILED(commandKey.SetStringValue(L"", command));
for (auto verb = fta.verbs.begin(); verb != fta.verbs.end(); ++verb)
@ -221,7 +223,7 @@ HRESULT FileTypeAssociation::ProcessFtaForAdd(Fta& fta)
RegistryKey verbCommandKey;
RETURN_IF_FAILED(verbKey.CreateSubKey(commandKeyName.c_str(), KEY_WRITE, &verbCommandKey));
std::wstring verbCommand = m_msixRequest->GetPackageInfo()->GetExecutableFilePath();
std::wstring verbCommand = executablePath;
if (verb->parameter.c_str() != nullptr)
{
verbCommand += std::wstring(L" ") + verb->parameter.c_str();
@ -303,7 +305,7 @@ HRESULT FileTypeAssociation::CreateHandler(MsixRequest * msixRequest, IPackageHa
RETURN_IF_FAILED(localInstance->m_classesKey.Open(HKEY_CLASSES_ROOT, nullptr, KEY_READ | KEY_WRITE | WRITE_DAC));
std::wstring registryFilePath = msixRequest->GetPackageInfo()->GetPackageDirectoryPath().c_str() + registryDatFile;
std::wstring registryFilePath = msixRequest->GetPackageDirectoryPath() + registryDatFile;
RETURN_IF_FAILED(RegistryDevirtualizer::Create(registryFilePath, msixRequest, &localInstance->m_registryDevirtualizer));
RETURN_IF_FAILED(localInstance->ParseManifest());

Просмотреть файл

@ -4,7 +4,10 @@
#include "IPackageHandler.hpp"
#include "RegistryKey.hpp"
#include "RegistryDevirtualizer.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Data structs to be filled in from the information in the manifest
struct Verb
{
@ -59,3 +62,4 @@ private:
/// Creates a ProgID from the name of the fta. Simply take the package name and prepend it to the fta
std::wstring CreateProgID(PCWSTR name);
};
}

Просмотреть файл

@ -1,24 +1,26 @@
#ifndef FOOTPRINTFILES_H
#define FOOTPRINTFILES_H
#include "AppxPackaging.hpp"
// Describes the FootprintFilesType structure
template<typename Type>
struct FootprintFilesType
{
Type fileType;
const char* description;
bool isRequired;
};
// Types of footprint files in an app package
__declspec(selectany) FootprintFilesType<APPX_FOOTPRINT_FILE_TYPE> g_footprintFilesType[] =
{
{ APPX_FOOTPRINT_FILE_TYPE_MANIFEST, "manifest", true },
{ APPX_FOOTPRINT_FILE_TYPE_BLOCKMAP, "block map", true },
{ APPX_FOOTPRINT_FILE_TYPE_SIGNATURE, "digital signature", true },
{ APPX_FOOTPRINT_FILE_TYPE_CODEINTEGRITY, "CI catalog", false }, // this is ONLY required if there exists 1+ PEs
};
const int FootprintFilesCount = ARRAYSIZE(g_footprintFilesType);
#endif
#ifndef FOOTPRINTFILES_H
#define FOOTPRINTFILES_H
#include "AppxPackaging.hpp"
namespace Win7MsixInstallerLib
{
// Describes the FootprintFilesType structure
template<typename Type>
struct FootprintFilesType
{
Type fileType;
const char* description;
bool isRequired;
};
// Types of footprint files in an app package
__declspec(selectany) FootprintFilesType<APPX_FOOTPRINT_FILE_TYPE> g_footprintFilesType[] =
{
{ APPX_FOOTPRINT_FILE_TYPE_MANIFEST, "manifest", true },
{ APPX_FOOTPRINT_FILE_TYPE_BLOCKMAP, "block map", true },
{ APPX_FOOTPRINT_FILE_TYPE_SIGNATURE, "digital signature", true },
{ APPX_FOOTPRINT_FILE_TYPE_CODEINTEGRITY, "CI catalog", false }, // this is ONLY required if there exists 1+ PEs
};
const int FootprintFilesCount = ARRAYSIZE(g_footprintFilesType);
#endif
}

Просмотреть файл

@ -1,6 +1,9 @@
#pragma once
#include "Package.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Interface for a logical chunk of work done on an Msix request
class IPackageHandler
{
@ -9,12 +12,14 @@ public:
virtual HRESULT ExecuteForAddRequest() = 0;
virtual HRESULT ExecuteForRemoveRequest() { return S_OK; }
virtual bool IsMandatoryForRemoveRequest() { return false; }
virtual bool IsMandatoryForAddRequest() { return true; }
virtual ~IPackageHandler() {};
};
/// Function responsible for creating an instance of an IPackageHandler object
/// @param msixRequest - the msix request object to act upon
/// Function responsible for creating an instance of an IPackageHandler object /// Function responsible for creating an instance of an IPackageHandler object
/// @param msixRequest - the msix request object to act upon /// @return S_OK of the package.
/// @return S_OK if CreateHandler is to not fail the deployment of the package.
typedef HRESULT(*CreateHandler)(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
}

Просмотреть файл

@ -8,16 +8,16 @@
#include "GeneralUtil.hpp"
#include <TraceLoggingProvider.h>
#include "InstallUI.hpp"
using namespace Win7MsixInstallerLib;
const PCWSTR InstallComplete::HandlerName = L"InstallComplete";
HRESULT InstallComplete::ExecuteForAddRequest()
{
if (!m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
auto msixResponse = m_msixRequest->GetMsixResponse();
if (msixResponse != nullptr && !msixResponse->GetIsInstallCancelled())
{
AutoPtr<UI> ui = m_msixRequest->GetUI();
ui->SendInstallCompleteMsg();
msixResponse->Update(InstallationStep::InstallationStepCompleted, 100);
}
return S_OK;
}

Просмотреть файл

@ -2,7 +2,10 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
class InstallComplete : IPackageHandler
{
public:
@ -17,4 +20,5 @@ private:
InstallComplete() {}
InstallComplete(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
};
};
}

Просмотреть файл

@ -11,48 +11,22 @@
#include "resource.h"
#include <filesystem>
#include "Util.hpp"
#include "Win7MSIXInstallerLogger.hpp"
// MSIXWindows.hpp define NOMINMAX because we want to use std::min/std::max from <algorithm>
// GdiPlus.h requires a definiton for min and max. Use std namespace *BEFORE* including it.
using namespace std;
using namespace Win7MsixInstallerLib;
#include <GdiPlus.h>
static const int g_width = 500; // width of window
static const int g_heigth = 400; // height of window
const PCWSTR CreateAndShowUI::HandlerName = L"UI";
//
// Gets the stream of a file.
// PURPOSE: This compiles the information displayed on the UI when the user selects an msix
//
// Parameters:
// package - The package reader for the app package.
// name - Name of the file.
// stream - The stream for the file.
//
HRESULT GetStreamFromFile(IAppxPackageReader* package, LPCWCHAR name, IStream** stream)
{
*stream = nullptr;
ComPtr<IAppxFilesEnumerator> files;
RETURN_IF_FAILED(package->GetPayloadFiles(&files));
BOOL hasCurrent = FALSE;
RETURN_IF_FAILED(files->GetHasCurrent(&hasCurrent));
while (hasCurrent)
{
ComPtr<IAppxFile> file;
RETURN_IF_FAILED(files->GetCurrent(&file));
Text<WCHAR> fileName;
file->GetName(&fileName);
if (wcscmp(fileName.Get(), name) == 0)
{
RETURN_IF_FAILED(file->GetStream(stream));
return S_OK;
}
RETURN_IF_FAILED(files->MoveNext(&hasCurrent));
}
return S_OK;
}
// hWnd: the HWND of the window to draw controls
// windowRect: the size of the window
HRESULT UI::DrawPackageInfo(HWND hWnd, RECT windowRect)
{
@ -60,7 +34,7 @@ HRESULT UI::DrawPackageInfo(HWND hWnd, RECT windowRect)
{
auto displayText = m_installOrUpdateText + L" " + m_displayName + L"?";
auto messageText = L"Publisher: " + m_publisherCommonName + L"\nVersion: " + m_version;
ChangeText(hWnd, displayText, messageText, m_logoStream.Get());
ChangeText(hWnd, displayText, messageText, m_logoStream.get());
ChangeText(hWnd, GetStringResource(IDS_STRING_UI_INSTALL_COMPLETE), GetStringResource(IDS_STRING_UI_COMPLETION_MESSAGE));
}
else
@ -100,96 +74,78 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
}
case WM_COMMAND:
switch (LOWORD(wParam))
switch (LOWORD(wParam))
{
case IDC_INSTALLBUTTON:
case IDC_INSTALLBUTTON:
{
g_installing = true;
DestroyWindow(g_LaunchbuttonHWnd);
DestroyWindow(g_buttonHWnd);
ui->CreateCancelButton(hWnd, windowRect);
UpdateWindow(hWnd);
ui->CreateProgressBar(hWnd, windowRect);
ShowWindow(g_progressHWnd, SW_SHOW); //Show progress bar only when install is clicked
ui->ButtonClicked();
}
break;
case IDC_LAUNCHCHECKBOX:
{
if (SendMessage(GetDlgItem(hWnd, IDC_LAUNCHCHECKBOX), BM_GETCHECK, 0, 0) == BST_CHECKED)
{
g_installing = true;
DestroyWindow(g_LaunchbuttonHWnd);
DestroyWindow(g_buttonHWnd);
ui->CreateCancelButton(hWnd, windowRect);
UpdateWindow(hWnd);
if (ui != NULL)
{
ui->CreateProgressBar(hWnd, windowRect, ui->GetNumberOfFiles());
}
ShowWindow(g_progressHWnd, SW_SHOW); //Show progress bar only when install is clicked
if (ui != NULL)
{
ui->SetButtonClicked();
}
g_launchCheckBoxState = true;
}
else
{
g_launchCheckBoxState = false;
}
}
break;
case IDC_CANCELBUTTON:
{
ui->ConfirmAppCancel(hWnd);
break;
case IDC_LAUNCHCHECKBOX:
{
if (SendMessage(GetDlgItem(hWnd, IDC_LAUNCHCHECKBOX), BM_GETCHECK, 0, 0) == BST_CHECKED)
{
g_launchCheckBoxState = true;
}
else
{
g_launchCheckBoxState = false;
}
}
}
case IDC_LAUNCHBUTTON:
{
ui->LaunchInstalledApp();
break;
case IDC_CANCELBUTTON:
{
ui->ConfirmAppCancel(hWnd);
break;
}
case IDC_LAUNCHBUTTON:
{
ui->LaunchInstalledApp();
break;
}
}
}
break;
case WM_INSTALLCOMPLETE_MSG:
{
g_installing = false; // installation complete, clicking on 'x' should not show the cancellation popup
DestroyWindow(g_CancelbuttonHWnd);
ui->CreateLaunchButton(hWnd, windowRect, 150, 60);
ShowWindow(g_LaunchbuttonHWnd, SW_SHOW);
UpdateWindow(hWnd);
ShowWindow(g_progressHWnd, SW_HIDE); //hide progress bar
ShowWindow(g_checkboxHWnd, SW_HIDE); //hide launch check box
if (g_launchCheckBoxState)
{
ui->LaunchInstalledApp(); // launch app
DestroyWindow(hWnd); // close msix app installer
ui->CloseUI();
}
else
{
//wait for user to click launch button or close the window
while (true)
{
switch (MsgWaitForMultipleObjects(0, NULL, FALSE, INFINITE, QS_ALLINPUT))
{
case WAIT_OBJECT_0:
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
break;
}
}
RECT windowRect;
GetClientRect(hWnd, &windowRect);
DestroyWindow(g_CancelbuttonHWnd);
ui->CreateLaunchButton(hWnd, windowRect, 150, 60);
UpdateWindow(hWnd);
ShowWindow(g_progressHWnd, SW_HIDE); //hide progress bar
ShowWindow(g_checkboxHWnd, SW_HIDE); //hide launch check box
ShowWindow(g_LaunchbuttonHWnd, SW_SHOW);
}
break;
}
case WM_CTLCOLORSTATIC:
{
break;
case WM_CTLCOLORSTATIC:
{
switch (::GetDlgCtrlID((HWND)lParam))
{
case IDC_LAUNCHCHECKBOX:
{
HBRUSH hbr = (HBRUSH)DefWindowProc(hWnd, message, wParam, lParam);
::DeleteObject(hbr);
SetBkMode((HDC)wParam, TRANSPARENT);
return (LRESULT)::GetStockObject(NULL_BRUSH);
}
{
case IDC_LAUNCHCHECKBOX:
{
HBRUSH hbr = (HBRUSH)DefWindowProc(hWnd, message, wParam, lParam);
::DeleteObject(hbr);
SetBkMode((HDC)wParam, TRANSPARENT);
return (LRESULT)::GetStockObject(NULL_BRUSH);
}
}
break;
}
case WM_CLOSE:
@ -224,7 +180,7 @@ void UI::ConfirmAppCancel(HWND hWnd)
switch (cancelResult)
{
case IDYES:
m_msixRequest->GetMsixResponse()->CancelRequest();
m_msixResponse->CancelRequest();
break;
case IDNO:
break;
@ -233,10 +189,9 @@ void UI::ConfirmAppCancel(HWND hWnd)
HRESULT UI::LaunchInstalledApp()
{
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
std::wstring resolvedExecutableFullPath = packageInfo->GetExecutableFilePath();
auto installedPackage = m_packageManager->FindPackage(m_packageInfo->GetPackageFullName());
//check for error while launching app here
ShellExecute(NULL, NULL, resolvedExecutableFullPath.c_str(), NULL, NULL, SW_SHOW);
ShellExecute(NULL, NULL, installedPackage->GetFullExecutableFilePath().c_str(), NULL, NULL, SW_SHOW);
return S_OK;
}
@ -305,129 +260,79 @@ void StartUIThread(UI* ui)
}
void UI::LoadInfo()
HRESULT UI::ParseInfoFromPackage()
{
m_loadingPackageInfoCode = ParseInfoFromPackage();
}
HRESULT UI::ParseInfoFromPackage()
{
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
ComPtr<IMsixDocumentElement> domElement;
RETURN_IF_FAILED(packageInfo->GetManifestReader()->QueryInterface(UuidOfImpl<IMsixDocumentElement>::iid, reinterpret_cast<void**>(&domElement)));
ComPtr<IMsixElement> element;
RETURN_IF_FAILED(domElement->GetDocumentElement(&element));
// Obtain the Display Name and Logo
ComPtr<IMsixElementEnumerator> veElementEnum;
RETURN_IF_FAILED(element->GetElements(
L"/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']",
&veElementEnum));
if (m_packageInfo == nullptr)
{
switch (m_type)
{
case InstallUIAdd:
{
m_packageInfo = m_packageManager->GetMsixPackageInfo(m_path);
if (m_packageInfo == nullptr)
{
return E_FAIL;
}
}
break;
case InstallUIRemove:
{
m_packageInfo = m_packageManager->FindPackage(m_path);
if (m_packageInfo == nullptr)
{
return E_FAIL;
}
}
break;
}
}
// Obtain publisher name
auto wpublisher = std::wstring(packageInfo->GetPublisher());
m_publisherCommonName = wpublisher.substr(wpublisher.find_first_of(L"=") + 1,
wpublisher.find_first_of(L",") - wpublisher.find_first_of(L"=") - 1);
m_publisherCommonName = m_packageInfo->GetPublisherDisplayName();
// Obtain version number
m_version = ConvertVersionToString(packageInfo->GetVersion());
m_version = m_packageInfo->GetVersion();
//Obtain the number of files
m_numberOfFiles = packageInfo->GetNumberOfPayloadFiles();
// Obtain logo
BOOL hc = FALSE;
RETURN_IF_FAILED(veElementEnum->GetHasCurrent(&hc));
if (hc)
{
ComPtr<IMsixElement> visualElementsElement;
Text<WCHAR> displayNameValue;
RETURN_IF_FAILED(veElementEnum->GetCurrent(&visualElementsElement));
RETURN_IF_FAILED(visualElementsElement->GetAttributeValue(L"DisplayName", &displayNameValue));
m_displayName = std::wstring(displayNameValue.Get());
Text<WCHAR> logo;
RETURN_IF_FAILED(visualElementsElement->GetAttributeValue(L"Square150x150Logo", &logo));
RETURN_IF_FAILED(GetStreamFromFile(packageInfo->GetPackageReader(), logo.Get(), &m_logoStream));
}
m_displayName = m_packageInfo->GetDisplayName();
m_logoStream = std::move(m_packageInfo->GetLogo());
return S_OK;
}
HRESULT UI::ShowUI()
{
m_loadingPackageInfoCode = ParseInfoFromPackage();
std::thread thread(StartUIThread, this);
thread.detach();
DWORD waitResult = WaitForSingleObject(m_buttonClickedEvent, INFINITE);
return S_OK;
}
HRESULT CreateAndShowUI::ExecuteForAddRequest()
{
if (m_msixRequest->IsQuietUX())
{
return S_OK;
}
AutoPtr<UI> ui;
RETURN_IF_FAILED(UI::Make(m_msixRequest, &ui));
ui->LoadInfo();
m_msixRequest->SetUI(ui.Detach());
RETURN_IF_FAILED(m_msixRequest->GetUI()->ShowUI());
return S_OK;
}
HRESULT CreateAndShowUI::CreateHandler(MsixRequest * msixRequest, IPackageHandler ** instance)
{
std::unique_ptr<CreateAndShowUI> localInstance(new CreateAndShowUI(msixRequest));
if (localInstance == nullptr)
{
return E_OUTOFMEMORY;
}
*instance = localInstance.release();
DWORD waitResult = WaitForSingleObject(m_closeUI, INFINITE);
return S_OK;
}
void UI::PreprocessRequest()
{
std::wstring currentPackageFamilyName = GetFamilyNameFromFullName(m_msixRequest->GetPackageInfo()->GetPackageFullName());
for (auto& p : std::experimental::filesystem::directory_iterator(m_msixRequest->GetFilePathMappings()->GetMsix7Directory()))
auto existingPackage = m_packageManager->FindPackageByFamilyName(m_packageInfo->GetPackageFamilyName());
if (existingPackage != nullptr)
{
std::wstring installedPackageFamilyName = GetFamilyNameFromFullName(p.path().filename());
if (CaseInsensitiveEquals(m_msixRequest->GetPackageInfo()->GetPackageFullName(), p.path().filename()))
if (CaseInsensitiveEquals(existingPackage->GetPackageFullName(), m_packageInfo->GetPackageFullName()))
{
/// Same package is already installed
ChangeInstallButtonText(GetStringResource(IDS_STRING_REINSTALLAPP)); /// change install button text to 'reinstall'
ShowWindow(g_LaunchbuttonHWnd, SW_SHOW); /// show launch button window
}
else if (CaseInsensitiveEquals(currentPackageFamilyName, installedPackageFamilyName))
else
{
/// Package with same family name exists and may be an update
m_installOrUpdateText = GetStringResource(IDS_STRING_UPDATETEXT);
m_cancelPopUpMessage = GetStringResource(IDS_STRING_CANCEL_UPDATEPOPUP);
ChangeInstallButtonText(GetStringResource(IDS_STRING_UPDATETEXT));
ChangeInstallButtonText(GetStringResource(IDS_STRING_UPDATETEXT));
}
}
}
HRESULT UI::Make(MsixRequest * msixRequest, UI ** instance)
{
std::unique_ptr<UI> localInstance(new UI(msixRequest));
if (localInstance == nullptr)
{
return E_OUTOFMEMORY;
}
*instance = localInstance.release();
return S_OK;
}
BOOL UI::CreateProgressBar(HWND parentHWnd, RECT parentRect, int count)
BOOL UI::CreateProgressBar(HWND parentHWnd, RECT parentRect)
{
int scrollHeight = GetSystemMetrics(SM_CYVSCROLL);
@ -448,8 +353,7 @@ BOOL UI::CreateProgressBar(HWND parentHWnd, RECT parentRect, int count)
);
// Set defaults for range and increments
SendMessage(g_progressHWnd, PBM_SETRANGE, 0, MAKELPARAM(0, count)); // set range
SendMessage(g_progressHWnd, PBM_SETSTEP, (WPARAM)1, 0); // set increment
SendMessage(g_progressHWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); // set range
return TRUE;
}
@ -492,26 +396,26 @@ BOOL UI::InstallButton(HWND parentHWnd, RECT parentRect) {
return TRUE;
}
BOOL UI::CreateCancelButton(HWND parentHWnd, RECT parentRect)
BOOL UI::CreateCancelButton(HWND parentHWnd, RECT parentRect)
{
LPVOID buttonPointer = nullptr;
g_CancelbuttonHWnd = CreateWindowEx(
WS_EX_LEFT, // extended window style
L"BUTTON",
L"Cancel", // text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | BS_FLAT, // style
parentRect.right - 100 - 50, // x coord
parentRect.bottom - 60, // y coord
120, // width
35, // height
parentHWnd, // parent
(HMENU)IDC_CANCELBUTTON, // menu
reinterpret_cast<HINSTANCE>(GetWindowLongPtr(parentHWnd, GWLP_HINSTANCE)),
buttonPointer); // pointer to button
return TRUE;
LPVOID buttonPointer = nullptr;
g_CancelbuttonHWnd = CreateWindowEx(
WS_EX_LEFT, // extended window style
L"BUTTON",
L"Cancel", // text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | BS_FLAT, // style
parentRect.right - 100 - 50, // x coord
parentRect.bottom - 60, // y coord
120, // width
35, // height
parentHWnd, // parent
(HMENU)IDC_CANCELBUTTON, // menu
reinterpret_cast<HINSTANCE>(GetWindowLongPtr(parentHWnd, GWLP_HINSTANCE)),
buttonPointer); // pointer to button
return TRUE;
}
BOOL UI::CreateLaunchButton(HWND parentHWnd, RECT parentRect, int xDiff, int yDiff)
BOOL UI::CreateLaunchButton(HWND parentHWnd, RECT parentRect, int xDiff, int yDiff)
{
LPVOID buttonPointer = nullptr;
g_LaunchbuttonHWnd = CreateWindowEx(
@ -548,9 +452,9 @@ BOOL UI::ChangeText(HWND parentHWnd, std::wstring displayName, std::wstring mess
Gdiplus::Font messageFont(L"Arial", 10);
Gdiplus::StringFormat format;
format.SetAlignment(Gdiplus::StringAlignmentNear);
auto windowsTextColor = Gdiplus::Color();
windowsTextColor.SetFromCOLORREF(GetSysColor(COLOR_WINDOWTEXT));
Gdiplus::SolidBrush textBrush(windowsTextColor);
auto windowsTextColor = Gdiplus::Color();
windowsTextColor.SetFromCOLORREF(GetSysColor(COLOR_WINDOWTEXT));
Gdiplus::SolidBrush textBrush(windowsTextColor);
graphics.DrawString(displayName.c_str(), -1, &displayNameFont, layoutRect, &format, &textBrush);
layoutRect.Y += 40;
@ -610,12 +514,45 @@ int UI::CreateInitWindow(HINSTANCE hInstance, int nCmdShow, const std::wstring&
return static_cast<int>(msg.wParam);
}
void UI::UpdateProgressBar()
void UI::ButtonClicked()
{
SendMessage(g_progressHWnd, PBM_STEPIT, 0, 0);
switch (m_type)
{
case InstallUIAdd:
{
m_msixResponse = m_packageManager->AddPackageAsync(m_path, DeploymentOptions::None, [this](const IMsixResponse & sender) {
SendMessage(g_progressHWnd, PBM_SETPOS, (WPARAM)sender.GetPercentage(), 0);
switch (sender.GetStatus())
{
case InstallationStep::InstallationStepCompleted:
{
SendInstallCompleteMsg();
}
break;
case InstallationStep::InstallationStepError:
{
//auto error = sender->GetTextStatus();
CloseUI();
}
break;
}
});
}
break;
}
}
void UI::SendInstallCompleteMsg()
{
SendMessage(GetHwnd(), WM_INSTALLCOMPLETE_MSG, NULL, NULL);
}
void UI::CloseUI()
{
DestroyWindow(GetHwnd()); // close msix app installer
SetEvent(m_closeUI);
}

Просмотреть файл

@ -1,39 +1,49 @@
#pragma once
/// Install UI Header
/// UI Functions
#include <windows.h>
#include <string>
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "resource.h"
/// Child window identifiers
#define IDC_LAUNCHCHECKBOX 101
#define IDC_INSTALLBUTTON 102
#define IDC_CANCELBUTTON 103
#define IDC_LAUNCHBUTTON 104
#define WM_INSTALLCOMPLETE_MSG (WM_APP+1)
/// Global variables
static HWND g_buttonHWnd = NULL;
static HWND g_checkboxHWnd = NULL;
static HWND g_progressHWnd = NULL;
static HWND g_CancelbuttonHWnd = NULL;
static HWND g_LaunchbuttonHWnd = NULL;
static bool g_launchCheckBoxState = true; /// launch checkbox is checked by default
static bool g_installing = false; /// variable used to indicate that app installation is in progress
#pragma once
/// Install UI Header
/// UI Functions
#include <windows.h>
#include <string>
#include "Util.hpp"
#include <IPackageManager.hpp>
#include <IMsixResponse.hpp>
#include "resource.h"
/// Child window identifiers
#define IDC_LAUNCHCHECKBOX 101
#define IDC_INSTALLBUTTON 102
#define IDC_CANCELBUTTON 103
#define IDC_LAUNCHBUTTON 104
#define WM_INSTALLCOMPLETE_MSG (WM_APP+1)
/// Global variables
static HWND g_buttonHWnd = NULL;
static HWND g_checkboxHWnd = NULL;
static HWND g_progressHWnd = NULL;
static HWND g_CancelbuttonHWnd = NULL;
static HWND g_LaunchbuttonHWnd = NULL;
static bool g_launchCheckBoxState = true; /// launch checkbox is checked by default
static bool g_installing = false; /// variable used to indicate that app installation is in progress
enum UIType { InstallUIAdd, InstallUIRemove};
class UI
{
public:
HRESULT ShowUI();
HRESULT LaunchInstalledApp();
void ConfirmAppCancel(HWND parentHWnd);
static HRESULT Make(_In_ MsixRequest* msixRequest, _Out_ UI** instance);
UI(_In_ Win7MsixInstallerLib::IPackageManager* packageManager, _In_ const std::wstring & path, UIType type) : m_packageManager(packageManager), m_type(type)
{
m_path = std::wstring(path);
m_closeUI = CreateEvent(NULL, FALSE, FALSE, NULL);
}
~UI() {}
private:
MsixRequest* m_msixRequest = nullptr;
Win7MsixInstallerLib::IPackageManager* m_packageManager = nullptr;
std::shared_ptr<Win7MsixInstallerLib::IPackage> m_packageInfo = nullptr;
std::wstring m_path;
std::shared_ptr<Win7MsixInstallerLib::IMsixResponse> m_msixResponse;
//Parent Window Hwnd
HWND hWnd = NULL;
@ -48,18 +58,14 @@ private:
std::wstring m_cancelPopUpTitle = GetStringResource(IDS_STRING_CANCEL_POPUP_TITLE);
std::wstring m_displayName = L"";
std::wstring m_publisherCommonName = L"";
ComPtr<IStream> m_logoStream;
std::unique_ptr<IStream> m_logoStream;
std::wstring m_version = L"";
int m_numberOfFiles = 0;
HRESULT m_loadingPackageInfoCode = 0;
HANDLE m_buttonClickedEvent;
UI() {}
UI(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest)
{
m_buttonClickedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
HRESULT m_loadingPackageInfoCode = 0;
UIType m_type;
HANDLE m_closeUI;
HRESULT ParseInfoFromPackage();
/// This function sets the parent window hwnd after create window
@ -91,80 +97,63 @@ public:
/// @param windowClass - the class text of the window
/// @param windowTitle - the window title
int CreateInitWindow(HINSTANCE hInstance, int nCmdShow, const std::wstring& windowClass, const std::wstring& title);
void LoadInfo();
int GetNumberOfFiles() { return m_numberOfFiles; }
void SetButtonClicked() { SetEvent(m_buttonClickedEvent); }
/// Creates the progress bar
///
/// @param parentHWnd - the HWND of the window to add the progress bar to
/// @param parentRect - the dimmensions of the parent window
/// count: the number of objects to be iterated through in the progress bar
BOOL CreateProgressBar(HWND parentHWnd, RECT parentRect, int count);
/// Create the lower right install button
///
/// @param parentHWnd - the HWND of the window to add the button to
/// @param parentRect - the specs of the parent window
BOOL InstallButton(HWND parentHWnd, RECT parentRect);
void ButtonClicked();
/// Creates the progress bar
///
/// @param parentHWnd - the HWND of the window to add the progress bar to
/// @param parentRect - the dimmensions of the parent window
BOOL CreateProgressBar(HWND parentHWnd, RECT parentRect);
/// Create the lower right install button
///
/// @param parentHWnd - the HWND of the window to add the button to
/// @param parentRect - the specs of the parent window
BOOL InstallButton(HWND parentHWnd, RECT parentRect);
/// Create the launch when ready checkbox on the bottom left
///
/// @param parentHWnd - the HWND of the window to add the checkbox to
/// @param parentRect - the specs of the parent window
BOOL CreateCheckbox(HWND parentHWnd, RECT parentRect);
/// @param parentRect - the specs of the parent window
BOOL CreateCheckbox(HWND parentHWnd, RECT parentRect);
/// Create the cancel button on the bottom right corner when user clicks on install
///
/// @param parentHWnd - the HWND of the window to add the checkbox to
/// @param parentRect - the specs of the parent window
BOOL CreateCancelButton(HWND parentHWnd, RECT parentRect);
/// @param parentRect - the specs of the parent window
BOOL CreateCancelButton(HWND parentHWnd, RECT parentRect);
/// Create the launch button on the botton right after app has been installed
///
/// @param parentHWnd - the HWND of the window to add the checkbox to
/// @param parentRect - the specs of the parent window
/// @param xDiff - the x coordinate difference to create the button from the parent window
/// @param yDiff - the y coordinate difference to create the button from the parent window
BOOL CreateLaunchButton(HWND parentHWnd, RECT parentRect, int xDiff, int yDiff);
/// Changes the text of the lower right 'Install' button
/// Changes text to 'Update' in case of an update, changes text to 'Reinstall' in case app is already installed on the machine
///
/// @param newMessage - the message to change the button to
BOOL ChangeInstallButtonText(const std::wstring& newMessage);
/// Change the text of the installation window based on the given input
///
/// @param parentHWnd - the HWND of the window to be changed
/// @param windowText - the text to change the window to
/// @param parentRect - the specs of the parent window
/// @param xDiff - the x coordinate difference to create the button from the parent window
/// @param yDiff - the y coordinate difference to create the button from the parent window
BOOL CreateLaunchButton(HWND parentHWnd, RECT parentRect, int xDiff, int yDiff);
/// Changes the text of the lower right 'Install' button
/// Changes text to 'Update' in case of an update, changes text to 'Reinstall' in case app is already installed on the machine
///
/// @param newMessage - the message to change the button to
BOOL ChangeInstallButtonText(const std::wstring& newMessage);
/// Change the text of the installation window based on the given input
///
/// @param parentHWnd - the HWND of the window to be changed
/// @param windowText - the text to change the window to
BOOL ChangeText(HWND parentHWnd, std::wstring displayText, std::wstring messageText, IStream* logoStream = nullptr);
/// Increment the progress bar one tick based on preset tick
void UpdateProgressBar();
/// Sends the WM_INSTALLCOMPLETE_MSG message to the main window when app installation is complete
/// Sends the WM_INSTALLCOMPLETE_MSG message to the main window when app installation is complete
void SendInstallCompleteMsg();
// The add operation could be an update if V1 version of the package is already installed. Show appropriate UI with respect to operation type
/// The add operation could be an update if V1 version of the package is already installed on the machine
/// This method checks the same and sets the button and install screen UI text to 'Update'
/// The add operation could be an update if V1 version of the package is already installed. Show appropriate UI with respect to operation type
/// The add operation could be an update if V1 version of the package is already installed on the machine
/// This method checks the same and sets the button and install screen UI text to 'Update'
///
void PreprocessRequest();
HRESULT ShowUI();
void CloseUI();
};
class CreateAndShowUI : IPackageHandler
{
public:
HRESULT ExecuteForAddRequest();
static const PCWSTR HandlerName;
static HRESULT CreateHandler(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
~CreateAndShowUI() {}
private:
MsixRequest* m_msixRequest = nullptr;
CreateAndShowUI() {}
CreateAndShowUI(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
};

Просмотреть файл

@ -1,4 +1,4 @@
#include "generalutil.hpp"
#include "GeneralUtil.hpp"
#include "MsixRequest.hpp"
#include <string>
@ -12,7 +12,6 @@
#include "FootprintFiles.hpp"
#include "FilePaths.hpp"
#include "InstallUI.hpp"
#include <cstdio>
#include <experimental/filesystem> // C++-standard header file name
#include <filesystem> // Microsoft-specific implementation header file name
@ -32,11 +31,13 @@
#include "ErrorHandler.hpp"
#include "ValidateTargetDeviceFamily.hpp"
#include "Constants.hpp"
// MSIXWindows.hpp define NOMINMAX because we want to use std::min/std::max from <algorithm>
// GdiPlus.h requires a definiton for min and max. Use std namespace *BEFORE* including it.
using namespace std;
#include <GdiPlus.h>
using namespace Win7MsixInstallerLib;
struct HandlerInfo
{
CreateHandler create;
@ -46,26 +47,24 @@ struct HandlerInfo
std::map<PCWSTR, HandlerInfo> AddHandlers =
{
//HandlerName Function to create NextHandler ErrorHandlerInfo
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, CreateAndShowUI::HandlerName, ErrorHandler::HandlerName}},
{CreateAndShowUI::HandlerName, {CreateAndShowUI::CreateHandler, ValidateTargetDeviceFamily::HandlerName, ErrorHandler::HandlerName}},
{ValidateTargetDeviceFamily::HandlerName, {ValidateTargetDeviceFamily::CreateHandler, ProcessPotentialUpdate::HandlerName, ErrorHandler::HandlerName}},
{ProcessPotentialUpdate::HandlerName, {ProcessPotentialUpdate::CreateHandler, Extractor::HandlerName, ErrorHandler::HandlerName}},
{Extractor::HandlerName, {Extractor::CreateHandler, StartMenuLink::HandlerName, ErrorHandler::HandlerName}},
{StartMenuLink::HandlerName, {StartMenuLink::CreateHandler, AddRemovePrograms::HandlerName, ErrorHandler::HandlerName}},
{AddRemovePrograms::HandlerName, {AddRemovePrograms::CreateHandler, Protocol::HandlerName, ErrorHandler::HandlerName}},
{Protocol::HandlerName, {Protocol::CreateHandler, ComInterface::HandlerName, ErrorHandler::HandlerName}},
{ComInterface::HandlerName, {ComInterface::CreateHandler, ComServer::HandlerName, ErrorHandler::HandlerName}},
{ComServer::HandlerName, {ComServer::CreateHandler, FileTypeAssociation::HandlerName, ErrorHandler::HandlerName}},
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, InstallComplete::HandlerName, ErrorHandler::HandlerName}},
{InstallComplete::HandlerName, {InstallComplete::CreateHandler, nullptr, ErrorHandler::HandlerName}},
{ErrorHandler::HandlerName, {ErrorHandler::CreateHandler, nullptr, nullptr}},
//HandlerName Function to create NextHandler ErrorHandlerInfo
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, ProcessPotentialUpdate::HandlerName, ErrorHandler::HandlerName}},
{ProcessPotentialUpdate::HandlerName, {ProcessPotentialUpdate::CreateHandler, Extractor::HandlerName, ErrorHandler::HandlerName}},
{Extractor::HandlerName, {Extractor::CreateHandler, StartMenuLink::HandlerName, ErrorHandler::HandlerName}},
{StartMenuLink::HandlerName, {StartMenuLink::CreateHandler, AddRemovePrograms::HandlerName, ErrorHandler::HandlerName}},
{AddRemovePrograms::HandlerName, {AddRemovePrograms::CreateHandler, Protocol::HandlerName, ErrorHandler::HandlerName}},
{Protocol::HandlerName, {Protocol::CreateHandler, ComInterface::HandlerName, ErrorHandler::HandlerName}},
{ComInterface::HandlerName, {ComInterface::CreateHandler, ComServer::HandlerName, ErrorHandler::HandlerName}},
{ComServer::HandlerName, {ComServer::CreateHandler, FileTypeAssociation::HandlerName, ErrorHandler::HandlerName}},
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, InstallComplete::HandlerName, ErrorHandler::HandlerName}},
{InstallComplete::HandlerName, {InstallComplete::CreateHandler, nullptr, ErrorHandler::HandlerName}},
{ErrorHandler::HandlerName, {ErrorHandler::CreateHandler, nullptr, nullptr}},
};
std::map<PCWSTR, HandlerInfo> RemoveHandlers =
{
//HandlerName Function to create NextHandler
{CreateAndShowUI::HandlerName, {CreateAndShowUI::CreateHandler, StartMenuLink::HandlerName}},
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, StartMenuLink::HandlerName}},
{StartMenuLink::HandlerName, {StartMenuLink::CreateHandler, AddRemovePrograms::HandlerName}},
{AddRemovePrograms::HandlerName, {AddRemovePrograms::CreateHandler, Protocol::HandlerName}},
{Protocol::HandlerName, {Protocol::CreateHandler, ComInterface::HandlerName}},
@ -75,108 +74,53 @@ std::map<PCWSTR, HandlerInfo> RemoveHandlers =
{Extractor::HandlerName, {Extractor::CreateHandler, nullptr}},
};
HRESULT MsixRequest::Make(OperationType operationType, Flags flags, std::wstring packageFilePath, std::wstring packageFullName, MSIX_VALIDATION_OPTION validationOption, MsixRequest ** outInstance)
HRESULT MsixRequest::Make(OperationType operationType, const std::wstring & packageFilePath, std::wstring packageFullName, MSIX_VALIDATION_OPTION validationOption, MsixRequest ** outInstance)
{
std::unique_ptr<MsixRequest> instance(new MsixRequest());
AutoPtr<MsixRequest> instance(new MsixRequest());
if (instance == nullptr)
{
return E_OUTOFMEMORY;
}
instance->m_operationType = operationType;
instance->m_flags = flags;
instance->m_packageFilePath = packageFilePath;
instance->m_packageFullName = packageFullName;
instance->m_validationOptions = validationOption;
RETURN_IF_FAILED(instance->InitializeFilePathMappings());
RETURN_IF_FAILED(FilePathMappings::GetInstance().GetInitializationResult());
//Set MsixResponse
AutoPtr<MsixResponse> localResponse;
RETURN_IF_FAILED(MsixResponse::Make(&localResponse));
instance->m_msixResponse = localResponse.Detach();
instance->m_msixResponse = std::make_shared<MsixResponse>();
*outInstance = instance.release();
*outInstance = instance.Detach();
return S_OK;
}
HRESULT MsixRequest::InitializeFilePathMappings()
{
return m_filePathMappings.Initialize();
}
HRESULT MsixRequest::ProcessRequest()
{
m_msixResponse->Update(InstallationStep::InstallationStepStarted, 0);
switch (m_operationType)
{
case OperationType::Add:
{
RETURN_IF_FAILED(ProcessAddRequest());
break;
}
case OperationType::Remove:
{
RETURN_IF_FAILED(ProcessRemoveRequest());
break;
}
case OperationType::FindAllPackages:
{
RETURN_IF_FAILED(FindAllPackages());
break;
}
case OperationType::FindPackage:
{
RETURN_IF_FAILED(DisplayPackageInfo());
break;
}
default:
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
return S_OK;
}
HRESULT MsixRequest::DisplayPackageInfo()
{
AutoPtr<IPackageHandler> handler;
RETURN_IF_FAILED(PopulatePackageInfo::CreateHandler(this, &handler));
HRESULT packageFoundResult = handler->ExecuteForRemoveRequest();
if (packageFoundResult == S_OK)
case OperationType::Add:
{
std::wcout << std::endl;
std::wcout << L"PackageFullName: " << m_packageInfo->GetPackageFullName().c_str() << std::endl;
std::wcout << L"DisplayName: " << m_packageInfo->GetDisplayName().c_str() << std::endl;
std::wcout << L"DirectoryPath: " << m_packageInfo->GetPackageDirectoryPath().c_str() << std::endl;
std::wcout << std::endl;
RETURN_IF_FAILED(ProcessAddRequest());
break;
}
else
case OperationType::Remove:
{
std::wcout << std::endl;
std::wcout << L"Package not found " << std::endl;
RETURN_IF_FAILED(ProcessRemoveRequest());
break;
}
default:
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
return S_OK;
}
HRESULT MsixRequest::FindAllPackages()
{
int numPackages = 0;
for (auto& p : std::experimental::filesystem::directory_iterator(m_filePathMappings.GetMsix7Directory()))
{
std::cout << p.path().filename() << std::endl;
numPackages++;
}
std::cout << numPackages << " Package(s) found" << std::endl;
return S_OK;
}
HRESULT MsixRequest::ProcessAddRequest()
{
PCWSTR currentHandlerName = PopulatePackageInfo::HandlerName;
while (currentHandlerName != nullptr)
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
@ -185,10 +129,20 @@ HRESULT MsixRequest::ProcessAddRequest()
HandlerInfo currentHandler = AddHandlers[currentHandlerName];
AutoPtr<IPackageHandler> handler;
RETURN_IF_FAILED(currentHandler.create(this, &handler));
HRESULT hrAddExecute = handler->ExecuteForAddRequest();
if (FAILED(hrAddExecute))
auto hrExecute = currentHandler.create(this, &handler);
if (FAILED(hrExecute))
{
if (handler->IsMandatoryForAddRequest())
{
m_msixResponse->SetErrorStatus(hrExecute, L"Can't create the handler " + std::wstring(currentHandlerName));
return hrExecute;
}
}
hrExecute = handler->ExecuteForAddRequest();
if (FAILED(hrExecute))
{
m_msixResponse->SetErrorStatus(hrExecute, L"Can't execute the handler " + std::wstring(currentHandlerName));
currentHandlerName = currentHandler.errorHandler;
}
else
@ -202,13 +156,7 @@ HRESULT MsixRequest::ProcessAddRequest()
HRESULT MsixRequest::ProcessRemoveRequest()
{
// Run PopulatePackageInfo separately - if it fails (for instance, if the package is not found) it IS fatal.
AutoPtr<IPackageHandler> handler;
RETURN_IF_FAILED(PopulatePackageInfo::CreateHandler(this, &handler));
RETURN_IF_FAILED(handler->ExecuteForRemoveRequest());
PCWSTR currentHandlerName = CreateAndShowUI::HandlerName;
PCWSTR currentHandlerName = PopulatePackageInfo::HandlerName;
while (currentHandlerName != nullptr)
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
@ -217,8 +165,18 @@ HRESULT MsixRequest::ProcessRemoveRequest()
HandlerInfo currentHandler = RemoveHandlers[currentHandlerName];
AutoPtr<IPackageHandler> handler;
RETURN_IF_FAILED(currentHandler.create(this, &handler));
HRESULT hrExecute = handler->ExecuteForRemoveRequest();
HRESULT hrExecute = currentHandler.create(this, &handler);
if (FAILED(hrExecute))
{
if (handler->IsMandatoryForAddRequest())
{
m_msixResponse->SetErrorStatus(hrExecute, L"Can't create the handler " + std::wstring(currentHandlerName));
m_msixResponse->Update(InstallationStep::InstallationStepError, 0);
return hrExecute;
}
}
hrExecute = handler->ExecuteForRemoveRequest();
if (FAILED(hrExecute))
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
@ -226,6 +184,11 @@ HRESULT MsixRequest::ProcessRemoveRequest()
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(currentHandlerName, "HandlerName"),
TraceLoggingValue(hrExecute, "HR"));
if (handler->IsMandatoryForRemoveRequest())
{
m_msixResponse->SetErrorStatus(hrExecute, L"Can't execute the handler " + std::wstring(currentHandlerName));
return hrExecute;
}
}
currentHandlerName = currentHandler.nextHandler;
@ -234,12 +197,16 @@ HRESULT MsixRequest::ProcessRemoveRequest()
return S_OK;
}
void MsixRequest::SetUI(UI * ui)
{
m_UI = ui;
}
void MsixRequest::SetPackageInfo(PackageInfo* packageInfo)
void MsixRequest::SetPackageInfo(std::shared_ptr<PackageBase> packageInfo)
{
m_packageInfo = packageInfo;
}
std::wstring MsixRequest::GetPackageDirectoryPath()
{
if (m_packageInfo == nullptr)
return nullptr;
return FilePathMappings::GetInstance().GetMsix7Directory() + m_packageInfo->GetPackageFullName();
}

Просмотреть файл

@ -1,25 +1,16 @@
#pragma once
#include "PackageInfo.hpp"
#include "Package.hpp"
#include "FilePaths.hpp"
#include "MsixResponse.hpp"
class UI;
namespace Win7MsixInstallerLib
{
enum OperationType
{
Undefined = 0,
Add = 1,
Remove = 2,
FindPackage = 3,
FindAllPackages = 4,
};
enum Flags
{
NoFlags = 0,
QuietUX = 0x1,
};
DEFINE_ENUM_FLAG_OPERATORS(Flags);
/// MsixRequest represents what this instance of the executable will be doing and tracks the state of the current operation
class MsixRequest
{
@ -28,78 +19,56 @@ private:
std::wstring m_packageFilePath;
std::wstring m_packageFullName;
MSIX_VALIDATION_OPTION m_validationOptions = MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL;
Flags m_flags = NoFlags;
OperationType m_operationType = Add;
FilePathMappings m_filePathMappings;
/// Filled by PopulatePackageInfo
AutoPtr<PackageInfo> m_packageInfo;
/// Filled in by CreateAndShowUI
AutoPtr<UI> m_UI;
std::shared_ptr<PackageBase> m_packageInfo;
/// MsixResponse object populated by handlers
AutoPtr<MsixResponse> m_msixResponse;
std::shared_ptr<MsixResponse> m_msixResponse;
protected:
MsixRequest() {}
public:
static HRESULT Make(OperationType operationType, Flags flags, std::wstring packageFilePath, std::wstring packageFullName, MSIX_VALIDATION_OPTION validationOption, MsixRequest** outInstance);
static HRESULT Make(OperationType operationType, const std::wstring & packageFilePath, std::wstring packageFullName, MSIX_VALIDATION_OPTION validationOption, MsixRequest** outInstance);
/// The main function processes the request based on whichever operation type was requested and then
/// going through the sequence of individual handlers.
HRESULT ProcessRequest();
/// Called by PopulatePackageInfo
void SetPackageInfo(PackageInfo* packageInfo);
/// Called by CreateAndShowUI
void SetUI(UI* ui);
// Getters
inline MSIX_VALIDATION_OPTION GetValidationOptions() { return m_validationOptions; }
inline PCWSTR GetPackageFilePath() { return m_packageFilePath.c_str(); }
inline PCWSTR GetPackageFullName() { return m_packageFullName.c_str(); }
inline FilePathMappings* GetFilePathMappings() { return &m_filePathMappings; }
/// @return can return null if called before PopulatePackageInfo.
PackageInfo* GetPackageInfo() { return m_packageInfo; }
/// @return can return null if called before CreateAndShowUI or if Flags::QuietUX was passed in and there is no UI.
UI* GetUI() { return m_UI; }
inline bool IsQuietUX() { return (m_flags & Flags::QuietUX) == Flags::QuietUX; }
inline bool IsRemove()
bool IsRemove()
{
return m_operationType == OperationType::Remove;
}
inline bool AllowSignatureOriginUnknown()
bool AllowSignatureOriginUnknown()
{
m_validationOptions = static_cast<MSIX_VALIDATION_OPTION>(m_validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN);
return true;
}
inline MSIX_VALIDATION_OPTION GetValidationOptions() { return m_validationOptions; }
inline PCWSTR GetPackageFilePath() { return m_packageFilePath.c_str(); }
inline PCWSTR GetPackageFullName() { return m_packageFullName.c_str(); }
/// Retrieves the msixResponse object
///
/// @return m_msixResponse object
MsixResponse* GetMsixResponse() { return m_msixResponse; }
std::shared_ptr<MsixResponse> GetMsixResponse() { return m_msixResponse; }
/// Called by PopulatePackageInfo
void SetPackageInfo(std::shared_ptr<PackageBase> packageInfo);
std::wstring GetPackageDirectoryPath();
/// @return can return null if called before PopulatePackageInfo.
std::shared_ptr<PackageBase> GetPackageInfo() { return m_packageInfo; }
private:
/// FilePath Mappings maps the VFS tokens (e.g. Windows) to the actual folder on disk (e.g. C:\windows)
HRESULT InitializeFilePathMappings();
/// This handles FindAllPackages operation and finds all packages installed by the Win7MSIXInstaller
HRESULT FindAllPackages();
/// This handles Add operation and proceeds through each of the AddSequenceHandlers to install the package
HRESULT ProcessAddRequest();
/// This handles Remove operation and proceeds through each of the RemoveSequenceHandlers to uninstall the package
HRESULT ProcessRemoveRequest();
/// This handles FindPackage operation and displays the package info for a given package.
/// @return E_NOT_SET when the package could not be found
HRESULT DisplayPackageInfo();
};
}

Просмотреть файл

@ -1,18 +1,36 @@
#include "generalutil.hpp"
#include "GeneralUtil.hpp"
#include "MsixResponse.hpp"
using namespace Win7MsixInstallerLib;
HRESULT MsixResponse::Make(MsixResponse ** outInstance)
void MsixResponse::Update(InstallationStep status, float progress)
{
std::unique_ptr<MsixResponse> instance(new MsixResponse());
if (instance == nullptr)
if (m_percentage == progress && m_status == status)
{
return E_OUTOFMEMORY;
return;
}
instance->m_hresultTextCode = NULL;
instance->m_textStatus = NULL;
instance->m_isInstallCancelled = false;
*outInstance = instance.release();
m_percentage = progress;
m_status = status;
if (m_callback)
{
m_callback(*this);
}
}
return S_OK;
}
void MsixResponse::SetCallback(std::function<void(const IMsixResponse& sender)> callback)
{
m_callback = callback;
}
void MsixResponse::SetErrorStatus(HRESULT errorCode, std::wstring errorText)
{
m_percentage = 0;
m_status = InstallationStep::InstallationStepError;
m_hresultTextCode = errorCode;
m_textStatus = errorText;
if (m_callback)
{
m_callback(*this);
}
}

Просмотреть файл

@ -1,11 +1,15 @@
#pragma once
#include <windows.h>
#include <string>
#include "GeneralUtil.hpp"
#include <windows.h>
#include <string>
#include <functional>
#include "IMsixResponse.hpp"
#include "GeneralUtil.hpp"
namespace Win7MsixInstallerLib
{
/// The response class tracks the response state of the msix deploy operation
/// (if the operation was cancelled, progress bar updates)
class MsixResponse
class MsixResponse: public IMsixResponse
{
private:
@ -13,15 +17,21 @@ private:
bool m_isInstallCancelled = false;
/// HResult to be populated by handlers in the msix response
HRESULT m_hresultTextCode;
HRESULT m_hresultTextCode = 0;
/// Detailed text status of the msix response
PCWSTR m_textStatus;
std::wstring m_textStatus;
/// Progress percentage of the msix deployment
float m_percentage;
InstallationStep m_status = InstallationStepUnknown;
/// Callback to indicate how the progress of the installation
std::function<void(const IMsixResponse&)> m_callback;
public:
static HRESULT Make(MsixResponse** outInstance);
/// Method used to return the status of the cancel button
///
/// @return variable indicating the state of cancel button
@ -31,23 +41,16 @@ public:
}
/// Method used to set the status of the cancel button if 'Cancel' is clicked
void CancelRequest()
virtual void CancelRequest()
{
m_isInstallCancelled = true;
}
/// Set Hresult code as passed by handlers in the msix response(not being set currently)
///
/// @param hresult - hresult value passed
inline void SetHResultTextCode(HRESULT hresult)
{
m_hresultTextCode = hresult;
}
/// Get the Hresult value in an msix response
///
/// @return Hresult code as set in the response
inline HRESULT GetHResultTextCode()
virtual inline HRESULT GetHResultTextCode() const
{
return m_hresultTextCode;
}
@ -55,7 +58,7 @@ public:
/// Sets the detailed text status in the msix response object
///
/// @param textStatus - the textStatus to be set
inline void SetTextStatus(PCWSTR textStatus)
inline void SetTextStatus(std::wstring textStatus)
{
m_textStatus = textStatus;
}
@ -63,8 +66,42 @@ public:
/// Returns the detailed text status as set in the msix response object
///
/// @return textStatus in the msix response
inline PCWSTR GetTextStatus()
virtual inline std::wstring GetTextStatus() const
{
return m_textStatus;
}
};
/// Update response and send a callback to the UI
///
/// @param status - current step of the installation
/// @param percentage - installation progresss percentage
void Update(InstallationStep status, float percentage);
/// Update response to indicate an error status
///
/// @param errorCode - code associated to the error
/// @param errorText - description of the error
void SetErrorStatus(HRESULT errorCode, std::wstring errorText);
/// Set a callback for the UI
///
/// @param callback - callback called when status or percentage change
virtual void SetCallback(std::function<void(const IMsixResponse&)> callback);
/// Get the installation progress percentage
///
/// @return the percentage (from 0 to 100)
virtual inline float GetPercentage() const
{
return m_percentage;
}
/// Get the installation status
///
/// @return the installation status
virtual inline InstallationStep GetStatus() const
{
return m_status;
}
};
}

Просмотреть файл

@ -1,11 +1,51 @@
#include <windows.h>
#include "PackageInfo.hpp"
#include "Package.hpp"
#include "GeneralUtil.hpp"
#include "MsixRequest.hpp"
#include <TraceLoggingProvider.h>
#include <fstream>
using namespace Win7MsixInstallerLib;
HRESULT PackageInfo::SetExecutableAndAppIdFromManifestElement(IMsixElement* element, PCWSTR packageFullName, MsixRequest * msixRequest)
//
// Gets the stream of a file.
//
// Parameters:
// package - The package reader for the app package.
// name - Name of the file.
// stream - The stream for the file.
//
HRESULT GetStreamFromFile(IAppxPackageReader* package, LPCWCHAR name, IStream** stream)
{
*stream = nullptr;
ComPtr<IAppxFilesEnumerator> files;
RETURN_IF_FAILED(package->GetPayloadFiles(&files));
BOOL hasCurrent = FALSE;
RETURN_IF_FAILED(files->GetHasCurrent(&hasCurrent));
while (hasCurrent)
{
ComPtr<IAppxFile> file;
RETURN_IF_FAILED(files->GetCurrent(&file));
Text<WCHAR> fileName;
file->GetName(&fileName);
if (wcscmp(fileName.Get(), name) == 0)
{
RETURN_IF_FAILED(file->GetStream(stream));
return S_OK;
}
RETURN_IF_FAILED(files->MoveNext(&hasCurrent));
}
return S_OK;
}
std::wstring PackageBase::GetVersion()
{
return Win7MsixInstallerLib_ConvertVersionToString(m_version);
}
HRESULT PackageBase::ParseManifest(IMsixElement* element)
{
BOOL hc = FALSE;
ComPtr<IMsixElementEnumerator> applicationElementEnum;
@ -26,23 +66,14 @@ HRESULT PackageInfo::SetExecutableAndAppIdFromManifestElement(IMsixElement* elem
RETURN_IF_FAILED(applicationElementEnum->GetCurrent(&applicationElement));
Text<wchar_t> executablePath;
RETURN_IF_FAILED(applicationElement->GetAttributeValue(L"Executable", &executablePath));
m_executableFilePath = msixRequest->GetFilePathMappings()->GetExecutablePath(executablePath.Get(), packageFullName);
Text<wchar_t> applicationId;
RETURN_IF_FAILED(applicationElement->GetAttributeValue(L"Executable", &executablePath));
RETURN_IF_FAILED(applicationElement->GetAttributeValue(L"Id", &applicationId));
m_relativeExecutableFilePath = executablePath.Get();
m_applicationId = applicationId.Get();
return S_OK;
}
HRESULT PackageInfo::SetDisplayNameFromManifestElement(IMsixElement* element)
{
ComPtr<IMsixElementEnumerator> visualElementsEnum;
RETURN_IF_FAILED(element->GetElements(
L"/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']",
&visualElementsEnum));
BOOL hc = FALSE;
RETURN_IF_FAILED(applicationElement->GetElements(L"*[local-name()='VisualElements']", &visualElementsEnum));
RETURN_IF_FAILED(visualElementsEnum->GetHasCurrent(&hc));
if (!hc)
{
@ -59,27 +90,17 @@ HRESULT PackageInfo::SetDisplayNameFromManifestElement(IMsixElement* element)
RETURN_IF_FAILED(visualElementsElement->GetAttributeValue(L"DisplayName", &displayName));
m_displayName = displayName.Get();
Text<WCHAR> logo;
RETURN_IF_FAILED(visualElementsElement->GetAttributeValue(L"Square150x150Logo", &logo));
m_relativeLogoPath = logo.Get();
return S_OK;
}
HRESULT PackageInfo::MakeFromManifestReader(IAppxManifestReader * manifestReader, MsixRequest * msixRequest, PackageInfo ** packageInfo)
{
std::unique_ptr<PackageInfo> instance(new PackageInfo());
if (instance == nullptr)
{
return E_OUTOFMEMORY;
}
RETURN_IF_FAILED(instance->SetManifestReader(manifestReader, msixRequest));
*packageInfo = instance.release();
return S_OK;
}
HRESULT PackageInfo::MakeFromPackageReader(IAppxPackageReader * packageReader, MsixRequest * msixRequest, PackageInfo ** packageInfo)
HRESULT Package::MakeFromPackageReader(IAppxPackageReader * packageReader, std::shared_ptr<Package> * packageInfo)
{
std::unique_ptr<PackageInfo> instance(new PackageInfo());
std::shared_ptr<Package> instance = std::make_shared<Package>();
if (instance == nullptr)
{
return E_OUTOFMEMORY;
@ -89,7 +110,7 @@ HRESULT PackageInfo::MakeFromPackageReader(IAppxPackageReader * packageReader, M
ComPtr<IAppxManifestReader> manifestReader;
RETURN_IF_FAILED(packageReader->GetManifest(&manifestReader));
RETURN_IF_FAILED(instance->SetManifestReader(manifestReader.Get(), msixRequest));
RETURN_IF_FAILED(instance->SetManifestReader(manifestReader.Get()));
// Get the number of payload files
DWORD numberOfPayloadFiles = 0;
@ -105,27 +126,32 @@ HRESULT PackageInfo::MakeFromPackageReader(IAppxPackageReader * packageReader, M
}
instance->m_numberOfPayloadFiles = numberOfPayloadFiles;
*packageInfo = instance.release();
*packageInfo = instance;
return S_OK;
}
HRESULT PackageInfo::SetManifestReader(IAppxManifestReader * manifestReader, MsixRequest * msixRequest)
HRESULT PackageBase::SetManifestReader(IAppxManifestReader * manifestReader)
{
m_manifestReader = manifestReader;
std::wstring msix7DirectoryPath = msixRequest->GetFilePathMappings()->GetMsix7Directory();
// Also fill other fields that come from the manifest reader
ComPtr<IAppxManifestPackageId> manifestId;
RETURN_IF_FAILED(manifestReader->GetPackageId(&manifestId));
RETURN_IF_FAILED(manifestId->GetPublisher(&m_publisher));
Text<WCHAR> publisher;
RETURN_IF_FAILED(manifestId->GetPublisher(&publisher));
m_publisher = publisher.Get();
m_publisherName = m_publisher.substr(m_publisher.find_first_of(L"=") + 1,
m_publisher.find_first_of(L",") - m_publisher.find_first_of(L"=") - 1);
RETURN_IF_FAILED(manifestId->GetVersion(&m_version));
Text<WCHAR> packageFullName;
RETURN_IF_FAILED(manifestId->GetPackageFullName(&packageFullName));
m_packageFullName = packageFullName.Get();
m_packageDirectoryPath = msix7DirectoryPath + packageFullName.Get();
m_packageFamilyName = Win7MsixInstallerLib_GetFamilyNameFromFullName(m_packageFullName);
ComPtr<IMsixDocumentElement> domElement;
RETURN_IF_FAILED(manifestReader->QueryInterface(UuidOfImpl<IMsixDocumentElement>::iid, reinterpret_cast<void**>(&domElement)));
@ -133,9 +159,7 @@ HRESULT PackageInfo::SetManifestReader(IAppxManifestReader * manifestReader, Msi
ComPtr<IMsixElement> element;
RETURN_IF_FAILED(domElement->GetDocumentElement(&element));
RETURN_IF_FAILED(SetExecutableAndAppIdFromManifestElement(element.Get(), packageFullName.Get(), msixRequest));
RETURN_IF_FAILED(SetDisplayNameFromManifestElement(element.Get()));
RETURN_IF_FAILED(ParseManifest(element.Get()));
Text<WCHAR> packageFamilyName;
RETURN_IF_FAILED(manifestId->GetPackageFamilyName(&packageFamilyName));
@ -143,5 +167,48 @@ HRESULT PackageInfo::SetManifestReader(IAppxManifestReader * manifestReader, Msi
{
m_appUserModelId = std::wstring(packageFamilyName.Get()) + L"!" + m_applicationId;
}
return S_OK;
}
std::unique_ptr<IStream> Package::GetLogo()
{
if (m_packageReader.Get() == nullptr)
{
return nullptr;
}
IStream * logoStream;
if (GetStreamFromFile(m_packageReader.Get(), m_relativeLogoPath.data(), &logoStream) == S_OK)
{
return std::unique_ptr<IStream>(logoStream);
}
return nullptr;
}
std::unique_ptr<IStream> InstalledPackage::GetLogo()
{
auto iconPath = m_packageDirectoryPath + m_relativeLogoPath;
IStream* stream;
if (SUCCEEDED(CreateStreamOnFileUTF16(iconPath.c_str(), true, &stream)))
{
return std::unique_ptr<IStream>(stream);
}
return nullptr;
}
HRESULT InstalledPackage::MakeFromManifestReader(const std::wstring & directoryPath, IAppxManifestReader * manifestReader, std::shared_ptr<InstalledPackage> * packageInfo)
{
std::shared_ptr<InstalledPackage> instance = std::make_shared<InstalledPackage>();
if (instance == nullptr)
{
return E_OUTOFMEMORY;
}
RETURN_IF_FAILED(instance->SetManifestReader(manifestReader));
instance->m_packageDirectoryPath = directoryPath + L"\\";
*packageInfo = instance;
return S_OK;
}

Просмотреть файл

@ -0,0 +1,123 @@
#pragma once
#include "GeneralUtil.hpp"
#include "AppxPackaging.hpp"
#include "MSIXWindows.hpp"
#include "IPackage.hpp"
namespace Win7MsixInstallerLib
{
class PackageBase
{
protected:
std::wstring m_packageFullName;
std::wstring m_packageFamilyName;
std::wstring m_relativeExecutableFilePath;
std::wstring m_displayName;
std::wstring m_appUserModelId;
std::wstring m_applicationId;
unsigned long long m_version = 0;
std::wstring m_publisher;
std::wstring m_publisherName;
std::wstring m_relativeLogoPath;
ComPtr<IAppxManifestReader> m_manifestReader;
unsigned int m_numberOfPayloadFiles = 0;
public:
std::wstring GetPackageFullName() { return m_packageFullName; }
std::wstring GetPackageFamilyName() { return m_packageFamilyName; }
std::wstring GetRelativeExecutableFilePath() { return m_relativeExecutableFilePath; }
std::wstring GetDisplayName() { return m_displayName; }
std::wstring GetId() { return m_appUserModelId; }
unsigned long long GetVersionNumber() { return m_version; }
std::wstring GetVersion();
std::wstring GetPublisher() { return m_publisher; }
std::wstring GetPublisherDisplayName() { return m_publisherName; }
protected:
PackageBase() {}
/// Sets the manifest reader, and other fields derived from the manifest
/// Specifically, packageFullName, packageDirectoryPath, executableFilePath, displayname, version and publisher.
///
/// @param manifestReader - manifestReader to set
HRESULT SetManifestReader(IAppxManifestReader* manifestReader);
/// Parse the manifest file
///
/// @param element - the root node of the manifest file
HRESULT ParseManifest(IMsixElement * element);
public:
virtual ~PackageBase()
{
ReleaseManifest();
}
unsigned int GetNumberOfPayloadFiles() { return m_numberOfPayloadFiles; }
// Getters
IAppxManifestReader * GetManifestReader() { return m_manifestReader.Get(); }
/// This is meant only to be called when deleting the manifest file; the reader needs to first be released so it can be deleted
void ReleaseManifest() {
m_manifestReader.Release();
}
};
class Package : public PackageBase, public IPackage
{
public:
std::wstring GetPackageFullName() { return m_packageFullName; }
std::wstring GetPackageFamilyName() { return m_packageFamilyName; }
std::wstring GetRelativeExecutableFilePath() { return m_relativeExecutableFilePath; }
std::wstring GetDisplayName() { return m_displayName; }
std::wstring GetId() { return m_appUserModelId; }
unsigned long long GetVersionNumber() { return m_version; }
std::wstring GetVersion() { return PackageBase::GetVersion(); }
std::wstring GetPublisher() { return m_publisher; }
std::wstring GetPublisherDisplayName() { return m_publisherName; }
std::unique_ptr<IStream> GetLogo();
IAppxPackageReader * GetPackageReader() { return m_packageReader.Get(); }
/// Create a Package using the package reader. This is intended for Add scenarios where
/// the actual .msix package file is given.
static HRESULT MakeFromPackageReader(IAppxPackageReader* packageReader, std::shared_ptr<Package>* packageInfo);
virtual ~Package()
{
m_packageReader.Release();
}
Package() : PackageBase(), IPackage(){}
private:
/// PackageReader and payloadFiles are available on Add, but not Remove because it's created off the original package itself which is no longer available once it's been installed.
ComPtr<IAppxPackageReader> m_packageReader;
};
class InstalledPackage : public PackageBase, public IInstalledPackage
{
public:
std::wstring GetPackageFullName() { return m_packageFullName; }
std::wstring GetPackageFamilyName() { return m_packageFamilyName; }
std::wstring GetRelativeExecutableFilePath() { return m_relativeExecutableFilePath; }
std::wstring GetDisplayName() { return m_displayName; }
std::wstring GetId() { return m_appUserModelId; }
unsigned long long GetVersionNumber() { return m_version; }
std::wstring GetVersion() { return PackageBase::GetVersion(); }
std::wstring GetPublisher() { return m_publisher; }
std::wstring GetPublisherDisplayName() { return m_publisherName; }
std::unique_ptr<IStream> GetLogo();
virtual std::wstring GetFullExecutableFilePath()
{
return m_packageDirectoryPath + m_relativeExecutableFilePath;
}
virtual std::wstring GetInstalledLocation()
{
return m_packageDirectoryPath;
}
/// Create a InstalledPackage using the manifest reader and directory path. This is intended for Remove scenarios where
/// the actual .msix package file is no longer accessible.
static HRESULT MakeFromManifestReader(const std::wstring & directoryPath, IAppxManifestReader* manifestReader, std::shared_ptr<InstalledPackage>* packageInfo);
InstalledPackage() :PackageBase(), IInstalledPackage() {}
private:
std::wstring m_packageDirectoryPath;
};
}

Просмотреть файл

@ -1,69 +0,0 @@
#pragma once
#include "GeneralUtil.hpp"
#include "AppxPackaging.hpp"
#include "MSIXWindows.hpp"
class MsixRequest;
class PackageInfo
{
private:
ComPtr<IAppxManifestReader> m_manifestReader;
std::wstring m_packageFullName;
std::wstring m_packageDirectoryPath;
std::wstring m_executableFilePath;
std::wstring m_displayName;
std::wstring m_appUserModelId;
std::wstring m_applicationId;
UINT64 m_version = 0;
Text<WCHAR> m_publisher;
/// PackageReader and payloadFiles are available on Add, but not Remove because it's created off the original package itself which is no longer available once it's been installed.
ComPtr<IAppxPackageReader> m_packageReader;
DWORD m_numberOfPayloadFiles = 0;
/// Sets the manifest reader, and other fields derived from the manifest
/// Specifically, packageFullName, packageDirectoryPath, executableFilePath, displayname, version and publisher.
///
/// @param manifestReader - manifestReader to set
/// @param msix7DirectoryPath - the root msix7 directory path, which is the parent directory of the package directory.
HRESULT SetManifestReader(IAppxManifestReader* manifestReader, MsixRequest * msixRequest);
/// Sets the executable path and app ID by reading it from the manifest element
HRESULT SetExecutableAndAppIdFromManifestElement(IMsixElement * element, PCWSTR packageFullName, MsixRequest * msixRequest);
/// Sets the display name by reading it from the manifest element
HRESULT SetDisplayNameFromManifestElement(IMsixElement * element);
/// Sets the application model user id from the manifest reader
HRESULT SetApplicationUserModelIdFromManifestElement(IAppxManifestReader* manifestReader);
public:
/// Create a PackageInfo using the manifest reader and directory path. This is intended for Remove scenarios where
/// the actual .msix package file is no longer accessible.
static HRESULT MakeFromManifestReader(IAppxManifestReader* manifestReader, MsixRequest * msixRequest, PackageInfo** packageInfo);
/// Create a PackageInfo using the package reader. This is intended for Add scenarios where
/// the actual .msix package file is given.
static HRESULT MakeFromPackageReader(IAppxPackageReader* packageReader, MsixRequest * msixRequest, PackageInfo** packageInfo);
/// When made from manifest reader, it won't have PackageReader available.
bool HasPackageReader() { return (m_packageReader.Get() != nullptr); };
IAppxPackageReader * GetPackageReader() { return m_packageReader.Get(); }
DWORD GetNumberOfPayloadFiles() { return m_numberOfPayloadFiles; }
// Getters
IAppxManifestReader * GetManifestReader() { return m_manifestReader.Get(); }
std::wstring GetPackageFullName() { return m_packageFullName; }
std::wstring GetPackageDirectoryPath() { return m_packageDirectoryPath; }
std::wstring GetExecutableFilePath() { return m_executableFilePath; }
std::wstring GetDisplayName() { return m_displayName; }
std::wstring GetAppModelUserId() { return m_appUserModelId; }
UINT64 GetVersion() { return m_version; }
PCWSTR GetPublisher() { return m_publisher.Get(); }
/// This is meant only to be called when deleting the manifest file; the reader needs to first be released so it can be deleted
void ReleaseManifest() { m_manifestReader.Release(); }
};

Просмотреть файл

@ -2,75 +2,95 @@
#include "PopulatePackageInfo.hpp"
#include "GeneralUtil.hpp"
#include "FilePaths.hpp"
#include <TraceLoggingProvider.h>
#include <experimental/filesystem> // C++-standard header file name
#include "Constants.hpp"
using namespace Win7MsixInstallerLib;
const PCWSTR PopulatePackageInfo::HandlerName = L"PopulatePackageInfo";
HRESULT PopulatePackageInfo::CreatePackageReader()
HRESULT PopulatePackageInfo::GetPackageInfoFromPackage(const std::wstring & packageFilePath, MSIX_VALIDATION_OPTION validationOption, std::shared_ptr<Package> * packageInfo)
{
ComPtr<IStream> inputStream;
RETURN_IF_FAILED(CreateStreamOnFileUTF16(m_msixRequest->GetPackageFilePath(), /*forRead */ true, &inputStream));
RETURN_IF_FAILED(CreateStreamOnFileUTF16(packageFilePath.c_str(), /*forRead */ true, &inputStream));
// On Win32 platforms CoCreateAppxFactory defaults to CoTaskMemAlloc/CoTaskMemFree
// On non-Win32 platforms CoCreateAppxFactory will return 0x80070032 (e.g. HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
// So on all platforms, it's always safe to call CoCreateAppxFactoryWithHeap, just be sure to bring your own heap!
ComPtr<IAppxFactory> appxFactory;
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(MyAllocate, MyFree, m_msixRequest->GetValidationOptions(), &appxFactory));
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(Win7MsixInstallerLib_MyAllocate, Win7MsixInstallerLib_MyFree, validationOption, &appxFactory));
// Create a new package reader using the factory.
ComPtr<IAppxPackageReader> packageReader;
RETURN_IF_FAILED(appxFactory->CreatePackageReader(inputStream.Get(), &packageReader));
AutoPtr<PackageInfo> packageInfo;
RETURN_IF_FAILED(PackageInfo::MakeFromPackageReader(packageReader.Get(), m_msixRequest, &packageInfo));
m_msixRequest->SetPackageInfo(packageInfo.Detach());
RETURN_IF_FAILED(Package::MakeFromPackageReader(packageReader.Get(), packageInfo));
packageReader.Release();
inputStream.Release();
return S_OK;
}
HRESULT PopulatePackageInfo::GetPackageInfoFromManifest(const std::wstring & directoryPath, MSIX_VALIDATION_OPTION validationOption, std::shared_ptr<InstalledPackage> * packageInfo)
{
std::wstring manifestPath = directoryPath + manifestFile;
// On Win32 platforms CoCreateAppxFactory defaults to CoTaskMemAlloc/CoTaskMemFree
// On non-Win32 platforms CoCreateAppxFactory will return 0x80070032 (e.g. HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
// So on all platforms, it's always safe to call CoCreateAppxFactoryWithHeap, just be sure to bring your own heap!
ComPtr<IStream> inputStream;
RETURN_IF_FAILED(CreateStreamOnFileUTF16(manifestPath.c_str(), /*forRead*/ true, &inputStream));
// Create a new package reader using the factory.
ComPtr<IAppxFactory> appxFactory;
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(Win7MsixInstallerLib_MyAllocate, Win7MsixInstallerLib_MyFree, validationOption, &appxFactory));
ComPtr<IAppxManifestReader> manifestReader;
RETURN_IF_FAILED(appxFactory->CreateManifestReader(inputStream.Get(), &manifestReader));
RETURN_IF_FAILED(InstalledPackage::MakeFromManifestReader(directoryPath, manifestReader.Get(), packageInfo));
manifestReader.Release();
inputStream.Release();
return S_OK;
}
HRESULT PopulatePackageInfo::ExecuteForAddRequest()
{
RETURN_IF_FAILED(CreatePackageReader());
std::shared_ptr<Package> packageInfo;
RETURN_IF_FAILED(PopulatePackageInfo::GetPackageInfoFromPackage(m_msixRequest->GetPackageFilePath(), m_msixRequest->GetValidationOptions(), &packageInfo));
if (packageInfo == nullptr)
{
return E_FAIL;
}
m_msixRequest->SetPackageInfo(packageInfo);
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"PackageInfo",
TraceLoggingValue(m_msixRequest->GetPackageInfo()->GetPackageFullName().c_str(), "PackageFullName"),
TraceLoggingValue(m_msixRequest->GetPackageInfo()->GetNumberOfPayloadFiles(), "NumberOfPayloadFiles"),
TraceLoggingValue(m_msixRequest->GetPackageInfo()->GetExecutableFilePath().c_str(), "ExecutableFilePath"),
TraceLoggingValue(m_msixRequest->GetPackageInfo()->GetDisplayName().c_str(), "DisplayName"));
TraceLoggingValue(packageInfo->GetPackageFullName().c_str(), "PackageFullName"),
TraceLoggingValue(packageInfo->GetNumberOfPayloadFiles(), "NumberOfPayloadFiles"),
TraceLoggingValue(m_msixRequest->GetPackageDirectoryPath().c_str(), "ExecutableFilePath"),
TraceLoggingValue(packageInfo->GetDisplayName().c_str(), "DisplayName"));
return S_OK;
}
HRESULT PopulatePackageInfo::ExecuteForRemoveRequest()
{
std::wstring packageDirectoryPath = m_msixRequest->GetFilePathMappings()->GetMsix7Directory() + m_msixRequest->GetPackageFullName();
std::experimental::filesystem::path directory = packageDirectoryPath;
if (!std::experimental::filesystem::exists(directory))
auto packageDirectoryPath = FilePathMappings::GetInstance().GetMsix7Directory() + m_msixRequest->GetPackageFullName();
std::shared_ptr<InstalledPackage> package;
RETURN_IF_FAILED(GetPackageInfoFromManifest(packageDirectoryPath, MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN, &package));
if (package == nullptr)
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Could not find package directory",
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName"),
TraceLoggingValue(directory.c_str(), "PackageDirectoryPath"));
return E_NOT_SET;
return E_FAIL;
}
std::wstring manifestPath = packageDirectoryPath + manifestFile;
ComPtr<IStream> stream;
RETURN_IF_FAILED(CreateStreamOnFileUTF16(manifestPath.c_str(), true /*forRead*/, &stream));
ComPtr<IAppxFactory> appxFactory;
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(MyAllocate, MyFree, m_msixRequest->GetValidationOptions(), &appxFactory));
ComPtr<IAppxManifestReader> manifestReader;
RETURN_IF_FAILED(appxFactory->CreateManifestReader(stream.Get(), &manifestReader));
AutoPtr<PackageInfo> packageInfo;
RETURN_IF_FAILED(PackageInfo::MakeFromManifestReader(manifestReader.Get(), m_msixRequest, &packageInfo));
m_msixRequest->SetPackageInfo(packageInfo.Detach());
m_msixRequest->SetPackageInfo(package);
return S_OK;
}
@ -85,4 +105,4 @@ HRESULT PopulatePackageInfo::CreateHandler(MsixRequest * msixRequest, IPackageHa
*instance = localInstance.release();
return S_OK;
}
}

Просмотреть файл

@ -1,10 +1,13 @@
#pragma once
#pragma once
#include "GeneralUtil.hpp"
#include "Package.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
#include <string>
namespace Win7MsixInstallerLib
{
class PopulatePackageInfo : IPackageHandler
{
public:
@ -15,14 +18,18 @@ public:
/// @return E_NOT_SET when the package cannot be found
HRESULT ExecuteForRemoveRequest();
bool IsMandatoryForRemoveRequest() { return true; }
static const PCWSTR HandlerName;
static HRESULT CreateHandler(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
~PopulatePackageInfo() {}
static HRESULT GetPackageInfoFromManifest(const std::wstring & directoryPath, MSIX_VALIDATION_OPTION validationOption, std::shared_ptr<InstalledPackage> * packageInfo);
static HRESULT GetPackageInfoFromPackage(const std::wstring & packageFilePath, MSIX_VALIDATION_OPTION validationOption, std::shared_ptr<Package> * packageInfo);
private:
MsixRequest* m_msixRequest = nullptr;
PopulatePackageInfo() {}
PopulatePackageInfo(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
HRESULT CreatePackageReader();
};
}

Просмотреть файл

@ -1,6 +1,7 @@
#include "ProcessPotentialUpdate.hpp"
#include <filesystem>
using namespace Win7MsixInstallerLib;
const PCWSTR ProcessPotentialUpdate::HandlerName = L"ProcessPotentialUpdate";
HRESULT ProcessPotentialUpdate::ExecuteForAddRequest()
@ -9,13 +10,13 @@ HRESULT ProcessPotentialUpdate::ExecuteForAddRequest()
/// This is currently good enough for our requirements; it leverages existing removal codepaths.
/// An alternate, more complicated design would have each handler to expose a new Update verb (e.g. ExecuteForUpdate that takes in the old package)
/// and each handler would have the opportunity to reason between the old and new packages to perform more efficient updating.
std::wstring currentPackageFamilyName = GetFamilyNameFromFullName(m_msixRequest->GetPackageInfo()->GetPackageFullName());
std::wstring currentPackageFamilyName = m_msixRequest->GetPackageInfo()->GetPackageFamilyName();
for (auto& p : std::experimental::filesystem::directory_iterator(m_msixRequest->GetFilePathMappings()->GetMsix7Directory()))
for (auto& p : std::experimental::filesystem::directory_iterator(FilePathMappings::GetInstance().GetMsix7Directory()))
{
std::wstring installedPackageFamilyName = GetFamilyNameFromFullName(p.path().filename());
if (CaseInsensitiveEquals(currentPackageFamilyName, installedPackageFamilyName)
&& !CaseInsensitiveEquals(m_msixRequest->GetPackageInfo()->GetPackageFullName(), p.path().filename()))
std::wstring installedPackageFamilyName = Win7MsixInstallerLib_GetFamilyNameFromFullName(p.path().filename());
if (Win7MsixInstallerLib_CaseInsensitiveEquals(currentPackageFamilyName, installedPackageFamilyName)
&& !Win7MsixInstallerLib_CaseInsensitiveEquals(m_msixRequest->GetPackageInfo()->GetPackageFullName(), p.path().filename()))
{
RETURN_IF_FAILED(RemovePackage(p.path().filename()));
return S_OK;
@ -34,7 +35,7 @@ HRESULT ProcessPotentialUpdate::RemovePackage(std::wstring packageFullName)
TraceLoggingValue(packageFullName.c_str(), "PackageToBeRemoved"));
AutoPtr<MsixRequest> localRequest;
RETURN_IF_FAILED(MsixRequest::Make(OperationType::Remove, Flags::NoFlags, std::wstring(), packageFullName, MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &localRequest));
RETURN_IF_FAILED(MsixRequest::Make(OperationType::Remove, std::wstring(), packageFullName, MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &localRequest));
const HRESULT hrProcessRequest = localRequest->ProcessRequest();
if (FAILED(hrProcessRequest))

Просмотреть файл

@ -2,7 +2,10 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Determines if the incoming add request is actually an update to an existing package.
/// If it is, it'll remove the outdated package
class ProcessPotentialUpdate : IPackageHandler
@ -24,3 +27,4 @@ private:
/// Synchronously removes the outdated package before allowing the current request to proceed
HRESULT RemovePackage(std::wstring packageFullName);
};
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "GeneralUtil.hpp"
#include "Constants.hpp"
#include <TraceLoggingProvider.h>
using namespace Win7MsixInstallerLib;
const PCWSTR Protocol::HandlerName = L"Protocol";
@ -42,7 +43,7 @@ HRESULT Protocol::ParseProtocolElement(IMsixElement* protocolElement)
Text<wchar_t> logoPath;
RETURN_IF_FAILED(logoElement->GetText(&logoPath));
protocol.logo = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath() + std::wstring(L"\\") + logoPath.Get();
protocol.logo = m_msixRequest->GetPackageDirectoryPath() + std::wstring(L"\\") + logoPath.Get();
}
ComPtr<IMsixElementEnumerator> displayNameEnum;
@ -148,7 +149,7 @@ HRESULT Protocol::ProcessProtocolForAdd(ProtocolData& protocol)
RegistryKey commandKey;
RETURN_IF_FAILED(openKey.CreateSubKey(commandKeyName.c_str(), KEY_WRITE, &commandKey));
std::wstring command = m_msixRequest->GetPackageInfo()->GetExecutableFilePath();
std::wstring command = m_msixRequest->GetPackageDirectoryPath() + L"\\" + m_msixRequest->GetPackageInfo()->GetRelativeExecutableFilePath();
if (protocol.parameters.c_str() != nullptr)
{
command += std::wstring(L" ") + protocol.parameters;
@ -188,7 +189,7 @@ bool Protocol::IsCurrentlyAssociatedWithPackage(PCWSTR name)
return false;
}
std::wstring executablePath = m_msixRequest->GetPackageInfo()->GetExecutableFilePath();
std::wstring executablePath = m_msixRequest->GetPackageDirectoryPath() + L"\\" + m_msixRequest->GetPackageInfo()->GetRelativeExecutableFilePath();
std::wstring currentlyAssociatedExe;
if (SUCCEEDED(protocolExeKey.GetStringValue(L"", currentlyAssociatedExe)))
{

Просмотреть файл

@ -4,6 +4,10 @@
#include "IPackageHandler.hpp"
#include "RegistryKey.hpp"
#include <vector>
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Data structs to be filled in from the information in the manifest
struct ProtocolData
@ -55,4 +59,4 @@ private:
/// @param name - the name of the protocol
bool IsCurrentlyAssociatedWithPackage(PCWSTR name);
};
}

Просмотреть файл

@ -2,6 +2,7 @@
#include "FilePaths.hpp"
#include "Constants.hpp"
#include <vector>
using namespace Win7MsixInstallerLib;
struct VirtualRegistryMapping
{
@ -212,7 +213,7 @@ HRESULT RegistryDevirtualizer::DetokenizeData(std::wstring& data)
// get the contents of what's in between the braces, i.e. [{token}]
std::wstring token = data.substr(beginToken + 2, (endToken - beginToken - 2)); // +2 to skip over [{ characters, -2 to omit }] characters
std::map<std::wstring, std::wstring> map = m_msixRequest->GetFilePathMappings()->GetMap();
std::map<std::wstring, std::wstring> map = FilePathMappings::GetInstance().GetMap();
for (auto& pair : map)
{
if (token.find(pair.first) != std::wstring::npos)

Просмотреть файл

@ -4,7 +4,10 @@
#include "MsixRequest.hpp"
#include "RegistryKey.hpp"
#include <vector>
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Handles the conversion of the information stored in Registry.dat
/// to the currently running OS's registry, which is referred to here as "actual registry"
/// The information stored in Registry.dat is referred to here as "virtual registry" or "virtualized registry"
@ -86,3 +89,4 @@ private:
RegistryKey m_rootKey;
bool m_hiveFileNameExists = false;
};
}

Просмотреть файл

@ -1,4 +1,5 @@
#include "RegistryKey.hpp"
using namespace Win7MsixInstallerLib;
HRESULT RegistryKey::Open(
_In_ const HKEY hkey,

Просмотреть файл

@ -1,7 +1,8 @@
#pragma once
#include "GeneralUtil.hpp"
namespace Win7MsixInstallerLib
{
/// Encapsulates and lifetimes the HKEY used by the RegOpenKey et al APIs.
class RegistryKey
{
@ -155,4 +156,5 @@ public:
protected:
std::wstring m_path;
HKEY m_hkey = nullptr;
};
};
}

Просмотреть файл

@ -9,6 +9,7 @@
#include "StartMenuLink.hpp"
#include "GeneralUtil.hpp"
#include <TraceLoggingProvider.h>
using namespace Win7MsixInstallerLib;
const PCWSTR StartMenuLink::HandlerName = L"StartMenuLink";
@ -50,12 +51,12 @@ HRESULT StartMenuLink::ExecuteForAddRequest()
{
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
auto packageInfo = m_msixRequest->GetPackageInfo();
std::wstring filePath = m_msixRequest->GetFilePathMappings()->GetMap()[L"Common Programs"] + L"\\" + packageInfo->GetDisplayName() + L".lnk";
std::wstring filePath = FilePathMappings::GetInstance().GetMap()[L"Common Programs"] + L"\\" + packageInfo->GetDisplayName() + L".lnk";
std::wstring resolvedExecutableFullPath = packageInfo->GetExecutableFilePath();
std::wstring appUserModelId = m_msixRequest->GetPackageInfo()->GetAppModelUserId();
std::wstring resolvedExecutableFullPath = m_msixRequest->GetPackageDirectoryPath() + L"\\" + packageInfo->GetRelativeExecutableFilePath();
std::wstring appUserModelId = m_msixRequest->GetPackageInfo()->GetId();
RETURN_IF_FAILED(CreateLink(resolvedExecutableFullPath.c_str(), filePath.c_str(), L"", appUserModelId.c_str()));
return S_OK;
@ -63,9 +64,9 @@ HRESULT StartMenuLink::ExecuteForAddRequest()
HRESULT StartMenuLink::ExecuteForRemoveRequest()
{
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
auto packageInfo = m_msixRequest->GetPackageInfo();
std::wstring filePath = m_msixRequest->GetFilePathMappings()->GetMap()[L"Common Programs"] + L"\\" + packageInfo->GetDisplayName() + L".lnk";
std::wstring filePath = FilePathMappings::GetInstance().GetMap()[L"Common Programs"] + L"\\" + packageInfo->GetDisplayName() + L".lnk";
RETURN_IF_FAILED(DeleteFile(filePath.c_str()));
return S_OK;

Просмотреть файл

@ -2,7 +2,10 @@
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace Win7MsixInstallerLib
{
/// Handles adding/removing the shortcut in the start menu to launch the application
class StartMenuLink : IPackageHandler
{
@ -31,3 +34,4 @@ private:
/// @param appUserModelId- Application User Model ID, needed to display toasts.
HRESULT CreateLink(PCWSTR targetFilePath, PCWSTR linkFilePath, PCWSTR description, PCWSTR appUserModelId = NULL);
};
}

Просмотреть файл

@ -0,0 +1,40 @@
#include "Util.hpp"
#include <string>
#include <codecvt>
#include <iostream>
std::string utf16_to_utf8(const std::wstring& utf16string)
{
auto converted = std::wstring_convert<std::codecvt_utf8<wchar_t>>{}.to_bytes(utf16string.data());
std::string result(converted.begin(), converted.end());
return result;
}
std::wstring utf8_to_utf16(const std::string& utf8string)
{
// see https://connect.microsoft.com/VisualStudio/feedback/details/1403302/unresolved-external-when-using-codecvt-utf8
auto converted = std::wstring_convert<std::codecvt_utf8_utf16<unsigned short>, unsigned short>{}.from_bytes(utf8string.data());
std::wstring result(converted.begin(), converted.end());
return result;
}
std::wstring GetStringResource(UINT resourceId)
{
HMODULE instance = GetModuleHandle(nullptr);
WCHAR buffer[MAX_PATH] = L"";
int loadStringRet = LoadStringW(instance, resourceId, buffer, ARRAYSIZE(buffer));
if (loadStringRet <= 0)
{
return std::wstring(L"Failed to load string resource");
}
std::wstring stringResource(buffer);
return stringResource;
}
bool CaseInsensitiveEquals(const std::wstring& left, const std::wstring& right)
{
return (_wcsicmp(left.c_str(), right.c_str()) == 0);
}

Просмотреть файл

@ -1,29 +1,8 @@
#pragma once
#include <windows.h>
#include "AppxPackaging.hpp"
#include <TraceLoggingProvider.h>
#include <winmeta.h>
#include <string.h>
TRACELOGGING_DECLARE_PROVIDER(g_MsixTraceLoggingProvider);
// Definition of function to return error if failed
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define RETURN_IF_FAILED(a) \
{ \
HRESULT __hr = a; \
if (FAILED(__hr)) \
{ \
TraceLoggingWrite(g_MsixTraceLoggingProvider, \
"RETURN_IF_FAILED", \
TraceLoggingLevel(WINEVENT_LEVEL_ERROR), \
TraceLoggingValue(#a, "Code"), \
TraceLoggingHResult(__hr, "HR"), \
TraceLoggingUInt32(__LINE__, "Line"), \
TraceLoggingValue(__FILENAME__, "Filename")); \
return __hr; \
} \
}
/// Converts a wstring from utf16 to utf8
///
@ -36,32 +15,19 @@ std::string utf16_to_utf8(const std::wstring& utf16string);
/// @param utf8string - A utf8 string
/// @return utf16 string
std::wstring utf8_to_utf16(const std::string& utf8string);
/// Helper to convert version number to a version string of the form a.b.c.d
///
/// @param version - version number
/// @return a.b.c.d string representation of version
std::wstring ConvertVersionToString(UINT64 version);
/// Helper to get string resource
///
/// @param resourceId - resource ID, these should be listed in resource.h
/// @return string for the resource, resolved from the stringtable defined in Win7MsixInstaller.rc
std::wstring GetStringResource(UINT resourceId);
/// Converts a packageFullName (i.e. examplePackageName_1.0.0.0_x64_resourceId_8wekyb3d8bbwe)
/// into a packageFamilyName (i.e. examplePackageName_8wekyb3d8bbwe)
///
/// @param fullName - the packageFullName, assumed to be properly formatted and not validated.
/// @return packageFamilyName for the packageFullName
std::wstring GetFamilyNameFromFullName(const std::wstring& fullName);
/// Determines if two strings are case-insensitive equals
///
/// @param left - one of the two strings
/// @param right - the other of the two strings
/// @return true if the strings equal, false otherwise
bool CaseInsensitiveEquals(const std::wstring& left, const std::wstring& right);
bool CaseInsensitiveEquals(const std::wstring& left, const std::wstring& right);
//
// A designated memory allocator

Просмотреть файл

@ -6,38 +6,23 @@
#include <CommCtrl.h>
#include <string>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <utility>
#include <iomanip>
#include "GeneralUtil.hpp"
#include "FilePaths.hpp"
#include <cstdio>
#include <vector>
#include <TraceLoggingProvider.h>
#include "InstallUI.hpp"
#include "CommandLineInterface.hpp"
#include "Win7MSIXInstallerLogger.hpp"
#include "Util.hpp"
#include "resource.h"
#include <VersionHelpers.h>
// Define the GUID to use in TraceLoggingProviderRegister
// {033321d3-d599-48e0-868d-c59f15901637}
// One way to enable:
// logman create trace <nameoftrace> -p "{033321d3-d599-48e0-868d-c59f15901637}" -o <filename>
// i.e. logman create trace MsixTrace -p "{033321d3-d599-48e0-868d-c59f15901637}" -o c:\msixtrace.etl
// logman start MsixTrace
// logman stop MsixTrace
// tracerpt.exe, Windows Performance Analyzer or other tools can be used to view the etl file.
TRACELOGGING_DEFINE_PROVIDER(
g_MsixTraceLoggingProvider,
"MsixTraceLoggingProvider",
(0x033321d3, 0xd599, 0x48e0, 0x86, 0x8d, 0xc5, 0x9f, 0x15, 0x90, 0x16, 0x37));
#include <Win7MSIXInstallerActions.hpp>
using namespace std;
int main(int argc, char * argv[])
{
// Register the provider
TraceLoggingRegister(g_MsixTraceLoggingProvider);
TraceLoggingRegister(g_MsixUITraceLoggingProvider);
HRESULT hrCoInitialize = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hrCoInitialize))
@ -48,20 +33,86 @@ int main(int argc, char * argv[])
CommandLineInterface cli(argc, argv);
AutoPtr<MsixRequest> msixRequest;
const HRESULT hrCreateRequest = cli.CreateRequest(&msixRequest);
const HRESULT hrCreateRequest = cli.Init();
if (SUCCEEDED(hrCreateRequest))
{
const HRESULT hrProcessRequest = msixRequest->ProcessRequest();
if (FAILED(hrProcessRequest))
switch (cli.GetOperationType())
{
case OperationType::Add:
{
AutoPtr<Win7MsixInstallerLib::IPackageManager> packageManager;
RETURN_IF_FAILED(Win7MsixInstallerLib_CreatePackageManager(&packageManager));
std::wcout << GetStringResource(IDS_STRING_FAILED_REQUEST) << " " << std::hex << hrProcessRequest << std::endl;
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Failed to process request",
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingValue(hrProcessRequest, "HR"));
return 1;
if (cli.IsQuietMode())
{
auto res = packageManager->AddPackage(cli.GetPackageFilePathToInstall(), DeploymentOptions::None);
if (FAILED(res))
{
return res;
}
}
else
{
auto ui = new UI(packageManager, cli.GetPackageFilePathToInstall(), UIType::InstallUIAdd);
ui->ShowUI();
}
break;
}
case OperationType::Remove:
{
AutoPtr<Win7MsixInstallerLib::IPackageManager> packageManager;
RETURN_IF_FAILED(Win7MsixInstallerLib_CreatePackageManager(&packageManager));
auto packageFullName = cli.GetPackageFullName();
auto res = packageManager->RemovePackage(packageFullName);
if (FAILED(res))
{
return res;
}
break;
}
case OperationType::FindPackage:
{
AutoPtr<Win7MsixInstallerLib::IPackageManager> packageManager;
RETURN_IF_FAILED(Win7MsixInstallerLib_CreatePackageManager(&packageManager));
shared_ptr<Win7MsixInstallerLib::IInstalledPackage> packageInfo = packageManager->FindPackage(cli.GetPackageFullName());
if (packageInfo == NULL)
{
std::wcout << std::endl;
std::wcout << L"No packages found" << std::endl;
std::wcout << std::endl;
}
else {
std::wcout << std::endl;
std::wcout << L"PackageFullName: " << packageInfo->GetPackageFullName().c_str() << std::endl;
std::wcout << L"DisplayName: " << packageInfo->GetDisplayName().c_str() << std::endl;
std::wcout << L"DirectoryPath: " << packageInfo->GetInstalledLocation().c_str() << std::endl;
std::wcout << std::endl;
}
return S_OK;
}
case OperationType::FindAllPackages:
{
AutoPtr<Win7MsixInstallerLib::IPackageManager> packageManager;
RETURN_IF_FAILED(Win7MsixInstallerLib_CreatePackageManager(&packageManager));
auto packages = packageManager->FindPackages();
unsigned int numPackages = 0;
for (auto& package : *packages)
{
std::wcout << package->GetPackageFullName() << std::endl;
numPackages++;
}
std::cout << numPackages << " Packages found" << std::endl;
return S_OK;
}
default:
return E_NOT_SET;
}
}
else
@ -69,10 +120,9 @@ int main(int argc, char * argv[])
cli.DisplayHelp();
}
// Stop TraceLogging and unregister the provider
TraceLoggingUnregister(g_MsixTraceLoggingProvider);
TraceLoggingUnregister(g_MsixUITraceLoggingProvider);
return 0;
}

Просмотреть файл

@ -90,16 +90,16 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\Win7MsixInstallerLib\inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\Debug;..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>win7msixinstallerlib.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "..\..\..\.vs\bin\msix.dll" "$(OutDir)"</Command>
@ -113,20 +113,24 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..\Win7MsixInstallerLib\inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\x64\Debug;..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>win7msixinstallerlib.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "..\..\..\.vs\bin\msix.dll" "$(OutDir)"</Command>
</PostBuildEvent>
<CustomBuildStep>
<Command>
</Command>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -138,7 +142,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\Win7MsixInstallerLib\inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
@ -146,10 +150,10 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\Release;..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>win7msixinstallerlib.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "..\..\..\.vs\bin\msix.dll" "$(OutDir)"</Command>
@ -165,7 +169,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\Win7MsixInstallerLib\inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
@ -173,10 +177,10 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\x64\Release;..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>win7msixinstallerlib.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "..\..\..\.vs\bin\msix.dll" "$(OutDir)"</Command>
@ -186,57 +190,18 @@
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="AddRemovePrograms.hpp" />
<ClInclude Include="ComInterface.hpp" />
<ClInclude Include="ComServer.hpp" />
<ClInclude Include="Constants.hpp" />
<ClInclude Include="ErrorHandler.hpp" />
<ClInclude Include="MsixResponse.hpp" />
<ClInclude Include="Extractor.hpp" />
<ClInclude Include="FileTypeAssociation.hpp" />
<ClInclude Include="FootprintFiles.hpp" />
<ClInclude Include="GeneralUtil.hpp" />
<ClInclude Include="FilePaths.hpp" />
<ClInclude Include="Util.hpp" />
<ClInclude Include="CommandLineInterface.hpp" />
<ClInclude Include="InstallComplete.hpp" />
<ClInclude Include="PopulatePackageInfo.hpp" />
<ClInclude Include="PackageInfo.hpp" />
<ClInclude Include="IPackageHandler.hpp" />
<ClInclude Include="MsixRequest.hpp" />
<ClInclude Include="InstallUI.hpp" />
<ClInclude Include="..\..\..\.vs\src\msix\AppxPackaging.hpp" />
<ClInclude Include="..\..\..\.vs\src\msix\MSIXWindows.hpp" />
<ClInclude Include="ProcessPotentialUpdate.hpp" />
<ClInclude Include="Protocol.hpp" />
<ClInclude Include="RegistryDevirtualizer.hpp" />
<ClInclude Include="RegistryKey.hpp" />
<ClInclude Include="resource.h" />
<ClInclude Include="StartMenuLink.hpp" />
<ClInclude Include="ValidateTargetDeviceFamily.hpp" />
<ClInclude Include="Win7MSIXInstallerLogger.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ComInterface.cpp" />
<ClCompile Include="ComServer.cpp" />
<ClCompile Include="ErrorHandler.cpp" />
<ClCompile Include="Extractor.cpp" />
<ClCompile Include="FilePaths.cpp" />
<ClCompile Include="FileTypeAssociation.cpp" />
<ClCompile Include="GeneralUtil.cpp" />
<ClCompile Include="InstallComplete.cpp" />
<ClCompile Include="Util.cpp" />
<ClCompile Include="InstallUI.cpp" />
<ClCompile Include="MsixResponse.cpp" />
<ClCompile Include="PackageInfo.cpp" />
<ClCompile Include="ProcessPotentialUpdate.cpp" />
<ClCompile Include="Protocol.cpp" />
<ClCompile Include="RegistryDevirtualizer.cpp" />
<ClCompile Include="RegistryKey.cpp" />
<ClCompile Include="CommandLineInterface.cpp" />
<ClCompile Include="MsixRequest.cpp" />
<ClCompile Include="PopulatePackageInfo.cpp" />
<ClCompile Include="AddRemovePrograms.cpp" />
<ClCompile Include="StartMenuLink.cpp" />
<ClCompile Include="ValidateTargetDeviceFamily.cpp" />
<ClCompile Include="Win7MSIXInstaller.cpp" />
<ClCompile Include="Win7MSIXInstallerLogger.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Win7MSIXInstaller.rc" />

Просмотреть файл

@ -18,64 +18,13 @@
<ClInclude Include="CommandLineInterface.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MsixRequest.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IPackageHandler.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PackageInfo.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PopulatePackageInfo.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StartMenuLink.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AddRemovePrograms.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FileTypeAssociation.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Protocol.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RegistryDevirtualizer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RegistryKey.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Extractor.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FilePaths.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FootprintFiles.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GeneralUtil.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="InstallUI.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Constants.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\.vs\src\msix\AppxPackaging.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\.vs\src\msix\MSIXWindows.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="InstallComplete.hpp">
<ClInclude Include="Win7MSIXInstallerLogger.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ComInterface.hpp">
@ -84,13 +33,7 @@
<ClInclude Include="ComServer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MsixResponse.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ErrorHandler.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ProcessPotentialUpdate.hpp">
<ClInclude Include="Util.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ValidateTargetDeviceFamily.hpp">
@ -98,52 +41,16 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Win7MSIXInstaller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GeneralUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Extractor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FilePaths.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="InstallUI.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MsixRequest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CommandLineInterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PopulatePackageInfo.cpp">
<ClCompile Include="Win7MSIXInstallerLogger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StartMenuLink.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AddRemovePrograms.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FileTypeAssociation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Protocol.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RegistryDevirtualizer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RegistryKey.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PackageInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="InstallComplete.cpp">
<ClCompile Include="Win7MSIXInstaller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ComInterface.cpp">
@ -152,13 +59,7 @@
<ClCompile Include="ComServer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MsixResponse.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ErrorHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ProcessPotentialUpdate.cpp">
<ClCompile Include="Util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ValidateTargetDeviceFamily.cpp">

Просмотреть файл

@ -0,0 +1,13 @@
#include "Win7MSIXInstallerLogger.hpp"
// Define the GUID to use in TraceLoggingProviderRegister
// {035426d5-d599-48e0-868d-c59f15901637}
// One way to enable:
// logman create trace <nameoftrace> -p "{035426d5-d599-48e0-868d-c59f15901637}" -o <filename>
// i.e. logman create trace MsixTrace -p "{035426d5-d599-48e0-868d-c59f15901637}" -o c:\msixtrace.etl
// logman start MsixTrace
// logman stop MsixTrace
// tracerpt.exe, Windows Performance Analyzer or other tools can be used to view the etl file.
TRACELOGGING_DEFINE_PROVIDER(
g_MsixUITraceLoggingProvider,
"MsixInstallerUITraceLoggingProvider",
(0x035426d5, 0xd599, 0x48e0, 0x86, 0x8d, 0xc5, 0x9f, 0x15, 0x90, 0x16, 0x37));

Просмотреть файл

@ -0,0 +1,23 @@
#pragma once
#include <windows.h>
#include <TraceLoggingProvider.h>
TRACELOGGING_DECLARE_PROVIDER(g_MsixUITraceLoggingProvider);
// Definition of function to return error if failed
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define RETURN_IF_FAILED(a) \
{ \
HRESULT __hr = a; \
if (FAILED(__hr)) \
{ \
TraceLoggingWrite(g_MsixUITraceLoggingProvider, \
"RETURN_IF_FAILED", \
TraceLoggingLevel(WINEVENT_LEVEL_ERROR), \
TraceLoggingValue(#a, "Code"), \
TraceLoggingHResult(__hr, "HR"), \
TraceLoggingUInt32(__LINE__, "Line"), \
TraceLoggingValue(__FILENAME__, "Filename")); \
return __hr; \
} \
}

Просмотреть файл

@ -1,24 +1,30 @@
#include "GeneralUtil.hpp"
#include <string>
#include <codecvt>
#include <iostream>
std::string utf16_to_utf8(const std::wstring& utf16string)
{
auto converted = std::wstring_convert<std::codecvt_utf8<wchar_t>>{}.to_bytes(utf16string.data());
std::string result(converted.begin(), converted.end());
return result;
}
std::wstring utf8_to_utf16(const std::string& utf8string)
{
// see https://connect.microsoft.com/VisualStudio/feedback/details/1403302/unresolved-external-when-using-codecvt-utf8
auto converted = std::wstring_convert<std::codecvt_utf8_utf16<unsigned short>, unsigned short>{}.from_bytes(utf8string.data());
std::wstring result(converted.begin(), converted.end());
return result;
}
std::wstring ConvertVersionToString(UINT64 version)
#include "GeneralUtil.hpp"
#include <string>
#include <codecvt>
#include <iostream>
using namespace Win7MsixInstallerLib;
TRACELOGGING_DEFINE_PROVIDER(
g_MsixTraceLoggingProvider,
"MsixTraceLoggingProvider",
(0x033321d3, 0xd599, 0x48e0, 0x86, 0x8d, 0xc5, 0x9f, 0x15, 0x90, 0x16, 0x37));
/// Converts a wstring from utf16 to utf8
///
/// @param utf16string - A utf16 wstring
/// @return utf8 string
std::string Win7MsixInstallerLib_utf16_to_utf8(const std::wstring& utf16string)
{
auto converted = std::wstring_convert<std::codecvt_utf8<wchar_t>>{}.to_bytes(utf16string.data());
std::string result(converted.begin(), converted.end());
return result;
}
/// Helper to convert version number to a version string of the form a.b.c.d
///
/// @param version - version number
/// @return a.b.c.d string representation of version
std::wstring Win7MsixInstallerLib_ConvertVersionToString(UINT64 version)
{
return std::to_wstring((version >> 0x30) & 0xFFFF) + L"."
+ std::to_wstring((version >> 0x20) & 0xFFFF) + L"."
@ -26,32 +32,16 @@ std::wstring ConvertVersionToString(UINT64 version)
+ std::to_wstring((version) & 0xFFFF);
}
std::wstring GetStringResource(UINT resourceId)
{
HMODULE instance = GetModuleHandle(nullptr);
WCHAR buffer[MAX_PATH] = L"";
int loadStringRet = LoadStringW(instance, resourceId, buffer, ARRAYSIZE(buffer));
if (loadStringRet <= 0)
{
return std::wstring(L"Failed to load string resource");
}
std::wstring stringResource(buffer);
return stringResource;
}
std::wstring GetFamilyNameFromFullName(const std::wstring& fullName)
std::wstring Win7MsixInstallerLib_GetFamilyNameFromFullName(const std::wstring& fullName)
{
return fullName.substr(0, fullName.find(L"_")) + fullName.substr(fullName.find_last_of(L"_"));
}
bool CaseInsensitiveEquals(const std::wstring& left, const std::wstring& right)
{
return (_wcsicmp(left.c_str(), right.c_str()) == 0);
}
}
bool Win7MsixInstallerLib_CaseInsensitiveEquals(const std::wstring& left, const std::wstring& right)
{
return (_wcsicmp(left.c_str(), right.c_str()) == 0);
}
HRESULT GetAttributeValueFromElement(IMsixElement * element, const std::wstring attributeName, std::wstring & attributeValue)
{
Text<wchar_t> textValue;
@ -62,13 +52,13 @@ HRESULT GetAttributeValueFromElement(IMsixElement * element, const std::wstring
}
return S_OK;
}
std::wstring GuidFromManifestId(std::wstring id)
{
return L"{" + id + L"}";
}
}
std::wstring GuidFromManifestId(std::wstring id)
{
return L"{" + id + L"}";
}
HRESULT FileExists(std::wstring file, _Out_ bool &exists)
{
DWORD fileAttributes = GetFileAttributesW(file.c_str());

Просмотреть файл

@ -0,0 +1,242 @@
#pragma once
#include <windows.h>
#include "AppxPackaging.hpp"
#include <TraceLoggingProvider.h>
#include <winmeta.h>
#include <string.h>
TRACELOGGING_DECLARE_PROVIDER(g_MsixTraceLoggingProvider);
// Definition of function to return error if failed
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define RETURN_IF_FAILED(a) \
{ \
HRESULT __hr = a; \
if (FAILED(__hr)) \
{ \
TraceLoggingWrite(g_MsixTraceLoggingProvider, \
"RETURN_IF_FAILED", \
TraceLoggingLevel(WINEVENT_LEVEL_ERROR), \
TraceLoggingValue(#a, "Code"), \
TraceLoggingHResult(__hr, "HR"), \
TraceLoggingUInt32(__LINE__, "Line"), \
TraceLoggingValue(__FILENAME__, "Filename")); \
return __hr; \
} \
}
//
// Converts a wstring from utf16 to utf8
//
// Parameters:
// utf16string - A utf16 wstring
//
std::string Win7MsixInstallerLib_utf16_to_utf8(const std::wstring& utf16string);
// Helper to convert version number to a version number string
std::wstring Win7MsixInstallerLib_ConvertVersionToString(UINT64 version);
//
// A designated memory allocator
//
// Parameters:
// cb - The size of memory
//
inline LPVOID STDMETHODCALLTYPE Win7MsixInstallerLib_MyAllocate(SIZE_T cb) { return std::malloc(cb); }
//
// A designated memory freeing method
//
// Parameters:
// pv - A pointer to the file to release
//
inline void STDMETHODCALLTYPE Win7MsixInstallerLib_MyFree(LPVOID pv) { std::free(pv); }
/// Converts a packageFullName (i.e. examplePackageName_1.0.0.0_x64_resourceId_8wekyb3d8bbwe)
/// into a packageFamilyName (i.e. examplePackageName_8wekyb3d8bbwe)
///
/// @param fullName - the packageFullName, assumed to be properly formatted and not validated.
/// @return packageFamilyName for the packageFullName
std::wstring Win7MsixInstallerLib_GetFamilyNameFromFullName(const std::wstring& fullName);
/// Determines if two strings are case-insensitive equals
///
/// @param left - one of the two strings
/// @param right - the other of the two strings
/// @return true if the strings equal, false otherwise
bool Win7MsixInstallerLib_CaseInsensitiveEquals(const std::wstring& left, const std::wstring& right);
namespace Win7MsixInstallerLib
{
//
// Stripped down ComPtr class provided for those platforms that do not already have a ComPtr class.
//
template <class T>
class ComPtr
{
public:
// default ctor
ComPtr() = default;
ComPtr(T* ptr) : m_ptr(ptr) { InternalAddRef(); }
~ComPtr() { InternalRelease(); }
inline T* operator->() const { return m_ptr; }
inline T* Get() const { return m_ptr; }
inline T** operator&()
{
InternalRelease();
return &m_ptr;
}
inline T* operator=(__in_opt T* ptr) throw()
{
InternalRelease();
m_ptr = ptr;
InternalAddRef();
return m_ptr;
}
void Release() { InternalRelease(); }
protected:
T * m_ptr = nullptr;
inline void InternalAddRef() { if (m_ptr) { m_ptr->AddRef(); } }
inline void InternalRelease()
{
T* temp = m_ptr;
if (temp)
{
m_ptr = nullptr;
temp->Release();
}
}
};
template <class T>
class AutoPtr
{
public:
AutoPtr() = default;
AutoPtr(T * ptr) : m_ptr(ptr) {}
~AutoPtr() { delete m_ptr; }
void Free() { delete m_ptr; m_ptr = 0; }
inline T* Detach()
{
T* old = m_ptr;
m_ptr = 0;
return old;
}
inline operator const T* () const
{
return (T*)m_ptr;
}
inline operator T* ()
{
return (T*)m_ptr;
}
inline const T& operator*() const
{
return *m_ptr;
}
inline T& operator*()
{
return *m_ptr;
}
inline const T* Get() const
{
return m_ptr;
}
inline T* Get()
{
return m_ptr;
}
inline T** operator&()
{
return &m_ptr;
}
inline T** AddressOf()
{
return &m_ptr;
}
inline T** FreeAndAddressOf()
{
Free();
return &m_ptr;
}
inline const T* operator->() const
{
return m_ptr;
}
inline T* operator->()
{
return m_ptr;
}
inline T* operator=(T* ptr)
{
if (m_ptr != ptr)
{
delete m_ptr;
m_ptr = ptr;
}
return m_ptr;
}
protected:
T* m_ptr = nullptr;
};
//
// Helper class to free string buffers obtained from the packaging APIs.
//
template<typename T>
class Text
{
public:
T** operator&() { return &content; }
~Text() { Cleanup(); }
T* Get() { return content; }
T* content = nullptr;
protected:
void Cleanup() { if (content) { Win7MsixInstallerLib_MyFree(content); content = nullptr; } }
};
//
// Helper class to free string buffers created using OLE memory allocator.
//
template<typename T>
class TextOle
{
public:
T** operator&() { return &content; }
~TextOle() { Cleanup(); }
T* Get() { return content; }
T* content = nullptr;
protected:
void Cleanup() { if (content) { CoTaskMemFree(content); content = nullptr; } }
};
}
HRESULT GetAttributeValueFromElement(IMsixElement* element, std::wstring attributeName, std::wstring& attributeValue);
/// The manifest ID is missing the curly braces;
/// This adds the curly braces to convert it into a proper Guid form.
std::wstring GuidFromManifestId(std::wstring id);
HRESULT FileExists(std::wstring file, _Out_ bool &exists);

Просмотреть файл

@ -0,0 +1,163 @@
#include "PackageManager.hpp"
#include "MsixRequest.hpp"
#include "Constants.hpp"
#include "PopulatePackageInfo.hpp"
#include <experimental/filesystem>
#include <thread>
using namespace std;
using namespace Win7MsixInstallerLib;
PackageManager::PackageManager()
{
}
shared_ptr<IMsixResponse> PackageManager::AddPackageAsync(const wstring & packageFilePath, DeploymentOptions options, function<void(const IMsixResponse&)> callback)
{
MsixRequest * impl;
auto res = (MsixRequest::Make(OperationType::Add, packageFilePath, L"", MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &impl));
if (FAILED(res))
{
return nullptr;
}
if (callback != nullptr)
{
impl->GetMsixResponse()->SetCallback(callback);
}
auto t = thread([&impl]() {
impl->ProcessRequest();
delete impl;
impl = nullptr;
});
t.detach();
return impl->GetMsixResponse();
}
HRESULT PackageManager::AddPackage(const wstring & packageFilePath, DeploymentOptions options)
{
AutoPtr<MsixRequest> impl;
auto res = (MsixRequest::Make(OperationType::Add, packageFilePath, L"", MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &impl));
if (FAILED(res))
{
return res;
}
return impl->ProcessRequest();
}
shared_ptr<IMsixResponse> PackageManager::RemovePackageAsync(const wstring & packageFullName, function<void(const IMsixResponse&)> callback)
{
MsixRequest* impl;
auto res = (MsixRequest::Make(OperationType::Remove, L"", packageFullName, MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &impl));
if (FAILED(res))
{
return nullptr;
}
if (callback != nullptr)
{
impl->GetMsixResponse()->SetCallback(callback);
}
thread t([&impl]() {
impl->ProcessRequest();
impl = nullptr;
});
t.detach();
return impl->GetMsixResponse();
}
HRESULT PackageManager::RemovePackage(const wstring & packageFullName)
{
AutoPtr<MsixRequest> impl;
auto res = (MsixRequest::Make(OperationType::Remove, L"", packageFullName, MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &impl));
if (FAILED(res))
{
return res;
}
return impl->ProcessRequest();
}
shared_ptr<IInstalledPackage> PackageManager::GetPackageInfo(const wstring & msix7Directory, const wstring & directoryPath)
{
std::shared_ptr<InstalledPackage> packageInfo;
auto res = PopulatePackageInfo::GetPackageInfoFromManifest(directoryPath.c_str(), MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &packageInfo);
if (FAILED(res))
{
return nullptr;
}
return std::dynamic_pointer_cast<IInstalledPackage>(packageInfo);
}
shared_ptr<IInstalledPackage> PackageManager::FindPackage(const wstring & packageFullName)
{
auto filemapping = FilePathMappings::GetInstance();
auto res = filemapping.GetInitializationResult();
if (FAILED(res))
{
return nullptr;
}
wstring msix7Directory = filemapping.GetMsix7Directory();
wstring packageDirectoryPath = msix7Directory + packageFullName;
auto package = GetPackageInfo(msix7Directory, packageDirectoryPath);
return package;
}
shared_ptr<IInstalledPackage> PackageManager::FindPackageByFamilyName(const wstring & packageFamilyName)
{
auto filemapping = FilePathMappings::GetInstance();
auto res = filemapping.GetInitializationResult();
if (FAILED(res))
{
return nullptr;
}
auto msix7Directory = filemapping.GetMsix7Directory();
for (auto& p : experimental::filesystem::directory_iterator(msix7Directory))
{
auto installedAppFamilyName = Win7MsixInstallerLib_GetFamilyNameFromFullName(p.path().filename());
if (Win7MsixInstallerLib_CaseInsensitiveEquals(installedAppFamilyName, packageFamilyName))
{
return GetPackageInfo(msix7Directory, p.path());
}
}
return nullptr;
}
unique_ptr<vector<shared_ptr<IInstalledPackage>>> PackageManager::FindPackages()
{
auto packages = std::make_unique<std::vector<shared_ptr<IInstalledPackage>>>();
auto filemapping = FilePathMappings::GetInstance();
auto res = filemapping.GetInitializationResult();
if (FAILED(res))
{
return packages;
}
auto msix7Directory = filemapping.GetMsix7Directory();
for (auto& p : experimental::filesystem::directory_iterator(msix7Directory))
{
auto packageInfo = GetPackageInfo(msix7Directory, p.path());
if (packageInfo != nullptr)
{
packages->push_back(packageInfo);
}
}
return packages;
}
shared_ptr<IPackage> PackageManager::GetMsixPackageInfo(const wstring & msixFullPath)
{
auto filemapping = FilePathMappings::GetInstance();
auto res = filemapping.GetInitializationResult();
if (FAILED(res))
{
return nullptr;
}
shared_ptr<Package> packageInfo;
res = PopulatePackageInfo::GetPackageInfoFromPackage(msixFullPath.c_str(), MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &packageInfo);
if (FAILED(res))
{
return nullptr;
}
return dynamic_pointer_cast<IPackage>(packageInfo);
}

Просмотреть файл

@ -0,0 +1,23 @@
#pragma once
#include "inc/IPackageManager.hpp"
#include "inc/IPackage.hpp"
namespace Win7MsixInstallerLib {
class PackageManager :
public IPackageManager
{
public:
PackageManager();
std::shared_ptr<IMsixResponse> AddPackageAsync(const std::wstring & packageFilePath, DeploymentOptions options, std::function<void(const IMsixResponse&)> callback = nullptr) override;
HRESULT AddPackage(const std::wstring & packageFilePath, DeploymentOptions options) override;
std::shared_ptr<IMsixResponse> RemovePackageAsync(const std::wstring & packageFullName, std::function<void(const IMsixResponse&)> callback = nullptr) override;
HRESULT RemovePackage(const std::wstring & packageFullName) override;
std::shared_ptr<IInstalledPackage> FindPackage(const std::wstring & packageFullName) override;
std::shared_ptr<IInstalledPackage> FindPackageByFamilyName(const std::wstring & packageFamilyName) override;
std::unique_ptr<std::vector<std::shared_ptr<IInstalledPackage>>> FindPackages() override;
std::shared_ptr<IPackage> GetMsixPackageInfo(const std::wstring & msixFullPath) override;
private:
std::shared_ptr<IInstalledPackage> GetPackageInfo(const std::wstring & msix7Directory, const std::wstring & directoryPath);
};
}

Просмотреть файл

@ -0,0 +1,10 @@
#include "Win7MSIXInstallerActions.hpp"
#include "PackageManager.hpp"
using namespace Win7MsixInstallerLib;
HRESULT Win7MsixInstallerLib_CreatePackageManager(Win7MsixInstallerLib::IPackageManager** packageManager)
{
*packageManager = new PackageManager();
return S_OK;
}

Просмотреть файл

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{46BE19BD-72E0-4452-9919-33A1F8A5F064}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Win7MSIXInstaller</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>Win7MSIXInstallerLib</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>No</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>No</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>No</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>No</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>Win7MsixInstallerLib_EXPORTS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;..\Win7MSIXInstaller;inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>Version.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "$(ProjectDir)MSIXPackaging\x86\Debug\msix.*" "$(OutDir)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>Win7MsixInstallerLib_EXPORTS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;..\Win7MSIXInstaller;inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>Version.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "..\..\..\.vs\bin\msix.dll" "$(OutDir)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>Win7MsixInstallerLib_EXPORTS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;..\Win7MSIXInstaller;inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>Version.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "$(ProjectDir)MSIXPackaging\x86\msix.dll" "$(OutDir)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>Win7MsixInstallerLib_EXPORTS;WIN32;NDEBUG;_CONSOLE;WIN7MSIXINSTALLER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;..\Win7MSIXInstaller;inc;..\..\..\.vs\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\.vs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalOptions>comctl32.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>Version.lib;msix.lib;msi.lib;comctl32.lib;gdiplus.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D "..\..\..\.vs\bin\msix.dll" "$(OutDir)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\Win7MSIXInstaller\AddRemovePrograms.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\ComInterface.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\ComServer.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\Constants.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\ErrorHandler.hpp" />
<ClInclude Include="inc\IMsixResponse.hpp" />
<ClInclude Include="inc\DeploymentOptions.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\Extractor.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\FileTypeAssociation.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\FootprintFiles.hpp" />
<ClInclude Include="inc\IPackageManager.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\InstallComplete.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\MsixRequest.hpp" />
<ClInclude Include="GeneralUtil.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\FilePaths.hpp" />
<ClInclude Include="inc\IPackage.hpp" />
<ClInclude Include="inc\Win7MSIXInstallerActions.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\IPackageHandler.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\MsixResponse.hpp" />
<ClInclude Include="PackageManager.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\Package.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\PopulatePackageInfo.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\ProcessPotentialUpdate.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\Protocol.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\RegistryDevirtualizer.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\RegistryKey.hpp" />
<ClInclude Include="..\Win7MSIXInstaller\StartMenuLink.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Win7MSIXInstaller\ComInterface.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\ComServer.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\ErrorHandler.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\Extractor.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\FilePaths.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\FileTypeAssociation.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\InstallComplete.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\MsixRequest.cpp" />
<ClCompile Include="GeneralUtil.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\MsixResponse.cpp" />
<ClCompile Include="PackageManager.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\Package.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\PopulatePackageInfo.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\ProcessPotentialUpdate.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\Protocol.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\RegistryDevirtualizer.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\RegistryKey.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\AddRemovePrograms.cpp" />
<ClCompile Include="..\Win7MSIXInstaller\StartMenuLink.cpp" />
<ClCompile Include="Win7MSIXInstallerActions.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Просмотреть файл

@ -0,0 +1,7 @@
#pragma once
enum DeploymentOptions
{
None = 0,
//ForceUpdateFromAnyVersion = 262144
};

Просмотреть файл

@ -0,0 +1,27 @@
#pragma once
#include <functional>
#include <windows.h>
namespace Win7MsixInstallerLib {
enum InstallationStep {
InstallationStepUnknown,
InstallationStepStarted,
InstallationStepGetPackageInformation,
InstallationStepExtraction,
InstallationStepCompleted,
InstallationStepError,
//can be extend for future scenarios.
};
class IMsixResponse
{
public:
virtual void SetCallback(std::function<void(const IMsixResponse &)> callback) = 0;
virtual inline float GetPercentage() const = 0;
virtual inline InstallationStep GetStatus() const = 0;
virtual inline HRESULT GetHResultTextCode() const = 0;
virtual inline std::wstring GetTextStatus() const = 0;
virtual inline void CancelRequest() = 0;
};
}

Просмотреть файл

@ -0,0 +1,30 @@
#pragma once
#include <Windows.h>
namespace Win7MsixInstallerLib {
class IPackage {
public:
virtual unsigned long long GetVersionNumber() = 0;
virtual std::wstring GetVersion() = 0;
virtual std::wstring GetPublisherDisplayName() = 0;
virtual std::wstring GetPackageFullName() = 0;
virtual std::wstring GetPackageFamilyName() = 0;
virtual std::wstring GetDisplayName() = 0;
virtual std::wstring GetId() = 0;
virtual std::unique_ptr<IStream> GetLogo() = 0;
virtual ~IPackage() {}
protected:
IPackage() {}
};
class IInstalledPackage : public IPackage
{
public:
virtual std::wstring GetFullExecutableFilePath() = 0;
virtual std::wstring GetInstalledLocation() = 0;
virtual ~IInstalledPackage() {}
protected:
IInstalledPackage() {}
};
}

Просмотреть файл

@ -0,0 +1,23 @@
#pragma once
#include <string>
#include <vector>
#include <functional>
#include "IMsixResponse.hpp"
#include "IPackage.hpp"
#include "DeploymentOptions.hpp"
namespace Win7MsixInstallerLib {
class IPackageManager
{
public:
virtual std::shared_ptr<IMsixResponse> AddPackageAsync(const std::wstring & packageFilePath, DeploymentOptions options, std::function<void(const IMsixResponse&)> callback = nullptr) = 0;
virtual HRESULT AddPackage(const std::wstring & packageFilePath, DeploymentOptions options) = 0;
virtual std::shared_ptr<IMsixResponse> RemovePackageAsync(const std::wstring & packageFullName, std::function<void(const IMsixResponse&)> callback = nullptr) = 0;
virtual HRESULT RemovePackage(const std::wstring & packageFullName) = 0;
virtual std::shared_ptr<IInstalledPackage> FindPackage(const std::wstring & packageFamilyName) = 0;
virtual std::shared_ptr<IInstalledPackage> FindPackageByFamilyName(const std::wstring & packageFamilyName) = 0;
virtual std::unique_ptr<std::vector<std::shared_ptr<IInstalledPackage>>> FindPackages() = 0;
virtual std::shared_ptr<IPackage> GetMsixPackageInfo(const std::wstring & msixFullPath) = 0;
};
}

Просмотреть файл

@ -0,0 +1,4 @@
#pragma once
#include "IPackageManager.hpp"
extern "C" HRESULT Win7MsixInstallerLib_CreatePackageManager(Win7MsixInstallerLib::IPackageManager** packageManager);

Просмотреть файл

@ -426,7 +426,7 @@ namespace MSIX
return IsAuthenticodeTrustedChain(certChainContext.get());
}
static bool GetPublisherName(/*in*/byte* signatureBuffer, /*in*/ ULONG cbSignatureBuffer, /*inout*/ std::string& publisher)
static bool GetPublisherDisplayName(/*in*/byte* signatureBuffer, /*in*/ ULONG cbSignatureBuffer, /*inout*/ std::string& publisher)
{
unique_cert_context certificateContext(GetCertContext(signatureBuffer, cbSignatureBuffer, true));
if (certificateContext.get() == NULL)
@ -606,7 +606,7 @@ namespace MSIX
"Unknown signature origin");
ThrowErrorIfNot(Error::SignatureInvalid,
GetPublisherName(p7s, p7sSize, publisher) == true,
GetPublisherDisplayName(p7s, p7sSize, publisher) == true,
"Could not retrieve publisher name");
return true;