From 1dd1673adf7478a24984346f57c6e0ba9c40e80d Mon Sep 17 00:00:00 2001 From: n0dai Date: Sat, 18 Jul 2026 18:40:15 +0200 Subject: [PATCH] create: reject username equal to the VM name for Windows guests The VM name becomes the guest ComputerName (asb_provision_unattend). When the admin username is identical to it, the unattend UserAccounts pass creates the account but fails to add it to any local group: LookupAccountName on a machine named like the user resolves the computer/domain object first, so NetLocalGroupAddMembers fails with ERROR_NO_SUCH_MEMBER (0x8007056b in UnattendGC\setupact.log). The account ends up group-less, msoobe considers no usable account exists, creates and autologs defaultuser0 instead, FirstLogonCommands never run, so setup.cmd / appsandbox-agent.exe --install never execute and the VM sits on "Installing Windows" forever (agent never online, no input). Reject the collision at creation time in the three input validators: - web/app.js validateUsername (GUI, both hosts) + revalidate the username when the VM name field changes - src/app_win/headless.c validate_create (Windows daemon) - src/app_mac/headless.m validate_create_mac (macOS daemon, Windows guests only) Likely the root cause of the Windows reports in #87. --- src/app_mac/headless.m | 6 ++++++ src/app_win/headless.c | 6 ++++++ web/app.js | 14 ++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/src/app_mac/headless.m b/src/app_mac/headless.m index a77d007..ebd6946 100644 --- a/src/app_mac/headless.m +++ b/src/app_mac/headless.m @@ -372,6 +372,12 @@ static BOOL vm_installing(const AsbVmMac *v) { @"LPT1",@"LPT2",@"LPT3",@"LPT4",@"LPT5",@"LPT6",@"LPT7",@"LPT8",@"LPT9"]; if ([reserved containsObject:user.uppercaseString]) return @"Username is a reserved name."; + /* Windows guests: the VM name becomes the guest ComputerName; a user named + like the machine cannot be added to local groups during the unattend pass + (ERROR_NO_SUCH_MEMBER), so the account ends up group-less and the agent + never installs. */ + if (is_win && [user caseInsensitiveCompare:name] == NSOrderedSame) + return @"Username cannot be the same as the VM name."; /* numeric ranges (0 = unset -> the core fills a default). The even-RAM rule is kept for interface parity with the GUI/Windows daemon. */ diff --git a/src/app_win/headless.c b/src/app_win/headless.c index f1f2a5b..f473a3d 100644 --- a/src/app_win/headless.c +++ b/src/app_win/headless.c @@ -535,6 +535,12 @@ static const char *validate_create(const wchar_t *name, const wchar_t *os, int r; for (r = 0; r < (int)(sizeof(res)/sizeof(res[0])); r++) if (_wcsicmp(user, res[r]) == 0) return "Username is a reserved name."; } + /* The VM name becomes the guest ComputerName; a user named like + the machine cannot be added to local groups during the unattend + pass (ERROR_NO_SUCH_MEMBER), so the account ends up group-less + and the agent never installs. */ + if (_wcsicmp(user, name) == 0) + return "Username cannot be the same as the VM name."; } if (is_linux) { if (!pass || !pass[0]) return "Password is required."; diff --git a/web/app.js b/web/app.js index ece3a1d..18304ee 100644 --- a/web/app.js +++ b/web/app.js @@ -378,6 +378,8 @@ function revalidateVmName() { document.getElementById('vm-name-warn').textContent = validateVmName(name) || ''; } document.getElementById('vm-name').addEventListener('input', revalidateVmName); +/* Username validity depends on the VM name (Windows: username != VM name). */ +document.getElementById('vm-name').addEventListener('input', revalidateUsername); function revalidateUsername() { var u = document.getElementById('admin-user').value.trim(); @@ -524,6 +526,18 @@ function validateUsername(name) { 'COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9', 'LPT1','LPT2','LPT3','LPT4','LPT5','LPT6','LPT7','LPT8','LPT9']; if (reserved.indexOf(name.toUpperCase()) >= 0) return 'Username is a reserved name.'; + /* Windows guests: the VM name becomes the guest ComputerName, and a user + named like the machine cannot be added to local groups during the + unattend pass (LookupAccountName resolves the machine object first, + NetLocalGroupAddMembers fails with ERROR_NO_SUCH_MEMBER). The account + ends up group-less, OOBE autologs defaultuser0 instead and the agent + never installs. */ + if (osType === 'Windows') { + var vmNameEl = document.getElementById('vm-name'); + var vmName = vmNameEl ? vmNameEl.value.trim() : ''; + if (vmName && name.toLowerCase() === vmName.toLowerCase()) + return 'Username cannot be the same as the VM name.'; + } return null; }