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/burn | |
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/burn')
-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 |
3 files changed, 262 insertions, 9 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" |