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
>

Reply via email to