X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0e320a79f187558effb04d92020b470372bbe456..57bf907d8e45ced18486d74c04f41c06034b7e65:/src/os2/utilsexc.cpp diff --git a/src/os2/utilsexc.cpp b/src/os2/utilsexc.cpp index b842d08e90..c50a311691 100644 --- a/src/os2/utilsexc.cpp +++ b/src/os2/utilsexc.cpp @@ -1,28 +1,243 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: utilsexec.cpp -// Purpose: Execution-related utilities -// Author: AUTHOR +// Name: src/os2/utilsexec.cpp +// Purpose: Various utilities +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/utils.h" + #include "wx/app.h" + #include "wx/intl.h" + #include "wx/log.h" +#endif + +#include "wx/process.h" + +#include "wx/os2/private.h" + +#define PURE_32 +#ifndef __EMX__ + #include + #ifndef __WATCOMC__ + #include + #include + #endif #endif -#include "wx/utils.h" +#include +#ifdef __EMX__ +#include +#endif + +#include +#include #include #include #include +#include +#include + -#define wxEXECUTE_WIN_MESSAGE 10000 +// this message is sent when the process we're waiting for terminates +#define wxWM_PROC_TERMINATED (WM_USER + 10000) -long wxExecute(const wxString& command, bool sync, wxProcess *handler) +#ifndef NO_ERROR +# define NO_ERROR 0 +#endif + +// structure describing the process we're being waiting for +struct wxExecuteData { - // TODO +public: + ~wxExecuteData() + { +// cout << "Closing thread: " << endl; + DosExit(EXIT_PROCESS, 0); + } + + HWND hWnd; // window to send wxWM_PROC_TERMINATED to [not used] + RESULTCODES vResultCodes; + wxProcess* pHandler; + ULONG ulExitCode; // the exit code of the process + bool bState; // set to false when the process finishes +}; + +static ULONG wxExecuteThread(wxExecuteData* pData) +{ + ULONG ulRc; + PID vPidChild; + +// cout << "Executing thread: " << endl; + + ulRc = ::DosWaitChild( DCWA_PROCESSTREE + ,DCWW_NOWAIT + ,&pData->vResultCodes + ,&vPidChild + ,pData->vResultCodes.codeTerminate // process PID to look at + ); + if (ulRc != NO_ERROR) + { + wxLogLastError(wxT("DosWaitChild")); + } + delete pData; + return 0; +} + +// window procedure of a hidden window which is created just to receive +// the notification message when a process exits +MRESULT APIENTRY wxExecuteWindowCbk( HWND hWnd, + ULONG ulMessage, + MPARAM WXUNUSED(wParam), + MPARAM lParam) +{ + if (ulMessage == wxWM_PROC_TERMINATED) + { + wxExecuteData* pData = (wxExecuteData *)lParam; + + if (pData->pHandler) + { + pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate + ,(int)pData->vResultCodes.codeResult + ); + } + + if (pData->bState) + { + // we're executing synchronously, tell the waiting thread + // that the process finished + pData->bState = 0; + } + else + { + // asynchronous execution - we should do the clean up + delete pData; + } + ::WinDestroyWindow(hWnd); // we don't need it any more + } return 0; } + +long wxExecute( const wxString& rCommand, + int flags, + wxProcess* pHandler) +{ + if (rCommand.empty()) + { +// cout << "empty command in wxExecute." << endl; + return 0; + } + + // create the process + UCHAR vLoadError[CCHMAXPATH] = {0}; + RESULTCODES vResultCodes = {0}; + ULONG ulExecFlag; + PSZ zArgs = NULL; + PSZ zEnvs = NULL; + APIRET rc; + TID vTID; + + if (flags & wxEXEC_SYNC) + ulExecFlag = EXEC_SYNC; + else + ulExecFlag = EXEC_ASYNCRESULT; + + rc = ::DosExecPgm( (PCHAR)vLoadError + ,sizeof(vLoadError) + ,ulExecFlag + ,zArgs + ,zEnvs + ,&vResultCodes + ,rCommand.c_str() + ); + if (rc != NO_ERROR) + { + wxLogSysError(_("Execution of command '%s' failed with error: %ul"), rCommand.c_str(), rc); + return 0; + } +// cout << "Executing: " << rCommand.c_str() << endl; + // Alloc data + wxExecuteData* pData = new wxExecuteData; + + pData->vResultCodes = vResultCodes; + pData->hWnd = NULLHANDLE; + pData->bState = (flags & wxEXEC_SYNC) != 0; + if (flags & wxEXEC_SYNC) + { + wxASSERT_MSG(!pHandler, wxT("wxProcess param ignored for sync execution")); + pData->pHandler = NULL; + } + else + { + // may be NULL or not + pData->pHandler = pHandler; + } + + rc = ::DosCreateThread( &vTID + ,(PFNTHREAD)&wxExecuteThread + ,(ULONG)pData + ,CREATE_READY|STACK_SPARSE + ,8192 + ); + if (rc != NO_ERROR) + { + wxLogLastError(wxT("CreateThread in wxExecute")); + delete pData; + + // the process still started up successfully... + return vResultCodes.codeTerminate; + } + if (!(flags & wxEXEC_SYNC)) + { + // return the pid + // warning: don't exit your app unless you actively + // kill and cleanup you child processes + // Maybe detach the process here??? + // If cmd.exe need to pass DETACH to detach the process here + return vResultCodes.codeTerminate; + } + + // waiting until command executed + ::DosWaitThread(&vTID, DCWW_WAIT); + + ULONG ulExitCode = pData->vResultCodes.codeResult; + delete pData; + + // return the exit code + return (long)ulExitCode; +} + +long wxExecute( + char** ppArgv +, int flags +, wxProcess* pHandler +) +{ + wxString sCommand; + + while (*ppArgv != NULL) + { + wxString sArg((wxChar*)(*ppArgv++)); + + + sCommand << sArg.c_str() << ' '; + } + sCommand.RemoveLast(); + return wxExecute( sCommand + ,flags + ,pHandler + ); +} + +bool wxGetFullHostName( wxChar* zBuf, int nMaxSize) +{ + return wxGetHostName( zBuf, nMaxSize ); +}