PowerToys/installer/PowerToysSetupCustomActions/CustomAction.cpp

1124 lines
34 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "resource.h"
#include "RcResource.h"
#include <ProjectTelemetry.h>
#include <spdlog/sinks/base_sink.h>
#include "../../src/common/logger/logger.h"
#include "../../src/common/utils/gpo.h"
#include "../../src/common/utils/MsiUtils.h"
#include "../../src/common/utils/modulesRegistry.h"
#include "../../src/common/updating/installer.h"
#include "../../src/common/version/version.h"
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Management.Deployment.h>
#include <wtsapi32.h>
#include <processthreadsapi.h>
#include <UserEnv.h>
#include <winnt.h>
using namespace std;
HINSTANCE DLL_HANDLE = nullptr;
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToysInstaller",
// {e1d8165d-5cb6-5c74-3b51-bdfbfe4f7a3b}
(0xe1d8165d, 0x5cb6, 0x5c74, 0x3b, 0x51, 0xbd, 0xfb, 0xfe, 0x4f, 0x7a, 0x3b),
TraceLoggingOptionProjectTelemetry());
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
{
DWORD len = 0;
wchar_t _[1];
MsiGetPropertyW(hInstall, L"CustomActionData", _, &len);
len += 1;
installationDir.resize(len);
HRESULT hr = MsiGetPropertyW(hInstall, L"CustomActionData", installationDir.data(), &len);
if (installationDir.length())
{
installationDir.resize(installationDir.length() - 1);
}
ExitOnFailure(hr, "Failed to get INSTALLFOLDER property.");
LExit:
return hr;
}
BOOL IsLocalSystem()
{
HANDLE hToken;
UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES];
PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser;
ULONG cbTokenUser;
SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
PSID pSystemSid;
BOOL bSystem;
// open process token
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY,
&hToken))
return FALSE;
// retrieve user SID
if (!GetTokenInformation(hToken, TokenUser, pTokenUser,
sizeof(bTokenUser), &cbTokenUser))
{
CloseHandle(hToken);
return FALSE;
}
CloseHandle(hToken);
// allocate LocalSystem well-known SID
if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
return FALSE;
// compare the user SID from the token with the LocalSystem SID
bSystem = EqualSid(pTokenUser->User.Sid, pSystemSid);
FreeSid(pSystemSid);
return bSystem;
}
BOOL ImpersonateLoggedInUserAndDoSomething(std::function<bool(HANDLE userToken)> action)
{
HRESULT hr = S_OK;
HANDLE hUserToken = NULL;
DWORD dwSessionId;
ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId);
auto rv = WTSQueryUserToken(dwSessionId, &hUserToken);
if (rv == 0)
{
hr = E_ABORT;
ExitOnFailure(hr, "Failed to query user token");
}
HANDLE hUserTokenDup;
if (DuplicateTokenEx(hUserToken, TOKEN_ALL_ACCESS, NULL, SECURITY_IMPERSONATION_LEVEL::SecurityImpersonation, TOKEN_TYPE::TokenPrimary, &hUserTokenDup) == 0)
{
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
hr = E_ABORT;
ExitOnFailure(hr, "Failed to duplicate user token");
}
if (ImpersonateLoggedOnUser(hUserTokenDup))
{
if (!action(hUserTokenDup))
{
hr = E_ABORT;
ExitOnFailure(hr, "Failed to execute action");
}
RevertToSelf();
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
}
else
{
hr = E_ABORT;
ExitOnFailure(hr, "Failed to duplicate user token");
}
LExit:
return SUCCEEDED(hr);
}
UINT __stdcall LaunchPowerToysCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder, path, args;
std::wstring commandLine;
hr = WcaInitialize(hInstall, "LaunchPowerToys");
ExitOnFailure(hr, "Failed to initialize");
hr = getInstallFolder(hInstall, installationFolder);
ExitOnFailure(hr, "Failed to get installFolder.");
path = installationFolder;
path += L"\\PowerToys.exe";
args = L"--dont-elevate";
commandLine = L"\"" + path + L"\" ";
commandLine += args;
BOOL isSystemUser = IsLocalSystem();
if (isSystemUser) {
auto action = [&commandLine](HANDLE userToken) {
STARTUPINFO startupInfo{ .cb = sizeof(STARTUPINFO), .wShowWindow = SW_SHOWNORMAL };
PROCESS_INFORMATION processInformation;
PVOID lpEnvironment = NULL;
CreateEnvironmentBlock(&lpEnvironment, userToken, FALSE);
CreateProcessAsUser(
userToken,
NULL,
commandLine.data(),
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE | CREATE_UNICODE_ENVIRONMENT,
lpEnvironment,
NULL,
&startupInfo,
&processInformation);
if (!CloseHandle(processInformation.hProcess))
{
return false;
}
if (!CloseHandle(processInformation.hThread))
{
return false;
}
return true;
};
if (!ImpersonateLoggedInUserAndDoSomething(action))
{
hr = E_ABORT;
ExitOnFailure(hr, "ImpersonateLoggedInUserAndDoSomething failed");
}
}
else
{
STARTUPINFO startupInfo{ .cb = sizeof(STARTUPINFO), .wShowWindow = SW_SHOWNORMAL };
PROCESS_INFORMATION processInformation;
// Start the resizer
CreateProcess(
NULL,
commandLine.data(),
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&startupInfo,
&processInformation);
if (!CloseHandle(processInformation.hProcess))
{
hr = E_ABORT;
ExitOnFailure(hr, "Failed to close process handle");
}
if (!CloseHandle(processInformation.hThread))
{
hr = E_ABORT;
ExitOnFailure(hr, "Failed to close thread handle");
}
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall CheckGPOCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
hr = WcaInitialize(hInstall, "CheckGPOCA");
ExitOnFailure(hr, "Failed to initialize");
LPWSTR currentScope = nullptr;
hr = WcaGetProperty(L"InstallScope", &currentScope);
if (std::wstring{ currentScope } == L"perUser")
{
if (powertoys_gpo::getDisablePerUserInstallationValue() == powertoys_gpo::gpo_rule_configured_enabled)
{
PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiRecordSetString(hRecord, 0, TEXT("The system administrator has disabled per-user installation."));
MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
hr = E_ABORT;
}
}
LExit:
UINT er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
bool failedToApply = false;
hr = WcaInitialize(hInstall, "ApplyModulesRegistryChangeSets");
ExitOnFailure(hr, "Failed to initialize");
hr = getInstallFolder(hInstall, installationFolder);
2021-10-27 17:39:25 +08:00
ExitOnFailure(hr, "Failed to get installFolder.");
for (const auto& changeSet : getAllOnByDefaultModulesChangeSets(installationFolder))
{
if (!changeSet.apply())
{
Logger::error(L"Couldn't apply registry changeSet");
failedToApply = true;
}
}
if (!failedToApply)
{
Logger::info(L"All registry changeSets applied successfully");
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
hr = WcaInitialize(hInstall, "UndoModulesRegistryChangeSets"); // original func name is too long
ExitOnFailure(hr, "Failed to initialize");
hr = getInstallFolder(hInstall, installationFolder);
2021-10-27 17:39:25 +08:00
ExitOnFailure(hr, "Failed to get installFolder.");
for (const auto& changeSet : getAllModulesChangeSets(installationFolder))
{
changeSet.unApply();
}
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
ExitOnFailure(hr, "Failed to extract msix");
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall InstallEmbeddedMSIXCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "InstallEmbeddedMSIXCA");
ExitOnFailure(hr, "Failed to initialize");
if (auto msix = RcResource::create(IDR_BIN_MSIX_HELLO_PACKAGE, L"BIN", DLL_HANDLE))
{
Logger::info(L"Extracted MSIX");
// TODO: Use to activate embedded MSIX
const auto msix_path = std::filesystem::temp_directory_path() / "hello_package.msix";
if (!msix->saveAsFile(msix_path))
{
ExitOnFailure(hr, "Failed to save msix");
}
Logger::info(L"Saved MSIX");
using namespace winrt::Windows::Management::Deployment;
using namespace winrt::Windows::Foundation;
Uri msix_uri{ msix_path.wstring() };
PackageManager pm;
auto result = pm.AddPackageAsync(msix_uri, nullptr, DeploymentOptions::None).get();
if (!result)
{
ExitOnFailure(hr, "Failed to AddPackage");
}
Logger::info(L"MSIX[s] were installed!");
}
else
{
ExitOnFailure(hr, "Failed to extract msix");
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall UninstallEmbeddedMSIXCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
using namespace winrt::Windows::Management::Deployment;
using namespace winrt::Windows::Foundation;
// TODO: This must be replaced with the actual publisher and package name
const wchar_t package_name[] = L"46b35c25-b593-48d5-aeb1-d3e9c3b796e9";
const wchar_t publisher[] = L"CN=yuyoyuppe";
PackageManager pm;
hr = WcaInitialize(hInstall, "UninstallEmbeddedMSIXCA");
ExitOnFailure(hr, "Failed to initialize");
for (const auto& p : pm.FindPackagesForUser({}, package_name, publisher))
{
auto result = pm.RemovePackageAsync(p.Id().FullName()).get();
if (result)
{
Logger::info(L"MSIX was uninstalled!");
}
else
{
Logger::error(L"Couldn't uninstall MSIX!");
}
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall RemoveWindowsServiceByName(std::wstring serviceName)
{
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!hSCManager)
{
return ERROR_INSTALL_FAILURE;
}
SC_HANDLE hService = OpenService(hSCManager, serviceName.c_str(), SERVICE_STOP | DELETE);
if (!hService)
{
CloseServiceHandle(hSCManager);
return ERROR_INSTALL_FAILURE;
}
SERVICE_STATUS ss;
if (ControlService(hService, SERVICE_CONTROL_STOP, &ss))
{
Sleep(1000);
while (QueryServiceStatus(hService, &ss))
{
if (ss.dwCurrentState == SERVICE_STOP_PENDING)
{
Sleep(1000);
}
else
{
break;
}
}
}
BOOL deleteResult = DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
if (!deleteResult)
{
return ERROR_INSTALL_FAILURE;
}
return ERROR_SUCCESS;
}
UINT __stdcall UninstallServicesCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "UninstallServicesCA");
ExitOnFailure(hr, "Failed to initialize");
hr = RemoveWindowsServiceByName(L"PowerToys.MWB.Service");
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
// Removes all Scheduled Tasks in the PowerToys folder and deletes the folder afterwards.
// Based on the Task Scheduler Displaying Task Names and State example:
// https://learn.microsoft.com/windows/desktop/TaskSchd/displaying-task-names-and-state--c---/
UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
ITaskService* pService = nullptr;
ITaskFolder* pTaskFolder = nullptr;
IRegisteredTaskCollection* pTaskCollection = nullptr;
ITaskFolder* pRootFolder = nullptr;
LONG numTasks = 0;
hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA");
ExitOnFailure(hr, "Failed to initialize");
Logger::info(L"RemoveScheduledTasksCA Initialized.");
// COM and Security Initialization is expected to have been done by the MSI.
// It couldn't be done in the DLL, anyway.
// ------------------------------------------------------
// Create an instance of the Task Service.
hr = CoCreateInstance(CLSID_TaskScheduler,
nullptr,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
reinterpret_cast<void**>(&pService));
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
// ------------------------------------------------------
// Get the PowerToys task folder.
hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder);
if (FAILED(hr))
{
// Folder doesn't exist. No need to delete anything.
Logger::info(L"The PowerToys scheduled task folder wasn't found. Nothing to delete.");
hr = S_OK;
ExitFunction();
}
// -------------------------------------------------------
// Get the registered tasks in the folder.
hr = pTaskFolder->GetTasks(TASK_ENUM_HIDDEN, &pTaskCollection);
ExitOnFailure(hr, "Cannot get the registered tasks: %x", hr);
hr = pTaskCollection->get_Count(&numTasks);
for (LONG i = 0; i < numTasks; i++)
{
// Delete all the tasks found.
// If some tasks can't be deleted, the folder won't be deleted later and the user will still be notified.
IRegisteredTask* pRegisteredTask = nullptr;
hr = pTaskCollection->get_Item(_variant_t(i + 1), &pRegisteredTask);
if (SUCCEEDED(hr))
{
BSTR taskName = nullptr;
hr = pRegisteredTask->get_Name(&taskName);
if (SUCCEEDED(hr))
{
hr = pTaskFolder->DeleteTask(taskName, 0);
if (FAILED(hr))
{
Logger::error(L"Cannot delete the {} task: {}", taskName, hr);
}
SysFreeString(taskName);
}
else
{
Logger::error(L"Cannot get the registered task name: {}", hr);
}
pRegisteredTask->Release();
}
else
{
Logger::error(L"Cannot get the registered task item at index={}: {}", i + 1, hr);
}
}
// ------------------------------------------------------
// Get the pointer to the root task folder and delete the PowerToys subfolder.
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
ExitOnFailure(hr, "Cannot get Root Folder pointer: %x", hr);
hr = pRootFolder->DeleteFolder(_bstr_t(L"PowerToys"), 0);
pRootFolder->Release();
ExitOnFailure(hr, "Cannot delete the PowerToys folder: %x", hr);
Logger::info(L"Deleted the PowerToys Task Scheduler folder.");
LExit:
if (pService)
{
pService->Release();
}
if (pTaskFolder)
{
pTaskFolder->Release();
}
if (pTaskCollection)
{
pTaskCollection->Release();
}
if (!SUCCEEDED(hr))
{
PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiRecordSetString(hRecord, 0, TEXT("Failed to remove the PowerToys folder from the scheduled task. These can be removed manually later."));
MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
}
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogInstallSuccessCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"Install_Success",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogInstallCancelCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogInstallCancelCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"Install_Cancel",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogInstallFailCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogInstallFailCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"Install_Fail",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogUninstallSuccessCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogUninstallSuccessCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"UnInstall_Success",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogUninstallCancelCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogUninstallCancelCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"UnInstall_Cancel",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogUninstallFailCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogUninstallFailCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"UnInstall_Fail",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogRepairCancelCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogRepairCancelCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"Repair_Cancel",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall TelemetryLogRepairFailCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogRepairFailCA");
ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite(
g_hProvider,
"Repair_Fail",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "DetectPrevInstallPathCA");
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", L"");
LPWSTR currentScope = nullptr;
hr = WcaGetProperty(L"InstallScope", &currentScope);
try
{
if (auto install_path = GetMsiPackageInstalledPath(std::wstring{ currentScope } == L"perUser"))
{
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", install_path->data());
}
}
catch (...)
{
}
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall)
{
#ifdef CIBuild // On pipeline we are using microsoft certification
WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA");
return WcaFinalize(ERROR_SUCCESS);
#else
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR certificatePath = nullptr;
HCERTSTORE hCertStore = nullptr;
HANDLE hfile = nullptr;
DWORD size = INVALID_FILE_SIZE;
char* pFileContent = nullptr;
hr = WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA");
ExitOnFailure(hr, "Failed to initialize", hr);
hr = WcaGetProperty(L"CustomActionData", &certificatePath);
ExitOnFailure(hr, "Failed to get install property", hr);
hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"AuthRoot");
if (!hCertStore)
{
hr = GetLastError();
ExitOnFailure(hr, "Cannot put principal run level: %x", hr);
}
hfile = CreateFile(certificatePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hfile == INVALID_HANDLE_VALUE)
{
hr = GetLastError();
ExitOnFailure(hr, "Certificate file open failed", hr);
}
size = GetFileSize(hfile, nullptr);
if (size == INVALID_FILE_SIZE)
{
hr = GetLastError();
ExitOnFailure(hr, "Certificate file size not valid", hr);
}
pFileContent = static_cast<char*>(malloc(size));
DWORD sizeread;
if (!ReadFile(hfile, pFileContent, size, &sizeread, nullptr))
{
hr = GetLastError();
ExitOnFailure(hr, "Certificate file read failed", hr);
}
if (!CertAddEncodedCertificateToStore(hCertStore,
X509_ASN_ENCODING,
reinterpret_cast<const BYTE*>(pFileContent),
size,
CERT_STORE_ADD_ALWAYS,
nullptr))
{
hr = GetLastError();
ExitOnFailure(hr, "Adding certificate failed", hr);
}
free(pFileContent);
LExit:
ReleaseStr(certificatePath);
if (hCertStore)
{
CertCloseStore(hCertStore, 0);
}
if (hfile)
{
CloseHandle(hfile);
}
if (!SUCCEEDED(hr))
{
PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiRecordSetString(hRecord, 0, TEXT("Failed to add certificate to store"));
MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
}
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
#endif
}
UINT __stdcall InstallVirtualCameraDriverCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR driverPath = nullptr;
hr = WcaInitialize(hInstall, "InstallVirtualCameraDriverCA");
ExitOnFailure(hr, "Failed to initialize");
hr = WcaGetProperty(L"CustomActionData", &driverPath);
ExitOnFailure(hr, "Failed to get install property");
BOOL requiresReboot;
DiInstallDriverW(GetConsoleWindow(), driverPath, DIIRFLAG_FORCE_INF, &requiresReboot);
hr = GetLastError();
ExitOnFailure(hr, "Failed to install driver");
LExit:
if (!SUCCEEDED(hr))
{
PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiRecordSetString(hRecord, 0, TEXT("Failed to install virtual camera driver"));
MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
}
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall UninstallVirtualCameraDriverCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR driverPath = nullptr;
hr = WcaInitialize(hInstall, "UninstallVirtualCameraDriverCA");
ExitOnFailure(hr, "Failed to initialize");
hr = WcaGetProperty(L"CustomActionData", &driverPath);
ExitOnFailure(hr, "Failed to get uninstall property");
BOOL requiresReboot;
DiUninstallDriverW(GetConsoleWindow(), driverPath, 0, &requiresReboot);
switch (GetLastError())
{
case ERROR_ACCESS_DENIED:
case ERROR_FILE_NOT_FOUND:
case ERROR_INVALID_FLAGS:
case ERROR_IN_WOW64:
{
hr = GetLastError();
ExitOnFailure(hr, "Failed to uninstall driver");
break;
}
}
LExit:
if (!SUCCEEDED(hr))
{
PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiRecordSetString(hRecord, 0, TEXT("Failed to uninstall virtual camera driver"));
MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
}
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Management::Deployment;
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "UnRegisterContextMenuPackagesCA"); // original func name is too long
try
{
// Packages to unregister
const std::vector<std::wstring> packagesToRemoveDisplayName{ { L"PowerRenameContextMenu" }, { L"ImageResizerContextMenu" } };
PackageManager packageManager;
for (auto const& package : packageManager.FindPackages())
{
const auto& packageFullName = std::wstring{ package.Id().FullName() };
for (const auto& packageToRemove : packagesToRemoveDisplayName)
{
if (packageFullName.contains(packageToRemove))
{
auto deploymentOperation{ packageManager.RemovePackageAsync(packageFullName) };
deploymentOperation.get();
// Check the status of the operation
if (deploymentOperation.Status() == AsyncStatus::Error)
{
auto deploymentResult{ deploymentOperation.GetResults() };
auto errorCode = deploymentOperation.ErrorCode();
auto errorText = deploymentResult.ErrorText();
Logger::error(L"Unregister {} package failed. ErrorCode: {}, ErrorText: {}", packageFullName, std::to_wstring(errorCode), errorText);
er = ERROR_INSTALL_FAILURE;
}
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
{
Logger::error(L"Unregister {} package canceled.", packageFullName);
er = ERROR_INSTALL_FAILURE;
}
else if (deploymentOperation.Status() == AsyncStatus::Completed)
{
Logger::info(L"Unregister {} package completed.", packageFullName);
}
else
{
Logger::debug(L"Unregister {} package started.", packageFullName);
}
}
}
}
}
catch (std::exception& e)
{
std::string errorMessage{ "Exception thrown while trying to unregister sparse packages: " };
errorMessage += e.what();
Logger::error(errorMessage);
er = ERROR_INSTALL_FAILURE;
}
er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
return WcaFinalize(er);
}
UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TerminateProcessesCA");
std::vector<DWORD> processes;
const size_t maxProcesses = 4096;
DWORD bytes = maxProcesses * sizeof(processes[0]);
processes.resize(maxProcesses);
if (!EnumProcesses(processes.data(), bytes, &bytes))
{
return 1;
}
processes.resize(bytes / sizeof(processes[0]));
std::array<std::wstring_view, 27> processesToTerminate = {
L"PowerToys.PowerLauncher.exe",
L"PowerToys.Settings.exe",
L"PowerToys.Awake.exe",
L"PowerToys.FancyZones.exe",
L"PowerToys.FancyZonesEditor.exe",
[New PowerToy] File Locksmith (#20930) * Imported offline solution * Make solution compile * Add Windows sample, doesn't work? * Added new project to implement the dll * Remove unneeded header * Implemented IUnknown part of ExplorerCommand * Implemented IExplorerCommand methods * Implemented ClassFactory * Implemented DLL register/unregister * Implemented other DLL exports, not working? * Implemented IShellExtInit inferface * Implemented IContextMenu, it works! * Implement command data fetching * Make sample project compile on VS 2022 * Add plan * Implement Lib as separate project * Implemented IPC, not tested * Console UI project skeleton * Implemented basic console UI * Implemented piping, there are bugs * Prototype works * Remove old project * Added GUI project skeleton * Mitigate issue with WinUI3 * Added a control for displaying results * Add button * Implement core functions in lib project * Call new library function from console main * Implement showing results * Improve UI * Implemented subdirectory search * Remove useless code * Set window size * UI adjustments * Implement killing process * Rename variable * Add lib project to main solution * Add Ext and GUI projects to solution * Tweak packages for GUI project * Add a settings page * Add a few resource strings * Add one more resources string * VS keeps trying to correct this * Add references to File Locksmith in /,github * Implement some parts of FileLocksmithModule * Change output directory * Change target name and add to runner * Add logger * Started implementing settings backend * Fix log folder * Settings work * Add some basic tracing * Attempt at adding resources * Remove junk files * Added missing defines * Replaced some constants with resources Something's not working * Move resources to the Ext project * Remove experiment * Add binaries for signing * Improve tracing * Remove old Settings calls * Show something when there are no results * Change window title * Move computation to another thread, improve UX * Increase font size for default text * Remove entries for killed processes * Show user name * Remove nonrecursive implementation * Implement back end for getting file names * Show list of files, UI tweaks * Remove useless includes * Implement back end for getting full process path * Dark title bar on dark themes * Using Expander, other UI adjustments * Show "No results" after killing all processes * Show progress ring * Update configuration mapping * Revert "Update configuration mapping" This reverts commit d8e13206f3c7de3c6dbf880299bfff3bf9f27a37. * Fixed solution configuration, ARM64 should build * Backend for refreshing * Variable window size * Add refresh button * New WinUI3 C# project for FL * Started porting functionality * Add Interop project * Move IPC to Ext project * Ported native functions to Interop * Ported finding processes * Ported most of Main Window functionality * Display paths of files * Implement killing processes * Use resource string for "End Task" * Remove entries for terminated processes * Show User name * Set default window size * Make the new UI the default * Reading paths from stdin, completed port to C# * Fix small bug * Moving to MVVM * Adding Labs * Merge branch 'ivan/file-locksmith' of https://github.com/microsoft/PowerToys into ivan/file-locksmith Removing one parent commit for cleaner history Co-Authored-By: Niels Laute <niels.laute@live.nl> * Reintroducing features * Moving UI strings to resources file * Restored functionality * Add missing dlls * Add FIle Locksmith to publish.cmd * Rebase fixes * Try updating nuget.config * Fix copy-paste blunder * Add File Locksmith UI for publishing * Add .pubxml file in FileLocksmith * Change build output folder * Fix installer build issues Remove old projects from solution so MSBuild doesn't build them. Downgrade target framework to what most other projects are using. Fix publishing profile and project runtimes. Remove unused CsWinRT references. * [CI] Add clear to nuget packages * Fix module reference counting * Fix nuget for release CI * Fix version and signing * Fix path for resources * Fix incorrect results when running 2 instances * Fix default nuget source * Windows 10 icon and fallback for UI * Code clean-up and spaces instead of tabs * Add gif showcasing FL * Add screenshot of File Locksmith for Settings * Add new files to the installer * Add OOBE page * Showing selected paths in the header * Tweak path list * Added new, wider gif * Add GPO * Add some logs * [CI]Get CommunityToolkit.Labs from BigPark feed * [CI]Use azure package feed for Nuget in release * [CI]Another try for the labs source * Revert changes to feed * Use RestoreAdditionalProjectSources * Add tooltip to file list * Change tooltip to not trim the lines * Add Tips and tricks section mentioning elevated * Add some more logs messages. * Grammar fix * Add to bug report tool * Fix UI virtualization not working * Disable virtualization to avoid crashes * Get better virtualization * Add dialog instead of tooltip to show list of items * No results refresh icon is now a button too * Use managed methods for handling processes * Remove registry code from Ext. * Support drives too Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
2022-10-28 21:51:21 +08:00
L"PowerToys.FileLocksmithUI.exe",
[New Utility]Mouse Jump(#23566) * #23216 - initial MouseJump commit * #23216 - Mouse Jump - fix spelling, removing Interop folder * #23216 - Mouse Jump - removed orphaned project guids from PowerToys.sln * #23216 - Mouse Jump - removed orphaned project guids from PowerToys.sln * #23216 - Mouse Jump - switch MS Logger to NLog for nuget package allow-listing * #23216 added MouseJumpUI.UnitTests.dll to "MS Tests" step in build-powertoys-steps.yml * [MouseJump] fixed screenshot coords (x & y were transposed) (#23216) * [MouseJump] close form rather than hide on deactivate (#23216) * [MouseJump] added UI dll for signing (#23216) * [MouseJump] close form rather than hide on deactivate (#23216) * [MouseJump] removed redundant line * [MouseJump] configure dpi awareness, add NLog.config (microsoft#23216) * [MouseJump] fix spellchecker errors (microsoft#23216) * [MouseJump] fixing comment style warning (microsoft#23216) * [MouseJump] simplified dpi config (microsoft#23216) * [MouseJump] fixed edge case issue with moving cursor (microsoft#23216) * [MouseJump] fixed typo (microsoft#23216) * [MouseJump] added attribution (microsoft#23216) * [Mouse Jump] fix attribution link and spelling (microsoft#23216) * Add MouseJump to installer * Fix centralized version control * Add Quick Access enable/disable entry * Fix analyzer error in GPO * Fix botched merge * Disabled by default and remove boilerplate code * Add GPO definitions * Add GPO implications when starting standalone * Update hotkey when it's changed in Settings * Use standard Logger * Add OOBE strings for Mouse Jump * Add telemetry * Update installer * Add signing * Add to bug report tool * Address PR feedback
2023-02-24 21:30:30 +08:00
L"PowerToys.MouseJumpUI.exe",
L"PowerToys.ColorPickerUI.exe",
L"PowerToys.AlwaysOnTop.exe",
Registry Preview: complete feature with integration with Settings and the Launcher UX (#23709) * Initial src for Registry Preview Initial collection of files * Update MainWindow.Utilities.cs fixing a few spelling items * Update expect.txt * Update App.xaml.cs * Update MainWindow.Events.cs * Update MainWindow.Utilities.cs * Update MainWindow.xaml.cs * Update expect.txt * Update MainWindow.Events.cs * Rename AddPreviewtoRegfile.reg to AddPreviewToRegfile.reg * Rename RemovePreviewtoRegfile.reg to RemovePreviewToRegfile.reg * Update Resources.resw * Update MainWindow.xaml * Turns on self-contained mode Updates the csproj file to compile the app as self-contained . Includes fixes for code that expected the app to be in an ApplicationContainer. Updates WindowsAppSDK from 1.1.5 to 1.2.230118.102. * Updated to align with StyleCop errors Multiple changes across the codebase that now aligns with StyleCop guidelines. Tested again after the changes, to make sure no new bugs crept in. * Added comments for spell-checker Unclear if this side step should be done or not, but the kxz comes from a GUID and the other three names are constants. * Adding code-custom.dic Comments didn't work; trying a dic file * Added four new terms to expects.txt file Cleaning up attempt to update the spell-checker with dic file and moved it to expects.txt file * Adding one more string Adding one more string for Spell-Check * Adding back egfile Seems this is needed. * Correcting a variable name Seems one of the variable names that changed globally got missed in a XAML file. * Update project to be more PowerToys friendly Tweaking names and output file name to fit better with PowerToys. * First pass at integration into Settings and Launcher This PR is not as large as it seems: - RegistryPreview's source moved around to a "better" directory that makes it look like the whole app changed. It didn't. In fact, I opened it in Beyond Compare and there's not much difference in the RegistryPreview app. - Added RegistryPreviewExt that produces a DLL that the Launcher can run the EXE - Changes to Runner calls the Ext DLL rather than the app - Settings UI got a bunch of changes to enable the Settings page for enable/disable across ViewModels, Views, and string tables. Still todo: - Add "Preview" to .REG files, when the app is enable (and remove it when disabled) - Update the thumbnail-screenshot in the Settings page - Add support for OOBE * Update expect.txt Added REGISTRYPREVIEWEXT for recent changes and corrected an alphabetic sorting error. * Updating project file for Release mode Build failed due to a bad Includes path in Release mode. * Adds REG registration but breaks settings This update will update the HKCU branch of the Registry for REG files: if the app in PowerToys is enabled, it adds a Preview item to the context menu of REG files and disabling in PowerToys removes the menu item. While working on this, I noticed that the application settings were broken, after moving to a self-contained EXE: there must have been old settings from past builds, when it was still using containers and family names. Added TODO's to add a new way to save settings, likely as JSON. * Re-enabled app settings Moved from using ApplicationDataContainer for app settings and now use simple JSON. Also cleaned up handling the scenario where the Launcher send in the PID from PowerToys' main thread. Fixed past spelling errors as well. * Update RegistryPreview.png Captured new screenshot. * Integration into OOBE Integrates new page for Registry Preview into OOBE process. * Removing old comment and unneeded calls Two bits of source removed as they aren't needed any longer Removing a chunk of old commented out code that doesn't make sense anymore. * Merging file from upstream Updating some files due to three merge conflicts from upstream changes and a couple of other changes to keep up. * Update .gitignore Adding two vcxproj files that have local updates for atls.lib locations. * Update Resources.resw Fixing a typo that involved a missing closing tag. * Fix analyzer warnings * Fix CI build * Fix ARM64 build Project file cleanup * Add to installer * expect.txt * Remove unneeded dll * Update MainWindow.xaml.cs Added check for current Theme and adjust TextBox Foreground accordingly. * Update expect.txt Cleaning up merge cruft. * Revert wrong .gitignore changes * Fix ARM installer * Update Brushes for textBox to use Theme based versions Finally figured out how to use the built-in, Theme-aware Brushes for the font colors in the onscreen textBox. Also have it aligning the font color for the hover state. * Align configuration in PowerToys.sln * [installer] Add missing files * Fix bad merge * Fixes for stefansjfw's review Includes: - two new strings for UX localization - adds compatibility section for Windows 10 - fix to only track successful activations - Removes two REG files that were there for examples * Fixes from review from htcfreek Updates: - Fixed an issue where TextBox_TextChanged was firing when you simply opened a file. - Added clamp to prevent files larger than 10MB from being opened. - Added support in the UX to show Keys and Values that are deleted via the file - Added support to specially handle Keys that start with - and Values that have =- in them (delete scenario) - Changed AppBarButton icon for Edit from Rename to NewWindow * Create deleted-folder32.png * Added Registry Preview to GPO * Update expect.txt Updating spellchecker works * Updating Size/Move code for better results - Moved the size/move to the MainWindow layer - Cleaned up the JSON settings handling to avoid an access denied on first run * Improving text handling Changed how special characters are parse, which helps with live entry. * Updates to parsing and other fixes - Renamed the value PNG for parity - Added new error image - Added check that values have " at start and finish. - Added support for a new "ERROR" type for Values - Fixed support for @ versus "@" in values - Fixed bug where Save wasn't activating in all scernarios * Fix signing and versioning * Update src/settings-ui/Settings.UI/ViewModels/RegistryPreviewViewModel.cs Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * Apply suggestions from code review Adds Launch button to the settings page. Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * Update Resources.resw Adding strings for new launch button * Adding new version for GPO Moving to 0.69.0 * More parsing bug fixes - Changes to look for [- instead of -[ for syntax deleting keys (fix for developer's mental hiccup) - Moved [- to top of the decision making stack, as it needs to come before [ - Added new StripEscapedCharacters function for both sides of a Value line - Fixed crashing bug for scenario where no Keys are parsed before a Value * Bug fixes from most recent review. - Dictionary will now be case insensitive when searching for keys - Added tool tips (and strings) to the images of the Keys and Values - Updated delete handling for Keys, so that only the leaf-most node gets marked as deleted; also stops the top most roots from being marked deleted. * Tweaking for @=- Forces the UX to take @=- and treat it as @="" since that's what Registry Editor would do. * Removing unused usings * Updates app description * Update src/gpo/assets/PowerToys.admx Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * cleanup proj file launch process only if module is enabled add process to bugreport process list * Add context menu icon * Update src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * Use modulesRegistry.h to apply/unapply registry changes * Tweaked window settings Moved the loading of the settings a little later in the initialization code, which gives more time for things to initialize. * Update registry.h Moving the definition out of the detail namespace to the registry name space to fix a compilation issue in RegistryPreviewExt. * Unapply on creation If module is disabled in settings.json, on startup reg entries should be unnaplied. TODO: read m_enabled from settings file on creation * Removing size/move main window Added a TODO comment that responds to the size/position settings that are being saved out in the JSON blob on close as it doesn't always work on every PC, as the MainWindow initializes at different times. * Change to always keep Save As active No reason for this to be disabled, honestly. --------- Co-authored-by: Clint Rutkas <clint@rutkas.com> Co-authored-by: Stefan Markovic <stefan@janeasystems.com> Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> Co-authored-by: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com>
2023-03-27 21:21:46 +08:00
L"PowerToys.RegistryPreview.exe",
L"PowerToys.Hosts.exe",
L"PowerToys.PowerRename.exe",
L"PowerToys.ImageResizer.exe",
L"PowerToys.GcodeThumbnailProvider.exe",
L"PowerToys.PdfThumbnailProvider.exe",
L"PowerToys.MonacoPreviewHandler.exe",
L"PowerToys.MarkdownPreviewHandler.exe",
L"PowerToys.StlThumbnailProvider.exe",
L"PowerToys.SvgThumbnailProvider.exe",
L"PowerToys.GcodePreviewHandler.exe",
L"PowerToys.PdfPreviewHandler.exe",
L"PowerToys.SvgPreviewHandler.exe",
[Peek] Powertoys Peek MVP (#25922) * Peek (#22498) * Add peek dll project * add spacebar preview and launch on hotkey press * add todo * add process handle to handle continuous press of hotkey * add tool to stop all powertoys processes * Add a blank Peek page and update nav menu * Add some initial content to Peek page including a toggle * refactor settings parsing * rename spacebar peek to peek viewer * rename script to stop powertoys processes * remove tool * Adding FileUtils for retrieving selected file in File Explorer * Remove unnecessary SndPeekSettings * Add shortcut setting * Set the shortcut to ctrl+space * Launching viewer with selected FE file * Add PeekUI WinUI3 project with interop events * Moving FileTypeUtils into PeekFileUtils project * execute winui3 app on hotkey * Fix paths with spaces * remove winui3 project * Resolve comment * add wpf app with toggle visibility on hotkey * fix visibility on startup * remove window properties and add todos * Fixed hidden extension and system file handling * wip * Add working WPF app with FileExplorer querying * remove c++ projects * Move native awaiter * Working Image control with image files * Resize and move window based on explorer monitor * Image render, window positioning and sizing clean up * add window management logic and selection logic * add extension methods to add circular iterating capability to linkedlistnode * Add OnArrowKeyPresshandler * Added titlebar with file name and scaling with titlebar height * fix flashing window on startup and process kept alive when powertoys exits * remove wait for debugger loop in ui * Add KeyIsDown method * Fix KeyDown issue with Key handled and check for repeat * Add thumbnail logic * Add all folder items if only one item is selected * File type helper * Using hresult * Add cancellation and rotation handling * Use extension instead of path * fIX CONFLICTS * Fixing some file type checks * Add new icon for Peek * Update page with the new Peek icon * Initialize IsEnabled and hook ActivationShortcut to dllmain * add icon to taskbar and titlebar * Add theme sensitive backgrounds * rename event handlers * add settings image * Move window data into obserable object * Refactor viewmodel, interop and helpers * Clean up * Add loading spinner * Add todos * Fix conflicts * Move native code into its own folder * Add peek to installer * Fix building peek and peekui projects * Replace UWP namespaces to WinAppSDK * Working WASDK placeholder project * Add exit when powertoys runner exit * Working winui3 with image display * Add WIC project with <TreatWarningAsErros> false for now * Fit content to window * Use Size from Windows.Foundation * Change order * Add some todos * Refactored native/interop code and added helpers to imagepreviewer * Rename projects * Move some code * Remove using Co-authored-by: Michael Salmon <miksalmon@users.noreply.github.com> Co-authored-by: Michael Salmon 🐟 <michaelpsalmon@outlook.com> Co-authored-by: Alireza Ebadi Ghajari <alirezae@microsoft.com> Co-authored-by: Jessie Su <Jessie.Su@microsoft.com> Co-authored-by: sujessie <102062556+sujessie@users.noreply.github.com> * Bump Microsoft.Windows.SDK.BuildTools version * [Peek] Plugin pattern to enable any file type previewing (#22475) * [Peek] Fetching image size through PropertyStore (#22530) * Fetching metadata from PropertySTore * Releasing objects to fix crash * Creating new PropertyHelper Co-authored-by: Daniel Chau <dancha@microsoft.com> * Juliata/filetypes (#22538) * Using the same list of file extensions as Lightbox's AppxManifest, and ensuring we convert file extension to lowercase * Add IsFileTypeSupported to IPreviewer * respond to PR comments * Add scale awareness to window centering (#22541) * [Peek] Fix installer builds, project configs and update assets (#22540) * Update installer * Fix installer errors * Fix peek vcxproj * Add package signing * Add peek to arm64 * Add back ARM64 toMeasureToolUI * Add versions to project * Update assets and icons * Add correct icon * [Peek] Enable PropertyStore for offline files (#22567) * Enabling PropertyStore for offline files Co-authored-by: Daniel Chau <dancha@microsoft.com> * [Peek] Adding unsupported file previewer (#22598) * Unsupported file previewer * Fix file display info * Fix property store calls * Update TODO * [Peek] Add WebView2 integration (#22506) * First commit with WIP logic to support WV2 in Peek module * Minor code cleanup and try/catch block * Added control to wrap WebView2 logic * Cleanup * Added logic to handle HTML previewing Properly update FilePreview according to file type * Code cleanup Updated comments * Updated comment * Removed comment * Code cleanup * Improved opening of web browser preview to avoid "blank" or "seeing previous page" issue Removed unused method Added xaml fallback to guarantee default/starting state * Removed folder * Updated factory logic to match master * address code review * addressed PR review * address PR review * Address PR review * address PR review * Address PR review * [Peek] Add basic file querying and navigation (#22589) * Refactor to facilitate file data initialization * Extract file-related code to new FileManager class * Add temp basic version * Clean + add todo for cancellations * Fix various nav-related issues * Temp - start moving iteration-related code to bg thread * Minor tweaks * Add FEHelper todo * Rename FileManager + various tweaks * Add basic throttling * Improve bg thread synchronization * Clean * Clean * Rename based on feedback * Rename FileQuery * Rename properties * Rename remaining fields * Add todos for nav success/failures Co-authored-by: Esteban Margaron <emargaron@microsoft.com> * [Peek] Add customized title bar (#22600) * Add basic button UI * Add function to get default app name and to open file in default app * Correct error output * Add filename to titlebar * Remove titlebar text from Resw * Add basic button UI * Add function to get default app name and to open file in default app * Add filename to titlebar * Correct error output * Remove titlebar text from Resw * Add SetDragRectangles * Correct logic, update function name * Add localization * Cleanup and adaptive width * Add fileIndex/NumberOfFiles for multiple files activation * Refine titlebar styles * Update error message; Return HResult from native methods; Update variable initialisation and string null testing * Titlebar height and adaptive width refinement * Add fallback to launch app picker if fail to open default app * Temp change to hide AppTitle_FileCount * Update launch button to command; Add keyboard accelerator * Update titlebar inactive background color * Update tooltip to add keyboard accelerator * Add comments to resw file * Fix accidental deletion from previous merge Co-authored-by: Jojo Zhou <yizzho@microsoft.com> Co-authored-by: Yawen Hou <yawenhou@microsoft.com> * Fix crash * Fix wrong thread exception * Make CurrentItemIndex setter private * Update titlebar filecount text * Fix titlebar draggable region and interactive region (bump WinAppSdk to latest) * [Peek] Unsupported File Previewer - Formatting string from resources (#22609) * Moving to string resource usage * Moving ReadableStringHelper to common project * Fix comments * [Peek] Fix foregrounding (#22633) * Fixing foregrounding * Get window handle inside BringToForeground extension method Co-authored-by: Daniel Chau <dancha@microsoft.com> Co-authored-by: Samuel Chapleau <sachaple@microsoft.com> * [Peek] ImagePreviewer - Handle error states (#22637) * add better preview state handling * add error handling in imagepreviewer and better state handling * fix error handling so exception is not bubbled up * improve performance and hook up unsupported previewer on error * remove commented code * address pr comments * [Peek] add PDF viewing support (#22636) * [Peek] add PDF viewing support * Fixed issue which would redirect some HTML and PDF files to external browser * Fixed refactored interface name * [Peek] Refine titlebar adaptive width (#22642) * Adjust adaptive width of titlebar * Remove visualstate setters for AppTitle_FileCount Co-authored-by: Jojo Zhou <yizzho@microsoft.com> * [Peek] New File Explorer tabs break Shell API to get selected files (#22641) * fix FE tab bug * remove unnecessary unsafe keyword * [Peek] add extra logic to properly render PNG files with transparency (#22613) * [Peek] added extra logic to render PNG files with proper transparency * Moved logic to ThumbnailHelper Cleanup * Created a separated previewer for PNG to only load the preview image with thumbnail logic * removed unused code * Updated state loading change * [Peek] Unsupported File Previewer - Setting Window Size (#22645) * Adding setting for unsupported file window * Fix * [Peek] Add tooltip to File (#22640) * Add tooltip to File * Add placeholder text for no tooltip * Address comments * Use StringBuilder Co-authored-by: Jojo Zhou <yizzho@microsoft.com> * Add full image quality support (#22654) * [Peek] Window foregrounding simplification and fixes + keep window visible if FE single selection changed (#22657) * Use different apis to bring to foreground removing remote thread wait and work as well as library loading * Keep window open if single selected file in FE is different * Removed unused methods * [Peek] Add cancellation token OnFilePropertyChanged (#22643) * Cancel file loading before opening another file * Add omitted cancellation checks * Catch task cancelled exception; Add more cancellation checkpoints * Add cancellation checkpoint beofre GetBitmapFromHBitmapAsync * Correct typo * Update to pass cancellation token individually to each async methods * Add lost cancellationToken source * Add cancellation token to PngPreviewer Co-authored-by: Yawen Hou <yawenhou@microsoft.com> * [Peek] Unsupported File Previewer - Preserve Transparency For File Icons (#22650) * Preserving transparency or icons * Remove TODO Co-authored-by: Samuel Chapleau <sachaple@microsoft.com> * [Peek] Update some installer build steps + assets update (#22683) * Fix settings & peek.ui.wpf * Add back missing icon * Add missing files and actions to installer * Keep window open if the selected file in explorer is different (only works for single file selection) * Undo last * [Peek] Add copy keyboard accelerator (#22647) * add copy keyboard accelerator * Fix comments Co-authored-by: Samuel Chapleau <sachaple@microsoft.com> * [Peek] add WV2 improvements (behavior and UX) (#22685) * [Peek] added logic to get max monitor size for opening WebView2 * Removed ununsed dependency property * Added workaround for cases where the web page would not finish navigating in a quick timing, for example google.com. * Remove window extensions from common and use nullable size argument instead Co-authored-by: Samuel Chapleau <sachaple@microsoft.com> * [Peek] Merge main, self-contained .NET and fix WebView2 user data dir issue (#22899) * Merge remote-tracking branch 'origin/main' into peek * Test sc * Set WebView2 user data dir * spellcheck * Fix comment * Move check if higher quality image is already loaded to the exact line where we change the Preview bitmap (#23083) * Fix opening Peek when FE window is set to full name path (#23082) * Move check for png thubmnail loading priority * Remove Peek.UI.WPF project * Remove duplicated method in powertoys setup * [Peek] Fix selecting files from the correct focused opened File Explorer tab & from Desktop (#23489) * Get file based on active tab handle instead of window title * Refactor code to get active tab * Getting all items from the shell API working again, except for desktop * Refactor and cleanup com & native code * Add back removed peek xaml assets in Product.wxs * Remove some dependencies that do not seem necessary in Product.wxs * [Peek] Small images (#23554) * change stretch value * compare with actual window size * consider scaling factor * set max size * clean up * clean up * clean up previewers * scaling factor in bitmap previewer * max image size property * [Peek]Handle errors for HEIC/HEIF and fall back to default previewer if there is no thumbnail (#22684) * Handle errors when getting filesize by falling back to default previewer * Bringing back other file types that are fixed with these code changes --------- Co-authored-by: Samuel Chapleau <sachaple@microsoft.com> * [Peek] Add unsupported file icon fallback (#23735) * Refactor icon retrieval, refactor hbitmap to bitmap conversion, add icon fallback * Add svg to assets in installer * [Peek] Refactoring of file system models, removal of PngPreviewer, retrieving of folder size via Scripting com reference and other fixes (#23955) * Refactor icon retrieval, refactor hbitmap to bitmap conversion, add icon fallback * Add svg to assets in installer * - Refactor File class into IFileSystemItem, FileItem & FolderItem - Display size for folders using Scripting namespace - Remove default app buttons for files or folders not supporting it * Add better content type via storage apis * Add check for storagefile in PngPreviewer * Fix png stretching * Remove png previewer * Rename ThumbnailOptions.None to ThumbnailOptions.ResizeToFit * [Peek] Removed monitor percentage evaluation for the UnsupportedFilePreview control (#24002) * Remove settings for percentage of windows and keep default min size. * Fix margin on unsupported control * Use nullable Size for image size & open file on background thread (#24004) * [Peek] SVG support (#24237) * svg previewer * svg size * set scaling factor * set image size * changed image source type * non nullable image size * notify svg previewer changed * uncomment * rename BitmapPreviewer * move svg support * remove svg previewer * [Peek] Implementation of a performant and reliable Neighboring Files Query (#24943) * Use IShellItemArray as the backing array of item * Finalize and cleanup NFQ implementation * Cleanup remainder of the code * Remove unused using * [Peek] Pin the window position (#24927) * [Peek] Telemetry and logging (#25231) * text preview * scrolling * changed size * webview2 preview * common preview project * previewpane: use common project * peek: use common * previewpane: moved md * peek: md * previewpane: clean up * clean up * moved monaco files * moved formatters * rename * moved common monaco helper * dev files support * installer * removed versions * warnings: culture info * warnings: names * clean up * warnings: dispose * warnings: default values * warnings * warnings: charset * warnings: exceptions * suppress warning * installer: added peek * changed peek guid * monaco folders * peek deps * peek files * peek resources * removed additional monaco folder * set host name * Update installer * hardcode monaco path * leave single webview control * moved path to common * project * more meaningful todos * moved temp folder cleanup * todo * extension check * spell: monaco * spellcheck * spellcheck * fix id * fix spelling * key to spelling * id fix * Fix monaco resolution at install time * Fix user install. Add needed files * installer: remove peek localization files. It's a WinUI app * installer:fix signing * removed unused * settings: flyout enable/disable for Peek * simplify string * property changed handle * [Peek][Settings] Peek OOBE page (#25895) * [Peek] GPO (#25918) * Add Native methods file to exception * Fix merge issue on solution file * Adjust spellcheck * Remove boilerplate code * Add module interface telemetry * Remove change to README.md * Add entry to README * Clean up some non-changes * Fix order of Peek in Settings menu * [Settings] Make peek descriptions more descriptive --------- Co-authored-by: Michael Salmon <miksalmon@users.noreply.github.com> Co-authored-by: Michael Salmon 🐟 <michaelpsalmon@outlook.com> Co-authored-by: Alireza Ebadi Ghajari <alirezae@microsoft.com> Co-authored-by: Jessie Su <Jessie.Su@microsoft.com> Co-authored-by: sujessie <102062556+sujessie@users.noreply.github.com> Co-authored-by: Daniel Chau <d.chau@alumni.ubc.ca> Co-authored-by: Daniel Chau <dancha@microsoft.com> Co-authored-by: jth-ms <73617023+jth-ms@users.noreply.github.com> Co-authored-by: Robson <rp.pontin@gmail.com> Co-authored-by: estebanm123 <49930791+estebanm123@users.noreply.github.com> Co-authored-by: Esteban Margaron <emargaron@microsoft.com> Co-authored-by: Yawen Hou <Sytta@users.noreply.github.com> Co-authored-by: Jojo Zhou <yizzho@microsoft.com> Co-authored-by: Yawen Hou <yawenhou@microsoft.com> Co-authored-by: Jojo Zhou <39350350+Joanna-Zhou@users.noreply.github.com> Co-authored-by: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com> Co-authored-by: Seraphima Zykova <zykovas91@gmail.com> Co-authored-by: Stefan Markovic <stefan@janeasystems.com> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
2023-05-11 01:43:03 +08:00
L"PowerToys.Peek.UI.exe",
L"PowerToys.MouseWithoutBorders.exe",
L"PowerToys.MouseWithoutBordersHelper.exe",
L"PowerToys.MouseWithoutBordersService.exe",
L"PowerToys.exe",
};
for (const auto procID : processes)
{
if (!procID)
{
continue;
}
wchar_t processName[MAX_PATH] = L"<unknown>";
HANDLE hProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID) };
if (!hProcess)
{
continue;
}
HMODULE hMod;
DWORD cbNeeded;
if (!EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
{
CloseHandle(hProcess);
continue;
}
GetModuleBaseNameW(hProcess, hMod, processName, sizeof(processName) / sizeof(wchar_t));
for (const auto processToTerminate : processesToTerminate)
{
if (processName == processToTerminate)
{
const DWORD timeout = 500;
auto windowEnumerator = [](HWND hwnd, LPARAM procIDPtr) -> BOOL {
auto targetProcID = *reinterpret_cast<const DWORD*>(procIDPtr);
DWORD windowProcID = 0;
GetWindowThreadProcessId(hwnd, &windowProcID);
if (windowProcID == targetProcID)
{
DWORD_PTR _{};
SendMessageTimeoutA(hwnd, WM_CLOSE, 0, 0, SMTO_BLOCK, timeout, &_);
}
return TRUE;
};
EnumWindows(windowEnumerator, reinterpret_cast<LPARAM>(&procID));
Sleep(timeout);
TerminateProcess(hProcess, 0);
break;
}
}
CloseHandle(hProcess);
}
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
void initSystemLogger()
{
static std::once_flag initLoggerFlag;
std::call_once(initLoggerFlag, []() {
WCHAR temp_path[MAX_PATH];
auto ret = GetTempPath(MAX_PATH, temp_path);
if (ret)
{
Logger::init("PowerToysMSI", std::wstring{ temp_path } + L"\\PowerToysMSIInstaller", L"");
}
});
}
// DllMain - Initialize and cleanup WiX custom action utils.
extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
WcaGlobalInitialize(hInst);
initSystemLogger();
TraceLoggingRegister(g_hProvider);
DLL_HANDLE = hInst;
break;
case DLL_PROCESS_DETACH:
TraceLoggingUnregister(g_hProvider);
WcaGlobalFinalize();
break;
}
return TRUE;
}