Subj : src/doors/syncconquer/CMakeLists.txt PROVENANCE.md src/doors/syncconqu To : Git commit to main/sbbs/master From : Rob Swindell (on Windows 11) Date : Fri Jul 10 2026 03:28:50 https://gitlab.synchro.net/main/sbbs/-/commit/37de0f10359177f53b344452 Modified Files: src/doors/syncconquer/CMakeLists.txt PROVENANCE.md src/doors/syncconquer/door/door_io.c src/doors/syncconquer/vanilla/common/utfargs.h src/doors/syncconquer/vanilla/redalert/startup.cpp Log Message: syncalert: fix four Windows-only defects that broke the door end to end The door's first-ever Windows build surfaced four bugs, each invisible on *nix. Two are in our code, two in the vendored engine's Windows-without-SDL path -- which upstream never compiles, because its Windows build always defines SDL_BUILD. All four date from f5578ea57f (foam-43-clip), where the door landed and was only ever built for *nix. 1. setvbuf(stderr, NULL, _IOLBF, 0) fast-failed the process before it could log a thing: MSVC's CRT requires 2 <= size <= INT_MAX for _IOLBF/_IOFBF, so size 0 is an invalid parameter and, with no handler installed, __fastfail()s (c0000409, FAST_FAIL_INVALID_ARG, straight through ucrtbase!_invoke_watson). glibc ignores the size. Launching the door dumped the caller back to the BBS with a zero-byte node log. Use _IONBF on Windows: valid with size 0, and it flushes every write -- the crash-durability the comment promises, which _IOLBF would not have delivered there anyway (that CRT silently treats it as _IOFBF). syncduke fixed the identical fast-fail in 705a840fe9 (panel-11-mind); syncconquer had copied the pre-fix idiom. 2. Winsock was only ever initialized from door_early_write(), which runs on failure paths (the missing-assets splash). syncduke gets away with the same placement because its constructor calls its splash unconditionally. Here, a healthy launch never called WSAStartup() and died on its first recv() with WSANOTINITIALISED (10093), which the pump reads as a client hangup -- again dropping the user back to the BBS. Hoist it into an idempotent door_wsa_ensure() called from the pre-main constructor. xpdev's sockwrap does not self-init Winsock. 3. redalert/startup.cpp's `UtfArgs args(argc, argv)` replaces ArgV with a fresh CommandLineToArgvU(GetCommandLineW()) parse, discarding the argv door_sanitize_argv() rewrote in the constructor. So -NOMOVIES never reached the engine (the intro and mission FMV played, with music but no dialog audio -- vqaaudio_null.cpp stubs the VQA player's audio hooks), and the door's own -s/-home tokens reached Parse_Command_Line(), whose strstr() substring scan over every token can mis-set an engine option from an unrelated path. utfargs.h now honors SYNCALERT_KEEP_CRT_ARGV, defined for VanillaRA only. UNICODE/_UNICODE stay on, so common/'s UTF-8 path handling is untouched; only the argv re-derivation is skipped. 4. "Exit Game" hung forever. main() sets ReadyToQuit = 1, posts WM_DESTROY to MainWindow, then spins on Keyboard->Check() until winstub.cpp's window procedure advances it. The headless door has no window (MainWindow is NULL) and no message pump, so nothing ever did: the process stayed alive burning CPU in door_io_pump()'s recv(), the terminal kept looping its music, and no frames were drawn. Emergency_Exit()'s ReadyToQuit == 3 spin would hang the same way. Both are now gated on !NEW_VIDEO_BUILD, which upstream sets for exactly the backends (SDL1/SDL2) that have no legacy WndProc -- a no-op for every upstream configuration. Also close the door's own console window on Windows. Synchronet spawns a native door with CREATE_NEW_CONSOLE, so a console pops up on the BBS machine each session; the door draws to the client's terminal and logs to data/syncalert/syncalert_n.log, so it is pure noise. Detach only when we own the console exclusively (GetConsoleProcessList() == 1) -- a developer running the door from a shell shares that shell's console and must not lose stdout -- and only with a door socket. FreeConsole() invalidates all three std streams even when stderr already points at a file, so it runs BEFORE the node log is opened and re-points every stream at NUL (the engine still printf()s on some paths). Vendored patches 10 and 11 recorded in PROVENANCE.md. Verified on Windows (VS2022, Win32/Release) and by Rob against the live BBS: the door launches, plays with audio, shows no movies, and exits cleanly. The engine-argv fix confirmed under cdb (argv[1] "-s999" -> "-NOMOVIES"; bNoMovies 00 -> 01 across Parse_Command_Line); the console detach confirmed against a CREATE_NEW_CONSOLE / CREATE_NO_WINDOW launcher, with the node log intact in both. Not compiled by GCC/Clang. Co-Authored-By: Claude Opus 4.8 (1M context) --- þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net .