static int rtMemAllocExInRange(size_t cbAlloc, uint32_t fFlags, void **ppv, uintptr_t uAddr, uintptr_t uAddrLast) { /* * Try with every possible address hint since the possible range is very limited. */ DWORD fPageProt = (fFlags & RTMEMALLOCEX_FLAGS_EXEC ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); while (uAddr <= uAddrLast) { MEMORY_BASIC_INFORMATION MemInfo; SIZE_T cbRange = VirtualQuery((void *)uAddr, &MemInfo, sizeof(MemInfo)); AssertReturn(cbRange == sizeof(MemInfo), VERR_NOT_SUPPORTED); Assert(MemInfo.RegionSize > 0); if ( MemInfo.State == MEM_FREE && MemInfo.RegionSize >= cbAlloc) { void *pv = VirtualAlloc((void *)uAddr, cbAlloc, MEM_RESERVE | MEM_COMMIT, fPageProt); if ((uintptr_t)pv == uAddr) { *ppv = pv; return VINF_SUCCESS; } AssertStmt(!pv, VirtualFree(pv, cbAlloc, MEM_RELEASE)); } /* skip ahead */ uintptr_t uAddrNext = (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize; if (uAddrNext <= uAddr) break; uAddr += uAddrNext; } return VERR_NO_MEMORY; }
/** * \#DB (Debug event) handler for the hypervisor code. * * This is mostly the same as TRPMGCTrap01Handler, but we skip the PGM auto * mapping set as well as the default trap exit path since they are both really * bad ideas in this context. * * @returns VBox status code. * VINF_SUCCESS means we completely handled this trap, * other codes are passed execution to host context. * * @param pTrpmCpu Pointer to TRPMCPU data (within VM). * @param pRegFrame Pointer to the register frame for the trap. * @internal */ DECLASM(int) TRPMGCHyperTrap01Handler(PTRPMCPU pTrpmCpu, PCPUMCTXCORE pRegFrame) { RTGCUINTREG uDr6 = ASMGetAndClearDR6(); PVM pVM = TRPMCPU_2_VM(pTrpmCpu); PVMCPU pVCpu = TRPMCPU_2_VMCPU(pTrpmCpu); LogFlow(("TRPMGCHyper01: cs:eip=%04x:%08x uDr6=%RTreg\n", pRegFrame->cs.Sel, pRegFrame->eip, uDr6)); /* * We currently don't make use of the X86_DR7_GD bit, but * there might come a time when we do. */ AssertReleaseMsgReturn((uDr6 & X86_DR6_BD) != X86_DR6_BD, ("X86_DR6_BD isn't used, but it's set! dr7=%RTreg(%RTreg) dr6=%RTreg\n", ASMGetDR7(), CPUMGetHyperDR7(pVCpu), uDr6), VERR_NOT_IMPLEMENTED); AssertReleaseMsg(!(uDr6 & X86_DR6_BT), ("X86_DR6_BT is impossible!\n")); /* * Now leave the rest to the DBGF. */ int rc = DBGFRZTrap01Handler(pVM, pVCpu, pRegFrame, uDr6); AssertStmt(rc != VINF_EM_RAW_GUEST_TRAP, rc = VERR_TRPM_IPE_1); Log6(("TRPMGCHyper01: %Rrc (%04x:%08x %RTreg)\n", rc, pRegFrame->cs.Sel, pRegFrame->eip, uDr6)); return rc; }
/** * Refreshes globals from GIP after one or more CPUs were added. * * There are potential races here. We might race other threads and we may race * more CPUs being added. */ static void rtMpWinRefreshGip(void) { PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; if ( pGip && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC) { /* * Since CPUs cannot be removed, we only have to update the IDs and * indexes of CPUs that we think are inactive and the group member counts. */ for (;;) { unsigned const cbGip = pGip->cPages * PAGE_SIZE; uint32_t const cGipActiveCpus = pGip->cOnlineCpus; uint32_t const cMyActiveCpus = ASMAtomicReadU32(&g_cRtMpWinActiveCpus); ASMCompilerBarrier(); for (uint32_t idxGroup = 0; idxGroup < g_cRtMpWinMaxCpus; idxGroup++) { unsigned offCpuGroup = pGip->aoffCpuGroup[idxGroup]; if (offCpuGroup < cbGip) { PSUPGIPCPUGROUP pGipCpuGrp = (PSUPGIPCPUGROUP)((uintptr_t)pGip + offCpuGroup); uint32_t cMaxMembers = pGipCpuGrp->cMaxMembers; AssertStmt(cMaxMembers < RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers), cMaxMembers = RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers)); for (uint32_t idxMember = g_aRtMpWinCpuGroups[idxGroup].cActiveCpus; idxMember < cMaxMembers; idxMember++) { int16_t idxSet = pGipCpuGrp->aiCpuSetIdxs[idxMember]; g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = idxSet; if ((unsigned)idxSet < RT_ELEMENTS(g_aidRtMpWinByCpuSetIdx)) # ifdef IPRT_WITH_RTCPUID_AS_GROUP_AND_NUMBER g_aidRtMpWinByCpuSetIdx[idxSet] = RTMPCPUID_FROM_GROUP_AND_NUMBER(idxGroup, idxMember); # else g_aidRtMpWinByCpuSetIdx[idxSet] = idxSet; # endif } g_aRtMpWinCpuGroups[idxGroup].cMaxCpus = RT_MIN(pGipCpuGrp->cMembers, cMaxMembers); g_aRtMpWinCpuGroups[idxGroup].cActiveCpus = RT_MIN(pGipCpuGrp->cMembers, cMaxMembers); } else Assert(g_aRtMpWinCpuGroups[idxGroup].cActiveCpus == 0); } ASMCompilerBarrier(); if (cGipActiveCpus == pGip->cOnlineCpus) if (ASMAtomicCmpXchgU32(&g_cRtMpWinActiveCpus, cGipActiveCpus, cMyActiveCpus)) break; } } }
/** * Helper function for formatting the opcode bytes. * * @returns The number of output bytes. * * @param pDis Pointer to the disassembler state. * @param pszDst The output buffer. * @param cchDst The size of the output buffer. * @param fFlags The flags passed to the formatter. */ size_t disFormatBytes(PCDISSTATE pDis, char *pszDst, size_t cchDst, uint32_t fFlags) { size_t cchOutput = 0; uint32_t cb = pDis->cbInstr; AssertStmt(cb <= 16, cb = 16); #define PUT_C(ch) \ do { \ cchOutput++; \ if (cchDst > 1) \ { \ cchDst--; \ *pszDst++ = (ch); \ } \ } while (0) #define PUT_NUM(cch, fmt, num) \ do { \ cchOutput += (cch); \ if (cchDst > 1) \ { \ const size_t cchTmp = RTStrPrintf(pszDst, cchDst, fmt, (num)); \ pszDst += cchTmp; \ cchDst -= cchTmp; \ } \ } while (0) if (fFlags & DIS_FMT_FLAGS_BYTES_BRACKETS) PUT_C('['); for (uint32_t i = 0; i < cb; i++) { if (i != 0 && (fFlags & DIS_FMT_FLAGS_BYTES_SPACED)) PUT_NUM(3, " %02x", pDis->abInstr[i]); else PUT_NUM(2, "%02x", pDis->abInstr[i]); } if (fFlags & DIS_FMT_FLAGS_BYTES_BRACKETS) PUT_C(']'); /* Terminate it just in case. */ if (cchDst >= 1) *pszDst = '\0'; #undef PUT_C #undef PUT_NUM return cchOutput; }
/** * \#BP (Breakpoint) handler. * * This is similar to TRPMGCTrap03Handler but we bits which are potentially * harmful to us (common trap exit and the auto mapping set). * * @returns VBox status code. * VINF_SUCCESS means we completely handled this trap, * other codes are passed execution to host context. * * @param pTrpmCpu Pointer to TRPMCPU data (within VM). * @param pRegFrame Pointer to the register frame for the trap. * @internal */ DECLASM(int) TRPMGCHyperTrap03Handler(PTRPMCPU pTrpmCpu, PCPUMCTXCORE pRegFrame) { LogFlow(("TRPMGCHyper03: %04x:%08x\n", pRegFrame->cs.Sel, pRegFrame->eip)); PVM pVM = TRPMCPU_2_VM(pTrpmCpu); PVMCPU pVCpu = TRPMCPU_2_VMCPU(pTrpmCpu); /* * Hand it over to DBGF. */ int rc = DBGFRZTrap03Handler(pVM, pVCpu, pRegFrame); AssertStmt(rc != VINF_EM_RAW_GUEST_TRAP, rc = VERR_TRPM_IPE_2); Log6(("TRPMGCHyper03: %Rrc (%04x:%08x)\n", rc, pRegFrame->cs.Sel, pRegFrame->eip)); return rc; }
RTR3DECL(int) RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser) { AssertPtrReturn(ppszUser, VERR_INVALID_POINTER); int rc; if ( hProcess == NIL_RTPROCESS || hProcess == RTProcSelf()) { /* * Figure a good buffer estimate. */ int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX); if (cbPwdMax <= _1K) cbPwdMax = _1K; else AssertStmt(cbPwdMax <= 32*_1M, cbPwdMax = 32*_1M); char *pchBuf = (char *)RTMemTmpAllocZ(cbPwdMax); if (pchBuf) { /* * Get the password file entry. */ struct passwd Pwd; struct passwd *pPwd = NULL; rc = getpwuid_r(geteuid(), &Pwd, pchBuf, cbPwdMax, &pPwd); if (!rc) { /* * Convert the name to UTF-8, assuming that we're getting it in the local codeset. */ rc = RTStrCurrentCPToUtf8(ppszUser, pPwd->pw_name); } else rc = RTErrConvertFromErrno(rc); RTMemFree(pchBuf); } else rc = VERR_NO_TMP_MEMORY; } else rc = VERR_NOT_SUPPORTED; return rc; }
/** * Does the waiting on a section of the handle array. * * @param pSubworker Pointer to the calling thread's data. * @param cMsWait Number of milliseconds to wait. */ void VirtualBox::ClientWatcher::subworkerWait(VirtualBox::ClientWatcher::PerSubworker *pSubworker, uint32_t cMsWait) { /* * Figure out what section to wait on and do the waiting. */ uint32_t idxHandle = pSubworker->iSubworker * CW_MAX_HANDLES_PER_THREAD; uint32_t cHandles = CW_MAX_HANDLES_PER_THREAD; if (idxHandle + cHandles > mcWaitHandles) { cHandles = mcWaitHandles - idxHandle; AssertStmt(idxHandle < mcWaitHandles, cHandles = 1); } Assert(mahWaitHandles[idxHandle] == mUpdateReq); DWORD dwWait = ::WaitForMultipleObjects(cHandles, &mahWaitHandles[idxHandle], FALSE /*fWaitAll*/, cMsWait); pSubworker->dwWait = dwWait; /* * If we didn't wake up because of the UpdateReq handle, signal it to make * sure everyone else wakes up too. */ if (dwWait != WAIT_OBJECT_0) { BOOL fRc = SetEvent(mUpdateReq); Assert(fRc); NOREF(fRc); } /* * Last one signals the main thread. */ if (ASMAtomicDecU32(&mcActiveSubworkers) == 0) { int vrc = RTThreadUserSignal(maSubworkers[0].hThread); AssertLogRelMsg(RT_SUCCESS(vrc), ("RTThreadUserSignal -> %Rrc\n", vrc)); } }
RTDECL(int) RTAsn1Integer_ToString(PRTASN1INTEGER pThis, char *pszBuf, size_t cbBuf, uint32_t fFlags, size_t *pcbActual) { AssertReturn(RTAsn1Integer_IsPresent(pThis), VERR_INVALID_PARAMETER); AssertReturn(fFlags == 0, VERR_INVALID_FLAGS); /* * We only do hex conversions via this API. * Currently we consider all numbers to be unsigned. */ /** @todo Signed ASN.1 INTEGER. */ int rc; size_t cbActual; if (pThis->Asn1Core.cb <= 8) { cbActual = 2 + pThis->Asn1Core.cb*2 + 1; if (cbActual <= cbBuf) { ssize_t cchFormat = RTStrFormatU64(pszBuf, cbBuf, pThis->uValue.u, 16, (int)cbActual - 1 /*cchWidth*/, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD); rc = VINF_SUCCESS; AssertStmt(cchFormat == (ssize_t)cbActual - 1, rc = VERR_INTERNAL_ERROR_3); } else rc = VERR_BUFFER_OVERFLOW; } else { cbActual = pThis->Asn1Core.cb * 3 - 1 /* save one separator */ + 1 /* terminator */; if (cbActual <= cbBuf) { rc = RTStrPrintHexBytes(pszBuf, cbBuf, pThis->Asn1Core.uData.pv, pThis->Asn1Core.cb, RTSTRPRINTHEXBYTES_F_SEP_SPACE); Assert(rc == VINF_SUCCESS); } else rc = VERR_BUFFER_OVERFLOW; } if (pcbActual) *pcbActual = cbActual; return rc; }
RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(pThis->fRead, VERR_PIPE_NOT_READ); AssertPtrReturn(pcbReadable, VERR_INVALID_POINTER); int cb = 0; int rc = ioctl(pThis->fd, FIONREAD, &cb); if (rc != -1) { AssertStmt(cb >= 0, cb = 0); *pcbReadable = cb; return VINF_SUCCESS; } rc = errno; if (rc == ENOTTY) rc = VERR_NOT_SUPPORTED; else rc = RTErrConvertFromErrno(rc); return rc; }
/** * @callback_method_impl{FNRTONCE, * Resolves dynamic imports and initializes globals.} */ static DECLCALLBACK(int32_t) rtMpWinInitOnce(void *pvUser) { RT_NOREF(pvUser); Assert(g_WinOsInfoEx.dwOSVersionInfoSize != 0); Assert(g_hModKernel32 != NULL); /* * Resolve dynamic APIs. */ #define RESOLVE_API(a_szMod, a_FnName) \ do { \ RT_CONCAT(g_pfn,a_FnName) = (decltype(a_FnName) *)GetProcAddress(g_hModKernel32, #a_FnName); \ } while (0) RESOLVE_API("kernel32.dll", GetMaximumProcessorCount); //RESOLVE_API("kernel32.dll", GetActiveProcessorCount); - slow :/ RESOLVE_API("kernel32.dll", GetCurrentProcessorNumber); RESOLVE_API("kernel32.dll", GetCurrentProcessorNumberEx); RESOLVE_API("kernel32.dll", GetLogicalProcessorInformation); RESOLVE_API("kernel32.dll", GetLogicalProcessorInformationEx); /* * Reset globals. */ for (unsigned i = 0; i < RT_ELEMENTS(g_aidRtMpWinByCpuSetIdx); i++) g_aidRtMpWinByCpuSetIdx[i] = NIL_RTCPUID; for (unsigned idxGroup = 0; idxGroup < RT_ELEMENTS(g_aRtMpWinCpuGroups); idxGroup++) { g_aRtMpWinCpuGroups[idxGroup].cMaxCpus = 0; g_aRtMpWinCpuGroups[idxGroup].cActiveCpus = 0; for (unsigned idxMember = 0; idxMember < RT_ELEMENTS(g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers); idxMember++) g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = -1; } /* * Query group information, partitioning CPU IDs and CPU set indexes. * * We ASSUME the GroupInfo index is the same as the group number. * * We CANNOT ASSUME that the kernel CPU indexes are assigned in any given * way, though they usually are in group order by active processor. So, * we do that to avoid trouble. We must use information provided thru GIP * if we want the kernel CPU set indexes. Even there, the inactive CPUs * wont have sensible indexes. Sigh. * * We try to assign IDs to inactive CPUs in the same manner as mp-r0drv-nt.cpp * * Note! We will die (AssertFatal) if there are too many processors! */ union { SYSTEM_INFO SysInfo; SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Info; uint8_t abPaddingG[ sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) + sizeof(PROCESSOR_GROUP_INFO) * RTCPUSET_MAX_CPUS]; uint8_t abPaddingC[ sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) + (sizeof(PROCESSOR_RELATIONSHIP) + sizeof(GROUP_AFFINITY)) * RTCPUSET_MAX_CPUS]; } uBuf; if (g_pfnGetLogicalProcessorInformationEx) { /* Query the information. */ DWORD cbData = sizeof(uBuf); AssertFatalMsg(g_pfnGetLogicalProcessorInformationEx(RelationGroup, &uBuf.Info, &cbData) != FALSE, ("last error = %u, cbData = %u (in %u)\n", GetLastError(), cbData, sizeof(uBuf))); AssertFatalMsg(uBuf.Info.Relationship == RelationGroup, ("Relationship = %u, expected %u!\n", uBuf.Info.Relationship, RelationGroup)); AssertFatalMsg(uBuf.Info.Group.MaximumGroupCount <= RT_ELEMENTS(g_aRtMpWinCpuGroups), ("MaximumGroupCount is %u, we only support up to %u!\n", uBuf.Info.Group.MaximumGroupCount, RT_ELEMENTS(g_aRtMpWinCpuGroups))); AssertMsg(uBuf.Info.Group.MaximumGroupCount == uBuf.Info.Group.ActiveGroupCount, /* 2nd assumption mentioned above. */ ("%u vs %u\n", uBuf.Info.Group.MaximumGroupCount, uBuf.Info.Group.ActiveGroupCount)); AssertFatal(uBuf.Info.Group.MaximumGroupCount >= uBuf.Info.Group.ActiveGroupCount); g_cRtMpWinMaxCpuGroups = uBuf.Info.Group.MaximumGroupCount; /* Count max cpus (see mp-r0drv0-nt.cpp) why we don't use GetMaximumProcessorCount(ALL). */ uint32_t idxGroup; g_cRtMpWinMaxCpus = 0; for (idxGroup = 0; idxGroup < uBuf.Info.Group.ActiveGroupCount; idxGroup++) g_cRtMpWinMaxCpus += uBuf.Info.Group.GroupInfo[idxGroup].MaximumProcessorCount; /* Process the active groups. */ uint32_t cActive = 0; uint32_t cInactive = 0; uint32_t idxCpu = 0; uint32_t idxCpuSetNextInactive = g_cRtMpWinMaxCpus - 1; for (idxGroup = 0; idxGroup < uBuf.Info.Group.ActiveGroupCount; idxGroup++) { PROCESSOR_GROUP_INFO const *pGroupInfo = &uBuf.Info.Group.GroupInfo[idxGroup]; g_aRtMpWinCpuGroups[idxGroup].cMaxCpus = pGroupInfo->MaximumProcessorCount; g_aRtMpWinCpuGroups[idxGroup].cActiveCpus = pGroupInfo->ActiveProcessorCount; for (uint32_t idxMember = 0; idxMember < pGroupInfo->MaximumProcessorCount; idxMember++) { if (pGroupInfo->ActiveProcessorMask & RT_BIT_64(idxMember)) { g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = idxCpu; g_aidRtMpWinByCpuSetIdx[idxCpu] = idxCpu; idxCpu++; cActive++; } else { if (idxCpuSetNextInactive >= idxCpu) { g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = idxCpuSetNextInactive; g_aidRtMpWinByCpuSetIdx[idxCpuSetNextInactive] = idxCpuSetNextInactive; idxCpuSetNextInactive--; } cInactive++; } } } g_cRtMpWinActiveCpus = cActive; Assert(cActive + cInactive <= g_cRtMpWinMaxCpus); Assert(idxCpu <= idxCpuSetNextInactive + 1); Assert(idxCpu <= g_cRtMpWinMaxCpus); /* Just in case the 2nd assumption doesn't hold true and there are inactive groups. */ for (; idxGroup < uBuf.Info.Group.MaximumGroupCount; idxGroup++) { DWORD cMaxMembers = g_pfnGetMaximumProcessorCount(idxGroup); g_aRtMpWinCpuGroups[idxGroup].cMaxCpus = cMaxMembers; g_aRtMpWinCpuGroups[idxGroup].cActiveCpus = 0; for (uint32_t idxMember = 0; idxMember < cMaxMembers; idxMember++) { if (idxCpuSetNextInactive >= idxCpu) { g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = idxCpuSetNextInactive; g_aidRtMpWinByCpuSetIdx[idxCpuSetNextInactive] = idxCpuSetNextInactive; idxCpuSetNextInactive--; } cInactive++; } } Assert(cActive + cInactive <= g_cRtMpWinMaxCpus); Assert(idxCpu <= idxCpuSetNextInactive + 1); } else { /* Legacy: */ GetSystemInfo(&uBuf.SysInfo); g_cRtMpWinMaxCpuGroups = 1; g_cRtMpWinMaxCpus = uBuf.SysInfo.dwNumberOfProcessors; g_aRtMpWinCpuGroups[0].cMaxCpus = uBuf.SysInfo.dwNumberOfProcessors; g_aRtMpWinCpuGroups[0].cActiveCpus = uBuf.SysInfo.dwNumberOfProcessors; for (uint32_t idxMember = 0; idxMember < uBuf.SysInfo.dwNumberOfProcessors; idxMember++) { g_aRtMpWinCpuGroups[0].aidxCpuSetMembers[idxMember] = idxMember; g_aidRtMpWinByCpuSetIdx[idxMember] = idxMember; } } AssertFatalMsg(g_cRtMpWinMaxCpus <= RTCPUSET_MAX_CPUS, ("g_cRtMpWinMaxCpus=%u (%#x); RTCPUSET_MAX_CPUS=%u\n", g_cRtMpWinMaxCpus, g_cRtMpWinMaxCpus, RTCPUSET_MAX_CPUS)); g_cbRtMpWinGrpRelBuf = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) + (g_cRtMpWinMaxCpuGroups + 2) * sizeof(PROCESSOR_GROUP_INFO); /* * Get information about cores. * * Note! This will only give us info about active processors according to * MSDN, we'll just have to hope that CPUs aren't hotplugged after we * initialize here (or that the API consumers doesn't care too much). */ /** @todo A hot CPU plug event would be nice. */ g_cRtMpWinMaxCpuCores = g_cRtMpWinMaxCpus; if (g_pfnGetLogicalProcessorInformationEx) { /* Query the information. */ DWORD cbData = sizeof(uBuf); AssertFatalMsg(g_pfnGetLogicalProcessorInformationEx(RelationProcessorCore, &uBuf.Info, &cbData) != FALSE, ("last error = %u, cbData = %u (in %u)\n", GetLastError(), cbData, sizeof(uBuf))); g_cRtMpWinMaxCpuCores = 0; for (uint32_t off = 0; off < cbData; ) { SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pCur = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&uBuf.abPaddingG[off]; AssertFatalMsg(pCur->Relationship == RelationProcessorCore, ("off = %#x, Relationship = %u, expected %u!\n", off, pCur->Relationship, RelationProcessorCore)); g_cRtMpWinMaxCpuCores++; off += pCur->Size; } #if ARCH_BITS == 32 if (g_cRtMpWinMaxCpuCores > g_cRtMpWinMaxCpus) { /** @todo WOW64 trouble where the emulation environment has folded the high * processor masks (63..32) into the low (31..0), hiding some * processors from us. Currently we don't deal with that. */ g_cRtMpWinMaxCpuCores = g_cRtMpWinMaxCpus; } else AssertStmt(g_cRtMpWinMaxCpuCores > 0, g_cRtMpWinMaxCpuCores = g_cRtMpWinMaxCpus); #else AssertStmt(g_cRtMpWinMaxCpuCores > 0 && g_cRtMpWinMaxCpuCores <= g_cRtMpWinMaxCpus, g_cRtMpWinMaxCpuCores = g_cRtMpWinMaxCpus); #endif } else { /* * Sadly, on XP and Server 2003, even if the API is present, it does not tell us * how many physical cores there are (any package will look like a single core). * That is worse than not using the API at all, so just skip it unless it's Vista+. */ if ( g_pfnGetLogicalProcessorInformation && g_WinOsInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT && g_WinOsInfoEx.dwMajorVersion >= 6) { /* Query the info. */ DWORD cbSysProcInfo = _4K; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION paSysInfo = NULL; BOOL fRc = FALSE; do { cbSysProcInfo = RT_ALIGN_32(cbSysProcInfo, 256); void *pv = RTMemRealloc(paSysInfo, cbSysProcInfo); if (!pv) break; paSysInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)pv; fRc = g_pfnGetLogicalProcessorInformation(paSysInfo, &cbSysProcInfo); } while (!fRc && GetLastError() == ERROR_INSUFFICIENT_BUFFER); if (fRc) { /* Count the cores in the result. */ g_cRtMpWinMaxCpuCores = 0; uint32_t i = cbSysProcInfo / sizeof(paSysInfo[0]); while (i-- > 0) if (paSysInfo[i].Relationship == RelationProcessorCore) g_cRtMpWinMaxCpuCores++; AssertStmt(g_cRtMpWinMaxCpuCores > 0 && g_cRtMpWinMaxCpuCores <= g_cRtMpWinMaxCpus, g_cRtMpWinMaxCpuCores = g_cRtMpWinMaxCpus); } RTMemFree(paSysInfo); } } return VINF_SUCCESS; }
int vbsfPathGuestToHost(SHFLCLIENTDATA *pClient, SHFLROOT hRoot, PCSHFLSTRING pGuestString, uint32_t cbGuestString, char **ppszHostPath, uint32_t *pcbHostPathRoot, uint32_t fu32Options, uint32_t *pfu32PathFlags) { #ifdef VBOX_STRICT /* * Check that the pGuestPath has correct size and encoding. */ if (ShflStringIsValidIn(pGuestString, cbGuestString, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) == false) { LogFunc(("Invalid input string\n")); return VERR_INTERNAL_ERROR; } #else NOREF(cbGuestString); #endif /* * Resolve the root handle into a string. */ uint32_t cbRootLen = 0; const char *pszRoot = NULL; int rc = vbsfMappingsQueryHostRootEx(hRoot, &pszRoot, &cbRootLen); if (RT_FAILURE(rc)) { LogFunc(("invalid root\n")); return rc; } AssertReturn(cbRootLen > 0, VERR_INTERNAL_ERROR_2); /* vbsfMappingsQueryHostRootEx ensures this. */ /* * Get the UTF8 string with the relative path provided by the guest. * If guest uses UTF-16 then convert it to UTF-8. */ uint32_t cbGuestPath = 0; /* Shut up MSC */ const char *pchGuestPath = NULL; /* Ditto. */ char *pchGuestPathAllocated = NULL; /* Converted from UTF-16. */ if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) { /* UTF-8 */ cbGuestPath = pGuestString->u16Length; pchGuestPath = pGuestString->String.ach; } else { /* UTF-16 */ #ifdef RT_OS_DARWIN /* Misplaced hack! See todo! */ uint32_t cwcSrc = 0; PRTUTF16 pwszSrc = NULL; rc = vbsfNormalizeStringDarwin(&pGuestString->String.ucs2[0], pGuestString->u16Length / sizeof(RTUTF16), &pwszSrc, &cwcSrc); #else uint32_t const cwcSrc = pGuestString->u16Length / sizeof(RTUTF16); PCRTUTF16 const pwszSrc = &pGuestString->String.ucs2[0]; #endif if (RT_SUCCESS(rc)) { size_t cbPathAsUtf8 = RTUtf16CalcUtf8Len(pwszSrc); if (cbPathAsUtf8 >= cwcSrc) { /* Allocate buffer that will be able to contain the converted UTF-8 string. */ pchGuestPathAllocated = (char *)RTMemAlloc(cbPathAsUtf8 + 1); if (RT_LIKELY(pchGuestPathAllocated != NULL)) { if (RT_LIKELY(cbPathAsUtf8)) { size_t cchActual; char *pszDst = pchGuestPathAllocated; rc = RTUtf16ToUtf8Ex(pwszSrc, cwcSrc, &pszDst, cbPathAsUtf8 + 1, &cchActual); AssertRC(rc); AssertStmt(RT_FAILURE(rc) || cchActual == cbPathAsUtf8, rc = VERR_INTERNAL_ERROR_4); Assert(strlen(pszDst) == cbPathAsUtf8); } if (RT_SUCCESS(rc)) { /* Terminate the string. */ pchGuestPathAllocated[cbPathAsUtf8] = '\0'; cbGuestPath = (uint32_t)cbPathAsUtf8; Assert(cbGuestPath == cbPathAsUtf8); pchGuestPath = pchGuestPathAllocated; } } else { rc = VERR_NO_MEMORY; } } else { AssertFailed(); rc = VERR_INTERNAL_ERROR_3; } #ifdef RT_OS_DARWIN RTMemFree(pwszSrc); #endif } } char *pszFullPath = NULL; if (RT_SUCCESS(rc)) { LogFlowFunc(("Root %s path %.*s\n", pszRoot, cbGuestPath, pchGuestPath)); /* * Allocate enough memory to build the host full path from the root and the relative path. */ const uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */ pszFullPath = (char *)RTMemAlloc(cbFullPathAlloc); if (RT_LIKELY(pszFullPath != NULL)) { /* Buffer for the verified guest path. */ char *pchVerifiedPath = (char *)RTMemAlloc(cbGuestPath + 1); if (RT_LIKELY(pchVerifiedPath != NULL)) { /* Init the pointer for the guest relative path. */ uint32_t cbSrc = cbGuestPath; const char *pchSrc = pchGuestPath; /* Strip leading delimiters from the path the guest specified. */ while ( cbSrc > 0 && *pchSrc == pClient->PathDelimiter) { ++pchSrc; --cbSrc; } /* * Iterate the guest path components, verify each of them replacing delimiters with the host slash. */ char *pchDst = pchVerifiedPath; bool fLastComponentHasWildcard = false; for (; cbSrc > 0; --cbSrc, ++pchSrc) { if (RT_LIKELY(*pchSrc != pClient->PathDelimiter)) { if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc))) { if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc)) { fLastComponentHasWildcard = true; } *pchDst++ = *pchSrc; } else { rc = VERR_INVALID_NAME; break; } } else { /* Replace with the host slash. */ *pchDst++ = RTPATH_SLASH; if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1) { /* Processed component has a wildcard and there are more characters in the path. */ *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX; } fLastComponentHasWildcard = false; } } if (RT_SUCCESS(rc)) { *pchDst++ = 0; /* Construct the full host path removing '.' and '..'. */ rc = vbsfPathAbs(pszRoot, pchVerifiedPath, pszFullPath, cbFullPathAlloc); if (RT_SUCCESS(rc)) { if (pfu32PathFlags && fLastComponentHasWildcard) { *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST; } /* Check if the full path is still within the shared folder. */ if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE) { if (!RTPathStartsWith(pszFullPath, pszRoot)) { rc = VERR_INVALID_NAME; } } if (RT_SUCCESS(rc)) { /* * If the host file system is case sensitive and the guest expects * a case insensitive fs, then correct the path components casing. */ if ( vbsfIsHostMappingCaseSensitive(hRoot) && !vbsfIsGuestMappingCaseSensitive(hRoot)) { const bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD); const bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT); rc = vbsfCorrectPathCasing(pClient, pszFullPath, strlen(pszFullPath), fWildCard, fPreserveLastComponent); } if (RT_SUCCESS(rc)) { LogFlowFunc(("%s\n", pszFullPath)); /* Return the full host path. */ *ppszHostPath = pszFullPath; if (pcbHostPathRoot) { /* Return the length of the root path without the trailing slash. */ *pcbHostPathRoot = RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]) ? cbRootLen - 1 : /* pszRoot already had the trailing slash. */ cbRootLen; /* pszRoot did not have the trailing slash. */ } } } } else { LogFunc(("vbsfPathAbs %Rrc\n", rc)); } } RTMemFree(pchVerifiedPath); } else { rc = VERR_NO_MEMORY; } } else { rc = VERR_NO_MEMORY; } } /* * Cleanup. */ RTMemFree(pchGuestPathAllocated); if (RT_SUCCESS(rc)) { return rc; } /* * Cleanup on failure. */ RTMemFree(pszFullPath); LogFunc(("%Rrc\n", rc)); return rc; }
RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags) { int rc; /* * Validate input. */ AssertPtrReturn(pDir, VERR_INVALID_POINTER); AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE); AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER); AssertReturn(enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST, VERR_INVALID_PARAMETER); AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRYEX, szName[2]), ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])), VERR_INVALID_PARAMETER); } /* * Fetch data? */ if (!pDir->fDataUnread) { rc = rtDirNtFetchMore(pDir); if (RT_FAILURE(rc)) return rc; } /* * Convert the filename to UTF-8. */ rc = rtDirNtConvertCurName(pDir); if (RT_FAILURE(rc)) return rc; /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ PFILE_BOTH_DIR_INFORMATION pBoth = pDir->uCurData.pBoth; pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName)); #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pDir->enmInfoClass != FileMaximumInformation) #endif { uint8_t cbShort = pBoth->ShortNameLength; if (cbShort > 0) { AssertStmt(cbShort < sizeof(pDirEntry->wszShortName), cbShort = sizeof(pDirEntry->wszShortName) - 2); memcpy(pDirEntry->wszShortName, pBoth->ShortName, cbShort); pDirEntry->cwcShortName = cbShort / 2; } else pDirEntry->cwcShortName = 0; pDirEntry->Info.cbObject = pBoth->EndOfFile.QuadPart; pDirEntry->Info.cbAllocated = pBoth->AllocationSize.QuadPart; Assert(sizeof(uint64_t) == sizeof(pBoth->CreationTime)); RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, pBoth->CreationTime.QuadPart); RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, pBoth->LastAccessTime.QuadPart); RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, pBoth->LastWriteTime.QuadPart); RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, pBoth->ChangeTime.QuadPart); pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pBoth->FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, pszName, cchName); } #ifdef IPRT_WITH_NT_PATH_PASSTHRU else { pDirEntry->cwcShortName = 0; pDirEntry->Info.cbObject = 0; pDirEntry->Info.cbAllocated = 0; RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, 0); RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, 0); RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, 0); RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, 0); if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("Directory"))) pDirEntry->Info.Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("SymbolicLink"))) pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777; else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, RT_STR_TUPLE("Device"))) pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666; else pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666; } #endif /* * Requested attributes (we cannot provide anything actually). */ switch (enmAdditionalAttribs) { case RTFSOBJATTRADD_EASIZE: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE; #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pDir->enmInfoClass == FileMaximumInformation) pDirEntry->Info.Attr.u.EASize.cb = 0; else #endif pDirEntry->Info.Attr.u.EASize.cb = pBoth->EaSize; break; case RTFSOBJATTRADD_UNIX: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX; pDirEntry->Info.Attr.u.Unix.uid = ~0U; pDirEntry->Info.Attr.u.Unix.gid = ~0U; pDirEntry->Info.Attr.u.Unix.cHardlinks = 1; pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.fFlags = 0; pDirEntry->Info.Attr.u.Unix.GenerationId = 0; pDirEntry->Info.Attr.u.Unix.Device = 0; break; case RTFSOBJATTRADD_NOTHING: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING; break; case RTFSOBJATTRADD_UNIX_OWNER: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER; pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U; pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */ break; case RTFSOBJATTRADD_UNIX_GROUP: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP; pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U; pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0'; break; default: AssertMsgFailed(("Impossible!\n")); return VERR_INTERNAL_ERROR; } /* * Follow links if requested. */ if ( (fFlags & RTPATH_F_FOLLOW_LINK) && RTFS_IS_SYMLINK(fFlags)) { /** @todo Symlinks: Find[First|Next]FileW will return info about the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */ } /* * Finally advance the buffer. */ return rtDirNtAdvanceBuffer(pDir); }
RTDECL(int) RTPipeFromNative(PRTPIPE phPipe, RTHCINTPTR hNativePipe, uint32_t fFlags) { AssertPtrReturn(phPipe, VERR_INVALID_POINTER); AssertReturn(!(fFlags & ~RTPIPE_N_VALID_MASK), VERR_INVALID_PARAMETER); AssertReturn(!!(fFlags & RTPIPE_N_READ) != !!(fFlags & RTPIPE_N_WRITE), VERR_INVALID_PARAMETER); /* * Get and validate the pipe handle info. */ HANDLE hNative = (HANDLE)hNativePipe; AssertReturn(GetFileType(hNative) == FILE_TYPE_PIPE, VERR_INVALID_HANDLE); DWORD cMaxInstances; DWORD fInfo; if (!GetNamedPipeInfo(hNative, &fInfo, NULL, NULL, &cMaxInstances)) return RTErrConvertFromWin32(GetLastError()); AssertReturn(!(fInfo & PIPE_TYPE_MESSAGE), VERR_INVALID_HANDLE); AssertReturn(cMaxInstances == 1, VERR_INVALID_HANDLE); DWORD cInstances; DWORD fState; if (!GetNamedPipeHandleState(hNative, &fState, &cInstances, NULL, NULL, NULL, 0)) return RTErrConvertFromWin32(GetLastError()); AssertReturn(!(fState & PIPE_NOWAIT), VERR_INVALID_HANDLE); AssertReturn(!(fState & PIPE_READMODE_MESSAGE), VERR_INVALID_HANDLE); AssertReturn(cInstances <= 1, VERR_INVALID_HANDLE); /* * Looks kind of OK, create a handle so we can try rtPipeQueryInfo on it * and see if we need to duplicate it to make that call work. */ RTPIPEINTERNAL *pThis = (RTPIPEINTERNAL *)RTMemAllocZ(sizeof(RTPIPEINTERNAL)); if (!pThis) return VERR_NO_MEMORY; int rc = RTCritSectInit(&pThis->CritSect); if (RT_SUCCESS(rc)) { pThis->Overlapped.hEvent = CreateEvent(NULL, TRUE /*fManualReset*/, TRUE /*fInitialState*/, NULL /*pName*/); if (pThis->Overlapped.hEvent != NULL) { pThis->u32Magic = RTPIPE_MAGIC; pThis->hPipe = hNative; pThis->fRead = !!(fFlags & RTPIPE_N_READ); //pThis->fIOPending = false; //pThis->fZeroByteRead = false; //pThis->fBrokenPipe = false; //pThisR->fPromisedWritable= false; //pThis->cUsers = 0; //pThis->pbBounceBuf = NULL; //pThis->cbBounceBufUsed = 0; //pThis->cbBounceBufAlloc= 0; pThis->hPollSet = NIL_RTPOLLSET; HANDLE hNative2 = INVALID_HANDLE_VALUE; FILE_PIPE_LOCAL_INFORMATION Info; if (rtPipeQueryInfo(pThis, &Info)) rc = VINF_SUCCESS; else { if (DuplicateHandle(GetCurrentProcess() /*hSrcProcess*/, hNative /*hSrcHandle*/, GetCurrentProcess() /*hDstProcess*/, &hNative2 /*phDstHandle*/, pThis->fRead ? GENERIC_READ : GENERIC_WRITE | FILE_READ_ATTRIBUTES /*dwDesiredAccess*/, !!(fFlags & RTPIPE_N_INHERIT) /*fInheritHandle*/, 0 /*dwOptions*/)) { pThis->hPipe = hNative2; if (rtPipeQueryInfo(pThis, &Info)) rc = VINF_SUCCESS; else { rc = VERR_ACCESS_DENIED; CloseHandle(hNative2); } } else hNative2 = INVALID_HANDLE_VALUE; } if (RT_SUCCESS(rc)) { /* * Verify the pipe state and correct the inheritability. */ AssertStmt( Info.NamedPipeState == FILE_PIPE_CONNECTED_STATE || Info.NamedPipeState == FILE_PIPE_CLOSING_STATE || Info.NamedPipeState == FILE_PIPE_DISCONNECTED_STATE, VERR_INVALID_HANDLE); AssertStmt( Info.NamedPipeConfiguration == ( Info.NamedPipeEnd == FILE_PIPE_SERVER_END ? (pThis->fRead ? FILE_PIPE_INBOUND : FILE_PIPE_OUTBOUND) : (pThis->fRead ? FILE_PIPE_OUTBOUND : FILE_PIPE_INBOUND) ), VERR_INVALID_HANDLE); if ( RT_SUCCESS(rc) && hNative2 == INVALID_HANDLE_VALUE && !SetHandleInformation(hNative, HANDLE_FLAG_INHERIT /*dwMask*/, fFlags & RTPIPE_N_INHERIT ? HANDLE_FLAG_INHERIT : 0)) { rc = RTErrConvertFromWin32(GetLastError()); AssertMsgFailed(("%Rrc\n", rc)); } if (RT_SUCCESS(rc)) { /* * Ok, we're good! */ if (hNative2 != INVALID_HANDLE_VALUE) CloseHandle(hNative); *phPipe = pThis; return VINF_SUCCESS; } } /* Bail out. */ if (hNative2 != INVALID_HANDLE_VALUE) CloseHandle(hNative2); CloseHandle(pThis->Overlapped.hEvent); } RTCritSectDelete(&pThis->CritSect); } RTMemFree(pThis); return rc; }
RTDECL(int) RTEnvQueryUtf16Block(RTENV hEnv, PRTUTF16 *ppwszzBlock) { RTENV hClone = NIL_RTENV; PRTENVINTERNAL pIntEnv; int rc; /* * Validate / simplify input. */ if (hEnv == RTENV_DEFAULT) { rc = RTEnvClone(&hClone, RTENV_DEFAULT); if (RT_FAILURE(rc)) return rc; pIntEnv = hClone; } else { pIntEnv = hEnv; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); rc = VINF_SUCCESS; } RTENV_LOCK(pIntEnv); /* * Sort it first. */ RTSortApvShell((void **)pIntEnv->papszEnv, pIntEnv->cVars, rtEnvSortCompare, pIntEnv); /* * Calculate the size. */ size_t cwc; size_t cwcTotal = 2; for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) { rc = RTStrCalcUtf16LenEx(pIntEnv->papszEnv[iVar], RTSTR_MAX, &cwc); AssertRCBreak(rc); cwcTotal += cwc + 1; } PRTUTF16 pwszzBlock = NULL; if (RT_SUCCESS(rc)) { /* * Perform the conversion. */ PRTUTF16 pwszz = pwszzBlock = (PRTUTF16)RTMemAlloc(cwcTotal * sizeof(RTUTF16)); if (pwszz) { size_t cwcLeft = cwcTotal; for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) { rc = RTStrToUtf16Ex(pIntEnv->papszEnv[iVar], RTSTR_MAX, &pwszz, cwcTotal - (pwszz - pwszzBlock), &cwc); AssertRCBreak(rc); pwszz += cwc + 1; cwcLeft -= cwc + 1; AssertBreakStmt(cwcLeft >= 2, rc = VERR_INTERNAL_ERROR_3); } AssertStmt(cwcLeft == 2 || RT_FAILURE(rc), rc = VERR_INTERNAL_ERROR_2); if (RT_SUCCESS(rc)) { pwszz[0] = '\0'; pwszz[1] = '\0'; } else { RTMemFree(pwszzBlock); pwszzBlock = NULL; } } else rc = VERR_NO_MEMORY; } RTENV_UNLOCK(pIntEnv); if (hClone != NIL_RTENV) RTEnvDestroy(hClone); if (RT_SUCCESS(rc)) *ppwszzBlock = pwszzBlock; return rc; }
/** * Raises a generic debug event if enabled and not being ignored. * * @returns Strict VBox status code. * @retval VINF_EM_DBG_EVENT if the event was raised and the caller should * return ASAP to the debugger (via EM). * @retval VINF_SUCCESS if the event was disabled or ignored. * * @param pVM The cross context VM structure. * @param pVCpu The cross context virtual CPU structure. * @param enmEvent The generic event being raised. * @param uEventArg The argument of that event. * @param enmCtx The context in which this event is being raised. * * @thread EMT(pVCpu) */ VMM_INT_DECL(VBOXSTRICTRC) DBGFEventGenericWithArg(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent, uint64_t uEventArg, DBGFEVENTCTX enmCtx) { /* * Is it enabled. */ if (dbgfEventIsGenericWithArgEnabled(pVM, enmEvent, uEventArg)) { /* * Any events on the stack. Should the incoming event be ignored? */ uint64_t const rip = CPUMGetGuestRIP(pVCpu); uint32_t i = pVCpu->dbgf.s.cEvents; if (i > 0) { while (i-- > 0) { if ( pVCpu->dbgf.s.aEvents[i].Event.enmType == enmEvent && pVCpu->dbgf.s.aEvents[i].enmState == DBGFEVENTSTATE_IGNORE && pVCpu->dbgf.s.aEvents[i].rip == rip) { pVCpu->dbgf.s.aEvents[i].enmState = DBGFEVENTSTATE_RESTORABLE; return VINF_SUCCESS; } Assert(pVCpu->dbgf.s.aEvents[i].enmState != DBGFEVENTSTATE_CURRENT); } /* * Trim the event stack. */ i = pVCpu->dbgf.s.cEvents; while (i-- > 0) { if ( pVCpu->dbgf.s.aEvents[i].rip == rip && ( pVCpu->dbgf.s.aEvents[i].enmState == DBGFEVENTSTATE_RESTORABLE || pVCpu->dbgf.s.aEvents[i].enmState == DBGFEVENTSTATE_IGNORE) ) pVCpu->dbgf.s.aEvents[i].enmState = DBGFEVENTSTATE_IGNORE; else { if (i + 1 != pVCpu->dbgf.s.cEvents) memmove(&pVCpu->dbgf.s.aEvents[i], &pVCpu->dbgf.s.aEvents[i + 1], (pVCpu->dbgf.s.cEvents - i) * sizeof(pVCpu->dbgf.s.aEvents)); pVCpu->dbgf.s.cEvents--; } } i = pVCpu->dbgf.s.cEvents; AssertStmt(i < RT_ELEMENTS(pVCpu->dbgf.s.aEvents), i = RT_ELEMENTS(pVCpu->dbgf.s.aEvents) - 1); } /* * Push the event. */ pVCpu->dbgf.s.aEvents[i].enmState = DBGFEVENTSTATE_CURRENT; pVCpu->dbgf.s.aEvents[i].rip = rip; pVCpu->dbgf.s.aEvents[i].Event.enmType = enmEvent; pVCpu->dbgf.s.aEvents[i].Event.enmCtx = enmCtx; pVCpu->dbgf.s.aEvents[i].Event.u.Generic.uArg = uEventArg; pVCpu->dbgf.s.cEvents = i + 1; return VINF_EM_DBG_EVENT; } return VINF_SUCCESS; }
RTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser, size_t *pcbUser) { AssertReturn( (pszUser && cbUser > 0) || (!pszUser && !cbUser), VERR_INVALID_PARAMETER); AssertReturn(pcbUser || pszUser, VERR_INVALID_PARAMETER); int rc; if ( hProcess == NIL_RTPROCESS || hProcess == RTProcSelf()) { /* * Figure a good buffer estimate. */ int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX); if (cbPwdMax <= _1K) cbPwdMax = _1K; else AssertStmt(cbPwdMax <= 32*_1M, cbPwdMax = 32*_1M); char *pchBuf = (char *)RTMemTmpAllocZ(cbPwdMax); if (pchBuf) { /* * Get the password file entry. */ struct passwd Pwd; struct passwd *pPwd = NULL; rc = getpwuid_r(geteuid(), &Pwd, pchBuf, cbPwdMax, &pPwd); if (!rc) { /* * Convert the name to UTF-8, assuming that we're getting it in the local codeset. */ /** @todo This isn't exactly optimal... the current codeset/page conversion * stuff never was. Should optimize that for UTF-8 and ASCII one day. * And also optimize for avoiding heap. */ char *pszTmp = NULL; rc = RTStrCurrentCPToUtf8(&pszTmp, pPwd->pw_name); if (RT_SUCCESS(rc)) { size_t cbTmp = strlen(pszTmp) + 1; if (pcbUser) *pcbUser = cbTmp; if (cbTmp <= cbUser) { memcpy(pszUser, pszTmp, cbTmp); rc = VINF_SUCCESS; } else rc = VERR_BUFFER_OVERFLOW; RTStrFree(pszTmp); } } else rc = RTErrConvertFromErrno(rc); RTMemFree(pchBuf); } else rc = VERR_NO_TMP_MEMORY; } else rc = VERR_NOT_SUPPORTED; return rc; }
/** * @callback_method_impl{FNRTONCE, Updates globals with information from GIP.} */ static DECLCALLBACK(int32_t) rtMpWinInitOnceGip(void *pvUser) { RT_NOREF(pvUser); RTOnce(&g_MpInitOnce, rtMpWinInitOnce, NULL); PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; if ( pGip && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC) { /* * Update globals. */ if (g_cRtMpWinMaxCpus != pGip->cPossibleCpus) g_cRtMpWinMaxCpus = pGip->cPossibleCpus; if (g_cRtMpWinActiveCpus != pGip->cOnlineCpus) g_cRtMpWinActiveCpus = pGip->cOnlineCpus; Assert(g_cRtMpWinMaxCpuGroups == pGip->cPossibleCpuGroups); if (g_cRtMpWinMaxCpuGroups != pGip->cPossibleCpuGroups) { g_cRtMpWinMaxCpuGroups = pGip->cPossibleCpuGroups; g_cbRtMpWinGrpRelBuf = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) + (g_cRtMpWinMaxCpuGroups + 2) * sizeof(PROCESSOR_GROUP_INFO); } /* * Update CPU set IDs. */ for (unsigned i = g_cRtMpWinMaxCpus; i < RT_ELEMENTS(g_aidRtMpWinByCpuSetIdx); i++) g_aidRtMpWinByCpuSetIdx[i] = NIL_RTCPUID; unsigned const cbGip = pGip->cPages * PAGE_SIZE; for (uint32_t idxGroup = 0; idxGroup < g_cRtMpWinMaxCpus; idxGroup++) { uint32_t idxMember; unsigned offCpuGroup = pGip->aoffCpuGroup[idxGroup]; if (offCpuGroup < cbGip) { PSUPGIPCPUGROUP pGipCpuGrp = (PSUPGIPCPUGROUP)((uintptr_t)pGip + offCpuGroup); uint32_t cMaxMembers = pGipCpuGrp->cMaxMembers; AssertStmt(cMaxMembers < RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers), cMaxMembers = RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers)); g_aRtMpWinCpuGroups[idxGroup].cMaxCpus = cMaxMembers; g_aRtMpWinCpuGroups[idxGroup].cActiveCpus = RT_MIN(pGipCpuGrp->cMembers, cMaxMembers); for (idxMember = 0; idxMember < cMaxMembers; idxMember++) { int16_t idxSet = pGipCpuGrp->aiCpuSetIdxs[idxMember]; g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = idxSet; if ((unsigned)idxSet < RT_ELEMENTS(g_aidRtMpWinByCpuSetIdx)) # ifdef IPRT_WITH_RTCPUID_AS_GROUP_AND_NUMBER g_aidRtMpWinByCpuSetIdx[idxSet] = RTMPCPUID_FROM_GROUP_AND_NUMBER(idxGroup, idxMember); # else g_aidRtMpWinByCpuSetIdx[idxSet] = idxSet; # endif } } else idxMember = 0; for (; idxMember < RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers); idxMember++) g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = -1; } } return VINF_SUCCESS; }