{
char *envcpy;
char *cp;
-
- /*
- * Each CRT has its own _putenv() symbol and copy of the environment.
- * Update the environment in each CRT module currently loaded, so every
- * third-party library sees this change regardless of the CRT it links
- * against.
- */
#ifdef _MSC_VER
typedef int (_cdecl * PUTENVPROC) (const char *);
- static struct
- {
- char *modulename;
- HMODULE hmodule;
- PUTENVPROC putenvFunc;
- } rtmodules[] =
- {
- {
- "msvcrt", NULL, NULL
- }, /* Visual Studio 6.0 / MinGW */
- {
- "msvcrtd", NULL, NULL
- },
- {
- "msvcr70", NULL, NULL
- }, /* Visual Studio 2002 */
- {
- "msvcr70d", NULL, NULL
- },
- {
- "msvcr71", NULL, NULL
- }, /* Visual Studio 2003 */
- {
- "msvcr71d", NULL, NULL
- },
- {
- "msvcr80", NULL, NULL
- }, /* Visual Studio 2005 */
- {
- "msvcr80d", NULL, NULL
- },
- {
- "msvcr90", NULL, NULL
- }, /* Visual Studio 2008 */
- {
- "msvcr90d", NULL, NULL
- },
- {
- "msvcr100", NULL, NULL
- }, /* Visual Studio 2010 */
- {
- "msvcr100d", NULL, NULL
- },
- {
- "msvcr110", NULL, NULL
- }, /* Visual Studio 2012 */
- {
- "msvcr110d", NULL, NULL
- },
- {
- "msvcr120", NULL, NULL
- }, /* Visual Studio 2013 */
- {
- "msvcr120d", NULL, NULL
- },
- {
- "ucrtbase", NULL, NULL
- }, /* Visual Studio 2015 and later */
- {
- "ucrtbased", NULL, NULL
- },
- {
- NULL, NULL, NULL
- }
+ static const char *const modulenames[] = {
+ "msvcrt", /* Visual Studio 6.0 / MinGW */
+ "msvcrtd",
+ "msvcr70", /* Visual Studio 2002 */
+ "msvcr70d",
+ "msvcr71", /* Visual Studio 2003 */
+ "msvcr71d",
+ "msvcr80", /* Visual Studio 2005 */
+ "msvcr80d",
+ "msvcr90", /* Visual Studio 2008 */
+ "msvcr90d",
+ "msvcr100", /* Visual Studio 2010 */
+ "msvcr100d",
+ "msvcr110", /* Visual Studio 2012 */
+ "msvcr110d",
+ "msvcr120", /* Visual Studio 2013 */
+ "msvcr120d",
+ "ucrtbase", /* Visual Studio 2015 and later */
+ "ucrtbased",
+ NULL
};
int i;
-
- for (i = 0; rtmodules[i].modulename; i++)
- {
- if (rtmodules[i].putenvFunc == NULL)
- {
- if (rtmodules[i].hmodule == NULL)
- {
- /* 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)
- {
- 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 */
/*
* Update process environment, making this change visible to child
- * processes and to CRTs initializing in the future.
+ * processes and to CRTs initializing in the future. Do this before the
+ * _putenv() loop, for the benefit of any CRT that initializes during this
+ * pgwin32_putenv() execution, after the loop checks that CRT.
*
* Need a copy of the string so we can modify it.
*/
}
free(envcpy);
+ /*
+ * Each CRT has its own _putenv() symbol and copy of the environment.
+ * Update the environment in each CRT module currently loaded, so every
+ * third-party library sees this change regardless of the CRT it links
+ * against. Addresses within these modules may become invalid the moment
+ * we call FreeLibrary(), so don't cache them.
+ */
+#ifdef _MSC_VER
+ for (i = 0; modulenames[i]; i++)
+ {
+ HMODULE hmodule = NULL;
+ BOOL res = GetModuleHandleEx(0, modulenames[i], &hmodule);
+
+ if (res != 0 && hmodule != NULL)
+ {
+ PUTENVPROC putenvFunc;
+
+ putenvFunc = (PUTENVPROC) GetProcAddress(hmodule, "_putenv");
+ if (putenvFunc)
+ putenvFunc(envval);
+ FreeLibrary(hmodule);
+ }
+ }
+#endif /* _MSC_VER */
+
/* Finally, update our "own" cache */
return _putenv(envval);
}