# dotfiles

Windows development-box provisioning scripts.

`setup-windows.bat` takes a fresh Windows install to a working C++ / native
development environment: editors and shells, Python, the Visual Studio 2022
toolchain (including the Clang and Windows XP targeting toolsets), the Windows
Driver Kit, and a handful of analysis tools (Sysinternals, OpenCppCoverage,
BinSkim, the Windows Performance Toolkit). It also sets the box up to be driven
remotely: OpenSSH Server plus an rsync build for Windows, which is what makes a
throwaway VM reachable from a Linux host.

`setup-windows-xp.bat` does the equivalent job for the Windows XP VM the
XP-toolset builds get tested on: an SSH server and the last Python that still
runs there. It shares no machinery with the modern script, because XP has none
of it.

## Files

| File | Purpose |
| --- | --- |
| `setup-windows.bat` | Entry point. Runs the non-elevated, per-user half (winget installs, user `PATH` edits, global git config), then launches the elevated half and prints its log. |
| `setup-windows-xp.bat` | Standalone, for a Windows XP VM. Installs and configures an SSH server, fixes the two XP logon policies that silently break SSH password auth, and installs Python 3.4.4. Installs nothing it did not find staged on disk first. |
| `xp-fetch.py` | Downloads over TLS 1.2 from inside the XP VM, which the OS itself cannot do. Verifies against `cacert.pem` beside it, since XP's root store is too old to validate anything current. `--tls-check HOST` reports the negotiated protocol and cipher, which separates "TLS stack too old" from "certificate store too old". |
| `setup-windows-with-uac.ps1` | The elevated half, started via UAC by the batch file. Enables `ssh-agent`, installs and starts OpenSSH Server, installs `rsync.exe` to the machine `PATH`, then installs Visual Studio 2022 Community with the required components, the WDK, and the Windows Performance Toolkit. Can also be run directly from an Administrator prompt. |

## Usage

1. **Edit `setup-windows.bat` first.** The global git identity near the middle of
   the file is placeholder text:

   ```bat
   git config --global user.name "PLACEHOLDER_NAME"
   git config --global user.email "PLACEHOLDER_EMAIL"
   ```

   Substitute your own name and email, or comment both lines out to keep your
   identity per-repository.

2. Run it from a normal (non-elevated) prompt:

   ```bat
   setup-windows.bat
   ```

   It will raise a single UAC prompt for the elevated half. Accept it — declining
   leaves Visual Studio and the WDK uninstalled, and the script says so.

3. Restart your shell afterwards so the updated user `PATH` is picked up, and
   reboot if a step reported that a restart was required.

## Notes

- The elevated half writes a transcript to `setup-windows-uac.log` next to the
  script; the batch file prints it when the elevated window closes. The log is
  gitignored, as it contains local paths.
- Both halves are idempotent — re-running skips anything already installed.
  BinSkim in particular checks NuGet for the newest stable version *before*
  downloading: the package is a self-contained .NET build well over 100 MB, and
  re-provisioning an up-to-date box should not pay for it. The installed version
  is tracked in `nupkg-version.txt` beside the tool.
- **Remote access.** OpenSSH Server is installed from the Windows on-demand
  capability (10/1809+), set to start automatically, and given an inbound TCP 22
  firewall rule on *all* profiles — a VM's host-only or bridged adapter is
  routinely classified Public, which is the usual reason a running `sshd` is
  unreachable. Windows ships no `rsync`, so a build of it
  ([nuket/rsync-windows](https://github.com/nuket/rsync-windows)) is installed to
  `C:\Tools\rsync` and added to the **machine** `PATH`. That last detail matters:
  the remote end of an `rsync` runs non-interactively, with no login shell, and
  Win32-OpenSSH builds that environment from the registry `PATH` rather than from
  a profile. Key auth needs `~/.ssh/authorized_keys` ACL'd to just you and
  `SYSTEM`; accounts in the Administrators group use
  `C:\ProgramData\ssh\administrators_authorized_keys` instead.
- Visual Studio is installed in three labelled passes (base workload, Clang/LLVM,
  XP toolset) so a failure identifies which component group is responsible.
- The scripts were extracted from a native Windows project, so the component
  selection is tuned for that: Spectre-mitigated runtimes, the v141/XP toolset,
  and driver-kit headers. Trim the component lists in the `.ps1` if you don't
  need them — each group is a plain array near the top.

## The XP VM

XP is far enough back that the usual approach inverts. There is no winget, no
PowerShell, no `where.exe`, no `setx.exe` and no `curl` — and XP's SChannel tops
out at TLS 1.0, so the VM cannot fetch anything from python.org, sourceforge or
github over HTTPS. `setup-windows-xp.bat` therefore **downloads nothing**. Run
it with nothing staged and it prints exactly which files to fetch on the host
and where to drop them (`vendor-xp/`, gitignored), then stops.

Run it from your normal account first. It finds that it is not an
administrator, copies itself and the payload to `C:\xp-setup` — a share mounted
under your account is invisible to the Administrator account, which is the whole
reason for the copy — and prints the `runas` line to use, including the `--user`
flag that tells the elevated run which account you will actually SSH in as.
`--help` prints the full option list.

- **SSH server.** OpenSSH for Windows 3.8.1p1-1, the 2004 `sshwindows` build:
  one unattended installer, a real service, authentication against local
  accounts, no runtime and no network. Its crypto is of its era, so the script
  finishes by printing the `ssh` flags and the matching `~/.ssh/config` block a
  current client needs (`diffie-hellman-group1-sha1`, `ssh-rsa`, `aes128-cbc`).
  Bitvise 6.x and Cygwin 2.5.2 from the Cygwin Time Machine are the two
  modern-crypto alternatives, both noted in the script's comments.

  **Unresolved.** The 3.8.1p1 *binary* is no longer in the SourceForge file
  release — that folder now holds only the NSIS installer source. The one
  binary still published under the project is 3.7.1p1 from October 2003, which
  sits on the wrong side of that autumn's OpenSSH buffer-management advisories.
  So the payload manifest asks for a file that cannot currently be fetched. The
  backend is under review, and Cygwin is the likely replacement: it is served
  over plain HTTP, so XP's TLS ceiling does not apply, and its unattended
  installer can be driven from the host through `VBoxManage guestcontrol`.
- **The two policies that break SSH on XP.** `sshd` authenticates with a network
  logon, and two XP defaults sabotage exactly that: `forceguest=1` collapses
  every network logon to Guest (the default in a workgroup, which a VM always
  is), and `limitblankpassworduse=1` blocks accounts with an empty password. The
  script switches the first to Classic — `--keep-forceguest` opts out, and it
  prints the line to revert — and only reports the second, since the fix there is
  to give the account a password rather than weaken the policy.
- **Python.** 3.4.4 is the last CPython that supports XP; 3.5 raised the floor to
  Vista. `--python27` adds 2.7.18 alongside it. The 3.4 MSI has no "add to PATH"
  option, so the script edits the machine `PATH` in the registry and restarts
  `sshd`, which would otherwise hand SSH sessions the pre-Python environment.
  Bootstrapping `pip` prefers a staged `get-pip.py` (pip 19.1.1, the last release
  supporting 3.4) over `ensurepip` (pip 6, which today's PyPI turns away).
  Installing from PyPI later is its own problem — expect to stage wheels on the
  host and use `pip install --no-index --find-links`.
- Batch on XP is unforgiving about what can go in a message string: no `!`, no
  `<` or `>`, and no parentheses. The `:say` helper documents each one, all found
  the hard way.
