+@rem ---------------------------------------------------------------------------\r
+@rem Can this account elevate? Worked out ONCE, here, because it gates two very\r
+@rem different things: the elevated half far below, and a handful of the "per-user"\r
+@rem winget installs just after this, which are per-user in name only.\r
+@rem\r
+@rem ALREADY - already elevated. IsInRole(Administrator) is false for an admin\r
+@rem running unelevated under UAC, so this means actually elevated,\r
+@rem not merely capable of it.\r
+@rem PROMPT - not elevated, UAC on, so elevation can be requested.\r
+@rem NOLUA - UAC is off machine-wide (EnableLUA = 0) AND this is not an\r
+@rem administrator. Elevation is impossible, not merely declined:\r
+@rem Windows has no prompt to offer. Note that with UAC off,\r
+@rem `Start-Process -Verb RunAs` does not fail - it is silently\r
+@rem ignored, runs the child with the caller's own token, and reports\r
+@rem success, which is why this needs detecting rather than trying.\r
+@rem ---------------------------------------------------------------------------\r
+set "ELEV=PROMPT"\r
+for /f "usebackq tokens=*" %%A in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "$id=[Security.Principal.WindowsIdentity]::GetCurrent(); if (([Security.Principal.WindowsPrincipal]$id).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { 'ALREADY' } elseif ((Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -ErrorAction SilentlyContinue).EnableLUA -eq 0) { 'NOLUA' } else { 'PROMPT' }"`) do set "ELEV=%%A"\r
+echo [setup-windows] Elevation: %ELEV%\r
+if "%ELEV%"=="NOLUA" (\r
+ echo [setup-windows] This account cannot elevate ^(UAC off, not an administrator^). Packages that\r
+ echo [setup-windows] need a machine-wide install will be SKIPPED rather than left to fail; the\r
+ echo [setup-windows] plan below marks each one, and there is a summary before the elevated half.\r
+)\r
+\r
+@rem ---------------------------------------------------------------------------\r
+@rem ARM64 is a lean build box, x64 is the full workstation\r
+@rem\r
+@rem The ARM64 machine here is a small VM, and everything it was installing\r
+@rem without a native build was going to run under Prism emulation anyway. So the\r
+@rem two architectures now provision different things on purpose: x64 keeps the\r
+@rem full set, ARM64 installs ONE C/C++ compiler - MSVC from Visual Studio - and\r
+@rem nothing that merely duplicates it or that exists only as an x64 binary.\r
+@rem Rust does not break that rule: it is a different language, not a second\r
+@rem C/C++ compiler, and its native aarch64 MSVC toolchain links through MSVC.\r
+@rem\r
+@rem Dropped on ARM64, and which script would otherwise take each one:\r
+@rem Brave.Brave here no ARM64 build; Edge is in-box and native\r
+@rem WinMerge.WinMerge here ARM64 build is machine-scope only\r
+@rem LLVM.LLVM here second Clang, dropped with VS's clang-cl\r
+@rem NASM.NASM here x86/x64 assembler; ARM64 uses MSVC's armasm64\r
+@rem Google.AndroidGPUInspector here x64-only, profiles Android devices\r
+@rem OpenCppCoverage.OpenCppCoverage here x86/x64 only; cannot instrument ARM64 binaries\r
+@rem VS Clang/LLVM component with-uac see $ClangComponents\r
+@rem Windows Driver Kit with-uac see the WDK step\r
+@rem BinSkim no-uac NuGet publishes win-x64 only\r
+@rem\r
+@rem The decision itself is made in ONE place, setup-windows-steps.ps1, which\r
+@rem marks each of these -X64Only with its reason. The plan shows them as [-]\r
+@rem with that reason before anything runs, and :want prints it again in the log\r
+@rem where the step would have run, so the skip and its reason stay together.\r
+@rem ---------------------------------------------------------------------------\r
+\r
+@rem ---------------------------------------------------------------------------\r
+@rem The plan: what this run will do, shown BEFORE any of it happens\r
+@rem\r
+@rem setup-windows-plan.ps1 lists every step this file and its two halves can\r
+@rem take - from the catalog in setup-windows-steps.ps1, marked for this host's\r
+@rem architecture and elevation - and lets you switch steps off and on. Nothing\r
+@rem below runs unless it was on that list and still selected when you pressed\r
+@rem Enter; with no console to ask on, it stops unless given -Yes. Arguments to\r
+@rem this script go straight to the planner:\r
+@rem setup-windows.bat -WhatIf show the plan, do nothing\r
+@rem setup-windows.bat -Skip VirtualBox,Brave start with those switched off\r
+@rem setup-windows.bat -Only E -Yes just the elevated half, no questions\r
+@rem\r
+@rem The choice comes back as a scratch .cmd of `set` lines, called here:\r
+@rem STEP_<Id>, WHY_<Id>, PKG_<Id> per step this file takes - see :want\r
+@rem UAC_STEPS, USER_STEPS comma lists passed to the halves as -Only\r
+@rem PLAN_RUN, PLAN_RC go on (1), or stop and exit with PLAN_RC\r
+@rem No file at all means the planner failed - it exits 0 even on a mistyped\r
+@rem parameter - so that stops the run too, before anything has been done.\r
+@rem ---------------------------------------------------------------------------\r
+set "PLAN_ARGS=%*"\r
+if "%~1"=="/?" set "PLAN_ARGS=-Help"\r
+if "%~1"=="-?" set "PLAN_ARGS=-Help"\r
+set "PLAN_CMD=%TEMP%\setup-windows-plan-%RANDOM%%RANDOM%.cmd"\r
+if exist "%PLAN_CMD%" del "%PLAN_CMD%"\r
+powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0setup-windows-plan.ps1" -HostArch "%HOST_ARCH%" -Elevation "%ELEV%" -OutFile "%PLAN_CMD%" %PLAN_ARGS%\r
+if not exist "%PLAN_CMD%" (\r
+ echo [setup-windows] No plan was made ^(see above^), so nothing has been done.\r
+ exit /b 1\r
+)\r
+call "%PLAN_CMD%"\r
+del "%PLAN_CMD%"\r
+if not "%PLAN_RUN%"=="1" exit /b %PLAN_RC%\r
+\r
+@rem --- Claude Code, from Anthropic's own installer rather than winget ---\r
+@rem\r
+@rem NOT `winget install Anthropic.ClaudeCode` any more: recent releases are\r
+@rem broken through that route. This is the documented native install,\r
+@rem `irm https://claude.ai/install.ps1 | iex`. The script downloads the current\r
+@rem release's claude.exe, checks it against the SHA-256 in that release's\r
+@rem manifest, and runs `claude install`, which puts the launcher in\r
+@rem %USERPROFILE%\.local\bin - per-user, no elevation. Re-running it updates to\r
+@rem the latest release.\r
+@rem\r
+@rem Two things are fixed up around it, both about which build it gets:\r
+@rem - It picks win32-arm64 or win32-x64 from $env:PROCESSOR_ARCHITECTURE and\r
+@rem nothing else - the variable the block at the top of this file shows to be\r
+@rem WRONG in an emulated x64 shell on ARM64, where it would hand you the\r
+@rem emulated build. So %HOST_ARCH%, the registry's answer, is written into it\r
+@rem for the installer's process first. That only corrects the value; anything\r
+@rem else in that process that reads it sees the truth too.\r
+@rem - It refuses a 32-bit PowerShell outright ("does not support 32-bit\r
+@rem Windows"), and a bare `powershell` from a 32-bit cmd.exe is exactly that.\r
+@rem %SystemRoot%\Sysnative reaches the 64-bit one from there - it exists only\r
+@rem for 32-bit processes - so it is used when present.\r
+@rem\r
+@rem A copy left behind by the old winget route is a second claude.exe, reached\r
+@rem through WinGet\Links on the user PATH, and it can win over this one. It is\r
+@rem reported, not removed: `winget uninstall Anthropic.ClaudeCode` is yours to run.\r
+@rem\r
+@rem The installer has no "already current" check - it downloads and reinstalls\r
+@rem the whole release every time - so setup-windows-current.ps1 asks first: is\r
+@rem the native claude.exe already the latest release, and the build for this\r
+@rem host? Only a clear yes skips it; a check that cannot decide installs.\r
+set "PS64=powershell"\r
+if exist "%SystemRoot%\Sysnative\WindowsPowerShell\v1.0\powershell.exe" set "PS64=%SystemRoot%\Sysnative\WindowsPowerShell\v1.0\powershell.exe"\r
+call :want ClaudeCode || goto :after_claude\r
+"%PS64%" -NoProfile -ExecutionPolicy Bypass -File "%~dp0setup-windows-current.ps1" -Step ClaudeCode -HostArch "%HOST_ARCH%"\r
+if "%ERRORLEVEL%"=="0" goto :claude_leftover\r
+echo [setup-windows] ClaudeCode: irm https://claude.ai/install.ps1 ^| iex ^(as %HOST_ARCH%^)\r
+"%PS64%" -NoProfile -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $env:PROCESSOR_ARCHITECTURE = '%HOST_ARCH%'; irm https://claude.ai/install.ps1 | iex"\r
+if not "%ERRORLEVEL%"=="0" echo [setup-windows] WARNING: the Claude Code installer failed ^(exit %ERRORLEVEL%^); see above. Continuing.\r
+:claude_leftover\r
+set "CLAUDE_WINGET="\r
+if exist "%LOCALAPPDATA%\Microsoft\WinGet\Links\claude.exe" set "CLAUDE_WINGET=1"\r
+for /d %%D in ("%LOCALAPPDATA%\Microsoft\WinGet\Packages\Anthropic.ClaudeCode_*") do set "CLAUDE_WINGET=1"\r
+if defined CLAUDE_WINGET (\r
+ echo [setup-windows] WARNING: Claude Code is ALSO installed through winget ^(Anthropic.ClaudeCode^), the\r
+ echo [setup-windows] route this script no longer uses. That claude.exe can win over the new one on\r
+ echo [setup-windows] the PATH. Remove it with: winget uninstall Anthropic.ClaudeCode\r
+)\r
+:after_claude\r
+\r