https://bugs.winehq.org/show_bug.cgi?id=50556
Bug ID: 50556 Summary: Wine-Gecko debug channel 'gecko' doesn't work (win32 API 'SetEnvironmentVariable' has no effect on CRT 'getenv') Product: Wine Version: 6.0 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: mshtml Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
found by chance while checking some issues with Wine-Gecko. Many years ago one had to manually set/export 'NSPR_LOG_MODULES=all:5' environment variable to get more verbosity from Gecko engine.
Since commit https://source.winehq.org/git/wine.git/commitdiff/f9cbbab53b27ab5b9801d56359... ("mshtml: Added gecko debug channel to control Gecko logging."), part of Wine 1.1.12 release, this wasn't necessary anymore.
After that, 'WINEDEBUG=+gecko' achieves the same.
Wine source:
https://source.winehq.org/git/wine.git/blob/2d4dd4252b0cf6526b3cc8194cce642b...
--- snip --- 443 static void set_environment(LPCWSTR gre_path) 444 { 445 size_t len, gre_path_len; 446 int debug_level = 0; 447 WCHAR *path, buf[20]; 448 const WCHAR *ptr; 449 450 SetEnvironmentVariableW(L"XPCOM_DEBUG_BREAK", L"warn"); 451 452 if(TRACE_ON(gecko)) 453 debug_level = 5; 454 else if(WARN_ON(gecko)) 455 debug_level = 2; 456 else if(ERR_ON(gecko)) 457 debug_level = 1; 458 459 swprintf(buf, ARRAY_SIZE(buf), L"all:%d", debug_level); 460 SetEnvironmentVariableW(L"NSPR_LOG_MODULES", buf); 461 462 len = GetEnvironmentVariableW(L"PATH", NULL, 0); 463 gre_path_len = lstrlenW(gre_path); 464 path = heap_alloc((len+gre_path_len+1)*sizeof(WCHAR)); 465 if(!path) 466 return; 467 GetEnvironmentVariableW(L"PATH", path, len); 468 469 /* We have to modify PATH as xul.dll loads other DLLs from this directory. */ 470 if(!(ptr = wcsstr(path, gre_path)) 471 || (ptr > path && *(ptr-1) != ';') 472 || (ptr[gre_path_len] && ptr[gre_path_len] != ';')) { 473 if(len) 474 path[len-1] = ';'; 475 lstrcpyW(path+len, gre_path); 476 SetEnvironmentVariableW(L"PATH", path); 477 } 478 heap_free(path); 479 } --- snip ---
It worked until Wine-Gecko was built with msvcrt/UCRT runtime.
Wine-Gecko 2.47.1, part of Wine 5.0-rc1 release.
https://source.winehq.org/git/wine.git/commitdiff/5f0b5d350566a46f0f999e4cff... ("mshtml: Update to Wine Gecko 2.47.1.")
--- snip --- $ WINEDEBUG=+relay,+gecko wine iexplore.exe ... 031c:Call KERNEL32.SetEnvironmentVariableW(01836084 L"NSPR_LOG_MODULES",0031cfb0 L"all:5") ret=017c2ea1 ... 031c:Ret KERNEL32.SetEnvironmentVariableW() retval=00000001 ret=017c2ea1 ... 031c:Call ucrtbase.getenv(0b5d46b0 "NSPR_LOG_MODULES") ret=0b58b3f9 031c:Ret ucrtbase.getenv() retval=00000000 ret=0b58b3f9 ... --- snip ---
The workaround using external (shell) environment variable:
--- snip --- $ NSPR_LOG_MODULES=all:5 WINEDEBUG=+relay wine iexplore.exe ... 01d0:Call KERNEL32.SetEnvironmentVariableW(01836084 L"NSPR_LOG_MODULES",0031cfb0 L"all:1") ret=017c2ea1 ... 01d0:Ret KERNEL32.SetEnvironmentVariableW() retval=00000001 ret=017c2ea1 ... 01d0:Call ucrtbase.getenv(093d46b0 "NSPR_LOG_MODULES") ret=0938b3f9 01d0:Ret ucrtbase.getenv() retval=001389d6 ret=0938b3f9 01d0:Call ucrtbase.strlen(001389d6 "all:5") ret=09385b52 01d0:Ret ucrtbase.strlen() retval=00000005 ret=09385b52 ... --- snip ---
'getenv' makes a copy of the environment variable block of the process on startup. Any later changes using win32 API 'SetEnvironmentVariable' are not reflected in the block of variables used by 'getenv' by design.
https://source.winehq.org/git/wine.git/blob/2d4dd4252b0cf6526b3cc8194cce642b...
--- snip --- 28 /********************************************************************* 29 * getenv (MSVCRT.@) 30 */ 31 char * CDECL getenv(const char *name) 32 { 33 char **env; 34 unsigned int length=strlen(name); 35 36 for (env = MSVCRT__environ; *env; env++) 37 { 38 char *str = *env; 39 char *pos = strchr(str,'='); 40 if (pos && ((pos - str) == length) && !_strnicmp(str,name,length)) 41 { 42 TRACE("(%s): got %s\n", debugstr_a(name), debugstr_a(pos + 1)); 43 return pos + 1; 44 } 45 } 46 return NULL; 47 } --- snip ---
https://source.winehq.org/git/wine.git/blob/2d4dd4252b0cf6526b3cc8194cce642b...
--- snip --- 402 /* INTERNAL: Since we can't rely on Winelib startup code calling w/getmainargs, 403 * we initialise data values during DLL loading. When called by a native 404 * program we simply return the data we've already initialised. This also means 405 * you can call multiple times without leaking 406 */ 407 void msvcrt_init_args(void) 408 { 409 OSVERSIONINFOW osvi; 410 411 MSVCRT__acmdln = _strdup( GetCommandLineA() ); 412 MSVCRT__wcmdln = _wcsdup( GetCommandLineW() ); 413 initial_wargv = cmdline_to_argv( GetCommandLineW(), &initial_argc ); 414 MSVCRT___argc = initial_argc; 415 MSVCRT___wargv = initial_wargv; 416 MSVCRT___argv = build_argv( initial_wargv ); 417 418 TRACE("got %s, wide = %s argc=%d\n", debugstr_a(MSVCRT__acmdln), 419 debugstr_w(MSVCRT__wcmdln),MSVCRT___argc); 420 421 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); 422 GetVersionExW( &osvi ); 423 MSVCRT__winver = (osvi.dwMajorVersion << 8) | osvi.dwMinorVersion; 424 MSVCRT__winmajor = osvi.dwMajorVersion; 425 MSVCRT__winminor = osvi.dwMinorVersion; 426 MSVCRT__osver = osvi.dwBuildNumber; 427 MSVCRT__osplatform = osvi.dwPlatformId; 428 TRACE( "winver %08x winmajor %08x winminor %08x osver %08x\n", 429 MSVCRT__winver, MSVCRT__winmajor, MSVCRT__winminor, MSVCRT__osver); 430 #ifdef _CRTDLL 431 CRTDLL__baseversion_dll = (GetVersion() >> 16); 432 CRTDLL__basemajor_dll = CRTDLL__baseversion_dll >> 8; 433 CRTDLL__baseminor_dll = CRTDLL__baseversion_dll & 0xff; 434 #endif 435 436 MSVCRT__HUGE = HUGE_VAL; 437 MSVCRT___setlc_active = 0; 438 MSVCRT___unguarded_readlc_active = 0; 439 MSVCRT__fmode = _O_TEXT; 440 441 MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(NULL); 442 MSVCRT___initenv = msvcrt_SnapshotOfEnvironmentA(NULL); 443 MSVCRT___winitenv = msvcrt_SnapshotOfEnvironmentW(NULL); ... --- snip ---
$ wine --version wine-6.0-202-gc7de9f2daa8
Regards
https://bugs.winehq.org/show_bug.cgi?id=50556
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |regression Regression SHA1| |5f0b5d350566a46f0f999e4cff7 | |ad9e280fcfa05
https://bugs.winehq.org/show_bug.cgi?id=50556
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Wine-Gecko debug channel |Wine-Gecko debug channel |'gecko' doesn't work (win32 |'gecko' doesn't work since |API |Wine 5.0-rc1 / Wine-Gecko |'SetEnvironmentVariable' |2.47.1 update (win32 API |has no effect on CRT |'SetEnvironmentVariable' |'getenv') |has no effect on CRT | |'getenv')
https://bugs.winehq.org/show_bug.cgi?id=50556
Jacek Caban jacek@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |jacek@codeweavers.com
--- Comment #1 from Jacek Caban jacek@codeweavers.com --- Good catch, thanks for the report. I think that the right place is to change _PR_InitLog and relevant code in Wine Gecko to use GetEnvironmentVariable instead of getenv. I will look at that.
All pre-2.47.2 versions of Wine Gecko are linked to msvcrt.dll. Current versions link to msvcrt.dll or ucrtbase.dll, depending on the toolchain config (this release allowed using more toolchains, including UCRT-based llvm-mingw). Official builds use UCRT for 2.47.2.
I think that the bug always existed, but it happened to usually work before migration to PE started. Wine itself didn't load msvcrt.dll, so it was loaded by Gecko after mshtml.dll had a chance to set the variable (unless other application modules pulled it already). I didn't test it, but if I'm right:
- it got "broken" when iexplore.exe and later mshtml.dll and others started linking to msvcrt.dll - it got "fixed" by changing Wine builtin components to use UCRT (DLLs first, programs like iexplore later) - it got "broken" again by Gecko 2.47.2 release, which moved to Gecko UCRT as well