chore: format PowerToys custom actions (#2104)

* chore: format PowerToys custom actions

* add curly braces
This commit is contained in:
Andrey Nekrasov
2020-04-13 16:00:51 +03:00
committed by GitHub
parent 77e4984468
commit 6bb0f18d53

View File

@@ -17,11 +17,11 @@
using namespace std; using namespace std;
TRACELOGGING_DEFINE_PROVIDER( TRACELOGGING_DEFINE_PROVIDER(
g_hProvider, g_hProvider,
"Microsoft.PowerToysInstaller", "Microsoft.PowerToysInstaller",
// {e1d8165d-5cb6-5c74-3b51-bdfbfe4f7a3b} // {e1d8165d-5cb6-5c74-3b51-bdfbfe4f7a3b}
(0xe1d8165d, 0x5cb6, 0x5c74, 0x3b, 0x51, 0xbd, 0xfb, 0xfe, 0x4f, 0x7a, 0x3b), (0xe1d8165d, 0x5cb6, 0x5c74, 0x3b, 0x51, 0xbd, 0xfb, 0xfe, 0x4f, 0x7a, 0x3b),
TraceLoggingOptionProjectTelemetry()); TraceLoggingOptionProjectTelemetry());
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0' const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0' const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
@@ -30,502 +30,562 @@ const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
// The path of the executable to run should be passed as the CustomActionData (Value). // The path of the executable to run should be passed as the CustomActionData (Value).
// Based on the Task Scheduler Logon Trigger Example: // Based on the Task Scheduler Logon Trigger Example:
// https://docs.microsoft.com/en-us/windows/win32/taskschd/logon-trigger-example--c---/ // https://docs.microsoft.com/en-us/windows/win32/taskschd/logon-trigger-example--c---/
UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall) { UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
TCHAR username_domain[USERNAME_DOMAIN_LEN]; TCHAR username_domain[USERNAME_DOMAIN_LEN];
TCHAR username[USERNAME_LEN]; TCHAR username[USERNAME_LEN];
std::wstring wstrTaskName; std::wstring wstrTaskName;
ITaskService *pService = NULL; ITaskService* pService = NULL;
ITaskFolder *pTaskFolder = NULL; ITaskFolder* pTaskFolder = NULL;
ITaskDefinition *pTask = NULL; ITaskDefinition* pTask = NULL;
IRegistrationInfo *pRegInfo = NULL; IRegistrationInfo* pRegInfo = NULL;
ITaskSettings *pSettings = NULL; ITaskSettings* pSettings = NULL;
ITriggerCollection *pTriggerCollection = NULL; ITriggerCollection* pTriggerCollection = NULL;
IRegisteredTask *pRegisteredTask = NULL; IRegisteredTask* pRegisteredTask = NULL;
hr = WcaInitialize(hInstall, "CreateScheduledTaskCA"); hr = WcaInitialize(hInstall, "CreateScheduledTaskCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized."); WcaLog(LOGMSG_STANDARD, "Initialized.");
// ------------------------------------------------------ // ------------------------------------------------------
// Get the Domain/Username for the trigger. // Get the Domain/Username for the trigger.
// //
// This action needs to run as the system to get elevated privileges from the installation, // 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. // so GetUserNameEx can't be used to get the current user details.
// The USERNAME and USERDOMAIN environment variables are used instead. // The USERNAME and USERDOMAIN environment variables are used instead.
if (!GetEnvironmentVariable(L"USERNAME", username, USERNAME_LEN)) { if (!GetEnvironmentVariable(L"USERNAME", username, USERNAME_LEN))
ExitWithLastError(hr, "Getting username failed: %x", hr); {
} 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 (!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);
// If the same task exists, remove it. WcaLog(LOGMSG_STANDARD, "Current user detected: %ls", username_domain);
pTaskFolder->DeleteTask(_bstr_t(wstrTaskName.c_str()), 0);
// Create the task builder object to create the task. // Task Name.
hr = pService->NewTask(0, &pTask); wstrTaskName = L"Autorun for ";
ExitOnFailure(hr, "Failed to create a task definition: %x", hr); wstrTaskName += username;
// ------------------------------------------------------ // Get the executable path passed to the custom action.
// Get the registration info for setting the identification. LPWSTR wszExecutablePath = NULL;
hr = pTask->get_RegistrationInfo(&pRegInfo); hr = WcaGetProperty(L"CustomActionData", &wszExecutablePath);
ExitOnFailure(hr, "Cannot get identification pointer: %x", hr); ExitOnFailure(hr, "Failed to get the executable path from CustomActionData.");
hr = pRegInfo->put_Author(_bstr_t(username_domain));
ExitOnFailure(hr, "Cannot put identification info: %x", hr);
// ------------------------------------------------------ // COM and Security Initialization is expected to have been done by the MSI.
// Create the settings for the task // It couldn't be done in the DLL, anyway.
hr = pTask->get_Settings(&pSettings); // ------------------------------------------------------
ExitOnFailure(hr, "Cannot get settings pointer: %x", hr); // 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);
hr = pSettings->put_StartWhenAvailable(VARIANT_FALSE); // Connect to the task service.
ExitOnFailure(hr, "Cannot put_StartWhenAvailable setting info: %x", hr); hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
hr = pSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE); ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
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. // Get the PowerToys task folder. Creates it if it doesn't exist.
hr = pTask->get_Triggers(&pTriggerCollection); hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder);
ExitOnFailure(hr, "Cannot get trigger collection: %x", hr); 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.");
}
// Add the logon trigger to the task. // If the same task exists, remove it.
ITrigger *pTrigger = NULL; pTaskFolder->DeleteTask(_bstr_t(wstrTaskName.c_str()), 0);
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
ExitOnFailure(hr, "Cannot create the trigger: %x", hr);
ILogonTrigger *pLogonTrigger = NULL; // Create the task builder object to create the task.
hr = pTrigger->QueryInterface( hr = pService->NewTask(0, &pTask);
IID_ILogonTrigger, (void**)&pLogonTrigger); ExitOnFailure(hr, "Failed to create a task definition: %x", hr);
pTrigger->Release();
ExitOnFailure(hr, "QueryInterface call failed for ILogonTrigger: %x", hr);
hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1")); // ------------------------------------------------------
if (FAILED(hr)) { // Get the registration info for setting the identification.
WcaLogError(hr, "Cannot put the trigger ID: %x", hr); 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);
// Timing issues may make explorer not be started when the task runs. // ------------------------------------------------------
// Add a little delay to mitigate this. // Create the settings for the task
hr = pLogonTrigger->put_Delay(_bstr_t(L"PT03S")); hr = pTask->get_Settings(&pSettings);
if (FAILED(hr)) { ExitOnFailure(hr, "Cannot get settings pointer: %x", hr);
WcaLogError(hr, "Cannot put the trigger delay: %x", hr);
}
// Define the user. The task will execute when the user logs on. hr = pSettings->put_StartWhenAvailable(VARIANT_FALSE);
// The specified user must be a user on this computer. ExitOnFailure(hr, "Cannot put_StartWhenAvailable setting info: %x", hr);
hr = pLogonTrigger->put_UserId(_bstr_t(username_domain)); hr = pSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
pLogonTrigger->Release(); ExitOnFailure(hr, "Cannot put_StopIfGoingOnBatteries setting info: %x", hr);
ExitOnFailure(hr, "Cannot add user ID to logon trigger: %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);
// ------------------------------------------------------ // ------------------------------------------------------
// Add an Action to the task. This task will execute the path passed to this custom action. // Get the trigger collection to insert the logon trigger.
IActionCollection *pActionCollection = NULL; hr = pTask->get_Triggers(&pTriggerCollection);
ExitOnFailure(hr, "Cannot get trigger collection: %x", hr);
// Get the task action collection pointer. // Add the logon trigger to the task.
hr = pTask->get_Actions(&pActionCollection); ITrigger* pTrigger = NULL;
ExitOnFailure(hr, "Cannot get Task collection pointer: %x", hr); hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
ExitOnFailure(hr, "Cannot create the trigger: %x", hr);
// Create the action, specifying that it is an executable action. ILogonTrigger* pLogonTrigger = NULL;
IAction *pAction = NULL; hr = pTrigger->QueryInterface(
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction); IID_ILogonTrigger, (void**)&pLogonTrigger);
pActionCollection->Release(); pTrigger->Release();
ExitOnFailure(hr, "Cannot create the action: %x", hr); ExitOnFailure(hr, "QueryInterface call failed for ILogonTrigger: %x", hr);
IExecAction *pExecAction = NULL; hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
// QI for the executable task pointer. if (FAILED(hr))
hr = pAction->QueryInterface( {
IID_IExecAction, (void**)&pExecAction); WcaLogError(hr, "Cannot put the trigger ID: %x", hr);
pAction->Release(); }
ExitOnFailure(hr, "QueryInterface call failed for IExecAction: %x", hr);
// Set the path of the executable to PowerToys (passed as CustomActionData). // Timing issues may make explorer not be started when the task runs.
hr = pExecAction->put_Path(_bstr_t(wszExecutablePath)); // Add a little delay to mitigate this.
pExecAction->Release(); hr = pLogonTrigger->put_Delay(_bstr_t(L"PT03S"));
ExitOnFailure(hr, "Cannot set path of executable: %x", hr); if (FAILED(hr))
{
WcaLogError(hr, "Cannot put the trigger delay: %x", hr);
}
// ------------------------------------------------------ // Define the user. The task will execute when the user logs on.
// Create the principal for the task // The specified user must be a user on this computer.
IPrincipal *pPrincipal = NULL; hr = pLogonTrigger->put_UserId(_bstr_t(username_domain));
hr = pTask->get_Principal(&pPrincipal); pLogonTrigger->Release();
ExitOnFailure(hr, "Cannot get principal pointer: %x", hr); ExitOnFailure(hr, "Cannot add user ID to logon trigger: %x", hr);
// Set up principal information: // ------------------------------------------------------
hr = pPrincipal->put_Id(_bstr_t(L"Principal1")); // Add an Action to the task. This task will execute the path passed to this custom action.
if (FAILED(hr)) { IActionCollection* pActionCollection = NULL;
WcaLogError(hr, "Cannot put the principal ID: %x", hr);
}
hr = pPrincipal->put_UserId(_bstr_t(username_domain)); // Get the task action collection pointer.
if (FAILED(hr)) { hr = pTask->get_Actions(&pActionCollection);
WcaLogError(hr, "Cannot put principal user Id: %x", hr); ExitOnFailure(hr, "Cannot get Task collection pointer: %x", hr);
}
hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN); // Create the action, specifying that it is an executable action.
if (FAILED(hr)) { IAction* pAction = NULL;
WcaLogError(hr, "Cannot put principal logon type: %x", hr); hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
} pActionCollection->Release();
ExitOnFailure(hr, "Cannot create the action: %x", hr);
// Run the task with the highest available privileges. IExecAction* pExecAction = NULL;
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_LUA); // QI for the executable task pointer.
pPrincipal->Release(); hr = pAction->QueryInterface(
ExitOnFailure(hr, "Cannot put principal run level: %x", hr); 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).
// Save the task in the PowerToys folder. hr = pExecAction->put_Path(_bstr_t(wszExecutablePath));
{ pExecAction->Release();
_variant_t SDDL_FULL_ACCESS_FOR_EVERYONE = L"D:(A;;FA;;;WD)"; ExitOnFailure(hr, "Cannot set path of executable: %x", hr);
hr = pTaskFolder->RegisterTaskDefinition(
_bstr_t(wstrTaskName.c_str()),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(username_domain),
_variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN,
SDDL_FULL_ACCESS_FOR_EVERYONE,
&pRegisteredTask);
ExitOnFailure(hr, "Error saving the Task : %x", hr);
}
WcaLog(LOGMSG_STANDARD, "Scheduled task created for the current user."); // ------------------------------------------------------
// 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_LUA);
pPrincipal->Release();
ExitOnFailure(hr, "Cannot put principal run level: %x", hr);
// ------------------------------------------------------
// Save the task in the PowerToys folder.
{
_variant_t SDDL_FULL_ACCESS_FOR_EVERYONE = L"D:(A;;FA;;;WD)";
hr = pTaskFolder->RegisterTaskDefinition(
_bstr_t(wstrTaskName.c_str()),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(username_domain),
_variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN,
SDDL_FULL_ACCESS_FOR_EVERYONE,
&pRegisteredTask);
ExitOnFailure(hr, "Error saving the Task : %x", hr);
}
WcaLog(LOGMSG_STANDARD, "Scheduled task created for the current user.");
LExit: LExit:
ReleaseStr(wszExecutablePath); ReleaseStr(wszExecutablePath);
if (pService) pService->Release(); if (pService)
if (pTaskFolder) pTaskFolder->Release(); {
if (pTask) pTask->Release(); pService->Release();
if (pRegInfo) pRegInfo->Release(); }
if (pSettings) pSettings->Release(); if (pTaskFolder)
if (pTriggerCollection) pTriggerCollection->Release(); {
if (pRegisteredTask) pRegisteredTask->Release(); 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)) { 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.")); PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord); 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; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
// Removes all Scheduled Tasks in the PowerToys folder and deletes the folder afterwards. // Removes all Scheduled Tasks in the PowerToys folder and deletes the folder afterwards.
// Based on the Task Scheduler Displaying Task Names and State example: // 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---/ // https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/displaying-task-names-and-state--c---/
UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall) { UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
ITaskService *pService = NULL; ITaskService* pService = NULL;
ITaskFolder *pTaskFolder = NULL; ITaskFolder* pTaskFolder = NULL;
IRegisteredTaskCollection* pTaskCollection = NULL; IRegisteredTaskCollection* pTaskCollection = NULL;
hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA"); hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized."); WcaLog(LOGMSG_STANDARD, "Initialized.");
// COM and Security Initialization is expected to have been done by the MSI. // COM and Security Initialization is expected to have been done by the MSI.
// It couldn't be done in the DLL, anyway. // It couldn't be done in the DLL, anyway.
// ------------------------------------------------------ // ------------------------------------------------------
// Create an instance of the Task Service. // Create an instance of the Task Service.
hr = CoCreateInstance(CLSID_TaskScheduler, hr = CoCreateInstance(CLSID_TaskScheduler,
NULL, NULL,
CLSCTX_INPROC_SERVER, CLSCTX_INPROC_SERVER,
IID_ITaskService, IID_ITaskService,
(void**)&pService); (void**)&pService);
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr); ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service. // Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
_variant_t(), _variant_t()); ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
// ------------------------------------------------------ // ------------------------------------------------------
// Get the PowerToys task folder. // Get the PowerToys task folder.
hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder); hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder);
if (FAILED(hr)) { 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."); // Folder doesn't exist. No need to delete anything.
hr = S_OK; WcaLog(LOGMSG_STANDARD, "The PowerToys scheduled task folder wasn't found. Nothing to delete.");
ExitFunction(); 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. // Get the registered tasks in the folder.
ITaskFolder *pRootFolder = NULL; hr = pTaskFolder->GetTasks(TASK_ENUM_HIDDEN, &pTaskCollection);
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder); ExitOnFailure(hr, "Cannot get the registered tasks: %x", hr);
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."); 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: LExit:
if (pService) pService->Release(); if (pService)
if (pTaskFolder) pTaskFolder->Release(); {
if (pTaskCollection) pTaskCollection->Release(); pService->Release();
}
if (pTaskFolder)
{
pTaskFolder->Release();
}
if (pTaskCollection)
{
pTaskCollection->Release();
}
if (!SUCCEEDED(hr)) { 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.")); PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord); 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; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogInstallSuccessCA"); hr = WcaInitialize(hInstall, "TelemetryLogInstallSuccessCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"Install_Success", "Install_Success",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogInstallCancelCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogInstallCancelCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogInstallCancelCA"); hr = WcaInitialize(hInstall, "TelemetryLogInstallCancelCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"Install_Cancel", "Install_Cancel",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogInstallFailCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogInstallFailCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogInstallFailCA"); hr = WcaInitialize(hInstall, "TelemetryLogInstallFailCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"Install_Fail", "Install_Fail",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogUninstallSuccessCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogUninstallSuccessCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogUninstallSuccessCA"); hr = WcaInitialize(hInstall, "TelemetryLogUninstallSuccessCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"UnInstall_Success", "UnInstall_Success",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogUninstallCancelCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogUninstallCancelCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogUninstallCancelCA"); hr = WcaInitialize(hInstall, "TelemetryLogUninstallCancelCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"UnInstall_Cancel", "UnInstall_Cancel",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogUninstallFailCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogUninstallFailCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogUninstallFailCA"); hr = WcaInitialize(hInstall, "TelemetryLogUninstallFailCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"UnInstall_Fail", "UnInstall_Fail",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogRepairCancelCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogRepairCancelCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogRepairCancelCA"); hr = WcaInitialize(hInstall, "TelemetryLogRepairCancelCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"Repair_Cancel", "Repair_Cancel",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
UINT __stdcall TelemetryLogRepairFailCA(MSIHANDLE hInstall) { UINT __stdcall TelemetryLogRepairFailCA(MSIHANDLE hInstall)
HRESULT hr = S_OK; {
UINT er = ERROR_SUCCESS; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "TelemetryLogRepairFailCA"); hr = WcaInitialize(hInstall, "TelemetryLogRepairFailCA");
ExitOnFailure(hr, "Failed to initialize"); ExitOnFailure(hr, "Failed to initialize");
TraceLoggingWrite( TraceLoggingWrite(
g_hProvider, g_hProvider,
"Repair_Fail", "Repair_Fail",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
LExit: LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er); return WcaFinalize(er);
} }
// DllMain - Initialize and cleanup WiX custom action utils. // DllMain - Initialize and cleanup WiX custom action utils.
extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID) { extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID)
switch (ulReason) { {
case DLL_PROCESS_ATTACH: switch (ulReason)
WcaGlobalInitialize(hInst); {
TraceLoggingRegister(g_hProvider); case DLL_PROCESS_ATTACH:
break; WcaGlobalInitialize(hInst);
TraceLoggingRegister(g_hProvider);
break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
TraceLoggingUnregister(g_hProvider); TraceLoggingUnregister(g_hProvider);
WcaGlobalFinalize(); WcaGlobalFinalize();
break; break;
} }
return TRUE; return TRUE;
} }