X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dbbcfbb642f5dffe1285bd39c41d8c4b3e1164c2..2d5779d44094cf386fce5cea2d7eb2ce4c5467f7:/src/msw/utilsexc.cpp diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 5d2e0b52cb..c2cc31a73b 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -82,9 +82,7 @@ #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); +#include "wx/msw/private/hiddenwin.h" // ---------------------------------------------------------------------------- // constants @@ -146,7 +144,7 @@ public: // running processes if ( !::SetEvent(gs_heventShutdown) ) { - wxLogDebug(_T("Failed to set shutdown event in wxExecuteModule")); + wxLogDebug(wxT("Failed to set shutdown event in wxExecuteModule")); } ::CloseHandle(gs_heventShutdown); @@ -165,7 +163,7 @@ public: 3000 // long but finite value ) == WAIT_TIMEOUT ) { - wxLogDebug(_T("Failed to stop all wxExecute monitor threads")); + wxLogDebug(wxT("Failed to stop all wxExecute monitor threads")); } for ( size_t n = 0; n < numThreads; n++ ) @@ -181,7 +179,7 @@ public: { if ( !::UnregisterClass(wxMSWEXEC_WNDCLASSNAME, wxGetInstance()) ) { - wxLogLastError(_T("UnregisterClass(wxExecClass)")); + wxLogLastError(wxT("UnregisterClass(wxExecClass)")); } gs_classForHiddenWindow = NULL; @@ -336,7 +334,7 @@ static DWORD __stdcall wxExecuteThread(void *arg) gs_heventShutdown = ::CreateEvent(NULL, TRUE, FALSE, NULL); if ( !gs_heventShutdown ) { - wxLogDebug(_T("CreateEvent() in wxExecuteThread failed")); + wxLogDebug(wxT("CreateEvent() in wxExecuteThread failed")); } } @@ -369,7 +367,7 @@ static DWORD __stdcall wxExecuteThread(void *arg) break; default: - wxLogDebug(_T("Waiting for the process termination failed!")); + wxLogDebug(wxT("Waiting for the process termination failed!")); } return 0; @@ -465,7 +463,7 @@ bool wxPipeInputStream::CanRead() const if ( ::GetLastError() != ERROR_BROKEN_PIPE ) { // unexpected error - wxLogLastError(_T("PeekNamedPipe")); + wxLogLastError(wxT("PeekNamedPipe")); } // don't try to continue reading from a pipe if an error occurred or if @@ -522,7 +520,7 @@ wxPipeOutputStream::wxPipeOutputStream(HANDLE hOutput) NULL // timeout (we don't set it neither) ) ) { - wxLogLastError(_T("SetNamedPipeHandleState(PIPE_NOWAIT)")); + wxLogLastError(wxT("SetNamedPipeHandleState(PIPE_NOWAIT)")); } } @@ -610,7 +608,8 @@ wxExecuteDDE(const wxString& ddeServer, #endif // wxUSE_IPC -long wxExecute(const wxString& cmd, int flags, wxProcess *handler) +long wxExecute(const wxString& cmd, int flags, wxProcess *handler, + const wxExecuteEnv *env) { wxCHECK_MSG( !cmd.empty(), 0, wxT("empty command in wxExecute") ); @@ -619,7 +618,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) // thread -- this could be fixed, but as Unix versions don't support this // neither I don't want to waste time on this now wxASSERT_MSG( wxThread::IsMain(), - _T("wxExecute() can be called only from the main thread") ); + wxT("wxExecute() can be called only from the main thread") ); #endif // wxUSE_THREADS wxString command; @@ -635,7 +634,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) // case we execute just and process the rest below wxString ddeServer, ddeTopic, ddeCommand; static const size_t lenDdePrefix = 7; // strlen("WX_DDE:") - if ( cmd.Left(lenDdePrefix) == _T("WX_DDE#") ) + if ( cmd.Left(lenDdePrefix) == wxT("WX_DDE#") ) { // speed up the concatenations below ddeServer.reserve(256); @@ -643,7 +642,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) ddeCommand.reserve(256); const wxChar *p = cmd.c_str() + 7; - while ( *p && *p != _T('#') ) + while ( *p && *p != wxT('#') ) { command += *p++; } @@ -655,10 +654,10 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) } else { - wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute")); + wxFAIL_MSG(wxT("invalid WX_DDE command in wxExecute")); } - while ( *p && *p != _T('#') ) + while ( *p && *p != wxT('#') ) { ddeServer += *p++; } @@ -670,10 +669,10 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) } else { - wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute")); + wxFAIL_MSG(wxT("invalid WX_DDE command in wxExecute")); } - while ( *p && *p != _T('#') ) + while ( *p && *p != wxT('#') ) { ddeTopic += *p++; } @@ -685,7 +684,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) } else { - wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute")); + wxFAIL_MSG(wxT("invalid WX_DDE command in wxExecute")); } while ( *p ) @@ -782,7 +781,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) DUPLICATE_SAME_ACCESS // same access as for src handle ) ) { - wxLogLastError(_T("DuplicateHandle")); + wxLogLastError(wxT("DuplicateHandle")); } ::CloseHandle(pipeInWrite); @@ -800,6 +799,55 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) wxString arguments = command.AfterFirst(wxT(' ')); #endif + wxWxCharBuffer envBuffer; + bool useCwd = false; + if ( env ) + { + useCwd = !env->cwd.empty(); + + // Translate environment variable map into NUL-terminated list of + // NUL-terminated strings. + if ( !env->env.empty() ) + { +#if wxUSE_UNICODE + // Environment variables can contain non-ASCII characters. We could + // check for it and not use this flag if everything is really ASCII + // only but there doesn't seem to be any reason to do it so just + // assume Unicode by default. + dwFlags |= CREATE_UNICODE_ENVIRONMENT; +#endif // wxUSE_UNICODE + + wxEnvVariableHashMap::const_iterator it; + + size_t envSz = 1; // ending '\0' + for ( it = env->env.begin(); it != env->env.end(); ++it ) + { + // Add size of env variable name and value, and '=' char and + // ending '\0' + envSz += it->first.length() + it->second.length() + 2; + } + + envBuffer.extend(envSz); + + wxChar *p = envBuffer.data(); + for ( it = env->env.begin(); it != env->env.end(); ++it ) + { + const wxString line = it->first + wxS("=") + it->second; + + // Include the trailing NUL which will always terminate the + // buffer returned by t_str(). + const size_t len = line.length() + 1; + + wxTmemcpy(p, line.t_str(), len); + + p += len; + } + + // And another NUL to terminate the list of NUL-terminated strings. + *p = 0; + } + } + bool ok = ::CreateProcess ( // WinCE requires appname to be non null @@ -818,8 +866,10 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) NULL, // the process and its main thread redirect, // inherit handles if we use pipes dwFlags, // process creation flags - NULL, // environment (use the same) - NULL, // current directory (use the same) + envBuffer.data(), // environment (may be NULL which is fine) + useCwd // initial working directory + ? const_cast(env->cwd.wx_str()) + : NULL, // (or use the same) &si, // startup info (unused here) &pi // process info ) != 0; @@ -923,7 +973,9 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) // close unneeded handle if ( !::CloseHandle(pi.hThread) ) + { wxLogLastError(wxT("CloseHandle(hThread)")); + } if ( !hThread ) { @@ -953,14 +1005,14 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) switch ( ::WaitForInputIdle(pi.hProcess, 10000 /* 10 seconds */) ) { default: - wxFAIL_MSG( _T("unexpected WaitForInputIdle() return code") ); + wxFAIL_MSG( wxT("unexpected WaitForInputIdle() return code") ); // fall through - case -1: - wxLogLastError(_T("WaitForInputIdle() in wxExecute")); + case WAIT_FAILED: + wxLogLastError(wxT("WaitForInputIdle() in wxExecute")); case WAIT_TIMEOUT: - wxLogDebug(_T("Timeout too small in WaitForInputIdle")); + wxLogDebug(wxT("Timeout too small in WaitForInputIdle")); ok = false; break; @@ -972,7 +1024,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) if ( !ok ) { - wxLogDebug(_T("Failed to send DDE request to the process \"%s\"."), + wxLogDebug(wxT("Failed to send DDE request to the process \"%s\"."), cmd.c_str()); } } @@ -987,7 +1039,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) } wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; - wxCHECK_MSG( traits, -1, _T("no wxAppTraits in wxExecute()?") ); + wxCHECK_MSG( traits, -1, wxT("no wxAppTraits in wxExecute()?") ); void *cookie = NULL; if ( !(flags & wxEXEC_NODISABLE) ) @@ -1037,7 +1089,8 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) } template -long wxExecuteImpl(CharType **argv, int flags, wxProcess *handler) +long wxExecuteImpl(CharType **argv, int flags, wxProcess *handler, + const wxExecuteEnv *env) { wxString command; command.reserve(1024); @@ -1076,19 +1129,21 @@ long wxExecuteImpl(CharType **argv, int flags, wxProcess *handler) command += ' '; } - return wxExecute(command, flags, handler); + return wxExecute(command, flags, handler, env); } -long wxExecute(char **argv, int flags, wxProcess *handler) +long wxExecute(char **argv, int flags, wxProcess *handler, + const wxExecuteEnv *env) { - return wxExecuteImpl(argv, flags, handler); + return wxExecuteImpl(argv, flags, handler, env); } #if wxUSE_UNICODE -long wxExecute(wchar_t **argv, int flags, wxProcess *handler) +long wxExecute(wchar_t **argv, int flags, wxProcess *handler, + const wxExecuteEnv *env) { - return wxExecuteImpl(argv, flags, handler); + return wxExecuteImpl(argv, flags, handler, env); } #endif // wxUSE_UNICODE