diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index b0d6988aff..4d72a6a8c1 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -18,6 +18,7 @@
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <pwd.h>
 #include <unistd.h>
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index f210ccbde8..3503605a7d 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -10,6 +10,7 @@
 #include <ctype.h>
 #include <limits.h>
 #include <math.h>
+#include <pwd.h>
 #include <signal.h>
 #ifndef WIN32
 #include <unistd.h>				/* for write() */
diff --git a/src/include/port.h b/src/include/port.h
index df81fa97c6..3f1716188b 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -14,7 +14,6 @@
 #define PG_PORT_H
 
 #include <ctype.h>
-#include <pwd.h>
 
 /*
  * Windows has enough specialized port stuff that we push most of it off
@@ -478,10 +477,10 @@ extern char *dlerror(void);
 #define RTLD_GLOBAL 0
 #endif
 
-/* thread.h */
+/* thread.c */
 #ifndef WIN32
-extern int	pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
-					   size_t buflen, struct passwd **result);
+extern bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen);
+extern bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen);
 #endif
 
 extern void pg_qsort(void *base, size_t nel, size_t elsize,
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 8d2e4e5db4..aa4534578a 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -35,7 +35,6 @@
 #ifndef  MAXHOSTNAMELEN
 #include <netdb.h>				/* for MAXHOSTNAMELEN on some */
 #endif
-#include <pwd.h>
 #endif
 
 #include "common/md5.h"
@@ -1091,14 +1090,17 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
 
 
 /*
- * pg_fe_getauthname
+ * pg_fe_getusername
  *
- * Returns a pointer to malloc'd space containing whatever name the user
- * has authenticated to the system.  If there is an error, return NULL,
- * and append a suitable error message to *errorMessage if that's not NULL.
+ * Returns a pointer to malloc'd space containing the name of the
+ * specified user_id.  If there is an error, return NULL, and append
+ * a suitable error message to *errorMessage if that's not NULL.
+ *
+ * Caution: on Windows, the user_id argument is ignored, and we always
+ * fetch the current user's name.
  */
 char *
-pg_fe_getauthname(PQExpBuffer errorMessage)
+pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
 {
 	char	   *result = NULL;
 	const char *name = NULL;
@@ -1108,17 +1110,13 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
 	char		username[256 + 1];
 	DWORD		namesize = sizeof(username);
 #else
-	uid_t		user_id = geteuid();
 	char		pwdbuf[BUFSIZ];
-	struct passwd pwdstr;
-	struct passwd *pw = NULL;
-	int			pwerr;
 #endif
 
 	/*
 	 * Some users are using configure --enable-thread-safety-force, so we
 	 * might as well do the locking within our library to protect
-	 * pqGetpwuid(). In fact, application developers can use getpwuid() in
+	 * getpwuid(). In fact, application developers can use getpwuid() in
 	 * their application if they use the locking call we provide, or install
 	 * their own locking function using PQregisterThreadLock().
 	 */
@@ -1132,21 +1130,10 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
 						  libpq_gettext("user name lookup failure: error code %lu\n"),
 						  GetLastError());
 #else
-	pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
-	if (pw != NULL)
-		name = pw->pw_name;
+	if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf)))
+		name = pwdbuf;
 	else if (errorMessage)
-	{
-		if (pwerr != 0)
-			appendPQExpBuffer(errorMessage,
-							  libpq_gettext("could not look up local user ID %d: %s\n"),
-							  (int) user_id,
-							  strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
-		else
-			appendPQExpBuffer(errorMessage,
-							  libpq_gettext("local user with ID %d does not exist\n"),
-							  (int) user_id);
-	}
+		appendPQExpBuffer(errorMessage, "%s\n", pwdbuf);
 #endif
 
 	if (name)
@@ -1162,6 +1149,23 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
 	return result;
 }
 
+/*
+ * pg_fe_getauthname
+ *
+ * Returns a pointer to malloc'd space containing whatever name the user
+ * has authenticated to the system.  If there is an error, return NULL,
+ * and append a suitable error message to *errorMessage if that's not NULL.
+ */
+char *
+pg_fe_getauthname(PQExpBuffer errorMessage)
+{
+#ifdef WIN32
+	return pg_fe_getusername(0, errorMessage);
+#else
+	return pg_fe_getusername(geteuid(), errorMessage);
+#endif
+}
+
 
 /*
  * PQencryptPassword -- exported routine to encrypt a password with MD5
diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h
index 16d5e1da0f..f22b3fe648 100644
--- a/src/interfaces/libpq/fe-auth.h
+++ b/src/interfaces/libpq/fe-auth.h
@@ -20,6 +20,7 @@
 
 /* Prototypes for functions in fe-auth.c */
 extern int	pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn);
+extern char *pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage);
 extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
 
 /* Mechanisms in fe-auth-scram.c */
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index a12e0180fd..5fc16be849 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2813,10 +2813,7 @@ keep_going:						/* We will come back to here until there is
 					IS_AF_UNIX(conn->raddr.addr.ss_family))
 				{
 #ifndef WIN32
-					char		pwdbuf[BUFSIZ];
-					struct passwd pass_buf;
-					struct passwd *pass;
-					int			passerr;
+					char	   *remote_username;
 #endif
 					uid_t		uid;
 					gid_t		gid;
@@ -2839,28 +2836,20 @@ keep_going:						/* We will come back to here until there is
 					}
 
 #ifndef WIN32
-					passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
-					if (pass == NULL)
-					{
-						if (passerr != 0)
-							appendPQExpBuffer(&conn->errorMessage,
-											  libpq_gettext("could not look up local user ID %d: %s\n"),
-											  (int) uid,
-											  strerror_r(passerr, sebuf, sizeof(sebuf)));
-						else
-							appendPQExpBuffer(&conn->errorMessage,
-											  libpq_gettext("local user with ID %d does not exist\n"),
-											  (int) uid);
-						goto error_return;
-					}
+					remote_username = pg_fe_getusername(uid,
+														&conn->errorMessage);
+					if (remote_username == NULL)
+						goto error_return;	/* message already logged */
 
-					if (strcmp(pass->pw_name, conn->requirepeer) != 0)
+					if (strcmp(remote_username, conn->requirepeer) != 0)
 					{
 						appendPQExpBuffer(&conn->errorMessage,
 										  libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
-										  conn->requirepeer, pass->pw_name);
+										  conn->requirepeer, remote_username);
+						free(remote_username);
 						goto error_return;
 					}
+					free(remote_username);
 #else							/* WIN32 */
 					/* should have failed with ENOSYS above */
 					Assert(false);
@@ -7271,16 +7260,7 @@ pqGetHomeDirectory(char *buf, int bufsize)
 
 	home = getenv("HOME");
 	if (home == NULL || home[0] == '\0')
-	{
-		char		pwdbuf[BUFSIZ];
-		struct passwd pwdstr;
-		struct passwd *pwd = NULL;
-
-		(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
-		if (pwd == NULL)
-			return false;
-		home = pwd->pw_dir;
-	}
+		return pg_get_user_home_dir(geteuid(), buf, bufsize);
 	strlcpy(buf, home, bufsize);
 	return true;
 #else
diff --git a/src/port/path.c b/src/port/path.c
index 5ac26f4bcf..69bb8fe40b 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -815,16 +815,7 @@ get_home_path(char *ret_path)
 
 	home = getenv("HOME");
 	if (home == NULL || home[0] == '\0')
-	{
-		char		pwdbuf[BUFSIZ];
-		struct passwd pwdstr;
-		struct passwd *pwd = NULL;
-
-		(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
-		if (pwd == NULL)
-			return false;
-		home = pwd->pw_dir;
-	}
+		return pg_get_user_home_dir(geteuid(), ret_path, MAXPGPATH);
 	strlcpy(ret_path, home, MAXPGPATH);
 	return true;
 #else
diff --git a/src/port/thread.c b/src/port/thread.c
index a4c1672c89..e2a570ec40 100644
--- a/src/port/thread.c
+++ b/src/port/thread.c
@@ -49,6 +49,7 @@
  *	One thread-safe solution for gethostbyname() might be to use getaddrinfo().
  */
 
+#ifndef WIN32
 
 /*
  * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
@@ -60,8 +61,7 @@
  * error during lookup: returns an errno code, *result is NULL
  * (caller should *not* assume that the errno variable is set)
  */
-#ifndef WIN32
-int
+static int
 pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
 		   size_t buflen, struct passwd **result)
 {
@@ -75,4 +75,74 @@ pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
 	return (*result == NULL) ? errno : 0;
 #endif
 }
-#endif
+
+/*
+ * pg_get_user_name - get the name of the user with the given ID
+ *
+ * On success, the user name is returned into the buffer (of size buflen),
+ * and "true" is returned.  On failure, a localized error message is
+ * returned into the buffer, and "false" is returned.
+ */
+bool
+pg_get_user_name(uid_t user_id, char *buffer, size_t buflen)
+{
+	char		pwdbuf[BUFSIZ];
+	struct passwd pwdstr;
+	struct passwd *pw = NULL;
+	int			pwerr;
+
+	pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
+	if (pw != NULL)
+	{
+		strlcpy(buffer, pw->pw_name, buflen);
+		return true;
+	}
+	if (pwerr != 0)
+		snprintf(buffer, buflen,
+				 _("could not look up local user ID %d: %s"),
+				 (int) user_id,
+				 strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
+	else
+		snprintf(buffer, buflen,
+				 _("local user with ID %d does not exist"),
+				 (int) user_id);
+	return false;
+}
+
+/*
+ * pg_get_user_home_dir - get the home directory of the user with the given ID
+ *
+ * On success, the directory path is returned into the buffer (of size buflen),
+ * and "true" is returned.  On failure, a localized error message is
+ * returned into the buffer, and "false" is returned.
+ *
+ * Note that this does not incorporate the common behavior of checking
+ * $HOME first, since it's independent of which user_id is queried.
+ */
+bool
+pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
+{
+	char		pwdbuf[BUFSIZ];
+	struct passwd pwdstr;
+	struct passwd *pw = NULL;
+	int			pwerr;
+
+	pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
+	if (pw != NULL)
+	{
+		strlcpy(buffer, pw->pw_dir, buflen);
+		return true;
+	}
+	if (pwerr != 0)
+		snprintf(buffer, buflen,
+				 _("could not look up local user ID %d: %s"),
+				 (int) user_id,
+				 strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
+	else
+		snprintf(buffer, buflen,
+				 _("local user with ID %d does not exist"),
+				 (int) user_id);
+	return false;
+}
+
+#endif							/* !WIN32 */
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index deb62c1c7b..ec3546d0c0 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -106,7 +106,7 @@ sub mkvcbuild
 	  pread.c preadv.c pwrite.c pwritev.c pg_bitutils.c
 	  pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
 	  pqsignal.c mkdtemp.c qsort.c qsort_arg.c bsearch_arg.c quotes.c system.c
-	  strerror.c tar.c thread.c
+	  strerror.c tar.c
 	  win32env.c win32error.c win32ntdll.c
 	  win32security.c win32setlocale.c win32stat.c);
 
