From 49ca06e0042caf5c5264aed91f8f38f062dacb60 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Tue, 6 Sep 2016 16:02:00 +0900
Subject: [PATCH 3/3] Pin any DLL as soon as seen when looking for _putenv on
 Windows

This prevents the DLL to be unloaded, and maintains the load until the
process is terminated.
---
 src/port/win32env.c | 54 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 19 deletions(-)

diff --git a/src/port/win32env.c b/src/port/win32env.c
index 3f56ba8..ed20f1c 100644
--- a/src/port/win32env.c
+++ b/src/port/win32env.c
@@ -43,36 +43,37 @@ pgwin32_putenv(const char *envval)
 		char	   *modulename;
 		HMODULE		hmodule;
 		PUTENVPROC	putenvFunc;
+		bool		pinned;
 	}			rtmodules[] =
 	{
 		/* Visual Studio 6.0 / mingw */
-		{"msvcrt",		NULL,	NULL},
-		{"msvcrtd",		NULL,	NULL},
+		{"msvcrt",		NULL,	NULL,	false},
+		{"msvcrtd",		NULL,	NULL,	false},
 		/* Visual Studio 2002 */
-		{"msvcr70",		NULL,	NULL},
-		{"msvcr70d",	NULL,	NULL},
+		{"msvcr70",		NULL,	NULL,	false},
+		{"msvcr70d",	NULL,	NULL,	false},
 		/* Visual Studio 2003 */
-		{"msvcr71",		NULL,	NULL},
-		{"msvcr71d",	NULL,	NULL},
+		{"msvcr71",		NULL,	NULL,	false},
+		{"msvcr71d",	NULL,	NULL,	false},
 		/* Visual Studio 2005 */
-		{"msvcr80",		NULL,	NULL},
-		{"msvcr80d",	NULL,	NULL},
+		{"msvcr80",		NULL,	NULL,	false},
+		{"msvcr80d",	NULL,	NULL,	false},
 		/* Visual Studio 2008 */
-		{"msvcr90",		NULL,	NULL},
-		{"msvcr90d",	NULL,	NULL},
+		{"msvcr90",		NULL,	NULL,	false},
+		{"msvcr90d",	NULL,	NULL,	false},
 		/* Visual Studio 2010 */
-		{"msvcr100",	NULL,	NULL},
-		{"msvcr100d",	NULL,	NULL},
+		{"msvcr100",	NULL,	NULL,	false},
+		{"msvcr100d",	NULL,	NULL,	false},
 		/* Visual Studio 2012 */
-		{"msvcr110",	NULL,	NULL},
-		{"msvcr110d",	NULL,	NULL},
+		{"msvcr110",	NULL,	NULL,	false},
+		{"msvcr110d",	NULL,	NULL,	false},
 		/* Visual Studio 2013 */
-		{"msvcr120",	NULL,	NULL},
-		{"msvcr120d",	NULL,	NULL},
+		{"msvcr120",	NULL,	NULL,	false},
+		{"msvcr120d",	NULL,	NULL,	false},
 		/* Visual Studio 2015 and later */
-		{"ucrtbase",	NULL,	NULL},
-		{"ucrtbased",	NULL,	NULL},
-		{NULL,			NULL,	NULL}
+		{"ucrtbase",	NULL,	NULL,	false},
+		{"ucrtbased",	NULL,	NULL,	false},
+		{NULL,			NULL,	NULL,	false}
 	};
 	int			i;
 
@@ -90,6 +91,21 @@ pgwin32_putenv(const char *envval)
 				}
 				else
 				{
+					/*
+					 * Pin this DLL handle as soon as possible to avoid it
+					 * to be unloaded until the process terminates.
+					 */
+					if (!rtmodules[i].pinned)
+					{
+						HMODULE tmp;
+						bool res = GetModuleHandleEx(
+								GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+									| GET_MODULE_HANDLE_EX_FLAG_PIN,
+								(LPCTSTR)rtmodules[i].hmodule,
+								&tmp);
+						rtmodules[i].pinned = (res != NULL);
+					}
+
 					rtmodules[i].putenvFunc = (PUTENVPROC) GetProcAddress(rtmodules[i].hmodule, "_putenv");
 					if (rtmodules[i].putenvFunc == NULL)
 					{
-- 
2.10.0

