@@ -442,6 +442,14 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
442
442
ThemeControlElevates (_theme, ID_INSTALL_BUTTON, elevated);
443
443
ThemeControlElevates (_theme, ID_INSTALL_SIMPLE_BUTTON, elevated);
444
444
ThemeControlElevates (_theme, ID_INSTALL_UPGRADE_BUTTON, elevated);
445
+
446
+ LONGLONG blockedLauncher;
447
+ if (SUCCEEDED (BalGetNumericVariable (L" BlockedLauncher" , &blockedLauncher)) && blockedLauncher) {
448
+ LOC_STRING *pLocString = nullptr ;
449
+ if (SUCCEEDED (LocGetString (_wixLoc, L" #(loc.ShortInstallLauncherBlockedLabel)" , &pLocString)) && pLocString) {
450
+ ThemeSetTextControl (_theme, ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, pLocString->wzText );
451
+ }
452
+ }
445
453
}
446
454
447
455
void Custom1Page_Show () {
@@ -718,25 +726,67 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
718
726
__in DWORD64 /* dw64Version*/ ,
719
727
__in BOOTSTRAPPER_RELATED_OPERATION operation
720
728
) {
721
- if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation &&
722
- (CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , wzPackageId, -1 , L" launcher_AllUsers" , -1 ) ||
723
- CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , wzPackageId, -1 , L" launcher_JustForMe" , -1 ))) {
724
- auto hr = LoadAssociateFilesStateFromKey (_engine, fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER);
725
- if (hr == S_OK) {
726
- _engine->SetVariableNumeric (L" AssociateFiles" , 1 );
727
- } else if (hr == S_FALSE) {
728
- _engine->SetVariableNumeric (L" AssociateFiles" , 0 );
729
- } else if (FAILED (hr)) {
730
- BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " Failed to load AssociateFiles state: error code 0x%08X" , hr);
729
+ // Only check launcher_AllUsers because we'll find the same packages
730
+ // twice if we check launcher_JustForMe as well.
731
+ if (CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , wzPackageId, -1 , L" launcher_AllUsers" , -1 )) {
732
+ BalLog (BOOTSTRAPPER_LOG_LEVEL_STANDARD, " Detected existing launcher install" );
733
+
734
+ LONGLONG blockedLauncher, detectedLauncher;
735
+ if (FAILED (BalGetNumericVariable (L" BlockedLauncher" , &blockedLauncher))) {
736
+ blockedLauncher = 0 ;
737
+ }
738
+
739
+ // Get the prior DetectedLauncher value so we can see if we've
740
+ // detected more than one, and then update the stored variable
741
+ // (we use the original value later on via the local).
742
+ if (FAILED (BalGetNumericVariable (L" DetectedLauncher" , &detectedLauncher))) {
743
+ detectedLauncher = 0 ;
744
+ }
745
+ if (!detectedLauncher) {
746
+ _engine->SetVariableNumeric (L" DetectedLauncher" , 1 );
747
+ }
748
+
749
+ if (blockedLauncher) {
750
+ // Nothing else to do, we're already blocking
751
+ }
752
+ else if (BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) {
753
+ // Found a higher version, so we can't install ours.
754
+ BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " Higher version launcher has been detected." );
755
+ BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " Launcher will not be installed" );
756
+ _engine->SetVariableNumeric (L" BlockedLauncher" , 1 );
757
+ }
758
+ else if (detectedLauncher) {
759
+ if (!blockedLauncher) {
760
+ BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " Multiple launcher installs have been detected." );
761
+ BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " No launcher will be installed or upgraded until one has been removed." );
762
+ _engine->SetVariableNumeric (L" BlockedLauncher" , 1 );
763
+ }
731
764
}
765
+ else if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation) {
766
+ // Found an older version, so let's run the equivalent as an upgrade
767
+ // This overrides "unknown" all users options, but will leave alone
768
+ // any that have already been set/detected.
769
+ // User can deselect the option to include the launcher, but cannot
770
+ // change it from the current per user/machine setting.
771
+ LONGLONG includeLauncher, includeLauncherAllUsers;
772
+ if (FAILED (BalGetNumericVariable (L" Include_launcher" , &includeLauncher))) {
773
+ includeLauncher = -1 ;
774
+ }
775
+ if (FAILED (BalGetNumericVariable (L" InstallLauncherAllUsers" , &includeLauncherAllUsers))) {
776
+ includeLauncherAllUsers = -1 ;
777
+ }
732
778
733
- LONGLONG includeLauncher;
734
- if (FAILED (BalGetNumericVariable (L" Include_launcher" , &includeLauncher))
735
- || includeLauncher == -1 ) {
736
- _engine->SetVariableNumeric (L" Include_launcher" , 1 );
737
- _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , fPerMachine ? 1 : 0 );
779
+ if (includeLauncher < 0 ) {
780
+ _engine->SetVariableNumeric (L" Include_launcher" , 1 );
781
+ }
782
+ if (includeLauncherAllUsers < 0 ) {
783
+ _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , fPerMachine ? 1 : 0 );
784
+ } else if (includeLauncherAllUsers != fPerMachine ? 1 : 0 ) {
785
+ // Requested AllUsers option is inconsistent, so block
786
+ _engine->SetVariableNumeric (L" BlockedLauncher" , 1 );
787
+ }
788
+ _engine->SetVariableNumeric (L" DetectedOldLauncher" , 1 );
738
789
}
739
- _engine->SetVariableNumeric (L" DetectedOldLauncher" , 1 );
740
790
}
741
791
return CheckCanceled () ? IDCANCEL : IDNOACTION;
742
792
}
@@ -784,48 +834,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
784
834
__in LPCWSTR wzPackageId,
785
835
__in HRESULT hrStatus,
786
836
__in BOOTSTRAPPER_PACKAGE_STATE state
787
- ) {
788
- if (FAILED (hrStatus)) {
789
- return ;
790
- }
791
-
792
- BOOL detectedLauncher = FALSE ;
793
- HKEY hkey = HKEY_LOCAL_MACHINE;
794
- if (CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , wzPackageId, -1 , L" launcher_AllUsers" , -1 )) {
795
- if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE == state) {
796
- detectedLauncher = TRUE ;
797
- _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , 1 );
798
- }
799
- } else if (CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , wzPackageId, -1 , L" launcher_JustForMe" , -1 )) {
800
- if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE == state) {
801
- detectedLauncher = TRUE ;
802
- _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , 0 );
803
- }
804
- }
805
-
806
- LONGLONG includeLauncher;
807
- if (SUCCEEDED (BalGetNumericVariable (L" Include_launcher" , &includeLauncher))
808
- && includeLauncher != -1 ) {
809
- detectedLauncher = FALSE ;
810
- }
811
-
812
- if (detectedLauncher) {
813
- /* When we detect the current version of the launcher. */
814
- _engine->SetVariableNumeric (L" Include_launcher" , 1 );
815
- _engine->SetVariableNumeric (L" DetectedLauncher" , 1 );
816
- _engine->SetVariableString (L" Include_launcherState" , L" disable" );
817
- _engine->SetVariableString (L" InstallLauncherAllUsersState" , L" disable" );
818
-
819
- auto hr = LoadAssociateFilesStateFromKey (_engine, hkey);
820
- if (hr == S_OK) {
821
- _engine->SetVariableNumeric (L" AssociateFiles" , 1 );
822
- } else if (hr == S_FALSE) {
823
- _engine->SetVariableNumeric (L" AssociateFiles" , 0 );
824
- } else if (FAILED (hr)) {
825
- BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " Failed to load AssociateFiles state: error code 0x%08X" , hr);
826
- }
827
- }
828
- }
837
+ ) { }
829
838
830
839
831
840
virtual STDMETHODIMP_ (void ) OnDetectComplete(__in HRESULT hrStatus) {
@@ -835,19 +844,67 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
835
844
}
836
845
837
846
if (SUCCEEDED (hrStatus)) {
838
- LONGLONG includeLauncher;
839
- if (SUCCEEDED (BalGetNumericVariable (L" Include_launcher" , &includeLauncher))
840
- && includeLauncher == -1 ) {
841
- if (BOOTSTRAPPER_ACTION_LAYOUT == _command.action ||
842
- (BOOTSTRAPPER_ACTION_INSTALL == _command.action && !_upgrading)) {
843
- // When installing/downloading, we want to include the launcher
844
- // by default.
845
- _engine->SetVariableNumeric (L" Include_launcher" , 1 );
846
- } else {
847
- // Any other action, if we didn't detect the MSI then we want to
848
- // keep it excluded
849
- _engine->SetVariableNumeric (L" Include_launcher" , 0 );
850
- _engine->SetVariableNumeric (L" AssociateFiles" , 0 );
847
+ // Update launcher install states
848
+ // If we didn't detect any existing installs, Include_launcher and
849
+ // InstallLauncherAllUsers will both be -1, so we will set to their
850
+ // defaults and leave the options enabled.
851
+ // Otherwise, if we detected an existing install, we disable the
852
+ // options so they remain fixed.
853
+ // The code in OnDetectRelatedMsiPackage is responsible for figuring
854
+ // out whether existing installs are compatible with the settings in
855
+ // place during detection.
856
+ LONGLONG blockedLauncher;
857
+ if (SUCCEEDED (BalGetNumericVariable (L" BlockedLauncher" , &blockedLauncher))
858
+ && blockedLauncher) {
859
+ _engine->SetVariableNumeric (L" Include_launcher" , 0 );
860
+ _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , 0 );
861
+ _engine->SetVariableString (L" InstallLauncherAllUsersState" , L" disable" );
862
+ _engine->SetVariableString (L" Include_launcherState" , L" disable" );
863
+ }
864
+ else {
865
+ LONGLONG includeLauncher, includeLauncherAllUsers, associateFiles;
866
+
867
+ if (FAILED (BalGetNumericVariable (L" Include_launcher" , &includeLauncher))) {
868
+ includeLauncher = -1 ;
869
+ }
870
+ if (FAILED (BalGetNumericVariable (L" InstallLauncherAllUsers" , &includeLauncherAllUsers))) {
871
+ includeLauncherAllUsers = -1 ;
872
+ }
873
+ if (FAILED (BalGetNumericVariable (L" AssociateFiles" , &associateFiles))) {
874
+ associateFiles = -1 ;
875
+ }
876
+
877
+ if (includeLauncherAllUsers < 0 ) {
878
+ includeLauncherAllUsers = 0 ;
879
+ _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , includeLauncherAllUsers);
880
+ }
881
+
882
+ if (includeLauncher < 0 ) {
883
+ if (BOOTSTRAPPER_ACTION_LAYOUT == _command.action ||
884
+ (BOOTSTRAPPER_ACTION_INSTALL == _command.action && !_upgrading)) {
885
+ // When installing/downloading, we include the launcher
886
+ // (though downloads should ignore this setting anyway)
887
+ _engine->SetVariableNumeric (L" Include_launcher" , 1 );
888
+ } else {
889
+ // Any other action, we should have detected an existing
890
+ // install (e.g. on remove/modify), so if we didn't, we
891
+ // assume it's not selected.
892
+ _engine->SetVariableNumeric (L" Include_launcher" , 0 );
893
+ _engine->SetVariableNumeric (L" AssociateFiles" , 0 );
894
+ }
895
+ }
896
+
897
+ if (associateFiles < 0 ) {
898
+ auto hr = LoadAssociateFilesStateFromKey (
899
+ _engine,
900
+ includeLauncherAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER
901
+ );
902
+ if (FAILED (hr)) {
903
+ BalLog (BOOTSTRAPPER_LOG_LEVEL_ERROR, " Failed to load AssociateFiles state: error code 0x%08X" , hr);
904
+ } else if (hr == S_OK) {
905
+ associateFiles = 1 ;
906
+ }
907
+ _engine->SetVariableNumeric (L" AssociateFiles" , associateFiles);
851
908
}
852
909
}
853
910
}
0 commit comments