// Created: 10/17/99
// RCS-ID: $Id$
// Copyright: (c) David Webster
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/os2/private.h"
-#define INCL_DOS
-#include <os2.h>
+#define PURE_32
+#ifndef __EMX__
+#include <upm.h>
+#include <netcons.h>
+#include <netbios.h>
+#endif
#include <ctype.h>
-#include <direct.h>
+#ifdef __EMX__
+#include <dirent.h>
+#endif
#include <sys/stat.h>
#include <io.h>
#include <errno.h>
#include <stdarg.h>
+
// this message is sent when the process we're waiting for terminates
#define wxWM_PROC_TERMINATED (WM_USER + 10000)
+#ifndef NO_ERROR
+# define NO_ERROR 0
+#endif
+
// structure describing the process we're being waiting for
struct wxExecuteData
{
public:
~wxExecuteData()
{
-// TODO:
-/*
- if ( !::CloseHandle(hProcess) )
- {
- wxLogLastError("CloseHandle(hProcess)");
- }
-*/
+// cout << "Closing thread: " << endl;
+ DosExit(EXIT_PROCESS, 0);
}
- HWND hWnd; // window to send wxWM_PROC_TERMINATED to
- HANDLE hProcess; // handle of the process
- DWORD dwProcessId; // pid of the process
- wxProcess *handler;
- DWORD dwExitCode; // the exit code of the process
- bool state; // set to FALSE when the process finishes
+ 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 DWORD wxExecuteThread(wxExecuteData *data)
+static ULONG wxExecuteThread(
+ wxExecuteData* pData
+)
{
-// TODO:
-/*
- WaitForSingleObject(data->hProcess, INFINITE);
-
- // get the exit code
- if ( !GetExitCodeProcess(data->hProcess, &data->dwExitCode) )
+ 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("GetExitCodeProcess");
+ wxLogLastError("DosWaitChild");
}
-
- 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);
-*/
+ 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, UINT message,
- MPARAM wParam, MPARAM lParam)
+MRESULT APIENTRY wxExecuteWindowCbk(
+ HWND hWnd
+, ULONG ulMessage
+, MPARAM wParam
+, MPARAM lParam
+)
{
- if ( message == wxWM_PROC_TERMINATED )
+ if (ulMessage == wxWM_PROC_TERMINATED)
{
-// DestroyWindow(hWnd); // we don't need it any more
+ wxExecuteData* pData = (wxExecuteData *)lParam;
- wxExecuteData *data = (wxExecuteData *)lParam;
- if ( data->handler )
+ if (pData->pHandler)
{
- data->handler->OnTerminate((int)data->dwProcessId,
- (int)data->dwExitCode);
+ pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate
+ ,(int)pData->vResultCodes.codeResult
+ );
}
- if ( data->state )
+ if (pData->bState)
{
// we're executing synchronously, tell the waiting thread
// that the process finished
- data->state = 0;
+ pData->bState = 0;
}
else
{
// asynchronous execution - we should do the clean up
- delete data;
+ delete pData;
}
+ ::WinDestroyWindow(hWnd); // we don't need it any more
}
-
return 0;
}
-extern wxChar wxPanelClassName[];
-
-long wxExecute(const wxString& command, bool sync, wxProcess *handler)
+long wxExecute(
+ const wxString& rCommand
+, int flags
+, wxProcess* pHandler
+)
{
- wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") );
-
- // the old code is disabled because we really need a process handle
- // if we want to execute it asynchronously or even just get its
- // return code and for this we must use CreateProcess() and not
- // ShellExecute()
+ if (rCommand.IsEmpty())
+ {
+// cout << "empty command in wxExecute." << endl;
+ return 0;
+ }
// create the process
-// TODO:
-/*
- STARTUPINFO si;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
-
- PROCESS_INFORMATION pi;
-
- if ( ::CreateProcess(
- NULL, // application name (use only cmd line)
- (wxChar *)command.c_str(), // full command line
- NULL, // security attributes: defaults for both
- NULL, // the process and its main thread
- FALSE, // don't inherit handles
- CREATE_DEFAULT_ERROR_MODE, // flags
- NULL, // environment (use the same)
- NULL, // current directory (use the same)
- &si, // startup info (unused here)
- &pi // process info
- ) == 0 )
+ 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
+ ,(PSZ)rCommand.c_str()
+ );
+ if (rc != NO_ERROR)
{
- wxLogSysError(_("Execution of command '%s' failed"), command.c_str());
-
+ wxLogSysError(_("Execution of command '%s' failed with error: %ul"), rCommand.c_str(), rc);
return 0;
}
-
- // close unneeded handle
- if ( !::CloseHandle(pi.hThread) )
- wxLogLastError("CloseHandle(hThread)");
-
- // create a hidden window to receive notification about process
- // termination
- HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
- (HMENU)NULL, wxGetInstance(), 0);
- wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
-
- FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
- wxGetInstance());
-
- ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
-
+// cout << "Executing: " << rCommand.c_str() << endl;
// Alloc data
- wxExecuteData *data = new wxExecuteData;
- data->hProcess = pi.hProcess;
- data->dwProcessId = pi.dwProcessId;
- data->hWnd = hwnd;
- data->state = sync;
- if ( sync )
- {
- wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") );
+ wxExecuteData* pData = new wxExecuteData;
- data->handler = NULL;
+ 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
- data->handler = handler;
+ pData->pHandler = pHandler;
}
- DWORD tid;
- HANDLE hThread = ::CreateThread(NULL,
- 0,
- (LPTHREAD_START_ROUTINE)wxExecuteThread,
- (void *)data,
- 0,
- &tid);
-
- if ( !hThread )
+ rc = ::DosCreateThread( &vTID
+ ,(PFNTHREAD)&wxExecuteThread
+ ,(ULONG)pData
+ ,CREATE_READY|STACK_SPARSE
+ ,8192
+ );
+ if (rc != NO_ERROR)
{
wxLogLastError("CreateThread in wxExecute");
-
- DestroyWindow(hwnd);
- delete data;
+ delete pData;
// the process still started up successfully...
- return pi.dwProcessId;
+ return vResultCodes.codeTerminate;
}
-
- if ( !sync )
+ if (!(flags & wxEXEC_SYNC))
{
- // clean up will be done when the process terminates
-
// return the pid
- return pi.dwProcessId;
+ // 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
- while ( data->state )
- wxYield();
+ ::DosWaitThread(&vTID, DCWW_WAIT);
- DWORD dwExitCode = data->dwExitCode;
- delete data;
+ ULONG ulExitCode = pData->vResultCodes.codeResult;
+ delete pData;
// return the exit code
- return dwExitCode;
-*/
- return 0;
+ return (long)ulExitCode;
}
-long wxExecute(char **argv, bool sync, wxProcess *handler)
+long wxExecute(
+ char** ppArgv
+, int flags
+, wxProcess* pHandler
+)
{
- wxString command;
+ wxString sCommand;
- while ( *argv != NULL )
+ while (*ppArgv != NULL)
{
- command << *argv++ << ' ';
- }
+ wxString sArg((wxChar*)(*ppArgv++));
- command.RemoveLast();
- return wxExecute(command, sync, handler);
+ sCommand << sArg.c_str() << ' ';
+ }
+ sCommand.RemoveLast();
+ return wxExecute( sCommand
+ ,flags
+ ,pHandler
+ );
}
-bool wxGetFullHostName(wxChar *buf, int maxSize)
+bool wxGetFullHostName(
+ wxChar* zBuf
+, int nMaxSize
+)
{
- DWORD nSize = maxSize ;
-// TODO:
-/*
- if ( !::GetComputerName(buf, &nSize) )
- {
- wxLogLastError("GetComputerName");
-
- return FALSE;
- }
-*/
+#if wxUSE_NET_API
+ char zServer[256];
+ char zComputer[256];
+ unsigned long ulLevel = 0;
+ unsigned char* zBuffer = NULL;
+ unsigned long ulBuffer = 256;
+ unsigned long* pulTotalAvail = NULL;
+
+ NetBios32GetInfo( (const unsigned char*)zServer
+ ,(const unsigned char*)zComputer
+ ,ulLevel
+ ,zBuffer
+ ,ulBuffer
+ ,pulTotalAvail
+ );
+ strncpy(zBuf, zComputer, nMaxSize);
+ zBuf[nMaxSize] = _T('\0');
+#else
+ strcpy((char*)zBuf, "noname");
+#endif
+ return *zBuf ? TRUE : FALSE;
return TRUE;
}