Example #1
0
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;
}
Example #2
0
/**
 * \#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;
}
Example #3
0
/**
 * 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;
        }
    }
}
Example #4
0
/**
 * 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;
}
Example #5
0
/**
 * \#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;
}
Example #6
0
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;
}
Example #7
0
/**
 * 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));
    }

}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
/**
 * @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);
}
Example #13
0
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;
}
Example #15
0
/**
 * 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;
}
Example #16
0
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;
}
Example #17
0
/**
 * @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;
}