X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4dd03db9761040ce1b5175cd97e5ac99468af0bc..118322a3dfcc1803bd13df8193ea1be9ae39e653:/src/msw/utilsexc.cpp?ds=sidebyside diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 4e9958f801..4dcec53bde 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -5,7 +5,7 @@ // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) 1998-2002 wxWindows dev team +// Copyright: (c) 1998-2002 wxWidgets dev team // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,7 +17,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation #endif @@ -35,13 +35,13 @@ #include "wx/log.h" #endif -#ifdef __WIN32__ - #include "wx/stream.h" - #include "wx/process.h" -#endif +#include "wx/stream.h" +#include "wx/process.h" #include "wx/apptrait.h" +#include "wx/module.h" + #include "wx/msw/private.h" #include @@ -58,14 +58,14 @@ #include #endif -#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) -#ifndef __UNIX__ - #include -#endif +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) + #ifndef __UNIX__ + #include + #endif -#ifndef __GNUWIN32__ -#include -#endif + #ifndef __GNUWIN32__ + #include + #endif #endif #include @@ -82,6 +82,10 @@ #include "wx/dde.h" // for WX_DDE hack in wxExecute #endif // wxUSE_IPC +// implemented in utils.cpp +extern "C" WXDLLIMPEXP_BASE HWND +wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc); + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -96,6 +100,7 @@ // we need to create a hidden window to receive the process termination // notifications and for this we need a (Win) class name for it which we will // register the first time it's needed +static const wxChar *wxMSWEXEC_WNDCLASSNAME = wxT("_wxExecute_Internal_Class"); static const wxChar *gs_classForHiddenWindow = NULL; // ---------------------------------------------------------------------------- @@ -108,12 +113,10 @@ struct wxExecuteData public: ~wxExecuteData() { -#ifndef __WIN16__ if ( !::CloseHandle(hProcess) ) { wxLogLastError(wxT("CloseHandle(hProcess)")); } -#endif } HWND hWnd; // window to send wxWM_PROC_TERMINATED to @@ -124,7 +127,28 @@ public: bool state; // set to FALSE when the process finishes }; -#if defined(__WIN32__) && wxUSE_STREAMS && !defined(__WXWINCE__) +class wxExecuteModule : public wxModule +{ +public: + virtual bool OnInit() { return true; } + virtual void OnExit() + { + if ( *gs_classForHiddenWindow ) + { + if ( !::UnregisterClass(wxMSWEXEC_WNDCLASSNAME, wxGetInstance()) ) + { + wxLogLastError(_T("UnregisterClass(wxExecClass)")); + } + + gs_classForHiddenWindow = NULL; + } + } + +private: + DECLARE_DYNAMIC_CLASS(wxExecuteModule) +}; + +#if wxUSE_STREAMS && !defined(__WXWINCE__) // ---------------------------------------------------------------------------- // wxPipeStreams @@ -211,21 +235,12 @@ public: 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]; - } + 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) { - 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; @@ -258,8 +273,6 @@ private: // implementation // ============================================================================ -#ifdef __WIN32__ - // ---------------------------------------------------------------------------- // process termination detecting support // ---------------------------------------------------------------------------- @@ -414,6 +427,21 @@ size_t wxPipeInputStream::OnSysRead(void *buffer, size_t len) wxPipeOutputStream::wxPipeOutputStream(HANDLE hOutput) { m_hOutput = hOutput; + + // unblock the pipe to prevent deadlocks when we're writing to the pipe + // from which the child process can't read because it is writing in its own + // end of it + DWORD mode = PIPE_READMODE_BYTE | PIPE_NOWAIT; + if ( !::SetNamedPipeHandleState + ( + m_hOutput, + &mode, + NULL, // collection count (we don't set it) + NULL // timeout (we don't set it neither) + ) ) + { + wxLogLastError(_T("SetNamedPipeHandleState(PIPE_NOWAIT)")); + } } wxPipeOutputStream::~wxPipeOutputStream() @@ -423,23 +451,33 @@ wxPipeOutputStream::~wxPipeOutputStream() size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t len) { - DWORD bytesWritten; - m_lasterror = wxSTREAM_NO_ERROR; - if ( !::WriteFile(m_hOutput, buffer, len, &bytesWritten, NULL) ) + + DWORD totalWritten = 0; + while ( len > 0 ) { - m_lasterror = ::GetLastError() == ERROR_BROKEN_PIPE - ? wxSTREAM_EOF - : wxSTREAM_WRITE_ERROR; + DWORD chunkWritten; + if ( !::WriteFile(m_hOutput, buffer, len, &chunkWritten, NULL) ) + { + m_lasterror = ::GetLastError() == ERROR_BROKEN_PIPE + ? wxSTREAM_EOF + : wxSTREAM_WRITE_ERROR; + break; + } + + if ( !chunkWritten ) + break; + + buffer = (char *)buffer + chunkWritten; + totalWritten += chunkWritten; + len -= chunkWritten; } - return bytesWritten; + return totalWritten; } #endif // wxUSE_STREAMS -#endif // Win32 - // ============================================================================ // wxExecute functions family // ============================================================================ @@ -451,7 +489,7 @@ static bool wxExecuteDDE(const wxString& ddeServer, const wxString& ddeTopic, const wxString& ddeCommand) { - bool ok = FALSE; + bool ok wxDUMMY_INITIALIZE(false); wxDDEClient client; wxConnectionBase *conn = client.MakeConnection(wxEmptyString, @@ -738,36 +776,15 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) } #endif // wxUSE_STREAMS - // register the class for the hidden window used for the notifications - if ( !gs_classForHiddenWindow ) - { - gs_classForHiddenWindow = _T("wxHiddenWindow"); - - WNDCLASS wndclass; - wxZeroMemory(wndclass); - wndclass.lpfnWndProc = (WNDPROC)wxExecuteWindowCbk; - wndclass.hInstance = wxGetInstance(); - wndclass.lpszClassName = gs_classForHiddenWindow; - - if ( !::RegisterClass(&wndclass) ) - { - wxLogLastError(wxT("RegisterClass(hidden window)")); - } - } - // create a hidden window to receive notification about process // termination -#ifdef __WXWINCE__ - HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL, - WS_OVERLAPPED, - 0, 0, 0, 0, NULL, - (HMENU)NULL, wxGetInstance(), 0); -#else - HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL, - WS_OVERLAPPEDWINDOW, - 0, 0, 0, 0, NULL, - (HMENU)NULL, wxGetInstance(), 0); -#endif + HWND hwnd = wxCreateHiddenWindow + ( + &gs_classForHiddenWindow, + wxMSWEXEC_WNDCLASSNAME, + (WNDPROC)wxExecuteWindowCbk + ); + wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") ); // Alloc data @@ -852,6 +869,12 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) // ok, process ready to accept DDE requests ok = wxExecuteDDE(ddeServer, ddeTopic, ddeCommand); } + + if ( !ok ) + { + wxLogDebug(_T("Failed to send DDE request to the process \"%s\"."), + cmd.c_str()); + } } #endif // wxUSE_IPC