@@ -87,11 +87,13 @@ enum CONTROL_ID {
8787 ID_INSTALL_UPGRADE_BUTTON,
8888 ID_INSTALL_UPGRADE_CUSTOM_BUTTON,
8989 ID_INSTALL_CANCEL_BUTTON,
90-
90+ ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX,
91+
9192 // Customize Page
9293 ID_TARGETDIR_EDITBOX,
9394 ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX,
9495 ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX,
96+ ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX,
9597 ID_CUSTOM_COMPILE_ALL_CHECKBOX,
9698 ID_CUSTOM_BROWSE_BUTTON,
9799 ID_CUSTOM_BROWSE_BUTTON_LABEL,
@@ -150,10 +152,12 @@ static THEME_ASSIGN_CONTROL_ID CONTROL_ID_NAMES[] = {
150152 { ID_INSTALL_UPGRADE_BUTTON, L" InstallUpgradeButton" },
151153 { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L" InstallUpgradeCustomButton" },
152154 { ID_INSTALL_CANCEL_BUTTON, L" InstallCancelButton" },
155+ { ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L" InstallLauncherAllUsers" },
153156
154157 { ID_TARGETDIR_EDITBOX, L" TargetDir" },
155158 { ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, L" AssociateFiles" },
156159 { ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, L" InstallAllUsers" },
160+ { ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L" CustomInstallLauncherAllUsers" },
157161 { ID_CUSTOM_COMPILE_ALL_CHECKBOX, L" CompileAll" },
158162 { ID_CUSTOM_BROWSE_BUTTON, L" CustomBrowseButton" },
159163 { ID_CUSTOM_BROWSE_BUTTON_LABEL, L" CustomBrowseButtonLabel" },
@@ -261,10 +265,11 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
261265 LPWSTR defaultDir = nullptr ;
262266 LPWSTR targetDir = nullptr ;
263267 LONGLONG elevated, crtInstalled, installAllUsers;
264- BOOL checked;
268+ BOOL checked, launcherChecked ;
265269 WCHAR wzPath[MAX_PATH] = { };
266270 BROWSEINFOW browseInfo = { };
267271 PIDLIST_ABSOLUTE pidl = nullptr ;
272+ DWORD pageId;
268273 HRESULT hr = S_OK;
269274
270275 switch (id) {
@@ -278,7 +283,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
278283 case ID_INSTALL_BUTTON:
279284 SavePageSettings ();
280285
281- if (!QueryElevateForCrtInstall ()) {
286+ if (!WillElevate () && ! QueryElevateForCrtInstall ()) {
282287 break ;
283288 }
284289
@@ -344,18 +349,32 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
344349 ReleaseStr (targetDir);
345350 }
346351
347- checked = ThemeIsControlChecked (_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX);
348- if (!checked && !QueryElevateForCrtInstall ()) {
352+ if (!WillElevate () && !QueryElevateForCrtInstall ()) {
349353 break ;
350354 }
351355
352356 OnPlan (_command.action );
353357 break ;
354358
359+ case ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX:
360+ checked = ThemeIsControlChecked (_theme, ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX);
361+ _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , checked);
362+
363+ ThemeControlElevates (_theme, ID_INSTALL_BUTTON, WillElevate ());
364+ break ;
365+
366+ case ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX:
367+ checked = ThemeIsControlChecked (_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX);
368+ _engine->SetVariableNumeric (L" InstallLauncherAllUsers" , checked);
369+
370+ ThemeControlElevates (_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate ());
371+ break ;
372+
355373 case ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX:
356- hr = BalGetNumericVariable (L" WixBundleElevated" , &elevated);
357374 checked = ThemeIsControlChecked (_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX);
358- ThemeControlElevates (_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED (hr) || !elevated));
375+ _engine->SetVariableNumeric (L" InstallAllUsers" , checked);
376+
377+ ThemeControlElevates (_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate ());
359378 ThemeControlEnable (_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, !checked);
360379 if (checked) {
361380 _engine->SetVariableNumeric (L" CompileAll" , 1 );
@@ -416,6 +435,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
416435 case ID_MODIFY_BUTTON:
417436 // Some variables cannot be modified
418437 _engine->SetVariableString (L" InstallAllUsersState" , L" disable" );
438+ _engine->SetVariableString (L" InstallLauncherAllUsersState" , L" disable" );
419439 _engine->SetVariableString (L" TargetDirState" , L" disable" );
420440 _engine->SetVariableString (L" CustomBrowseButtonState" , L" disable" );
421441 _modifying = TRUE ;
@@ -437,35 +457,36 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
437457
438458 void InstallPage_Show () {
439459 // Ensure the All Users install button has a UAC shield
440- LONGLONG elevated, installAll ;
441-
442- if ( FAILED ( BalGetNumericVariable ( L" WixBundleElevated " , & elevated))) {
443- elevated = 0 ;
444- }
460+ BOOL elevated = WillElevate () ;
461+ ThemeControlElevates (_theme, ID_INSTALL_BUTTON, elevated);
462+ ThemeControlElevates (_theme, ID_INSTALL_SIMPLE_BUTTON, elevated);
463+ ThemeControlElevates (_theme, ID_INSTALL_UPGRADE_BUTTON, elevated) ;
464+ }
445465
466+ void Custom1Page_Show () {
467+ LONGLONG installLauncherAllUsers;
446468
447- if (SUCCEEDED (BalGetNumericVariable (L" InstallAllUsers" , &installAll)) && installAll && !elevated) {
448- ThemeControlElevates (_theme, ID_INSTALL_BUTTON, TRUE );
449- ThemeControlElevates (_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE );
450- ThemeControlElevates (_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE );
469+ if (FAILED (BalGetNumericVariable (L" InstallLauncherAllUsers" , &installLauncherAllUsers))) {
470+ installLauncherAllUsers = 0 ;
451471 }
452- }
453472
454- void Custom1Page_Show () {
473+ ThemeSendControlMessage (_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, BM_SETCHECK,
474+ installLauncherAllUsers ? BST_CHECKED : BST_UNCHECKED, 0 );
455475 }
456476
457477 void Custom2Page_Show () {
458478 HRESULT hr;
459- LONGLONG installAll, elevated, includeLauncher;
479+ LONGLONG installAll, includeLauncher;
460480
461- if (FAILED (BalGetNumericVariable (L" WixBundleElevated " , &elevated ))) {
462- elevated = 0 ;
481+ if (FAILED (BalGetNumericVariable (L" InstallAllUsers " , &installAll ))) {
482+ installAll = 0 ;
463483 }
464- if (SUCCEEDED (BalGetNumericVariable (L" InstallAllUsers" , &installAll))) {
465- ThemeControlElevates (_theme, ID_CUSTOM_INSTALL_BUTTON, installAll && !elevated);
484+
485+ if (WillElevate ()) {
486+ ThemeControlElevates (_theme, ID_CUSTOM_INSTALL_BUTTON, TRUE );
466487 ThemeShowControl (_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_HIDE);
467488 } else {
468- installAll = 0 ;
489+ ThemeControlElevates (_theme, ID_CUSTOM_INSTALL_BUTTON, FALSE ) ;
469490 ThemeShowControl (_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_SHOW);
470491 }
471492
@@ -1839,8 +1860,8 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
18391860 COLORREF fg = fnt->crForeground , bg = fnt->crBackground ;
18401861 *brush = fnt->hBackground ;
18411862 RemapColor (&fg, &bg, brush);
1842- SetTextColor (hDC, fg);
1843- SetBkColor (hDC, bg);
1863+ :: SetTextColor (hDC, fg);
1864+ :: SetBkColor (hDC, bg);
18441865
18451866 return TRUE ;
18461867 }
@@ -2080,6 +2101,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
20802101
20812102 for (DWORD i = 0 ; i < pPage->cControlIndices ; ++i) {
20822103 THEME_CONTROL* pControl = _theme->rgControls + pPage->rgdwControlIndices [i];
2104+ BOOL enableControl = TRUE ;
20832105
20842106 // If this is a named control, try to set its default state.
20852107 if (pControl->sczName && *pControl->sczName ) {
@@ -2091,7 +2113,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
20912113
20922114 // If the control value isn't set then disable it.
20932115 if (!SUCCEEDED (hr)) {
2094- ThemeControlEnable (_theme, pControl-> wId , FALSE ) ;
2116+ enableControl = FALSE ;
20952117 } else {
20962118 ThemeSendControlMessage (
20972119 _theme,
@@ -2110,20 +2132,34 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
21102132 LPWSTR controlState = nullptr ;
21112133 hr = BalGetStringVariable (controlName, &controlState);
21122134 if (SUCCEEDED (hr) && controlState && *controlState) {
2135+ if (controlState[0 ] == ' [' ) {
2136+ LPWSTR formatted = nullptr ;
2137+ if (SUCCEEDED (BalFormatString (controlState, &formatted))) {
2138+ StrFree (controlState);
2139+ controlState = formatted;
2140+ }
2141+ }
2142+
21132143 if (CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , controlState, -1 , L" disable" , -1 )) {
21142144 BalLog (BOOTSTRAPPER_LOG_LEVEL_STANDARD, " Disable control %ls" , pControl->sczName );
2115- ThemeControlEnable (_theme, pControl-> wId , FALSE ) ;
2145+ enableControl = FALSE ;
21162146 } else if (CSTR_EQUAL == ::CompareStringW (LOCALE_NEUTRAL, 0 , controlState, -1 , L" hide" , -1 )) {
21172147 BalLog (BOOTSTRAPPER_LOG_LEVEL_STANDARD, " Hide control %ls" , pControl->sczName );
21182148 // TODO: This doesn't work
21192149 ThemeShowControl (_theme, pControl->wId , SW_HIDE);
2150+ } else {
2151+ // An explicit state can override the lack of a
2152+ // backing variable.
2153+ enableControl = TRUE ;
21202154 }
21212155 }
21222156 StrFree (controlState);
21232157 }
21242158 StrFree (controlName);
21252159 }
21262160
2161+ ThemeControlEnable (_theme, pControl->wId , enableControl);
2162+
21272163 // Format the text in each of the new page's controls
21282164 if (pControl->sczText && *pControl->sczText ) {
21292165 // If the wix developer is showing a hidden variable
@@ -2405,6 +2441,16 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
24052441 }
24062442 }
24072443
2444+ BOOL WillElevate () {
2445+ static BAL_CONDITION WILL_ELEVATE_CONDITION = {
2446+ L" not WixBundleElevated and (InstallAllUsers or (InstallLauncherAllUsers and Include_launcher))" ,
2447+ L" "
2448+ };
2449+ BOOL result;
2450+
2451+ return SUCCEEDED (BalConditionEvaluate (&WILL_ELEVATE_CONDITION, _engine, &result, nullptr )) && result;
2452+ }
2453+
24082454 BOOL IsCrtInstalled () {
24092455 if (_crtInstalledToken > 0 ) {
24102456 return TRUE ;
0 commit comments