bool wxTextDataObject::GetDataHere(void *buf) const { // NOTE: use wxTmemcpy() instead of wxStrncpy() to allow // retrieval of strings with embedded NULLs wxTmemcpy( (wxChar*)buf, GetText().c_str(), GetTextLength() ); return true; }
const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormalize) { wxASSERT(uri != NULL); //copy of the uri - used for figuring out //length of each component const wxChar* uricopy = uri; /// hier-part = "//" authority path-abempty /// / path-absolute /// / path-rootless /// / path-empty /// /// relative-part = "//" authority path-abempty /// / path-absolute /// / path-noscheme /// / path-empty /// /// path-abempty = *( "/" segment ) /// path-absolute = "/" [ segment-nz *( "/" segment ) ] /// path-noscheme = segment-nz-nc *( "/" segment ) /// path-rootless = segment-nz *( "/" segment ) /// path-empty = 0<pchar> /// /// segment = *pchar /// segment-nz = 1*pchar /// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) /// ; non-zero-length segment without any colon ":" /// /// pchar = unreserved / pct-encoded / sub-delims / ":" / "@" if (*uri == wxT('/')) { m_path += *uri++; while(*uri && *uri != wxT('#') && *uri != wxT('?')) { if( IsUnreserved(*uri) || IsSubDelim(*uri) || *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/')) m_path += *uri++; else if (IsEscape(uri)) { m_path += *uri++; m_path += *uri++; m_path += *uri++; } else Escape(m_path, *uri++); } if (bNormalize) { wxStringBufferLength theBuffer(m_path, m_path.length() + 1); #if wxUSE_STL wxTmemcpy(theBuffer, m_path.c_str(), m_path.length()+1); #endif Normalize(theBuffer, true); theBuffer.SetLength(wxStrlen(theBuffer)); } //mark the path as valid m_fields |= wxURI_PATH; } else if(*uri) //Relative path { if (bReference) { //no colon allowed while(*uri && *uri != wxT('#') && *uri != wxT('?')) { if(IsUnreserved(*uri) || IsSubDelim(*uri) || *uri == wxT('@') || *uri == wxT('/')) m_path += *uri++; else if (IsEscape(uri)) { m_path += *uri++; m_path += *uri++; m_path += *uri++; } else Escape(m_path, *uri++); } } else { while(*uri && *uri != wxT('#') && *uri != wxT('?')) { if(IsUnreserved(*uri) || IsSubDelim(*uri) || *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/')) m_path += *uri++; else if (IsEscape(uri)) { m_path += *uri++; m_path += *uri++; m_path += *uri++; } else Escape(m_path, *uri++); } } if (uri != uricopy) { if (bNormalize) { wxStringBufferLength theBuffer(m_path, m_path.length() + 1); #if wxUSE_STL wxTmemcpy(theBuffer, m_path.c_str(), m_path.length()+1); #endif Normalize(theBuffer); theBuffer.SetLength(wxStrlen(theBuffer)); } //mark the path as valid m_fields |= wxURI_PATH; } } return uri; }
long wxExecute(const wxString& cmd, int flags, wxProcess *handler, const wxExecuteEnv *env) { wxCHECK_MSG( !cmd.empty(), 0, wxT("empty command in wxExecute") ); #if wxUSE_THREADS // for many reasons, the code below breaks down if it's called from another // 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(), wxT("wxExecute() can be called only from the main thread") ); #endif // wxUSE_THREADS wxString command; #if wxUSE_IPC // DDE hack: this is really not pretty, but we need to allow this for // transparent handling of DDE servers in wxMimeTypesManager. Usually it // returns the command which should be run to view/open/... a file of the // given type. Sometimes, however, this command just launches the server // and an additional DDE request must be made to really open the file. To // keep all this well hidden from the application, we allow a special form // of command: WX_DDE#<command>#DDE_SERVER#DDE_TOPIC#DDE_COMMAND in which // case we execute just <command> and process the rest below wxString ddeServer, ddeTopic, ddeCommand; static const size_t lenDdePrefix = 7; // strlen("WX_DDE:") if ( cmd.Left(lenDdePrefix) == wxT("WX_DDE#") ) { // speed up the concatenations below ddeServer.reserve(256); ddeTopic.reserve(256); ddeCommand.reserve(256); const wxChar *p = cmd.c_str() + 7; #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ while ( *p && *p != wxT('#') ) { command += *p++; } if ( *p ) { // skip '#' p++; } else { wxFAIL_MSG(wxT("invalid WX_DDE command in wxExecute")); } #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ while ( *p && *p != wxT('#') ) { ddeServer += *p++; } if ( *p ) { // skip '#' p++; } else { wxFAIL_MSG(wxT("invalid WX_DDE command in wxExecute")); } #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ while ( *p && *p != wxT('#') ) { ddeTopic += *p++; } if ( *p ) { // skip '#' p++; } else { wxFAIL_MSG(wxT("invalid WX_DDE command in wxExecute")); } #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ while ( *p ) { ddeCommand += *p++; } // if we want to just launch the program and not wait for its // termination, try to execute DDE command right now, it can succeed if // the process is already running - but as it fails if it's not // running, suppress any errors it might generate if ( !(flags & wxEXEC_SYNC) ) { wxLogNull noErrors; if ( wxExecuteDDE(ddeServer, ddeTopic, ddeCommand) ) { // a dummy PID - this is a hack, of course, but it's well worth // it as we don't open a new server each time we're called // which would be quite bad return -1; } } } else #endif // wxUSE_IPC { // no DDE command = cmd; } // the IO redirection is only supported with wxUSE_STREAMS BOOL redirect = FALSE; #if wxUSE_STREAMS wxPipe pipeIn, pipeOut, pipeErr; // open the pipes to which child process IO will be redirected if needed if ( handler && handler->IsRedirected() ) { // create pipes for redirecting stdin, stdout and stderr if ( !pipeIn.Create() || !pipeOut.Create() || !pipeErr.Create() ) { wxLogSysError(_("Failed to redirect the child process IO")); // indicate failure: we need to return different error code // depending on the sync flag return flags & wxEXEC_SYNC ? -1 : 0; } redirect = TRUE; } #endif // wxUSE_STREAMS // create the process STARTUPINFO si; wxZeroMemory(si); si.cb = sizeof(si); #if wxUSE_STREAMS if ( redirect ) { si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = pipeIn[wxPipe::Read]; si.hStdOutput = pipeOut[wxPipe::Write]; si.hStdError = pipeErr[wxPipe::Write]; // We must set the handles to those sides of std* pipes that we won't // in the child to be non-inheritable. We must do this before launching // the child process as otherwise these handles will be inherited by // the child which will never close them and so the pipe will not // return ERROR_BROKEN_PIPE if the parent or child exits unexpectedly // causing the remaining process to potentially become deadlocked in // ReadFile() or WriteFile(). if ( !::SetHandleInformation(pipeIn[wxPipe::Write], HANDLE_FLAG_INHERIT, 0) ) wxLogLastError(wxT("SetHandleInformation(pipeIn)")); if ( !::SetHandleInformation(pipeOut[wxPipe::Read], HANDLE_FLAG_INHERIT, 0) ) wxLogLastError(wxT("SetHandleInformation(pipeOut)")); if ( !::SetHandleInformation(pipeErr[wxPipe::Read], HANDLE_FLAG_INHERIT, 0) ) wxLogLastError(wxT("SetHandleInformation(pipeErr)")); } #endif // wxUSE_STREAMS // The default logic for showing the console is to show it only if the IO // is not redirected however wxEXEC_{SHOW,HIDE}_CONSOLE flags can be // explicitly specified to change it. if ( (flags & wxEXEC_HIDE_CONSOLE) || (redirect && !(flags & wxEXEC_SHOW_CONSOLE)) ) { si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; } PROCESS_INFORMATION pi; DWORD dwFlags = CREATE_SUSPENDED; if ( (flags & wxEXEC_MAKE_GROUP_LEADER) ) dwFlags |= CREATE_NEW_PROCESS_GROUP; dwFlags |= CREATE_DEFAULT_ERROR_MODE ; 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' #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ 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(); #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ 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; } } // Translate wxWidgets priority to Windows conventions. if ( handler ) { unsigned prio = handler->GetPriority(); if ( prio <= 20 ) dwFlags |= IDLE_PRIORITY_CLASS; else if ( prio <= 40 ) dwFlags |= BELOW_NORMAL_PRIORITY_CLASS; else if ( prio <= 60 ) dwFlags |= NORMAL_PRIORITY_CLASS; else if ( prio <= 80 ) dwFlags |= ABOVE_NORMAL_PRIORITY_CLASS; else if ( prio <= 99 ) dwFlags |= HIGH_PRIORITY_CLASS; else if ( prio <= 100 ) dwFlags |= REALTIME_PRIORITY_CLASS; else { wxFAIL_MSG(wxT("invalid value of thread priority parameter")); dwFlags |= NORMAL_PRIORITY_CLASS; } } bool ok = ::CreateProcess ( NULL, // application name (use only cmd line) wxMSW_CONV_LPTSTR(command), // full command line NULL, // security attributes: defaults for both NULL, // the process and its main thread redirect, // inherit handles if we use pipes dwFlags, // process creation flags envBuffer.data(), // environment (may be NULL which is fine) useCwd // initial working directory ? wxMSW_CONV_LPTSTR(env->cwd) : NULL, // (or use the same) &si, // startup info (unused here) &pi // process info ) != 0; #if wxUSE_STREAMS // we can close the pipe ends used by child anyhow if ( redirect ) { ::CloseHandle(pipeIn.Detach(wxPipe::Read)); ::CloseHandle(pipeOut.Detach(wxPipe::Write)); ::CloseHandle(pipeErr.Detach(wxPipe::Write)); } #endif // wxUSE_STREAMS if ( !ok ) { #if wxUSE_STREAMS // close the other handles too if ( redirect ) { ::CloseHandle(pipeIn.Detach(wxPipe::Write)); ::CloseHandle(pipeOut.Detach(wxPipe::Read)); ::CloseHandle(pipeErr.Detach(wxPipe::Read)); } #endif // wxUSE_STREAMS wxLogSysError(_("Execution of command '%s' failed"), command.c_str()); return flags & wxEXEC_SYNC ? -1 : 0; } #if wxUSE_STREAMS // the input buffer bufOut is connected to stdout, this is why it is // called bufOut and not bufIn wxStreamTempInputBuffer bufOut, bufErr; if ( redirect ) { // We can now initialize the wxStreams wxPipeInputStream * outStream = new wxPipeInputStream(pipeOut.Detach(wxPipe::Read)); wxPipeInputStream * errStream = new wxPipeInputStream(pipeErr.Detach(wxPipe::Read)); wxPipeOutputStream * inStream = new wxPipeOutputStream(pipeIn.Detach(wxPipe::Write)); handler->SetPipeStreams(outStream, inStream, errStream); bufOut.Init(outStream); bufErr.Init(errStream); } #endif // wxUSE_STREAMS // create a hidden window to receive notification about process // termination HWND hwnd = wxCreateHiddenWindow ( &gs_classForHiddenWindow, wxMSWEXEC_WNDCLASSNAME, (WNDPROC)wxExecuteWindowCbk ); wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") ); // Alloc data wxExecuteData *data = new wxExecuteData; data->hProcess = pi.hProcess; data->dwProcessId = pi.dwProcessId; data->hWnd = hwnd; data->state = (flags & wxEXEC_SYNC) != 0; if ( flags & wxEXEC_SYNC ) { // handler may be !NULL for capturing program output, but we don't use // it wxExecuteData struct in this case data->handler = NULL; } else { // may be NULL or not data->handler = handler; if (handler) handler->SetPid(pi.dwProcessId); } DWORD tid; HANDLE hThread = ::CreateThread(NULL, 0, wxExecuteThread, (void *)data, 0, &tid); // resume process we created now - whether the thread creation succeeded or // not if ( ::ResumeThread(pi.hThread) == (DWORD)-1 ) { // ignore it - what can we do? wxLogLastError(wxT("ResumeThread in wxExecute")); } // close unneeded handle if ( !::CloseHandle(pi.hThread) ) { wxLogLastError(wxT("CloseHandle(hThread)")); } if ( !hThread ) { wxLogLastError(wxT("CreateThread in wxExecute")); DestroyWindow(hwnd); delete data; // the process still started up successfully... return pi.dwProcessId; } gs_asyncThreads.push_back(hThread); data->hThread = hThread; #if wxUSE_IPC // second part of DDE hack: now establish the DDE conversation with the // just launched process if ( !ddeServer.empty() ) { bool ddeOK; // give the process the time to init itself // // we use a very big timeout hoping that WaitForInputIdle() will return // much sooner, but not INFINITE just in case the process hangs // completely - like this we will regain control sooner or later switch ( ::WaitForInputIdle(pi.hProcess, 10000 /* 10 seconds */) ) { default: wxFAIL_MSG( wxT("unexpected WaitForInputIdle() return code") ); // fall through case WAIT_FAILED: wxLogLastError(wxT("WaitForInputIdle() in wxExecute")); case WAIT_TIMEOUT: wxLogDebug(wxT("Timeout too small in WaitForInputIdle")); ddeOK = false; break; case 0: // ok, process ready to accept DDE requests ddeOK = wxExecuteDDE(ddeServer, ddeTopic, ddeCommand); } if ( !ddeOK ) { wxLogDebug(wxT("Failed to send DDE request to the process \"%s\"."), cmd.c_str()); } } #endif // wxUSE_IPC if ( !(flags & wxEXEC_SYNC) ) { // clean up will be done when the process terminates // return the pid return pi.dwProcessId; } wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; wxCHECK_MSG( traits, -1, wxT("no wxAppTraits in wxExecute()?") ); void *cookie = NULL; if ( !(flags & wxEXEC_NODISABLE) ) { // disable all app windows while waiting for the child process to finish cookie = traits->BeforeChildWaitLoop(); } // wait until the child process terminates #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ while ( data->state ) { #if wxUSE_STREAMS if ( !bufOut.Update() && !bufErr.Update() ) #endif // wxUSE_STREAMS { // don't eat 100% of the CPU -- ugly but anything else requires // real async IO which we don't have for the moment ::Sleep(50); } // we must always process messages for our hidden window or we'd never // get wxWM_PROC_TERMINATED and so this loop would never terminate MSG msg; ::PeekMessage(&msg, data->hWnd, 0, 0, PM_REMOVE); // we may also need to process messages for all the other application // windows if ( !(flags & wxEXEC_NOEVENTS) ) { wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); if ( loop ) loop->Yield(); } } if ( !(flags & wxEXEC_NODISABLE) ) { // reenable disabled windows back traits->AfterChildWaitLoop(cookie); } DWORD dwExitCode = data->dwExitCode; delete data; // return the exit code return dwExitCode; }
const wxChar* wxURI::ParseServer(const wxChar* uri) { wxASSERT(uri != NULL); //copy of the uri - used for figuring out //length of each component const wxChar* uricopy = uri; // host = IP-literal / IPv4address / reg-name // IP-literal = "[" ( IPv6address / IPvFuture ) "]" if (*uri == wxT('[')) { ++uri; //some compilers don't support *&ing a ++* if (ParseIPv6address(uri) && *uri == wxT(']')) { ++uri; m_hostType = wxURI_IPV6ADDRESS; wxStringBufferLength theBuffer(m_server, uri - uricopy); wxTmemcpy(theBuffer, uricopy, uri-uricopy); theBuffer.SetLength(uri-uricopy); } else { uri = uricopy; ++uri; //some compilers don't support *&ing a ++* if (ParseIPvFuture(uri) && *uri == wxT(']')) { ++uri; m_hostType = wxURI_IPVFUTURE; wxStringBufferLength theBuffer(m_server, uri - uricopy); wxTmemcpy(theBuffer, uricopy, uri-uricopy); theBuffer.SetLength(uri-uricopy); } else uri = uricopy; } } else { if (ParseIPv4address(uri)) { m_hostType = wxURI_IPV4ADDRESS; wxStringBufferLength theBuffer(m_server, uri - uricopy); wxTmemcpy(theBuffer, uricopy, uri-uricopy); theBuffer.SetLength(uri-uricopy); } else uri = uricopy; } if(m_hostType == wxURI_REGNAME) { uri = uricopy; // reg-name = *( unreserved / pct-encoded / sub-delims ) while(*uri && *uri != wxT('/') && *uri != wxT(':') && *uri != wxT('#') && *uri != wxT('?')) { if(IsUnreserved(*uri) || IsSubDelim(*uri)) m_server += *uri++; else if (IsEscape(uri)) { m_server += *uri++; m_server += *uri++; m_server += *uri++; } else Escape(m_server, *uri++); } } //mark the server as valid m_fields |= wxURI_SERVER; return uri; }