Hi, I've been looking at an issue where using a JNI library built with MSVC 14 with TomEE under Windows 2016 as a service with commons-daemon isn't able to pick up environment variables set for the service using getenv().
I note from https://github.com/apache/commons-daemon/tree/master/src/native/windows that the build chain is VC 6 and Platform SDK for Windows Server 2003 R2 - the build with that fails with and error on this line for me: https://github.com/apache/commons-daemon/blob/master/src/native/windows/src/log.c#L61 - if I change "10000000ULL" to "10000000i64", it compiles and links ok. Doing a "dumpbin /headers prunsrv.exe" on the 1.1.0 release shows a linker version of 9.00, and looking at the imports, it uses msvcrt.dll (as opposed to msvcrt800.dll). I'd like to get my build chain as close as possible to what's actually used to create the binaries that are distributed. Is there a more recent buildchain (DDK?) that uses a later compiler/linker, but still uses msvcrt.dll rather than msvcrtXX.dll? While digging further into the issue, it appears that different runtime DLLs effectively get their own copy of the environment, and the JNI library built with VC14 is using ucrtbase.dll for getenv, while commons-daemon is adding entries from to the environment using _wputenv in msvcrt.dll. The attached code demonstrates this. This article looks related as well: https://docs.microsoft.com/en-us/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries?view=vs-2019 I have experimented with dynamically loading ucrtbase.dll and calling its _wputenv() in addition to the _wputenv() call in msvcrt in commons-daemon, and doing nothing if the library or function isn't present. I need to do more testing on this, but my setInprocEnvironment() function looks like this: static void setInprocEnvironment() { LPWSTR p, e; HINSTANCE hinstUcrtLib; WPUTENV wputenv_ucrt; if (!SO_ENVIRONMENT) return; /* Nothing to do */ hinstUcrtLib = LoadLibrary(TEXT("ucrtbase.dll")); if (hinstUcrtLib != NULL) { wputenv_ucrt = (WPUTENV) GetProcAddress(hinstUcrtLib, "_wputenv"); } for (p = SO_ENVIRONMENT; *p; p++) { e = apxExpandStrW(gPool, p); _wputenv(e); if (wputenv_ucrt != NULL) { wputenv_ucrt(e); } apxFree(e); while (*p) p++; } if (hinstUcrtLib != NULL) { FreeLibrary(hinstUcrtLib); } } This does work for my specific use-case, but I don't know if this is a "good" approach, or something that the community would consider adopting. I'd be grateful for feedback, and I'm happy to try different approaches and create patches - I probably just need some pointers. I did also try calling SetEnvironmentVariableW() (which didn't work, although its possible I made a mistake, so I can certainly try it again). Compiling commons-daemon with VC14 did appear to work, but that has the issue of loading in specific versions of msvcrtXX.dll which sounds rather undesirable. Many thanks Jon
--------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org