diff --git a/CHANGELOG.md b/CHANGELOG.md
index 73fc00d..9d9cade 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,13 @@ Beta pre-release for the framerate and reliability work since 1.1.0.
- **MSI ProductVersion now tracks the build version** — it was hardcoded to
1.0.0.0, so in-place upgrades (MajorUpgrade) never saw a newer version.
Upgrading from an earlier install may require a manual uninstall once.
+- **Control surface works out of the box for standard users** — the installer
+ now reserves the http.sys URL namespace for `http://127.0.0.1:9755/`
+ (removed again on uninstall). Previously the REST/WebSocket control surface
+ failed with "Access is denied" on every non-Administrator launch. Note for
+ LAN-reachable mode: it still needs its own `http://+:9755/` reservation
+ (the app logs the exact command), and that reservation must be deleted when
+ reverting to loopback-only — while idle it makes http.sys 503 every request.
- **CAB embedded in the MSI** — the installer is a single self-contained
file again; distributing only the MSI no longer fails with error 1302.
diff --git a/installer/Dragon-ISO.Installer.wixproj b/installer/Dragon-ISO.Installer.wixproj
index e286bfe..477bfbb 100644
--- a/installer/Dragon-ISO.Installer.wixproj
+++ b/installer/Dragon-ISO.Installer.wixproj
@@ -39,6 +39,8 @@
-->
+
+
\ No newline at end of file
diff --git a/installer/Package.wxs b/installer/Package.wxs
index 6a65a73..2f0e31d 100644
--- a/installer/Package.wxs
+++ b/installer/Package.wxs
@@ -224,5 +224,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Dragon-ISO.App/Services/ControlSurfaceServer.cs b/src/Dragon-ISO.App/Services/ControlSurfaceServer.cs
index 1f6eb0b..4ed0e26 100644
--- a/src/Dragon-ISO.App/Services/ControlSurfaceServer.cs
+++ b/src/Dragon-ISO.App/Services/ControlSurfaceServer.cs
@@ -97,11 +97,17 @@ public sealed partial class ControlSurfaceServer : IAsyncDisposable
/// "headless show machine + thin client controller" setups. When false
/// (default), binds to 127.0.0.1 only.
///
- /// LAN binding requires either running Dragon-ISO as Administrator OR a
- /// one-time URL ACL reservation at the OS level:
- /// netsh http add urlacl url=http://+:9755/ user=Everyone
- /// If neither is in place the listener throws AccessDeniedException
- /// which we catch and surface as a logger warning.
+ /// Binding requires either running Dragon-ISO as Administrator OR a
+ /// one-time URL ACL reservation at the OS level for the prefix actually
+ /// being bound (the installer reserves the loopback default,
+ /// http://127.0.0.1:9755/):
+ /// netsh http add urlacl url=http://127.0.0.1:9755/ sddl=D:(A;;GX;;;WD)
+ /// or url=http://+:9755/ for LAN mode. CAUTION: an idle
+ /// http://+:port/ reservation makes http.sys 503 every request to
+ /// the loopback-bound listener — only add it while LAN mode is in use,
+ /// and delete it when reverting to loopback-only. If no reservation is
+ /// in place the listener throws AccessDeniedException which we catch and
+ /// surface as a logger warning.
///
public void Start(int port, bool bindToLan = false)
{
@@ -123,9 +129,11 @@ public sealed partial class ControlSurfaceServer : IAsyncDisposable
{
_logger?.LogWarning(ex,
"Could not start control surface on {Prefix}. " +
- "If binding to LAN, run as Administrator once OR run: " +
- "netsh http add urlacl url=http://+:{Port}/ user=Everyone",
- prefix, port);
+ "Run as Administrator once OR reserve the URL namespace: " +
+ "netsh http add urlacl url={UrlAclUrl} sddl=D:(A;;GX;;;WD) " +
+ "(if switching back from LAN mode, also delete the stale " +
+ "http://+:{Port}/ reservation — while idle it 503s the loopback listener)",
+ prefix, prefix, port);
_listener = null;
return;
}