RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env) { const char * const *papszRet; if (Env == RTENV_DEFAULT) { papszRet = rtEnvDefault(); if (!papszRet) { static const char * const s_papszDummy[2] = { NULL, NULL }; papszRet = &s_papszDummy[0]; } } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, NULL); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, NULL); RTENV_LOCK(pIntEnv); /* * Free any old envp. */ if (pIntEnv->papszEnvOtherCP) { for (size_t iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++) { RTStrFree(pIntEnv->papszEnvOtherCP[iVar]); pIntEnv->papszEnvOtherCP[iVar] = NULL; } RTMemFree(pIntEnv->papszEnvOtherCP); pIntEnv->papszEnvOtherCP = NULL; } /* * Construct a new envp with the strings in the process code set. */ char **papsz; papszRet = pIntEnv->papszEnvOtherCP = papsz = (char **)RTMemAlloc(sizeof(char *) * (pIntEnv->cVars + 1)); if (papsz) { papsz[pIntEnv->cVars] = NULL; for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) { int rc = RTStrUtf8ToCurrentCP(&papsz[iVar], pIntEnv->papszEnv[iVar]); if (RT_FAILURE(rc)) { /* RTEnvDestroy / we cleans up later. */ papsz[iVar] = NULL; AssertRC(rc); papszRet = NULL; break; } } } RTENV_UNLOCK(pIntEnv); } return papszRet; }
RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertReturn(*pszVar, VERR_INVALID_PARAMETER); int rc; if (Env == RTENV_DEFAULT) { /* * Since RTEnvUnset isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { rc = RTEnvUnset(pszVarOtherCP); RTStrFree(pszVarOtherCP); } } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnv); /* * Remove all variable by the given name. */ rc = VINF_ENV_VAR_NOT_FOUND; const size_t cchVar = strlen(pszVar); size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar) && pIntEnv->papszEnv[iVar][cchVar] == '=') { RTMemFree(pIntEnv->papszEnv[iVar]); pIntEnv->cVars--; if (pIntEnv->cVars > 0) pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars]; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; rc = VINF_SUCCESS; /* no break, there could be more. */ } RTENV_UNLOCK(pIntEnv); } return rc; }
RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar) { AssertPtrReturn(pszVar, false); bool fExists = false; if (Env == RTENV_DEFAULT) { #ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API fExists = RTEnvExistsUtf8(pszVar); #else /* * Since RTEnvExist isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; int rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { fExists = RTEnvExist(pszVarOtherCP); RTStrFree(pszVarOtherCP); } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, false); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, false); RTENV_LOCK(pIntEnv); /* * Simple search. */ const size_t cchVar = strlen(pszVar); for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) if (!pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)) { if (pIntEnv->papszEnv[iVar][cchVar] == '=') { fExists = true; break; } if (pIntEnv->papszEnv[iVar][cchVar] == '\0') break; } RTENV_UNLOCK(pIntEnv); } return fExists; }
/** * @param aCompRegLocation Path to compreg.dat, in Utf8. * @param aXPTIDatLocation Path to xpti.data, in Utf8. */ HRESULT DirectoryServiceProvider::init(const char *aCompRegLocation, const char *aXPTIDatLocation, const char *aComponentDirLocation, const char *aCurrProcDirLocation) { AssertReturn(aCompRegLocation, NS_ERROR_INVALID_ARG); AssertReturn(aXPTIDatLocation, NS_ERROR_INVALID_ARG); /** @todo r=bird: Gotta check how this encoding stuff plays out on darwin! * We get down to [VBoxNsxp]NS_NewNativeLocalFile and that file isn't * nsLocalFileUnix.cpp on 32-bit darwin. On 64-bit darwin it's a question * of what we're doing in IPRT and such... We should probably add a * RTPathConvertToNative for use here. */ int vrc = RTStrUtf8ToCurrentCP(&mCompRegLocation, aCompRegLocation); if (RT_SUCCESS(vrc)) vrc = RTStrUtf8ToCurrentCP(&mXPTIDatLocation, aXPTIDatLocation); if (RT_SUCCESS(vrc) && aComponentDirLocation) vrc = RTStrUtf8ToCurrentCP(&mComponentDirLocation, aComponentDirLocation); if (RT_SUCCESS(vrc) && aCurrProcDirLocation) vrc = RTStrUtf8ToCurrentCP(&mCurrProcDirLocation, aCurrProcDirLocation); return RT_SUCCESS(vrc) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
/** @note To be called only from #AssignMachine() */ HRESULT Session::grabIPCSemaphore() { HRESULT rc = E_FAIL; /* open the IPC semaphore based on the sessionId and try to grab it */ Bstr ipcId; rc = mControl->GetIPCId(ipcId.asOutParam()); AssertComRCReturnRC(rc); LogFlowThisFunc(("ipcId='%ls'\n", ipcId.raw())); #if defined(RT_OS_WINDOWS) /* * Since Session is an MTA object, this method can be executed on * any thread, and this thread will not necessarily match the thread on * which close() will be called later. Therefore, we need a separate * thread to hold the IPC mutex and then release it in close(). */ mIPCThreadSem = ::CreateEvent(NULL, FALSE, FALSE, NULL); AssertMsgReturn(mIPCThreadSem, ("Cannot create an event sem, err=%d", ::GetLastError()), E_FAIL); void *data[3]; data[0] = (void*)(BSTR)ipcId.raw(); data[1] = (void*)mIPCThreadSem; data[2] = 0; /* will get an output from the thread */ /* create a thread to hold the IPC mutex until signalled to release it */ RTTHREAD tid; int vrc = RTThreadCreate(&tid, IPCMutexHolderThread, (void*)data, 0, RTTHREADTYPE_MAIN_WORKER, 0, "IPCHolder"); AssertRCReturn(vrc, E_FAIL); /* wait until thread init is completed */ DWORD wrc = ::WaitForSingleObject(mIPCThreadSem, INFINITE); AssertMsg(wrc == WAIT_OBJECT_0, ("Wait failed, err=%d\n", ::GetLastError())); Assert(data[2]); if (wrc == WAIT_OBJECT_0 && data[2]) { /* memorize the event sem we should signal in close() */ mIPCSem = (HANDLE)data[2]; rc = S_OK; } else { ::CloseHandle(mIPCThreadSem); mIPCThreadSem = NULL; rc = E_FAIL; } #elif defined(RT_OS_OS2) /* We use XPCOM where any message (including close()) can arrive on any * worker thread (which will not necessarily match this thread that opens * the mutex). Therefore, we need a separate thread to hold the IPC mutex * and then release it in close(). */ int vrc = RTSemEventCreate(&mIPCThreadSem); AssertRCReturn(vrc, E_FAIL); void *data[3]; data[0] = (void*)ipcId.raw(); data[1] = (void*)mIPCThreadSem; data[2] = (void*)false; /* will get the thread result here */ /* create a thread to hold the IPC mutex until signalled to release it */ vrc = RTThreadCreate(&mIPCThread, IPCMutexHolderThread, (void *) data, 0, RTTHREADTYPE_MAIN_WORKER, 0, "IPCHolder"); AssertRCReturn(vrc, E_FAIL); /* wait until thread init is completed */ vrc = RTThreadUserWait (mIPCThread, RT_INDEFINITE_WAIT); AssertReturn(RT_SUCCESS(vrc) || vrc == VERR_INTERRUPTED, E_FAIL); /* the thread must succeed */ AssertReturn((bool)data[2], E_FAIL); #elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) # ifdef VBOX_WITH_NEW_SYS_V_KEYGEN Utf8Str ipcKey = ipcId; key_t key = RTStrToUInt32(ipcKey.c_str()); AssertMsgReturn (key != 0, ("Key value of 0 is not valid for IPC semaphore"), E_FAIL); # else /* !VBOX_WITH_NEW_SYS_V_KEYGEN */ Utf8Str semName = ipcId; char *pszSemName = NULL; RTStrUtf8ToCurrentCP (&pszSemName, semName); key_t key = ::ftok (pszSemName, 'V'); RTStrFree (pszSemName); # endif /* !VBOX_WITH_NEW_SYS_V_KEYGEN */ mIPCSem = ::semget (key, 0, 0); AssertMsgReturn (mIPCSem >= 0, ("Cannot open IPC semaphore, errno=%d", errno), E_FAIL); /* grab the semaphore */ ::sembuf sop = { 0, -1, SEM_UNDO }; int rv = ::semop (mIPCSem, &sop, 1); AssertMsgReturn (rv == 0, ("Cannot grab IPC semaphore, errno=%d", errno), E_FAIL); #else # error "Port me!" #endif return rc; }
/** * Main thread. Starts also the LWIP thread. */ int VBoxNetLwipNAT::init() { LogFlowFuncEnter(); /* virtualbox initialized in super class */ int rc = ::VBoxNetBaseService::init(); AssertRCReturn(rc, rc); std::string networkName = getNetworkName(); rc = findNatNetwork(virtualbox, networkName, m_net); AssertRCReturn(rc, rc); ComEventTypeArray aNetEvents; aNetEvents.push_back(VBoxEventType_OnNATNetworkPortForward); aNetEvents.push_back(VBoxEventType_OnNATNetworkSetting); rc = createNatListener(m_listener, virtualbox, this, aNetEvents); AssertRCReturn(rc, rc); // resolver changes are reported on vbox but are retrieved from // host so stash a pointer for future lookups HRESULT hrc = virtualbox->COMGETTER(Host)(m_host.asOutParam()); AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); ComEventTypeArray aVBoxEvents; aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange); aVBoxEvents.push_back(VBoxEventType_OnNATNetworkStartStop); rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents); AssertRCReturn(rc, rc); BOOL fIPv6Enabled = FALSE; hrc = m_net->COMGETTER(IPv6Enabled)(&fIPv6Enabled); AssertComRCReturn(hrc, VERR_NOT_FOUND); BOOL fIPv6DefaultRoute = FALSE; if (fIPv6Enabled) { hrc = m_net->COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(&fIPv6DefaultRoute); AssertComRCReturn(hrc, VERR_NOT_FOUND); } m_ProxyOptions.ipv6_enabled = fIPv6Enabled; m_ProxyOptions.ipv6_defroute = fIPv6DefaultRoute; com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str()); com::Bstr bstrSourceIpX; hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIpX.asOutParam()); if (SUCCEEDED(hrc)) { RTNETADDRIPV4 addr; rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIpX).c_str(), &addr); if (RT_SUCCESS(rc)) { RT_ZERO(m_src4); m_src4.sin_addr.s_addr = addr.u; m_ProxyOptions.src4 = &m_src4; bstrSourceIpX.setNull(); } } if (!fDontLoadRulesOnStartup) { fetchNatPortForwardRules(m_net, false, m_vecPortForwardRule4); fetchNatPortForwardRules(m_net, true, m_vecPortForwardRule6); } /* if (!fDontLoadRulesOnStartup) */ AddressToOffsetMapping tmp; rc = localMappings(m_net, tmp); if (RT_SUCCESS(rc) && tmp.size() != 0) { unsigned long i = 0; for (AddressToOffsetMapping::iterator it = tmp.begin(); it != tmp.end() && i < RT_ELEMENTS(m_lo2off); ++it, ++i) { ip4_addr_set_u32(&m_lo2off[i].loaddr, it->first.u); m_lo2off[i].off = it->second; } m_loOptDescriptor.lomap = m_lo2off; m_loOptDescriptor.num_lomap = i; m_ProxyOptions.lomap_desc = &m_loOptDescriptor; } com::Bstr bstr; hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam()); AssertComRCReturn(hrc, VERR_NOT_FOUND); if (!bstr.isEmpty()) { com::Utf8Str strTftpRoot(com::Utf8StrFmt("%ls%c%s", bstr.raw(), RTPATH_DELIMITER, "TFTP")); char *pszStrTemp; // avoid const char ** vs char ** rc = RTStrUtf8ToCurrentCP(&pszStrTemp, strTftpRoot.c_str()); AssertRC(rc); m_ProxyOptions.tftp_root = pszStrTemp; } m_ProxyOptions.nameservers = getHostNameservers(); /* end of COM initialization */ rc = g_pLwipNat->tryGoOnline(); if (RT_FAILURE(rc)) return rc; /* this starts LWIP thread */ vboxLwipCoreInitialize(VBoxNetLwipNAT::onLwipTcpIpInit, this); LogFlowFuncLeaveRC(rc); return rc; }
RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER); AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER); AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER); AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); if (pcchActual) *pcchActual = 0; int rc; if (Env == RTENV_DEFAULT) { #ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API rc = RTEnvGetUtf8(pszVar, pszValue, cbValue, pcchActual); #else /* * Since RTEnvGet isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { const char *pszValueOtherCP = RTEnvGet(pszVarOtherCP); RTStrFree(pszVarOtherCP); if (pszValueOtherCP) { char *pszValueUtf8; rc = RTStrCurrentCPToUtf8(&pszValueUtf8, pszValueOtherCP); if (RT_SUCCESS(rc)) { rc = VINF_SUCCESS; size_t cch = strlen(pszValueUtf8); if (pcchActual) *pcchActual = cch; if (pszValue && cbValue) { if (cch < cbValue) memcpy(pszValue, pszValueUtf8, cch + 1); else rc = VERR_BUFFER_OVERFLOW; } RTStrFree(pszValueUtf8); } } else rc = VERR_ENV_VAR_NOT_FOUND; } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnv); /* * Locate the first variable and return it to the caller. */ rc = VERR_ENV_VAR_NOT_FOUND; const size_t cchVar = strlen(pszVar); size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if (!pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)) { if (pIntEnv->papszEnv[iVar][cchVar] == '=') { rc = VINF_SUCCESS; const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1; size_t cch = strlen(pszValueOrg); if (pcchActual) *pcchActual = cch; if (pszValue && cbValue) { if (cch < cbValue) memcpy(pszValue, pszValueOrg, cch + 1); else rc = VERR_BUFFER_OVERFLOW; } break; } if (pIntEnv->papszEnv[iVar][cchVar] == '\0') { Assert(pIntEnv->fPutEnvBlock); rc = VERR_ENV_VAR_UNSET; break; } } RTENV_UNLOCK(pIntEnv); } return rc; }
RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertReturn(*pszVar, VERR_INVALID_PARAMETER); AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); int rc; if (Env == RTENV_DEFAULT) { #ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API rc = RTEnvUnsetUtf8(pszVar); #else /* * Since RTEnvUnset isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { rc = RTEnvUnset(pszVarOtherCP); RTStrFree(pszVarOtherCP); } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnv); /* * Remove all variable by the given name. */ rc = VINF_ENV_VAR_NOT_FOUND; const size_t cchVar = strlen(pszVar); size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if ( !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar) && ( pIntEnv->papszEnv[iVar][cchVar] == '=' || pIntEnv->papszEnv[iVar][cchVar] == '\0') ) { if (!pIntEnv->fPutEnvBlock) { RTMemFree(pIntEnv->papszEnv[iVar]); pIntEnv->cVars--; if (pIntEnv->cVars > 0) pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars]; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; } else { /* Record this unset by keeping the variable without any equal sign. */ pIntEnv->papszEnv[iVar][cchVar] = '\0'; } rc = VINF_SUCCESS; /* no break, there could be more. */ } /* * If this is a change record, we may need to add it. */ if (rc == VINF_ENV_VAR_NOT_FOUND && pIntEnv->fPutEnvBlock) { char *pszEntry = (char *)RTMemDup(pszVar, cchVar + 1); if (pszEntry) { rc = rtEnvIntAppend(pIntEnv, pszEntry); if (RT_SUCCESS(rc)) rc = VINF_ENV_VAR_NOT_FOUND; else RTMemFree(pszEntry); } else rc = VERR_NO_MEMORY; } RTENV_UNLOCK(pIntEnv); } return rc; }
RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertReturn(*pszVar, VERR_INVALID_PARAMETER); AssertPtrReturn(pszValue, VERR_INVALID_POINTER); AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); int rc; if (Env == RTENV_DEFAULT) { #ifdef RT_OS_WINDOWS rc = RTEnvSetUtf8(pszVar, pszValue); #else /* * Since RTEnvPut isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { char *pszValueOtherCP; rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue); if (RT_SUCCESS(rc)) { rc = RTEnvSet(pszVarOtherCP, pszValueOtherCP); RTStrFree(pszValueOtherCP); } RTStrFree(pszVarOtherCP); } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); /* * Create the variable string. */ const size_t cchVar = strlen(pszVar); const size_t cchValue = strlen(pszValue); char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2); if (pszEntry) { memcpy(pszEntry, pszVar, cchVar); pszEntry[cchVar] = '='; memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1); RTENV_LOCK(pIntEnv); /* * Find the location of the variable. (iVar = cVars if new) */ rc = VINF_SUCCESS; size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if ( !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar) && ( pIntEnv->papszEnv[iVar][cchVar] == '=' || pIntEnv->papszEnv[iVar][cchVar] == '\0') ) break; if (iVar < pIntEnv->cVars) { /* * Replace the current entry. Simple. */ RTMemFree(pIntEnv->papszEnv[iVar]); pIntEnv->papszEnv[iVar] = pszEntry; } else { /* * New variable, append it. */ Assert(pIntEnv->cVars == iVar); rc = rtEnvIntAppend(pIntEnv, pszEntry); } RTENV_UNLOCK(pIntEnv); if (RT_FAILURE(rc)) RTMemFree(pszEntry); } else rc = VERR_NO_MEMORY; } return rc; }
/** * Internal write API, stream lock already held. * * @returns IPRT status code. * @param pStream The stream. * @param pvBuf What to write. * @param cbWrite How much to write. * @param pcbWritten Where to optionally return the number of bytes * written. * @param fSureIsText Set if we're sure this is UTF-8 text already. */ static int rtStrmWriteLocked(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite, size_t *pcbWritten, bool fSureIsText) { int rc = pStream->i32Error; if (RT_FAILURE(rc)) return rc; if (pStream->fRecheckMode) rtStreamRecheckMode(pStream); #ifdef RT_OS_WINDOWS /* * Use the unicode console API when possible in order to avoid stuff * getting lost in unnecessary code page translations. */ HANDLE hCon; if (rtStrmIsConsoleUnlocked(pStream, &hCon)) { # ifdef HAVE_FWRITE_UNLOCKED if (!fflush_unlocked(pStream->pFile)) # else if (!fflush(pStream->pFile)) # endif { /** @todo Consider buffering later. For now, we'd rather correct output than * fast output. */ DWORD cwcWritten = 0; PRTUTF16 pwszSrc = NULL; size_t cwcSrc = 0; rc = RTStrToUtf16Ex((const char *)pvBuf, cbWrite, &pwszSrc, 0, &cwcSrc); if (RT_SUCCESS(rc)) { if (!WriteConsoleW(hCon, pwszSrc, (DWORD)cwcSrc, &cwcWritten, NULL)) { /* try write char-by-char to avoid heap problem. */ cwcWritten = 0; while (cwcWritten != cwcSrc) { DWORD cwcThis; if (!WriteConsoleW(hCon, &pwszSrc[cwcWritten], 1, &cwcThis, NULL)) { if (!pcbWritten || cwcWritten == 0) rc = RTErrConvertFromErrno(GetLastError()); break; } if (cwcThis != 1) /* Unable to write current char (amount)? */ break; cwcWritten++; } } if (RT_SUCCESS(rc)) { if (cwcWritten == cwcSrc) { if (pcbWritten) *pcbWritten = cbWrite; } else if (pcbWritten) { PCRTUTF16 pwszCur = pwszSrc; const char *pszCur = (const char *)pvBuf; while ((uintptr_t)(pwszCur - pwszSrc) < cwcWritten) { RTUNICP CpIgnored; RTUtf16GetCpEx(&pwszCur, &CpIgnored); RTStrGetCpEx(&pszCur, &CpIgnored); } *pcbWritten = pszCur - (const char *)pvBuf; } else rc = VERR_WRITE_ERROR; } RTUtf16Free(pwszSrc); } } else rc = RTErrConvertFromErrno(errno); if (RT_FAILURE(rc)) ASMAtomicWriteS32(&pStream->i32Error, rc); return rc; } #endif /* RT_OS_WINDOWS */ /* * If we're sure it's text output, convert it from UTF-8 to the current * code page before printing it. * * Note! Partial writes are not supported in this scenario because we * cannot easily report back a written length matching the input. */ /** @todo Skip this if the current code set is UTF-8. */ if ( pStream->fCurrentCodeSet && !pStream->fBinary && ( fSureIsText || rtStrmIsUtf8Text(pvBuf, cbWrite)) ) { char *pszSrcFree = NULL; const char *pszSrc = (const char *)pvBuf; if (pszSrc[cbWrite]) { pszSrc = pszSrcFree = RTStrDupN(pszSrc, cbWrite); if (pszSrc == NULL) rc = VERR_NO_STR_MEMORY; } if (RT_SUCCESS(rc)) { char *pszSrcCurCP; rc = RTStrUtf8ToCurrentCP(&pszSrcCurCP, pszSrc); if (RT_SUCCESS(rc)) { size_t cchSrcCurCP = strlen(pszSrcCurCP); IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ #ifdef HAVE_FWRITE_UNLOCKED ssize_t cbWritten = fwrite_unlocked(pszSrcCurCP, cchSrcCurCP, 1, pStream->pFile); #else ssize_t cbWritten = fwrite(pszSrcCurCP, cchSrcCurCP, 1, pStream->pFile); #endif IPRT_ALIGNMENT_CHECKS_ENABLE(); if (cbWritten == 1) { if (pcbWritten) *pcbWritten = cbWrite; } #ifdef HAVE_FWRITE_UNLOCKED else if (!ferror_unlocked(pStream->pFile)) #else else if (!ferror(pStream->pFile)) #endif { if (pcbWritten) *pcbWritten = 0; } else rc = VERR_WRITE_ERROR; RTStrFree(pszSrcCurCP); } RTStrFree(pszSrcFree); } if (RT_FAILURE(rc)) ASMAtomicWriteS32(&pStream->i32Error, rc); return rc; }
/** * Initializes the COM runtime. * * This method must be called on each thread of the client application that * wants to access COM facilities. The initialization must be performed before * calling any other COM method or attempting to instantiate COM objects. * * On platforms using XPCOM, this method uses the following scheme to search for * XPCOM runtime: * * 1. If the VBOX_APP_HOME environment variable is set, the path it specifies * is used to search XPCOM libraries and components. If this method fails to * initialize XPCOM runtime using this path, it will immediately return a * failure and will NOT check for other paths as described below. * * 2. If VBOX_APP_HOME is not set, this methods tries the following paths in the * given order: * * a) Compiled-in application data directory (as returned by * RTPathAppPrivateArch()) * b) "/usr/lib/virtualbox" (Linux only) * c) "/opt/VirtualBox" (Linux only) * * The first path for which the initialization succeeds will be used. * * On MS COM platforms, the COM runtime is provided by the system and does not * need to be searched for. * * Once the COM subsystem is no longer necessary on a given thread, Shutdown() * must be called to free resources allocated for it. Note that a thread may * call Initialize() several times but for each of tese calls there must be a * corresponding Shutdown() call. * * @return S_OK on success and a COM result code in case of failure. */ HRESULT Initialize(bool fGui) { HRESULT rc = E_FAIL; #if !defined(VBOX_WITH_XPCOM) /* * We initialize COM in GUI thread in STA, to be compliant with QT and * OLE requirments (for example to allow D&D), while other threads * initialized in regular MTA. To allow fast proxyless access from * GUI thread to COM objects, we explicitly provide our COM objects * with free threaded marshaller. * !!!!! Please think twice before touching this code !!!!! */ DWORD flags = fGui ? COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY : COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE | COINIT_SPEED_OVER_MEMORY; rc = CoInitializeEx(NULL, flags); /* the overall result must be either S_OK or S_FALSE (S_FALSE means * "already initialized using the same apartment model") */ AssertMsg(rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc)); /* To be flow compatible with the XPCOM case, we return here if this isn't * the main thread or if it isn't its first initialization call. * Note! CoInitializeEx and CoUninitialize does it's own reference * counting, so this exercise is entirely for the EventQueue init. */ bool fRc; RTTHREAD hSelf = RTThreadSelf(); if (hSelf != NIL_RTTHREAD) ASMAtomicCmpXchgHandle(&gCOMMainThread, hSelf, NIL_RTTHREAD, fRc); else fRc = false; if (fGui) Assert(RTThreadIsMain(hSelf)); if (!fRc) { if ( gCOMMainThread == hSelf && SUCCEEDED(rc)) gCOMMainInitCount++; AssertComRC(rc); return rc; } Assert(RTThreadIsMain(hSelf)); /* this is the first main thread initialization */ Assert(gCOMMainInitCount == 0); if (SUCCEEDED(rc)) gCOMMainInitCount = 1; #else /* !defined (VBOX_WITH_XPCOM) */ /* Unused here */ NOREF(fGui); if (ASMAtomicXchgBool(&gIsXPCOMInitialized, true) == true) { /* XPCOM is already initialized on the main thread, no special * initialization is necessary on additional threads. Just increase * the init counter if it's a main thread again (to correctly support * nested calls to Initialize()/Shutdown() for compatibility with * Win32). */ nsCOMPtr<nsIEventQueue> eventQ; rc = NS_GetMainEventQ(getter_AddRefs(eventQ)); if (NS_SUCCEEDED(rc)) { PRBool isOnMainThread = PR_FALSE; rc = eventQ->IsOnCurrentThread(&isOnMainThread); if (NS_SUCCEEDED(rc) && isOnMainThread) ++gXPCOMInitCount; } AssertComRC(rc); return rc; } Assert(RTThreadIsMain(RTThreadSelf())); /* this is the first initialization */ gXPCOMInitCount = 1; bool const fInitEventQueues = true; /* prepare paths for registry files */ char szCompReg[RTPATH_MAX]; char szXptiDat[RTPATH_MAX]; int vrc = GetVBoxUserHomeDirectory(szCompReg, sizeof(szCompReg)); AssertRCReturn(vrc, NS_ERROR_FAILURE); strcpy(szXptiDat, szCompReg); vrc = RTPathAppend(szCompReg, sizeof(szCompReg), "compreg.dat"); AssertRCReturn(vrc, NS_ERROR_FAILURE); vrc = RTPathAppend(szXptiDat, sizeof(szXptiDat), "xpti.dat"); AssertRCReturn(vrc, NS_ERROR_FAILURE); LogFlowFunc(("component registry : \"%s\"\n", szCompReg)); LogFlowFunc(("XPTI data file : \"%s\"\n", szXptiDat)); #if defined (XPCOM_GLUE) XPCOMGlueStartup(nsnull); #endif static const char *kAppPathsToProbe[] = { NULL, /* 0: will use VBOX_APP_HOME */ NULL, /* 1: will try RTPathAppPrivateArch() */ #ifdef RT_OS_LINUX "/usr/lib/virtualbox", "/opt/VirtualBox", #elif RT_OS_SOLARIS "/opt/VirtualBox/amd64", "/opt/VirtualBox/i386", #elif RT_OS_DARWIN "/Application/VirtualBox.app/Contents/MacOS", #endif }; /* Find out the directory where VirtualBox binaries are located */ for (size_t i = 0; i < RT_ELEMENTS(kAppPathsToProbe); ++ i) { char szAppHomeDir[RTPATH_MAX]; if (i == 0) { /* Use VBOX_APP_HOME if present */ vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_APP_HOME", szAppHomeDir, sizeof(szAppHomeDir), NULL); if (vrc == VERR_ENV_VAR_NOT_FOUND) continue; AssertRC(vrc); } else if (i == 1) { /* Use RTPathAppPrivateArch() first */ vrc = RTPathAppPrivateArch(szAppHomeDir, sizeof(szAppHomeDir)); AssertRC(vrc); } else { /* Iterate over all other paths */ szAppHomeDir[RTPATH_MAX - 1] = '\0'; strncpy(szAppHomeDir, kAppPathsToProbe[i], RTPATH_MAX - 1); vrc = VINF_SUCCESS; } if (RT_FAILURE(vrc)) { rc = NS_ERROR_FAILURE; continue; } char szCompDir[RTPATH_MAX]; vrc = RTPathAppend(strcpy(szCompDir, szAppHomeDir), sizeof(szCompDir), "components"); if (RT_FAILURE(vrc)) { rc = NS_ERROR_FAILURE; continue; } LogFlowFunc(("component directory : \"%s\"\n", szCompDir)); nsCOMPtr<DirectoryServiceProvider> dsProv; dsProv = new DirectoryServiceProvider(); if (dsProv) rc = dsProv->init(szCompReg, szXptiDat, szCompDir, szAppHomeDir); else rc = NS_ERROR_OUT_OF_MEMORY; if (NS_FAILED(rc)) break; /* Setup the application path for NS_InitXPCOM2. Note that we properly * answer the NS_XPCOM_CURRENT_PROCESS_DIR query in our directory * service provider but it seems to be activated after the directory * service is used for the first time (see the source NS_InitXPCOM2). So * use the same value here to be on the safe side. */ nsCOMPtr <nsIFile> appDir; { char *appDirCP = NULL; vrc = RTStrUtf8ToCurrentCP(&appDirCP, szAppHomeDir); if (RT_SUCCESS(vrc)) { nsCOMPtr<nsILocalFile> file; rc = NS_NewNativeLocalFile(nsEmbedCString(appDirCP), PR_FALSE, getter_AddRefs(file)); if (NS_SUCCEEDED(rc)) appDir = do_QueryInterface(file, &rc); RTStrFree(appDirCP); } else rc = NS_ERROR_FAILURE; } if (NS_FAILED(rc)) break; /* Set VBOX_XPCOM_HOME to the same app path to make XPCOM sources that * still use it instead of the directory service happy */ vrc = RTEnvSetEx(RTENV_DEFAULT, "VBOX_XPCOM_HOME", szAppHomeDir); AssertRC(vrc); /* Finally, initialize XPCOM */ { nsCOMPtr<nsIServiceManager> serviceManager; rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), appDir, dsProv); if (NS_SUCCEEDED(rc)) { nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager, &rc); if (NS_SUCCEEDED(rc)) { rc = registrar->AutoRegister(nsnull); if (NS_SUCCEEDED(rc)) { /* We succeeded, stop probing paths */ LogFlowFunc(("Succeeded.\n")); break; } } } } /* clean up before the new try */ rc = NS_ShutdownXPCOM(nsnull); if (i == 0) { /* We failed with VBOX_APP_HOME, don't probe other paths */ break; } } #endif /* !defined (VBOX_WITH_XPCOM) */ // for both COM and XPCOM, we only get here if this is the main thread; // only then initialize the autolock system (AutoLock.cpp) Assert(RTThreadIsMain(RTThreadSelf())); util::InitAutoLockSystem(); AssertComRC(rc); /* * Init the main event queue (ASSUMES it cannot fail). */ if (SUCCEEDED(rc)) EventQueue::init(); return rc; }
/* * We are always executed from one specific HGCM thread. So thread safe. */ int vbsfMappingsAdd(PSHFLSTRING pFolderName, PSHFLSTRING pMapName, bool fWritable, bool fAutoMount, bool fSymlinksCreate, bool fMissing) { unsigned i; Assert(pFolderName && pMapName); Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2)); /* check for duplicates */ for (i=0; i<SHFL_MAX_MAPPINGS; i++) { if (FolderMapping[i].fValid == true) { if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) { AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2)); return VERR_ALREADY_EXISTS; } } } for (i=0; i<SHFL_MAX_MAPPINGS; i++) { if (FolderMapping[i].fValid == false) { int rc = RTUtf16ToUtf8(pFolderName->String.ucs2, &FolderMapping[i].pszFolderName); AssertRCReturn(rc, rc); FolderMapping[i].pMapName = (PSHFLSTRING)RTMemAlloc(ShflStringSizeOfBuffer(pMapName)); if (!FolderMapping[i].pMapName) { RTStrFree(FolderMapping[i].pszFolderName); AssertFailed(); return VERR_NO_MEMORY; } FolderMapping[i].pMapName->u16Length = pMapName->u16Length; FolderMapping[i].pMapName->u16Size = pMapName->u16Size; memcpy(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2, pMapName->u16Size); FolderMapping[i].fValid = true; FolderMapping[i].cMappings = 0; FolderMapping[i].fWritable = fWritable; FolderMapping[i].fAutoMount = fAutoMount; FolderMapping[i].fSymlinksCreate = fSymlinksCreate; FolderMapping[i].fMissing = fMissing; /* Check if the host file system is case sensitive */ RTFSPROPERTIES prop; char *pszAsciiRoot; rc = RTStrUtf8ToCurrentCP(&pszAsciiRoot, FolderMapping[i].pszFolderName); if (RT_SUCCESS(rc)) { rc = RTFsQueryProperties(pszAsciiRoot, &prop); AssertRC(rc); RTStrFree(pszAsciiRoot); } FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false; vbsfRootHandleAdd(i); break; } } if (i == SHFL_MAX_MAPPINGS) { AssertMsgFailed(("vbsfMappingsAdd: no more room to add mapping %ls to %ls!!\n", pFolderName->String.ucs2, pMapName->String.ucs2)); return VERR_TOO_MUCH_DATA; } Log(("vbsfMappingsAdd: added mapping %ls to %ls\n", pFolderName->String.ucs2, pMapName->String.ucs2)); return VINF_SUCCESS; }
RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertReturn(*pszVar, VERR_INVALID_PARAMETER); AssertPtrReturn(pszValue, VERR_INVALID_POINTER); int rc; if (Env == RTENV_DEFAULT) { /* * Since RTEnvPut isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { char *pszValueOtherCP; rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue); if (RT_SUCCESS(rc)) { rc = RTEnvSet(pszVarOtherCP, pszValueOtherCP); RTStrFree(pszValueOtherCP); } RTStrFree(pszVarOtherCP); } } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); /* * Create the variable string. */ const size_t cchVar = strlen(pszVar); const size_t cchValue = strlen(pszValue); char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2); if (pszEntry) { memcpy(pszEntry, pszVar, cchVar); pszEntry[cchVar] = '='; memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1); RTENV_LOCK(pIntEnv); /* * Find the location of the variable. (iVar = cVars if new) */ rc = VINF_SUCCESS; size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar) && pIntEnv->papszEnv[iVar][cchVar] == '=') break; if (iVar < pIntEnv->cVars) { /* * Replace the current entry. Simple. */ RTMemFree(pIntEnv->papszEnv[iVar]); pIntEnv->papszEnv[iVar] = pszEntry; } else { /* * Adding a new variable. Resize the array if required * and then insert the new value at the end. */ if (pIntEnv->cVars + 2 > pIntEnv->cAllocated) { void *pvNew = RTMemRealloc(pIntEnv->papszEnv, sizeof(char *) * (pIntEnv->cAllocated + RTENV_GROW_SIZE)); if (!pvNew) rc = VERR_NO_MEMORY; else { pIntEnv->papszEnv = (char **)pvNew; pIntEnv->cAllocated += RTENV_GROW_SIZE; for (size_t iNewVar = pIntEnv->cVars; iNewVar < pIntEnv->cAllocated; iNewVar++) pIntEnv->papszEnv[iNewVar] = NULL; } } if (RT_SUCCESS(rc)) { pIntEnv->papszEnv[iVar] = pszEntry; pIntEnv->papszEnv[iVar + 1] = NULL; /* this isn't really necessary, but doesn't hurt. */ pIntEnv->cVars++; Assert(pIntEnv->cVars == iVar + 1); } } RTENV_UNLOCK(pIntEnv); if (RT_FAILURE(rc)) RTMemFree(pszEntry); } else rc = VERR_NO_MEMORY; } return rc; }