Uninstall app when Cancel button is clicked (#71)

* Uninstall when cancel is clicked

* Move Uninstall package request to MsixRequest

* remove setpackagefullname

* Move Comments to header file

* Create msixrequest and call remove for uninstall

* Pass packagename to uninstall package in case of cancel request

* Addressed PR comments

* Removed cancel check from ExecuteForAddRequest in msixrequest.cpp

* Show popup when user clicks on cancel

* Initial changes based on PR feedback

* Adding response object

* PR feedback and updated handlerinfo structure

* PR comments and updated HandlerInfo structure

* Spaces

* Added doxygen style comments, inline, casing

* Added more comments, inline methods, updates response variable names

* Inline methods, Removed extra checks
This commit is contained in:
jyvenugo 2019-04-03 16:02:21 -07:00 коммит произвёл GitHub
Родитель 1c0248a27a
Коммит e0823b3c30
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 411 добавлений и 226 удалений

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

@ -13,6 +13,11 @@ const PCWSTR AddRemovePrograms::HandlerName = L"AddRemovePrograms";
HRESULT AddRemovePrograms::ExecuteForAddRequest()
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
std::wstring packageFullName = packageInfo->GetPackageFullName();
@ -42,7 +47,7 @@ HRESULT AddRemovePrograms::ExecuteForAddRequest()
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));
std::wstring versionString(ConvertVersionToString(packageInfo->GetVersion()));
RETURN_IF_FAILED(packageKey.SetStringValue(L"DisplayVersion", versionString));
@ -52,9 +57,9 @@ HRESULT AddRemovePrograms::ExecuteForAddRequest()
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Added Uninstall key successfully",
TraceLoggingValue(packageFullName.c_str(), "packageFullName"),
TraceLoggingValue(uninstallCommand.c_str(), "uninstallString"),
TraceLoggingValue(uninstallCommand.c_str(), "uninstallString"),
TraceLoggingValue(displayName.c_str(), "displayName"),
TraceLoggingValue(directoryPath.c_str(), "installLocation"),
TraceLoggingValue(directoryPath.c_str(), "installLocation"),
TraceLoggingValue(publisherString.c_str(), "publisher"),
TraceLoggingValue(versionString.c_str(), "displayVersion"),
TraceLoggingValue(packageIconString.c_str(), "displayIcon"));

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

@ -0,0 +1,46 @@
#include <windows.h>
#include <shlobj_core.h>
#include <CommCtrl.h>
#include "GeneralUtil.hpp"
#include <TraceLoggingProvider.h>
#include "ErrorHandler.hpp"
#include "MsixRequest.hpp"
const PCWSTR ErrorHandler::HandlerName = L"ErrorHandler";
HRESULT ErrorHandler::ExecuteForAddRequest()
{
RETURN_IF_FAILED(RemovePackage(m_msixRequest->GetPackageInfo()->GetPackageFullName()));
return S_OK;
}
HRESULT ErrorHandler::RemovePackage(std::wstring packageFullName)
{
AutoPtr<MsixRequest> removePackageRequest;
RETURN_IF_FAILED(MsixRequest::Make(OperationType::Remove, Flags::NoFlags, std::wstring(), packageFullName,
MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, &removePackageRequest));
const HRESULT hrCancelRequest = removePackageRequest->ProcessRequest();
if (FAILED(hrCancelRequest))
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Failed to process cancel request",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrCancelRequest, "HR"));
}
return S_OK;
}
HRESULT ErrorHandler::CreateHandler(MsixRequest * msixRequest, IPackageHandler ** instance)
{
std::unique_ptr<ErrorHandler> localInstance(new ErrorHandler(msixRequest));
if (localInstance == nullptr)
{
return E_OUTOFMEMORY;
}
*instance = localInstance.release();
return S_OK;
}

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

@ -0,0 +1,28 @@
#pragma once
#include <windows.h>
#include <string>
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
class ErrorHandler : IPackageHandler
{
public:
HRESULT ExecuteForAddRequest();
/// Intentionally skipping implementation of ExecuteForRemoveRequest()
/// since there is no use case as of now to handle an error in case of a remove request
static const PCWSTR HandlerName;
static HRESULT CreateHandler(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
~ErrorHandler() {}
private:
MsixRequest * m_msixRequest = nullptr;
ErrorHandler() {}
ErrorHandler(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
/// Prepares and sends msixrequest to uninstall the package in case cancel button was clicked during installation
HRESULT RemovePackage(std::wstring packageFullName);
};

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

@ -105,6 +105,11 @@ HRESULT Extractor::ExtractFootprintFiles()
for (int i = 0; i < FootprintFilesCount; i++)
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
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())
@ -136,6 +141,10 @@ HRESULT Extractor::ExtractPayloadFiles()
while (hasCurrent)
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
ComPtr<IAppxFile> file;
RETURN_IF_FAILED(files->GetCurrent(&file));
@ -184,7 +193,7 @@ HRESULT Extractor::CreatePackageRoot()
HRESULT Extractor::ExecuteForAddRequest()
{
RETURN_IF_FAILED(CreatePackageRoot());
RETURN_IF_FAILED(ExtractPackage());
return S_OK;
}

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

@ -155,6 +155,11 @@ HRESULT FileTypeAssociation::ProcessFtaForAdd(Fta& fta)
bool needToProcessAnyExtensions = false;
for (auto extensionName = fta.extensions.begin(); extensionName != fta.extensions.end(); ++extensionName)
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
bool registryHasExtension = false;
RETURN_IF_FAILED(m_registryDevirtualizer->HasFTA(*extensionName, registryHasExtension));

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

@ -14,8 +14,11 @@ const PCWSTR InstallComplete::HandlerName = L"InstallComplete";
HRESULT InstallComplete::ExecuteForAddRequest()
{
AutoPtr<UI> ui;
ui->SendInstallCompleteMsg();
if (!m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
AutoPtr<UI> ui = m_msixRequest->GetUI();
ui->SendInstallCompleteMsg();
}
return S_OK;
}

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

@ -6,14 +6,15 @@
class InstallComplete : IPackageHandler
{
public:
HRESULT ExecuteForAddRequest();
/// Send install complete message to UI
HRESULT ExecuteForAddRequest();
static const PCWSTR HandlerName;
static HRESULT CreateHandler(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
~InstallComplete() {}
static const PCWSTR HandlerName;
static HRESULT CreateHandler(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
~InstallComplete() {}
private:
MsixRequest * m_msixRequest = nullptr;
MsixRequest * m_msixRequest = nullptr;
InstallComplete() {}
InstallComplete(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
InstallComplete() {}
InstallComplete(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
};

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

@ -55,12 +55,6 @@ HRESULT GetStreamFromFile(IAppxPackageReader* package, LPCWCHAR name, IStream**
return S_OK;
}
//
// PURPOSE: This compiles the information displayed on the UI when the user selects an msix
//
// hWnd: the HWND of the window to draw controls
// windowRect: the size of the window
HRESULT UI::DrawPackageInfo(HWND hWnd, RECT windowRect)
{
if (SUCCEEDED(m_loadingPackageInfoCode))
@ -95,7 +89,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
{
case WM_CREATE:
ui->LaunchButton(hWnd, windowRect);
ui->InstallButton(hWnd, windowRect);
ui->CreateCheckbox(hWnd, windowRect);
break;
case WM_PAINT:
@ -110,27 +104,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (LOWORD(wParam))
{
case IDC_INSTALLBUTTON:
{
if (!g_installed)
{
g_installed = true;
DestroyWindow(g_buttonHWnd);
ui->CreateCancelButton(hWnd, windowRect);
UpdateWindow(hWnd);
if (ui != NULL)
{
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();
}
ui->CreateProgressBar(hWnd, windowRect, ui->GetNumberOfFiles());
}
else
ShowWindow(g_progressHWnd, SW_SHOW); //Show progress bar only when install is clicked
if (ui != NULL)
{
PostQuitMessage(0);
exit(0);
}
ui->SetButtonClicked();
}
}
break;
case IDC_LAUNCHCHECKBOX:
@ -145,9 +132,16 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
}
break;
case IDC_CANCELBUTTON:
{
ui->ConfirmAppCancel();
break;
}
case IDC_LAUNCHBUTTON:
{
ui->LaunchInstalledApp();
break;
}
}
break;
case WM_INSTALLCOMPLETE_MSG:
@ -157,7 +151,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
UpdateWindow(hWnd);
ShowWindow(g_progressHWnd, SW_HIDE); //hide progress bar
ShowWindow(g_checkboxHWnd, SW_HIDE); //hide launch check box
if (g_launchCheckBoxState) {
if (g_launchCheckBoxState)
{
ui->LaunchInstalledApp(); // launch app
DestroyWindow(hWnd); // close msix app installer
}
@ -181,6 +176,30 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
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);
}
}
break;
}
case WM_CLOSE:
if (g_installed)
{
ui->ConfirmAppCancel();
}
else
{
DestroyWindow(hWnd);
}
break;
case WM_SIZE:
case WM_SIZING:
break;
@ -188,21 +207,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
PostQuitMessage(0);
exit(0);
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);
}
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
@ -211,6 +215,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
void UI::ConfirmAppCancel()
{
const int cancelResult = MessageBox(hWnd, L"Are you sure you want to cancel the install?", L"Cancel App install", MB_YESNO);
switch (cancelResult)
{
case IDYES:
m_msixRequest->GetMsixResponse()->CancelRequest();
break;
case IDNO:
break;
}
}
HRESULT UI::LaunchInstalledApp()
{
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
@ -222,7 +239,6 @@ HRESULT UI::LaunchInstalledApp()
void StartParseFile(HWND hWnd)
{
//auto result = ParseAndRun(hWnd);
int result = 0;
if (result != 0)
@ -386,13 +402,6 @@ HRESULT UI::Make(MsixRequest * msixRequest, UI ** instance)
return S_OK;
}
// FUNCTION: CreateProgressBar(HWND parentHWnd, RECT parentRect, int count)
//
// PURPOSE: Creates the progress bar
//
// parentHWnd: the HWND of the window to add the progress bar to
// parentRect: the dimensions of the parent window
// count: the number of objects to be iterated through in the progress bar
BOOL UI::CreateProgressBar(HWND parentHWnd, RECT parentRect, int count)
{
int scrollHeight = GetSystemMetrics(SM_CYVSCROLL);
@ -419,36 +428,6 @@ BOOL UI::CreateProgressBar(HWND parentHWnd, RECT parentRect, int count)
return TRUE;
}
// FUNCTION: LaunchButton(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the lower right button
//
// parentHWnd: the HWND of the window to add the button to
// parentRect: the specs of the parent window
BOOL UI::LaunchButton(HWND parentHWnd, RECT parentRect) {
LPVOID buttonPointer = nullptr;
g_buttonHWnd = CreateWindowEx(
WS_EX_LEFT, // extended window style
L"BUTTON",
L"Install", // 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_INSTALLBUTTON, // menu
reinterpret_cast<HINSTANCE>(GetWindowLongPtr(parentHWnd, GWLP_HINSTANCE)),
buttonPointer); // pointer to button
return TRUE;
}
// FUNCTION: CreateCheckbox(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the launch checkbox on the bottom left
//
// parentHWnd: the HWND of the window to add the checkbox to
// parentRect: the specs of the parent window
BOOL UI::CreateCheckbox(HWND parentHWnd, RECT parentRect)
{
g_checkboxHWnd = CreateWindowEx(
@ -470,12 +449,24 @@ BOOL UI::CreateCheckbox(HWND parentHWnd, RECT parentRect)
return TRUE;
}
// FUNCTION: CancelButton(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the lower right cancel button when install is clicked
//
// parentHWnd: the HWND of the window to add the button to
// parentRect: the specs of the parent window
BOOL UI::InstallButton(HWND parentHWnd, RECT parentRect) {
LPVOID buttonPointer = nullptr;
g_buttonHWnd = CreateWindowEx(
WS_EX_LEFT, // extended window style
L"BUTTON",
L"Install", // 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_INSTALLBUTTON, // menu
reinterpret_cast<HINSTANCE>(GetWindowLongPtr(parentHWnd, GWLP_HINSTANCE)),
buttonPointer); // pointer to button
return TRUE;
}
BOOL UI::CreateCancelButton(HWND parentHWnd, RECT parentRect)
{
LPVOID buttonPointer = nullptr;
@ -495,12 +486,6 @@ BOOL UI::CreateCancelButton(HWND parentHWnd, RECT parentRect)
return TRUE;
}
// FUNCTION: CreateLaunchButton(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the launch button on the botton right after app has been installed
//
// parentHWnd: the HWND of the window to add the checkbox to
// parentRect: the specs of the parent window
BOOL UI::CreateLaunchButton(HWND parentHWnd, RECT parentRect)
{
LPVOID buttonPointer = nullptr;
@ -520,28 +505,12 @@ BOOL UI::CreateLaunchButton(HWND parentHWnd, RECT parentRect)
return TRUE;
}
// FUNCTION: ChangeButtonText(LPARAM newMessage)
//
// PURPOSE: Changes the text of the lower right button
//
// newMessage: the message to change the button to
BOOL UI::ChangeButtonText(const std::wstring& newMessage)
{
SendMessage(g_buttonHWnd, WM_SETTEXT, NULL, reinterpret_cast<LPARAM>(newMessage.c_str()));
return ShowWindow(g_buttonHWnd, SW_SHOW);
}
BOOL UI::HideButtonWindow()
{
return ShowWindow(g_buttonHWnd, SW_HIDE);
}
// FUNCTION: ChangeText(HWND parentHWnd, std::wstring& windowText)
//
// PURPOSE: Change the text of the installation window based on the given input
//
// parentHWnd: the HWND of the window to be changed
// windowText: the text to change the window to
BOOL UI::ChangeText(HWND parentHWnd, std::wstring displayName, std::wstring messageText, IStream* logoStream)
{
PAINTSTRUCT paint;
@ -578,11 +547,6 @@ BOOL UI::ChangeText(HWND parentHWnd, std::wstring displayName, std::wstring mess
return TRUE;
}
// FUNCTION: CreateInitWindow(HINSTANCE hInstance, int nCmdShow, TCHAR windowClass[], TCHAR windowTitle[])
//
// PURPOSE: Creates the initial installation UI window
// windowClass: the class text of the window
// windowTitle: the window title
int UI::CreateInitWindow(HINSTANCE hInstance, int nCmdShow, const std::wstring& windowClass, const std::wstring& title)
{
hWnd = CreateWindow(
@ -627,4 +591,4 @@ void UI::UpdateProgressBar()
void UI::SendInstallCompleteMsg()
{
SendMessage(hWnd, WM_INSTALLCOMPLETE_MSG, NULL, NULL);
}
}

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

@ -1,33 +1,34 @@
#pragma once
// Install UI Header
// UI Functions
/// Install UI Header
/// UI Functions
#include <windows.h>
#include <string>
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
// Child window identifiers
#define IDC_LAUNCHCHECKBOX 1
#define IDC_INSTALLBUTTON 2
#define IDC_CANCELBUTTON 3
#define IDC_LAUNCHBUTTON 4
/// 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 hWnd = NULL; // parent window hwnd
/// Global variables
static HWND hWnd = NULL; /// parent window hwnd
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_installed = false;
static bool g_launchCheckBoxState = true; // launch checkbox is checked by default
class UI
{
public:
HRESULT ShowUI();
HRESULT LaunchInstalledApp();
HRESULT LaunchInstalledApp();
void ConfirmAppCancel();
static HRESULT Make(_In_ MsixRequest* msixRequest, _Out_ UI** instance);
~UI() {}
@ -51,82 +52,71 @@ private:
HRESULT ParseInfoFromPackage();
public:
HRESULT DrawPackageInfo(HWND hWnd, RECT windowRect);
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); }
// FUNCTION: CreateProgressBar(HWND parentHWnd, RECT parentRect, int count)
//
// PURPOSE: Creates the progress bar
//
// parentHWnd: the HWND of the window to add the progress bar to
// parentRect: the dimmensions of the parent window
// count: the number of objects to be iterated through in the progress bar
/// This function compiles the information displayed on the UI when the user selects an msix
///
/// @param hWnd - the HWND of the window to draw controls
/// @param windowRect - the size of the window
HRESULT DrawPackageInfo(HWND hWnd, RECT windowRect);
/// Creates the initial installation UI window
///
/// @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); }
MsixRequest* GetMsixRequest() {
return m_msixRequest;
}
/// 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);
// FUNCTION: LaunchButton(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the lower right install button
//
// parentHWnd: the HWND of the window to add the button to
// parentRect: the specs of the parent window
BOOL LaunchButton(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);
// FUNCTION: CreateCheckbox(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the launch when ready checkbox on the bottom left
//
// parentHWnd: the HWND of the window to add the checkbox to
// parentRect: the specs of the parent window
/// 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);
// FUNCTION: CreateCancelButton(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the cancel button on the bottom right corner when user clicks on install
//
// parentHWnd: the HWND of the window to add the checkbox to
// parentRect: the specs of the parent window
/// 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);
// FUNCTION: CreateLaunchButton(HWND parentHWnd, RECT parentRect)
//
// PURPOSE: Create the launch button on the botton right after app has been installed
//
// parentHWnd: the HWND of the window to add the checkbox to
// parentRect: the specs of the parent window
/// 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
BOOL CreateLaunchButton(HWND parentHWnd, RECT parentRect);
// FUNCTION: ChangeButtonText(LPARAM newMessage)
//
// PURPOSE: Changes the text of the lower right button
//
// newMessage: the message to change the button to
/// Changes the text of the lower right button
///
/// @param newMessage - the message to change the button to
BOOL ChangeButtonText(const std::wstring& newMessage);
// FUNCTION: HideButtonWindow()
//
// PURPOSE: Hides the lower right button
//
BOOL HideButtonWindow();
// FUNCTION: ChangeText(HWND parentHWnd, std::wstring& windowText)
//
// PURPOSE: Change the text of the installation window based on the given input
//
// parentHWnd: the HWND of the window to be changed
// windowText: the text to change the window to
/// 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);
// FUNCTION: UpdateProgressBar
//
// PURPOSE: Increment the progress bar one tick based on preset tick
/// Increment the progress bar one tick based on preset tick
void UpdateProgressBar();
// FUNCTION: SendInstallCompleteMsg
//
// PURPOSE: 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();
};

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

@ -29,6 +29,7 @@
#include "FileTypeAssociation.hpp"
#include "ProcessPotentialUpdate.hpp"
#include "InstallComplete.hpp"
#include "ErrorHandler.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.
@ -39,22 +40,24 @@ struct HandlerInfo
{
CreateHandler create;
PCWSTR nextHandler;
PCWSTR errorHandler;
};
std::map<PCWSTR, HandlerInfo> AddHandlers =
{
//HandlerName Function to create NextHandler
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, CreateAndShowUI::HandlerName }},
{CreateAndShowUI::HandlerName, {CreateAndShowUI::CreateHandler, ProcessPotentialUpdate::HandlerName }},
{ProcessPotentialUpdate::HandlerName, {ProcessPotentialUpdate::CreateHandler, Extractor::HandlerName }},
{Extractor::HandlerName, {Extractor::CreateHandler, StartMenuLink::HandlerName }},
{StartMenuLink::HandlerName, {StartMenuLink::CreateHandler, AddRemovePrograms::HandlerName}},
{AddRemovePrograms::HandlerName, {AddRemovePrograms::CreateHandler, Protocol::HandlerName}},
{Protocol::HandlerName, {Protocol::CreateHandler, ComInterface::HandlerName}},
{ComInterface::HandlerName, {ComInterface::CreateHandler, ComServer::HandlerName}},
{ComServer::HandlerName, {ComServer::CreateHandler, FileTypeAssociation::HandlerName}},
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, InstallComplete::HandlerName }},
{InstallComplete::HandlerName, {InstallComplete::CreateHandler, nullptr}},
//HandlerName Function to create NextHandler ErrorHandlerInfo
{PopulatePackageInfo::HandlerName, {PopulatePackageInfo::CreateHandler, CreateAndShowUI::HandlerName, ErrorHandler::HandlerName}},
{CreateAndShowUI::HandlerName, {CreateAndShowUI::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 =
@ -82,6 +85,12 @@ HRESULT MsixRequest::Make(OperationType operationType, Flags flags, std::wstring
instance->m_packageFullName = packageFullName;
instance->m_validationOptions = validationOption;
RETURN_IF_FAILED(instance->InitializeFilePathMappings());
//Set MsixResponse
AutoPtr<MsixResponse> localResponse;
RETURN_IF_FAILED(MsixResponse::Make(&localResponse));
instance->m_msixResponse = localResponse.Detach();
*outInstance = instance.release();
return S_OK;
@ -155,7 +164,7 @@ HRESULT MsixRequest::FindAllPackages()
numPackages++;
}
std::cout << numPackages << " Packages found" << std::endl;
std::cout << numPackages << " Package(s) found" << std::endl;
return S_OK;
}
@ -173,9 +182,14 @@ HRESULT MsixRequest::ProcessAddRequest()
HandlerInfo currentHandler = AddHandlers[currentHandlerName];
AutoPtr<IPackageHandler> handler;
RETURN_IF_FAILED(currentHandler.create(this, &handler));
RETURN_IF_FAILED(handler->ExecuteForAddRequest());
currentHandlerName = currentHandler.nextHandler;
if (FAILED(handler->ExecuteForAddRequest()))
{
currentHandlerName = currentHandler.errorHandler;
}
else
{
currentHandlerName = currentHandler.nextHandler;
}
}
return S_OK;
@ -222,5 +236,5 @@ void MsixRequest::SetUI(UI * ui)
void MsixRequest::SetPackageInfo(PackageInfo* packageInfo)
{
m_packageInfo = packageInfo;
m_packageInfo = packageInfo;
}

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

@ -1,6 +1,7 @@
#pragma once
#include "PackageInfo.hpp"
#include "FilePaths.hpp"
#include "MsixResponse.hpp"
class UI;
enum OperationType
@ -37,6 +38,9 @@ private:
/// Filled in by CreateAndShowUI
AutoPtr<UI> m_UI;
/// MsixResponse object populated by handlers
AutoPtr<MsixResponse> m_msixResponse;
public:
static HRESULT Make(OperationType operationType, Flags flags, std::wstring packageFilePath, std::wstring packageFullName, MSIX_VALIDATION_OPTION validationOption, MsixRequest** outInstance);
@ -51,29 +55,35 @@ public:
void SetUI(UI* ui);
// Getters
MSIX_VALIDATION_OPTION GetValidationOptions() { return m_validationOptions; }
PCWSTR GetPackageFilePath() { return m_packageFilePath.c_str(); }
PCWSTR GetPackageFullName() { return m_packageFullName.c_str(); }
FilePathMappings* GetFilePathMappings() { return &m_filePathMappings; }
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; }
bool IsQuietUX() { return (m_flags & Flags::QuietUX) == Flags::QuietUX; }
inline bool IsQuietUX() { return (m_flags & Flags::QuietUX) == Flags::QuietUX; }
bool IsRemove()
inline bool IsRemove()
{
return m_operationType == OperationType::Remove;
}
bool AllowSignatureOriginUnknown()
inline bool AllowSignatureOriginUnknown()
{
m_validationOptions = static_cast<MSIX_VALIDATION_OPTION>(m_validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN);
return true;
}
/// Retrieves the msixResponse object
///
/// @return m_msixResponse object
MsixResponse* GetMsixResponse() { return m_msixResponse; }
private:
/// FilePath Mappings maps the VFS tokens (e.g. Windows) to the actual folder on disk (e.g. C:\windows)
HRESULT InitializeFilePathMappings();
@ -90,5 +100,6 @@ private:
/// 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();
};

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

@ -0,0 +1,18 @@
#include "generalutil.hpp"
#include "MsixResponse.hpp"
HRESULT MsixResponse::Make(MsixResponse ** outInstance)
{
std::unique_ptr<MsixResponse> instance(new MsixResponse());
if (instance == nullptr)
{
return E_OUTOFMEMORY;
}
instance->m_hresultTextCode = NULL;
instance->m_textStatus = NULL;
instance->m_isInstallCancelled = false;
*outInstance = instance.release();
return S_OK;
}

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

@ -0,0 +1,70 @@
#pragma once
#include <windows.h>
#include <string>
#include "GeneralUtil.hpp"
/// The response class tracks the response state of the msix deploy operation
/// (if the operation was cancelled, progress bar updates)
class MsixResponse
{
private:
/// Variable used to indicate if add package request was cancelled during installation
bool m_isInstallCancelled = false;
/// HResult to be populated by handlers in the msix response
HRESULT m_hresultTextCode;
/// Detailed text status of the msix response
PCWSTR m_textStatus;
public:
static HRESULT Make(MsixResponse** outInstance);
/// Method used to return the status of the cancel button
///
/// @return variable indicating the state of cancel button
bool GetIsInstallCancelled()
{
return m_isInstallCancelled;
}
/// Method used to set the status of the cancel button if 'Cancel' is clicked
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()
{
return m_hresultTextCode;
}
/// Sets the detailed text status in the msix response object
///
/// @param textStatus - the textStatus to be set
inline void SetTextStatus(PCWSTR textStatus)
{
m_textStatus = textStatus;
}
/// Returns the detailed text status as set in the msix response object
///
/// @return textStatus in the msix response
inline PCWSTR GetTextStatus()
{
return m_textStatus;
}
};

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

@ -82,6 +82,11 @@ HRESULT Protocol::ParseManifest()
RETURN_IF_FAILED(extensionEnum->GetHasCurrent(&hasCurrent));
while (hasCurrent)
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
ComPtr<IMsixElement> extensionElement;
RETURN_IF_FAILED(extensionEnum->GetCurrent(&extensionElement));
Text<wchar_t> extensionCategory;

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

@ -46,6 +46,10 @@ HRESULT StartMenuLink::CreateLink(PCWSTR targetFilePath, PCWSTR linkFilePath, PC
HRESULT StartMenuLink::ExecuteForAddRequest()
{
if (m_msixRequest->GetMsixResponse()->GetIsInstallCancelled())
{
return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
}
PackageInfo* packageInfo = m_msixRequest->GetPackageInfo();
std::wstring filePath = m_msixRequest->GetFilePathMappings()->GetMap()[L"Common Programs"] + L"\\" + packageInfo->GetDisplayName() + L".lnk";

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

@ -187,6 +187,8 @@
<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" />
@ -211,12 +213,14 @@
<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="InstallUI.cpp" />
<ClCompile Include="MsixResponse.cpp" />
<ClCompile Include="PackageInfo.cpp" />
<ClCompile Include="ProcessPotentialUpdate.cpp" />
<ClCompile Include="Protocol.cpp" />
@ -233,7 +237,6 @@
<ResourceCompile Include="Win7MSIXInstaller.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="ico00001.ico" />
<Image Include="icon1.ico" />
<Image Include="icon2.ico" />
</ItemGroup>

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

@ -84,6 +84,12 @@
<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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Win7MSIXInstaller.cpp">
@ -140,6 +146,12 @@
<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>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Win7MSIXInstaller.rc">
@ -153,8 +165,5 @@
<Image Include="icon2.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="ico00001.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

Двоичные данные
preview/Win7Msix/Win7MSIXInstaller/ico00001.ico

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 44 KiB