diff --git a/doc/openocd.texi b/doc/openocd.texi
index 39a56303198d28b8ce0120508087357df1d146f7..63ab6fedf62a0e0d271a65ee57da583a9b9589ea 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -557,7 +557,6 @@ the @option{-s <search>} switch. The current directory and the OpenOCD
 target library is in the search path by default.
 
 For details on the @option{-p} option. @xref{Connecting to GDB}.
-Option @option{-p} is not currently supported under native win32.
 
 Note! OpenOCD will launch the GDB & telnet server even if it can not
 establish a connection with the target. In general, it is possible for
diff --git a/src/helper/options.c b/src/helper/options.c
index 203791bd66024fd68c9c70615db2f672e37840c8..dd9f71387a79733b2c39275e8f5b716264d4c672 100644
--- a/src/helper/options.c
+++ b/src/helper/options.c
@@ -148,14 +148,8 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
 #if BUILD_ECOSBOARD == 1
 				/* pipes unsupported on hosted platforms */
 				LOG_WARNING("pipes not supported on this platform");
-#else
-#ifdef IS_MINGW
-				/* pipes currently unsupported on win32 */
-				LOG_WARNING("pipes currently unsupported on win32");
-				exit(1);
 #else
 				server_use_pipes = 1;
-#endif
 #endif
 				break;
 		}
diff --git a/src/helper/replacements.c b/src/helper/replacements.c
index b6ddfd7c562082c9db9cd3a98b23e3ba1ace9bef..39a736c7c4336e2d26c3684f3c81ad223a058999 100644
--- a/src/helper/replacements.c
+++ b/src/helper/replacements.c
@@ -68,6 +68,10 @@ void *fill_malloc(size_t size)
 
 #include <stdio.h>
 
+#ifdef _WIN32
+#include <io.h>
+#endif
+
 /* replacements for gettimeofday */
 #ifndef HAVE_GETTIMEOFDAY
 
@@ -137,3 +141,151 @@ char* strndup(const char *s, size_t n)
 	return (char *) memcpy (new, s, len);
 }
 #endif
+
+#ifdef _WIN32
+int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+	DWORD ms_total, limit;
+	HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+	int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
+	int n_handles = 0, i;
+	fd_set sock_read, sock_write, sock_except;
+	fd_set aread, awrite, aexcept;
+	int sock_max_fd = -1;
+	struct timeval tvslice;
+	int retcode;
+
+#define SAFE_FD_ISSET(fd, set)	(set != NULL && FD_ISSET(fd, set))
+
+	/* calculate how long we need to wait in milliseconds */
+	if (tv == NULL) {
+		ms_total = INFINITE;
+	} else {
+		ms_total = tv->tv_sec * 1000;
+		ms_total += tv->tv_usec / 1000;
+	}
+
+	FD_ZERO(&sock_read);
+	FD_ZERO(&sock_write);
+	FD_ZERO(&sock_except);
+
+	/* build an array of handles for non-sockets */
+	for (i = 0; i < max_fd; i++) {
+		if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
+			handles[n_handles] = (HANDLE)_get_osfhandle(i);
+			if (handles[n_handles] == INVALID_HANDLE_VALUE) {
+				/* socket */
+				if (SAFE_FD_ISSET(i, rfds)) {
+					FD_SET(i, &sock_read);
+				}
+				if (SAFE_FD_ISSET(i, wfds)) {
+					FD_SET(i, &sock_write);
+				}
+				if (SAFE_FD_ISSET(i, efds)) {
+					FD_SET(i, &sock_except);
+				}
+				if (i > sock_max_fd) {
+					sock_max_fd = i;
+				}
+			} else {
+				handle_slot_to_fd[n_handles] = i;
+				n_handles++;
+			}
+		}
+	}
+
+	if (n_handles == 0) {
+		/* plain sockets only - let winsock handle the whole thing */
+		return select(max_fd, rfds, wfds, efds, tv);
+	}
+
+	/* mixture of handles and sockets; lets multiplex between
+	 * winsock and waiting on the handles */
+
+	FD_ZERO(&aread);
+	FD_ZERO(&awrite);
+	FD_ZERO(&aexcept);
+	
+	limit = GetTickCount() + ms_total;
+	do {
+		retcode = 0;
+	
+		if (sock_max_fd >= 0) {
+			/* overwrite the zero'd sets here; the select call
+			 * will clear those that are not active */
+			aread = sock_read;
+			awrite = sock_write;
+			aexcept = sock_except;
+
+			tvslice.tv_sec = 0;
+			tvslice.tv_usec = 100000;
+
+			retcode = select(sock_max_fd+1, &aread, &awrite, &aexcept, &tvslice);
+		}
+		if (n_handles > 0) {
+			/* check handles */
+			DWORD wret;
+
+			wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode > 0 ? 0 : 100, QS_ALLEVENTS);
+
+			if (wret == WAIT_TIMEOUT) {
+				/* set retcode to 0; this is the default.
+				 * select() may have set it to something else,
+				 * in which case we leave it alone, so this branch
+				 * does nothing */
+				;
+			} else if (wret == WAIT_FAILED) {
+				if (retcode == 0) {
+					retcode = -1;
+				}
+			} else {
+				if (retcode < 0) {
+					retcode = 0;
+				}
+				for (i = 0; i < n_handles; i++) {
+					if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
+						if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
+							DWORD dwBytes;
+							
+							if (PeekNamedPipe((HANDLE)_get_osfhandle(handle_slot_to_fd[i]), NULL, 0, NULL, &dwBytes, NULL))
+							{
+								/* check to see if gdb pipe has data available */
+								if (dwBytes)
+								{
+									FD_SET(handle_slot_to_fd[i], &aread);
+									retcode++;
+								}
+							}
+							else
+							{
+								FD_SET(handle_slot_to_fd[i], &aread);
+								retcode++;
+							}
+						}
+						if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) {
+							FD_SET(handle_slot_to_fd[i], &awrite);
+							retcode++;
+						}
+						if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) {
+							FD_SET(handle_slot_to_fd[i], &aexcept);
+							retcode++;
+						}
+					}
+				}
+			}
+		}
+	} while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
+
+	if (rfds) {
+		*rfds = aread;
+	}
+	if (wfds) {
+		*wfds = awrite;
+	}
+	if (efds) {
+		*efds = aexcept;
+	}
+
+	return retcode;
+}
+#endif
diff --git a/src/helper/replacements.h b/src/helper/replacements.h
index b6165085a889ac2304913d18812fac14e3c2cb2a..c3a2bf77d94e5bc3dbc3d8bfe607457e08b1dc0f 100644
--- a/src/helper/replacements.h
+++ b/src/helper/replacements.h
@@ -180,6 +180,9 @@ static __inline void outb(unsigned char value, unsigned short int port)
 }
 
 #endif /* IS_MINGW */
+
+int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv);
+
 #endif  /* _WIN32 */
 
 /* generic socket functions for Windows and Posix */
@@ -221,6 +224,15 @@ static __inline void socket_nonblock(int fd)
 #endif
 }
 
+static __inline int socket_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+#ifdef _WIN32
+	return win_select(max_fd, rfds, wfds, efds, tv);
+#else
+	return select(max_fd, rfds, wfds, efds, tv);
+#endif
+}
+
 #ifndef HAVE_ELF_H
 
 typedef struct
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 3f9e1e71a7dd0cbb50030acbc43b67eda735565f..eb612c7a9b88a2f0a074ad853541c3467dbc2341 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -126,7 +126,7 @@ int check_pending(connection_t *connection, int timeout_s, int *got_data)
 
 	tv.tv_sec = timeout_s;
 	tv.tv_usec = 0;
-	if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
+	if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
 	{
 		/* This can typically be because a "monitor" command took too long
 		 * before printing any progress messages
diff --git a/src/server/server.c b/src/server/server.c
index b5b9a205db137564f96583b4160f4b481e2d9ef1..e97dac9ac77061b8c82aa82dbfaed9566460fe6a 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -97,12 +97,11 @@ int add_connection(service_t *service, command_context_t *cmd_ctx)
 	}
 	else if (service->type == CONNECTION_PIPE)
 	{
-#ifndef _WIN32
 		c->fd = service->fd;
 		
 		/* do not check for new connections again on stdin */
 		service->fd = -1;
-#endif
+		
 		LOG_INFO("accepting '%s' connection from pipe", service->name);
 		if ((retval = service->new_connection(c)) != ERROR_OK)
 		{
@@ -223,6 +222,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
 			LOG_WARNING("cannot change stdout mode to binary");
 		if (_setmode(_fileno(stdin), _O_BINARY) < 0)
 			LOG_WARNING("cannot change stdin mode to binary");
+		if (_setmode(_fileno(stderr), _O_BINARY) < 0)
+			LOG_WARNING("cannot change stderr mode to binary");
 #else
 		socket_nonblock(c->fd);
 #endif
@@ -365,7 +366,7 @@ int server_loop(command_context_t *command_context)
 		kept_alive();
 		
 		/* Only while we're sleeping we'll let others run */
-		retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
+		retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
 		openocd_sleep_postlude();
 
 		if (retval == -1)
@@ -503,7 +504,7 @@ int server_init(void)
 	WORD wVersionRequested;
 	WSADATA wsaData;
 
-	wVersionRequested = MAKEWORD( 2, 2 );
+	wVersionRequested = MAKEWORD(2, 2);
 
 	if (WSAStartup(wVersionRequested, &wsaData) != 0)
 	{
@@ -511,7 +512,16 @@ int server_init(void)
 		exit(-1);
 	}
 
-	SetConsoleCtrlHandler( ControlHandler, TRUE );
+	if (server_use_pipes == 0)
+	{
+		/* register ctrl-c handler */
+		SetConsoleCtrlHandler(ControlHandler, TRUE);
+	}
+	else
+	{
+		/* we are using pipes so ignore ctrl-c */
+		SetConsoleCtrlHandler(NULL, TRUE);
+	}
 
 	signal(SIGINT, sig_handler);
 	signal(SIGTERM, sig_handler);