You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.1KB

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