250 строки
13 KiB
C++
250 строки
13 KiB
C++
#include "GeneralUtil.hpp"
|
|
#include "MsixRequest.hpp"
|
|
|
|
#include <string>
|
|
#include <map>
|
|
#include <algorithm>
|
|
#include <utility>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <functional>
|
|
#include <thread>
|
|
|
|
#include "FootprintFiles.hpp"
|
|
#include "FilePaths.hpp"
|
|
#include <cstdio>
|
|
#include <experimental/filesystem> // C++-standard header file name
|
|
#include <filesystem> // Microsoft-specific implementation header file name
|
|
#include <TraceLoggingProvider.h>
|
|
#include "MsixTraceLoggingProvider.hpp"
|
|
|
|
// handlers
|
|
#include "Extractor.hpp"
|
|
#include "StartMenuLink.hpp"
|
|
#include "AddRemovePrograms.hpp"
|
|
#include "PopulatePackageInfo.hpp"
|
|
#include "Protocol.hpp"
|
|
#include "ComInterface.hpp"
|
|
#include "ComServer.hpp"
|
|
#include "StartupTask.hpp"
|
|
#include "FileTypeAssociation.hpp"
|
|
#include "ProcessPotentialUpdate.hpp"
|
|
#include "InstallComplete.hpp"
|
|
#include "ErrorHandler.hpp"
|
|
#include "ValidateArchitecture.hpp"
|
|
#include "ValidateTargetDeviceFamily.hpp"
|
|
#include "PrepareDevirtualizedRegistry.hpp"
|
|
#include "WriteDevirtualizedRegistry.hpp"
|
|
#include "FirewallRules.hpp"
|
|
#include "AutoPlay.hpp"
|
|
#include "VirtualFileHandler.hpp"
|
|
#include "PSFScriptExecuter.hpp"
|
|
#include "AppExecutionAlias.hpp"
|
|
|
|
#include "Constants.hpp"
|
|
|
|
using namespace std;
|
|
using namespace MsixCoreLib;
|
|
|
|
enum ErrorHandlingMode
|
|
{
|
|
IgnoreAndProcessNextHandler = 0, // ignore the error and proceed with nextHandler as if the current handler were successful
|
|
ExecuteErrorHandler = 1, // go to errorHandler instead of nextHandler
|
|
ReturnError = 2, // return immediately, do not process any further handlers
|
|
};
|
|
|
|
struct AddHandlerInfo
|
|
{
|
|
CreateHandler create;
|
|
PCWSTR nextHandler;
|
|
ErrorHandlingMode errorMode;
|
|
PCWSTR errorHandler;
|
|
};
|
|
|
|
struct RemoveHandlerInfo
|
|
{
|
|
CreateHandler create;
|
|
PCWSTR nextHandler;
|
|
ErrorHandlingMode errorMode;
|
|
};
|
|
|
|
std::map<PCWSTR, AddHandlerInfo> AddHandlers =
|
|
{
|
|
//HandlerName Function to create NextHandler (on success) ErrorHandlingMode ErrorHandler (when ExecuteErrorHandler)
|
|
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, ValidateArchitecture::HandlerName, ReturnError, nullptr}},
|
|
{ValidateArchitecture::HandlerName, {ValidateArchitecture::CreateHandler, ValidateTargetDeviceFamily::HandlerName, ReturnError, nullptr}},
|
|
{ValidateTargetDeviceFamily::HandlerName, {ValidateTargetDeviceFamily::CreateHandler, ProcessPotentialUpdate::HandlerName, ReturnError, nullptr}},
|
|
{ProcessPotentialUpdate::HandlerName, {ProcessPotentialUpdate::CreateHandler, Extractor::HandlerName, ReturnError, nullptr}},
|
|
{Extractor::HandlerName, {Extractor::CreateHandler, PrepareDevirtualizedRegistry::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{PrepareDevirtualizedRegistry::HandlerName, {PrepareDevirtualizedRegistry::CreateHandler, VirtualFileHandler::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{VirtualFileHandler::HandlerName, {VirtualFileHandler::CreateHandler, WriteDevirtualizedRegistry::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{WriteDevirtualizedRegistry::HandlerName, {WriteDevirtualizedRegistry::CreateHandler, PSFScriptExecuter::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{PSFScriptExecuter::HandlerName, {PSFScriptExecuter::CreateHandler, StartMenuLink::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{StartMenuLink::HandlerName, {StartMenuLink::CreateHandler, AddRemovePrograms::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{AddRemovePrograms::HandlerName, {AddRemovePrograms::CreateHandler, Protocol::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{Protocol::HandlerName, {Protocol::CreateHandler, ComInterface::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{ComInterface::HandlerName, {ComInterface::CreateHandler, ComServer::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{ComServer::HandlerName, {ComServer::CreateHandler, StartupTask::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{StartupTask::HandlerName, {StartupTask::CreateHandler, FileTypeAssociation::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, FirewallRules::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{FirewallRules::HandlerName, {FirewallRules::CreateHandler, AutoPlay::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{AutoPlay::HandlerName, {AutoPlay::CreateHandler, AppExecutionAlias::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{AppExecutionAlias::HandlerName, {AppExecutionAlias::CreateHandler, InstallComplete::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{InstallComplete::HandlerName, {InstallComplete::CreateHandler, nullptr, ExecuteErrorHandler, ErrorHandler::HandlerName}},
|
|
{ErrorHandler::HandlerName, {ErrorHandler::CreateHandler, nullptr, ReturnError, nullptr}},
|
|
};
|
|
|
|
std::map<PCWSTR, RemoveHandlerInfo> RemoveHandlers =
|
|
{
|
|
//HandlerName Function to create NextHandler ErrorHandling
|
|
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, StartMenuLink::HandlerName, ReturnError}},
|
|
{StartMenuLink::HandlerName, {StartMenuLink::CreateHandler, AddRemovePrograms::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{AddRemovePrograms::HandlerName, {AddRemovePrograms::CreateHandler, PrepareDevirtualizedRegistry::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{PrepareDevirtualizedRegistry::HandlerName, {PrepareDevirtualizedRegistry::CreateHandler, Protocol::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{Protocol::HandlerName, {Protocol::CreateHandler, ComInterface::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{ComInterface::HandlerName, {ComInterface::CreateHandler, ComServer::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{ComServer::HandlerName, {ComServer::CreateHandler, StartupTask::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{StartupTask::HandlerName, {StartupTask::CreateHandler, FileTypeAssociation::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, FirewallRules::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{FirewallRules::HandlerName, {FirewallRules::CreateHandler, AutoPlay::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{AutoPlay::HandlerName, {AutoPlay::CreateHandler, AppExecutionAlias::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{AppExecutionAlias::HandlerName, {AppExecutionAlias::CreateHandler, VirtualFileHandler::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{VirtualFileHandler::HandlerName, {VirtualFileHandler::CreateHandler, WriteDevirtualizedRegistry::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{WriteDevirtualizedRegistry::HandlerName, {WriteDevirtualizedRegistry::CreateHandler, Extractor::HandlerName, IgnoreAndProcessNextHandler}},
|
|
{Extractor::HandlerName, {Extractor::CreateHandler, nullptr, IgnoreAndProcessNextHandler}},
|
|
};
|
|
|
|
HRESULT MsixRequest::Make(OperationType operationType, IStream * packageStream, std::wstring packageFullName, MSIX_VALIDATION_OPTION validationOption, MsixRequest ** outInstance)
|
|
{
|
|
AutoPtr<MsixRequest> instance(new MsixRequest());
|
|
if (instance == nullptr)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
instance->m_operationType = operationType;
|
|
instance->m_packageStream = packageStream;
|
|
instance->m_packageFullName = packageFullName;
|
|
instance->m_validationOptions = validationOption;
|
|
RETURN_IF_FAILED(FilePathMappings::GetInstance().GetInitializationResult());
|
|
|
|
//Set MsixResponse
|
|
instance->m_msixResponse = std::make_shared<MsixResponse>();
|
|
|
|
*outInstance = instance.Detach();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
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;
|
|
}
|
|
default:
|
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT MsixRequest::ProcessAddRequest()
|
|
{
|
|
PCWSTR currentHandlerName = PopulatePackageInfo::HandlerName;
|
|
while (currentHandlerName != nullptr)
|
|
{
|
|
TraceLoggingWrite(g_MsixTraceLoggingProvider,
|
|
"Executing handler",
|
|
TraceLoggingValue(currentHandlerName, "HandlerName"));
|
|
|
|
AddHandlerInfo currentHandler = AddHandlers[currentHandlerName];
|
|
AutoPtr<IPackageHandler> handler;
|
|
HRESULT hr = currentHandler.create(this, &handler);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = handler->ExecuteForAddRequest();
|
|
}
|
|
if (FAILED(hr) && currentHandler.errorMode != IgnoreAndProcessNextHandler)
|
|
{
|
|
m_msixResponse->SetErrorStatus(hr, L"Unable to install package. Please go to aka.ms/msix for more information.");
|
|
|
|
if (currentHandler.errorMode == ReturnError)
|
|
{
|
|
return hr;
|
|
}
|
|
currentHandlerName = currentHandler.errorHandler;
|
|
}
|
|
else
|
|
{
|
|
currentHandlerName = currentHandler.nextHandler;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT MsixRequest::ProcessRemoveRequest()
|
|
{
|
|
PCWSTR currentHandlerName = PopulatePackageInfo::HandlerName;
|
|
while (currentHandlerName != nullptr)
|
|
{
|
|
TraceLoggingWrite(g_MsixTraceLoggingProvider,
|
|
"Executing handler",
|
|
TraceLoggingValue(currentHandlerName, "HandlerName"));
|
|
|
|
RemoveHandlerInfo currentHandler = RemoveHandlers[currentHandlerName];
|
|
AutoPtr<IPackageHandler> handler;
|
|
HRESULT hr = currentHandler.create(this, &handler);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = handler->ExecuteForRemoveRequest();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
TraceLoggingWrite(g_MsixTraceLoggingProvider,
|
|
"Handler failed -- if errorMode is IgnoreAndProcessNextHandler(0), this is non-fatal",
|
|
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
|
|
TraceLoggingValue(currentHandlerName, "HandlerName"),
|
|
TraceLoggingValue(hr, "HR"),
|
|
TraceLoggingUInt32(currentHandler.errorMode, "ErrorMode"));
|
|
if (currentHandler.errorMode == ReturnError)
|
|
{
|
|
m_msixResponse->SetErrorStatus(hr, L"Failed to process add request");
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
currentHandlerName = currentHandler.nextHandler;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void MsixRequest::SetPackageInfo(std::shared_ptr<PackageBase> packageInfo)
|
|
{
|
|
m_packageInfo = packageInfo;
|
|
}
|
|
|
|
std::wstring MsixRequest::GetPackageDirectoryPath()
|
|
{
|
|
if (m_packageInfo == nullptr)
|
|
return nullptr;
|
|
|
|
return FilePathMappings::GetInstance().GetMsixCoreDirectory() + m_packageInfo->GetPackageFullName();
|
|
}
|
|
|
|
void MsixRequest::SetRegistryDevirtualizer(std::shared_ptr<RegistryDevirtualizer> registryDevirualizer)
|
|
{
|
|
m_registryDevirtualizer = registryDevirualizer;
|
|
} |