diff --git a/configure.in b/configure.in
index fc9c52f83d2c792a76945712c86883883f7e67cf..52357a6bba3e48d1956733cfa7cae9c96666d03c 100644
--- a/configure.in
+++ b/configure.in
@@ -1353,6 +1353,7 @@ if test "$PORTNAME" = "win32"; then
   AC_REPLACE_FUNCS(gettimeofday)
   AC_LIBOBJ(kill)
   AC_LIBOBJ(open)
+  AC_LIBOBJ(system)
   AC_LIBOBJ(win32env)
   AC_LIBOBJ(win32error)
   AC_LIBOBJ(win32setlocale)
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 56e912d8c3d9e775c371c8b1c9c09e06d5a1693a..d22b6d38e291da113c796833ec651ed57fbfc7fa 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -970,7 +970,7 @@ get_bin_version(ClusterInfo *cluster)
 	int			pre_dot,
 				post_dot;
 
-	snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" --version" SYSTEMQUOTE, cluster->bindir);
+	snprintf(cmd, sizeof(cmd), "\"%s/pg_ctl\" --version", cluster->bindir);
 
 	if ((output = popen(cmd, "r")) == NULL ||
 		fgets(cmd_output, sizeof(cmd_output), output) == NULL)
diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
index fa0a0053bab4bebfe24b1086774075ba06fcee1f..476c6be276e0efd317be6e98f30b8f42050dfb2b 100644
--- a/contrib/pg_upgrade/controldata.c
+++ b/contrib/pg_upgrade/controldata.c
@@ -110,7 +110,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
 	pg_putenv("LC_ALL", NULL);
 	pg_putenv("LC_MESSAGES", "C");
 
-	snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE,
+	snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"",
 			 cluster->bindir,
 			 live_check ? "pg_controldata\"" : "pg_resetxlog\" -n",
 			 cluster->pgdata);
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 7f013013a0653f9373b0be9fa665cd43cfc1a8a3..91e66e6ecf465766ef88558754d3989384d4aeae 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -59,14 +59,14 @@ static DWORD       mainThreadId = 0;
 		mainThreadId = GetCurrentThreadId();
 #endif
 
-	written = strlcpy(cmd, SYSTEMQUOTE, sizeof(cmd));
+	written = 0;
 	va_start(ap, fmt);
 	written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
 	va_end(ap);
 	if (written >= MAXCMDLEN)
 		pg_fatal("command too long\n");
 	written += snprintf(cmd + written, MAXCMDLEN - written,
-						" >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
+						" >> \"%s\" 2>&1", log_file);
 	if (written >= MAXCMDLEN)
 		pg_fatal("command too long\n");
 
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index b53fa8bd088e6480625e26418ea686694c73a6f3..83b7f6e24d872ae8e796b3636f8a210c50f793c8 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1130,11 +1130,11 @@ test_config_settings(void)
 		test_buffs = MIN_BUFS_FOR_CONNS(test_conns);
 
 		snprintf(cmd, sizeof(cmd),
-				 SYSTEMQUOTE "\"%s\" --boot -x0 %s "
+				 "\"%s\" --boot -x0 %s "
 				 "-c max_connections=%d "
 				 "-c shared_buffers=%d "
 				 "-c dynamic_shared_memory_type=none "
-				 "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+				 "< \"%s\" > \"%s\" 2>&1",
 				 backend_exec, boot_options,
 				 test_conns, test_buffs,
 				 DEVNULL, DEVNULL);
@@ -1165,11 +1165,11 @@ test_config_settings(void)
 		}
 
 		snprintf(cmd, sizeof(cmd),
-				 SYSTEMQUOTE "\"%s\" --boot -x0 %s "
+				 "\"%s\" --boot -x0 %s "
 				 "-c max_connections=%d "
 				 "-c shared_buffers=%d "
 				 "-c dynamic_shared_memory_type=none "
-				 "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+				 "< \"%s\" > \"%s\" 2>&1",
 				 backend_exec, boot_options,
 				 n_connections, test_buffs,
 				 DEVNULL, DEVNULL);
@@ -1503,7 +1503,7 @@ bootstrap_template1(void)
 	unsetenv("PGCLIENTENCODING");
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" --boot -x1 %s %s %s" SYSTEMQUOTE,
+			 "\"%s\" --boot -x1 %s %s %s",
 			 backend_exec,
 			 data_checksums ? "-k" : "",
 			 boot_options, talkargs);
@@ -1544,7 +1544,7 @@ setup_auth(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -1622,7 +1622,7 @@ get_set_pwd(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -1722,7 +1722,7 @@ setup_depend(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -1755,7 +1755,7 @@ setup_sysviews(void)
 	 * We use -j here to avoid backslashing stuff in system_views.sql
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s -j template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s -j template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -1786,7 +1786,7 @@ setup_description(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -1893,7 +1893,7 @@ setup_collation(void)
 
 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2038,7 +2038,7 @@ setup_conversion(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2076,7 +2076,7 @@ setup_dictionary(void)
 	 * We use -j here to avoid backslashing stuff
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s -j template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s -j template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2127,7 +2127,7 @@ setup_privileges(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2190,7 +2190,7 @@ setup_schema(void)
 	 * We use -j here to avoid backslashing stuff in information_schema.sql
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s -j template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s -j template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2207,7 +2207,7 @@ setup_schema(void)
 	PG_CMD_CLOSE;
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2241,7 +2241,7 @@ load_plpgsql(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2266,7 +2266,7 @@ vacuum_db(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2322,7 +2322,7 @@ make_template0(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
@@ -2354,7 +2354,7 @@ make_postgres(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+			 "\"%s\" %s template1 >%s",
 			 backend_exec, backend_options,
 			 DEVNULL);
 
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index fc87e7d76ed166af23cf83fa91991211605af409..473d6534064c69ad74cbea480de6415040369d56 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -435,11 +435,11 @@ start_postmaster(void)
 	 * the PID without having to rely on reading it back from the pidfile.
 	 */
 	if (log_file != NULL)
-		snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &" SYSTEMQUOTE,
+		snprintf(cmd, MAXPGPATH, "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &",
 				 exec_path, pgdata_opt, post_opts,
 				 DEVNULL, log_file);
 	else
-		snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1 &" SYSTEMQUOTE,
+		snprintf(cmd, MAXPGPATH, "\"%s\" %s%s < \"%s\" 2>&1 &",
 				 exec_path, pgdata_opt, post_opts, DEVNULL);
 
 	return system(cmd);
@@ -453,10 +453,10 @@ start_postmaster(void)
 	PROCESS_INFORMATION pi;
 
 	if (log_file != NULL)
-		snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
+		snprintf(cmd, MAXPGPATH, "CMD /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"",
 				 exec_path, pgdata_opt, post_opts, DEVNULL, log_file);
 	else
-		snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1" SYSTEMQUOTE,
+		snprintf(cmd, MAXPGPATH, "CMD /C \"\"%s\" %s%s < \"%s\" 2>&1\"",
 				 exec_path, pgdata_opt, post_opts, DEVNULL);
 
 	if (!CreateRestrictedProcess(cmd, &pi, false))
@@ -814,10 +814,10 @@ do_init(void)
 		post_opts = "";
 
 	if (!silent_mode)
-		snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s" SYSTEMQUOTE,
+		snprintf(cmd, MAXPGPATH, "\"%s\" %s%s",
 				 exec_path, pgdata_opt, post_opts);
 	else
-		snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s > \"%s\"" SYSTEMQUOTE,
+		snprintf(cmd, MAXPGPATH, "\"%s\" %s%s > \"%s\"",
 				 exec_path, pgdata_opt, post_opts, DEVNULL);
 
 	if (system(cmd) != 0)
@@ -2035,7 +2035,7 @@ adjust_data_dir(void)
 		my_exec_path = pg_strdup(exec_path);
 
 	/* it's important for -C to be the first option, see main.c */
-	snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" -C data_directory %s%s" SYSTEMQUOTE,
+	snprintf(cmd, MAXPGPATH, "\"%s\" -C data_directory %s%s",
 			 my_exec_path,
 			 pgdata_opt ? pgdata_opt : "",
 			 post_opts ? post_opts : "");
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 47fe6ccc07f357c36c40a162c9eb1fc83568fd6e..208e49bbcd060d1db8a917f74d161145689b897e 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -1666,7 +1666,7 @@ runPgDump(const char *dbname)
 	PQExpBuffer cmd = createPQExpBuffer();
 	int			ret;
 
-	appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s", pg_dump_bin,
+	appendPQExpBuffer(cmd, "\"%s\" %s", pg_dump_bin,
 					  pgdumpopts->data);
 
 	/*
@@ -1687,8 +1687,6 @@ runPgDump(const char *dbname)
 
 	doShellQuoting(cmd, connstrbuf->data);
 
-	appendPQExpBufferStr(cmd, SYSTEMQUOTE);
-
 	if (verbose)
 		fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
 
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index fd64ba824f1dd4f95f25241b93489fa85dd0d91a..dabcd680fffcf7705e8b9e8c92bbe69c92d7f4f6 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1936,10 +1936,10 @@ editFile(const char *fname, int lineno)
 					editorName, fname);
 #else
 	if (lineno > 0)
-		sys = psprintf(SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
+		sys = psprintf("\"%s\" %s%d \"%s\"",
 				editorName, editor_lineno_arg, lineno, fname);
 	else
-		sys = psprintf(SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
+		sys = psprintf("\"%s\" \"%s\"",
 					editorName, fname);
 #endif
 	result = system(sys);
@@ -2643,7 +2643,7 @@ do_shell(const char *command)
 #ifndef WIN32
 		sys = psprintf("exec %s", shellName);
 #else
-		sys = psprintf(SYSTEMQUOTE "\"%s\"" SYSTEMQUOTE, shellName);
+		sys = psprintf("\"%s\"", shellName);
 #endif
 		result = system(sys);
 		free(sys);
diff --git a/src/include/port.h b/src/include/port.h
index 06986858b60d88d459190f1e2ca8918618da9882..21c8a05d0baf13dbcc58813a457b55b9bc87ada2 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -115,37 +115,6 @@ extern BOOL AddUserToTokenDacl(HANDLE hToken);
 #define DEVNULL "/dev/null"
 #endif
 
-/*
- *	Win32 needs double quotes at the beginning and end of system()
- *	strings.  If not, it gets confused with multiple quoted strings.
- *	It also requires double-quotes around the executable name and
- *	any files used for redirection.  Other args can use single-quotes.
- *
- *	Generated using Win32 "CMD /?":
- *
- *	1. If all of the following conditions are met, then quote characters
- *	on the command line are preserved:
- *
- *	 - no /S switch
- *	 - exactly two quote characters
- *	 - no special characters between the two quote characters, where special
- *	   is one of: &<>()@^|
- *	 - there are one or more whitespace characters between the two quote
- *	   characters
- *	 - the string between the two quote characters is the name of an
- *	   executable file.
- *
- *	 2. Otherwise, old behavior is to see if the first character is a quote
- *	 character and if so, strip the leading character and remove the last
- *	 quote character on the command line, preserving any text after the last
- *	 quote character.
- */
-#if defined(WIN32) && !defined(__CYGWIN__)
-#define SYSTEMQUOTE "\""
-#else
-#define SYSTEMQUOTE ""
-#endif
-
 /* Portable delay handling */
 extern void pg_usleep(long microsec);
 
@@ -332,12 +301,16 @@ extern FILE *pgwin32_fopen(const char *, const char *);
 #define		fopen(a,b) pgwin32_fopen(a,b)
 #endif
 
-#ifndef popen
-#define popen(a,b) _popen(a,b)
-#endif
-#ifndef pclose
+/*
+ * system() and popen() replacements to enclose the command in an extra
+ * pair of quotes.
+ */
+extern int pgwin32_system(const char *command);
+extern FILE *pgwin32_popen(const char *command, const char *type);
+
+#define system(a) pgwin32_system(a)
+#define popen(a,b) pgwin32_popen(a,b)
 #define pclose(a) _pclose(a)
-#endif
 
 /* New versions of MingW have gettimeofday, old mingw and msvc don't */
 #ifndef HAVE_GETTIMEOFDAY
diff --git a/src/interfaces/ecpg/test/pg_regress_ecpg.c b/src/interfaces/ecpg/test/pg_regress_ecpg.c
index cb79b61b2d5c5a885581c0c5266dc633d9cc69e4..e9bedb5c75d30c73e44b4138817b9cd7630d317b 100644
--- a/src/interfaces/ecpg/test/pg_regress_ecpg.c
+++ b/src/interfaces/ecpg/test/pg_regress_ecpg.c
@@ -137,7 +137,7 @@ ecpg_start_test(const char *testname,
 	snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
 
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "\"%s\" >\"%s\" 2>\"%s\"" SYSTEMQUOTE,
+			 "\"%s\" >\"%s\" 2>\"%s\"",
 			 inprg,
 			 outfile_stdout,
 			 outfile_stderr);
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 7f2d901111c1559e8e0e81fb2bb7f3a8a7e45fef..2b770d0a7215a61298a829191f6c9d839c5fdc13 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -38,7 +38,7 @@ OBJS=	fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
 OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \
 	thread.o
 # libpgport C files that are needed if identified by configure
-OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o snprintf.o strerror.o strlcpy.o win32error.o win32setlocale.o, $(LIBOBJS))
+OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strerror.o strlcpy.o win32error.o win32setlocale.o, $(LIBOBJS))
 # backend/libpq
 OBJS += ip.o md5.o
 # utils/mb
@@ -89,7 +89,7 @@ backend_src = $(top_srcdir)/src/backend
 # For some libpgport modules, this only happens if configure decides
 # the module is needed (see filter hack in OBJS, above).
 
-chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c pgsleep.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
+chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
 	rm -f $@ && $(LN_S) $< .
 
 ip.c md5.c: % : $(backend_src)/libpq/%
@@ -150,7 +150,7 @@ clean distclean: clean-lib
 # Might be left over from a Win32 client-only build
 	rm -f pg_config_paths.h
 	rm -f inet_net_ntop.c noblock.c pgstrcasecmp.c pqsignal.c thread.c
-	rm -f chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c open.c snprintf.c strerror.c strlcpy.c win32error.c win32setlocale.c
+	rm -f chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c open.c system.c snprintf.c strerror.c strlcpy.c win32error.c win32setlocale.c
 	rm -f pgsleep.c
 	rm -f md5.c ip.c
 	rm -f encnames.c wchar.c
diff --git a/src/interfaces/libpq/bcc32.mak b/src/interfaces/libpq/bcc32.mak
index 8f5cd8de470d24f6f39f629c24bbcd0a6324c0f7..78102fafd45c948a93bff59100677ddd728fdf53 100644
--- a/src/interfaces/libpq/bcc32.mak
+++ b/src/interfaces/libpq/bcc32.mak
@@ -106,6 +106,7 @@ CLEAN :
 	-@erase "$(INTDIR)\dirmod.obj"
 	-@erase "$(INTDIR)\pgsleep.obj"
 	-@erase "$(INTDIR)\open.obj"
+	-@erase "$(INTDIR)\system.obj"
 	-@erase "$(INTDIR)\win32error.obj"
 	-@erase "$(OUTDIR)\$(OUTFILENAME).lib"
 	-@erase "$(OUTDIR)\$(OUTFILENAME)dll.lib"
@@ -149,6 +150,7 @@ LIB32_OBJS= \
 	"$(INTDIR)\dirmod.obj" \
 	"$(INTDIR)\pgsleep.obj" \
 	"$(INTDIR)\open.obj" \
+	"$(INTDIR)\system.obj" \
 	"$(INTDIR)\win32error.obj" \
 	"$(INTDIR)\pthread-win32.obj"
 
@@ -295,6 +297,11 @@ LINK32_FLAGS = -Gn -L$(BCB)\lib;$(INTDIR); -x -Tpd -v
 	$(CPP_PROJ) /I"." ..\..\port\open.c
 <<
 
+"$(INTDIR)\system.obj" : ..\..\port\system.c
+	$(CPP) @<<
+	$(CPP_PROJ) /I"." ..\..\port\system.c
+<<
+
 "$(INTDIR)\win32error.obj" : ..\..\port\win32error.c
 	$(CPP) @<<
 	$(CPP_PROJ) /I"." ..\..\port\win32error.c
diff --git a/src/interfaces/libpq/win32.mak b/src/interfaces/libpq/win32.mak
index ee1884fe201125c9ba1b2d260a879596a0efb174..23e09e981006bf11127d58910a92953814ae3deb 100644
--- a/src/interfaces/libpq/win32.mak
+++ b/src/interfaces/libpq/win32.mak
@@ -113,6 +113,7 @@ CLEAN :
 	-@erase "$(INTDIR)\dirmod.obj"
 	-@erase "$(INTDIR)\pgsleep.obj"
 	-@erase "$(INTDIR)\open.obj"
+	-@erase "$(INTDIR)\system.obj"
 	-@erase "$(INTDIR)\win32error.obj"
 	-@erase "$(INTDIR)\win32setlocale.obj"
 	-@erase "$(OUTDIR)\$(OUTFILENAME).lib"
@@ -159,6 +160,7 @@ LIB32_OBJS= \
 	"$(INTDIR)\dirmod.obj" \
 	"$(INTDIR)\pgsleep.obj" \
 	"$(INTDIR)\open.obj" \
+	"$(INTDIR)\system.obj" \
 	"$(INTDIR)\win32error.obj" \
 	"$(INTDIR)\win32setlocale.obj" \
 	"$(INTDIR)\pthread-win32.obj"
@@ -335,6 +337,11 @@ LINK32_OBJS= \
 	$(CPP_PROJ) /I"." ..\..\port\open.c
 <<
 
+"$(INTDIR)\system.obj" : ..\..\port\system.c
+	$(CPP) @<<
+	$(CPP_PROJ) /I"." ..\..\port\system.c
+<<
+
 "$(INTDIR)\win32error.obj" : ..\..\port\win32error.c
 	$(CPP) @<<
 	$(CPP_PROJ) /I"." ..\..\port\win32error.c
diff --git a/src/port/system.c b/src/port/system.c
new file mode 100644
index 0000000000000000000000000000000000000000..f9c525dfbfcaa2519e6dda5daf4514c25e9da964
--- /dev/null
+++ b/src/port/system.c
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * system.c
+ *	   Win32 system() and popen() replacements
+ *
+ *
+ *	Win32 needs double quotes at the beginning and end of system()
+ *	strings.  If not, it gets confused with multiple quoted strings.
+ *	It also requires double-quotes around the executable name and
+ *	any files used for redirection.  Other args can use single-quotes.
+ *
+ *	Generated using Win32 "CMD /?":
+ *
+ *	1. If all of the following conditions are met, then quote characters
+ *	on the command line are preserved:
+ *
+ *	 - no /S switch
+ *	 - exactly two quote characters
+ *	 - no special characters between the two quote characters, where special
+ *	   is one of: &<>()@^|
+ *	 - there are one or more whitespace characters between the two quote
+ *	   characters
+ *	 - the string between the two quote characters is the name of an
+ *	   executable file.
+ *
+ *	 2. Otherwise, old behavior is to see if the first character is a quote
+ *	 character and if so, strip the leading character and remove the last
+ *	 quote character on the command line, preserving any text after the last
+ *	 quote character.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ *
+ * src/port/system.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <windows.h>
+#include <fcntl.h>
+
+#undef system
+#undef popen
+
+int
+pgwin32_system(const char *command)
+{
+	size_t		cmdlen = strlen(command);
+	char	   *buf;
+	int			save_errno;
+	int			res;
+
+	/*
+	 * Create a malloc'd copy of the command string, enclosed with an extra
+	 * pair of quotes
+	 */
+	buf = malloc(cmdlen + 2 + 1);
+	if (buf == NULL)
+	{
+		errno = ENOMEM;
+		return -1;
+	}
+	buf[0] = '"';
+	memcpy(&buf[1], command, cmdlen);
+	buf[cmdlen + 1] = '"';
+	buf[cmdlen + 2] = '\0';
+
+	res = system(buf);
+
+	save_errno = errno;
+	free(buf);
+	errno = save_errno;
+
+	return res;
+}
+
+
+FILE *
+pgwin32_popen(const char *command, const char *type)
+{
+	size_t		cmdlen = strlen(command);
+	char	   *buf;
+	int			save_errno;
+	FILE	   *res;
+
+	/*
+	 * Create a malloc'd copy of the command string, enclosed with an extra
+	 * pair of quotes
+	 */
+	buf = malloc(cmdlen + 2 + 1);
+	if (buf == NULL)
+	{
+		errno = ENOMEM;
+		return NULL;
+	}
+	buf[0] = '"';
+	memcpy(&buf[1], command, cmdlen);
+	buf[cmdlen + 1] = '"';
+	buf[cmdlen + 2] = '\0';
+
+	res = _popen(buf, type);
+
+	save_errno = errno;
+	free(buf);
+	errno = save_errno;
+
+	return res;
+}
+
+#endif
diff --git a/src/test/isolation/isolation_main.c b/src/test/isolation/isolation_main.c
index 64c41758cbaddfbbd3d28e373c5f409402977e00..c8d431fd9530cab61f4ce7fc02dbdd5d2e47fe69 100644
--- a/src/test/isolation/isolation_main.c
+++ b/src/test/isolation/isolation_main.c
@@ -77,7 +77,7 @@ isolation_start_test(const char *testname,
 						   "%s ", launcher);
 
 	snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
-			 SYSTEMQUOTE "\"%s\" \"dbname=%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+			 "\"%s\" \"dbname=%s\" < \"%s\" > \"%s\" 2>&1",
 			 isolation_exec,
 			 dblist->str,
 			 infile,
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 07dd8037ac3f3323a869cc8bbaa1aad37302061d..c41cf7e7711ad7ae21b6588076158492206de846 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -293,7 +293,7 @@ stop_postmaster(void)
 		fflush(stderr);
 
 		snprintf(buf, sizeof(buf),
-				 SYSTEMQUOTE "\"%s/pg_ctl\" stop -D \"%s/data\" -s -m fast" SYSTEMQUOTE,
+				 "\"%s/pg_ctl\" stop -D \"%s/data\" -s -m fast",
 				 bindir, temp_install);
 		r = system(buf);
 		if (r != 0)
@@ -904,7 +904,7 @@ psql_command(const char *database, const char *query,...)
 
 	/* And now we can build and execute the shell command */
 	snprintf(psql_cmd, sizeof(psql_cmd),
-			 SYSTEMQUOTE "\"%s%spsql\" -X -c \"%s\" \"%s\"" SYSTEMQUOTE,
+			 "\"%s%spsql\" -X -c \"%s\" \"%s\"",
 			 psqldir ? psqldir : "",
 			 psqldir ? "/" : "",
 			 query_escaped,
@@ -1033,7 +1033,7 @@ spawn_process(const char *cmdline)
 		exit(2);
 	}
 
-	cmdline2 = psprintf("cmd /c %s", cmdline);
+	cmdline2 = psprintf("cmd /c \"%s\"", cmdline);
 
 #ifndef __CYGWIN__
 	AddUserToTokenDacl(restrictedToken);
@@ -1251,7 +1251,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
 
 	/* OK, run the diff */
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
+			 "diff %s \"%s\" \"%s\" > \"%s\"",
 			 basic_diff_opts, expectfile, resultsfile, diff);
 
 	/* Is the diff file empty? */
@@ -1284,7 +1284,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
 		}
 
 		snprintf(cmd, sizeof(cmd),
-				 SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
+				 "diff %s \"%s\" \"%s\" > \"%s\"",
 				 basic_diff_opts, alt_expectfile, resultsfile, diff);
 
 		if (run_diff(cmd, diff) == 0)
@@ -1312,7 +1312,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
 	if (platform_expectfile)
 	{
 		snprintf(cmd, sizeof(cmd),
-				 SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
+				 "diff %s \"%s\" \"%s\" > \"%s\"",
 				 basic_diff_opts, default_expectfile, resultsfile, diff);
 
 		if (run_diff(cmd, diff) == 0)
@@ -1336,7 +1336,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
 	 * append to the diffs summary file.
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 SYSTEMQUOTE "diff %s \"%s\" \"%s\" >> \"%s\"" SYSTEMQUOTE,
+			 "diff %s \"%s\" \"%s\" >> \"%s\"",
 			 pretty_diff_opts, best_expect_file, resultsfile, difffilename);
 	run_diff(cmd, difffilename);
 
@@ -2121,11 +2121,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
 		/* "make install" */
 #ifndef WIN32_ONLY_COMPILER
 		snprintf(buf, sizeof(buf),
-				 SYSTEMQUOTE "\"%s\" -C \"%s\" DESTDIR=\"%s/install\" install > \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
+				 "\"%s\" -C \"%s\" DESTDIR=\"%s/install\" install > \"%s/log/install.log\" 2>&1",
 				 makeprog, top_builddir, temp_install, outputdir);
 #else
 		snprintf(buf, sizeof(buf),
-				 SYSTEMQUOTE "perl \"%s/src/tools/msvc/install.pl\" \"%s/install\" >\"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
+				 "perl \"%s/src/tools/msvc/install.pl\" \"%s/install\" >\"%s/log/install.log\" 2>&1",
 				 top_builddir, temp_install, outputdir);
 #endif
 		if (system(buf))
@@ -2138,7 +2138,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
 		{
 #ifndef WIN32_ONLY_COMPILER
 			snprintf(buf, sizeof(buf),
-					 SYSTEMQUOTE "\"%s\" -C \"%s/%s\" DESTDIR=\"%s/install\" install >> \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
+					 "\"%s\" -C \"%s/%s\" DESTDIR=\"%s/install\" install >> \"%s/log/install.log\" 2>&1",
 				   makeprog, top_builddir, sl->str, temp_install, outputdir);
 #else
 			fprintf(stderr, _("\n%s: --extra-install option not supported on this platform\n"), progname);
@@ -2155,7 +2155,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
 		/* initdb */
 		header(_("initializing database system"));
 		snprintf(buf, sizeof(buf),
-				 SYSTEMQUOTE "\"%s/initdb\" -D \"%s/data\" -L \"%s\" --noclean --nosync%s%s > \"%s/log/initdb.log\" 2>&1" SYSTEMQUOTE,
+				 "\"%s/initdb\" -D \"%s/data\" -L \"%s\" --noclean --nosync%s%s > \"%s/log/initdb.log\" 2>&1",
 				 bindir, temp_install, datadir,
 				 debug ? " --debug" : "",
 				 nolocale ? " --no-locale" : "",
@@ -2206,7 +2206,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
 		 * Check if there is a postmaster running already.
 		 */
 		snprintf(buf2, sizeof(buf2),
-				 SYSTEMQUOTE "\"%s/psql\" -X postgres <%s 2>%s" SYSTEMQUOTE,
+				 "\"%s/psql\" -X postgres <%s 2>%s",
 				 bindir, DEVNULL, DEVNULL);
 
 		for (i = 0; i < 16; i++)
@@ -2238,7 +2238,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
 		 */
 		header(_("starting postmaster"));
 		snprintf(buf, sizeof(buf),
-				 SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE,
+				 "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1",
 				 bindir, temp_install,
 				 debug ? " -d 5" : "",
 				 hostname ? hostname : "",
diff --git a/src/test/regress/pg_regress_main.c b/src/test/regress/pg_regress_main.c
index a4f66b8a33f0bc7ec9c1b4773e5ba8aa0a81c8ef..90327b06110d53a788f82ded66339e62640943a0 100644
--- a/src/test/regress/pg_regress_main.c
+++ b/src/test/regress/pg_regress_main.c
@@ -64,7 +64,7 @@ psql_start_test(const char *testname,
 						   "%s ", launcher);
 
 	snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
-			 SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+			 "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1",
 			 psqldir ? psqldir : "",
 			 psqldir ? "/" : "",
 			 dblist->str,
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index d06d6adf6ee4b43e40e25be38b1dc39f4e3666df..1254d89c2929ec5590736e84f19e2662803d5206 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -69,7 +69,7 @@ sub mkvcbuild
 	  srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
 	  erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
 	  pgcheckdir.c pg_crc.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
-	  qsort.c qsort_arg.c quotes.c
+	  qsort.c qsort_arg.c quotes.c system.c
 	  sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
 	  win32env.c win32error.c win32setlocale.c);