diff -r 0139403c8eb0 src/eval.c
--- a/src/eval.c	Fri Feb 25 18:38:36 2011 +0100
+++ b/src/eval.c	Sun Feb 27 23:46:24 2011 +0100
@@ -11888,7 +11888,7 @@
 #ifdef FEAT_SEARCHPATH
 	"file_in_path",
 #endif
-#if defined(UNIX) && !defined(USE_SYSTEM)
+#if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264)
 	"filterpipe",
 #endif
 #ifdef FEAT_FIND_ID
diff -r 0139403c8eb0 src/ex_cmds.c
--- a/src/ex_cmds.c	Fri Feb 25 18:38:36 2011 +0100
+++ b/src/ex_cmds.c	Sun Feb 27 23:46:24 2011 +0100
@@ -1114,7 +1114,7 @@
     if (do_out)
 	shell_flags |= SHELL_DOOUT;
 
-#if !defined(USE_SYSTEM) && defined(UNIX)
+#if (!defined(USE_SYSTEM) && defined(UNIX)) || defined(WIN3264)
     if (!do_in && do_out && !p_stmp)
     {
 	/* Use a pipe to fetch stdout of the command, do not use a temp file. */
diff -r 0139403c8eb0 src/os_win32.c
--- a/src/os_win32.c	Fri Feb 25 18:38:36 2011 +0100
+++ b/src/os_win32.c	Sun Feb 27 23:46:24 2011 +0100
@@ -204,6 +204,7 @@
 static int suppress_winsize = 1;	/* don't fiddle with console */
 #endif
 
+static int	show_shell_mess = TRUE;
 static char_u *exe_path = NULL;
 
     static void
@@ -417,6 +418,11 @@
 static PGNSECINFO pGetNamedSecurityInfo;
 #endif
 
+typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
+
+static BOOL allowPiping = FALSE;
+static PSETHANDLEINFORMATION pSetHandleInformation;
+
 /*
  * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or
  * VER_PLATFORM_WIN32_WINDOWS (Win95).
@@ -467,6 +473,18 @@
 	    }
 	}
 #endif
+        /*
+         * If we are on windows NT, try to load the pipe functions, only
+         * available from Win2K
+         */
+	if (g_PlatformId == VER_PLATFORM_WIN32_NT)
+	{
+	    HANDLE kernel32 = GetModuleHandle("kernel32");
+            pSetHandleInformation = (PSETHANDLEINFORMATION)GetProcAddress(kernel32,
+                                                                "SetHandleInformation");
+
+            allowPiping = pSetHandleInformation != NULL;
+        }
 	done = TRUE;
     }
 }
@@ -3166,7 +3184,7 @@
  *    4. Prompt the user to press a key to close the console window
  */
     static int
-mch_system(char *cmd, int options)
+mch_system_classic(char *cmd, int options)
 {
     STARTUPINFO		si;
     PROCESS_INFORMATION pi;
@@ -3271,6 +3289,508 @@
 
     return ret;
 }
+
+/*
+ * Append the text in "gap" below the cursor line and clear "gap".
+ */
+    static void
+append_ga_line(garray_T	*gap)
+{
+    /* Remove trailing CR. */
+    if (gap->ga_len > 0
+	    && !curbuf->b_p_bin
+	    && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
+	--gap->ga_len;
+    ga_append(gap, NUL);
+    ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
+    gap->ga_len = 0;
+}
+
+/*
+ * Thread launched by the gui to send the current buffer data to the
+ * process. This way avoid to hang up vim totally if the children
+ * process take a long time to process the lines.
+ */
+    static DWORD WINAPI
+sub_process_writer(LPVOID param)
+{
+    HANDLE          g_hChildStd_IN_Wr = param;
+
+    linenr_T        lnum = curbuf->b_op_start.lnum;
+    DWORD           len = 0;
+    DWORD	    l;
+    char_u	    *lp = ml_get(lnum);
+    char_u	    *s;
+    int	            written = 0;
+
+    for (;;)
+    {
+        l = (DWORD)STRLEN(lp + written);
+        if (l == 0)
+            len = 0;
+        else if (lp[written] == NL)
+        {
+            /* NL -> NUL translation */
+            WriteFile(g_hChildStd_IN_Wr,
+                      "", 1, &len, NULL);
+        }
+        else
+        {
+            s = vim_strchr(lp + written, NL);
+            WriteFile(g_hChildStd_IN_Wr, (char *)lp + written,
+                      s == NULL ? l : (DWORD)(s - (lp + written)),
+                      &len, NULL);
+        }
+        if (len == (int)l)
+        {
+            /* Finished a line, add a NL, unless this line
+             * should not have one. */
+            if (lnum != curbuf->b_op_end.lnum
+                || !curbuf->b_p_bin
+                || (lnum != curbuf->b_no_eol_lnum
+                    && (lnum !=
+                        curbuf->b_ml.ml_line_count
+                        || curbuf->b_p_eol)))
+            {
+                WriteFile(g_hChildStd_IN_Wr,
+                        "\n", 1, &ignored, NULL);
+            }
+
+            ++lnum;
+            if (lnum > curbuf->b_op_end.lnum)
+                break;
+
+            lp = ml_get(lnum);
+            written = 0;
+        }
+        else if (len > 0)
+            written += len;
+    }
+
+    /* finished all the lines, close pipe */
+    CloseHandle(g_hChildStd_IN_Wr);
+    ExitThread(0);
+}
+
+
+# define BUFLEN 100		/* length for buffer, stolen from unix version */
+
+/*
+ * This function read from the children's stdout and write the
+ * data on screen or in the buffer accordingly.
+ */
+    static void
+dump_pipe(int options,
+          HANDLE g_hChildStd_OUT_Rd,
+          garray_T   *ga,
+          char_u buffer[],
+          DWORD *buffer_off)
+{
+    DWORD availableBytes = 0;
+    DWORD       i;
+    int         c;
+    /*int         noread_cnt = 0;*/
+    char_u      *p;
+    int         ret;
+    DWORD       len;
+
+    /* we query the pipe to see if there is any data to read
+     * to avoid to perform a blocking read */
+    ret = PeekNamedPipe(g_hChildStd_OUT_Rd, /* pipe to query */
+                        NULL,               /* optional buffer */
+                        0,                  /* buffe size */
+                        NULL,               /* number of read bytes */
+                        &availableBytes,    /* available bytes total */
+                        NULL);              /* byteLeft */
+
+    /* We got real data in the pipe, read it */
+    while (ret != 0 && availableBytes > 0
+           && availableBytes != ((DWORD)(-1))) /* For an unknown reason, sometimes PeekNamedPipe
+                                                  return -1, causing the next ReadFile to hang,
+                                                  filter out this possibility. */
+    {
+        ReadFile(g_hChildStd_OUT_Rd, buffer
+# ifdef FEAT_MBYTE
+                 + *buffer_off, (DWORD)(BUFLEN - *buffer_off)
+# else
+                 , (DWORD)BUFLEN
+# endif
+                 , &len, NULL);
+
+        availableBytes -= len;
+
+        if ( len > 0 && (options & SHELL_READ) )
+        {
+            /* Do NUL -> NL translation, append NL separated
+             * lines to the current buffer. */
+            for (i = 0; i < len; ++i)
+            {
+                if (buffer[i] == NL)
+                    append_ga_line(ga);
+                else if (buffer[i] == NUL)
+                    ga_append(ga, NL);
+                else
+                    ga_append(ga, buffer[i]);
+            }
+        }
+# ifdef FEAT_MBYTE
+        else if (has_mbyte)
+        {
+            int		l;
+
+            len += *buffer_off;
+            buffer[len] = NUL;
+
+            /* Check if the last character in buffer[] is
+             * incomplete, keep these bytes for the next
+             * round. */
+            for (p = buffer; p < buffer + len; p += l)
+            {
+                l = mb_cptr2len(p);
+                if (l == 0)
+                    l = 1;  /* NUL byte? */
+                else if (MB_BYTE2LEN(*p) != l)
+                    break;
+            }
+            if (p == buffer)	/* no complete character */
+            {
+                /* avoid getting stuck at an illegal byte */
+                if (len >= 12)
+                    ++p;
+                else
+                {
+                    *buffer_off = len;
+                    return;
+                }
+            }
+            c = *p;
+            *p = NUL;
+            msg_puts(buffer);
+            if (p < buffer + len)
+            {
+                *p = c;
+                *buffer_off = (DWORD)((buffer + len) - p);
+                mch_memmove(buffer, p, *buffer_off);
+                return;
+            }
+            *buffer_off = 0;
+        }
+# endif /* FEAT_MBYTE */
+        else
+        {
+            buffer[len] = NUL;
+            msg_puts(buffer);
+        }
+
+        windgoto(msg_row, msg_col);
+        cursor_on();
+        out_flush();
+    }
+}
+
+/*
+ * Version of system to use for windows NT > 5.0 (Win2K), use pipe
+ * for communication and doesn't open any new window.
+ */
+    static int
+mch_system_piped(char *cmd, int options)
+{
+    STARTUPINFO		si;
+    PROCESS_INFORMATION pi;
+    DWORD		ret = 0;
+
+    HANDLE g_hChildStd_IN_Rd = NULL;
+    HANDLE g_hChildStd_IN_Wr = NULL;
+    HANDLE g_hChildStd_OUT_Rd = NULL;
+    HANDLE g_hChildStd_OUT_Wr = NULL;
+
+    char_u	    buffer[BUFLEN + 1]; /* reading buffer + size */
+    DWORD           len;
+
+    /* buffer used to receive keys */
+    char_u	    ta_buf[BUFLEN + 1];	/* TypeAHead */
+    int         ta_len = 0;		/* valid bytes in ta_buf[] */
+
+    DWORD       i;
+    int         c;
+    int         noread_cnt = 0;
+    garray_T    ga;
+    int	    delay = 1;
+# ifdef FEAT_MBYTE
+    DWORD       buffer_off = 0;	/* valid bytes in buffer[] */
+# endif
+
+    SECURITY_ATTRIBUTES saAttr; 
+
+    /* Set the bInheritHandle flag so pipe handles are inherited. */
+    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
+    saAttr.bInheritHandle = TRUE; 
+    saAttr.lpSecurityDescriptor = NULL; 
+
+    if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)
+        /* Ensure the read handle to the pipe for STDOUT is not inherited. */
+       || ! pSetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)
+        /* Create a pipe for the child process's STDIN. */
+       || ! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0) 
+        /* Ensure the write handle to the pipe for STDIN is not inherited. */
+       || ! pSetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) 
+    {
+        CloseHandle(g_hChildStd_IN_Rd);
+        CloseHandle(g_hChildStd_IN_Wr);
+        CloseHandle(g_hChildStd_OUT_Rd);
+        CloseHandle(g_hChildStd_OUT_Wr);
+        MSG_PUTS(_("\nCannot create pipes\n"));
+    }
+ 
+    si.cb = sizeof(si);
+    si.lpReserved = NULL;
+    si.lpDesktop = NULL;
+    si.lpTitle = NULL;
+    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+
+    /* set-up our file redirection */
+    si.hStdError = g_hChildStd_OUT_Wr;
+    si.hStdOutput = g_hChildStd_OUT_Wr;
+    si.hStdInput = g_hChildStd_IN_Rd;
+    si.wShowWindow = SW_HIDE;
+    si.cbReserved2 = 0;
+    si.lpReserved2 = NULL;
+
+    if (options & SHELL_READ)
+        ga_init2(&ga, 1, BUFLEN);
+
+    /* Now, run the command */
+    CreateProcess(NULL,			/* Executable name */
+		  cmd,			/* Command to execute */
+		  NULL,			/* Process security attributes */
+		  NULL,			/* Thread security attributes */
+
+		  // this command can be litigeous, handle inheritence was
+		  // deactivated for pending temp file, but, if we deactivate it,
+		  // the pipes don't work for some reason.
+		  TRUE,		        /* Inherit handles, first deactivated, but needed */
+		  CREATE_DEFAULT_ERROR_MODE, /* Creation flags */
+		  NULL,			/* Environment */
+		  NULL,			/* Current directory */
+		  &si,			/* Startup information */
+		  &pi);			/* Process information */
+
+
+    /* Close our unused side of the pipes */
+    CloseHandle(g_hChildStd_IN_Rd);
+    CloseHandle(g_hChildStd_OUT_Wr);
+
+    if (options & SHELL_WRITE)
+    {
+        HANDLE thread =
+           CreateThread(NULL,  /* security attributes */
+                        0,     /* default stack size */
+                        sub_process_writer, /* function to be executed */
+                        g_hChildStd_IN_Wr,  /* parameter */
+                        0,                  /* creation flag, start immediately */
+                        NULL);              /* we don't care about thread id */
+        CloseHandle(thread);
+        g_hChildStd_IN_Wr = NULL;
+    }
+
+
+    /* Keep updating the window while waiting for the shell to finish. */
+    for (;;)
+    {
+        MSG	msg;
+
+        if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE))
+        {
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+
+        /* we write pipe information in da window */
+        if ((options & (SHELL_READ|SHELL_WRITE))
+# ifdef FEAT_GUI
+                || (gui.in_use && show_shell_mess)
+# endif
+            )
+        {
+            len = 0;
+            if (!(options & SHELL_EXPAND)
+                && ((options &
+                        (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
+                    != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
+# ifdef FEAT_GUI
+                    || gui.in_use
+# endif
+                    )
+                /*&& wait_pid == 0*/
+                && (ta_len > 0 || noread_cnt > 4))
+            {
+                if (ta_len == 0)
+                {
+                    /* Get extra characters when we don't have any.
+                        * Reset the counter and timer. */
+                    noread_cnt = 0;
+# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+                    gettimeofday(&start_tv, NULL);
+# endif
+                    len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
+                }
+                if (ta_len > 0 || len > 0)
+                {
+                    /*
+                        * For pipes:
+                        * Check for CTRL-C: send interrupt signal to child.
+                        * Check for CTRL-D: EOF, close pipe to child.
+                        */
+                    if (len == 1 && cmd != NULL)
+                    {
+                        if (ta_buf[ta_len] == Ctrl_C)
+                        {
+                            /* Learn what exit code is expected, for
+                                * now put 9 as SIGKILL */
+                            TerminateProcess(pi.hProcess, 9);
+                        }
+                        if (ta_buf[ta_len] == Ctrl_D)
+                        {
+                            CloseHandle(g_hChildStd_IN_Wr);
+                            g_hChildStd_IN_Wr = NULL;
+                        }
+                    }
+
+                    /* replace K_BS by <BS> and K_DEL by <DEL> */
+                    for (i = ta_len; i < ta_len + len; ++i)
+                    {
+                        if (ta_buf[i] == CSI && len - i > 2)
+                        {
+                            c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
+                            if (c == K_DEL || c == K_KDEL || c == K_BS)
+                            {
+                                mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
+                                            (size_t)(len - i - 2));
+                                if (c == K_DEL || c == K_KDEL)
+                                    ta_buf[i] = DEL;
+                                else
+                                    ta_buf[i] = Ctrl_H;
+                                len -= 2;
+                            }
+                        }
+                        else if (ta_buf[i] == '\r')
+                            ta_buf[i] = '\n';
+# ifdef FEAT_MBYTE
+                        if (has_mbyte)
+                            i += (*mb_ptr2len_len)(ta_buf + i,
+                                                    ta_len + len - i) - 1;
+# endif
+                    }
+
+                    /*
+                        * For pipes: echo the typed characters.
+                        * For a pty this does not seem to work.
+                        */
+                    for (i = ta_len; i < ta_len + len; ++i)
+                    {
+                        if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
+                            msg_putchar(ta_buf[i]);
+# ifdef FEAT_MBYTE
+                        else if (has_mbyte)
+                        {
+                            int l = (*mb_ptr2len)(ta_buf + i);
+
+                            msg_outtrans_len(ta_buf + i, l);
+                            i += l - 1;
+                        }
+# endif
+                        else
+                            msg_outtrans_len(ta_buf + i, 1);
+                    }
+                    windgoto(msg_row, msg_col);
+                    out_flush();
+
+                    ta_len += len;
+
+                    /*
+                        * Write the characters to the child, unless EOF has
+                        * been typed for pipes.  Write one character at a
+                        * time, to avoid losing too much typeahead.
+                        * When writing buffer lines, drop the typed
+                        * characters (only check for CTRL-C).
+                        */
+                    if (options & SHELL_WRITE)
+                        ta_len = 0;
+                    else if (g_hChildStd_IN_Wr != NULL)
+                    {
+                        WriteFile(g_hChildStd_IN_Wr, (char*)ta_buf,
+                                    1, &len, NULL);
+                        // if we are typing in, we want to keep things reactive
+                        delay = 1;
+                        if (len > 0)
+                        {
+                            ta_len -= len;
+                            mch_memmove(ta_buf, ta_buf + len, ta_len);
+                        }
+                    }
+                }
+            }
+        }
+
+        ++noread_cnt;
+        dump_pipe(options, g_hChildStd_OUT_Rd,
+                    &ga, buffer, &buffer_off);
+
+        if (ta_len)
+            ui_inchar_undo(ta_buf, ta_len);
+
+        if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT)
+        {
+            dump_pipe(options, g_hChildStd_OUT_Rd,
+                        &ga, buffer, &buffer_off);
+            break;
+        }
+
+        /* We start waiting for a very short time and then increase it, so
+        * that we respond quickly when the process is quick, and don't
+        * consume too much overhead when it's slow. */
+        if (delay < 50)
+            delay += 10;
+    }
+
+    /* Close the pipe */
+    CloseHandle(g_hChildStd_OUT_Rd);
+    if (g_hChildStd_IN_Wr != NULL)
+        CloseHandle(g_hChildStd_IN_Wr);
+
+    WaitForSingleObject(pi.hProcess, INFINITE);
+
+    /* Get the command exit code */
+    GetExitCodeProcess(pi.hProcess, &ret);
+
+    if (options & SHELL_READ)
+    {
+        if (ga.ga_len > 0)
+        {
+            append_ga_line(&ga);
+            /* remember that the NL was missing */
+            curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
+        }
+        else
+            curbuf->b_no_eol_lnum = 0;
+        ga_clear(&ga);
+    }
+
+    /* Close the handles to the subprocess, so that it goes away */
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+
+    return ret;
+}
+
+    static int
+mch_system(char *cmd, int options)
+{
+    if (allowPiping)
+        return mch_system_piped(cmd, options);
+    else
+        return mch_system_classic(cmd, options);
+}
 #else
 
 # define mch_system(c, o) system(c)
@@ -3344,7 +3864,7 @@
 	char_u *newcmd;
 	long_u cmdlen =  (
 #ifdef FEAT_GUI_W32
-		STRLEN(vimrun_path) +
+		(allowPiping ? 0 : STRLEN(vimrun_path)) +
 #endif
 		STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10);
 
@@ -3431,7 +3951,7 @@
 			    MB_ICONWARNING);
 		    need_vimrun_warning = FALSE;
 		}
-		if (!s_dont_use_vimrun)
+		if (!s_dont_use_vimrun && !allowPiping)
 		    /* Use vimrun to execute the command.  It opens a console
 		     * window, which can be closed without killing Vim. */
 		    vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s",
@@ -3455,7 +3975,7 @@
     /* Print the return value, unless "vimrun" was used. */
     if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent
 #if defined(FEAT_GUI_W32)
-		&& ((options & SHELL_DOOUT) || s_dont_use_vimrun)
+		&& ((options & SHELL_DOOUT) || s_dont_use_vimrun || allowPiping)
 #endif
 	    )
     {
diff -r 0139403c8eb0 src/ui.c
--- a/src/ui.c	Fri Feb 25 18:38:36 2011 +0100
+++ b/src/ui.c	Sun Feb 27 23:46:24 2011 +0100
@@ -58,7 +58,7 @@
 #endif
 }
 
-#if defined(UNIX) || defined(VMS) || defined(PROTO)
+#if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(WIN3264)
 /*
  * When executing an external program, there may be some typed characters that
  * are not consumed by it.  Give them back to ui_inchar() and they are stored
