From 1c0f0d99ae14428bc6060241f4511eb9446288d0 Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Fri, 1 Jan 2010 14:57:19 +0000 Subject: [PATCH] Make the win32 putenv() override update *all* present versions of the MSVCRxx runtime, not just the current + Visual Studio 6 (MSVCRT). Clearly there can be an almost unlimited number of runtimes loaded at the same time. Per report from Hiroshi Inoue --- src/port/win32env.c | 82 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/src/port/win32env.c b/src/port/win32env.c index 9a32387337..0578dde818 100644 --- a/src/port/win32env.c +++ b/src/port/win32env.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/win32env.c,v 1.3 2009/06/11 14:49:15 momjian Exp $ + * $PostgreSQL: pgsql/src/port/win32env.c,v 1.3.2.1 2010/01/01 14:57:19 mha Exp $ * *------------------------------------------------------------------------- */ @@ -27,30 +27,72 @@ pgwin32_putenv(const char *envval) * Each version of MSVCRT has its own _putenv() call in the runtime * library. * - * If we're in VC 7.0 or later (means != mingw), update in the 6.0 - * MSVCRT.DLL environment as well, to work with third party libraries - * linked against it (such as gnuwin32 libraries). + * mingw always uses MSVCRT.DLL, but if we are in a Visual C++ environment, + * attempt to update the environment in all MSVCRT modules that are + * currently loaded, to work properly with any third party libraries + * linked against a different MSVCRT but still relying on environment + * variables. + * + * Also separately update the system environment that gets inherited by + * subprocesses. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#ifdef _MSC_VER typedef int (_cdecl * PUTENVPROC) (const char *); - HMODULE hmodule; - static PUTENVPROC putenvFunc = NULL; - int ret; + static struct { + char *modulename; + HMODULE hmodule; + PUTENVPROC putenvFunc; + } rtmodules[] = { + { "msvcrt", 0, NULL}, /* Visual Studio 6.0 / mingw */ + { "msvcr70", 0, NULL}, /* Visual Studio 2002 */ + { "msvcr71", 0, NULL}, /* Visual Studio 2003 */ + { "msvcr80", 0, NULL}, /* Visual Studio 2005 */ + { "msvcr90", 0, NULL}, /* Visual Studio 2008 */ + { NULL, 0, NULL} + }; + int i; - if (putenvFunc == NULL) + for (i = 0; rtmodules[i].modulename; i++) { - hmodule = GetModuleHandle("msvcrt"); - if (hmodule == NULL) - return 1; - putenvFunc = (PUTENVPROC) GetProcAddress(hmodule, "_putenv"); - if (putenvFunc == NULL) - return 1; + if (rtmodules[i].putenvFunc == NULL) + { + if (rtmodules[i].hmodule == 0) + { + /* Not attempted before, so try to find this DLL */ + rtmodules[i].hmodule = GetModuleHandle(rtmodules[i].modulename); + if (rtmodules[i].hmodule == NULL) + { + /* + * Set to INVALID_HANDLE_VALUE so we know we have tried this one + * before, and won't try again. + */ + rtmodules[i].hmodule = INVALID_HANDLE_VALUE; + continue; + } + else + { + rtmodules[i].putenvFunc = (PUTENVPROC) GetProcAddress(rtmodules[i].hmodule, "_putenv"); + if (rtmodules[i].putenvFunc == NULL) + { + CloseHandle(rtmodules[i].hmodule); + rtmodules[i].hmodule = INVALID_HANDLE_VALUE; + continue; + } + } + } + else + { + /* + * Module loaded, but we did not find the function last time. We're + * not going to find it this time either... + */ + continue; + } + } + /* At this point, putenvFunc is set or we have exited the loop */ + rtmodules[i].putenvFunc(envval); } - ret = putenvFunc(envval); - if (ret != 0) - return ret; -#endif /* _MSC_VER >= 1300 */ - +#endif /* _MSC_VER */ /* * Update the process environment - to make modifications visible to child