| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | |
| 3 | #include "precomp.h" |
| 4 | |
| 5 | |
| 6 | #define REGISTRY_UNINSTALL_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" |
| 7 | #define REGISTRY_RUN_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce" |
| 8 | #define TEST_BUNDLE_ID L"{D54F896D-1952-43E6-9C67-B5652240618C}" |
| 9 | #define TEST_BUNDLE_UPGRADE_CODE L"{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}" |
| 10 | |
| 11 | |
| 12 | namespace Microsoft |
| 13 | { |
| 14 | namespace Tools |
| 15 | { |
| 16 | namespace WindowsInstallerXml |
| 17 | { |
| 18 | namespace Test |
| 19 | { |
| 20 | namespace Bootstrapper |
| 21 | { |
| 22 | using namespace Microsoft::Win32; |
| 23 | using namespace System; |
| 24 | using namespace System::IO; |
| 25 | using namespace Xunit; |
| 26 | using namespace WixInternal::TestSupport; |
| 27 | |
| 28 | public ref class RegistrationTest : BurnUnitTest, IClassFixture<TestRegistryFixture^> |
| 29 | { |
| 30 | private: |
| 31 | TestRegistryFixture^ testRegistry; |
| 32 | String^ testRunKeyPath; |
| 33 | String^ testUninstallKeyPath; |
| 34 | String^ testVariableKeyPath; |
| 35 | public: |
| 36 | RegistrationTest(BurnTestFixture^ fixture, TestRegistryFixture^ registryFixture) : BurnUnitTest(fixture) |
| 37 | { |
| 38 | this->testRegistry = registryFixture; |
| 39 | |
| 40 | this->testRunKeyPath = this->testRegistry->GetDirectHkcuPath(REG_KEY_DEFAULT, gcnew String(REGISTRY_RUN_KEY)); |
| 41 | this->testUninstallKeyPath = this->testRegistry->GetDirectHkcuPath(REG_KEY_DEFAULT, gcnew String(REGISTRY_UNINSTALL_KEY), gcnew String(TEST_BUNDLE_ID)); |
| 42 | this->testVariableKeyPath = Path::Combine(this->testUninstallKeyPath, gcnew String(L"variables")); |
| 43 | } |
| 44 | |
| 45 | [Fact] |
| 46 | void RegisterBasicTest() |
| 47 | { |
| 48 | HRESULT hr = S_OK; |
| 49 | IXMLDOMElement* pixeBundle = NULL; |
| 50 | LPWSTR sczCurrentProcess = NULL; |
| 51 | BURN_VARIABLES variables = { }; |
| 52 | BURN_USER_EXPERIENCE userExperience = { }; |
| 53 | BOOTSTRAPPER_COMMAND command = { }; |
| 54 | BURN_REGISTRATION registration = { }; |
| 55 | BURN_LOGGING logging = { }; |
| 56 | BURN_PACKAGES packages = { }; |
| 57 | BURN_PLAN plan = { }; |
| 58 | BURN_CACHE cache = { }; |
| 59 | BURN_ENGINE_COMMAND internalCommand = { }; |
| 60 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID)); |
| 61 | String^ cacheExePath = Path::Combine(cacheDirectory, gcnew String(L"setup.exe")); |
| 62 | DWORD dwRegistrationOptions = BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; |
| 63 | DWORD64 qwEstimatedSize = 1024; |
| 64 | |
| 65 | try |
| 66 | { |
| 67 | this->testRegistry->SetUp(); |
| 68 | |
| 69 | logging.sczPath = L"BurnUnitTest.txt"; |
| 70 | |
| 71 | LPCWSTR wzDocument = |
| 72 | L"<Bundle>" |
| 73 | L" <UX PrimaryPayloadId='ux.exe'>" |
| 74 | L" <Payload Id='ux.exe' FilePath='ux.exe' Packaging='embedded' SourcePath='ux.exe' Hash='000000000000' />" |
| 75 | L" </UX>" |
| 76 | L" <Registration Id='{D54F896D-1952-43E6-9C67-B5652240618C}' UpgradeCode='{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 77 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='RegisterBasicTest' DisplayVersion='1.0.0.0' />" |
| 78 | L" </Registration>" |
| 79 | L"</Bundle>"; |
| 80 | |
| 81 | // load XML document |
| 82 | LoadBundleXmlHelper(wzDocument, &pixeBundle); |
| 83 | |
| 84 | hr = CacheInitialize(&cache, &internalCommand); |
| 85 | TestThrowOnFailure(hr, L"Failed initialize cache."); |
| 86 | |
| 87 | hr = VariableInitialize(&variables); |
| 88 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 89 | |
| 90 | hr = BootstrapperApplicationParseFromXml(&userExperience, pixeBundle); |
| 91 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 92 | |
| 93 | hr = RegistrationParseFromXml(®istration, &cache, pixeBundle); |
| 94 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); |
| 95 | |
| 96 | plan.action = BOOTSTRAPPER_ACTION_INSTALL; |
| 97 | plan.pCommand = &command; |
| 98 | plan.pInternalCommand = &internalCommand; |
| 99 | |
| 100 | hr = PlanSetResumeCommand(&plan, ®istration, &logging); |
| 101 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); |
| 102 | |
| 103 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); |
| 104 | TestThrowOnFailure(hr, L"Failed to get current process path."); |
| 105 | |
| 106 | // write registration |
| 107 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 108 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 109 | |
| 110 | // verify that registration was created |
| 111 | Assert::True(Directory::Exists(cacheDirectory), "Cache directory didn't exist."); |
| 112 | Assert::True(File::Exists(Path::Combine(cacheDirectory, gcnew String(L"setup.exe"))), "Bundle exe wasn't cached."); |
| 113 | |
| 114 | this->ValidateUninstallKeyString(L"InstallDate", DateTime::Now.ToString("yyyyMMdd")); |
| 115 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ACTIVE)); |
| 116 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 117 | |
| 118 | // end session |
| 119 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); |
| 120 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 121 | |
| 122 | // verify that registration was removed |
| 123 | Assert::False(Directory::Exists(cacheDirectory), "Cache directory wasn't removed."); |
| 124 | |
| 125 | this->ValidateUninstallKeyNull(L"InstallDate"); |
| 126 | this->ValidateUninstallKeyNull(L"Resume"); |
| 127 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 128 | } |
| 129 | finally |
| 130 | { |
| 131 | ReleaseStr(sczCurrentProcess); |
| 132 | ReleaseObject(pixeBundle); |
| 133 | BootstrapperApplicationUninitialize(&userExperience); |
| 134 | RegistrationUninitialize(®istration); |
| 135 | VariablesUninitialize(&variables); |
| 136 | |
| 137 | if (Directory::Exists(cacheDirectory)) |
| 138 | { |
| 139 | Directory::Delete(cacheDirectory, true); |
| 140 | } |
| 141 | |
| 142 | this->testRegistry->TearDown(); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | [Fact] |
| 147 | void RegisterArpMinimumTest() |
| 148 | { |
| 149 | HRESULT hr = S_OK; |
| 150 | IXMLDOMElement* pixeBundle = NULL; |
| 151 | LPWSTR sczCurrentProcess = NULL; |
| 152 | BURN_VARIABLES variables = { }; |
| 153 | BURN_USER_EXPERIENCE userExperience = { }; |
| 154 | BOOTSTRAPPER_COMMAND command = { }; |
| 155 | BURN_REGISTRATION registration = { }; |
| 156 | BURN_LOGGING logging = { }; |
| 157 | BURN_PACKAGES packages = { }; |
| 158 | BURN_PLAN plan = { }; |
| 159 | BURN_CACHE cache = { }; |
| 160 | BURN_ENGINE_COMMAND internalCommand = { }; |
| 161 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID)); |
| 162 | String^ cacheExePath = Path::Combine(cacheDirectory, gcnew String(L"setup.exe")); |
| 163 | DWORD dwRegistrationOptions = 0; |
| 164 | DWORD64 qwEstimatedSize = 1024; |
| 165 | try |
| 166 | { |
| 167 | this->testRegistry->SetUp(); |
| 168 | |
| 169 | logging.sczPath = L"BurnUnitTest.txt"; |
| 170 | |
| 171 | LPCWSTR wzDocument = |
| 172 | L"<Bundle>" |
| 173 | L" <UX PrimaryPayloadId='ux.exe'>" |
| 174 | L" <Payload Id='ux.exe' FilePath='ux.exe' Packaging='embedded' SourcePath='ux.exe' Hash='000000000000' />" |
| 175 | L" </UX>" |
| 176 | L" <Registration Id='{D54F896D-1952-43E6-9C67-B5652240618C}' UpgradeCode='{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 177 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='Product1' InProgressDisplayName='Product1 Installation' DisplayVersion='1.0.0.0' />" |
| 178 | L" </Registration>" |
| 179 | L"</Bundle>"; |
| 180 | |
| 181 | // load XML document |
| 182 | LoadBundleXmlHelper(wzDocument, &pixeBundle); |
| 183 | |
| 184 | hr = CacheInitialize(&cache, &internalCommand); |
| 185 | TestThrowOnFailure(hr, L"Failed initialize cache."); |
| 186 | |
| 187 | hr = VariableInitialize(&variables); |
| 188 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 189 | |
| 190 | hr = BootstrapperApplicationParseFromXml(&userExperience, pixeBundle); |
| 191 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 192 | |
| 193 | hr = RegistrationParseFromXml(®istration, &cache, pixeBundle); |
| 194 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); |
| 195 | |
| 196 | plan.action = BOOTSTRAPPER_ACTION_INSTALL; |
| 197 | plan.pCommand = &command; |
| 198 | plan.pInternalCommand = &internalCommand; |
| 199 | |
| 200 | hr = PlanSetResumeCommand(&plan, ®istration, &logging); |
| 201 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); |
| 202 | |
| 203 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); |
| 204 | TestThrowOnFailure(hr, L"Failed to get current process path."); |
| 205 | |
| 206 | // |
| 207 | // install |
| 208 | // |
| 209 | |
| 210 | // write registration |
| 211 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 212 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 213 | |
| 214 | // verify that registration was created |
| 215 | this->ValidateUninstallKeyDisplayName(L"Product1 Installation"); |
| 216 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ACTIVE)); |
| 217 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 218 | |
| 219 | // complete registration |
| 220 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 221 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 222 | |
| 223 | // verify that registration was updated |
| 224 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ARP)); |
| 225 | this->ValidateUninstallKeyInstalled(0); |
| 226 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 227 | |
| 228 | // |
| 229 | // uninstall |
| 230 | // |
| 231 | |
| 232 | // write registration |
| 233 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 234 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 235 | |
| 236 | // verify that registration was updated |
| 237 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ACTIVE)); |
| 238 | this->ValidateUninstallKeyInstalled(0); |
| 239 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 240 | |
| 241 | // delete registration |
| 242 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); |
| 243 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 244 | |
| 245 | // verify that registration was removed |
| 246 | this->ValidateUninstallKeyNull(L"Resume"); |
| 247 | this->ValidateUninstallKeyNull(L"Installed"); |
| 248 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 249 | } |
| 250 | finally |
| 251 | { |
| 252 | ReleaseStr(sczCurrentProcess); |
| 253 | ReleaseObject(pixeBundle); |
| 254 | BootstrapperApplicationUninitialize(&userExperience); |
| 255 | RegistrationUninitialize(®istration); |
| 256 | VariablesUninitialize(&variables); |
| 257 | |
| 258 | if (Directory::Exists(cacheDirectory)) |
| 259 | { |
| 260 | Directory::Delete(cacheDirectory, true); |
| 261 | } |
| 262 | |
| 263 | this->testRegistry->TearDown(); |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | [Fact] |
| 268 | void RegisterVariablesTest() |
| 269 | { |
| 270 | HRESULT hr = S_OK; |
| 271 | IXMLDOMElement* pixeBundle = NULL; |
| 272 | LPWSTR sczCurrentProcess = NULL; |
| 273 | BURN_VARIABLES variables = { }; |
| 274 | BURN_USER_EXPERIENCE userExperience = { }; |
| 275 | BOOTSTRAPPER_COMMAND command = { }; |
| 276 | BURN_REGISTRATION registration = { }; |
| 277 | BURN_LOGGING logging = { }; |
| 278 | BURN_PACKAGES packages = { }; |
| 279 | BURN_PLAN plan = { }; |
| 280 | BURN_CACHE cache = { }; |
| 281 | BURN_ENGINE_COMMAND internalCommand = { }; |
| 282 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID)); |
| 283 | String^ cacheExePath = Path::Combine(cacheDirectory, gcnew String(L"setup.exe")); |
| 284 | DWORD dwRegistrationOptions = 0; |
| 285 | DWORD64 qwEstimatedSize = 1024; |
| 286 | try |
| 287 | { |
| 288 | this->testRegistry->SetUp(); |
| 289 | |
| 290 | logging.sczPath = L"BurnUnitTest.txt"; |
| 291 | |
| 292 | LPCWSTR wzDocument = |
| 293 | L"<Bundle>" |
| 294 | L" <UX PrimaryPayloadId='ux.exe'>" |
| 295 | L" <Payload Id='ux.exe' FilePath='ux.exe' Packaging='embedded' SourcePath='ux.exe' Hash='000000000000' />" |
| 296 | L" </UX>" |
| 297 | L" <Registration Id='{D54F896D-1952-43E6-9C67-B5652240618C}' UpgradeCode='{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}' Tag='foo' ProviderKey='bar' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 298 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='Product1' DisplayVersion='1.0.0.0' />" |
| 299 | L" </Registration>" |
| 300 | L"</Bundle>"; |
| 301 | |
| 302 | // load XML document |
| 303 | LoadBundleXmlHelper(wzDocument, &pixeBundle); |
| 304 | |
| 305 | hr = CacheInitialize(&cache, &internalCommand); |
| 306 | TestThrowOnFailure(hr, L"Failed initialize cache."); |
| 307 | |
| 308 | hr = VariableInitialize(&variables); |
| 309 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 310 | |
| 311 | hr = BootstrapperApplicationParseFromXml(&userExperience, pixeBundle); |
| 312 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 313 | |
| 314 | hr = RegistrationParseFromXml(®istration, &cache, pixeBundle); |
| 315 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); |
| 316 | |
| 317 | plan.action = BOOTSTRAPPER_ACTION_INSTALL; |
| 318 | plan.pCommand = &command; |
| 319 | plan.pInternalCommand = &internalCommand; |
| 320 | |
| 321 | hr = RegistrationSetVariables(®istration, &variables); |
| 322 | TestThrowOnFailure(hr, L"Failed to set registration variables."); |
| 323 | |
| 324 | hr = PlanSetResumeCommand(&plan, ®istration, &logging); |
| 325 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); |
| 326 | |
| 327 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); |
| 328 | TestThrowOnFailure(hr, L"Failed to get current process path."); |
| 329 | |
| 330 | // |
| 331 | // install |
| 332 | // |
| 333 | |
| 334 | // write registration |
| 335 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 336 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 337 | |
| 338 | // verify that registration was created |
| 339 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ACTIVE)); |
| 340 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 341 | |
| 342 | // complete registration |
| 343 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_FULL); |
| 344 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 345 | |
| 346 | // verify that registration variables were updated |
| 347 | this->ValidateUninstallKeyDisplayName(L"Product1"); |
| 348 | registration.detectedRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_FULL; |
| 349 | |
| 350 | hr = RegistrationSetDynamicVariables(®istration, &variables); |
| 351 | TestThrowOnFailure(hr, L"Failed to set dynamic registration variables."); |
| 352 | |
| 353 | Assert::Equal(1ll, VariableGetNumericHelper(&variables, BURN_BUNDLE_INSTALLED)); |
| 354 | Assert::Equal<String^>(gcnew String(L"foo"), VariableGetStringHelper(&variables, BURN_BUNDLE_TAG)); |
| 355 | Assert::Equal<String^>(gcnew String(L"bar"), VariableGetStringHelper(&variables, BURN_BUNDLE_PROVIDER_KEY)); |
| 356 | Assert::Equal<String^>(gcnew String(L"1.0.0.0"), VariableGetVersionHelper(&variables, BURN_BUNDLE_VERSION)); |
| 357 | |
| 358 | // |
| 359 | // uninstall |
| 360 | // |
| 361 | |
| 362 | // delete registration |
| 363 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); |
| 364 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 365 | |
| 366 | // verify that registration was removed |
| 367 | this->ValidateUninstallKeyNull(L"Resume"); |
| 368 | this->ValidateUninstallKeyNull(L"Installed"); |
| 369 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 370 | } |
| 371 | finally |
| 372 | { |
| 373 | ReleaseStr(sczCurrentProcess); |
| 374 | ReleaseObject(pixeBundle); |
| 375 | BootstrapperApplicationUninitialize(&userExperience); |
| 376 | RegistrationUninitialize(®istration); |
| 377 | VariablesUninitialize(&variables); |
| 378 | |
| 379 | if (Directory::Exists(cacheDirectory)) |
| 380 | { |
| 381 | Directory::Delete(cacheDirectory, true); |
| 382 | } |
| 383 | |
| 384 | this->testRegistry->TearDown(); |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | [Fact] |
| 389 | void RegisterArpFullTest() |
| 390 | { |
| 391 | HRESULT hr = S_OK; |
| 392 | IXMLDOMElement* pixeBundle = NULL; |
| 393 | LPWSTR sczCurrentProcess = NULL; |
| 394 | BURN_VARIABLES variables = { }; |
| 395 | BURN_USER_EXPERIENCE userExperience = { }; |
| 396 | BOOTSTRAPPER_COMMAND command = { }; |
| 397 | BURN_REGISTRATION registration = { }; |
| 398 | BURN_LOGGING logging = { }; |
| 399 | BURN_PACKAGES packages = { }; |
| 400 | BURN_PLAN plan = { }; |
| 401 | BURN_CACHE cache = { }; |
| 402 | BURN_ENGINE_COMMAND internalCommand = { }; |
| 403 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID)); |
| 404 | String^ cacheExePath = Path::Combine(cacheDirectory, gcnew String(L"setup.exe")); |
| 405 | DWORD dwRegistrationOptions = 0; |
| 406 | DWORD64 qwEstimatedSize = 1024; |
| 407 | try |
| 408 | { |
| 409 | this->testRegistry->SetUp(); |
| 410 | |
| 411 | logging.sczPath = L"BurnUnitTest.txt"; |
| 412 | |
| 413 | LPCWSTR wzDocument = |
| 414 | L"<Bundle>" |
| 415 | L" <UX PrimaryPayloadId='ux.exe'>" |
| 416 | L" <Payload Id='ux.exe' FilePath='ux.exe' Packaging='embedded' SourcePath='ux.exe' Hash='000000000000' />" |
| 417 | L" </UX>" |
| 418 | L" <Registration Id='{D54F896D-1952-43E6-9C67-B5652240618C}' UpgradeCode='{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 419 | L" <Arp Register='yes' DisplayName='DisplayName1' DisplayVersion='1.2.3.4' Publisher='Publisher1' HelpLink='http://www.microsoft.com/help'" |
| 420 | L" HelpTelephone='555-555-5555' AboutUrl='http://www.microsoft.com/about' UpdateUrl='http://www.microsoft.com/update'" |
| 421 | L" Comments='Comments1' Contact='Contact1' DisableModify='yes' DisableRemove='yes' />" |
| 422 | L" </Registration>" |
| 423 | L"</Bundle>"; |
| 424 | |
| 425 | // load XML document |
| 426 | LoadBundleXmlHelper(wzDocument, &pixeBundle); |
| 427 | |
| 428 | hr = CacheInitialize(&cache, &internalCommand); |
| 429 | TestThrowOnFailure(hr, L"Failed initialize cache."); |
| 430 | |
| 431 | hr = VariableInitialize(&variables); |
| 432 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 433 | |
| 434 | hr = BootstrapperApplicationParseFromXml(&userExperience, pixeBundle); |
| 435 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 436 | |
| 437 | hr = RegistrationParseFromXml(®istration, &cache, pixeBundle); |
| 438 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); |
| 439 | |
| 440 | plan.action = BOOTSTRAPPER_ACTION_INSTALL; |
| 441 | plan.pCommand = &command; |
| 442 | plan.pInternalCommand = &internalCommand; |
| 443 | |
| 444 | hr = PlanSetResumeCommand(&plan, ®istration, &logging); |
| 445 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); |
| 446 | |
| 447 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); |
| 448 | TestThrowOnFailure(hr, L"Failed to get current process path."); |
| 449 | |
| 450 | // |
| 451 | // install |
| 452 | // |
| 453 | |
| 454 | // write registration |
| 455 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 456 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 457 | |
| 458 | // verify that registration was created |
| 459 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ACTIVE)); |
| 460 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 461 | |
| 462 | // finish registration |
| 463 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_FULL); |
| 464 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 465 | |
| 466 | // verify that registration was updated |
| 467 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ARP)); |
| 468 | this->ValidateUninstallKeyInstalled(1); |
| 469 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 470 | |
| 471 | this->ValidateUninstallKeyDisplayName(L"DisplayName1"); |
| 472 | this->ValidateUninstallKeyString(L"DisplayVersion", L"1.2.3.4"); |
| 473 | this->ValidateUninstallKeyString(L"Publisher", L"Publisher1"); |
| 474 | this->ValidateUninstallKeyString(L"HelpLink", L"http://www.microsoft.com/help"); |
| 475 | this->ValidateUninstallKeyString(L"HelpTelephone", L"555-555-5555"); |
| 476 | this->ValidateUninstallKeyString(L"URLInfoAbout", L"http://www.microsoft.com/about"); |
| 477 | this->ValidateUninstallKeyString(L"URLUpdateInfo", L"http://www.microsoft.com/update"); |
| 478 | this->ValidateUninstallKeyString(L"Comments", L"Comments1"); |
| 479 | this->ValidateUninstallKeyString(L"Contact", L"Contact1"); |
| 480 | this->ValidateUninstallKeyNumber(L"NoModify", 1); |
| 481 | this->ValidateUninstallKeyNumber(L"NoRemove", 1); |
| 482 | |
| 483 | // |
| 484 | // uninstall |
| 485 | // |
| 486 | |
| 487 | // write registration |
| 488 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 489 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 490 | |
| 491 | // verify that registration was updated |
| 492 | this->ValidateUninstallKeyResume(Int32(BURN_RESUME_MODE_ACTIVE)); |
| 493 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 494 | |
| 495 | // delete registration |
| 496 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); |
| 497 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 498 | |
| 499 | // verify that registration was removed |
| 500 | this->ValidateUninstallKeyNull(L"Resume"); |
| 501 | this->ValidateUninstallKeyNull(L"Installed"); |
| 502 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 503 | } |
| 504 | finally |
| 505 | { |
| 506 | ReleaseStr(sczCurrentProcess); |
| 507 | ReleaseObject(pixeBundle); |
| 508 | BootstrapperApplicationUninitialize(&userExperience); |
| 509 | RegistrationUninitialize(®istration); |
| 510 | VariablesUninitialize(&variables); |
| 511 | |
| 512 | if (Directory::Exists(cacheDirectory)) |
| 513 | { |
| 514 | Directory::Delete(cacheDirectory, true); |
| 515 | } |
| 516 | |
| 517 | this->testRegistry->TearDown(); |
| 518 | } |
| 519 | } |
| 520 | |
| 521 | [Fact] |
| 522 | void DUtilButilTest() |
| 523 | { |
| 524 | HRESULT hr = S_OK; |
| 525 | IXMLDOMElement* pixeBundle = NULL; |
| 526 | LPWSTR sczCurrentProcess = NULL; |
| 527 | LPWSTR sczValue = NULL; |
| 528 | LPWSTR sczRelatedBundleId = NULL; |
| 529 | DWORD dwRelatedBundleIndex = 0; |
| 530 | BURN_VARIABLES variables = { }; |
| 531 | BURN_USER_EXPERIENCE userExperience = { }; |
| 532 | BOOTSTRAPPER_COMMAND command = { }; |
| 533 | BURN_REGISTRATION registration = { }; |
| 534 | BURN_LOGGING logging = { }; |
| 535 | BURN_PACKAGES packages = { }; |
| 536 | BURN_PLAN plan = { }; |
| 537 | BURN_CACHE cache = { }; |
| 538 | BURN_ENGINE_COMMAND internalCommand = { }; |
| 539 | BYTE* pbBuffer = NULL; |
| 540 | SIZE_T cbBuffer = 0; |
| 541 | DWORD dwRegistrationOptions = 0; |
| 542 | DWORD64 qwEstimatedSize = 1024; |
| 543 | |
| 544 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID)); |
| 545 | try |
| 546 | { |
| 547 | this->testRegistry->SetUp(); |
| 548 | |
| 549 | logging.sczPath = L"BurnUnitTest.txt"; |
| 550 | |
| 551 | LPCWSTR wzDocument = |
| 552 | L"<Bundle>" |
| 553 | L" <UX PrimaryPayloadId='ux.exe'>" |
| 554 | L" <Payload Id='ux.exe' FilePath='ux.exe' Packaging='embedded' SourcePath='ux.exe' Hash='000000000000' />" |
| 555 | L" </UX>" |
| 556 | L" <RelatedBundle Id='" TEST_BUNDLE_UPGRADE_CODE L"' Action='Upgrade' />" |
| 557 | L" <Registration Id='" TEST_BUNDLE_ID L"' Tag='foo' ProviderKey='" TEST_BUNDLE_ID L"' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 558 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='RegisterBasicTest' DisplayVersion='1.0.0.0' />" |
| 559 | L" </Registration>" |
| 560 | L" <Variable Id='MyBurnVariable1' Type='numeric' Value='0' Hidden='no' Persisted='yes' />" |
| 561 | L" <Variable Id='MyBurnVariable2' Type='string' Value='foo' Hidden='no' Persisted='yes' />" |
| 562 | L" <Variable Id='MyBurnVariable3' Type='version' Value='v1.1-alpha' Hidden='no' Persisted='yes' />" |
| 563 | L" <Variable Id='MyBurnVariable4' Type='string' Value='foo' Hidden='no' Persisted='no' />" |
| 564 | L" <Variable Id='MyBurnVariable5' Type='version' Hidden='no' Persisted='yes' />" |
| 565 | L"</Bundle>"; |
| 566 | |
| 567 | // load XML document |
| 568 | LoadBundleXmlHelper(wzDocument, &pixeBundle); |
| 569 | |
| 570 | hr = CacheInitialize(&cache, &internalCommand); |
| 571 | TestThrowOnFailure(hr, L"Failed initialize cache."); |
| 572 | |
| 573 | hr = VariableInitialize(&variables); |
| 574 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 575 | |
| 576 | hr = VariablesParseFromXml(&variables, pixeBundle); |
| 577 | TestThrowOnFailure(hr, L"Failed to parse variables from XML."); |
| 578 | |
| 579 | hr = BootstrapperApplicationParseFromXml(&userExperience, pixeBundle); |
| 580 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 581 | |
| 582 | hr = RegistrationParseFromXml(®istration, &cache, pixeBundle); |
| 583 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); |
| 584 | |
| 585 | plan.action = BOOTSTRAPPER_ACTION_INSTALL; |
| 586 | plan.pCommand = &command; |
| 587 | plan.pInternalCommand = &internalCommand; |
| 588 | |
| 589 | hr = PlanSetResumeCommand(&plan, ®istration, &logging); |
| 590 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); |
| 591 | |
| 592 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); |
| 593 | TestThrowOnFailure(hr, L"Failed to get current process path."); |
| 594 | |
| 595 | // begin session |
| 596 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 597 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 598 | |
| 599 | VariableSetNumericHelper(&variables, L"MyBurnVariable1", 42); |
| 600 | VariableSetStringHelper(&variables, L"MyBurnVariable2", L"bar", FALSE); |
| 601 | VariableSetVersionHelper(&variables, L"MyBurnVariable3", L"v1.0-beta"); |
| 602 | VariableSetVersionHelper(&variables, L"MyBurnVariable5", L"vvv"); |
| 603 | |
| 604 | hr = VariableSerialize(&variables, TRUE, &pbBuffer, &cbBuffer); |
| 605 | TestThrowOnFailure(hr, "Failed to serialize variables."); |
| 606 | |
| 607 | if (!Directory::Exists(cacheDirectory)) |
| 608 | { |
| 609 | Directory::CreateDirectory(cacheDirectory); |
| 610 | } |
| 611 | |
| 612 | hr = RegistrationSaveState(®istration, pbBuffer, cbBuffer); |
| 613 | TestThrowOnFailure(hr, L"Failed to save state."); |
| 614 | |
| 615 | ReleaseNullMem(pbBuffer); |
| 616 | cbBuffer = 0; |
| 617 | |
| 618 | // Verify the variables exist |
| 619 | this->ValidateVariableKey(L"MyBurnVariable1", gcnew String(L"42")); |
| 620 | this->ValidateVariableKey(L"MyBurnVariable2", gcnew String(L"bar")); |
| 621 | this->ValidateVariableKey(L"MyBurnVariable3", gcnew String(L"1.0-beta")); |
| 622 | this->ValidateVariableKey(L"MyBurnVariable5", gcnew String(L"vvv")); |
| 623 | this->ValidateVariableKeyEmpty(L"WixBundleForcedRestartPackage"); |
| 624 | |
| 625 | hr = StrAlloc(&sczRelatedBundleId, MAX_GUID_CHARS + 1); |
| 626 | NativeAssert::Succeeded(hr, "Failed to allocate buffer for related bundle id."); |
| 627 | |
| 628 | // Verify we can find ourself via the UpgradeCode |
| 629 | hr = BundleEnumRelatedBundleFixed(TEST_BUNDLE_UPGRADE_CODE, BUNDLE_INSTALL_CONTEXT_USER, REG_KEY_DEFAULT, &dwRelatedBundleIndex, sczRelatedBundleId); |
| 630 | TestThrowOnFailure(hr, L"Failed to enumerate related bundle."); |
| 631 | |
| 632 | NativeAssert::StringEqual(TEST_BUNDLE_ID, sczRelatedBundleId); |
| 633 | |
| 634 | // Verify we can read the bundle variables via the API |
| 635 | hr = BundleGetBundleVariable(TEST_BUNDLE_ID, L"MyBurnVariable1", &sczValue); |
| 636 | TestThrowOnFailure(hr, L"Failed to read MyBurnVariable1."); |
| 637 | |
| 638 | NativeAssert::StringEqual(L"42", sczValue); |
| 639 | |
| 640 | // end session |
| 641 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); |
| 642 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 643 | } |
| 644 | finally |
| 645 | { |
| 646 | ReleaseStr(sczRelatedBundleId); |
| 647 | ReleaseStr(sczCurrentProcess); |
| 648 | ReleaseObject(pixeBundle); |
| 649 | BootstrapperApplicationUninitialize(&userExperience); |
| 650 | RegistrationUninitialize(®istration); |
| 651 | VariablesUninitialize(&variables); |
| 652 | |
| 653 | if (Directory::Exists(cacheDirectory)) |
| 654 | { |
| 655 | Directory::Delete(cacheDirectory, true); |
| 656 | } |
| 657 | |
| 658 | this->testRegistry->TearDown(); |
| 659 | } |
| 660 | } |
| 661 | |
| 662 | [Fact] |
| 663 | void ResumeTest() |
| 664 | { |
| 665 | HRESULT hr = S_OK; |
| 666 | IXMLDOMElement* pixeBundle = NULL; |
| 667 | LPWSTR sczCurrentProcess = NULL; |
| 668 | LPWSTR sczValue = NULL; |
| 669 | BURN_VARIABLES variables = { }; |
| 670 | BURN_USER_EXPERIENCE userExperience = { }; |
| 671 | BOOTSTRAPPER_COMMAND command = { }; |
| 672 | BURN_REGISTRATION registration = { }; |
| 673 | BURN_LOGGING logging = { }; |
| 674 | BURN_PACKAGES packages = { }; |
| 675 | BURN_PLAN plan = { }; |
| 676 | BURN_CACHE cache = { }; |
| 677 | BURN_ENGINE_COMMAND internalCommand = { }; |
| 678 | BOOTSTRAPPER_RESUME_TYPE resumeType = BOOTSTRAPPER_RESUME_TYPE_NONE; |
| 679 | BYTE* pbBuffer = NULL; |
| 680 | SIZE_T cbBuffer = 0; |
| 681 | SIZE_T piBuffer = 0; |
| 682 | String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID)); |
| 683 | String^ cacheExePath = Path::Combine(cacheDirectory, gcnew String(L"setup.exe")); |
| 684 | DWORD dwRegistrationOptions = 0; |
| 685 | DWORD64 qwEstimatedSize = 1024; |
| 686 | try |
| 687 | { |
| 688 | this->testRegistry->SetUp(); |
| 689 | |
| 690 | logging.sczPath = L"BurnUnitTest.txt"; |
| 691 | |
| 692 | LPCWSTR wzDocument = |
| 693 | L"<Bundle>" |
| 694 | L" <UX PrimaryPayloadId='ux.exe'>" |
| 695 | L" <Payload Id='ux.exe' FilePath='ux.exe' Packaging='embedded' SourcePath='ux.exe' Hash='000000000000' />" |
| 696 | L" </UX>" |
| 697 | L" <Registration Id='{D54F896D-1952-43E6-9C67-B5652240618C}' UpgradeCode='{89FDAE1F-8CC1-48B9-B930-3945E0D3E7F0}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" |
| 698 | L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='RegisterBasicTest' DisplayVersion='1.0.0.0' />" |
| 699 | L" </Registration>" |
| 700 | L" <Variable Id='MyBurnVariable1' Type='numeric' Value='0' Hidden='no' Persisted='yes' />" |
| 701 | L" <Variable Id='MyBurnVariable2' Type='string' Value='foo' Hidden='no' Persisted='yes' />" |
| 702 | L" <Variable Id='MyBurnVariable3' Type='version' Value='v1.1-alpha' Hidden='no' Persisted='yes' />" |
| 703 | L"</Bundle>"; |
| 704 | |
| 705 | // load XML document |
| 706 | LoadBundleXmlHelper(wzDocument, &pixeBundle); |
| 707 | |
| 708 | hr = CacheInitialize(&cache, &internalCommand); |
| 709 | TestThrowOnFailure(hr, L"Failed initialize cache."); |
| 710 | |
| 711 | hr = VariableInitialize(&variables); |
| 712 | TestThrowOnFailure(hr, L"Failed to initialize variables."); |
| 713 | |
| 714 | hr = VariablesParseFromXml(&variables, pixeBundle); |
| 715 | TestThrowOnFailure(hr, L"Failed to parse variables from XML."); |
| 716 | |
| 717 | hr = BootstrapperApplicationParseFromXml(&userExperience, pixeBundle); |
| 718 | TestThrowOnFailure(hr, L"Failed to parse UX from XML."); |
| 719 | |
| 720 | hr = RegistrationParseFromXml(®istration, &cache, pixeBundle); |
| 721 | TestThrowOnFailure(hr, L"Failed to parse registration from XML."); |
| 722 | |
| 723 | plan.action = BOOTSTRAPPER_ACTION_INSTALL; |
| 724 | plan.pCommand = &command; |
| 725 | plan.pInternalCommand = &internalCommand; |
| 726 | |
| 727 | hr = PlanSetResumeCommand(&plan, ®istration, &logging); |
| 728 | TestThrowOnFailure(hr, L"Failed to set registration resume command."); |
| 729 | |
| 730 | hr = PathForCurrentProcess(&sczCurrentProcess, NULL); |
| 731 | TestThrowOnFailure(hr, L"Failed to get current process path."); |
| 732 | |
| 733 | // read resume type before session |
| 734 | hr = RegistrationDetectResumeType(®istration, &resumeType); |
| 735 | TestThrowOnFailure(hr, L"Failed to read resume type."); |
| 736 | |
| 737 | Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_NONE, (int)resumeType); |
| 738 | |
| 739 | // begin session |
| 740 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 741 | TestThrowOnFailure(hr, L"Failed to register bundle."); |
| 742 | |
| 743 | VariableSetNumericHelper(&variables, L"MyBurnVariable1", 42); |
| 744 | VariableSetStringHelper(&variables, L"MyBurnVariable2", L"bar", FALSE); |
| 745 | VariableSetVersionHelper(&variables, L"MyBurnVariable3", L"v1.0-beta"); |
| 746 | |
| 747 | hr = VariableSerialize(&variables, TRUE, &pbBuffer, &cbBuffer); |
| 748 | TestThrowOnFailure(hr, "Failed to serialize variables."); |
| 749 | |
| 750 | if (!Directory::Exists(cacheDirectory)) |
| 751 | { |
| 752 | Directory::CreateDirectory(cacheDirectory); |
| 753 | } |
| 754 | |
| 755 | hr = RegistrationSaveState(®istration, pbBuffer, cbBuffer); |
| 756 | TestThrowOnFailure(hr, L"Failed to save state."); |
| 757 | |
| 758 | ReleaseNullMem(pbBuffer); |
| 759 | cbBuffer = 0; |
| 760 | |
| 761 | // Verify the variables exist |
| 762 | this->ValidateVariableKey(L"MyBurnVariable1", gcnew String(L"42")); |
| 763 | this->ValidateVariableKey(L"MyBurnVariable2", gcnew String(L"bar")); |
| 764 | this->ValidateVariableKey(L"MyBurnVariable3", gcnew String(L"1.0-beta")); |
| 765 | this->ValidateVariableKeyEmpty(L"WixBundleForcedRestartPackage"); |
| 766 | |
| 767 | hr = BundleGetBundleVariable(TEST_BUNDLE_ID, L"MyBurnVariable1", &sczValue); |
| 768 | TestThrowOnFailure(hr, L"Failed to read MyBurnVariable1."); |
| 769 | |
| 770 | NativeAssert::StringEqual(L"42", sczValue); |
| 771 | |
| 772 | // read interrupted resume type |
| 773 | hr = RegistrationDetectResumeType(®istration, &resumeType); |
| 774 | TestThrowOnFailure(hr, L"Failed to read interrupted resume type."); |
| 775 | |
| 776 | Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED, (int)resumeType); |
| 777 | |
| 778 | // suspend session |
| 779 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_SUSPEND, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 780 | TestThrowOnFailure(hr, L"Failed to suspend session."); |
| 781 | |
| 782 | // verify that run key was removed |
| 783 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, nullptr); |
| 784 | |
| 785 | // read suspend resume type |
| 786 | hr = RegistrationDetectResumeType(®istration, &resumeType); |
| 787 | TestThrowOnFailure(hr, L"Failed to read suspend resume type."); |
| 788 | |
| 789 | Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_SUSPEND, (int)resumeType); |
| 790 | |
| 791 | // read state back |
| 792 | hr = RegistrationLoadState(®istration, &pbBuffer, &cbBuffer); |
| 793 | TestThrowOnFailure(hr, L"Failed to load state."); |
| 794 | |
| 795 | hr = VariableDeserialize(&variables, TRUE, pbBuffer, cbBuffer, &piBuffer); |
| 796 | TestThrowOnFailure(hr, L"Failed to deserialize variables."); |
| 797 | |
| 798 | // write active resume mode |
| 799 | hr = RegistrationSessionBegin(sczCurrentProcess, ®istration, &cache, &variables, dwRegistrationOptions, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS); |
| 800 | TestThrowOnFailure(hr, L"Failed to write active resume mode."); |
| 801 | |
| 802 | // verify that run key was put back |
| 803 | this->ValidateRunOnceKeyEntry(cacheExePath); |
| 804 | |
| 805 | // end session |
| 806 | hr = RegistrationSessionEnd(®istration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, qwEstimatedSize, BOOTSTRAPPER_REGISTRATION_TYPE_NONE); |
| 807 | TestThrowOnFailure(hr, L"Failed to unregister bundle."); |
| 808 | |
| 809 | // read resume type after session |
| 810 | hr = RegistrationDetectResumeType(®istration, &resumeType); |
| 811 | TestThrowOnFailure(hr, L"Failed to read resume type."); |
| 812 | |
| 813 | Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_NONE, (int)resumeType); |
| 814 | } |
| 815 | finally |
| 816 | { |
| 817 | ReleaseStr(sczCurrentProcess); |
| 818 | ReleaseObject(pixeBundle); |
| 819 | BootstrapperApplicationUninitialize(&userExperience); |
| 820 | RegistrationUninitialize(®istration); |
| 821 | VariablesUninitialize(&variables); |
| 822 | |
| 823 | if (Directory::Exists(cacheDirectory)) |
| 824 | { |
| 825 | Directory::Delete(cacheDirectory, true); |
| 826 | } |
| 827 | |
| 828 | this->testRegistry->TearDown(); |
| 829 | } |
| 830 | } |
| 831 | |
| 832 | void ValidateRunOnceKeyString(LPCWSTR valueName, String^ expected) |
| 833 | { |
| 834 | WixAssert::StringEqual(expected, (String^)Registry::GetValue(this->testRunKeyPath, gcnew String(valueName), nullptr), false); |
| 835 | } |
| 836 | |
| 837 | void ValidateRunOnceKeyEntry(String^ exePath) |
| 838 | { |
| 839 | this->ValidateRunOnceKeyString(TEST_BUNDLE_ID, String::Concat(L"\"", exePath, L"\" /burn.runonce")); |
| 840 | } |
| 841 | |
| 842 | void ValidateUninstallKeyNull(LPCWSTR valueName) |
| 843 | { |
| 844 | Assert::Null(Registry::GetValue(this->testUninstallKeyPath, gcnew String(valueName), nullptr)); |
| 845 | } |
| 846 | |
| 847 | void ValidateUninstallKeyNumber(LPCWSTR valueName, Int32 expected) |
| 848 | { |
| 849 | Assert::Equal(expected, (Int32)Registry::GetValue(this->testUninstallKeyPath, gcnew String(valueName), nullptr)); |
| 850 | } |
| 851 | |
| 852 | void ValidateUninstallKeyString(LPCWSTR valueName, String^ expected) |
| 853 | { |
| 854 | WixAssert::StringEqual(expected, (String^)Registry::GetValue(this->testUninstallKeyPath, gcnew String(valueName), nullptr), false); |
| 855 | } |
| 856 | |
| 857 | void ValidateUninstallKeyDisplayName(String^ expected) |
| 858 | { |
| 859 | this->ValidateUninstallKeyString(L"DisplayName", expected); |
| 860 | } |
| 861 | |
| 862 | void ValidateUninstallKeyInstalled(Int32 expected) |
| 863 | { |
| 864 | this->ValidateUninstallKeyNumber(L"Installed", expected); |
| 865 | } |
| 866 | |
| 867 | void ValidateUninstallKeyResume(Int32 expected) |
| 868 | { |
| 869 | this->ValidateUninstallKeyNumber(L"Resume", expected); |
| 870 | } |
| 871 | |
| 872 | void ValidateVariableKey(LPCWSTR valueName, String^ expected) |
| 873 | { |
| 874 | WixAssert::StringEqual(expected, (String^)Registry::GetValue(this->testVariableKeyPath, gcnew String(valueName), nullptr), false); |
| 875 | } |
| 876 | |
| 877 | void ValidateVariableKeyEmpty(LPCWSTR valueName) |
| 878 | { |
| 879 | Assert::Empty((System::Collections::IEnumerable^)Registry::GetValue(this->testVariableKeyPath, gcnew String(valueName), nullptr)); |
| 880 | } |
| 881 | }; |
| 882 | } |
| 883 | } |
| 884 | } |
| 885 | } |
| 886 | } |