diff --git a/SystemTools.cxx b/SystemTools.cxx
index 0d307396455739e1adae1953153f1a2f7e2d8c58..8e1c96c19d3b8fb092a8325d9032d5dd25839cf8 100644
--- a/SystemTools.cxx
+++ b/SystemTools.cxx
@@ -531,12 +531,6 @@ bool SystemTools::GetEnv(const std::string& key, std::string& result)
 
 //----------------------------------------------------------------------------
 
-#if defined(__CYGWIN__) || defined(__GLIBC__)
-# define KWSYS_PUTENV_NAME  /* putenv("A")  removes A.  */
-#elif defined(_WIN32)
-# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
-#endif
-
 #if KWSYS_CXX_HAS_UNSETENV
 /* unsetenv("A") removes A from the environment.
    On older platforms it returns void instead of int.  */
@@ -555,18 +549,15 @@ static int kwsysUnPutEnv(const std::string& env)
   return 0;
 }
 
-#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
-/* putenv("A=") or putenv("A") removes A from the environment.  */
+#elif defined(__CYGWIN__) || defined(__GLIBC__)
+/* putenv("A") removes A from the environment.  It must not put the
+   memory in the environment because it does not have any "=" syntax.  */
 static int kwsysUnPutEnv(const std::string& env)
 {
   int err = 0;
   size_t pos = env.find('=');
   size_t const len = pos == env.npos ? env.size() : pos;
-# ifdef KWSYS_PUTENV_EMPTY
-  size_t const sz = len + 2;
-# else
   size_t const sz = len + 1;
-# endif
   char local_buf[256];
   char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
   if(!buf)
@@ -574,20 +565,11 @@ static int kwsysUnPutEnv(const std::string& env)
     return -1;
     }
   strncpy(buf, env.c_str(), len);
-# ifdef KWSYS_PUTENV_EMPTY
-  buf[len] = '=';
-  buf[len+1] = 0;
-  if(putenv(buf) < 0)
-    {
-    err = errno;
-    }
-# else
   buf[len] = 0;
   if(putenv(buf) < 0 && errno != EINVAL)
     {
     err = errno;
     }
-# endif
   if(buf != local_buf)
     {
     free(buf);
@@ -600,6 +582,29 @@ static int kwsysUnPutEnv(const std::string& env)
   return 0;
 }
 
+#elif defined(_WIN32)
+/* putenv("A=") places "A=" in the environment, which is as close to
+   removal as we can get with the putenv API.  We have to leak the
+   most recent value placed in the environment for each variable name
+   on program exit in case exit routines access it.  */
+
+static kwsysEnvSet kwsysUnPutEnvSet;
+
+static int kwsysUnPutEnv(std::string env)
+{
+  size_t const pos = env.find('=');
+  size_t const len = pos == env.npos ? env.size() : pos;
+  env.resize(len+1, '=');
+  char* newEnv = strdup(env.c_str());
+  if(!newEnv)
+    {
+    return -1;
+    }
+  kwsysEnvSet::Free oldEnv(kwsysUnPutEnvSet.Release(newEnv));
+  kwsysUnPutEnvSet.insert(newEnv);
+  return putenv(newEnv);
+}
+
 #else
 /* Manipulate the "environ" global directly.  */
 static int kwsysUnPutEnv(const std::string& env)