diff options
Diffstat (limited to 'src/burn/engine/bundlepackageengine.cpp')
| -rw-r--r-- | src/burn/engine/bundlepackageengine.cpp | 277 |
1 files changed, 254 insertions, 23 deletions
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp index f3badfc1..ef08d417 100644 --- a/src/burn/engine/bundlepackageengine.cpp +++ b/src/burn/engine/bundlepackageengine.cpp | |||
| @@ -2,6 +2,18 @@ | |||
| 2 | 2 | ||
| 3 | #include "precomp.h" | 3 | #include "precomp.h" |
| 4 | 4 | ||
| 5 | typedef struct _BUNDLE_QUERY_CONTEXT | ||
| 6 | { | ||
| 7 | BURN_PACKAGE* pPackage; | ||
| 8 | BURN_USER_EXPERIENCE* pUserExperience; | ||
| 9 | BOOL fSelfFound; | ||
| 10 | BOOL fNewerFound; | ||
| 11 | } BUNDLE_QUERY_CONTEXT; | ||
| 12 | |||
| 13 | static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback( | ||
| 14 | __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, | ||
| 15 | __in_opt LPVOID pvContext | ||
| 16 | ); | ||
| 5 | static HRESULT ExecuteBundle( | 17 | static HRESULT ExecuteBundle( |
| 6 | __in BURN_CACHE* pCache, | 18 | __in BURN_CACHE* pCache, |
| 7 | __in BURN_VARIABLES* pVariables, | 19 | __in BURN_VARIABLES* pVariables, |
| @@ -35,6 +47,18 @@ extern "C" HRESULT BundlePackageEngineParsePackageFromXml( | |||
| 35 | hr = XmlGetAttributeEx(pixnBundlePackage, L"BundleId", &pPackage->Bundle.sczBundleId); | 47 | hr = XmlGetAttributeEx(pixnBundlePackage, L"BundleId", &pPackage->Bundle.sczBundleId); |
| 36 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @BundleId."); | 48 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @BundleId."); |
| 37 | 49 | ||
| 50 | // @Version | ||
| 51 | hr = XmlGetAttributeEx(pixnBundlePackage, L"Version", &scz); | ||
| 52 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Version."); | ||
| 53 | |||
| 54 | hr = VerParseVersion(scz, 0, FALSE, &pPackage->Bundle.pVersion); | ||
| 55 | ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); | ||
| 56 | |||
| 57 | if (pPackage->Bundle.pVersion->fInvalid) | ||
| 58 | { | ||
| 59 | LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz); | ||
| 60 | } | ||
| 61 | |||
| 38 | // @InstallArguments | 62 | // @InstallArguments |
| 39 | hr = XmlGetAttributeEx(pixnBundlePackage, L"InstallArguments", &pPackage->Bundle.sczInstallArguments); | 63 | hr = XmlGetAttributeEx(pixnBundlePackage, L"InstallArguments", &pPackage->Bundle.sczInstallArguments); |
| 40 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArguments."); | 64 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArguments."); |
| @@ -55,6 +79,9 @@ extern "C" HRESULT BundlePackageEngineParsePackageFromXml( | |||
| 55 | hr = XmlGetYesNoAttribute(pixnBundlePackage, L"Win64", &pPackage->Bundle.fWin64); | 79 | hr = XmlGetYesNoAttribute(pixnBundlePackage, L"Win64", &pPackage->Bundle.fWin64); |
| 56 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Win64."); | 80 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Win64."); |
| 57 | 81 | ||
| 82 | hr = BundlePackageEngineParseRelatedCodes(pixnBundlePackage, &pPackage->Bundle.rgsczDetectCodes, &pPackage->Bundle.cDetectCodes, &pPackage->Bundle.rgsczUpgradeCodes, &pPackage->Bundle.cUpgradeCodes, &pPackage->Bundle.rgsczAddonCodes, &pPackage->Bundle.cAddonCodes, &pPackage->Bundle.rgsczPatchCodes, &pPackage->Bundle.cPatchCodes); | ||
| 83 | ExitOnFailure(hr, "Failed to parse related codes."); | ||
| 84 | |||
| 58 | hr = ExeEngineParseExitCodesFromXml(pixnBundlePackage, &pPackage->Bundle.rgExitCodes, &pPackage->Bundle.cExitCodes); | 85 | hr = ExeEngineParseExitCodesFromXml(pixnBundlePackage, &pPackage->Bundle.rgExitCodes, &pPackage->Bundle.cExitCodes); |
| 59 | ExitOnFailure(hr, "Failed to parse exit codes."); | 86 | ExitOnFailure(hr, "Failed to parse exit codes."); |
| 60 | 87 | ||
| @@ -70,11 +97,101 @@ LExit: | |||
| 70 | return hr; | 97 | return hr; |
| 71 | } | 98 | } |
| 72 | 99 | ||
| 100 | |||
| 101 | extern "C" HRESULT BundlePackageEngineParseRelatedCodes( | ||
| 102 | __in IXMLDOMNode* pixnBundle, | ||
| 103 | __in LPWSTR** prgsczDetectCodes, | ||
| 104 | __in DWORD* pcDetectCodes, | ||
| 105 | __in LPWSTR** prgsczUpgradeCodes, | ||
| 106 | __in DWORD* pcUpgradeCodes, | ||
| 107 | __in LPWSTR** prgsczAddonCodes, | ||
| 108 | __in DWORD* pcAddonCodes, | ||
| 109 | __in LPWSTR** prgsczPatchCodes, | ||
| 110 | __in DWORD* pcPatchCodes | ||
| 111 | ) | ||
| 112 | { | ||
| 113 | HRESULT hr = S_OK; | ||
| 114 | IXMLDOMNodeList* pixnNodes = NULL; | ||
| 115 | IXMLDOMNode* pixnElement = NULL; | ||
| 116 | LPWSTR sczAction = NULL; | ||
| 117 | LPWSTR sczId = NULL; | ||
| 118 | DWORD cElements = 0; | ||
| 119 | |||
| 120 | hr = XmlSelectNodes(pixnBundle, L"RelatedBundle", &pixnNodes); | ||
| 121 | ExitOnFailure(hr, "Failed to get RelatedBundle nodes"); | ||
| 122 | |||
| 123 | hr = pixnNodes->get_length((long*)&cElements); | ||
| 124 | ExitOnFailure(hr, "Failed to get RelatedBundle element count."); | ||
| 125 | |||
| 126 | for (DWORD i = 0; i < cElements; ++i) | ||
| 127 | { | ||
| 128 | hr = XmlNextElement(pixnNodes, &pixnElement, NULL); | ||
| 129 | ExitOnFailure(hr, "Failed to get next RelatedBundle element."); | ||
| 130 | |||
| 131 | hr = XmlGetAttributeEx(pixnElement, L"Action", &sczAction); | ||
| 132 | ExitOnFailure(hr, "Failed to get @Action."); | ||
| 133 | |||
| 134 | hr = XmlGetAttributeEx(pixnElement, L"Id", &sczId); | ||
| 135 | ExitOnFailure(hr, "Failed to get @Id."); | ||
| 136 | |||
| 137 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Detect", -1)) | ||
| 138 | { | ||
| 139 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczDetectCodes), *pcDetectCodes, 1, sizeof(LPWSTR), 5); | ||
| 140 | ExitOnFailure(hr, "Failed to resize Detect code array"); | ||
| 141 | |||
| 142 | *prgsczDetectCodes[*pcDetectCodes] = sczId; | ||
| 143 | sczId = NULL; | ||
| 144 | *pcDetectCodes += 1; | ||
| 145 | } | ||
| 146 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Upgrade", -1)) | ||
| 147 | { | ||
| 148 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczUpgradeCodes), *pcUpgradeCodes, 1, sizeof(LPWSTR), 5); | ||
| 149 | ExitOnFailure(hr, "Failed to resize Upgrade code array"); | ||
| 150 | |||
| 151 | *prgsczUpgradeCodes[*pcUpgradeCodes] = sczId; | ||
| 152 | sczId = NULL; | ||
| 153 | *pcUpgradeCodes += 1; | ||
| 154 | } | ||
| 155 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Addon", -1)) | ||
| 156 | { | ||
| 157 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczAddonCodes), *pcAddonCodes, 1, sizeof(LPWSTR), 5); | ||
| 158 | ExitOnFailure(hr, "Failed to resize Addon code array"); | ||
| 159 | |||
| 160 | *prgsczAddonCodes[*pcAddonCodes] = sczId; | ||
| 161 | sczId = NULL; | ||
| 162 | *pcAddonCodes += 1; | ||
| 163 | } | ||
| 164 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Patch", -1)) | ||
| 165 | { | ||
| 166 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczPatchCodes), *pcPatchCodes, 1, sizeof(LPWSTR), 5); | ||
| 167 | ExitOnFailure(hr, "Failed to resize Patch code array"); | ||
| 168 | |||
| 169 | *prgsczPatchCodes[*pcPatchCodes] = sczId; | ||
| 170 | sczId = NULL; | ||
| 171 | *pcPatchCodes += 1; | ||
| 172 | } | ||
| 173 | else | ||
| 174 | { | ||
| 175 | hr = E_INVALIDARG; | ||
| 176 | ExitOnFailure(hr, "Invalid value for @Action: %ls", sczAction); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | LExit: | ||
| 181 | ReleaseObject(pixnNodes); | ||
| 182 | ReleaseObject(pixnElement); | ||
| 183 | ReleaseStr(sczAction); | ||
| 184 | ReleaseStr(sczId); | ||
| 185 | |||
| 186 | return hr; | ||
| 187 | } | ||
| 188 | |||
| 73 | extern "C" void BundlePackageEnginePackageUninitialize( | 189 | extern "C" void BundlePackageEnginePackageUninitialize( |
| 74 | __in BURN_PACKAGE* pPackage | 190 | __in BURN_PACKAGE* pPackage |
| 75 | ) | 191 | ) |
| 76 | { | 192 | { |
| 77 | ReleaseStr(pPackage->Bundle.sczBundleId); | 193 | ReleaseStr(pPackage->Bundle.sczBundleId); |
| 194 | ReleaseVerutilVersion(pPackage->Bundle.pVersion); | ||
| 78 | ReleaseStr(pPackage->Bundle.sczRegistrationKey); | 195 | ReleaseStr(pPackage->Bundle.sczRegistrationKey); |
| 79 | ReleaseStr(pPackage->Bundle.sczInstallArguments); | 196 | ReleaseStr(pPackage->Bundle.sczInstallArguments); |
| 80 | ReleaseStr(pPackage->Bundle.sczRepairArguments); | 197 | ReleaseStr(pPackage->Bundle.sczRepairArguments); |
| @@ -92,45 +209,95 @@ extern "C" void BundlePackageEnginePackageUninitialize( | |||
| 92 | MemFree(pPackage->Bundle.rgCommandLineArguments); | 209 | MemFree(pPackage->Bundle.rgCommandLineArguments); |
| 93 | } | 210 | } |
| 94 | 211 | ||
| 212 | for (DWORD i = 0; i < pPackage->Bundle.cDetectCodes; ++i) | ||
| 213 | { | ||
| 214 | ReleaseStr(pPackage->Bundle.rgsczDetectCodes[i]); | ||
| 215 | } | ||
| 216 | ReleaseMem(pPackage->Bundle.rgsczDetectCodes); | ||
| 217 | |||
| 218 | for (DWORD i = 0; i < pPackage->Bundle.cUpgradeCodes; ++i) | ||
| 219 | { | ||
| 220 | ReleaseStr(pPackage->Bundle.rgsczUpgradeCodes[i]); | ||
| 221 | } | ||
| 222 | ReleaseMem(pPackage->Bundle.rgsczUpgradeCodes); | ||
| 223 | |||
| 224 | for (DWORD i = 0; i < pPackage->Bundle.cAddonCodes; ++i) | ||
| 225 | { | ||
| 226 | ReleaseStr(pPackage->Bundle.rgsczAddonCodes[i]); | ||
| 227 | } | ||
| 228 | ReleaseMem(pPackage->Bundle.rgsczAddonCodes); | ||
| 229 | |||
| 230 | for (DWORD i = 0; i < pPackage->Bundle.cPatchCodes; ++i) | ||
| 231 | { | ||
| 232 | ReleaseStr(pPackage->Bundle.rgsczPatchCodes[i]); | ||
| 233 | } | ||
| 234 | ReleaseMem(pPackage->Bundle.rgsczPatchCodes); | ||
| 235 | |||
| 95 | // clear struct | 236 | // clear struct |
| 96 | memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle)); | 237 | memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle)); |
| 97 | } | 238 | } |
| 98 | 239 | ||
| 99 | extern "C" HRESULT BundlePackageEngineDetectPackage( | 240 | extern "C" HRESULT BundlePackageEngineDetectPackage( |
| 100 | __in BURN_PACKAGE* pPackage | 241 | __in BURN_PACKAGE* pPackage, |
| 242 | __in BURN_REGISTRATION* /*pRegistration*/, | ||
| 243 | __in BURN_USER_EXPERIENCE* pUserExperience | ||
| 101 | ) | 244 | ) |
| 102 | { | 245 | { |
| 103 | HRESULT hr = S_OK; | 246 | HRESULT hr = S_OK; |
| 104 | HKEY hkRegistration = NULL; | 247 | BUNDLE_QUERY_CONTEXT queryContext = { }; |
| 105 | DWORD dwInstalled = 0; | 248 | |
| 106 | BOOL fDetected = FALSE; | 249 | queryContext.pPackage = pPackage; |
| 107 | HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | 250 | queryContext.pUserExperience = pUserExperience; |
| 108 | REG_KEY_BITNESS bitness = pPackage->Bundle.fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT; | 251 | |
| 109 | 252 | hr = BundleQueryRelatedBundles( | |
| 110 | // TODO: detect all related bundles, so that the Obsolete state can be detected. | 253 | BUNDLE_INSTALL_CONTEXT_MACHINE, |
| 111 | hr = RegOpenEx(hkRoot, pPackage->Bundle.sczRegistrationKey, KEY_QUERY_VALUE, bitness, &hkRegistration); | 254 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczDetectCodes), |
| 112 | if (SUCCEEDED(hr)) | 255 | pPackage->Bundle.cDetectCodes, |
| 256 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczUpgradeCodes), | ||
| 257 | pPackage->Bundle.cUpgradeCodes, | ||
| 258 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczAddonCodes), | ||
| 259 | pPackage->Bundle.cAddonCodes, | ||
| 260 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczPatchCodes), | ||
| 261 | pPackage->Bundle.cPatchCodes, | ||
| 262 | QueryRelatedBundlesCallback, | ||
| 263 | &queryContext); | ||
| 264 | ExitOnFailure(hr, "Failed to query per-machine related bundle packages."); | ||
| 265 | |||
| 266 | hr = BundleQueryRelatedBundles( | ||
| 267 | BUNDLE_INSTALL_CONTEXT_USER, | ||
| 268 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczDetectCodes), | ||
| 269 | pPackage->Bundle.cDetectCodes, | ||
| 270 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczUpgradeCodes), | ||
| 271 | pPackage->Bundle.cUpgradeCodes, | ||
| 272 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczAddonCodes), | ||
| 273 | pPackage->Bundle.cAddonCodes, | ||
| 274 | const_cast<LPCWSTR*>(pPackage->Bundle.rgsczPatchCodes), | ||
| 275 | pPackage->Bundle.cPatchCodes, | ||
| 276 | QueryRelatedBundlesCallback, | ||
| 277 | &queryContext); | ||
| 278 | ExitOnFailure(hr, "Failed to query per-user related bundle packages."); | ||
| 279 | |||
| 280 | if (queryContext.fNewerFound) | ||
| 113 | { | 281 | { |
| 114 | hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_INSTALLED, &dwInstalled); | 282 | pPackage->currentState = queryContext.fSelfFound ? BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED : BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE; |
| 115 | } | 283 | } |
| 116 | 284 | else | |
| 117 | // Not finding the key or value is okay. | ||
| 118 | if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr) | ||
| 119 | { | 285 | { |
| 120 | hr = S_OK; | 286 | pPackage->currentState = queryContext.fSelfFound ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; |
| 121 | } | 287 | } |
| 122 | 288 | ||
| 123 | fDetected = (1 == dwInstalled); | ||
| 124 | |||
| 125 | // update detect state | ||
| 126 | pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; | ||
| 127 | |||
| 128 | if (pPackage->fCanAffectRegistration) | 289 | if (pPackage->fCanAffectRegistration) |
| 129 | { | 290 | { |
| 130 | pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; | 291 | pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; |
| 131 | } | 292 | } |
| 132 | 293 | ||
| 133 | ReleaseRegKey(hkRegistration); | 294 | // TODO: The bundle is registering itself as a dependent when installed as a chain package, which prevents us from uninstalling it. |
| 295 | //hr = DependencyDetectChainPackage(pPackage, pRegistration); | ||
| 296 | //ExitOnFailure(hr, "Failed to detect dependencies for BUNDLE package."); | ||
| 297 | |||
| 298 | // TODO: uninstalling compatible Bundles like MsiEngine supports? | ||
| 299 | |||
| 300 | LExit: | ||
| 134 | return hr; | 301 | return hr; |
| 135 | } | 302 | } |
| 136 | 303 | ||
| @@ -148,7 +315,8 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
| 148 | // execute action | 315 | // execute action |
| 149 | switch (pPackage->currentState) | 316 | switch (pPackage->currentState) |
| 150 | { | 317 | { |
| 151 | case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: | 318 | case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: __fallthrough; |
| 319 | case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED: | ||
| 152 | switch (pPackage->requested) | 320 | switch (pPackage->requested) |
| 153 | { | 321 | { |
| 154 | case BOOTSTRAPPER_REQUEST_STATE_PRESENT: | 322 | case BOOTSTRAPPER_REQUEST_STATE_PRESENT: |
| @@ -173,6 +341,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
| 173 | } | 341 | } |
| 174 | break; | 342 | break; |
| 175 | 343 | ||
| 344 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough; | ||
| 176 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: | 345 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: |
| 177 | switch (pPackage->requested) | 346 | switch (pPackage->requested) |
| 178 | { | 347 | { |
| @@ -200,7 +369,8 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
| 200 | { | 369 | { |
| 201 | switch (pPackage->currentState) | 370 | switch (pPackage->currentState) |
| 202 | { | 371 | { |
| 203 | case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: | 372 | case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: __fallthrough; |
| 373 | case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED: | ||
| 204 | switch (pPackage->requested) | 374 | switch (pPackage->requested) |
| 205 | { | 375 | { |
| 206 | case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; | 376 | case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; |
| @@ -218,6 +388,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
| 218 | } | 388 | } |
| 219 | break; | 389 | break; |
| 220 | 390 | ||
| 391 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough; | ||
| 221 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: | 392 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: |
| 222 | switch (pPackage->requested) | 393 | switch (pPackage->requested) |
| 223 | { | 394 | { |
| @@ -481,6 +652,66 @@ LExit: | |||
| 481 | return; | 652 | return; |
| 482 | } | 653 | } |
| 483 | 654 | ||
| 655 | static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback( | ||
| 656 | __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, | ||
| 657 | __in_opt LPVOID pvContext | ||
| 658 | ) | ||
| 659 | { | ||
| 660 | HRESULT hr = S_OK; | ||
| 661 | BUNDLE_QUERY_CALLBACK_RESULT result = BUNDLE_QUERY_CALLBACK_RESULT_CONTINUE; | ||
| 662 | LPWSTR sczBundleVersion = NULL; | ||
| 663 | VERUTIL_VERSION* pVersion = NULL; | ||
| 664 | int nCompare = 0; | ||
| 665 | BUNDLE_QUERY_CONTEXT* pContext = reinterpret_cast<BUNDLE_QUERY_CONTEXT*>(pvContext); | ||
| 666 | BURN_PACKAGE* pPackage = pContext->pPackage; | ||
| 667 | BOOTSTRAPPER_RELATION_TYPE relationType = RelatedBundleConvertRelationType(pBundle->relationType); | ||
| 668 | BOOL fPerMachine = BUNDLE_INSTALL_CONTEXT_MACHINE == pBundle->installContext; | ||
| 669 | |||
| 670 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pBundle->wzBundleId, -1, pPackage->Bundle.sczBundleId, -1)) | ||
| 671 | { | ||
| 672 | Assert(BOOTSTRAPPER_RELATION_UPGRADE == relationType); | ||
| 673 | Assert(pPackage->Bundle.fWin64 == (REG_KEY_64BIT == pBundle->regBitness)); | ||
| 674 | |||
| 675 | pContext->fSelfFound = TRUE; | ||
| 676 | } | ||
| 677 | |||
| 678 | hr = RegReadString(pBundle->hkBundle, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, &sczBundleVersion); | ||
| 679 | ExitOnFailure(hr, "Failed to read version from registry for related bundle package: %ls", pBundle->wzBundleId); | ||
| 680 | |||
| 681 | hr = VerParseVersion(sczBundleVersion, 0, FALSE, &pVersion); | ||
| 682 | ExitOnFailure(hr, "Failed to parse related bundle package version: %ls", sczBundleVersion); | ||
| 683 | |||
| 684 | if (pVersion->fInvalid) | ||
| 685 | { | ||
| 686 | LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, pBundle->wzBundleId, sczBundleVersion); | ||
| 687 | } | ||
| 688 | |||
| 689 | if (BOOTSTRAPPER_RELATION_UPGRADE == relationType) | ||
| 690 | { | ||
| 691 | hr = VerCompareParsedVersions(pPackage->Bundle.pVersion, pVersion, &nCompare); | ||
| 692 | ExitOnFailure(hr, "Failed to compare related bundle package version: %ls", pVersion->sczVersion); | ||
| 693 | |||
| 694 | if (nCompare < 0) | ||
| 695 | { | ||
| 696 | pContext->fNewerFound = TRUE; | ||
| 697 | } | ||
| 698 | } | ||
| 699 | |||
| 700 | result = BUNDLE_QUERY_CALLBACK_RESULT_CANCEL; | ||
| 701 | |||
| 702 | // Pass to BA. | ||
| 703 | hr = UserExperienceOnDetectRelatedBundlePackage(pContext->pUserExperience, pPackage->sczId, pBundle->wzBundleId, relationType, fPerMachine, pVersion); | ||
| 704 | ExitOnRootFailure(hr, "BA aborted detect related BUNDLE package."); | ||
| 705 | |||
| 706 | result = BUNDLE_QUERY_CALLBACK_RESULT_CONTINUE; | ||
| 707 | |||
| 708 | LExit: | ||
| 709 | ReleaseVerutilVersion(pVersion); | ||
| 710 | ReleaseStr(sczBundleVersion); | ||
| 711 | |||
| 712 | return result; | ||
| 713 | } | ||
| 714 | |||
| 484 | static HRESULT ExecuteBundle( | 715 | static HRESULT ExecuteBundle( |
| 485 | __in BURN_CACHE* pCache, | 716 | __in BURN_CACHE* pCache, |
| 486 | __in BURN_VARIABLES* pVariables, | 717 | __in BURN_VARIABLES* pVariables, |
