CustomAction.cpp
1 #include "pch.h" 2 #include "resource.h" 3 #include "RcResource.h" 4 #include <ProjectTelemetry.h> 5 #include <spdlog/sinks/base_sink.h> 6 #include <filesystem> 7 #include <string_view> 8 9 #include "../../src/common/logger/logger.h" 10 #include "../../src/common/utils/gpo.h" 11 #include "../../src/common/utils/MsiUtils.h" 12 #include "../../src/common/utils/modulesRegistry.h" 13 #include "../../src/common/updating/installer.h" 14 #include "../../src/common/version/version.h" 15 #include "../../src/common/Telemetry/EtwTrace/EtwTrace.h" 16 #include "../../src/common/utils/package.h" 17 #include "../../src/common/utils/clean_video_conference.h" 18 19 #include <winrt/Windows.ApplicationModel.h> 20 #include <winrt/Windows.Foundation.h> 21 #include <winrt/Windows.Management.Deployment.h> 22 #include <winrt/Windows.Security.Credentials.h> 23 24 #include <wtsapi32.h> 25 #include <processthreadsapi.h> 26 #include <UserEnv.h> 27 #include <winnt.h> 28 29 using namespace std; 30 31 HINSTANCE DLL_HANDLE = nullptr; 32 33 TRACELOGGING_DEFINE_PROVIDER( 34 g_hProvider, 35 "Microsoft.PowerToys", 36 // {38e8889b-9731-53f5-e901-e8a7c1753074} 37 (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74), 38 TraceLoggingOptionProjectTelemetry()); 39 40 const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0' 41 const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0' 42 43 static const wchar_t *POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; 44 static const wchar_t *POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}"; 45 46 constexpr inline const wchar_t *DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys"; 47 constexpr inline const wchar_t *DataDiagnosticsRegValueName = L"AllowDataDiagnostics"; 48 49 #define TraceLoggingWriteWrapper(provider, eventName, ...) \ 50 if (isDataDiagnosticEnabled()) \ 51 { \ 52 trace.UpdateState(true); \ 53 TraceLoggingWrite(provider, eventName, __VA_ARGS__); \ 54 trace.Flush(); \ 55 trace.UpdateState(false); \ 56 } 57 58 static Shared::Trace::ETWTrace trace{L"PowerToys_Installer"}; 59 60 inline bool isDataDiagnosticEnabled() 61 { 62 HKEY key{}; 63 if (RegOpenKeyExW(HKEY_CURRENT_USER, 64 DataDiagnosticsRegKey, 65 0, 66 KEY_READ, 67 &key) != ERROR_SUCCESS) 68 { 69 return false; 70 } 71 72 DWORD isDataDiagnosticsEnabled = 0; 73 DWORD size = sizeof(isDataDiagnosticsEnabled); 74 75 if (RegGetValueW( 76 HKEY_CURRENT_USER, 77 DataDiagnosticsRegKey, 78 DataDiagnosticsRegValueName, 79 RRF_RT_REG_DWORD, 80 nullptr, 81 &isDataDiagnosticsEnabled, 82 &size) != ERROR_SUCCESS) 83 { 84 RegCloseKey(key); 85 return false; 86 } 87 RegCloseKey(key); 88 89 return isDataDiagnosticsEnabled == 1; 90 } 91 92 HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring &installationDir) 93 { 94 DWORD len = 0; 95 wchar_t _[1]; 96 MsiGetPropertyW(hInstall, L"CustomActionData", _, &len); 97 len += 1; 98 installationDir.resize(len); 99 HRESULT hr = MsiGetPropertyW(hInstall, L"CustomActionData", installationDir.data(), &len); 100 if (installationDir.length()) 101 { 102 installationDir.resize(installationDir.length() - 1); 103 } 104 ExitOnFailure(hr, "Failed to get INSTALLFOLDER property."); 105 LExit: 106 return hr; 107 } 108 109 BOOL IsLocalSystem() 110 { 111 HANDLE hToken; 112 UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES]; 113 PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser; 114 ULONG cbTokenUser; 115 SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; 116 PSID pSystemSid; 117 BOOL bSystem; 118 119 // open process token 120 if (!OpenProcessToken(GetCurrentProcess(), 121 TOKEN_QUERY, 122 &hToken)) 123 return FALSE; 124 125 // retrieve user SID 126 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, 127 sizeof(bTokenUser), &cbTokenUser)) 128 { 129 CloseHandle(hToken); 130 return FALSE; 131 } 132 133 CloseHandle(hToken); 134 135 // allocate LocalSystem well-known SID 136 if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID, 137 0, 0, 0, 0, 0, 0, 0, &pSystemSid)) 138 return FALSE; 139 140 // compare the user SID from the token with the LocalSystem SID 141 bSystem = EqualSid(pTokenUser->User.Sid, pSystemSid); 142 143 FreeSid(pSystemSid); 144 145 return bSystem; 146 } 147 148 BOOL ImpersonateLoggedInUserAndDoSomething(std::function<bool(HANDLE userToken)> action) 149 { 150 HRESULT hr = S_OK; 151 HANDLE hUserToken = NULL; 152 DWORD dwSessionId; 153 ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId); 154 auto rv = WTSQueryUserToken(dwSessionId, &hUserToken); 155 156 if (rv == 0) 157 { 158 hr = E_ABORT; 159 ExitOnFailure(hr, "Failed to query user token"); 160 } 161 162 HANDLE hUserTokenDup; 163 if (DuplicateTokenEx(hUserToken, TOKEN_ALL_ACCESS, NULL, SECURITY_IMPERSONATION_LEVEL::SecurityImpersonation, TOKEN_TYPE::TokenPrimary, &hUserTokenDup) == 0) 164 { 165 CloseHandle(hUserToken); 166 CloseHandle(hUserTokenDup); 167 hr = E_ABORT; 168 ExitOnFailure(hr, "Failed to duplicate user token"); 169 } 170 171 if (ImpersonateLoggedOnUser(hUserTokenDup)) 172 { 173 if (!action(hUserTokenDup)) 174 { 175 hr = E_ABORT; 176 ExitOnFailure(hr, "Failed to execute action"); 177 } 178 179 RevertToSelf(); 180 CloseHandle(hUserToken); 181 CloseHandle(hUserTokenDup); 182 } 183 else 184 { 185 hr = E_ABORT; 186 ExitOnFailure(hr, "Failed to duplicate user token"); 187 } 188 189 LExit: 190 return SUCCEEDED(hr); 191 } 192 193 static std::filesystem::path GetUserPowerShellModulesPath() 194 { 195 PWSTR myDocumentsBlockPtr; 196 197 if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &myDocumentsBlockPtr))) 198 { 199 const std::wstring myDocuments{myDocumentsBlockPtr}; 200 CoTaskMemFree(myDocumentsBlockPtr); 201 return std::filesystem::path(myDocuments) / "PowerShell" / "Modules"; 202 } 203 else 204 { 205 CoTaskMemFree(myDocumentsBlockPtr); 206 return {}; 207 } 208 } 209 210 UINT __stdcall LaunchPowerToysCA(MSIHANDLE hInstall) 211 { 212 HRESULT hr = S_OK; 213 UINT er = ERROR_SUCCESS; 214 std::wstring installationFolder, path, args; 215 std::wstring commandLine; 216 217 hr = WcaInitialize(hInstall, "LaunchPowerToys"); 218 ExitOnFailure(hr, "Failed to initialize"); 219 hr = getInstallFolder(hInstall, installationFolder); 220 ExitOnFailure(hr, "Failed to get installFolder."); 221 222 path = installationFolder; 223 path += L"\\PowerToys.exe"; 224 225 args = L"--dont-elevate"; 226 227 commandLine = L"\"" + path + L"\" "; 228 commandLine += args; 229 230 BOOL isSystemUser = IsLocalSystem(); 231 232 if (isSystemUser) 233 { 234 235 auto action = [&commandLine](HANDLE userToken) 236 { 237 STARTUPINFO startupInfo = { 0 }; 238 startupInfo.cb = sizeof(STARTUPINFO); 239 startupInfo.wShowWindow = SW_SHOWNORMAL; 240 PROCESS_INFORMATION processInformation; 241 242 PVOID lpEnvironment = NULL; 243 CreateEnvironmentBlock(&lpEnvironment, userToken, FALSE); 244 245 CreateProcessAsUser( 246 userToken, 247 NULL, 248 commandLine.data(), 249 NULL, 250 NULL, 251 FALSE, 252 CREATE_DEFAULT_ERROR_MODE | CREATE_UNICODE_ENVIRONMENT, 253 lpEnvironment, 254 NULL, 255 &startupInfo, 256 &processInformation); 257 258 if (!CloseHandle(processInformation.hProcess)) 259 { 260 return false; 261 } 262 if (!CloseHandle(processInformation.hThread)) 263 { 264 return false; 265 } 266 267 return true; 268 }; 269 270 if (!ImpersonateLoggedInUserAndDoSomething(action)) 271 { 272 hr = E_ABORT; 273 ExitOnFailure(hr, "ImpersonateLoggedInUserAndDoSomething failed"); 274 } 275 } 276 else 277 { 278 STARTUPINFO startupInfo = { 0 }; 279 startupInfo.cb = sizeof(STARTUPINFO); 280 startupInfo.wShowWindow = SW_SHOWNORMAL; 281 282 PROCESS_INFORMATION processInformation; 283 284 // Start the resizer 285 CreateProcess( 286 NULL, 287 commandLine.data(), 288 NULL, 289 NULL, 290 TRUE, 291 0, 292 NULL, 293 NULL, 294 &startupInfo, 295 &processInformation); 296 297 if (!CloseHandle(processInformation.hProcess)) 298 { 299 hr = E_ABORT; 300 ExitOnFailure(hr, "Failed to close process handle"); 301 } 302 if (!CloseHandle(processInformation.hThread)) 303 { 304 hr = E_ABORT; 305 ExitOnFailure(hr, "Failed to close thread handle"); 306 } 307 } 308 309 LExit: 310 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 311 return WcaFinalize(er); 312 } 313 314 UINT __stdcall CheckGPOCA(MSIHANDLE hInstall) 315 { 316 HRESULT hr = S_OK; 317 318 hr = WcaInitialize(hInstall, "CheckGPOCA"); 319 ExitOnFailure(hr, "Failed to initialize"); 320 321 LPWSTR currentScope = nullptr; 322 hr = WcaGetProperty(L"InstallScope", ¤tScope); 323 324 if (std::wstring{currentScope} == L"perUser") 325 { 326 if (powertoys_gpo::getDisablePerUserInstallationValue() == powertoys_gpo::gpo_rule_configured_enabled) 327 { 328 PMSIHANDLE hRecord = MsiCreateRecord(0); 329 MsiRecordSetString(hRecord, 0, TEXT("The system administrator has disabled per-user installation.")); 330 MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_ERROR + MB_OK), hRecord); 331 hr = E_ABORT; 332 } 333 } 334 335 LExit: 336 UINT er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 337 return WcaFinalize(er); 338 } 339 340 // We've deprecated Video Conference Mute. This Custom Action cleans up any stray registry entry for the driver dll. 341 UINT __stdcall CleanVideoConferenceRegistryCA(MSIHANDLE hInstall) 342 { 343 HRESULT hr = S_OK; 344 UINT er = ERROR_SUCCESS; 345 hr = WcaInitialize(hInstall, "CleanVideoConferenceRegistry"); 346 ExitOnFailure(hr, "Failed to initialize"); 347 clean_video_conference(); 348 LExit: 349 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 350 return WcaFinalize(er); 351 } 352 353 UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall) 354 { 355 HRESULT hr = S_OK; 356 UINT er = ERROR_SUCCESS; 357 std::wstring installationFolder; 358 bool failedToApply = false; 359 360 hr = WcaInitialize(hInstall, "ApplyModulesRegistryChangeSets"); 361 ExitOnFailure(hr, "Failed to initialize"); 362 hr = getInstallFolder(hInstall, installationFolder); 363 ExitOnFailure(hr, "Failed to get installFolder."); 364 365 for (const auto &changeSet : getAllOnByDefaultModulesChangeSets(installationFolder)) 366 { 367 if (!changeSet.apply()) 368 { 369 Logger::error(L"Couldn't apply registry changeSet"); 370 failedToApply = true; 371 } 372 } 373 374 if (!failedToApply) 375 { 376 Logger::info(L"All registry changeSets applied successfully"); 377 } 378 LExit: 379 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 380 return WcaFinalize(er); 381 } 382 383 UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall) 384 { 385 HRESULT hr = S_OK; 386 UINT er = ERROR_SUCCESS; 387 std::wstring installationFolder; 388 389 hr = WcaInitialize(hInstall, "UndoModulesRegistryChangeSets"); // original func name is too long 390 ExitOnFailure(hr, "Failed to initialize"); 391 hr = getInstallFolder(hInstall, installationFolder); 392 ExitOnFailure(hr, "Failed to get installFolder."); 393 for (const auto &changeSet : getAllModulesChangeSets(installationFolder)) 394 { 395 changeSet.unApply(); 396 } 397 398 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 399 400 ExitOnFailure(hr, "Failed to extract msix"); 401 402 LExit: 403 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 404 return WcaFinalize(er); 405 } 406 407 const wchar_t *DSC_CONFIGURE_PSD1_NAME = L"Microsoft.PowerToys.Configure.psd1"; 408 const wchar_t *DSC_CONFIGURE_PSM1_NAME = L"Microsoft.PowerToys.Configure.psm1"; 409 410 UINT __stdcall InstallDSCModuleCA(MSIHANDLE hInstall) 411 { 412 HRESULT hr = S_OK; 413 UINT er = ERROR_SUCCESS; 414 std::wstring installationFolder; 415 416 hr = WcaInitialize(hInstall, "InstallDSCModuleCA"); 417 ExitOnFailure(hr, "Failed to initialize"); 418 419 hr = getInstallFolder(hInstall, installationFolder); 420 ExitOnFailure(hr, "Failed to get installFolder."); 421 422 { 423 const auto baseModulesPath = GetUserPowerShellModulesPath(); 424 if (baseModulesPath.empty()) 425 { 426 hr = E_FAIL; 427 ExitOnFailure(hr, "Unable to determine Powershell modules path"); 428 } 429 430 const auto modulesPath = baseModulesPath / L"Microsoft.PowerToys.Configure" / (get_product_version(false) + L".0"); 431 432 std::error_code errorCode; 433 std::filesystem::create_directories(modulesPath, errorCode); 434 if (errorCode) 435 { 436 hr = E_FAIL; 437 ExitOnFailure(hr, "Unable to create Powershell modules folder"); 438 } 439 440 for (const auto *filename : {DSC_CONFIGURE_PSD1_NAME, DSC_CONFIGURE_PSM1_NAME}) 441 { 442 std::filesystem::copy_file(std::filesystem::path(installationFolder) / "DSCModules" / filename, modulesPath / filename, std::filesystem::copy_options::overwrite_existing, errorCode); 443 444 if (errorCode) 445 { 446 hr = E_FAIL; 447 ExitOnFailure(hr, "Unable to copy Powershell modules file"); 448 } 449 } 450 } 451 452 LExit: 453 if (SUCCEEDED(hr)) 454 { 455 er = ERROR_SUCCESS; 456 Logger::info(L"DSC module was installed!"); 457 } 458 else 459 { 460 er = ERROR_INSTALL_FAILURE; 461 Logger::error(L"Couldn't install DSC module!"); 462 } 463 464 return WcaFinalize(er); 465 } 466 467 UINT __stdcall UninstallDSCModuleCA(MSIHANDLE hInstall) 468 { 469 HRESULT hr = S_OK; 470 UINT er = ERROR_SUCCESS; 471 472 hr = WcaInitialize(hInstall, "UninstallDSCModuleCA"); 473 ExitOnFailure(hr, "Failed to initialize"); 474 475 { 476 const auto baseModulesPath = GetUserPowerShellModulesPath(); 477 if (baseModulesPath.empty()) 478 { 479 hr = E_FAIL; 480 ExitOnFailure(hr, "Unable to determine Powershell modules path"); 481 } 482 483 const auto powerToysModulePath = baseModulesPath / L"Microsoft.PowerToys.Configure"; 484 const auto versionedModulePath = powerToysModulePath / (get_product_version(false) + L".0"); 485 486 std::error_code errorCode; 487 488 for (const auto *filename : {DSC_CONFIGURE_PSD1_NAME, DSC_CONFIGURE_PSM1_NAME}) 489 { 490 std::filesystem::remove(versionedModulePath / filename, errorCode); 491 492 if (errorCode) 493 { 494 hr = E_FAIL; 495 ExitOnFailure(hr, "Unable to delete DSC file"); 496 } 497 } 498 499 for (const auto *modulePath : {&versionedModulePath, &powerToysModulePath}) 500 { 501 std::filesystem::remove(*modulePath, errorCode); 502 503 if (errorCode) 504 { 505 hr = E_FAIL; 506 ExitOnFailure(hr, "Unable to delete DSC folder"); 507 } 508 } 509 } 510 511 LExit: 512 if (SUCCEEDED(hr)) 513 { 514 er = ERROR_SUCCESS; 515 Logger::info(L"DSC module was uninstalled!"); 516 } 517 else 518 { 519 er = ERROR_INSTALL_FAILURE; 520 Logger::error(L"Couldn't uninstall DSC module!"); 521 } 522 523 return WcaFinalize(er); 524 } 525 526 UINT __stdcall InstallEmbeddedMSIXCA(MSIHANDLE hInstall) 527 { 528 HRESULT hr = S_OK; 529 UINT er = ERROR_SUCCESS; 530 hr = WcaInitialize(hInstall, "InstallEmbeddedMSIXCA"); 531 ExitOnFailure(hr, "Failed to initialize"); 532 533 if (auto msix = RcResource::create(IDR_BIN_MSIX_HELLO_PACKAGE, L"BIN", DLL_HANDLE)) 534 { 535 Logger::info(L"Extracted MSIX"); 536 // TODO: Use to activate embedded MSIX 537 const auto msix_path = std::filesystem::temp_directory_path() / "hello_package.msix"; 538 if (!msix->saveAsFile(msix_path)) 539 { 540 ExitOnFailure(hr, "Failed to save msix"); 541 } 542 Logger::info(L"Saved MSIX"); 543 using namespace winrt::Windows::Management::Deployment; 544 using namespace winrt::Windows::Foundation; 545 546 Uri msix_uri{msix_path.wstring()}; 547 PackageManager pm; 548 auto result = pm.AddPackageAsync(msix_uri, nullptr, DeploymentOptions::None).get(); 549 if (!result) 550 { 551 ExitOnFailure(hr, "Failed to AddPackage"); 552 } 553 554 Logger::info(L"MSIX[s] were installed!"); 555 } 556 else 557 { 558 ExitOnFailure(hr, "Failed to extract msix"); 559 } 560 561 LExit: 562 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 563 return WcaFinalize(er); 564 } 565 566 UINT __stdcall UninstallEmbeddedMSIXCA(MSIHANDLE hInstall) 567 { 568 HRESULT hr = S_OK; 569 UINT er = ERROR_SUCCESS; 570 using namespace winrt::Windows::Management::Deployment; 571 using namespace winrt::Windows::Foundation; 572 // TODO: This must be replaced with the actual publisher and package name 573 const wchar_t package_name[] = L"46b35c25-b593-48d5-aeb1-d3e9c3b796e9"; 574 const wchar_t publisher[] = L"CN=yuyoyuppe"; 575 PackageManager pm; 576 577 hr = WcaInitialize(hInstall, "UninstallEmbeddedMSIXCA"); 578 ExitOnFailure(hr, "Failed to initialize"); 579 580 for (const auto &p : pm.FindPackagesForUser({}, package_name, publisher)) 581 { 582 auto result = pm.RemovePackageAsync(p.Id().FullName()).get(); 583 if (result) 584 { 585 Logger::info(L"MSIX was uninstalled!"); 586 } 587 else 588 { 589 Logger::error(L"Couldn't uninstall MSIX!"); 590 } 591 } 592 593 LExit: 594 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 595 return WcaFinalize(er); 596 } 597 598 UINT __stdcall InstallPackageIdentityMSIXCA(MSIHANDLE hInstall) 599 { 600 HRESULT hr = S_OK; 601 UINT er = ERROR_SUCCESS; 602 LPWSTR customActionData = nullptr; 603 std::wstring installFolderPath; 604 std::wstring installScope; 605 std::wstring msixPath; 606 std::wstring data; 607 size_t delimiterPos; 608 bool isMachineLevel = false; 609 610 hr = WcaInitialize(hInstall, "InstallPackageIdentityMSIXCA"); 611 ExitOnFailure(hr, "Failed to initialize"); 612 613 hr = WcaGetProperty(L"CustomActionData", &customActionData); 614 ExitOnFailure(hr, "Failed to get CustomActionData property"); 615 616 // Parse CustomActionData: "[INSTALLFOLDER];[InstallScope]" 617 data = customActionData; 618 delimiterPos = data.find(L';'); 619 installFolderPath = data.substr(0, delimiterPos); 620 installScope = data.substr(delimiterPos + 1); 621 622 // Check if this is a machine-level installation 623 if (installScope == L"perMachine") 624 { 625 isMachineLevel = true; 626 } 627 628 Logger::info(L"Installing PackageIdentity MSIX - perUser: {}", !isMachineLevel); 629 630 // Construct path to PackageIdentity MSIX 631 msixPath = installFolderPath; 632 msixPath += L"PowerToysSparse.msix"; 633 634 if (std::filesystem::exists(msixPath)) 635 { 636 using namespace winrt::Windows::Management::Deployment; 637 using namespace winrt::Windows::Foundation; 638 639 try 640 { 641 642 std::wstring externalLocation = installFolderPath; // External content location (PowerToys install folder) 643 Uri externalUri{ externalLocation }; // External location URI for sparse package content 644 Uri packageUri{ msixPath }; // The MSIX file URI 645 646 PackageManager packageManager; 647 648 if (isMachineLevel) 649 { 650 // Machine-level installation 651 652 StagePackageOptions stageOptions; 653 stageOptions.ExternalLocationUri(externalUri); 654 655 auto stageResult = packageManager.StagePackageByUriAsync(packageUri, stageOptions).get(); 656 657 uint32_t stageErrorCode = static_cast<uint32_t>(stageResult.ExtendedErrorCode()); 658 if (stageErrorCode == 0) 659 { 660 std::wstring packageFamilyName = L"Microsoft.PowerToys.SparseApp_8wekyb3d8bbwe"; 661 662 try 663 { 664 auto provisionResult = packageManager.ProvisionPackageForAllUsersAsync(packageFamilyName).get(); 665 uint32_t provisionErrorCode = static_cast<uint32_t>(provisionResult.ExtendedErrorCode()); 666 667 if (provisionErrorCode != 0) 668 { 669 Logger::error(L"Machine-level provisioning failed: 0x{:08X}", provisionErrorCode); 670 } 671 } 672 catch (const winrt::hresult_error& ex) 673 { 674 Logger::error(L"Provisioning exception: HRESULT 0x{:08X}", static_cast<uint32_t>(ex.code())); 675 } 676 } 677 else 678 { 679 Logger::error(L"Package staging failed: 0x{:08X}", stageErrorCode); 680 } 681 } 682 else 683 { 684 AddPackageOptions addOptions; 685 addOptions.ExternalLocationUri(externalUri); 686 687 auto addResult = packageManager.AddPackageByUriAsync(packageUri, addOptions).get(); 688 689 if (!addResult.IsRegistered()) 690 { 691 uint32_t errorCode = static_cast<uint32_t>(addResult.ExtendedErrorCode()); 692 Logger::error(L"Per-user installation failed: 0x{:08X}", errorCode); 693 } 694 } 695 } 696 catch (const std::exception& ex) 697 { 698 Logger::error(L"PackageIdentity MSIX installation failed - Exception: {}", 699 winrt::to_hstring(ex.what()).c_str()); 700 } 701 } 702 else 703 { 704 Logger::error(L"PackageIdentity MSIX not found: " + msixPath); 705 } 706 707 LExit: 708 ReleaseStr(customActionData); 709 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 710 return WcaFinalize(er); 711 } 712 713 UINT __stdcall UninstallPackageIdentityMSIXCA(MSIHANDLE hInstall) 714 { 715 HRESULT hr = S_OK; 716 UINT er = ERROR_SUCCESS; 717 using namespace winrt::Windows::Management::Deployment; 718 using namespace winrt::Windows::Foundation; 719 720 LPWSTR installScope = nullptr; 721 bool isMachineLevel = false; 722 723 PackageManager pm; 724 725 hr = WcaInitialize(hInstall, "UninstallPackageIdentityMSIXCA"); 726 ExitOnFailure(hr, "Failed to initialize"); 727 728 // Check if this was a machine-level installation 729 hr = WcaGetProperty(L"InstallScope", &installScope); 730 if (SUCCEEDED(hr) && installScope && wcscmp(installScope, L"perMachine") == 0) 731 { 732 isMachineLevel = true; 733 } 734 735 Logger::info(L"Uninstalling PackageIdentity MSIX - perUser: {}", !isMachineLevel); 736 737 try 738 { 739 std::wstring packageFamilyName = L"Microsoft.PowerToys.SparseApp_8wekyb3d8bbwe"; 740 741 if (isMachineLevel) 742 { 743 // Machine-level uninstallation: deprovision + remove for all users 744 745 // First deprovision the package 746 try 747 { 748 auto deprovisionResult = pm.DeprovisionPackageForAllUsersAsync(packageFamilyName).get(); 749 if (deprovisionResult.IsRegistered()) 750 { 751 Logger::warn(L"Machine-level deprovisioning completed with warnings"); 752 } 753 } 754 catch (const winrt::hresult_error& ex) 755 { 756 Logger::warn(L"Machine-level deprovisioning failed: HRESULT 0x{:08X}", static_cast<uint32_t>(ex.code())); 757 } 758 759 // Then remove packages for all users 760 auto packages = pm.FindPackagesForUserWithPackageTypes({}, packageFamilyName, PackageTypes::Main); 761 for (const auto& package : packages) 762 { 763 try 764 { 765 auto machineResult = pm.RemovePackageAsync(package.Id().FullName(), RemovalOptions::RemoveForAllUsers).get(); 766 if (machineResult.IsRegistered()) 767 { 768 uint32_t errorCode = static_cast<uint32_t>(machineResult.ExtendedErrorCode()); 769 Logger::error(L"Machine-level removal failed: 0x{:08X} - {}", errorCode, machineResult.ErrorText()); 770 } 771 } 772 catch (const winrt::hresult_error& ex) 773 { 774 Logger::error(L"Machine-level removal exception: HRESULT 0x{:08X}", static_cast<uint32_t>(ex.code())); 775 } 776 } 777 } 778 else 779 { 780 // Per-user uninstallation: standard removal 781 782 auto packages = pm.FindPackagesForUserWithPackageTypes({}, packageFamilyName, PackageTypes::Main); 783 for (const auto& package : packages) 784 { 785 auto userResult = pm.RemovePackageAsync(package.Id().FullName()).get(); 786 if (userResult.IsRegistered()) 787 { 788 uint32_t errorCode = static_cast<uint32_t>(userResult.ExtendedErrorCode()); 789 Logger::error(L"Per-user removal failed: 0x{:08X} - {}", errorCode, userResult.ErrorText()); 790 } 791 } 792 } 793 } 794 catch (const std::exception& ex) 795 { 796 std::string errorMsg = "Failed to uninstall PackageIdentity MSIX: " + std::string(ex.what()); 797 Logger::error(errorMsg); 798 // Don't fail the entire uninstallation if PackageIdentity fails 799 Logger::warn(L"Continuing uninstallation despite PackageIdentity MSIX error"); 800 } 801 802 LExit: 803 ReleaseStr(installScope); 804 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 805 return WcaFinalize(er); 806 } 807 808 UINT __stdcall RemoveWindowsServiceByName(std::wstring serviceName) 809 { 810 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 811 812 if (!hSCManager) 813 { 814 return ERROR_INSTALL_FAILURE; 815 } 816 817 SC_HANDLE hService = OpenService(hSCManager, serviceName.c_str(), SERVICE_STOP | DELETE); 818 if (!hService) 819 { 820 CloseServiceHandle(hSCManager); 821 return ERROR_INSTALL_FAILURE; 822 } 823 824 SERVICE_STATUS ss; 825 if (ControlService(hService, SERVICE_CONTROL_STOP, &ss)) 826 { 827 Sleep(1000); 828 while (QueryServiceStatus(hService, &ss)) 829 { 830 if (ss.dwCurrentState == SERVICE_STOP_PENDING) 831 { 832 Sleep(1000); 833 } 834 else 835 { 836 break; 837 } 838 } 839 } 840 841 BOOL deleteResult = DeleteService(hService); 842 CloseServiceHandle(hService); 843 CloseServiceHandle(hSCManager); 844 845 if (!deleteResult) 846 { 847 return ERROR_INSTALL_FAILURE; 848 } 849 850 return ERROR_SUCCESS; 851 } 852 853 UINT __stdcall UnsetAdvancedPasteAPIKeyCA(MSIHANDLE hInstall) 854 { 855 HRESULT hr = S_OK; 856 UINT er = ERROR_SUCCESS; 857 858 try 859 { 860 hr = WcaInitialize(hInstall, "UnsetAdvancedPasteAPIKey"); 861 ExitOnFailure(hr, "Failed to initialize"); 862 863 winrt::Windows::Security::Credentials::PasswordVault vault; 864 865 auto hasPrefix = [](std::wstring_view value, wchar_t const* prefix) { 866 std::wstring_view prefixView{ prefix }; 867 return value.compare(0, prefixView.size(), prefixView) == 0; 868 }; 869 870 const wchar_t* resourcePrefixes[] = { 871 L"https://platform.openai.com/api-keys", 872 L"https://azure.microsoft.com/products/ai-services/openai-service", 873 L"https://azure.microsoft.com/products/ai-services/ai-inference", 874 L"https://console.mistral.ai/account/api-keys", 875 L"https://ai.google.dev/", 876 }; 877 878 const wchar_t* usernamePrefixes[] = { 879 L"PowerToys_AdvancedPaste_", 880 }; 881 882 auto credentials = vault.RetrieveAll(); 883 for (auto const& credential : credentials) 884 { 885 bool shouldRemove = false; 886 887 std::wstring resource{ credential.Resource() }; 888 for (auto const prefix : resourcePrefixes) 889 { 890 if (hasPrefix(resource, prefix)) 891 { 892 shouldRemove = true; 893 break; 894 } 895 } 896 897 if (!shouldRemove) 898 { 899 std::wstring username{ credential.UserName() }; 900 for (auto const prefix : usernamePrefixes) 901 { 902 if (hasPrefix(username, prefix)) 903 { 904 shouldRemove = true; 905 break; 906 } 907 } 908 } 909 910 if (!shouldRemove) 911 { 912 continue; 913 } 914 915 try 916 { 917 vault.Remove(credential); 918 } 919 catch (...) 920 { 921 } 922 } 923 } 924 catch (...) 925 { 926 } 927 928 LExit: 929 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 930 return WcaFinalize(er); 931 } 932 933 UINT __stdcall UninstallCommandNotFoundModuleCA(MSIHANDLE hInstall) 934 { 935 HRESULT hr = S_OK; 936 UINT er = ERROR_SUCCESS; 937 std::wstring installationFolder; 938 std::string command; 939 940 hr = WcaInitialize(hInstall, "UninstallCommandNotFoundModule"); 941 ExitOnFailure(hr, "Failed to initialize"); 942 943 hr = getInstallFolder(hInstall, installationFolder); 944 ExitOnFailure(hr, "Failed to get installFolder."); 945 946 #ifdef _M_ARM64 947 command = "powershell.exe"; 948 command += " "; 949 command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted"; 950 command += " -Command "; 951 command += "\"[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';' + [Environment]::GetEnvironmentVariable('PATH', 'User'), 'Process');"; 952 command += "pwsh.exe -NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File '" + winrt::to_string(installationFolder) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "'\""; 953 #else 954 command = "pwsh.exe"; 955 command += " "; 956 command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(installationFolder) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\""; 957 #endif 958 959 system(command.c_str()); 960 961 LExit: 962 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 963 return WcaFinalize(er); 964 } 965 966 UINT __stdcall UpgradeCommandNotFoundModuleCA(MSIHANDLE hInstall) 967 { 968 HRESULT hr = S_OK; 969 UINT er = ERROR_SUCCESS; 970 std::wstring installationFolder; 971 std::string command; 972 973 hr = WcaInitialize(hInstall, "UpgradeCommandNotFoundModule"); 974 ExitOnFailure(hr, "Failed to initialize"); 975 976 hr = getInstallFolder(hInstall, installationFolder); 977 ExitOnFailure(hr, "Failed to get installFolder."); 978 979 command = "pwsh.exe"; 980 command += " "; 981 command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(installationFolder) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\UpgradeModule.ps1" + "\""; 982 983 system(command.c_str()); 984 985 LExit: 986 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 987 return WcaFinalize(er); 988 } 989 990 UINT __stdcall UninstallServicesCA(MSIHANDLE hInstall) 991 { 992 HRESULT hr = S_OK; 993 UINT er = ERROR_SUCCESS; 994 hr = WcaInitialize(hInstall, "UninstallServicesCA"); 995 996 ExitOnFailure(hr, "Failed to initialize"); 997 998 hr = RemoveWindowsServiceByName(L"PowerToys.MWB.Service"); 999 1000 LExit: 1001 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1002 return WcaFinalize(er); 1003 } 1004 1005 // Removes all Scheduled Tasks in the PowerToys folder and deletes the folder afterwards. 1006 // Based on the Task Scheduler Displaying Task Names and State example: 1007 // https://learn.microsoft.com/windows/desktop/TaskSchd/displaying-task-names-and-state--c---/ 1008 UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall) 1009 { 1010 HRESULT hr = S_OK; 1011 UINT er = ERROR_SUCCESS; 1012 1013 ITaskService *pService = nullptr; 1014 ITaskFolder *pTaskFolder = nullptr; 1015 IRegisteredTaskCollection *pTaskCollection = nullptr; 1016 ITaskFolder *pRootFolder = nullptr; 1017 LONG numTasks = 0; 1018 1019 hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA"); 1020 ExitOnFailure(hr, "Failed to initialize"); 1021 1022 Logger::info(L"RemoveScheduledTasksCA Initialized."); 1023 1024 // COM and Security Initialization is expected to have been done by the MSI. 1025 // It couldn't be done in the DLL, anyway. 1026 // ------------------------------------------------------ 1027 // Create an instance of the Task Service. 1028 hr = CoCreateInstance(CLSID_TaskScheduler, 1029 nullptr, 1030 CLSCTX_INPROC_SERVER, 1031 IID_ITaskService, 1032 reinterpret_cast<void **>(&pService)); 1033 ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr); 1034 1035 // Connect to the task service. 1036 hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t()); 1037 ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr); 1038 1039 // ------------------------------------------------------ 1040 // Get the PowerToys task folder. 1041 hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder); 1042 if (FAILED(hr)) 1043 { 1044 // Folder doesn't exist. No need to delete anything. 1045 Logger::info(L"The PowerToys scheduled task folder wasn't found. Nothing to delete."); 1046 hr = S_OK; 1047 ExitFunction(); 1048 } 1049 1050 // ------------------------------------------------------- 1051 // Get the registered tasks in the folder. 1052 hr = pTaskFolder->GetTasks(TASK_ENUM_HIDDEN, &pTaskCollection); 1053 ExitOnFailure(hr, "Cannot get the registered tasks: %x", hr); 1054 1055 hr = pTaskCollection->get_Count(&numTasks); 1056 for (LONG i = 0; i < numTasks; i++) 1057 { 1058 // Delete all the tasks found. 1059 // If some tasks can't be deleted, the folder won't be deleted later and the user will still be notified. 1060 IRegisteredTask *pRegisteredTask = nullptr; 1061 hr = pTaskCollection->get_Item(_variant_t(i + 1), &pRegisteredTask); 1062 if (SUCCEEDED(hr)) 1063 { 1064 BSTR taskName = nullptr; 1065 hr = pRegisteredTask->get_Name(&taskName); 1066 if (SUCCEEDED(hr)) 1067 { 1068 hr = pTaskFolder->DeleteTask(taskName, 0); 1069 if (FAILED(hr)) 1070 { 1071 Logger::error(L"Cannot delete the {} task: {}", taskName, hr); 1072 } 1073 SysFreeString(taskName); 1074 } 1075 else 1076 { 1077 Logger::error(L"Cannot get the registered task name: {}", hr); 1078 } 1079 pRegisteredTask->Release(); 1080 } 1081 else 1082 { 1083 Logger::error(L"Cannot get the registered task item at index={}: {}", i + 1, hr); 1084 } 1085 } 1086 1087 // ------------------------------------------------------ 1088 // Get the pointer to the root task folder and delete the PowerToys subfolder. 1089 hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder); 1090 ExitOnFailure(hr, "Cannot get Root Folder pointer: %x", hr); 1091 hr = pRootFolder->DeleteFolder(_bstr_t(L"PowerToys"), 0); 1092 pRootFolder->Release(); 1093 ExitOnFailure(hr, "Cannot delete the PowerToys folder: %x", hr); 1094 1095 Logger::info(L"Deleted the PowerToys Task Scheduler folder."); 1096 1097 LExit: 1098 if (pService) 1099 { 1100 pService->Release(); 1101 } 1102 if (pTaskFolder) 1103 { 1104 pTaskFolder->Release(); 1105 } 1106 if (pTaskCollection) 1107 { 1108 pTaskCollection->Release(); 1109 } 1110 1111 if (!SUCCEEDED(hr)) 1112 { 1113 PMSIHANDLE hRecord = MsiCreateRecord(0); 1114 MsiRecordSetString(hRecord, 0, TEXT("Failed to remove the PowerToys folder from the scheduled task. These can be removed manually later.")); 1115 MsiProcessMessage(hInstall, static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_WARNING + MB_OK), hRecord); 1116 } 1117 1118 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1119 return WcaFinalize(er); 1120 } 1121 1122 UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall) 1123 { 1124 HRESULT hr = S_OK; 1125 UINT er = ERROR_SUCCESS; 1126 1127 hr = WcaInitialize(hInstall, "TelemetryLogInstallSuccessCA"); 1128 ExitOnFailure(hr, "Failed to initialize"); 1129 1130 TraceLoggingWriteWrapper( 1131 g_hProvider, 1132 "Install_Success", 1133 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1134 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1135 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1136 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1137 1138 LExit: 1139 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1140 return WcaFinalize(er); 1141 } 1142 1143 UINT __stdcall TelemetryLogInstallCancelCA(MSIHANDLE hInstall) 1144 { 1145 HRESULT hr = S_OK; 1146 UINT er = ERROR_SUCCESS; 1147 1148 hr = WcaInitialize(hInstall, "TelemetryLogInstallCancelCA"); 1149 ExitOnFailure(hr, "Failed to initialize"); 1150 1151 TraceLoggingWriteWrapper( 1152 g_hProvider, 1153 "Install_Cancel", 1154 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1155 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1156 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1157 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1158 1159 LExit: 1160 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1161 return WcaFinalize(er); 1162 } 1163 1164 UINT __stdcall TelemetryLogInstallFailCA(MSIHANDLE hInstall) 1165 { 1166 HRESULT hr = S_OK; 1167 UINT er = ERROR_SUCCESS; 1168 1169 hr = WcaInitialize(hInstall, "TelemetryLogInstallFailCA"); 1170 ExitOnFailure(hr, "Failed to initialize"); 1171 1172 TraceLoggingWriteWrapper( 1173 g_hProvider, 1174 "Install_Fail", 1175 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1176 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1177 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1178 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1179 1180 LExit: 1181 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1182 return WcaFinalize(er); 1183 } 1184 1185 UINT __stdcall TelemetryLogUninstallSuccessCA(MSIHANDLE hInstall) 1186 { 1187 HRESULT hr = S_OK; 1188 UINT er = ERROR_SUCCESS; 1189 1190 hr = WcaInitialize(hInstall, "TelemetryLogUninstallSuccessCA"); 1191 ExitOnFailure(hr, "Failed to initialize"); 1192 1193 TraceLoggingWriteWrapper( 1194 g_hProvider, 1195 "UnInstall_Success", 1196 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1197 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1198 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1199 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1200 1201 LExit: 1202 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1203 return WcaFinalize(er); 1204 } 1205 1206 UINT __stdcall TelemetryLogUninstallCancelCA(MSIHANDLE hInstall) 1207 { 1208 HRESULT hr = S_OK; 1209 UINT er = ERROR_SUCCESS; 1210 1211 hr = WcaInitialize(hInstall, "TelemetryLogUninstallCancelCA"); 1212 ExitOnFailure(hr, "Failed to initialize"); 1213 1214 TraceLoggingWriteWrapper( 1215 g_hProvider, 1216 "UnInstall_Cancel", 1217 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1218 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1219 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1220 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1221 1222 LExit: 1223 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1224 return WcaFinalize(er); 1225 } 1226 1227 UINT __stdcall TelemetryLogUninstallFailCA(MSIHANDLE hInstall) 1228 { 1229 HRESULT hr = S_OK; 1230 UINT er = ERROR_SUCCESS; 1231 1232 hr = WcaInitialize(hInstall, "TelemetryLogUninstallFailCA"); 1233 ExitOnFailure(hr, "Failed to initialize"); 1234 1235 TraceLoggingWriteWrapper( 1236 g_hProvider, 1237 "UnInstall_Fail", 1238 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1239 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1240 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1241 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1242 1243 LExit: 1244 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1245 return WcaFinalize(er); 1246 } 1247 1248 UINT __stdcall TelemetryLogRepairCancelCA(MSIHANDLE hInstall) 1249 { 1250 HRESULT hr = S_OK; 1251 UINT er = ERROR_SUCCESS; 1252 1253 hr = WcaInitialize(hInstall, "TelemetryLogRepairCancelCA"); 1254 ExitOnFailure(hr, "Failed to initialize"); 1255 1256 TraceLoggingWriteWrapper( 1257 g_hProvider, 1258 "Repair_Cancel", 1259 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1260 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1261 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1262 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1263 1264 LExit: 1265 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1266 return WcaFinalize(er); 1267 } 1268 1269 UINT __stdcall TelemetryLogRepairFailCA(MSIHANDLE hInstall) 1270 { 1271 HRESULT hr = S_OK; 1272 UINT er = ERROR_SUCCESS; 1273 1274 hr = WcaInitialize(hInstall, "TelemetryLogRepairFailCA"); 1275 ExitOnFailure(hr, "Failed to initialize"); 1276 1277 TraceLoggingWriteWrapper( 1278 g_hProvider, 1279 "Repair_Fail", 1280 TraceLoggingWideString(get_product_version().c_str(), "Version"), 1281 ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), 1282 TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), 1283 TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); 1284 1285 LExit: 1286 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1287 return WcaFinalize(er); 1288 } 1289 1290 UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall) 1291 { 1292 HRESULT hr = S_OK; 1293 UINT er = ERROR_SUCCESS; 1294 hr = WcaInitialize(hInstall, "DetectPrevInstallPathCA"); 1295 MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", L""); 1296 1297 LPWSTR currentScope = nullptr; 1298 hr = WcaGetProperty(L"InstallScope", ¤tScope); 1299 1300 try 1301 { 1302 if (auto install_path = GetMsiPackageInstalledPath(std::wstring{currentScope} == L"perUser")) 1303 { 1304 MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", install_path->data()); 1305 } 1306 } 1307 catch (...) 1308 { 1309 } 1310 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1311 return WcaFinalize(er); 1312 } 1313 1314 UINT __stdcall InstallCmdPalPackageCA(MSIHANDLE hInstall) 1315 { 1316 using namespace winrt::Windows::Foundation; 1317 using namespace winrt::Windows::Management::Deployment; 1318 1319 HRESULT hr = S_OK; 1320 UINT er = ERROR_SUCCESS; 1321 std::wstring installationFolder; 1322 1323 hr = WcaInitialize(hInstall, "InstallCmdPalPackage"); 1324 hr = getInstallFolder(hInstall, installationFolder); 1325 1326 try 1327 { 1328 auto msix = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\", false); 1329 auto dependencies = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\Dependencies\\", true); 1330 1331 if (!msix.empty()) 1332 { 1333 auto msixPath = msix[0]; 1334 1335 if (!package::RegisterPackage(msixPath, dependencies)) 1336 { 1337 Logger::error(L"Failed to install CmdPal package"); 1338 er = ERROR_INSTALL_FAILURE; 1339 } 1340 } 1341 } 1342 catch (std::exception &e) 1343 { 1344 std::string errorMessage{"Exception thrown while trying to install CmdPal package: "}; 1345 errorMessage += e.what(); 1346 Logger::error(errorMessage); 1347 1348 er = ERROR_INSTALL_FAILURE; 1349 } 1350 1351 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1352 return WcaFinalize(er); 1353 } 1354 1355 UINT __stdcall UnRegisterCmdPalPackageCA(MSIHANDLE hInstall) 1356 { 1357 using namespace winrt::Windows::Foundation; 1358 using namespace winrt::Windows::Management::Deployment; 1359 1360 HRESULT hr = S_OK; 1361 UINT er = ERROR_SUCCESS; 1362 1363 hr = WcaInitialize(hInstall, "UnRegisterCmdPalPackageCA"); 1364 1365 try 1366 { 1367 // Packages to unregister 1368 std::wstring packageToRemoveDisplayName {L"Microsoft.CommandPalette"}; 1369 1370 if (!package::UnRegisterPackage(packageToRemoveDisplayName)) 1371 { 1372 Logger::error(L"Failed to unregister package: " + packageToRemoveDisplayName); 1373 er = ERROR_INSTALL_FAILURE; 1374 } 1375 } 1376 catch (std::exception &e) 1377 { 1378 std::string errorMessage{"Exception thrown while trying to unregister the CmdPal package: "}; 1379 errorMessage += e.what(); 1380 Logger::error(errorMessage); 1381 1382 er = ERROR_INSTALL_FAILURE; 1383 } 1384 1385 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1386 return WcaFinalize(er); 1387 } 1388 1389 1390 UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall) 1391 { 1392 using namespace winrt::Windows::Foundation; 1393 using namespace winrt::Windows::Management::Deployment; 1394 1395 HRESULT hr = S_OK; 1396 UINT er = ERROR_SUCCESS; 1397 1398 hr = WcaInitialize(hInstall, "UnRegisterContextMenuPackagesCA"); // original func name is too long 1399 1400 try 1401 { 1402 // Packages to unregister 1403 const std::vector<std::wstring> packagesToRemoveDisplayName{{L"PowerRenameContextMenu"}, {L"ImageResizerContextMenu"}, {L"FileLocksmithContextMenu"}, {L"NewPlusContextMenu"}}; 1404 1405 for (auto const &package : packagesToRemoveDisplayName) 1406 { 1407 if (!package::UnRegisterPackage(package)) 1408 { 1409 Logger::error(L"Failed to unregister package: " + package); 1410 er = ERROR_INSTALL_FAILURE; 1411 } 1412 } 1413 } 1414 catch (std::exception &e) 1415 { 1416 std::string errorMessage{"Exception thrown while trying to unregister sparse packages: "}; 1417 errorMessage += e.what(); 1418 Logger::error(errorMessage); 1419 1420 er = ERROR_INSTALL_FAILURE; 1421 } 1422 1423 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1424 return WcaFinalize(er); 1425 } 1426 1427 1428 UINT __stdcall CleanImageResizerRuntimeRegistryCA(MSIHANDLE hInstall) 1429 { 1430 HRESULT hr = S_OK; 1431 UINT er = ERROR_SUCCESS; 1432 hr = WcaInitialize(hInstall, "CleanImageResizerRuntimeRegistryCA"); 1433 1434 try 1435 { 1436 const wchar_t* CLSID_STR = L"{51B4D7E5-7568-4234-B4BB-47FB3C016A69}"; 1437 const wchar_t* exts[] = { L".bmp", L".dib", L".gif", L".jfif", L".jpe", L".jpeg", L".jpg", L".jxr", L".png", L".rle", L".tif", L".tiff", L".wdp" }; 1438 1439 auto deleteKeyRecursive = [](HKEY root, const std::wstring &path) { 1440 RegDeleteTreeW(root, path.c_str()); 1441 }; 1442 1443 // InprocServer32 chain root CLSID 1444 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" + std::wstring(CLSID_STR)); 1445 // DragDrop handler 1446 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\Directory\\ShellEx\\DragDropHandlers\\ImageResizer"); 1447 // Extensions 1448 for (auto ext : exts) 1449 { 1450 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\SystemFileAssociations\\" + std::wstring(ext) + L"\\ShellEx\\ContextMenuHandlers\\ImageResizer"); 1451 } 1452 // Sentinel 1453 RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Microsoft\\PowerToys\\ImageResizer"); 1454 } 1455 catch (...) 1456 { 1457 er = ERROR_INSTALL_FAILURE; 1458 } 1459 1460 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1461 return WcaFinalize(er); 1462 } 1463 1464 UINT __stdcall CleanFileLocksmithRuntimeRegistryCA(MSIHANDLE hInstall) 1465 { 1466 HRESULT hr = S_OK; 1467 UINT er = ERROR_SUCCESS; 1468 hr = WcaInitialize(hInstall, "CleanFileLocksmithRuntimeRegistryCA"); 1469 try 1470 { 1471 const wchar_t* CLSID_STR = L"{84D68575-E186-46AD-B0CB-BAEB45EE29C0}"; 1472 auto deleteKeyRecursive = [](HKEY root, const std::wstring& path) { 1473 RegDeleteTreeW(root, path.c_str()); 1474 }; 1475 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" + std::wstring(CLSID_STR)); 1476 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\AllFileSystemObjects\\ShellEx\\ContextMenuHandlers\\FileLocksmithExt"); 1477 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\Drive\\ShellEx\\ContextMenuHandlers\\FileLocksmithExt"); 1478 RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Microsoft\\PowerToys\\FileLocksmith"); 1479 } 1480 catch (...) 1481 { 1482 er = ERROR_INSTALL_FAILURE; 1483 } 1484 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1485 return WcaFinalize(er); 1486 } 1487 1488 UINT __stdcall CleanPowerRenameRuntimeRegistryCA(MSIHANDLE hInstall) 1489 { 1490 HRESULT hr = S_OK; 1491 UINT er = ERROR_SUCCESS; 1492 hr = WcaInitialize(hInstall, "CleanPowerRenameRuntimeRegistryCA"); 1493 try 1494 { 1495 const wchar_t* CLSID_STR = L"{0440049F-D1DC-4E46-B27B-98393D79486B}"; 1496 auto deleteKeyRecursive = [](HKEY root, const std::wstring& path) { 1497 RegDeleteTreeW(root, path.c_str()); 1498 }; 1499 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" + std::wstring(CLSID_STR)); 1500 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\AllFileSystemObjects\\ShellEx\\ContextMenuHandlers\\PowerRenameExt"); 1501 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\Directory\\background\\ShellEx\\ContextMenuHandlers\\PowerRenameExt"); 1502 RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Microsoft\\PowerToys\\PowerRename"); 1503 } 1504 catch (...) 1505 { 1506 er = ERROR_INSTALL_FAILURE; 1507 } 1508 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1509 return WcaFinalize(er); 1510 } 1511 1512 UINT __stdcall CleanNewPlusRuntimeRegistryCA(MSIHANDLE hInstall) 1513 { 1514 HRESULT hr = S_OK; 1515 UINT er = ERROR_SUCCESS; 1516 hr = WcaInitialize(hInstall, "CleanNewPlusRuntimeRegistryCA"); 1517 try 1518 { 1519 const wchar_t* CLSID_STR = L"{FF90D477-E32A-4BE8-8CC5-A502A97F5401}"; 1520 auto deleteKeyRecursive = [](HKEY root, const std::wstring& path) { 1521 RegDeleteTreeW(root, path.c_str()); 1522 }; 1523 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" + std::wstring(CLSID_STR)); 1524 deleteKeyRecursive(HKEY_CURRENT_USER, L"Software\\Classes\\Directory\\background\\ShellEx\\ContextMenuHandlers\\NewPlusShellExtensionWin10"); 1525 RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Microsoft\\PowerToys\\NewPlus"); 1526 } 1527 catch (...) 1528 { 1529 er = ERROR_INSTALL_FAILURE; 1530 } 1531 er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er; 1532 return WcaFinalize(er); 1533 } 1534 1535 UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall) 1536 { 1537 HRESULT hr = S_OK; 1538 UINT er = ERROR_SUCCESS; 1539 hr = WcaInitialize(hInstall, "TerminateProcessesCA"); 1540 1541 std::vector<DWORD> processes; 1542 const size_t maxProcesses = 4096; 1543 DWORD bytes = maxProcesses * sizeof(processes[0]); 1544 processes.resize(maxProcesses); 1545 1546 if (!EnumProcesses(processes.data(), bytes, &bytes)) 1547 { 1548 return 1; 1549 } 1550 processes.resize(bytes / sizeof(processes[0])); 1551 1552 std::array<std::wstring_view, 45> processesToTerminate = { 1553 L"PowerToys.PowerLauncher.exe", 1554 L"PowerToys.Settings.exe", 1555 L"PowerToys.AdvancedPaste.exe", 1556 L"PowerToys.Awake.exe", 1557 L"PowerToys.FancyZones.exe", 1558 L"PowerToys.FancyZonesEditor.exe", 1559 L"PowerToys.FileLocksmithUI.exe", 1560 L"PowerToys.MouseJumpUI.exe", 1561 L"PowerToys.ColorPickerUI.exe", 1562 L"PowerToys.AlwaysOnTop.exe", 1563 L"PowerToys.RegistryPreview.exe", 1564 L"PowerToys.Hosts.exe", 1565 L"PowerToys.PowerRename.exe", 1566 L"PowerToys.ImageResizer.exe", 1567 L"PowerToys.LightSwitchService.exe", 1568 L"PowerToys.PowerDisplay.exe", 1569 L"PowerToys.GcodeThumbnailProvider.exe", 1570 L"PowerToys.BgcodeThumbnailProvider.exe", 1571 L"PowerToys.PdfThumbnailProvider.exe", 1572 L"PowerToys.MonacoPreviewHandler.exe", 1573 L"PowerToys.MarkdownPreviewHandler.exe", 1574 L"PowerToys.StlThumbnailProvider.exe", 1575 L"PowerToys.SvgThumbnailProvider.exe", 1576 L"PowerToys.GcodePreviewHandler.exe", 1577 L"PowerToys.BgcodePreviewHandler.exe", 1578 L"PowerToys.QoiPreviewHandler.exe", 1579 L"PowerToys.PdfPreviewHandler.exe", 1580 L"PowerToys.QoiThumbnailProvider.exe", 1581 L"PowerToys.SvgPreviewHandler.exe", 1582 L"PowerToys.Peek.UI.exe", 1583 L"PowerToys.MouseWithoutBorders.exe", 1584 L"PowerToys.MouseWithoutBordersHelper.exe", 1585 L"PowerToys.MouseWithoutBordersService.exe", 1586 L"PowerToys.CropAndLock.exe", 1587 L"PowerToys.EnvironmentVariables.exe", 1588 L"PowerToys.QuickAccess.exe", 1589 L"PowerToys.WorkspacesSnapshotTool.exe", 1590 L"PowerToys.WorkspacesLauncher.exe", 1591 L"PowerToys.WorkspacesLauncherUI.exe", 1592 L"PowerToys.WorkspacesEditor.exe", 1593 L"PowerToys.WorkspacesWindowArranger.exe", 1594 L"Microsoft.CmdPal.UI.exe", 1595 L"Microsoft.CmdPal.Ext.PowerToys.exe", 1596 L"PowerToys.ZoomIt.exe", 1597 L"PowerToys.exe", 1598 }; 1599 1600 for (const auto procID : processes) 1601 { 1602 if (!procID) 1603 { 1604 continue; 1605 } 1606 wchar_t processName[MAX_PATH] = L"<unknown>"; 1607 1608 HANDLE hProcess{OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID)}; 1609 if (!hProcess) 1610 { 1611 continue; 1612 } 1613 HMODULE hMod; 1614 DWORD cbNeeded; 1615 1616 if (!EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) 1617 { 1618 CloseHandle(hProcess); 1619 continue; 1620 } 1621 GetModuleBaseNameW(hProcess, hMod, processName, sizeof(processName) / sizeof(wchar_t)); 1622 1623 for (const auto processToTerminate : processesToTerminate) 1624 { 1625 if (processName == processToTerminate) 1626 { 1627 const DWORD timeout = 500; 1628 auto windowEnumerator = [](HWND hwnd, LPARAM procIDPtr) -> BOOL 1629 { 1630 auto targetProcID = *reinterpret_cast<const DWORD *>(procIDPtr); 1631 DWORD windowProcID = 0; 1632 GetWindowThreadProcessId(hwnd, &windowProcID); 1633 if (windowProcID == targetProcID) 1634 { 1635 DWORD_PTR _{}; 1636 SendMessageTimeoutA(hwnd, WM_CLOSE, 0, 0, SMTO_BLOCK, timeout, &_); 1637 } 1638 return TRUE; 1639 }; 1640 EnumWindows(windowEnumerator, reinterpret_cast<LPARAM>(&procID)); 1641 Sleep(timeout); 1642 TerminateProcess(hProcess, 0); 1643 break; 1644 } 1645 } 1646 CloseHandle(hProcess); 1647 } 1648 1649 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1650 return WcaFinalize(er); 1651 } 1652 1653 UINT __stdcall SetBundleInstallLocationCA(MSIHANDLE hInstall) 1654 { 1655 HRESULT hr = S_OK; 1656 UINT er = ERROR_SUCCESS; 1657 1658 // Declare all variables at the beginning to avoid goto issues 1659 std::wstring customActionData; 1660 std::wstring installationFolder; 1661 std::wstring bundleUpgradeCode; 1662 std::wstring installScope; 1663 bool isPerUser = false; 1664 size_t pos1 = std::wstring::npos; 1665 size_t pos2 = std::wstring::npos; 1666 std::vector<HKEY> keysToTry; 1667 1668 hr = WcaInitialize(hInstall, "SetBundleInstallLocationCA"); 1669 ExitOnFailure(hr, "Failed to initialize"); 1670 1671 // Parse CustomActionData: "installFolder;upgradeCode;installScope" 1672 hr = getInstallFolder(hInstall, customActionData); 1673 ExitOnFailure(hr, "Failed to get CustomActionData."); 1674 1675 pos1 = customActionData.find(L';'); 1676 if (pos1 == std::wstring::npos) 1677 { 1678 hr = E_INVALIDARG; 1679 ExitOnFailure(hr, "Invalid CustomActionData format - missing first semicolon"); 1680 } 1681 1682 pos2 = customActionData.find(L';', pos1 + 1); 1683 if (pos2 == std::wstring::npos) 1684 { 1685 hr = E_INVALIDARG; 1686 ExitOnFailure(hr, "Invalid CustomActionData format - missing second semicolon"); 1687 } 1688 1689 installationFolder = customActionData.substr(0, pos1); 1690 bundleUpgradeCode = customActionData.substr(pos1 + 1, pos2 - pos1 - 1); 1691 installScope = customActionData.substr(pos2 + 1); 1692 1693 isPerUser = (installScope == L"perUser"); 1694 1695 // Use the appropriate registry based on install scope 1696 HKEY targetKey = isPerUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 1697 const wchar_t* keyName = isPerUser ? L"HKCU" : L"HKLM"; 1698 1699 WcaLog(LOGMSG_STANDARD, "SetBundleInstallLocationCA: Searching for Bundle in %ls registry", keyName); 1700 1701 HKEY uninstallKey; 1702 LONG openResult = RegOpenKeyExW(targetKey, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &uninstallKey); 1703 if (openResult != ERROR_SUCCESS) 1704 { 1705 WcaLog(LOGMSG_STANDARD, "SetBundleInstallLocationCA: Failed to open uninstall key, error: %ld", openResult); 1706 goto LExit; 1707 } 1708 1709 DWORD index = 0; 1710 wchar_t subKeyName[256]; 1711 DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(wchar_t); 1712 1713 while (RegEnumKeyExW(uninstallKey, index, subKeyName, &subKeyNameSize, nullptr, nullptr, nullptr, nullptr) == ERROR_SUCCESS) 1714 { 1715 HKEY productKey; 1716 if (RegOpenKeyExW(uninstallKey, subKeyName, 0, KEY_READ | KEY_WRITE, &productKey) == ERROR_SUCCESS) 1717 { 1718 wchar_t upgradeCode[256]; 1719 DWORD upgradeCodeSize = sizeof(upgradeCode); 1720 DWORD valueType; 1721 1722 if (RegQueryValueExW(productKey, L"BundleUpgradeCode", nullptr, &valueType, 1723 reinterpret_cast<LPBYTE>(upgradeCode), &upgradeCodeSize) == ERROR_SUCCESS) 1724 { 1725 // Remove brackets from registry upgradeCode for comparison (bundleUpgradeCode doesn't have brackets) 1726 std::wstring regUpgradeCode = upgradeCode; 1727 if (!regUpgradeCode.empty() && regUpgradeCode.front() == L'{' && regUpgradeCode.back() == L'}') 1728 { 1729 regUpgradeCode = regUpgradeCode.substr(1, regUpgradeCode.length() - 2); 1730 } 1731 1732 if (_wcsicmp(regUpgradeCode.c_str(), bundleUpgradeCode.c_str()) == 0) 1733 { 1734 // Found matching Bundle, set InstallLocation 1735 LONG setResult = RegSetValueExW(productKey, L"InstallLocation", 0, REG_SZ, 1736 reinterpret_cast<const BYTE*>(installationFolder.c_str()), 1737 static_cast<DWORD>((installationFolder.length() + 1) * sizeof(wchar_t))); 1738 1739 if (setResult == ERROR_SUCCESS) 1740 { 1741 WcaLog(LOGMSG_STANDARD, "SetBundleInstallLocationCA: InstallLocation set successfully"); 1742 } 1743 else 1744 { 1745 WcaLog(LOGMSG_STANDARD, "SetBundleInstallLocationCA: Failed to set InstallLocation, error: %ld", setResult); 1746 } 1747 1748 RegCloseKey(productKey); 1749 RegCloseKey(uninstallKey); 1750 goto LExit; 1751 } 1752 } 1753 RegCloseKey(productKey); 1754 } 1755 1756 index++; 1757 subKeyNameSize = sizeof(subKeyName) / sizeof(wchar_t); 1758 } 1759 1760 RegCloseKey(uninstallKey); 1761 1762 LExit: 1763 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 1764 return WcaFinalize(er); 1765 } 1766 1767 void initSystemLogger() 1768 { 1769 static std::once_flag initLoggerFlag; 1770 std::call_once(initLoggerFlag, []() 1771 { 1772 WCHAR temp_path[MAX_PATH]; 1773 auto ret = GetTempPath(MAX_PATH, temp_path); 1774 1775 if (ret) 1776 { 1777 Logger::init("PowerToysMSI", std::wstring{ temp_path } + L"\\PowerToysMSIInstaller", L""); 1778 } }); 1779 } 1780 1781 // DllMain - Initialize and cleanup WiX custom action utils. 1782 extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID) 1783 { 1784 switch (ulReason) 1785 { 1786 case DLL_PROCESS_ATTACH: 1787 WcaGlobalInitialize(hInst); 1788 initSystemLogger(); 1789 TraceLoggingRegister(g_hProvider); 1790 DLL_HANDLE = hInst; 1791 break; 1792 1793 case DLL_PROCESS_DETACH: 1794 TraceLoggingUnregister(g_hProvider); 1795 WcaGlobalFinalize(); 1796 break; 1797 } 1798 1799 return TRUE; 1800 }