PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
win32env.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * win32env.c
4  * putenv() and unsetenv() for win32, which update both process environment
5  * and caches in (potentially multiple) C run-time library (CRT) versions.
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/port/win32env.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 
17 #include "c.h"
18 
19 int
20 pgwin32_putenv(const char *envval)
21 {
22  char *envcpy;
23  char *cp;
24  typedef int (_cdecl * PUTENVPROC) (const char *);
25  static const char *const modulenames[] = {
26  "msvcrt", /* Visual Studio 6.0 / MinGW */
27  "msvcrtd",
28  "msvcr70", /* Visual Studio 2002 */
29  "msvcr70d",
30  "msvcr71", /* Visual Studio 2003 */
31  "msvcr71d",
32  "msvcr80", /* Visual Studio 2005 */
33  "msvcr80d",
34  "msvcr90", /* Visual Studio 2008 */
35  "msvcr90d",
36  "msvcr100", /* Visual Studio 2010 */
37  "msvcr100d",
38  "msvcr110", /* Visual Studio 2012 */
39  "msvcr110d",
40  "msvcr120", /* Visual Studio 2013 */
41  "msvcr120d",
42  "ucrtbase", /* Visual Studio 2015 and later */
43  "ucrtbased",
44  NULL
45  };
46  int i;
47 
48  /*
49  * Update process environment, making this change visible to child
50  * processes and to CRTs initializing in the future. Do this before the
51  * _putenv() loop, for the benefit of any CRT that initializes during this
52  * pgwin32_putenv() execution, after the loop checks that CRT.
53  *
54  * Need a copy of the string so we can modify it.
55  */
56  envcpy = strdup(envval);
57  if (!envcpy)
58  return -1;
59  cp = strchr(envcpy, '=');
60  if (cp == NULL)
61  {
62  free(envcpy);
63  return -1;
64  }
65  *cp = '\0';
66  cp++;
67  if (strlen(cp))
68  {
69  /*
70  * Only call SetEnvironmentVariable() when we are adding a variable,
71  * not when removing it. Calling it on both crashes on at least
72  * certain versions of MinGW.
73  */
74  if (!SetEnvironmentVariable(envcpy, cp))
75  {
76  free(envcpy);
77  return -1;
78  }
79  }
80  free(envcpy);
81 
82  /*
83  * Each CRT has its own _putenv() symbol and copy of the environment.
84  * Update the environment in each CRT module currently loaded, so every
85  * third-party library sees this change regardless of the CRT it links
86  * against. Addresses within these modules may become invalid the moment
87  * we call FreeLibrary(), so don't cache them.
88  */
89  for (i = 0; modulenames[i]; i++)
90  {
91  HMODULE hmodule = NULL;
92  BOOL res = GetModuleHandleEx(0, modulenames[i], &hmodule);
93 
94  if (res != 0 && hmodule != NULL)
95  {
96  PUTENVPROC putenvFunc;
97 
98  putenvFunc = (PUTENVPROC) GetProcAddress(hmodule, "_putenv");
99  if (putenvFunc)
100  putenvFunc(envval);
101  FreeLibrary(hmodule);
102  }
103  }
104 
105  /*
106  * Finally, update our "own" cache. This is redundant with the loop
107  * above, except when PostgreSQL itself links to a CRT not listed above.
108  * Ideally, the loop does visit all possible CRTs, making this redundant.
109  */
110  return _putenv(envval);
111 }
112 
113 void
114 pgwin32_unsetenv(const char *name)
115 {
116  char *envbuf;
117 
118  envbuf = (char *) malloc(strlen(name) + 2);
119  if (!envbuf)
120  return;
121 
122  sprintf(envbuf, "%s=", name);
123  pgwin32_putenv(envbuf);
124  free(envbuf);
125 }
#define malloc(a)
Definition: header.h:45
#define free(a)
Definition: header.h:60
#define NULL
Definition: c.h:226
const char * name
Definition: encode.c:521
void pgwin32_unsetenv(const char *name)
Definition: win32env.c:114
int i
typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess
int pgwin32_putenv(const char *envval)
Definition: win32env.c:20