28{
29 char *envcpy;
30 char *cp;
31 typedef int (_cdecl * PUTENVPROC) (const char *);
32 static const char *const modulenames[] = {
33 "msvcrt", /* Visual Studio 6.0 / MinGW */
34 "msvcrtd",
35 "msvcr70", /* Visual Studio 2002 */
36 "msvcr70d",
37 "msvcr71", /* Visual Studio 2003 */
38 "msvcr71d",
39 "msvcr80", /* Visual Studio 2005 */
40 "msvcr80d",
41 "msvcr90", /* Visual Studio 2008 */
42 "msvcr90d",
43 "msvcr100", /* Visual Studio 2010 */
44 "msvcr100d",
45 "msvcr110", /* Visual Studio 2012 */
46 "msvcr110d",
47 "msvcr120", /* Visual Studio 2013 */
48 "msvcr120d",
49 "ucrtbase", /* Visual Studio 2015 and later */
50 "ucrtbased",
51 NULL
52 };
54
55 /*
56 * Update process environment, making this change visible to child
57 * processes and to CRTs initializing in the future. Do this before the
58 * _putenv() loop, for the benefit of any CRT that initializes during this
59 * pgwin32_putenv() execution, after the loop checks that CRT.
60 *
61 * Need a copy of the string so we can modify it.
62 */
63 envcpy = strdup(envval);
64 if (!envcpy)
65 return -1;
66 cp = strchr(envcpy, '=');
67 if (cp == NULL)
68 {
70 return -1;
71 }
72 *cp = '0円';
73 cp++;
74 if (*cp)
75 {
76 /*
77 * Only call SetEnvironmentVariable() when we are adding a variable,
78 * not when removing it. Calling it on both crashes on at least
79 * certain versions of MinGW.
80 */
81 if (!SetEnvironmentVariable(envcpy, cp))
82 {
84 return -1;
85 }
86 }
88
89 /*
90 * Each CRT has its own _putenv() symbol and copy of the environment.
91 * Update the environment in each CRT module currently loaded, so every
92 * third-party library sees this change regardless of the CRT it links
93 * against. Addresses within these modules may become invalid the moment
94 * we call FreeLibrary(), so don't cache them.
95 */
96 for (
i = 0; modulenames[
i];
i++)
97 {
98 HMODULE hmodule = NULL;
99 BOOL res = GetModuleHandleEx(0, modulenames[
i], &hmodule);
100
101 if (res != 0 && hmodule != NULL)
102 {
103 PUTENVPROC putenvFunc;
104
105 putenvFunc = (PUTENVPROC) (
pg_funcptr_t) GetProcAddress(hmodule,
"_putenv");
106 if (putenvFunc)
107 putenvFunc(envval);
108 FreeLibrary(hmodule);
109 }
110 }
111
112 /*
113 * Finally, update our "own" cache. This is redundant with the loop
114 * above, except when PostgreSQL itself links to a CRT not listed above.
115 * Ideally, the loop does visit all possible CRTs, making this redundant.
116 */
117 return _putenv(envval);
118}
void(* pg_funcptr_t)(void)