My attachment might be scrubbed off by the mailing list. Its available here: https://gist.github.com/jgallimore/aa84b1d580a8ba579e960a709ac1d235.
Thanks Jon On Tue, Apr 16, 2019 at 11:02 AM Jonathan Gallimore < jonathan.gallim...@gmail.com> wrote: > 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 >