+// 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
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// process termination detecting support
+// ----------------------------------------------------------------------------
+
+// thread function for the thread monitoring the process termination
+static DWORD __stdcall wxExecuteThread(void *arg)
+{
+ wxExecuteData * const data = (wxExecuteData *)arg;
+
+ if ( ::WaitForSingleObject(data->hProcess, INFINITE) != WAIT_OBJECT_0 )
+ {
+ wxLogDebug(_T("Waiting for the process termination failed!"));
+ }
+
+ // get the exit code
+ if ( !::GetExitCodeProcess(data->hProcess, &data->dwExitCode) )
+ {
+ wxLogLastError(wxT("GetExitCodeProcess"));
+ }
+
+ wxASSERT_MSG( data->dwExitCode != STILL_ACTIVE,
+ wxT("process should have terminated") );
+
+ // send a message indicating process termination to the window
+ ::SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data);
+
+ return 0;
+}
+
+// window procedure of a hidden window which is created just to receive
+// the notification message when a process exits
+LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ if ( message == wxWM_PROC_TERMINATED )
+ {
+ DestroyWindow(hWnd); // we don't need it any more
+
+ wxExecuteData * const data = (wxExecuteData *)lParam;
+ if ( data->handler )
+ {
+ data->handler->OnTerminate((int)data->dwProcessId,
+ (int)data->dwExitCode);
+ }
+
+ if ( data->state )
+ {
+ // we're executing synchronously, tell the waiting thread
+ // that the process finished
+ data->state = 0;
+ }
+ else
+ {
+ // asynchronous execution - we should do the clean up
+ delete data;
+ }
+
+ return 0;
+ }
+ else
+ {
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+ }
+}
+
+// ============================================================================
+// implementation of IO redirection support classes
+// ============================================================================
+
+#if wxUSE_STREAMS && !defined(__WXWINCE__)
+
+// ----------------------------------------------------------------------------
+// wxPipeInputStreams
+// ----------------------------------------------------------------------------