Skip to content

belauncher: Prepend install path for game_exe starting with backslash.#331

Open
PhialsBasement wants to merge 2 commits into
ValveSoftware:proton_11.0from
PhialsBasement:patch-1
Open

belauncher: Prepend install path for game_exe starting with backslash.#331
PhialsBasement wants to merge 2 commits into
ValveSoftware:proton_11.0from
PhialsBasement:patch-1

Conversation

@PhialsBasement
Copy link
Copy Markdown

@PhialsBasement PhialsBasement commented May 24, 2026

belauncher.exe fails to launch the game when a title's BELauncher.ini specifies a 64BitExe= value with a leading backslash (a Win32 "root-relative" path), e.g.:

64BitExe=\Game\Binaries\Win64\Game.exe

The existing guard in programs/belauncher/main.c only prepends the install directory when PathIsRelativeW(game_exeW) returns TRUE, however, PathIsRelativeW returns FALSE for any path whose first character is \ (per the implementation in dlls/kernelbase/path.c)

Reproduced under Proton Experimental (11.0-20260518b) with a title whose BELauncher.ini uses a leading-backslash 64BitExe=. With WINEDEBUG=+belauncher:

trace:belauncher:wWinMain PROTON_ORIG_LAUNCHER_NAME L"S:\common\<Game>\<Game>.exe".
trace:belauncher:wWinMain cmdline L"-XRRuntime=... -d3d11".
trace:belauncher:wWinMain Launching original launcher L"S:\common\<Game>\<Game>.exe".
trace:belauncher:wWinMain Launching game executable \<Game>\Binaries\Win64\<Game>.exe for BattlEye.
trace:belauncher:wWinMain game_exe L"\<Game>\Binaries\Win64\<Game>.exe".
trace:belauncher:wWinMain path L"S:\common\<Game>\", be_arg (null).
trace:belauncher:wWinMain launch_cmd L"\<Game>\Binaries\Win64\<Game>.exe -XRRuntime=... -d3d11".
err:belauncher:wWinMain CreateProcessW failed, error 2.

Note launch_cmd is missing the path prefix, even though path is known and traced one line earlier. The file at S:\common\<Game>\<Game>\Binaries\Win64\<Game>.exe exists; the path Wine actually queried (<current_drive>:\<Game>\Binaries\Win64\<Game>.exe) does not.

Editing the title's BELauncher.ini to remove the leading backslash makes the launch succeed, confirming the diagnosis.

P.S this fixes Contractors Showdown/Exfilzone which is yet another W for the steam frame

PathIsRelativeW() returns FALSE for paths with a leading backslash, so a 64BitExe= entry like "\Game\Binaries\Win64\Game.exe" skipped the install-path prefix in launch_cmd. CreateProcessW then resolved it against the root of the current drive instead of the install directory, yielding ERROR_FILE_NOT_FOUND.

Fixes games like Contractors Showdown (VR), which have opted in to allow linux but have such config
Comment thread programs/belauncher/main.c Outdated
_write(1, &battleye_status, 1);

if (PathIsRelativeW(game_exeW))
if (PathIsRelativeW(game_exeW) || game_exeW[0] == L'\\')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be useful to add a comment about game_exeW[0] == L'\\'.

I'm not a Windows dev, but I searched around and it seems leading backslash is supposed to translate to the root of the disk we're currently in.

That implies the line game_exeW[0] == L'\\' is working around BattleEye bug, where it translates the dir incorrectly (i.e. the game that works on Windows actually wasn't supposed to work there either).

So, I think it's useful to add a comment explaining the situation, i.e. why exactly we do the game_exeW[0] == L'\\' check here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ive just applied some comments to help identify that.

@Etaash-mathamsetty
Copy link
Copy Markdown
Contributor

Etaash-mathamsetty commented May 24, 2026

Maybe it would be better to check if the path is relative on the string + 1 to remove the \ character?

Something like

If (*str = L'\\') str++;

Handle leading backslash for Windows BattlEye game executable paths.
@PhialsBasement
Copy link
Copy Markdown
Author

PhialsBasement commented May 24, 2026

Maybe it would be better to check if the path is relative on the string + 1 to remove the \ character?

Something like

If (*str = L'\\') str++;

Good idea, done with memmove since game_exeW is an array rather than a pointer, plus a game_exeW[1] != L'\\' guard so UNC paths aren't mangled.

@Etaash-mathamsetty
Copy link
Copy Markdown
Contributor

I think using memmove is a bit overkill, just define a second variable that points to the array

@PhialsBasement
Copy link
Copy Markdown
Author

I think using memmove is a bit overkill, just define a second variable that points to the array

I'd prefer to keep the memmove, it leaves game_exeW in a single consistent state after the strip, so later code (here or any future patch) can't go for the original array and get the unstripped form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants