https://bugs.winehq.org/show_bug.cgi?id=51829
Paul Gofman pgofman@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |pgofman@codeweavers.com
--- Comment #1 from Paul Gofman pgofman@codeweavers.com --- I've debugged the issue.
The part of the blamed commit which changed things for Roblox Player is the change to env.c:create_startup_info(). After the commit the NT path ("\??\C:\...") provided for image name started being converted to DOS path ("C:\..."). Actually before the commit if the path provided to RtlCreateUserProcess() in RTL_USER_PROCESS_PARAMETERS was an NT path the process creation was failing. Things worked in Wine because the higher level Wine create functions are providing DOS path and the direct use of lower level creation functions is very rare. Windows instead fails process creation if DOS path instead of NT path is provided there. So this change is not a bug but an improvement.
After the start Roblox player process tries to create another instance of Roblox launcher (the two previous instances of the launcher started before the Player launch exit soon). That is done by calling RtlCreateUserProcess() with process parameters previously initialized with RtlCreateProcessParameters() with NT path for image (which is actually correct on Windows). Before the blamed commit the new launcher process creation was just failing and somehow Player is fine with that and goes on without delay. Now when the process creation succeeds the process start but exits immediately before completing initialization with intriguing Wine message saying that the executable "is a dll, not an executable". When the process creation succeeded but process does not proceed Player gets stuck for 20 seconds waiting for something before outputting debug messages "WARNING: Infinite yield possible..." and going on.
What is now breaking the process start is the trickery Player does on the newly launcher process before its initialization completed and before the process is resumed. Player preserves the contents of the launcher's main exe image section, unmaps main image sections, allocates anonymous virtual memory at the same address and puts the data back. That all works fine with Wine except for when it gets to ntdll/loader.c:build_main_module() and gets SECTION_IMAGE_INFORMATION for main exe through NtQueryInformationProcess(ProcessImageInformation) it receives the information for ntdll.dll instead of main exe which of course has that DLL flag and fails initialization. That happens because the way of how wineserver's get_process_info() works. When the image mapping is added for the .exe module it is put at the head of views list on the server. All the dll mappings are put at the tail. When process image info is required the first view in the list is taken and the image info is copied from it. But in the present case the main exe view was removed before the user part of initialization was finished.
Storing pe_image_info_t directly in the process structure (put there on first arrival) fixes the issue. The launcher process is created successfully and stays alive through the tormenting by Player process and the game load proceeds without delay.
I am going to do some Windows testing and approach a patch for that.