aboutsummaryrefslogtreecommitdiff
path: root/src/engine/dependency.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/dependency.cpp')
-rw-r--r--src/engine/dependency.cpp349
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
13static HRESULT DetectPackageDependents(
14 __in BURN_PACKAGE* pPackage,
15 __in STRINGDICT_HANDLE sdIgnoredDependents,
16 __in const BURN_REGISTRATION* pRegistration
17 );
18
13static HRESULT SplitIgnoreDependencies( 19static 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
31static HRESULT GetProviderInformation( 37static 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
38static void CalculateDependencyActionStates( 42static void CalculateDependencyActionStates(
@@ -70,20 +74,18 @@ static void UnregisterPackageDependency(
70 __in_z LPCWSTR wzDependentProviderKey 74 __in_z LPCWSTR wzDependentProviderKey
71 ); 75 );
72 76
73static BOOL PackageProviderExists(
74 __in const BURN_PACKAGE* pPackage
75 );
76
77 77
78// functions 78// functions
79 79
80extern "C" void DependencyUninitialize( 80extern "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
170extern "C" HRESULT DependencyDetectProviderKeyPackageId( 172extern "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
211LExit: 201LExit:
@@ -236,23 +226,77 @@ LExit:
236 return hr; 226 return hr;
237} 227}
238 228
229extern "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
280LExit:
281 ReleaseDict(sdIgnoredDependents);
282
283 return hr;
284}
285
239extern "C" HRESULT DependencyPlanInitialize( 286extern "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
258LExit: 302LExit:
@@ -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
437LExit: 485LExit:
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
703static 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
750LExit:
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*********************************************************************/
809static HRESULT GetProviderInformation( 908static 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
848LExit:
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*********************************************************************/
1189static BOOL PackageProviderExists(
1190 __in const BURN_PACKAGE* pPackage
1191 )
1192{
1193 HRESULT hr = DependencyDetectProviderKeyPackageId(pPackage, NULL, NULL);
1194 return SUCCEEDED(hr);
1195}