diff options
| author | Jacob Hoover <jacob.hoover@greenheck.com> | 2021-06-11 17:05:06 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2021-07-18 14:41:21 -0500 |
| commit | f3c96bcab560cb09355e9366eac3f4195479d95d (patch) | |
| tree | 1585c1f2af7e3582e14663c29c033702e910d12f /src | |
| parent | 5b2b06c9bffb4e6f17409cec41bc0b4b8dab4c90 (diff) | |
| download | wix-f3c96bcab560cb09355e9366eac3f4195479d95d.tar.gz wix-f3c96bcab560cb09355e9366eac3f4195479d95d.tar.bz2 wix-f3c96bcab560cb09355e9366eac3f4195479d95d.zip | |
Allow access to persisted variables from related bundles.
Implements #3704
Diffstat (limited to 'src')
| -rw-r--r-- | src/burn/engine/registration.cpp | 92 | ||||
| -rw-r--r-- | src/burn/test/BurnUnitTest/RegistrationTest.cpp | 178 | ||||
| -rw-r--r-- | src/burn/test/BurnUnitTest/precomp.h | 1 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/butil.cpp | 105 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/butil.h | 11 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/regutil.h | 8 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/regutil.cpp | 47 |
7 files changed, 420 insertions, 22 deletions
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp index eed1fee2..4088004d 100644 --- a/src/burn/engine/registration.cpp +++ b/src/burn/engine/registration.cpp | |||
| @@ -32,6 +32,7 @@ const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine"; | |||
| 32 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor"; | 32 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor"; |
| 33 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor"; | 33 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor"; |
| 34 | const LPCWSTR SWIDTAG_FOLDER = L"swidtag"; | 34 | const LPCWSTR SWIDTAG_FOLDER = L"swidtag"; |
| 35 | const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; | ||
| 35 | 36 | ||
| 36 | // internal function declarations | 37 | // internal function declarations |
| 37 | 38 | ||
| @@ -909,6 +910,7 @@ extern "C" HRESULT RegistrationSessionEnd( | |||
| 909 | { | 910 | { |
| 910 | HRESULT hr = S_OK; | 911 | HRESULT hr = S_OK; |
| 911 | LPWSTR sczRebootRequiredKey = NULL; | 912 | LPWSTR sczRebootRequiredKey = NULL; |
| 913 | LPWSTR sczVariableKey = NULL; | ||
| 912 | HKEY hkRebootRequired = NULL; | 914 | HKEY hkRebootRequired = NULL; |
| 913 | HKEY hkRegistration = NULL; | 915 | HKEY hkRegistration = NULL; |
| 914 | 916 | ||
| @@ -956,6 +958,17 @@ extern "C" HRESULT RegistrationSessionEnd( | |||
| 956 | 958 | ||
| 957 | RemoveSoftwareTags(pVariables, &pRegistration->softwareTags); | 959 | RemoveSoftwareTags(pVariables, &pRegistration->softwareTags); |
| 958 | 960 | ||
| 961 | // build variable registry key path | ||
| 962 | hr = StrAllocFormatted(&sczVariableKey, L"%s\\%s", pRegistration->sczRegistrationKey, REGISTRY_BUNDLE_VARIABLE_KEY); | ||
| 963 | ExitOnFailure(hr, "Failed to build variable registry key path."); | ||
| 964 | |||
| 965 | // Delete registration variable key. | ||
| 966 | hr = RegDelete(pRegistration->hkRoot, sczVariableKey, REG_KEY_DEFAULT, FALSE); | ||
| 967 | if (E_FILENOTFOUND != hr) | ||
| 968 | { | ||
| 969 | ExitOnFailure(hr, "Failed to delete registration variable key: %ls", sczVariableKey); | ||
| 970 | } | ||
| 971 | |||
| 959 | // Delete registration key. | 972 | // Delete registration key. |
| 960 | hr = RegDelete(pRegistration->hkRoot, pRegistration->sczRegistrationKey, REG_KEY_DEFAULT, FALSE); | 973 | hr = RegDelete(pRegistration->hkRoot, pRegistration->sczRegistrationKey, REG_KEY_DEFAULT, FALSE); |
| 961 | if (E_FILENOTFOUND != hr) | 974 | if (E_FILENOTFOUND != hr) |
| @@ -985,6 +998,7 @@ extern "C" HRESULT RegistrationSessionEnd( | |||
| 985 | LExit: | 998 | LExit: |
| 986 | ReleaseRegKey(hkRegistration); | 999 | ReleaseRegKey(hkRegistration); |
| 987 | ReleaseRegKey(hkRebootRequired); | 1000 | ReleaseRegKey(hkRebootRequired); |
| 1001 | ReleaseStr(sczVariableKey); | ||
| 988 | ReleaseStr(sczRebootRequiredKey); | 1002 | ReleaseStr(sczRebootRequiredKey); |
| 989 | 1003 | ||
| 990 | return hr; | 1004 | return hr; |
| @@ -1001,6 +1015,15 @@ extern "C" HRESULT RegistrationSaveState( | |||
| 1001 | ) | 1015 | ) |
| 1002 | { | 1016 | { |
| 1003 | HRESULT hr = S_OK; | 1017 | HRESULT hr = S_OK; |
| 1018 | BURN_VARIABLES variables = { }; | ||
| 1019 | SIZE_T iBuffer_Unused = 0; | ||
| 1020 | HKEY hkRegistration = NULL; | ||
| 1021 | LPWSTR sczVariableKey = NULL; | ||
| 1022 | LPWSTR sczVariableValue = NULL; | ||
| 1023 | LPWSTR sczValueName = NULL; | ||
| 1024 | DWORD dwType = 0; | ||
| 1025 | DWORD dwNumberOfExistingValues = 0; | ||
| 1026 | |||
| 1004 | 1027 | ||
| 1005 | // write data to file | 1028 | // write data to file |
| 1006 | hr = FileWrite(pRegistration->sczStateFile, FILE_ATTRIBUTE_NORMAL, pbBuffer, cbBuffer, NULL); | 1029 | hr = FileWrite(pRegistration->sczStateFile, FILE_ATTRIBUTE_NORMAL, pbBuffer, cbBuffer, NULL); |
| @@ -1011,7 +1034,76 @@ extern "C" HRESULT RegistrationSaveState( | |||
| 1011 | } | 1034 | } |
| 1012 | ExitOnFailure(hr, "Failed to write state to file: %ls", pRegistration->sczStateFile); | 1035 | ExitOnFailure(hr, "Failed to write state to file: %ls", pRegistration->sczStateFile); |
| 1013 | 1036 | ||
| 1037 | ::InitializeCriticalSection(&variables.csAccess); | ||
| 1038 | |||
| 1039 | hr = VariableDeserialize(&variables, TRUE, pbBuffer, cbBuffer, &iBuffer_Unused); | ||
| 1040 | ExitOnFailure(hr, "Failed to read variables."); | ||
| 1041 | |||
| 1042 | // build variable registry key path | ||
| 1043 | hr = StrAllocFormatted(&sczVariableKey, L"%s\\%s", pRegistration->sczRegistrationKey, REGISTRY_BUNDLE_VARIABLE_KEY); | ||
| 1044 | ExitOnFailure(hr, "Failed to build variable registry key path."); | ||
| 1045 | |||
| 1046 | // open registration variable key | ||
| 1047 | hr = RegCreate(pRegistration->hkRoot, sczVariableKey, KEY_WRITE | KEY_QUERY_VALUE, &hkRegistration); | ||
| 1048 | ExitOnFailure(hr, "Failed to create registration variable key."); | ||
| 1049 | |||
| 1050 | hr = RegQueryInfoKey(hkRegistration, 0, 0, 0, 0, 0, 0, &dwNumberOfExistingValues, 0, 0, 0, 0); | ||
| 1051 | ExitOnFailure(hr, "Failed to query registration variable count."); | ||
| 1052 | |||
| 1053 | for (DWORD i = dwNumberOfExistingValues; i >= 0; --i) | ||
| 1054 | { | ||
| 1055 | hr = RegValueEnum(hkRegistration, i, &sczValueName, &dwType); | ||
| 1056 | |||
| 1057 | if (E_NOMOREITEMS == hr) | ||
| 1058 | { | ||
| 1059 | hr = S_OK; | ||
| 1060 | break; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | ExitOnFailure(hr, "Failed to enumerate value %u", i); | ||
| 1064 | |||
| 1065 | hr = RegDeleteValue(hkRegistration, sczValueName); | ||
| 1066 | ExitOnFailure(hr, "Failed to delete registration variable value."); | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | // Write variables. | ||
| 1070 | for (DWORD i = 0; i < variables.cVariables; ++i) | ||
| 1071 | { | ||
| 1072 | BURN_VARIABLE* pVariable = &variables.rgVariables[i]; | ||
| 1073 | |||
| 1074 | // Write variable value. | ||
| 1075 | switch (pVariable->Value.Type) | ||
| 1076 | { | ||
| 1077 | case BURN_VARIANT_TYPE_NONE: | ||
| 1078 | hr = RegWriteNone(hkRegistration, pVariable->sczName); | ||
| 1079 | ExitOnFailure(hr, "Failed to set variable value."); | ||
| 1080 | break; | ||
| 1081 | case BURN_VARIANT_TYPE_NUMERIC: __fallthrough; | ||
| 1082 | case BURN_VARIANT_TYPE_VERSION: __fallthrough; | ||
| 1083 | case BURN_VARIANT_TYPE_FORMATTED: __fallthrough; | ||
| 1084 | case BURN_VARIANT_TYPE_STRING: | ||
| 1085 | hr = BVariantGetString(&pVariable->Value, &sczVariableValue); | ||
| 1086 | ExitOnFailure(hr, "Failed to get variable value."); | ||
| 1087 | |||
| 1088 | hr = RegWriteString(hkRegistration, pVariable->sczName, sczVariableValue); | ||
| 1089 | ExitOnFailure(hr, "Failed to set variable value."); | ||
| 1090 | |||
| 1091 | ReleaseNullStrSecure(sczVariableValue); | ||
| 1092 | |||
| 1093 | break; | ||
| 1094 | default: | ||
| 1095 | hr = E_INVALIDARG; | ||
| 1096 | ExitOnFailure(hr, "Unsupported variable type."); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | } | ||
| 1014 | LExit: | 1100 | LExit: |
| 1101 | VariablesUninitialize(&variables); | ||
| 1102 | ReleaseStr(sczValueName); | ||
| 1103 | ReleaseStr(sczVariableValue); | ||
| 1104 | ReleaseStr(sczVariableKey); | ||
| 1105 | ReleaseRegKey(hkRegistration); | ||
| 1106 | |||
| 1015 | return hr; | 1107 | return hr; |
| 1016 | } | 1108 | } |
| 1017 | 1109 | ||
diff --git a/src/burn/test/BurnUnitTest/RegistrationTest.cpp b/src/burn/test/BurnUnitTest/RegistrationTest.cpp index 96bdb2bf..298d4631 100644 --- a/src/burn/test/BurnUnitTest/RegistrationTest.cpp +++ b/src/burn/test/BurnUnitTest/RegistrationTest.cpp | |||
| @@ -8,9 +8,12 @@ | |||
| 8 | #define HKCU_PATH L"SOFTWARE\\WiX_Burn_UnitTest\\HKCU" | 8 | #define HKCU_PATH L"SOFTWARE\\WiX_Burn_UnitTest\\HKCU" |
| 9 | #define REGISTRY_UNINSTALL_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" | 9 | #define REGISTRY_UNINSTALL_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" |
| 10 | #define REGISTRY_RUN_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce" | 10 | #define REGISTRY_RUN_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce" |
| 11 | #define TEST_BUNDLE_ID L"{D54F896D-1952-43e6-9C67-B5652240618C}" | ||
| 12 | #define TEST_BUNDLE_UPGRADE_CODE L"{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}" | ||
| 11 | 13 | ||
| 12 | #define TEST_UNINSTALL_KEY L"HKEY_CURRENT_USER\\" HKCU_PATH L"\\" REGISTRY_UNINSTALL_KEY L"\\{D54F896D-1952-43e6-9C67-B5652240618C}" | 14 | #define TEST_UNINSTALL_KEY L"HKEY_CURRENT_USER\\" HKCU_PATH L"\\" REGISTRY_UNINSTALL_KEY L"\\{D54F896D-1952-43e6-9C67-B5652240618C}" |
| 13 | #define TEST_RUN_KEY L"HKEY_CURRENT_USER\\" HKCU_PATH L"\\" REGISTRY_RUN_KEY | 15 | #define TEST_RUN_KEY L"HKEY_CURRENT_USER\\" HKCU_PATH L"\\" REGISTRY_RUN_KEY |
| 16 | #define TEST_VARIABLE_KEY L"HKEY_CURRENT_USER\\" HKCU_PATH L"\\" REGISTRY_UNINSTALL_KEY L"\\{D54F896D-1952-43e6-9C67-B5652240618C}\\variables" | ||
| 14 | 17 | ||
| 15 | 18 | ||
| 16 | static LSTATUS APIENTRY RegistrationTest_RegCreateKeyExW( | 19 | static LSTATUS APIENTRY RegistrationTest_RegCreateKeyExW( |
| @@ -496,30 +499,153 @@ namespace Bootstrapper | |||
| 496 | } | 499 | } |
| 497 | } | 500 | } |
| 498 | 501 | ||
| 499 | [Fact(Skip = "Currently fails")] | 502 | [Fact] |
| 500 | void ResumeTest() | 503 | void DUtilButilTest() |
| 501 | { | 504 | { |
| 502 | HRESULT hr = S_OK; | 505 | HRESULT hr = S_OK; |
| 503 | IXMLDOMElement* pixeBundle = NULL; | 506 | IXMLDOMElement* pixeBundle = NULL; |
| 504 | LPWSTR sczCurrentProcess = NULL; | 507 | LPWSTR sczCurrentProcess = NULL; |
| 508 | LPWSTR sczValue = NULL; | ||
| 509 | LPWSTR sczRelatedBundleId = NULL; | ||
| 510 | DWORD dwRelatedBundleIndex = 0; | ||
| 505 | BURN_VARIABLES variables = { }; | 511 | BURN_VARIABLES variables = { }; |
| 506 | BURN_USER_EXPERIENCE userExperience = { }; | 512 | BURN_USER_EXPERIENCE userExperience = { }; |
| 507 | BOOTSTRAPPER_COMMAND command = { }; | 513 | BOOTSTRAPPER_COMMAND command = { }; |
| 508 | BURN_REGISTRATION registration = { }; | 514 | BURN_REGISTRATION registration = { }; |
| 509 | BURN_LOGGING logging = { }; | 515 | BURN_LOGGING logging = { }; |
| 510 | BURN_PACKAGES packages = { }; | 516 | BURN_PACKAGES packages = { }; |
| 511 | BYTE rgbData[256] = { }; | ||
| 512 | BOOTSTRAPPER_RESUME_TYPE resumeType = BOOTSTRAPPER_RESUME_TYPE_NONE; | ||
| 513 | BYTE* pbBuffer = NULL; | 517 | BYTE* pbBuffer = NULL; |
| 514 | SIZE_T cbBuffer = 0; | 518 | SIZE_T cbBuffer = 0; |
| 519 | |||
| 515 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}")); | 520 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}")); |
| 516 | try | 521 | try |
| 517 | { | 522 | { |
| 518 | for (DWORD i = 0; i < 256; ++i) | 523 | // set mock API's |
| 524 | RegFunctionOverride(RegistrationTest_RegCreateKeyExW, RegistrationTest_RegOpenKeyExW, RegistrationTest_RegDeleteKeyExW, NULL, NULL, NULL, NULL, NULL, NULL); | ||
| 525 | |||
| 526 | Registry::CurrentUser->CreateSubKey(gcnew String(HKCU_PATH)); | ||
| 527 | |||
| 528 | logging.sczPath = L"BurnUnitTest.txt"; | ||
| 529 | |||
| 530 | LPCWSTR wzDocument = | ||
| 531 | L"<Bundle>" | ||
| 532 | L" <UX>" | ||
| 533 | L" <Payload Id='ux.dll' FilePath='ux.dll' Packaging='embedded' SourcePath='ux.dll' Hash='000000000000' />" | ||
| 534 | L" </UX>" | ||
| 535 | L" <RelatedBundle Id='" TEST_BUNDLE_UPGRADE_CODE "' Action='Upgrade' />" | ||
| 536 | L" <Registration Id='" TEST_BUNDLE_ID "' Tag='foo' ProviderKey='" TEST_BUNDLE_ID "' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" | ||
| 537 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='RegisterBasicTest' DisplayVersion='1.0.0.0' />" | ||
| 538 | L" </Registration>" | ||
| 539 | L" <Variable Id='MyBurnVariable1' Type='numeric' Value='0' Hidden='no' Persisted='yes' />" | ||
| 540 | L" <Variable Id='MyBurnVariable2' Type='string' Value='foo' Hidden='no' Persisted='yes' />" | ||
| 541 | L" <Variable Id='MyBurnVariable3' Type='version' Value='v1.1-alpha' Hidden='no' Persisted='yes' />" | ||
| 542 | L" <Variable Id='MyBurnVariable4' Type='string' Value='foo' Hidden='no' Persisted='no' />" | ||
| 543 | L" <CommandLine Variables='upperCase' />" | ||
| 544 | L"</Bundle>"; | ||
| 545 | |||
| 546 | // load XML document | ||
| 547 | LoadBundleXmlHelper(wzDocument, &pixeBundle); | ||
| 548 | |||
| 549 | hr = VariableInitialize(&variables); | ||
| 550 | TestThrowOnFailure(hr, L"Failed to initialize variables."); | ||
| 551 | |||
| 552 | hr = VariablesParseFromXml(&variables, pixeBundle); | ||
| 553 | TestThrowOnFailure(hr, L"Failed to parse variables from XML."); | ||
| 554 | |||
| 555 | hr = UserExperienceParseFromXml(&userExperience, pixeBundle); | ||
| 556 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); | ||
| 557 | |||
| 558 | hr = RegistrationParseFromXml(®istration, pixeBundle); | ||
| 559 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); | ||
| 560 | |||
| 561 | hr = PlanSetResumeCommand(®istration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging); | ||
| 562 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); | ||
| 563 | |||
| 564 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); | ||
| 565 | TestThrowOnFailure(hr, L"Failed to get current process path."); | ||
| 566 | |||
| 567 | // begin session | ||
| 568 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); | ||
| 569 | TestThrowOnFailure(hr, L"Failed to register bundle."); | ||
| 570 | |||
| 571 | VariableSetNumericHelper(&variables, L"MyBurnVariable1", 42); | ||
| 572 | VariableSetStringHelper(&variables, L"MyBurnVariable2", L"bar", FALSE); | ||
| 573 | VariableSetVersionHelper(&variables, L"MyBurnVariable3", L"v1.0-beta"); | ||
| 574 | |||
| 575 | hr = VariableSerialize(&variables, TRUE, &pbBuffer, &cbBuffer); | ||
| 576 | TestThrowOnFailure(hr, "Failed to serialize variables."); | ||
| 577 | |||
| 578 | if (!Directory::Exists(cacheDirectory)) | ||
| 519 | { | 579 | { |
| 520 | rgbData[i] = (BYTE)i; | 580 | Directory::CreateDirectory(cacheDirectory); |
| 521 | } | 581 | } |
| 522 | 582 | ||
| 583 | hr = RegistrationSaveState(®istration, pbBuffer, cbBuffer); | ||
| 584 | TestThrowOnFailure(hr, L"Failed to save state."); | ||
| 585 | |||
| 586 | ReleaseNullBuffer(pbBuffer); | ||
| 587 | cbBuffer = 0; | ||
| 588 | // Verify the variables exist | ||
| 589 | Assert::Equal<String^>(gcnew String(L"42"), (String^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"MyBurnVariable1"), nullptr)); | ||
| 590 | Assert::Equal<String^>(gcnew String(L"bar"), (String^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"MyBurnVariable2"), nullptr)); | ||
| 591 | Assert::Equal<String^>(gcnew String(L"1.0-beta"), (String^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"MyBurnVariable3"), nullptr)); | ||
| 592 | Assert::Empty((System::Collections::IEnumerable ^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"WixBundleForcedRestartPackage"), nullptr)); | ||
| 593 | |||
| 594 | hr = StrAlloc(&sczRelatedBundleId, MAX_GUID_CHARS + 1); | ||
| 595 | |||
| 596 | // Verify we can find ourself via the UpgradeCode | ||
| 597 | hr = BundleEnumRelatedBundle(TEST_BUNDLE_UPGRADE_CODE, BUNDLE_INSTALL_CONTEXT_USER, &dwRelatedBundleIndex, sczRelatedBundleId); | ||
| 598 | TestThrowOnFailure(hr, L"Failed to enumerate related bundle."); | ||
| 599 | Assert::Equal<String^>(gcnew String(TEST_BUNDLE_ID), gcnew String(sczRelatedBundleId)); | ||
| 600 | |||
| 601 | // Verify we can read the bundle variables via the API | ||
| 602 | hr = BundleGetBundleVariable(TEST_BUNDLE_ID, L"MyBurnVariable1", &sczValue); | ||
| 603 | TestThrowOnFailure(hr, L"Failed to read MyBurnVariable1."); | ||
| 604 | Assert::Equal<String^>(gcnew String(L"42"), gcnew String(sczValue)); | ||
| 605 | |||
| 606 | // end session | ||
| 607 | hr = RegistrationSessionEnd(®istration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); | ||
| 608 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); | ||
| 609 | } | ||
| 610 | finally | ||
| 611 | { | ||
| 612 | ReleaseStr(sczRelatedBundleId); | ||
| 613 | ReleaseStr(sczCurrentProcess); | ||
| 614 | ReleaseObject(pixeBundle); | ||
| 615 | UserExperienceUninitialize(&userExperience); | ||
| 616 | RegistrationUninitialize(®istration); | ||
| 617 | VariablesUninitialize(&variables); | ||
| 618 | |||
| 619 | Registry::CurrentUser->DeleteSubKeyTree(gcnew String(ROOT_PATH)); | ||
| 620 | if (Directory::Exists(cacheDirectory)) | ||
| 621 | { | ||
| 622 | Directory::Delete(cacheDirectory, true); | ||
| 623 | } | ||
| 624 | |||
| 625 | RegFunctionOverride(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | ||
| 626 | } | ||
| 627 | } | ||
| 628 | |||
| 629 | [Fact]//(Skip = "Currently fails")] | ||
| 630 | void ResumeTest() | ||
| 631 | { | ||
| 632 | HRESULT hr = S_OK; | ||
| 633 | IXMLDOMElement* pixeBundle = NULL; | ||
| 634 | LPWSTR sczCurrentProcess = NULL; | ||
| 635 | LPWSTR sczValue = NULL; | ||
| 636 | BURN_VARIABLES variables = { }; | ||
| 637 | BURN_USER_EXPERIENCE userExperience = { }; | ||
| 638 | BOOTSTRAPPER_COMMAND command = { }; | ||
| 639 | BURN_REGISTRATION registration = { }; | ||
| 640 | BURN_LOGGING logging = { }; | ||
| 641 | BURN_PACKAGES packages = { }; | ||
| 642 | BOOTSTRAPPER_RESUME_TYPE resumeType = BOOTSTRAPPER_RESUME_TYPE_NONE; | ||
| 643 | BYTE* pbBuffer = NULL; | ||
| 644 | SIZE_T cbBuffer = 0; | ||
| 645 | SIZE_T piBuffer = 0; | ||
| 646 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}")); | ||
| 647 | try | ||
| 648 | { | ||
| 523 | // set mock API's | 649 | // set mock API's |
| 524 | RegFunctionOverride(RegistrationTest_RegCreateKeyExW, RegistrationTest_RegOpenKeyExW, RegistrationTest_RegDeleteKeyExW, NULL, NULL, NULL, NULL, NULL, NULL); | 650 | RegFunctionOverride(RegistrationTest_RegCreateKeyExW, RegistrationTest_RegOpenKeyExW, RegistrationTest_RegDeleteKeyExW, NULL, NULL, NULL, NULL, NULL, NULL); |
| 525 | 651 | ||
| @@ -535,6 +661,10 @@ namespace Bootstrapper | |||
| 535 | L" <Registration Id='{D54F896D-1952-43e6-9C67-B5652240618C}' UpgradeCode='{D54F896D-1952-43e6-9C67-B5652240618C}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" | 661 | L" <Registration Id='{D54F896D-1952-43e6-9C67-B5652240618C}' UpgradeCode='{D54F896D-1952-43e6-9C67-B5652240618C}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 536 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='RegisterBasicTest' DisplayVersion='1.0.0.0' />" | 662 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='RegisterBasicTest' DisplayVersion='1.0.0.0' />" |
| 537 | L" </Registration>" | 663 | L" </Registration>" |
| 664 | L" <Variable Id='MyBurnVariable1' Type='numeric' Value='0' Hidden='no' Persisted='yes' />" | ||
| 665 | L" <Variable Id='MyBurnVariable2' Type='string' Value='foo' Hidden='no' Persisted='yes' />" | ||
| 666 | L" <Variable Id='MyBurnVariable3' Type='version' Value='v1.1-alpha' Hidden='no' Persisted='yes' />" | ||
| 667 | L" <CommandLine Variables='upperCase' />" | ||
| 538 | L"</Bundle>"; | 668 | L"</Bundle>"; |
| 539 | 669 | ||
| 540 | // load XML document | 670 | // load XML document |
| @@ -543,6 +673,9 @@ namespace Bootstrapper | |||
| 543 | hr = VariableInitialize(&variables); | 673 | hr = VariableInitialize(&variables); |
| 544 | TestThrowOnFailure(hr, L"Failed to initialize variables."); | 674 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 545 | 675 | ||
| 676 | hr = VariablesParseFromXml(&variables, pixeBundle); | ||
| 677 | TestThrowOnFailure(hr, L"Failed to parse variables from XML."); | ||
| 678 | |||
| 546 | hr = UserExperienceParseFromXml(&userExperience, pixeBundle); | 679 | hr = UserExperienceParseFromXml(&userExperience, pixeBundle); |
| 547 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); | 680 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 548 | 681 | ||
| @@ -565,9 +698,33 @@ namespace Bootstrapper | |||
| 565 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); | 698 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 566 | TestThrowOnFailure(hr, L"Failed to register bundle."); | 699 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 567 | 700 | ||
| 568 | hr = RegistrationSaveState(®istration, rgbData, sizeof(rgbData)); | 701 | VariableSetNumericHelper(&variables, L"MyBurnVariable1", 42); |
| 702 | VariableSetStringHelper(&variables, L"MyBurnVariable2", L"bar", FALSE); | ||
| 703 | VariableSetVersionHelper(&variables, L"MyBurnVariable3", L"v1.0-beta"); | ||
| 704 | |||
| 705 | hr = VariableSerialize(&variables, TRUE, &pbBuffer, &cbBuffer); | ||
| 706 | TestThrowOnFailure(hr, "Failed to serialize variables."); | ||
| 707 | |||
| 708 | if (!Directory::Exists(cacheDirectory)) | ||
| 709 | { | ||
| 710 | Directory::CreateDirectory(cacheDirectory); | ||
| 711 | } | ||
| 712 | |||
| 713 | hr = RegistrationSaveState(®istration, pbBuffer, cbBuffer); | ||
| 569 | TestThrowOnFailure(hr, L"Failed to save state."); | 714 | TestThrowOnFailure(hr, L"Failed to save state."); |
| 570 | 715 | ||
| 716 | ReleaseNullBuffer(pbBuffer); | ||
| 717 | cbBuffer = 0; | ||
| 718 | // Verify the variables exist | ||
| 719 | Assert::Equal<String^>(gcnew String(L"42"), (String^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"MyBurnVariable1"), nullptr)); | ||
| 720 | Assert::Equal<String^>(gcnew String(L"bar"), (String^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"MyBurnVariable2"), nullptr)); | ||
| 721 | Assert::Equal<String^>(gcnew String(L"1.0-beta"), (String^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"MyBurnVariable3"), nullptr)); | ||
| 722 | Assert::Empty((System::Collections::IEnumerable^)Registry::GetValue(gcnew String(TEST_VARIABLE_KEY), gcnew String(L"WixBundleForcedRestartPackage"), nullptr)); | ||
| 723 | |||
| 724 | hr = BundleGetBundleVariable(TEST_BUNDLE_ID, L"MyBurnVariable1", &sczValue); | ||
| 725 | TestThrowOnFailure(hr, L"Failed to read MyBurnVariable1."); | ||
| 726 | Assert::Equal<String^>(gcnew String(L"42"), gcnew String(sczValue)); | ||
| 727 | |||
| 571 | // read interrupted resume type | 728 | // read interrupted resume type |
| 572 | hr = RegistrationDetectResumeType(®istration, &resumeType); | 729 | hr = RegistrationDetectResumeType(®istration, &resumeType); |
| 573 | TestThrowOnFailure(hr, L"Failed to read interrupted resume type."); | 730 | TestThrowOnFailure(hr, L"Failed to read interrupted resume type."); |
| @@ -591,8 +748,11 @@ namespace Bootstrapper | |||
| 591 | hr = RegistrationLoadState(®istration, &pbBuffer, &cbBuffer); | 748 | hr = RegistrationLoadState(®istration, &pbBuffer, &cbBuffer); |
| 592 | TestThrowOnFailure(hr, L"Failed to load state."); | 749 | TestThrowOnFailure(hr, L"Failed to load state."); |
| 593 | 750 | ||
| 594 | Assert::Equal((SIZE_T)sizeof(rgbData), cbBuffer); | 751 | hr = VariableDeserialize(&variables, TRUE, pbBuffer, cbBuffer, &piBuffer); |
| 595 | Assert::True(0 == memcmp(pbBuffer, rgbData, sizeof(rgbData))); | 752 | TestThrowOnFailure(hr, L"Failed to deserialize variables."); |
| 753 | |||
| 754 | //Assert::Equal((SIZE_T)sizeof(rgbData), cbBuffer); | ||
| 755 | //Assert::True(0 == memcmp(pbBuffer, rgbData, sizeof(rgbData))); | ||
| 596 | 756 | ||
| 597 | // write active resume mode | 757 | // write active resume mode |
| 598 | hr = RegistrationSessionResume(®istration, &variables, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); | 758 | hr = RegistrationSessionResume(®istration, &variables, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h index d2b57d61..78c44d39 100644 --- a/src/burn/test/BurnUnitTest/precomp.h +++ b/src/burn/test/BurnUnitTest/precomp.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <xmlutil.h> | 30 | #include <xmlutil.h> |
| 31 | #include <dictutil.h> | 31 | #include <dictutil.h> |
| 32 | #include <deputil.h> | 32 | #include <deputil.h> |
| 33 | #include <butil.h> | ||
| 33 | 34 | ||
| 34 | #include "BootstrapperEngine.h" | 35 | #include "BootstrapperEngine.h" |
| 35 | #include "BootstrapperApplication.h" | 36 | #include "BootstrapperApplication.h" |
diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp index e04b52e9..cda2a658 100644 --- a/src/libs/dutil/WixToolset.DUtil/butil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; | 20 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; |
| 21 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgradeCode"; | 21 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgradeCode"; |
| 22 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; | 22 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; |
| 23 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; | ||
| 23 | 24 | ||
| 24 | // Forward declarations. | 25 | // Forward declarations. |
| 25 | /******************************************************************** | 26 | /******************************************************************** |
| @@ -29,10 +30,13 @@ NOTE: caller is responsible for closing key | |||
| 29 | ********************************************************************/ | 30 | ********************************************************************/ |
| 30 | static HRESULT OpenBundleKey( | 31 | static HRESULT OpenBundleKey( |
| 31 | __in_z LPCWSTR wzBundleId, | 32 | __in_z LPCWSTR wzBundleId, |
| 32 | __in BUNDLE_INSTALL_CONTEXT context, | 33 | __in BUNDLE_INSTALL_CONTEXT context, |
| 33 | __inout HKEY *key); | 34 | __in_opt LPCWSTR szSubKey, |
| 34 | 35 | __inout HKEY* key); | |
| 35 | 36 | ||
| 37 | /******************************************************************** | ||
| 38 | BundleGetBundleInfo - Read the registration data for a gven bundle | ||
| 39 | ********************************************************************/ | ||
| 36 | extern "C" HRESULT DAPI BundleGetBundleInfo( | 40 | extern "C" HRESULT DAPI BundleGetBundleInfo( |
| 37 | __in_z LPCWSTR wzBundleId, | 41 | __in_z LPCWSTR wzBundleId, |
| 38 | __in_z LPCWSTR wzAttribute, | 42 | __in_z LPCWSTR wzAttribute, |
| @@ -43,7 +47,6 @@ extern "C" HRESULT DAPI BundleGetBundleInfo( | |||
| 43 | Assert(wzBundleId && wzAttribute); | 47 | Assert(wzBundleId && wzAttribute); |
| 44 | 48 | ||
| 45 | HRESULT hr = S_OK; | 49 | HRESULT hr = S_OK; |
| 46 | BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE; | ||
| 47 | LPWSTR sczValue = NULL; | 50 | LPWSTR sczValue = NULL; |
| 48 | HKEY hkBundle = NULL; | 51 | HKEY hkBundle = NULL; |
| 49 | DWORD cchSource = 0; | 52 | DWORD cchSource = 0; |
| @@ -55,8 +58,8 @@ extern "C" HRESULT DAPI BundleGetBundleInfo( | |||
| 55 | ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); | 58 | ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); |
| 56 | } | 59 | } |
| 57 | 60 | ||
| 58 | if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, &hkBundle)) && | 61 | if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, NULL, &hkBundle)) && |
| 59 | FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, &hkBundle))) | 62 | FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, NULL, &hkBundle))) |
| 60 | { | 63 | { |
| 61 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key path."); | 64 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key path."); |
| 62 | } | 65 | } |
| @@ -108,7 +111,10 @@ LExit: | |||
| 108 | return hr; | 111 | return hr; |
| 109 | } | 112 | } |
| 110 | 113 | ||
| 111 | HRESULT DAPI BundleEnumRelatedBundle( | 114 | /******************************************************************** |
| 115 | ********************************************************************/ | ||
| 116 | |||
| 117 | extern "C" HRESULT DAPI BundleEnumRelatedBundle( | ||
| 112 | __in_z LPCWSTR wzUpgradeCode, | 118 | __in_z LPCWSTR wzUpgradeCode, |
| 113 | __in BUNDLE_INSTALL_CONTEXT context, | 119 | __in BUNDLE_INSTALL_CONTEXT context, |
| 114 | __inout PDWORD pdwStartIndex, | 120 | __inout PDWORD pdwStartIndex, |
| @@ -231,11 +237,80 @@ LExit: | |||
| 231 | return hr; | 237 | return hr; |
| 232 | } | 238 | } |
| 233 | 239 | ||
| 240 | /******************************************************************** | ||
| 241 | BundleGetBundleVariable - Queries the bundle installation metadata for a given variable, | ||
| 242 | the caller is expected to free the memory returned vis psczValue | ||
| 243 | RETURNS: | ||
| 244 | S_OK | ||
| 245 | Success, if the variable had a value, it's returned in psczValue | ||
| 246 | E_INVALIDARG | ||
| 247 | An invalid parameter was passed to the function. | ||
| 248 | HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) | ||
| 249 | The bundle is not installed | ||
| 250 | HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) | ||
| 251 | The variable is unrecognized | ||
| 252 | E_NOTIMPL: | ||
| 253 | Tried to read a bundle variable for a type which has not been implemented | ||
| 254 | |||
| 255 | All other returns are unexpected returns from other dutil methods. | ||
| 256 | ********************************************************************/ | ||
| 257 | |||
| 258 | extern "C" HRESULT DAPI BundleGetBundleVariable( | ||
| 259 | __in_z LPCWSTR wzBundleId, | ||
| 260 | __in_z LPCWSTR wzVariable, | ||
| 261 | __deref_out_z LPWSTR * psczValue | ||
| 262 | ) | ||
| 263 | { | ||
| 264 | Assert(wzBundleId && wzVariable); | ||
| 265 | |||
| 266 | HRESULT hr = S_OK; | ||
| 267 | BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE; | ||
| 268 | HKEY hkBundle = NULL; | ||
| 269 | DWORD dwType = 0; | ||
| 270 | |||
| 271 | if (!wzBundleId || !wzVariable || !psczValue) | ||
| 272 | { | ||
| 273 | ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); | ||
| 274 | } | ||
| 275 | |||
| 276 | if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle)) && | ||
| 277 | FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle))) | ||
| 278 | { | ||
| 279 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key variable path."); | ||
| 280 | } | ||
| 281 | |||
| 282 | // If the bundle doesn't have the shared variable defined, return ERROR_UNKNOWN_PROPERTY | ||
| 283 | hr = RegGetType(hkBundle, wzVariable, &dwType); | ||
| 284 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) : hr, "Failed to locate bundle variable."); | ||
| 285 | |||
| 286 | switch (dwType) | ||
| 287 | { | ||
| 288 | case REG_SZ: | ||
| 289 | hr = RegReadString(hkBundle, wzVariable, psczValue); | ||
| 290 | ButilExitOnFailure(hr, "Failed to read string shared variable."); | ||
| 291 | break; | ||
| 292 | case REG_NONE: | ||
| 293 | hr = S_OK; | ||
| 294 | break; | ||
| 295 | default: | ||
| 296 | ButilExitOnFailure(hr = E_NOTIMPL, "Reading bundle variable of type 0x%x not implemented.", dwType); | ||
| 297 | |||
| 298 | } | ||
| 299 | |||
| 300 | LExit: | ||
| 301 | ReleaseRegKey(hkBundle); | ||
| 234 | 302 | ||
| 303 | return hr; | ||
| 304 | |||
| 305 | } | ||
| 306 | /******************************************************************** | ||
| 307 | * | ||
| 308 | ********************************************************************/ | ||
| 235 | HRESULT OpenBundleKey( | 309 | HRESULT OpenBundleKey( |
| 236 | __in_z LPCWSTR wzBundleId, | 310 | __in_z LPCWSTR wzBundleId, |
| 237 | __in BUNDLE_INSTALL_CONTEXT context, | 311 | __in BUNDLE_INSTALL_CONTEXT context, |
| 238 | __inout HKEY *key) | 312 | __in_opt LPCWSTR szSubKey, |
| 313 | __inout HKEY* key) | ||
| 239 | { | 314 | { |
| 240 | Assert(key && wzBundleId); | 315 | Assert(key && wzBundleId); |
| 241 | AssertSz(NULL == *key, "*key should be null"); | 316 | AssertSz(NULL == *key, "*key should be null"); |
| @@ -244,9 +319,16 @@ HRESULT OpenBundleKey( | |||
| 244 | HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | 319 | HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
| 245 | LPWSTR sczKeypath = NULL; | 320 | LPWSTR sczKeypath = NULL; |
| 246 | 321 | ||
| 247 | hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId); | 322 | if (szSubKey) |
| 323 | { | ||
| 324 | hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId, szSubKey); | ||
| 325 | } | ||
| 326 | else | ||
| 327 | { | ||
| 328 | hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId); | ||
| 329 | } | ||
| 248 | ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); | 330 | ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); |
| 249 | 331 | ||
| 250 | hr = RegOpen(hkRoot, sczKeypath, KEY_READ, key); | 332 | hr = RegOpen(hkRoot, sczKeypath, KEY_READ, key); |
| 251 | ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); | 333 | ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); |
| 252 | 334 | ||
| @@ -255,3 +337,4 @@ LExit: | |||
| 255 | 337 | ||
| 256 | return hr; | 338 | return hr; |
| 257 | } | 339 | } |
| 340 | |||
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/butil.h b/src/libs/dutil/WixToolset.DUtil/inc/butil.h index d1ec73bc..d910c113 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/butil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/butil.h | |||
| @@ -6,11 +6,11 @@ | |||
| 6 | extern "C" { | 6 | extern "C" { |
| 7 | #endif | 7 | #endif |
| 8 | 8 | ||
| 9 | enum BUNDLE_INSTALL_CONTEXT | 9 | typedef enum BUNDLE_INSTALL_CONTEXT |
| 10 | { | 10 | { |
| 11 | BUNDLE_INSTALL_CONTEXT_MACHINE, | 11 | BUNDLE_INSTALL_CONTEXT_MACHINE, |
| 12 | BUNDLE_INSTALL_CONTEXT_USER, | 12 | BUNDLE_INSTALL_CONTEXT_USER, |
| 13 | }; | 13 | } BUNDLE_INSTALL_CONTEXT; |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | /******************************************************************** | 16 | /******************************************************************** |
| @@ -55,6 +55,13 @@ HRESULT DAPI BundleEnumRelatedBundle( | |||
| 55 | __out_ecount(MAX_GUID_CHARS+1) LPWSTR lpBundleIdBuf | 55 | __out_ecount(MAX_GUID_CHARS+1) LPWSTR lpBundleIdBuf |
| 56 | ); | 56 | ); |
| 57 | 57 | ||
| 58 | HRESULT DAPI BundleGetBundleVariable( | ||
| 59 | __in_z LPCWSTR wzBundleId, | ||
| 60 | __in_z LPCWSTR wzVariable, | ||
| 61 | __deref_out_z LPWSTR* psczValue | ||
| 62 | ); | ||
| 63 | |||
| 64 | |||
| 58 | #ifdef __cplusplus | 65 | #ifdef __cplusplus |
| 59 | } | 66 | } |
| 60 | #endif | 67 | #endif |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h index 75284940..fcf13054 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h | |||
| @@ -178,6 +178,10 @@ HRESULT DAPI RegReadVersion( | |||
| 178 | __in_z_opt LPCWSTR wzName, | 178 | __in_z_opt LPCWSTR wzName, |
| 179 | __out DWORD64* pdw64Version | 179 | __out DWORD64* pdw64Version |
| 180 | ); | 180 | ); |
| 181 | HRESULT DAPI RegReadNone( | ||
| 182 | __in HKEY hk, | ||
| 183 | __in_z_opt LPCWSTR wzName | ||
| 184 | ); | ||
| 181 | HRESULT DAPI RegReadNumber( | 185 | HRESULT DAPI RegReadNumber( |
| 182 | __in HKEY hk, | 186 | __in HKEY hk, |
| 183 | __in_z_opt LPCWSTR wzName, | 187 | __in_z_opt LPCWSTR wzName, |
| @@ -211,6 +215,10 @@ HRESULT DAPI RegWriteStringFormatted( | |||
| 211 | __in __format_string LPCWSTR szFormat, | 215 | __in __format_string LPCWSTR szFormat, |
| 212 | ... | 216 | ... |
| 213 | ); | 217 | ); |
| 218 | HRESULT DAPI RegWriteNone( | ||
| 219 | __in HKEY hk, | ||
| 220 | __in_z_opt LPCWSTR wzName | ||
| 221 | ); | ||
| 214 | HRESULT DAPI RegWriteNumber( | 222 | HRESULT DAPI RegWriteNumber( |
| 215 | __in HKEY hk, | 223 | __in HKEY hk, |
| 216 | __in_z_opt LPCWSTR wzName, | 224 | __in_z_opt LPCWSTR wzName, |
diff --git a/src/libs/dutil/WixToolset.DUtil/regutil.cpp b/src/libs/dutil/WixToolset.DUtil/regutil.cpp index cb617932..458d8586 100644 --- a/src/libs/dutil/WixToolset.DUtil/regutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/regutil.cpp | |||
| @@ -672,6 +672,34 @@ LExit: | |||
| 672 | return hr; | 672 | return hr; |
| 673 | } | 673 | } |
| 674 | 674 | ||
| 675 | /******************************************************************** | ||
| 676 | RegReadNone - reads a NONE registry key value. | ||
| 677 | |||
| 678 | *********************************************************************/ | ||
| 679 | extern "C" HRESULT DAPI RegReadNone( | ||
| 680 | __in HKEY hk, | ||
| 681 | __in_z_opt LPCWSTR wzName) | ||
| 682 | { | ||
| 683 | HRESULT hr = S_OK; | ||
| 684 | DWORD er = ERROR_SUCCESS; | ||
| 685 | DWORD dwType = 0; | ||
| 686 | |||
| 687 | er = vpfnRegQueryValueExW(hk, wzName, NULL, &dwType, NULL, NULL); | ||
| 688 | if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) | ||
| 689 | { | ||
| 690 | ExitFunction1(hr = E_FILENOTFOUND); | ||
| 691 | } | ||
| 692 | RegExitOnWin32Error(er, hr, "Failed to query registry key value."); | ||
| 693 | |||
| 694 | if (REG_NONE != dwType) | ||
| 695 | { | ||
| 696 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE); | ||
| 697 | RegExitOnRootFailure(hr, "Error reading version registry value due to unexpected data type: %u", dwType); | ||
| 698 | } | ||
| 699 | |||
| 700 | LExit: | ||
| 701 | return hr; | ||
| 702 | } | ||
| 675 | 703 | ||
| 676 | /******************************************************************** | 704 | /******************************************************************** |
| 677 | RegReadNumber - reads a DWORD registry key value as a number. | 705 | RegReadNumber - reads a DWORD registry key value as a number. |
| @@ -886,6 +914,25 @@ LExit: | |||
| 886 | } | 914 | } |
| 887 | 915 | ||
| 888 | /******************************************************************** | 916 | /******************************************************************** |
| 917 | RegWriteNone - writes a registry key value as none. | ||
| 918 | |||
| 919 | *********************************************************************/ | ||
| 920 | extern "C" HRESULT DAPI RegWriteNone( | ||
| 921 | __in HKEY hk, | ||
| 922 | __in_z_opt LPCWSTR wzName | ||
| 923 | ) | ||
| 924 | { | ||
| 925 | HRESULT hr = S_OK; | ||
| 926 | DWORD er = ERROR_SUCCESS; | ||
| 927 | |||
| 928 | er = vpfnRegSetValueExW(hk, wzName, 0, REG_NONE, NULL, NULL); | ||
| 929 | RegExitOnWin32Error(er, hr, "Failed to set %ls value.", wzName); | ||
| 930 | |||
| 931 | LExit: | ||
| 932 | return hr; | ||
| 933 | } | ||
| 934 | |||
| 935 | /******************************************************************** | ||
| 889 | RegWriteNumber - writes a registry key value as a number. | 936 | RegWriteNumber - writes a registry key value as a number. |
| 890 | 937 | ||
| 891 | *********************************************************************/ | 938 | *********************************************************************/ |
