+#if defined(__WIN32__) && wxUSE_STREAMS
+
+// ----------------------------------------------------------------------------
+// wxPipeStreams
+// ----------------------------------------------------------------------------
+
+class wxPipeInputStream: public wxInputStream
+{
+public:
+ wxPipeInputStream(HANDLE hInput);
+ virtual ~wxPipeInputStream();
+
+ // returns TRUE if the pipe is still opened
+ bool IsOpened() const { return m_hInput != INVALID_HANDLE_VALUE; }
+
+ // returns TRUE if there is any data to be read from the pipe
+ virtual bool CanRead() const;
+
+protected:
+ size_t OnSysRead(void *buffer, size_t len);
+
+protected:
+ HANDLE m_hInput;
+
+ DECLARE_NO_COPY_CLASS(wxPipeInputStream)
+};
+
+class wxPipeOutputStream: public wxOutputStream
+{
+public:
+ wxPipeOutputStream(HANDLE hOutput);
+ virtual ~wxPipeOutputStream();
+
+protected:
+ size_t OnSysWrite(const void *buffer, size_t len);
+
+protected:
+ HANDLE m_hOutput;
+
+ DECLARE_NO_COPY_CLASS(wxPipeOutputStream)
+};
+
+// define this to let wxexec.cpp know that we know what we're doing
+#define _WX_USED_BY_WXEXECUTE_
+#include "../common/execcmn.cpp"
+
+// ----------------------------------------------------------------------------
+// wxPipe represents a Win32 anonymous pipe
+// ----------------------------------------------------------------------------
+
+class wxPipe
+{
+public:
+ // the symbolic names for the pipe ends
+ enum Direction
+ {
+ Read,
+ Write
+ };
+
+ // default ctor doesn't do anything
+ wxPipe() { m_handles[Read] = m_handles[Write] = INVALID_HANDLE_VALUE; }
+
+ // create the pipe, return TRUE if ok, FALSE on error
+ bool Create()
+ {
+ // default secutiry attributes
+ SECURITY_ATTRIBUTES security;
+
+ security.nLength = sizeof(security);
+ security.lpSecurityDescriptor = NULL;
+ security.bInheritHandle = TRUE; // to pass it to the child
+
+ if ( !::CreatePipe(&m_handles[0], &m_handles[1], &security, 0) )
+ {
+ wxLogSysError(_("Failed to create an anonymous pipe"));
+
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // return TRUE if we were created successfully
+ bool IsOk() const { return m_handles[Read] != INVALID_HANDLE_VALUE; }
+
+ // return the descriptor for one of the pipe ends
+ HANDLE operator[](Direction which) const
+ {
+ wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_handles),
+ _T("invalid pipe index") );
+
+ return m_handles[which];
+ }
+
+ // detach a descriptor, meaning that the pipe dtor won't close it, and
+ // return it
+ HANDLE Detach(Direction which)
+ {
+ wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_handles),
+ _T("invalid pipe index") );
+
+ HANDLE handle = m_handles[which];
+ m_handles[which] = INVALID_HANDLE_VALUE;
+
+ return handle;
+ }
+
+ // close the pipe descriptors
+ void Close()
+ {
+ for ( size_t n = 0; n < WXSIZEOF(m_handles); n++ )
+ {
+ if ( m_handles[n] != INVALID_HANDLE_VALUE )
+ {
+ ::CloseHandle(m_handles[n]);
+ m_handles[n] = INVALID_HANDLE_VALUE;
+ }
+ }
+ }
+
+ // dtor closes the pipe descriptors
+ ~wxPipe() { Close(); }
+
+private:
+ HANDLE m_handles[2];
+};
+
+#endif // wxUSE_STREAMS
+
+// ============================================================================
+// implementation
+// ============================================================================