diff options
Diffstat (limited to 'src/engine/dependency.cpp')
| -rw-r--r-- | src/engine/dependency.cpp | 349 |
1 files changed, 200 insertions, 149 deletions
diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp index af4ab0a1..1c33aaf2 100644 --- a/src/engine/dependency.cpp +++ b/src/engine/dependency.cpp | |||
| @@ -10,6 +10,12 @@ const LPCWSTR vcszIgnoreDependenciesDelim = L";"; | |||
| 10 | 10 | ||
| 11 | // internal function declarations | 11 | // internal function declarations |
| 12 | 12 | ||
| 13 | static HRESULT DetectPackageDependents( | ||
| 14 | __in BURN_PACKAGE* pPackage, | ||
| 15 | __in STRINGDICT_HANDLE sdIgnoredDependents, | ||
| 16 | __in const BURN_REGISTRATION* pRegistration | ||
| 17 | ); | ||
| 18 | |||
| 13 | static HRESULT SplitIgnoreDependencies( | 19 | static HRESULT SplitIgnoreDependencies( |
| 14 | __in_z LPCWSTR wzIgnoreDependencies, | 20 | __in_z LPCWSTR wzIgnoreDependencies, |
| 15 | __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, | 21 | __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, |
| @@ -28,11 +34,9 @@ static HRESULT GetIgnoredDependents( | |||
| 28 | __deref_inout STRINGDICT_HANDLE* psdIgnoredDependents | 34 | __deref_inout STRINGDICT_HANDLE* psdIgnoredDependents |
| 29 | ); | 35 | ); |
| 30 | 36 | ||
| 31 | static HRESULT GetProviderInformation( | 37 | static BOOL GetProviderExists( |
| 32 | __in HKEY hkRoot, | 38 | __in HKEY hkRoot, |
| 33 | __in_z LPCWSTR wzProviderKey, | 39 | __in_z LPCWSTR wzProviderKey |
| 34 | __deref_opt_out_z_opt LPWSTR* psczProviderKey, | ||
| 35 | __deref_opt_out_z_opt LPWSTR* psczId | ||
| 36 | ); | 40 | ); |
| 37 | 41 | ||
| 38 | static void CalculateDependencyActionStates( | 42 | static void CalculateDependencyActionStates( |
| @@ -70,20 +74,18 @@ static void UnregisterPackageDependency( | |||
| 70 | __in_z LPCWSTR wzDependentProviderKey | 74 | __in_z LPCWSTR wzDependentProviderKey |
| 71 | ); | 75 | ); |
| 72 | 76 | ||
| 73 | static BOOL PackageProviderExists( | ||
| 74 | __in const BURN_PACKAGE* pPackage | ||
| 75 | ); | ||
| 76 | |||
| 77 | 77 | ||
| 78 | // functions | 78 | // functions |
| 79 | 79 | ||
| 80 | extern "C" void DependencyUninitialize( | 80 | extern "C" void DependencyUninitializeProvider( |
| 81 | __in BURN_DEPENDENCY_PROVIDER* pProvider | 81 | __in BURN_DEPENDENCY_PROVIDER* pProvider |
| 82 | ) | 82 | ) |
| 83 | { | 83 | { |
| 84 | ReleaseStr(pProvider->sczKey); | 84 | ReleaseStr(pProvider->sczKey); |
| 85 | ReleaseStr(pProvider->sczVersion); | 85 | ReleaseStr(pProvider->sczVersion); |
| 86 | ReleaseStr(pProvider->sczDisplayName); | 86 | ReleaseStr(pProvider->sczDisplayName); |
| 87 | ReleaseDependencyArray(pProvider->rgDependents, pProvider->cDependents); | ||
| 88 | |||
| 87 | memset(pProvider, 0, sizeof(BURN_DEPENDENCY_PROVIDER)); | 89 | memset(pProvider, 0, sizeof(BURN_DEPENDENCY_PROVIDER)); |
| 88 | } | 90 | } |
| 89 | 91 | ||
| @@ -167,45 +169,33 @@ LExit: | |||
| 167 | return hr; | 169 | return hr; |
| 168 | } | 170 | } |
| 169 | 171 | ||
| 170 | extern "C" HRESULT DependencyDetectProviderKeyPackageId( | 172 | extern "C" HRESULT DependencyInitialize( |
| 171 | __in const BURN_PACKAGE* pPackage, | 173 | __in BURN_REGISTRATION* pRegistration, |
| 172 | __deref_opt_out_z_opt LPWSTR* psczProviderKey, | 174 | __in_z_opt LPCWSTR wzIgnoreDependencies |
| 173 | __deref_opt_out_z_opt LPWSTR* psczId | ||
| 174 | ) | 175 | ) |
| 175 | { | 176 | { |
| 176 | HRESULT hr = E_NOTFOUND; | 177 | HRESULT hr = S_OK; |
| 177 | LPWSTR wzProviderKey = NULL; | ||
| 178 | HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | ||
| 179 | 178 | ||
| 180 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) | 179 | // If no parent was specified at all, use the bundle id as the self dependent. |
| 180 | if (!pRegistration->sczActiveParent) | ||
| 181 | { | 181 | { |
| 182 | const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; | 182 | pRegistration->wzSelfDependent = pRegistration->sczId; |
| 183 | |||
| 184 | // Find the first package id registered for the provider key. | ||
| 185 | hr = GetProviderInformation(hkRoot, pProvider->sczKey, psczProviderKey, psczId); | ||
| 186 | if (E_NOTFOUND == hr) | ||
| 187 | { | ||
| 188 | continue; | ||
| 189 | } | ||
| 190 | ExitOnFailure(hr, "Failed to get the package provider information."); | ||
| 191 | |||
| 192 | ExitFunction(); | ||
| 193 | } | 183 | } |
| 194 | 184 | else if (*pRegistration->sczActiveParent) // if parent was specified use that as the self dependent. | |
| 195 | // Older bundles may not have written the id so try the default. | ||
| 196 | if (BURN_PACKAGE_TYPE_MSI == pPackage->type) | ||
| 197 | { | 185 | { |
| 198 | wzProviderKey = pPackage->Msi.sczProductCode; | 186 | pRegistration->wzSelfDependent = pRegistration->sczActiveParent; |
| 199 | } | 187 | } |
| 188 | // else parent:none was used which means we should not register a dependency on ourself. | ||
| 189 | |||
| 190 | // The current bundle provider key should always be ignored for dependency checks. | ||
| 191 | hr = DepDependencyArrayAlloc(&pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, pRegistration->sczProviderKey, NULL); | ||
| 192 | ExitOnFailure(hr, "Failed to add the bundle provider key to the list of dependencies to ignore."); | ||
| 200 | 193 | ||
| 201 | if (wzProviderKey) | 194 | // Add the list of dependencies to ignore. |
| 195 | if (wzIgnoreDependencies) | ||
| 202 | { | 196 | { |
| 203 | hr = GetProviderInformation(hkRoot, wzProviderKey, psczProviderKey, psczId); | 197 | hr = SplitIgnoreDependencies(wzIgnoreDependencies, &pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies); |
| 204 | if (E_NOTFOUND == hr) | 198 | ExitOnFailure(hr, "Failed to split the list of dependencies to ignore."); |
| 205 | { | ||
| 206 | ExitFunction(); | ||
| 207 | } | ||
| 208 | ExitOnFailure(hr, "Failed to get the package default provider information."); | ||
| 209 | } | 199 | } |
| 210 | 200 | ||
| 211 | LExit: | 201 | LExit: |
| @@ -236,23 +226,77 @@ LExit: | |||
| 236 | return hr; | 226 | return hr; |
| 237 | } | 227 | } |
| 238 | 228 | ||
| 229 | extern "C" HRESULT DependencyDetect( | ||
| 230 | __in BURN_ENGINE_STATE* pEngineState | ||
| 231 | ) | ||
| 232 | { | ||
| 233 | HRESULT hr = S_OK; | ||
| 234 | BURN_REGISTRATION* pRegistration = &pEngineState->registration; | ||
| 235 | STRINGDICT_HANDLE sdIgnoredDependents = NULL; | ||
| 236 | BURN_PACKAGE* pPackage = NULL; | ||
| 237 | |||
| 238 | // Always leave this empty so that all dependents get detected. Plan will ignore dependents based on its own logic. | ||
| 239 | hr = DictCreateStringList(&sdIgnoredDependents, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE); | ||
| 240 | ExitOnFailure(hr, "Failed to create the string dictionary."); | ||
| 241 | |||
| 242 | hr = DepCheckDependents(pRegistration->hkRoot, pRegistration->sczProviderKey, 0, sdIgnoredDependents, &pRegistration->rgDependents, &pRegistration->cDependents); | ||
| 243 | if (E_FILENOTFOUND != hr) | ||
| 244 | { | ||
| 245 | ExitOnFailure(hr, "Failed dependents check on bundle"); | ||
| 246 | } | ||
| 247 | else | ||
| 248 | { | ||
| 249 | hr = S_OK; | ||
| 250 | } | ||
| 251 | |||
| 252 | for (DWORD iPackage = 0; iPackage < pEngineState->packages.cPackages; ++iPackage) | ||
| 253 | { | ||
| 254 | pPackage = pEngineState->packages.rgPackages + iPackage; | ||
| 255 | hr = DetectPackageDependents(pPackage, sdIgnoredDependents, pRegistration); | ||
| 256 | ExitOnFailure(hr, "Failed to detect dependents for package '%ls'", pPackage->sczId); | ||
| 257 | } | ||
| 258 | |||
| 259 | for (DWORD iRelatedBundle = 0; iRelatedBundle < pEngineState->registration.relatedBundles.cRelatedBundles; ++iRelatedBundle) | ||
| 260 | { | ||
| 261 | pPackage = &pEngineState->registration.relatedBundles.rgRelatedBundles[iRelatedBundle].package; | ||
| 262 | hr = DetectPackageDependents(pPackage, sdIgnoredDependents, pRegistration); | ||
| 263 | ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (pRegistration->wzSelfDependent) | ||
| 267 | { | ||
| 268 | for (DWORD i = 0; i < pRegistration->cDependents; ++i) | ||
| 269 | { | ||
| 270 | DEPENDENCY* pDependent = pRegistration->rgDependents + i; | ||
| 271 | |||
| 272 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->wzSelfDependent, -1, pDependent->sczKey, -1)) | ||
| 273 | { | ||
| 274 | pRegistration->fSelfRegisteredAsDependent = TRUE; | ||
| 275 | break; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | LExit: | ||
| 281 | ReleaseDict(sdIgnoredDependents); | ||
| 282 | |||
| 283 | return hr; | ||
| 284 | } | ||
| 285 | |||
| 239 | extern "C" HRESULT DependencyPlanInitialize( | 286 | extern "C" HRESULT DependencyPlanInitialize( |
| 240 | __in const BURN_ENGINE_STATE* pEngineState, | 287 | __in const BURN_REGISTRATION* pRegistration, |
| 241 | __in BURN_PLAN* pPlan | 288 | __in BURN_PLAN* pPlan |
| 242 | ) | 289 | ) |
| 243 | { | 290 | { |
| 244 | HRESULT hr = S_OK; | 291 | HRESULT hr = S_OK; |
| 245 | 292 | ||
| 246 | // The current bundle provider key should always be ignored for dependency checks. | 293 | // TODO: After adding enumeration to STRINGDICT, a single STRINGDICT_HANDLE can be used everywhere. |
| 247 | hr = DepDependencyArrayAlloc(&pPlan->rgPlannedProviders, &pPlan->cPlannedProviders, pEngineState->registration.sczProviderKey, NULL); | 294 | for (DWORD i = 0; i < pRegistration->cIgnoredDependencies; ++i) |
| 248 | ExitOnFailure(hr, "Failed to add the bundle provider key to the list of dependencies to ignore."); | ||
| 249 | |||
| 250 | // Add the list of dependencies to ignore to the plan. | ||
| 251 | if (pEngineState->sczIgnoreDependencies) | ||
| 252 | { | 295 | { |
| 253 | // TODO: After adding enumeration to STRINGDICT, a single STRINGDICT_HANDLE can be used everywhere. | 296 | DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + i; |
| 254 | hr = SplitIgnoreDependencies(pEngineState->sczIgnoreDependencies, &pPlan->rgPlannedProviders, &pPlan->cPlannedProviders); | 297 | |
| 255 | ExitOnFailure(hr, "Failed to split the list of dependencies to ignore."); | 298 | hr = DepDependencyArrayAlloc(&pPlan->rgPlannedProviders, &pPlan->cPlannedProviders, pDependency->sczKey, pDependency->sczName); |
| 299 | ExitOnFailure(hr, "Failed to add the detected provider to the list of dependencies to ignore."); | ||
| 256 | } | 300 | } |
| 257 | 301 | ||
| 258 | LExit: | 302 | LExit: |
| @@ -323,9 +367,6 @@ extern "C" HRESULT DependencyPlanPackageBegin( | |||
| 323 | { | 367 | { |
| 324 | HRESULT hr = S_OK; | 368 | HRESULT hr = S_OK; |
| 325 | STRINGDICT_HANDLE sdIgnoredDependents = NULL; | 369 | STRINGDICT_HANDLE sdIgnoredDependents = NULL; |
| 326 | DEPENDENCY* rgDependents = NULL; | ||
| 327 | UINT cDependents = 0; | ||
| 328 | HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | ||
| 329 | BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE; | 370 | BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE; |
| 330 | BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE; | 371 | BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE; |
| 331 | 372 | ||
| @@ -361,18 +402,31 @@ extern "C" HRESULT DependencyPlanPackageBegin( | |||
| 361 | } | 402 | } |
| 362 | else | 403 | else |
| 363 | { | 404 | { |
| 405 | hr = S_OK; | ||
| 406 | |||
| 364 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) | 407 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) |
| 365 | { | 408 | { |
| 366 | const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; | 409 | const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders + i; |
| 367 | 410 | ||
| 368 | hr = DepCheckDependents(hkHive, pProvider->sczKey, 0, sdIgnoredDependents, &rgDependents, &cDependents); | 411 | for (DWORD j = 0; j < pProvider->cDependents; ++j) |
| 369 | if (E_FILENOTFOUND != hr) | ||
| 370 | { | ||
| 371 | ExitOnFailure(hr, "Failed dependents check on package provider: %ls", pProvider->sczKey); | ||
| 372 | } | ||
| 373 | else | ||
| 374 | { | 412 | { |
| 375 | hr = S_OK; | 413 | const DEPENDENCY* pDependency = pProvider->rgDependents + j; |
| 414 | |||
| 415 | hr = DictKeyExists(sdIgnoredDependents, pDependency->sczKey); | ||
| 416 | if (E_NOTFOUND == hr) | ||
| 417 | { | ||
| 418 | hr = S_OK; | ||
| 419 | |||
| 420 | if (!pPackage->fDependencyManagerWasHere) | ||
| 421 | { | ||
| 422 | pPackage->fDependencyManagerWasHere = TRUE; | ||
| 423 | |||
| 424 | LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_HASDEPENDENTS, pPackage->sczId); | ||
| 425 | } | ||
| 426 | |||
| 427 | LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_DEPENDENT, pDependency->sczKey, LoggingStringOrUnknownIfNull(pDependency->sczName)); | ||
| 428 | } | ||
| 429 | ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents."); | ||
| 376 | } | 430 | } |
| 377 | } | 431 | } |
| 378 | } | 432 | } |
| @@ -382,52 +436,46 @@ extern "C" HRESULT DependencyPlanPackageBegin( | |||
| 382 | CalculateDependencyActionStates(pPackage, pPlan->action, &dependencyExecuteAction, &dependencyRollbackAction); | 436 | CalculateDependencyActionStates(pPackage, pPlan->action, &dependencyExecuteAction, &dependencyRollbackAction); |
| 383 | 437 | ||
| 384 | // If dependents were found, change the action to not uninstall the package. | 438 | // If dependents were found, change the action to not uninstall the package. |
| 385 | if (0 < cDependents) | 439 | if (pPackage->fDependencyManagerWasHere) |
| 386 | { | 440 | { |
| 387 | LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_HASDEPENDENTS, pPackage->sczId, cDependents); | ||
| 388 | |||
| 389 | for (DWORD i = 0; i < cDependents; ++i) | ||
| 390 | { | ||
| 391 | const DEPENDENCY* pDependency = &rgDependents[i]; | ||
| 392 | LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_DEPENDENT, pDependency->sczKey, LoggingStringOrUnknownIfNull(pDependency->sczName)); | ||
| 393 | } | ||
| 394 | |||
| 395 | pPackage->fDependencyManagerWasHere = TRUE; | ||
| 396 | pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; | 441 | pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; |
| 397 | pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; | 442 | pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; |
| 398 | } | 443 | } |
| 399 | // Use the calculated dependency actions as the provider actions if there | 444 | else |
| 400 | // are any non-imported providers that need to be registered and the package | ||
| 401 | // is current (not obsolete). | ||
| 402 | else if (BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE != pPackage->currentState) | ||
| 403 | { | 445 | { |
| 404 | BOOL fAllImportedProviders = TRUE; // assume all providers were imported. | 446 | // Use the calculated dependency actions as the provider actions if there |
| 405 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) | 447 | // are any non-imported providers that need to be registered and the package |
| 448 | // is current (not obsolete). | ||
| 449 | if (BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE != pPackage->currentState) | ||
| 406 | { | 450 | { |
| 407 | const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; | 451 | BOOL fAllImportedProviders = TRUE; // assume all providers were imported. |
| 408 | if (!pProvider->fImported) | 452 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) |
| 409 | { | 453 | { |
| 410 | fAllImportedProviders = FALSE; | 454 | const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; |
| 411 | break; | 455 | if (!pProvider->fImported) |
| 456 | { | ||
| 457 | fAllImportedProviders = FALSE; | ||
| 458 | break; | ||
| 459 | } | ||
| 412 | } | 460 | } |
| 413 | } | ||
| 414 | 461 | ||
| 415 | if (!fAllImportedProviders) | 462 | if (!fAllImportedProviders) |
| 416 | { | 463 | { |
| 417 | pPackage->providerExecute = dependencyExecuteAction; | 464 | pPackage->providerExecute = dependencyExecuteAction; |
| 418 | pPackage->providerRollback = dependencyRollbackAction; | 465 | pPackage->providerRollback = dependencyRollbackAction; |
| 466 | } | ||
| 419 | } | 467 | } |
| 420 | } | ||
| 421 | 468 | ||
| 422 | // If the package will be removed, add its providers to the growing list in the plan. | 469 | // If the package will be removed, add its providers to the growing list in the plan. |
| 423 | if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) | 470 | if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) |
| 424 | { | ||
| 425 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) | ||
| 426 | { | 471 | { |
| 427 | const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; | 472 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) |
| 473 | { | ||
| 474 | const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; | ||
| 428 | 475 | ||
| 429 | hr = DepDependencyArrayAlloc(&pPlan->rgPlannedProviders, &pPlan->cPlannedProviders, pProvider->sczKey, NULL); | 476 | hr = DepDependencyArrayAlloc(&pPlan->rgPlannedProviders, &pPlan->cPlannedProviders, pProvider->sczKey, NULL); |
| 430 | ExitOnFailure(hr, "Failed to add the package provider key \"%ls\" to the planned list.", pProvider->sczKey); | 477 | ExitOnFailure(hr, "Failed to add the package provider key \"%ls\" to the planned list.", pProvider->sczKey); |
| 478 | } | ||
| 431 | } | 479 | } |
| 432 | } | 480 | } |
| 433 | 481 | ||
| @@ -435,7 +483,6 @@ extern "C" HRESULT DependencyPlanPackageBegin( | |||
| 435 | pPackage->dependencyRollback = dependencyRollbackAction; | 483 | pPackage->dependencyRollback = dependencyRollbackAction; |
| 436 | 484 | ||
| 437 | LExit: | 485 | LExit: |
| 438 | ReleaseDependencyArray(rgDependents, cDependents); | ||
| 439 | ReleaseDict(sdIgnoredDependents); | 486 | ReleaseDict(sdIgnoredDependents); |
| 440 | 487 | ||
| 441 | return hr; | 488 | return hr; |
| @@ -652,6 +699,58 @@ extern "C" void DependencyUnregisterBundle( | |||
| 652 | 699 | ||
| 653 | // internal functions | 700 | // internal functions |
| 654 | 701 | ||
| 702 | |||
| 703 | static HRESULT DetectPackageDependents( | ||
| 704 | __in BURN_PACKAGE* pPackage, | ||
| 705 | __in STRINGDICT_HANDLE sdIgnoredDependents, | ||
| 706 | __in const BURN_REGISTRATION* pRegistration | ||
| 707 | ) | ||
| 708 | { | ||
| 709 | HRESULT hr = S_OK; | ||
| 710 | HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | ||
| 711 | |||
| 712 | // There's currently no point in getting the dependents if the scope doesn't match, | ||
| 713 | // because they will just get ignored. | ||
| 714 | if (pRegistration->fPerMachine != pPackage->fPerMachine) | ||
| 715 | { | ||
| 716 | ExitFunction(); | ||
| 717 | } | ||
| 718 | |||
| 719 | for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) | ||
| 720 | { | ||
| 721 | BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; | ||
| 722 | |||
| 723 | hr = DepCheckDependents(hkHive, pProvider->sczKey, 0, sdIgnoredDependents, &pProvider->rgDependents, &pProvider->cDependents); | ||
| 724 | if (E_FILENOTFOUND != hr) | ||
| 725 | { | ||
| 726 | ExitOnFailure(hr, "Failed dependents check on package provider: %ls", pProvider->sczKey); | ||
| 727 | |||
| 728 | if (!pPackage->fPackageProviderExists && (0 < pProvider->cDependents || GetProviderExists(hkHive, pProvider->sczKey))) | ||
| 729 | { | ||
| 730 | pPackage->fPackageProviderExists = TRUE; | ||
| 731 | } | ||
| 732 | } | ||
| 733 | else | ||
| 734 | { | ||
| 735 | hr = S_OK; | ||
| 736 | |||
| 737 | if (!pPackage->fPackageProviderExists && GetProviderExists(hkHive, pProvider->sczKey)) | ||
| 738 | { | ||
| 739 | pPackage->fPackageProviderExists = TRUE; | ||
| 740 | } | ||
| 741 | } | ||
| 742 | } | ||
| 743 | |||
| 744 | // Older bundles may not have written the id so try the default. | ||
| 745 | if (!pPackage->fPackageProviderExists && BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.sczProductCode && GetProviderExists(hkHive, pPackage->Msi.sczProductCode)) | ||
| 746 | { | ||
| 747 | pPackage->fPackageProviderExists = TRUE; | ||
| 748 | } | ||
| 749 | |||
| 750 | LExit: | ||
| 751 | return hr; | ||
| 752 | } | ||
| 753 | |||
| 655 | /******************************************************************** | 754 | /******************************************************************** |
| 656 | SplitIgnoreDependencies - Splits a semicolon-delimited | 755 | SplitIgnoreDependencies - Splits a semicolon-delimited |
| 657 | string into a list of unique dependencies to ignore. | 756 | string into a list of unique dependencies to ignore. |
| @@ -803,52 +902,16 @@ LExit: | |||
| 803 | } | 902 | } |
| 804 | 903 | ||
| 805 | /******************************************************************** | 904 | /******************************************************************** |
| 806 | GetProviderId - Gets the ID of the package given the provider key. | 905 | GetProviderExists - Gets whether the provider key is registered. |
| 807 | 906 | ||
| 808 | *********************************************************************/ | 907 | *********************************************************************/ |
| 809 | static HRESULT GetProviderInformation( | 908 | static BOOL GetProviderExists( |
| 810 | __in HKEY hkRoot, | 909 | __in HKEY hkRoot, |
| 811 | __in_z LPCWSTR wzProviderKey, | 910 | __in_z LPCWSTR wzProviderKey |
| 812 | __deref_opt_out_z_opt LPWSTR* psczProviderKey, | ||
| 813 | __deref_opt_out_z_opt LPWSTR* psczId | ||
| 814 | ) | 911 | ) |
| 815 | { | 912 | { |
| 816 | HRESULT hr = S_OK; | 913 | HRESULT hr = DepGetProviderInformation(hkRoot, wzProviderKey, NULL, NULL, NULL); |
| 817 | LPWSTR sczId = NULL; | 914 | return SUCCEEDED(hr); |
| 818 | |||
| 819 | hr = DepGetProviderInformation(hkRoot, wzProviderKey, &sczId, NULL, NULL); | ||
| 820 | if (E_NOTFOUND == hr) | ||
| 821 | { | ||
| 822 | ExitFunction(); | ||
| 823 | } | ||
| 824 | ExitOnFailure(hr, "Failed to get the provider key package id."); | ||
| 825 | |||
| 826 | // If the id was registered return it and exit. | ||
| 827 | if (sczId && *sczId) | ||
| 828 | { | ||
| 829 | if (psczProviderKey) | ||
| 830 | { | ||
| 831 | hr = StrAllocString(psczProviderKey, wzProviderKey, 0); | ||
| 832 | ExitOnFailure(hr, "Failed to copy the provider key."); | ||
| 833 | } | ||
| 834 | |||
| 835 | if (psczId) | ||
| 836 | { | ||
| 837 | *psczId = sczId; | ||
| 838 | sczId = NULL; | ||
| 839 | } | ||
| 840 | |||
| 841 | ExitFunction(); | ||
| 842 | } | ||
| 843 | else | ||
| 844 | { | ||
| 845 | hr = E_NOTFOUND; | ||
| 846 | } | ||
| 847 | |||
| 848 | LExit: | ||
| 849 | ReleaseStr(sczId); | ||
| 850 | |||
| 851 | return hr; | ||
| 852 | } | 915 | } |
| 853 | 916 | ||
| 854 | /******************************************************************** | 917 | /******************************************************************** |
| @@ -886,7 +949,7 @@ static void CalculateDependencyActionStates( | |||
| 886 | switch (pPackage->currentState) | 949 | switch (pPackage->currentState) |
| 887 | { | 950 | { |
| 888 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: | 951 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: |
| 889 | if (!PackageProviderExists(pPackage)) | 952 | if (!pPackage->fPackageProviderExists) |
| 890 | { | 953 | { |
| 891 | break; | 954 | break; |
| 892 | } | 955 | } |
| @@ -902,7 +965,7 @@ static void CalculateDependencyActionStates( | |||
| 902 | switch (pPackage->currentState) | 965 | switch (pPackage->currentState) |
| 903 | { | 966 | { |
| 904 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: | 967 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: |
| 905 | if (!PackageProviderExists(pPackage)) | 968 | if (!pPackage->fPackageProviderExists) |
| 906 | { | 969 | { |
| 907 | break; | 970 | break; |
| 908 | } | 971 | } |
| @@ -1181,15 +1244,3 @@ static void UnregisterPackageDependency( | |||
| 1181 | } | 1244 | } |
| 1182 | } | 1245 | } |
| 1183 | } | 1246 | } |
| 1184 | |||
| 1185 | /******************************************************************** | ||
| 1186 | PackageProviderExists - Checks if a package provider is registered. | ||
| 1187 | |||
| 1188 | *********************************************************************/ | ||
| 1189 | static BOOL PackageProviderExists( | ||
| 1190 | __in const BURN_PACKAGE* pPackage | ||
| 1191 | ) | ||
| 1192 | { | ||
| 1193 | HRESULT hr = DependencyDetectProviderKeyPackageId(pPackage, NULL, NULL); | ||
| 1194 | return SUCCEEDED(hr); | ||
| 1195 | } | ||
