]> granicus.if.org Git - postgresql/commitdiff
Make the win32 putenv() override update *all* present versions of the
authorMagnus Hagander <magnus@hagander.net>
Fri, 1 Jan 2010 14:57:19 +0000 (14:57 +0000)
committerMagnus Hagander <magnus@hagander.net>
Fri, 1 Jan 2010 14:57:19 +0000 (14:57 +0000)
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

index 9a32387337e4d6bc292927ad5b0740b06f293b06..0578dde81811ba701b32e116bb29d3a14062e527 100644 (file)
@@ -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