summaryrefslogtreecommitdiff
path: root/src/port/win32env.c
diff options
context:
space:
mode:
authorMagnus Hagander2010-01-01 14:57:16 +0000
committerMagnus Hagander2010-01-01 14:57:16 +0000
commit741e4ad7de9e0069533d90efdd5b1fc9f3a64c81 (patch)
tree070196ffa83f237f91d7b403a90e859ab0a9077a /src/port/win32env.c
parent2aff8c422eaf27df15f55a75660e747c5d39b664 (diff)
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
Diffstat (limited to 'src/port/win32env.c')
-rw-r--r--src/port/win32env.c82
1 files changed, 60 insertions, 22 deletions
diff --git a/src/port/win32env.c b/src/port/win32env.c
index 6f15433078e..2aa448eef2d 100644
--- a/src/port/win32env.c
+++ b/src/port/win32env.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/port/win32env.c,v 1.5 2009/12/27 16:11:28 mha Exp $
+ * $PostgreSQL: pgsql/src/port/win32env.c,v 1.6 2010/01/01 14:57:16 mha Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,34 +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;
+ 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)
+ if (rtmodules[i].putenvFunc == NULL)
{
- /*
- * If the module is found, attempt to find the function. If not, that just
- * means we're not linked with msvcrt, so fall through and make our other
- * modifications anyway.
- * Ignore any errors and update whatever we can, since callers don't
- * check the return value anyway.
- */
- putenvFunc = (PUTENVPROC) GetProcAddress(hmodule, "_putenv");
- if (putenvFunc != NULL)
- putenvFunc(envval);
+ 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);
}
-#endif /* _MSC_VER >= 1300 */
-
+#endif /* _MSC_VER */
/*
* Update the process environment - to make modifications visible to child