+ bool state; // set to false when the process finishes
+};
+
+class wxExecuteModule : public wxModule
+{
+public:
+ virtual bool OnInit() { return true; }
+ virtual void OnExit()
+ {
+ if ( gs_heventShutdown )
+ {
+ // stop any threads waiting for the termination of asynchronously
+ // running processes
+ if ( !::SetEvent(gs_heventShutdown) )
+ {
+ wxLogDebug(wxT("Failed to set shutdown event in wxExecuteModule"));
+ }
+
+ ::CloseHandle(gs_heventShutdown);
+ gs_heventShutdown = NULL;
+
+ // now wait until they terminate
+ if ( !gs_asyncThreads.empty() )
+ {
+ const size_t numThreads = gs_asyncThreads.size();
+
+ if ( ::WaitForMultipleObjects
+ (
+ numThreads,
+ &gs_asyncThreads[0],
+ TRUE, // wait for all of them to become signalled
+ 3000 // long but finite value
+ ) == WAIT_TIMEOUT )
+ {
+ wxLogDebug(wxT("Failed to stop all wxExecute monitor threads"));
+ }
+
+ for ( size_t n = 0; n < numThreads; n++ )
+ {
+ ::CloseHandle(gs_asyncThreads[n]);
+ }
+
+ gs_asyncThreads.clear();
+ }
+ }
+
+ if ( gs_classForHiddenWindow )
+ {
+ if ( !::UnregisterClass(wxMSWEXEC_WNDCLASSNAME, wxGetInstance()) )
+ {
+ wxLogLastError(wxT("UnregisterClass(wxExecClass)"));
+ }
+
+ gs_classForHiddenWindow = NULL;
+ }
+ }
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxExecuteModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxExecuteModule, wxModule)
+
+#if wxUSE_STREAMS && !defined(__WXWINCE__)
+
+#include "wx/private/pipestream.h"
+#include "wx/private/streamtempinput.h"
+
+// ----------------------------------------------------------------------------
+// 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 { return m_handles[which]; }
+
+ // detach a descriptor, meaning that the pipe dtor won't close it, and
+ // return it
+ HANDLE Detach(Direction which)
+ {
+ 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];