diff --git a/.gitignore b/.gitignore
index 8d3af50..3cd37fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,3 +36,6 @@ lib*.pc
 /pgsql.sln.cache
 /Debug/
 /Release/
+
+# Generated by tests
+/tmp_check/
diff --git a/doc/src/sgml/install-windows.sgml b/doc/src/sgml/install-windows.sgml
index 9b77648..d3d8f5f 100644
--- a/doc/src/sgml/install-windows.sgml
+++ b/doc/src/sgml/install-windows.sgml
@@ -438,6 +438,7 @@ $ENV{CONFIG}="Debug";
 <userinput>vcregress contribcheck</userinput>
 <userinput>vcregress ecpgcheck</userinput>
 <userinput>vcregress isolationcheck</userinput>
+<userinput>vcregress tapcheck</userinput>
 <userinput>vcregress upgradecheck</userinput>
 </screen>
 
diff --git a/src/bin/initdb/t/001_initdb.pl b/src/bin/initdb/t/001_initdb.pl
index 149b3d1..091ec0e 100644
--- a/src/bin/initdb/t/001_initdb.pl
+++ b/src/bin/initdb/t/001_initdb.pl
@@ -1,10 +1,26 @@
 use strict;
 use warnings;
+use Config;
 use TestLib;
 use Test::More tests => 19;
 
 my $tempdir = TestLib::tempdir;
 
+sub cleanup_tempdir
+{
+	my $tempdir = shift;
+
+	if ($Config{osname} eq "MSWin32")
+	{
+		system_or_bail "rd /s /q $tempdir";
+		mkdir $tempdir;
+	}
+	else
+	{
+		system_or_bail "rm -rf '$tempdir'/*";
+	}
+}
+
 program_help_ok('initdb');
 program_version_ok('initdb');
 program_options_handling_ok('initdb');
@@ -18,27 +34,26 @@ command_fails([ 'initdb', '-S', "$tempdir/data3" ],
 mkdir "$tempdir/data4" or BAIL_OUT($!);
 command_ok([ 'initdb', "$tempdir/data4" ], 'existing empty data directory');
 
-system_or_bail "rm -rf '$tempdir'/*";
-
-command_ok([ 'initdb', "$tempdir/data", '-X', "$tempdir/pgxlog" ],
-	'separate xlog directory');
+cleanup_tempdir $tempdir;
 
-system_or_bail "rm -rf '$tempdir'/*";
+command_ok([ 'initdb', '-D', "$tempdir/data", '-X', "$tempdir/pgxlog" ],
+		   'separate xlog directory');
+cleanup_tempdir $tempdir;
 command_fails(
 	[ 'initdb', "$tempdir/data", '-X', 'pgxlog' ],
 	'relative xlog directory not allowed');
 
-system_or_bail "rm -rf '$tempdir'/*";
+cleanup_tempdir $tempdir;
 mkdir "$tempdir/pgxlog";
-command_ok([ 'initdb', "$tempdir/data", '-X', "$tempdir/pgxlog" ],
+command_ok([ 'initdb', '-D', "$tempdir/data", '-X', "$tempdir/pgxlog" ],
 	'existing empty xlog directory');
 
-system_or_bail "rm -rf '$tempdir'/*";
+cleanup_tempdir $tempdir;
 mkdir "$tempdir/pgxlog";
 mkdir "$tempdir/pgxlog/lost+found";
-command_fails([ 'initdb', "$tempdir/data", '-X', "$tempdir/pgxlog" ],
+command_fails([ 'initdb', '-D', "$tempdir/data", '-X', "$tempdir/pgxlog" ],
 	'existing nonempty xlog directory');
 
-system_or_bail "rm -rf '$tempdir'/*";
-command_ok([ 'initdb', "$tempdir/data", '-T', 'german' ],
+cleanup_tempdir $tempdir;
+command_ok([ 'initdb', '-D', "$tempdir/data", '-T', 'german' ],
 	'select default dictionary');
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 7e9a776..130f41a 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -1,8 +1,9 @@
 use strict;
 use warnings;
 use Cwd;
+use Config;
 use TestLib;
-use Test::More tests => 35;
+use Test::More tests => ($Config{osname} eq "MSWin32") ? 26 : 35;
 
 program_help_ok('pg_basebackup');
 program_version_ok('pg_basebackup');
@@ -18,7 +19,11 @@ command_fails(
 	'pg_basebackup fails because of hba');
 
 open HBA, ">>$tempdir/pgdata/pg_hba.conf";
-print HBA "local replication all trust\n";
+# Windows builds do not support local connections
+if ($Config{osname} ne "MSWin32")
+{
+	print HBA "local replication all trust\n";
+}
 print HBA "host replication all 127.0.0.1/32 trust\n";
 print HBA "host replication all ::1/128 trust\n";
 close HBA;
@@ -61,49 +66,53 @@ unlink "$tempdir/pgdata/$superlongname";
 # for the tablespace directories, which hopefully won't run afoul of
 # the 99 character length limit.
 my $shorter_tempdir = tempdir_short . "/tempdir";
-symlink "$tempdir", $shorter_tempdir;
 
-mkdir "$tempdir/tblspc1";
-psql 'postgres', "CREATE TABLESPACE tblspc1 LOCATION '$shorter_tempdir/tblspc1';";
-psql 'postgres', "CREATE TABLE test1 (a int) TABLESPACE tblspc1;";
-command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup2", '-Ft' ],
-	'tar format with tablespaces');
-ok(-f "$tempdir/tarbackup2/base.tar", 'backup tar was created');
-my @tblspc_tars = glob "$tempdir/tarbackup2/[0-9]*.tar";
-is(scalar(@tblspc_tars), 1, 'one tablespace tar was created');
-
-command_fails(
-	[ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp' ],
-	'plain format with tablespaces fails without tablespace mapping');
-
-command_ok(
-	[   'pg_basebackup',    '-D',
-		"$tempdir/backup1", '-Fp',
-		"-T$shorter_tempdir/tblspc1=$tempdir/tbackup/tblspc1" ],
-	'plain format with tablespaces succeeds with tablespace mapping');
-ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated');
-opendir(my $dh, "$tempdir/pgdata/pg_tblspc") or die;
-ok( (   grep
-		{
-			-l "$tempdir/backup1/pg_tblspc/$_"
-			  and readlink "$tempdir/backup1/pg_tblspc/$_" eq
-			  "$tempdir/tbackup/tblspc1"
-		  } readdir($dh)),
-	"tablespace symlink was updated");
-closedir $dh;
-
-mkdir "$tempdir/tbl=spc2";
-psql 'postgres', "DROP TABLE test1;";
-psql 'postgres', "DROP TABLESPACE tblspc1;";
-psql 'postgres', "CREATE TABLESPACE tblspc2 LOCATION '$shorter_tempdir/tbl=spc2';";
-command_ok(
-	[   'pg_basebackup',    '-D',
-		"$tempdir/backup3", '-Fp',
-		"-T$shorter_tempdir/tbl\\=spc2=$tempdir/tbackup/tbl\\=spc2" ],
-	'mapping tablespace with = sign in path');
-ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated');
-
-psql 'postgres', "DROP TABLESPACE tblspc2;";
+# Windows does not support symlink
+if ($Config{osname} ne "MSWin32")
+{
+	symlink "$tempdir", $shorter_tempdir;
+
+	mkdir "$tempdir/tblspc1";
+	psql 'postgres', "CREATE TABLESPACE tblspc1 LOCATION '$shorter_tempdir/tblspc1';";
+	psql 'postgres', "CREATE TABLE test1 (a int) TABLESPACE tblspc1;";
+	command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup2", '-Ft' ],
+			   'tar format with tablespaces');
+	ok(-f "$tempdir/tarbackup2/base.tar", 'backup tar was created');
+	my @tblspc_tars = glob "$tempdir/tarbackup2/[0-9]*.tar";
+	is(scalar(@tblspc_tars), 1, 'one tablespace tar was created');
+
+	command_fails(
+		[ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp' ],
+		'plain format with tablespaces fails without tablespace mapping');
+
+	command_ok(
+		[   'pg_basebackup',    '-D',
+			"$tempdir/backup1", '-Fp',
+			"-T$shorter_tempdir/tblspc1=$tempdir/tbackup/tblspc1" ],
+		'plain format with tablespaces succeeds with tablespace mapping');
+	ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated');
+	opendir(my $dh, "$tempdir/pgdata/pg_tblspc") or die;
+	ok( (   grep
+			{
+				-l "$tempdir/backup1/pg_tblspc/$_"
+					and readlink "$tempdir/backup1/pg_tblspc/$_" eq
+					"$tempdir/tbackup/tblspc1"
+			} readdir($dh)),
+		"tablespace symlink was updated");
+	closedir $dh;
+
+	mkdir "$tempdir/tbl=spc2";
+	psql 'postgres', "DROP TABLE test1;";
+	psql 'postgres', "DROP TABLESPACE tblspc1;";
+	psql 'postgres', "CREATE TABLESPACE tblspc2 LOCATION '$shorter_tempdir/tbl=spc2';";
+	command_ok(
+		[   'pg_basebackup',    '-D',
+			"$tempdir/backup3", '-Fp',
+			"-T$shorter_tempdir/tbl\\=spc2=$tempdir/tbackup/tbl\\=spc2" ],
+		'mapping tablespace with = sign in path');
+	ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated');
+	psql 'postgres', "DROP TABLESPACE tblspc2;";
+}
 
 command_fails(
 	[ 'pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp', "-T=/foo" ],
diff --git a/src/bin/pg_controldata/t/001_pg_controldata.pl b/src/bin/pg_controldata/t/001_pg_controldata.pl
index a4180e7..fc18a3a 100644
--- a/src/bin/pg_controldata/t/001_pg_controldata.pl
+++ b/src/bin/pg_controldata/t/001_pg_controldata.pl
@@ -1,5 +1,6 @@
 use strict;
 use warnings;
+use Config;
 use TestLib;
 use Test::More tests => 13;
 
@@ -11,6 +12,8 @@ program_options_handling_ok('pg_controldata');
 command_fails(['pg_controldata'], 'pg_controldata without arguments fails');
 command_fails([ 'pg_controldata', 'nonexistent' ],
 	'pg_controldata with nonexistent directory fails');
-system_or_bail "initdb -D '$tempdir'/data -A trust >/dev/null";
+
+my $null_ptr = ($Config{osname} eq "MSWin32") ? "NUL" : "/dev/null";
+system_or_bail "initdb -D $tempdir/data -A trust > $null_ptr";
 command_like([ 'pg_controldata', "$tempdir/data" ],
 	qr/checkpoint/, 'pg_controldata produces output');
diff --git a/src/bin/pg_ctl/t/001_start_stop.pl b/src/bin/pg_ctl/t/001_start_stop.pl
index 17309e8..f5b61cf 100644
--- a/src/bin/pg_ctl/t/001_start_stop.pl
+++ b/src/bin/pg_ctl/t/001_start_stop.pl
@@ -1,11 +1,15 @@
 use strict;
 use warnings;
+use Config;
 use TestLib;
 use Test::More tests => 17;
 
 my $tempdir = TestLib::tempdir;
 my $tempdir_short = TestLib::tempdir_short;
 
+my $pg_regress = ($Config{osname} eq "MSWin32") ?
+	$ENV{TESTREGRESS} : "$ENV{top_builddir}/src/test/regress/pg_regress";
+
 program_help_ok('pg_ctl');
 program_version_ok('pg_ctl');
 program_options_handling_ok('pg_ctl');
@@ -15,12 +19,19 @@ command_exit_is([ 'pg_ctl', 'start', '-D', "$tempdir/nonexistent" ],
 
 command_ok([ 'pg_ctl', 'initdb', '-D', "$tempdir/data" ], 'pg_ctl initdb');
 command_ok(
-	[   "$ENV{top_builddir}/src/test/regress/pg_regress", '--config-auth',
+	[   "$pg_regress", '--config-auth',
 		"$tempdir/data" ],
 	'configure authentication');
 open CONF, ">>$tempdir/data/postgresql.conf";
-print CONF "listen_addresses = ''\n";
-print CONF "unix_socket_directories = '$tempdir_short'\n";
+if ($Config{osname} eq "MSWin32")
+{
+	print CONF "listen_addresses = 'localhost'\n";
+}
+else
+{
+	print CONF "listen_addresses = ''\n";
+	print CONF "unix_socket_directories = '$tempdir_short'\n";
+}
 close CONF;
 command_ok([ 'pg_ctl', 'start', '-D', "$tempdir/data", '-w' ],
 	'pg_ctl start -w');
diff --git a/src/bin/pg_ctl/t/002_status.pl b/src/bin/pg_ctl/t/002_status.pl
index b8cbbda..ffea71f 100644
--- a/src/bin/pg_ctl/t/002_status.pl
+++ b/src/bin/pg_ctl/t/002_status.pl
@@ -1,5 +1,6 @@
 use strict;
 use warnings;
+use Config;
 use TestLib;
 use Test::More tests => 3;
 
@@ -11,8 +12,15 @@ command_exit_is([ 'pg_ctl', 'status', '-D', "$tempdir/nonexistent" ],
 
 standard_initdb "$tempdir/data";
 open CONF, ">>$tempdir/data/postgresql.conf";
-print CONF "listen_addresses = ''\n";
-print CONF "unix_socket_directories = '$tempdir_short'\n";
+if ($Config{osname} eq "MSWin32")
+{
+	print CONF "listen_addresses = 'localhost'\n";
+}
+else
+{
+	print CONF "listen_addresses = ''\n";
+	print CONF "unix_socket_directories = '$tempdir_short'\n";
+}
 close CONF;
 
 command_exit_is([ 'pg_ctl', 'status', '-D', "$tempdir/data" ],
diff --git a/src/bin/scripts/t/010_clusterdb.pl b/src/bin/scripts/t/010_clusterdb.pl
index cb9d04b..f125625 100644
--- a/src/bin/scripts/t/010_clusterdb.pl
+++ b/src/bin/scripts/t/010_clusterdb.pl
@@ -15,12 +15,12 @@ issues_sql_like(
 	qr/statement: CLUSTER;/,
 	'SQL CLUSTER run');
 
-command_fails([ 'clusterdb', '-t', 'nonexistent', 'postgres' ],
+command_fails([ 'clusterdb', '-t', 'nonexistent', '-d', 'postgres' ],
 	'fails with nonexistent table');
 
 psql 'postgres',
 'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a); CLUSTER test1 USING test1x';
 issues_sql_like(
-	[ 'clusterdb', 'postgres', '-t', 'test1' ],
+	[ 'clusterdb', '-d', 'postgres', '-t', 'test1' ],
 	qr/statement: CLUSTER test1;/,
 	'cluster specific table');
diff --git a/src/bin/scripts/t/020_createdb.pl b/src/bin/scripts/t/020_createdb.pl
index 40fbc92..7395381 100644
--- a/src/bin/scripts/t/020_createdb.pl
+++ b/src/bin/scripts/t/020_createdb.pl
@@ -1,5 +1,6 @@
 use strict;
 use warnings;
+use Config;
 use TestLib;
 use Test::More tests => 13;
 
@@ -14,9 +15,11 @@ issues_sql_like(
 	[ 'createdb', 'foobar1' ],
 	qr/statement: CREATE DATABASE foobar1/,
 	'SQL CREATE DATABASE run');
+
+my $encoding = ($Config{osname} eq "MSWin32") ? "win1252" : "LATIN1" ;
 issues_sql_like(
-	[ 'createdb', 'foobar2', '-l', 'C', '-E', 'LATIN1', '-T', 'template0' ],
-	qr/statement: CREATE DATABASE foobar2 ENCODING 'LATIN1'/,
+	[ 'createdb', '-l', 'C', '-E', "$encoding", '-T', 'template0', 'foobar2' ],
+	qr/statement: CREATE DATABASE foobar2 ENCODING '$encoding'/,
 	'create database with encoding');
 
 command_fails([ 'createdb', 'foobar1' ], 'fails if database already exists');
diff --git a/src/bin/scripts/t/090_reindexdb.pl b/src/bin/scripts/t/090_reindexdb.pl
index d24088e..f80a79e 100644
--- a/src/bin/scripts/t/090_reindexdb.pl
+++ b/src/bin/scripts/t/090_reindexdb.pl
@@ -20,18 +20,18 @@ issues_sql_like(
 psql 'postgres',
   'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a);';
 issues_sql_like(
-	[ 'reindexdb', 'postgres', '-t', 'test1' ],
+	[ 'reindexdb', '-d', 'postgres', '-t', 'test1' ],
 	qr/statement: REINDEX TABLE test1;/,
 	'reindex specific table');
 issues_sql_like(
-	[ 'reindexdb', 'postgres', '-i', 'test1x' ],
+	[ 'reindexdb', '-d', 'postgres', '-i', 'test1x' ],
 	qr/statement: REINDEX INDEX test1x;/,
 	'reindex specific index');
 issues_sql_like(
-	[ 'reindexdb', 'postgres', '-S', 'pg_catalog' ],
+	[ 'reindexdb', '-d', 'postgres', '-S', 'pg_catalog' ],
 	qr/statement: REINDEX SCHEMA pg_catalog;/,
 	'reindex specific schema');
 issues_sql_like(
-	[ 'reindexdb', 'postgres', '-s' ],
+	[ 'reindexdb', '-d', 'postgres', '-s' ],
 	qr/statement: REINDEX SYSTEM postgres;/,
 	'reindex system tables');
diff --git a/src/test/perl/TestLib.pm b/src/test/perl/TestLib.pm
index 003cd9a..26de1ac 100644
--- a/src/test/perl/TestLib.pm
+++ b/src/test/perl/TestLib.pm
@@ -3,6 +3,7 @@ package TestLib;
 use strict;
 use warnings;
 
+use Config;
 use Exporter 'import';
 our @EXPORT = qw(
   tempdir
@@ -73,9 +74,19 @@ sub tempdir_short
 sub standard_initdb
 {
 	my $pgdata = shift;
-	system_or_bail("initdb -D '$pgdata' -A trust -N >/dev/null");
-	system_or_bail("$ENV{top_builddir}/src/test/regress/pg_regress",
-				   '--config-auth', $pgdata);
+
+	if ($Config{osname} eq "MSWin32")
+	{
+		system_or_bail("initdb -D $pgdata -A trust -N > NUL");
+		system_or_bail("$ENV{TESTREGRESS}",
+					   '--config-auth', $pgdata);
+	}
+	else
+	{
+		system_or_bail("initdb -D '$pgdata' -A trust -N >/dev/null");
+		system_or_bail("$ENV{top_builddir}/src/test/regress/pg_regress",
+					   '--config-auth', $pgdata);
+	}
 }
 
 my ($test_server_datadir, $test_server_logfile);
@@ -87,10 +98,12 @@ sub start_test_server
 
 	my $tempdir_short = tempdir_short;
 
+	my $listen_addresses = ($Config{osname} eq "MSWin32") ? "localhost" : "''";
+
 	standard_initdb "$tempdir/pgdata";
 	$ret = system 'pg_ctl', '-D', "$tempdir/pgdata", '-s', '-w', '-l',
 	  "$tempdir/logfile", '-o',
-	  "--fsync=off -k $tempdir_short --listen-addresses='' --log-statement=all",
+	  "--fsync=off -k $tempdir_short --listen-addresses=$listen_addresses --log-statement=all",
 	  'start';
 
 	if ($ret != 0)
@@ -99,7 +112,7 @@ sub start_test_server
 		BAIL_OUT("pg_ctl failed");
 	}
 
-	$ENV{PGHOST}         = $tempdir_short;
+	$ENV{PGHOST}         = ($Config{osname} eq "MSWin32") ? "localhost" : $tempdir_short;
 	$test_server_datadir = "$tempdir/pgdata";
 	$test_server_logfile = "$tempdir/logfile";
 }
@@ -158,7 +171,7 @@ sub command_exit_is
 	my $h = start $cmd, '>', File::Spec->devnull(), '2>',
 	  File::Spec->devnull();
 	$h->finish();
-	is($h->result(0), $expected, $test_name);
+	is(($h->full_results)[0], $expected, $test_name);
 }
 
 sub program_help_ok
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index bd3dd2c..affe92b 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -7,7 +7,9 @@ use strict;
 our $config;
 
 use Cwd;
+use File::Basename;
 use File::Copy;
+use File::Find ();
 
 use Install qw(Install);
 
@@ -31,7 +33,7 @@ if (-e "src/tools/msvc/buildenv.pl")
 
 my $what = shift || "";
 if ($what =~
-/^(check|installcheck|plcheck|contribcheck|ecpgcheck|isolationcheck|upgradecheck)$/i
+/^(check|installcheck|plcheck|contribcheck|ecpgcheck|isolationcheck|upgradecheck|tapcheck)$/i
   )
 {
 	$what = uc $what;
@@ -77,6 +79,7 @@ my %command = (
 	ECPGCHECK      => \&ecpgcheck,
 	CONTRIBCHECK   => \&contribcheck,
 	ISOLATIONCHECK => \&isolationcheck,
+	TAPCHECK       => \&tapcheck,
 	UPGRADECHECK   => \&upgradecheck,);
 
 my $proc = $command{$what};
@@ -162,6 +165,59 @@ sub isolationcheck
 	exit $status if $status;
 }
 
+sub tapcheck
+{
+	# Temporary installation cannot be located deeper in src/ because
+	# of interferences with Install.pm scanning its content. So install
+	# it just once for all the tests.
+	my $tmp_root = "$topdir/tmp_check";
+	(mkdir $tmp_root || die $!) unless -d $tmp_root;
+	my $tmp_install = "$tmp_root/install";
+	Install($tmp_install, "all", $config);
+	my @args = (
+		"prove",
+		"--verbose",
+		"t/*.pl");
+
+	# XXX: Check existence of IPC::Run in environment?
+
+	# Set environment variables common to all the tests
+	my ($bindir, $libdir, $oldsrc, $newsrc) =
+	  ("$tmp_install/bin", "$tmp_install/lib", $topdir, $topdir);
+
+	$ENV{PATH} = "$bindir;$ENV{PATH}";
+	$ENV{PERL5LIB} = "$topdir/src/test/perl;$ENV{PERL5LIB}";
+	$ENV{TESTREGRESS} = "$topdir/$Config/pg_regress/pg_regress";
+	$ENV{top_builddir} = "$topdir";
+
+	# Find out all the existing TAP tests by simply looking for t/
+	# in the tree.
+	my $tap_dirs = [];
+	my @top_dir = ($topdir);
+	File::Find::find(
+		{   wanted => sub {
+				/^t\z/s
+				  && push(@$tap_dirs, $File::Find::name);
+			  }
+		},
+		@top_dir);
+
+	# Process each test
+	foreach(@$tap_dirs)
+	{
+		next if /pg_rewind/;
+		next if /ssl/;
+
+		my $dir = dirname($_);
+		chdir $dir;
+		# Reset those values, they may have been changed by another test.
+		$ENV{TESTDIR} = "$dir";
+		$ENV{PGHOST} = 'localhost';
+		$ENV{PGPORT} ||= 50432;
+		system(@args);
+	}
+}
+
 sub plcheck
 {
 	chdir "../../pl";
