|
10 | 10 |
|
11 | 11 | #include "pch.h" |
12 | 12 |
|
13 | | -static const LPCWSTR WIXBUNDLE_VARIABLE_ELEVATED = L"WixBundleElevated"; |
14 | | - |
15 | 13 | static const LPCWSTR PYBA_WINDOW_CLASS = L"PythonBA"; |
16 | 14 | static const LPCWSTR PYBA_VARIABLE_LAUNCH_TARGET_PATH = L"LaunchTarget"; |
17 | 15 | static const LPCWSTR PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID = L"LaunchTargetElevatedId"; |
@@ -232,7 +230,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
232 | 230 | void OnCommand(CONTROL_ID id) { |
233 | 231 | LPWSTR defaultDir = nullptr; |
234 | 232 | LPWSTR targetDir = nullptr; |
235 | | - LONGLONG elevated; |
| 233 | + LONGLONG elevated, crtInstalled; |
236 | 234 | BOOL checked; |
237 | 235 | WCHAR wzPath[MAX_PATH] = { }; |
238 | 236 | BROWSEINFOW browseInfo = { }; |
@@ -320,6 +318,10 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
320 | 318 | ReleaseStr(targetDir); |
321 | 319 | BalExitOnFailure(hr, "Failed to set install target directory"); |
322 | 320 |
|
| 321 | + if (!QueryElevateForCrtInstall()) { |
| 322 | + break; |
| 323 | + } |
| 324 | + |
323 | 325 | OnPlan(BOOTSTRAPPER_ACTION_INSTALL); |
324 | 326 | break; |
325 | 327 |
|
@@ -352,6 +354,11 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
352 | 354 | ReleaseStr(targetDir); |
353 | 355 | } |
354 | 356 |
|
| 357 | + checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); |
| 358 | + if (!checked && !QueryElevateForCrtInstall()) { |
| 359 | + break; |
| 360 | + } |
| 361 | + |
355 | 362 | OnPlan(_command.action); |
356 | 363 | break; |
357 | 364 |
|
@@ -2311,6 +2318,75 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
2311 | 2318 | } |
2312 | 2319 | } |
2313 | 2320 |
|
| 2321 | + BOOL IsCrtInstalled() { |
| 2322 | + if (_crtInstalledToken > 0) { |
| 2323 | + return TRUE; |
| 2324 | + } else if (_crtInstalledToken == 0) { |
| 2325 | + return FALSE; |
| 2326 | + } |
| 2327 | + |
| 2328 | + // Check whether at least CRT v10.0.9920.0 is available. |
| 2329 | + // It should only be installed as a Windows Update package, which means |
| 2330 | + // we don't need to worry about 32-bit/64-bit. |
| 2331 | + // However, since the WU package does not include vcruntime140.dll, we |
| 2332 | + // still install that ourselves. |
| 2333 | + LPCWSTR crtFile = L"api-ms-win-crt-runtime-l1-1-0.dll"; |
| 2334 | + |
| 2335 | + DWORD cbVer = GetFileVersionInfoSizeW(crtFile, nullptr); |
| 2336 | + if (!cbVer) { |
| 2337 | + _crtInstalledToken = 0; |
| 2338 | + return FALSE; |
| 2339 | + } |
| 2340 | + |
| 2341 | + void *pData = malloc(cbVer); |
| 2342 | + if (!pData) { |
| 2343 | + _crtInstalledToken = 0; |
| 2344 | + return FALSE; |
| 2345 | + } |
| 2346 | + |
| 2347 | + if (!GetFileVersionInfoW(crtFile, 0, cbVer, pData)) { |
| 2348 | + free(pData); |
| 2349 | + _crtInstalledToken = 0; |
| 2350 | + return FALSE; |
| 2351 | + } |
| 2352 | + |
| 2353 | + VS_FIXEDFILEINFO *ffi; |
| 2354 | + UINT cb; |
| 2355 | + BOOL result = FALSE; |
| 2356 | + |
| 2357 | + if (VerQueryValueW(pData, L"\\", (LPVOID*)&ffi, &cb) && |
| 2358 | + ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x26C00000) { |
| 2359 | + result = TRUE; |
| 2360 | + } |
| 2361 | + |
| 2362 | + free(pData); |
| 2363 | + _crtInstalledToken = result ? 1 : 0; |
| 2364 | + return result; |
| 2365 | + } |
| 2366 | + |
| 2367 | + BOOL QueryElevateForCrtInstall() { |
| 2368 | + // Called to prompt the user that even though they think they won't need |
| 2369 | + // to elevate, they actually will because of the CRT install. |
| 2370 | + if (IsCrtInstalled()) { |
| 2371 | + // CRT is already installed - no need to prompt |
| 2372 | + return TRUE; |
| 2373 | + } |
| 2374 | + |
| 2375 | + LONGLONG elevated; |
| 2376 | + HRESULT hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); |
| 2377 | + if (SUCCEEDED(hr) && elevated) { |
| 2378 | + // Already elevated - no need to prompt |
| 2379 | + return TRUE; |
| 2380 | + } |
| 2381 | + |
| 2382 | + LOC_STRING *locStr; |
| 2383 | + hr = LocGetString(_wixLoc, L"#(loc.ElevateForCRTInstall)", &locStr); |
| 2384 | + if (FAILED(hr)) { |
| 2385 | + BalLogError(hr, "Failed to get ElevateForCRTInstall string"); |
| 2386 | + return FALSE; |
| 2387 | + } |
| 2388 | + return ::MessageBoxW(_hWnd, locStr->wzText, _theme->sczCaption, MB_YESNO) != IDNO; |
| 2389 | + } |
2314 | 2390 |
|
2315 | 2391 | HRESULT EvaluateConditions() { |
2316 | 2392 | HRESULT hr = S_OK; |
@@ -2498,6 +2574,8 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
2498 | 2574 | } |
2499 | 2575 | } |
2500 | 2576 |
|
| 2577 | + pEngine->SetVariableNumeric(L"CRTInstalled", IsCrtInstalled() ? 1 : 0); |
| 2578 | + |
2501 | 2579 | _wixLoc = nullptr; |
2502 | 2580 | memset(&_bundle, 0, sizeof(_bundle)); |
2503 | 2581 | memset(&_conditions, 0, sizeof(_conditions)); |
@@ -2525,6 +2603,8 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
2525 | 2603 | _suppressRepair = FALSE; |
2526 | 2604 | _modifying = FALSE; |
2527 | 2605 |
|
| 2606 | + _crtInstalledToken = -1; |
| 2607 | + |
2528 | 2608 | _overridableVariables = nullptr; |
2529 | 2609 | _taskbarList = nullptr; |
2530 | 2610 | _taskbarButtonCreatedMessage = UINT_MAX; |
@@ -2606,6 +2686,8 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { |
2606 | 2686 | BOOL _suppressRepair; |
2607 | 2687 | BOOL _modifying; |
2608 | 2688 |
|
| 2689 | + int _crtInstalledToken; |
| 2690 | + |
2609 | 2691 | STRINGDICT_HANDLE _overridableVariables; |
2610 | 2692 |
|
2611 | 2693 | ITaskbarList3* _taskbarList; |
|
0 commit comments