mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
FancyZones and Shortcut Guide initial commit
Co-authored-by: Alexis Campailla <alexis@janeasystems.com> Co-authored-by: Bret Anderson <bretan@microsoft.com> Co-authored-by: Enrico Giordani <enrico.giordani@gmail.com> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: Jeff Bogdan <jeffbog@microsoft.com> Co-authored-by: March Rogers <marchr@microsoft.com> Co-authored-by: Mike Harsh <mharsh@microsoft.com> Co-authored-by: Nachum Bundak <Nachum.Bundak@microsoft.com> Co-authored-by: Oliver Jones <ojones@microsoft.com> Co-authored-by: Patrick Little <plittle@microsoft.com>
This commit is contained in:
committed by
Bartosz Sosnowski
parent
10c5396099
commit
8431b80e48
528
installer/PowerToysSetupCustomActions/CustomAction.cpp
Normal file
528
installer/PowerToysSetupCustomActions/CustomAction.cpp
Normal file
@@ -0,0 +1,528 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#define SECURITY_WIN32
|
||||
#include <Security.h>
|
||||
#pragma comment(lib, "Secur32.lib")
|
||||
#include <Lmcons.h>
|
||||
|
||||
#include <comdef.h>
|
||||
#include <taskschd.h>
|
||||
#pragma comment(lib, "taskschd.lib")
|
||||
#pragma comment(lib, "comsupp.lib")
|
||||
|
||||
#include <iostream>
|
||||
#include <strutil.h>
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
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'
|
||||
|
||||
// Creates a Scheduled Task to run at logon for the current user.
|
||||
// The path of the executable to run should be passed as the CustomActionData (Value).
|
||||
// Based on the Task Scheduler Logon Trigger Example:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/taskschd/logon-trigger-example--c---/
|
||||
UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall) {
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
|
||||
TCHAR username_domain[USERNAME_DOMAIN_LEN];
|
||||
TCHAR username[USERNAME_LEN];
|
||||
|
||||
std::wstring wstrTaskName;
|
||||
|
||||
ITaskService *pService = NULL;
|
||||
ITaskFolder *pTaskFolder = NULL;
|
||||
ITaskDefinition *pTask = NULL;
|
||||
IRegistrationInfo *pRegInfo = NULL;
|
||||
ITaskSettings *pSettings = NULL;
|
||||
ITriggerCollection *pTriggerCollection = NULL;
|
||||
IRegisteredTask *pRegisteredTask = NULL;
|
||||
|
||||
hr = WcaInitialize(hInstall, "CreateScheduledTaskCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "Initialized.");
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Get the Domain/Username for the trigger.
|
||||
//
|
||||
// This action needs to run as the system to get elevated privileges from the installation,
|
||||
// so GetUserNameEx can't be used to get the current user details.
|
||||
// The USERNAME and USERDOMAIN environment variables are used instead.
|
||||
if (!GetEnvironmentVariable(L"USERNAME", username, USERNAME_LEN)) {
|
||||
ExitWithLastError(hr, "Getting username failed: %x", hr);
|
||||
}
|
||||
if (!GetEnvironmentVariable(L"USERDOMAIN", username_domain, USERNAME_DOMAIN_LEN)) {
|
||||
ExitWithLastError(hr, "Getting the user's domain failed: %x", hr);
|
||||
}
|
||||
wcscat_s(username_domain, L"\\");
|
||||
wcscat_s(username_domain, username);
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "Current user detected: %ls", username_domain);
|
||||
|
||||
// Task Name.
|
||||
wstrTaskName = L"Autorun for ";
|
||||
wstrTaskName += username;
|
||||
|
||||
// Get the executable path passed to the custom action.
|
||||
LPWSTR wszExecutablePath = NULL;
|
||||
hr = WcaGetProperty(L"CustomActionData", &wszExecutablePath);
|
||||
ExitOnFailure(hr, "Failed to get the executable path from CustomActionData.");
|
||||
|
||||
// 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,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_ITaskService,
|
||||
(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. Creates it if it doesn't exist.
|
||||
hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder);
|
||||
if (FAILED(hr)) {
|
||||
// Folder doesn't exist. Get the Root folder and create the PowerToys subfolder.
|
||||
ITaskFolder *pRootFolder = NULL;
|
||||
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
|
||||
ExitOnFailure(hr, "Cannot get Root Folder pointer: %x", hr);
|
||||
hr = pRootFolder->CreateFolder(_bstr_t(L"\\PowerToys"), _variant_t(L""), &pTaskFolder);
|
||||
if (FAILED(hr)) {
|
||||
pRootFolder->Release();
|
||||
ExitOnFailure(hr, "Cannot create PowerToys task folder: %x", hr);
|
||||
}
|
||||
WcaLog(LOGMSG_STANDARD, "PowerToys task folder created.");
|
||||
}
|
||||
|
||||
// If the same task exists, remove it.
|
||||
pTaskFolder->DeleteTask(_bstr_t(wstrTaskName.c_str()), 0);
|
||||
|
||||
// Create the task builder object to create the task.
|
||||
hr = pService->NewTask(0, &pTask);
|
||||
ExitOnFailure(hr, "Failed to create a task definition: %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Get the registration info for setting the identification.
|
||||
hr = pTask->get_RegistrationInfo(&pRegInfo);
|
||||
ExitOnFailure(hr, "Cannot get identification pointer: %x", hr);
|
||||
hr = pRegInfo->put_Author(_bstr_t(username_domain));
|
||||
ExitOnFailure(hr, "Cannot put identification info: %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Create the settings for the task
|
||||
hr = pTask->get_Settings(&pSettings);
|
||||
ExitOnFailure(hr, "Cannot get settings pointer: %x", hr);
|
||||
|
||||
hr = pSettings->put_StartWhenAvailable(VARIANT_FALSE);
|
||||
ExitOnFailure(hr, "Cannot put_StartWhenAvailable setting info: %x", hr);
|
||||
hr = pSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
|
||||
ExitOnFailure(hr, "Cannot put_StopIfGoingOnBatteries setting info: %x", hr);
|
||||
hr = pSettings->put_ExecutionTimeLimit(_bstr_t(L"PT0S")); //Unlimited
|
||||
ExitOnFailure(hr, "Cannot put_ExecutionTimeLimit setting info: %x", hr);
|
||||
hr = pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
|
||||
ExitOnFailure(hr, "Cannot put_DisallowStartIfOnBatteries setting info: %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Get the trigger collection to insert the logon trigger.
|
||||
hr = pTask->get_Triggers(&pTriggerCollection);
|
||||
ExitOnFailure(hr, "Cannot get trigger collection: %x", hr);
|
||||
|
||||
// Add the logon trigger to the task.
|
||||
ITrigger *pTrigger = NULL;
|
||||
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
|
||||
ExitOnFailure(hr, "Cannot create the trigger: %x", hr);
|
||||
|
||||
ILogonTrigger *pLogonTrigger = NULL;
|
||||
hr = pTrigger->QueryInterface(
|
||||
IID_ILogonTrigger, (void**)&pLogonTrigger);
|
||||
pTrigger->Release();
|
||||
ExitOnFailure(hr, "QueryInterface call failed for ILogonTrigger: %x", hr);
|
||||
|
||||
hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
|
||||
if (FAILED(hr)) {
|
||||
WcaLogError(hr, "Cannot put the trigger ID: %x", hr);
|
||||
}
|
||||
|
||||
// Timing issues may make explorer not be started when the task runs.
|
||||
// Add a little delay to mitigate this.
|
||||
hr = pLogonTrigger->put_Delay(_bstr_t(L"PT03S"));
|
||||
if (FAILED(hr)) {
|
||||
WcaLogError(hr, "Cannot put the trigger delay: %x", hr);
|
||||
}
|
||||
|
||||
// Define the user. The task will execute when the user logs on.
|
||||
// The specified user must be a user on this computer.
|
||||
hr = pLogonTrigger->put_UserId(_bstr_t(username_domain));
|
||||
pLogonTrigger->Release();
|
||||
ExitOnFailure(hr, "Cannot add user ID to logon trigger: %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Add an Action to the task. This task will execute the path passed to this custom action.
|
||||
IActionCollection *pActionCollection = NULL;
|
||||
|
||||
// Get the task action collection pointer.
|
||||
hr = pTask->get_Actions(&pActionCollection);
|
||||
ExitOnFailure(hr, "Cannot get Task collection pointer: %x", hr);
|
||||
|
||||
// Create the action, specifying that it is an executable action.
|
||||
IAction *pAction = NULL;
|
||||
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
|
||||
pActionCollection->Release();
|
||||
ExitOnFailure(hr, "Cannot create the action: %x", hr);
|
||||
|
||||
IExecAction *pExecAction = NULL;
|
||||
// QI for the executable task pointer.
|
||||
hr = pAction->QueryInterface(
|
||||
IID_IExecAction, (void**)&pExecAction);
|
||||
pAction->Release();
|
||||
ExitOnFailure(hr, "QueryInterface call failed for IExecAction: %x", hr);
|
||||
|
||||
// Set the path of the executable to PowerToys (passed as CustomActionData).
|
||||
hr = pExecAction->put_Path(_bstr_t(wszExecutablePath));
|
||||
pExecAction->Release();
|
||||
ExitOnFailure(hr, "Cannot set path of executable: %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Create the principal for the task
|
||||
IPrincipal *pPrincipal = NULL;
|
||||
hr = pTask->get_Principal(&pPrincipal);
|
||||
ExitOnFailure(hr, "Cannot get principal pointer: %x", hr);
|
||||
|
||||
// Set up principal information:
|
||||
hr = pPrincipal->put_Id(_bstr_t(L"Principal1"));
|
||||
if (FAILED(hr)) {
|
||||
WcaLogError(hr, "Cannot put the principal ID: %x", hr);
|
||||
}
|
||||
|
||||
hr = pPrincipal->put_UserId(_bstr_t(username_domain));
|
||||
if (FAILED(hr)) {
|
||||
WcaLogError(hr, "Cannot put principal user Id: %x", hr);
|
||||
}
|
||||
|
||||
hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
|
||||
if (FAILED(hr)) {
|
||||
WcaLogError(hr, "Cannot put principal logon type: %x", hr);
|
||||
}
|
||||
|
||||
// Run the task with the highest available privileges.
|
||||
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
|
||||
pPrincipal->Release();
|
||||
ExitOnFailure(hr, "Cannot put principal run level: %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Save the task in the PowerToys folder.
|
||||
hr = pTaskFolder->RegisterTaskDefinition(
|
||||
_bstr_t(wstrTaskName.c_str()),
|
||||
pTask,
|
||||
TASK_CREATE_OR_UPDATE,
|
||||
_variant_t(username_domain),
|
||||
_variant_t(),
|
||||
TASK_LOGON_INTERACTIVE_TOKEN,
|
||||
_variant_t(L""),
|
||||
&pRegisteredTask);
|
||||
ExitOnFailure(hr, "Error saving the Task : %x", hr);
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "Scheduled task created for the current user.");
|
||||
|
||||
LExit:
|
||||
ReleaseStr(wszExecutablePath);
|
||||
if (pService) pService->Release();
|
||||
if (pTaskFolder) pTaskFolder->Release();
|
||||
if (pTask) pTask->Release();
|
||||
if (pRegInfo) pRegInfo->Release();
|
||||
if (pSettings) pSettings->Release();
|
||||
if (pTriggerCollection) pTriggerCollection->Release();
|
||||
if (pRegisteredTask) pRegisteredTask->Release();
|
||||
|
||||
if (!SUCCEEDED(hr)) {
|
||||
PMSIHANDLE hRecord = MsiCreateRecord(0);
|
||||
MsiRecordSetString(hRecord, 0, TEXT("Failed to create a scheduled task to start PowerToys at user login. You can re-try to create the scheduled task using the PowerToys settings."));
|
||||
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
|
||||
}
|
||||
|
||||
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://docs.microsoft.com/en-us/windows/desktop/TaskSchd/displaying-task-names-and-state--c---/
|
||||
UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall) {
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
|
||||
ITaskService *pService = NULL;
|
||||
ITaskFolder *pTaskFolder = NULL;
|
||||
IRegisteredTaskCollection* pTaskCollection = NULL;
|
||||
|
||||
hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "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,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_ITaskService,
|
||||
(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.
|
||||
WcaLog(LOGMSG_STANDARD, "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);
|
||||
|
||||
LONG numTasks = 0;
|
||||
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 = NULL;
|
||||
hr = pTaskCollection->get_Item(_variant_t(i + 1), &pRegisteredTask);
|
||||
if (SUCCEEDED(hr)) {
|
||||
BSTR taskName = NULL;
|
||||
hr = pRegisteredTask->get_Name(&taskName);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = pTaskFolder->DeleteTask(taskName, NULL);
|
||||
if (FAILED(hr)) {
|
||||
WcaLogError(hr, "Cannot delete the '%S' task: %x", taskName, hr);
|
||||
}
|
||||
SysFreeString(taskName);
|
||||
} else {
|
||||
WcaLogError(hr, "Cannot get the registered task name: %x", hr);
|
||||
}
|
||||
pRegisteredTask->Release();
|
||||
} else {
|
||||
WcaLogError(hr, "Cannot get the registered task item at index=%d: %x", i + 1, hr);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Get the pointer to the root task folder and delete the PowerToys subfolder.
|
||||
ITaskFolder *pRootFolder = NULL;
|
||||
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
|
||||
ExitOnFailure(hr, "Cannot get Root Folder pointer: %x", hr);
|
||||
hr = pRootFolder->DeleteFolder(_bstr_t(L"PowerToys"), NULL);
|
||||
pRootFolder->Release();
|
||||
ExitOnFailure(hr, "Cannot delete the PowerToys folder: %x", hr);
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "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, 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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
// 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);
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
WcaGlobalFinalize();
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
13
installer/PowerToysSetupCustomActions/CustomAction.def
Normal file
13
installer/PowerToysSetupCustomActions/CustomAction.def
Normal file
@@ -0,0 +1,13 @@
|
||||
LIBRARY "PowerToysSetupCustomActions"
|
||||
|
||||
EXPORTS
|
||||
CreateScheduledTaskCA
|
||||
RemoveScheduledTasksCA
|
||||
TelemetryLogInstallSuccessCA
|
||||
TelemetryLogInstallCancelCA
|
||||
TelemetryLogInstallFailCA
|
||||
TelemetryLogUninstallSuccessCA
|
||||
TelemetryLogUninstallCancelCA
|
||||
TelemetryLogUninstallFailCA
|
||||
TelemetryLogRepairCancelCA
|
||||
TelemetryLogRepairFailCA
|
||||
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{32f3882b-f2d6-4586-b5ed-11e39e522bd3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>PowerToysSetupCustomActions</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>inc;telemetry;$(WIX)sdk\$(WixPlatformToolset)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>inc;telemetry;$(WIX)sdk\$(WixPlatformToolset)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CustomAction.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CustomAction.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="Telemetry\ProjectTelemetry.h" />
|
||||
<ClInclude Include="Telemetry\TraceLoggingDefines.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(WixNativeCATargetsPath)" Condition=" '$(WixNativeCATargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.NativeCA.targets" Condition=" '$(WixNativeCATargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.NativeCA.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixNativeCATargetsImported)' != 'true' ">
|
||||
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
|
||||
</Target>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CustomAction.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="Telemetry\ProjectTelemetry.h">
|
||||
<Filter>Telemetry</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Telemetry\TraceLoggingDefines.h">
|
||||
<Filter>Telemetry</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CustomAction.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Telemetry">
|
||||
<UniqueIdentifier>{6e73ce5d-e715-4e7e-b796-c5d180b07ff2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <TraceLoggingProvider.h>
|
||||
#include <TraceLoggingDefines.h>
|
||||
|
||||
TRACELOGGING_DECLARE_PROVIDER(g_hProvider);
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define TraceLoggingOptionProjectTelemetry() TraceLoggingOptionGroup(0x42749043, 0x438c, 0x46a2, 0x82, 0xbe, 0xc6, 0xcb, 0xeb, 0x19, 0x2f, 0xf2)
|
||||
#define ProjectTelemetryPrivacyDataTag(tag) TraceLoggingUInt64((tag), "Ignore")
|
||||
#define ProjectTelemetryTag_ProductAndServicePerformance 0x0u
|
||||
#define PROJECT_KEYWORD_MEASURE 0x0
|
||||
4
installer/PowerToysSetupCustomActions/stdafx.cpp
Normal file
4
installer/PowerToysSetupCustomActions/stdafx.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
13
installer/PowerToysSetupCustomActions/stdafx.h
Normal file
13
installer/PowerToysSetupCustomActions/stdafx.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <msiquery.h>
|
||||
|
||||
// WiX Header Files:
|
||||
#include <wcautil.h>
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
Reference in New Issue
Block a user