STDMETHODIMP GuestFileEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
{
    switch (aType)
    {
    case VBoxEventType_OnGuestFileStateChanged:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestFileStateChangedEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestFile> pProcess;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pProcess.asOutParam()));
            AssertBreak(!pProcess.isNull());
            FileStatus_T fileSts;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&fileSts));
            Bstr strPath;
            CHECK_ERROR_BREAK(pProcess, COMGETTER(FileName)(strPath.asOutParam()));
            ULONG uID;
            CHECK_ERROR_BREAK(pProcess, COMGETTER(Id)(&uID));

            RTPrintf("File ID=%RU32 \"%s\" changed status to [%s]\n",
                     uID, Utf8Str(strPath).c_str(), gctlFileStatusToText(fileSts));

        } while (0);
        break;
    }

    default:
        AssertFailed();
    }

    return S_OK;
}
Beispiel #2
0
/**
 * Run once function that initializes the kstats we need here.
 *
 * @returns IPRT status code.
 * @param   pvUser1     Unused.
 * @param   pvUser2     Unused.
 */
static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
{
    int rc = VINF_SUCCESS;
    NOREF(pvUser1); NOREF(pvUser2);

    /*
     * Open kstat and find the cpu_info entries for each of the CPUs.
     */
    g_pKsCtl = kstat_open();
    if (g_pKsCtl)
    {
        g_capCpuInfo = RTMpGetCount();
        g_papCpuInfo = (kstat_t **)RTMemAllocZ(g_capCpuInfo * sizeof(kstat_t *));
        if (g_papCpuInfo)
        {
            rc = RTCritSectInit(&g_MpSolarisCritSect);
            if (RT_SUCCESS(rc))
            {
                RTCPUID i = 0;
                for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
                {
                    if (!strcmp(pKsp->ks_module, "cpu_info"))
                    {
                        AssertBreak(i < g_capCpuInfo);
                        g_papCpuInfo[i++] = pKsp;
                        /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
                    }
                }

                return VINF_SUCCESS;
            }

            /* bail out, we failed. */
            RTMemFree(g_papCpuInfo);
        }
        else
            rc = VERR_NO_MEMORY;
        kstat_close(g_pKsCtl);
        g_pKsCtl = NULL;
    }
    else
    {
        rc = RTErrConvertFromErrno(errno);
        if (RT_SUCCESS(rc))
            rc = VERR_INTERNAL_ERROR;
        Log(("kstat_open() -> %d (%Rrc)\n", errno, rc));
    }

    return rc;
}
Beispiel #3
0
/**
 * Internal worker for RTTimeNormalize and RTTimeLocalNormalize.
 * It doesn't adjust the UCT offset but leaves that for RTTimeLocalNormalize.
 */
static PRTTIME rtTimeNormalizeInternal(PRTTIME pTime)
{
    unsigned    uSecond;
    unsigned    uMinute;
    unsigned    uHour;
    bool        fLeapYear;

    /*
     * Fix the YearDay and Month/MonthDay.
     */
    fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
    if (!pTime->u16YearDay)
    {
        /*
         * The Month+MonthDay must present, overflow adjust them and calc the year day.
         */
        AssertMsgReturn(    pTime->u8Month
                        &&  pTime->u8MonthDay,
                        ("date=%d-%d-%d\n", pTime->i32Year, pTime->u8Month, pTime->u8MonthDay),
                        NULL);
        while (pTime->u8Month > 12)
        {
            pTime->u8Month -= 12;
            pTime->i32Year++;
            fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
            pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
        }

        for (;;)
        {
            unsigned cDaysInMonth = fLeapYear
                                  ? g_acDaysInMonthsLeap[pTime->u8Month - 1]
                                  : g_acDaysInMonths[pTime->u8Month - 1];
            if (pTime->u8MonthDay <= cDaysInMonth)
                break;
            pTime->u8MonthDay -= cDaysInMonth;
            if (pTime->u8Month != 12)
                pTime->u8Month++;
            else
            {
                pTime->u8Month = 1;
                pTime->i32Year++;
                fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
                pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
            }
        }

        pTime->u16YearDay  = pTime->u8MonthDay - 1
                           + (fLeapYear
                              ? g_aiDayOfYearLeap[pTime->u8Month - 1]
                              : g_aiDayOfYear[pTime->u8Month - 1]);
    }
    else
    {
        /*
         * Are both YearDay and Month/MonthDay valid?
         * Check that they don't overflow and match, if not use YearDay (simpler).
         */
        bool fRecalc = true;
        if (    pTime->u8Month
            &&  pTime->u8MonthDay)
        {
            do
            {
                uint16_t u16YearDay;

                /* If you change one, zero the other to make clear what you mean. */
                AssertBreak(pTime->u8Month <= 12);
                AssertBreak(pTime->u8MonthDay <= (fLeapYear
                                                  ? g_acDaysInMonthsLeap[pTime->u8Month - 1]
                                                  : g_acDaysInMonths[pTime->u8Month - 1]));
                u16YearDay = pTime->u8MonthDay - 1
                           + (fLeapYear
                              ? g_aiDayOfYearLeap[pTime->u8Month - 1]
                              : g_aiDayOfYear[pTime->u8Month - 1]);
                AssertBreak(u16YearDay == pTime->u16YearDay);
                fRecalc = false;
            } while (0);
        }
        if (fRecalc)
        {
            const uint16_t *paiDayOfYear;

            /* overflow adjust YearDay */
            while (pTime->u16YearDay > (fLeapYear ? 366 : 365))
            {
                pTime->u16YearDay -= fLeapYear ? 366 : 365;
                pTime->i32Year++;
                fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
                pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
            }

            /* calc Month and MonthDay */
            paiDayOfYear = fLeapYear
                         ? &g_aiDayOfYearLeap[0]
                         : &g_aiDayOfYear[0];
            pTime->u8Month = 1;
            while (pTime->u16YearDay > paiDayOfYear[pTime->u8Month])
                pTime->u8Month++;
            Assert(pTime->u8Month >= 1 && pTime->u8Month <= 12);
            pTime->u8MonthDay = pTime->u16YearDay - paiDayOfYear[pTime->u8Month - 1] + 1;
        }
    }

    /*
     * Fixup time overflows.
     * Use unsigned int values internally to avoid overflows.
     */
    uSecond = pTime->u8Second;
    uMinute = pTime->u8Minute;
    uHour   = pTime->u8Hour;

    while (pTime->u32Nanosecond >= 1000000000)
    {
        pTime->u32Nanosecond -= 1000000000;
        uSecond++;
    }

    while (uSecond >= 60)
    {
        uSecond -= 60;
        uMinute++;
    }

    while (uMinute >= 60)
    {
        uMinute -= 60;
        uHour++;
    }

    while (uHour >= 24)
    {
        uHour -= 24;

        /* This is really a RTTimeIncDay kind of thing... */
        if (pTime->u16YearDay + 1 != (fLeapYear ? g_aiDayOfYearLeap[pTime->u8Month] : g_aiDayOfYear[pTime->u8Month]))
        {
            pTime->u16YearDay++;
            pTime->u8MonthDay++;
        }
        else if (pTime->u8Month != 12)
        {
            pTime->u16YearDay++;
            pTime->u8Month++;
            pTime->u8MonthDay = 1;
        }
        else
        {
            pTime->i32Year++;
            fLeapYear = rtTimeIsLeapYear(pTime->i32Year);
            pTime->fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
            pTime->u16YearDay = 1;
            pTime->u8Month = 1;
            pTime->u8MonthDay = 1;
        }
    }

    pTime->u8Second = uSecond;
    pTime->u8Minute = uMinute;
    pTime->u8Hour = uHour;

    /*
     * Correct the leap year flag.
     * Assert if it's wrong, but ignore if unset.
     */
    if (fLeapYear)
    {
        Assert(!(pTime->fFlags & RTTIME_FLAGS_COMMON_YEAR));
        pTime->fFlags &= ~RTTIME_FLAGS_COMMON_YEAR;
        pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR;
    }
    else
    {
        Assert(!(pTime->fFlags & RTTIME_FLAGS_LEAP_YEAR));
        pTime->fFlags &= ~RTTIME_FLAGS_LEAP_YEAR;
        pTime->fFlags |= RTTIME_FLAGS_COMMON_YEAR;
    }


    /*
     * Calc week day.
     *
     * 1970-01-01 was a Thursday (3), so find the number of days relative to
     * that point. We use the table when possible and a slow+stupid+brute-force
     * algorithm for points outside it. Feel free to optimize the latter by
     * using some clever formula.
     */
    if (    pTime->i32Year >= OFF_YEAR_IDX_0_YEAR
        &&  pTime->i32Year <  OFF_YEAR_IDX_0_YEAR + (int32_t)RT_ELEMENTS(g_aoffYear))
    {
        int32_t offDays = g_aoffYear[pTime->i32Year - OFF_YEAR_IDX_0_YEAR]
                        + pTime->u16YearDay -1;
        pTime->u8WeekDay = ((offDays % 7) + 3 + 7) % 7;
    }
    else
    {
        int32_t i32Year = pTime->i32Year;
        if (i32Year >= 1970)
        {
            uint64_t offDays = pTime->u16YearDay - 1;
            while (--i32Year >= 1970)
                offDays += rtTimeIsLeapYear(i32Year) ? 366 : 365;
            pTime->u8WeekDay = (uint8_t)((offDays + 3) % 7);
        }
        else
        {
            int64_t offDays = (fLeapYear ? -366 - 1 : -365 - 1) + pTime->u16YearDay;
            while (++i32Year < 1970)
                offDays -= rtTimeIsLeapYear(i32Year) ? 366 : 365;
            pTime->u8WeekDay = ((int)(offDays % 7) + 3 + 7) % 7;
        }
    }
    return pTime;
}
static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
                                                 uint32_t *pcSamplesPlayed)
{
    NOREF(pInterface);
    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);

    PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;

    int rc = VINF_SUCCESS;
    uint32_t cbReadTotal = 0;

    do
    {
        snd_pcm_sframes_t cAvail;
        rc = drvHostALSAAudioGetAvail(pThisStrmOut->phPCM, &cAvail);
        if (RT_FAILURE(rc))
        {
            LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc));
            break;
        }

        size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
                                                 cAvail),
                                 AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
                                                 drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */)));
        LogFlowFunc(("cbToRead=%zu, cbAvail=%zu\n",
                     cbToRead, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cAvail)));

        uint32_t cRead, cbRead;
        snd_pcm_sframes_t cWritten;
        while (cbToRead)
        {
            rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvBuf, cbToRead, &cRead);
            if (RT_FAILURE(rc))
                break;

            cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
            AssertBreak(cbRead);

            cWritten = snd_pcm_writei(pThisStrmOut->phPCM, pThisStrmOut->pvBuf, cRead);
            if (cWritten <= 0)
            {
                switch (cWritten)
                {
                    case 0:
                    {
                        LogFunc(("Failed to write %RI32 frames\n", cRead));
                        rc = VERR_ACCESS_DENIED;
                        break;
                    }

                    case -EPIPE:
                    {
                        rc = drvHostALSAAudioRecover(pThisStrmOut->phPCM);
                        if (RT_FAILURE(rc))
                            break;

                        LogFlowFunc(("Recovered from playback\n"));
                        continue;
                    }

                    case -ESTRPIPE:
                    {
                        /* Stream was suspended and waiting for a recovery. */
                        rc = drvHostALSAAudioResume(pThisStrmOut->phPCM);
                        if (RT_FAILURE(rc))
                        {
                            LogRel(("ALSA: Failed to resume output stream\n"));
                            break;
                        }

                        LogFlowFunc(("Resumed suspended output stream\n"));
                        continue;
                    }

                    default:
                        LogFlowFunc(("Failed to write %RI32 output frames, rc=%Rrc\n",
                                     cRead, rc));
                        rc = VERR_GENERAL_FAILURE; /** @todo */
                        break;
                }
            }

            if (RT_FAILURE(rc))
                break;

            Assert(cbToRead >= cbRead);
            cbToRead -= cbRead;
            cbReadTotal += cbRead;
        }
    }
    while (0);

    if (RT_SUCCESS(rc))
    {
        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
        if (cReadTotal)
            AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);

        if (pcSamplesPlayed)
            *pcSamplesPlayed = cReadTotal;

        LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n",
                     cReadTotal, cbReadTotal, rc));
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Beispiel #5
0
/**
 * Recursive worker function to walk the /dev tree looking for DVD or floppy
 * devices.
 * @returns true if we have already found MAX_DEVICE_NODES devices, false
 *          otherwise
 * @param   pszPath   the path to start recursing.  The function can modify
 *                    this string at and after the terminating zero
 * @param   cchPath   the size of the buffer (not the string!) in @a pszPath
 * @param   aDevices  where to fill in information about devices that we have
 *                    found
 * @param   wantDVD   are we looking for DVD devices (or floppies)?
 */
static bool devFindDeviceRecursive(char *pszPath, size_t cchPath,
                                   deviceNodeArray aDevices, bool wantDVD)
{
    /*
     * Check assumptions made by the code below.
     */
    size_t const cchBasePath = strlen(pszPath);
    AssertReturn(cchBasePath < RTPATH_MAX - 10U, false);
    AssertReturn(pszPath[cchBasePath - 1] != '/', false);

    PRTDIR  pDir;
    if (RT_FAILURE(RTDirOpen(&pDir, pszPath)))
        return false;
    for (;;)
    {
        RTDIRENTRY Entry;
        RTFSOBJINFO ObjInfo;
        int rc = RTDirRead(pDir, &Entry, NULL);
        if (RT_FAILURE(rc))
            break;
        if (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN)
        {
            if (RT_FAILURE(RTPathQueryInfo(pszPath, &ObjInfo,
                           RTFSOBJATTRADD_UNIX)))
                continue;
            if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
                continue;
        }

        if (Entry.enmType == RTDIRENTRYTYPE_SYMLINK)
            continue;
        pszPath[cchBasePath] = '\0';
        if (RT_FAILURE(RTPathAppend(pszPath, cchPath, Entry.szName)))
            break;

        /* Do the matching. */
        dev_t DevNode;
        char szDesc[256], szUdi[256];
        if (!devValidateDevice(pszPath, wantDVD, &DevNode, szDesc,
                               sizeof(szDesc), szUdi, sizeof(szUdi)))
            continue;
        unsigned i;
        for (i = 0; i < MAX_DEVICE_NODES; ++i)
            if (!aDevices[i].Device || (aDevices[i].Device == DevNode))
                break;
        AssertBreak(i < MAX_DEVICE_NODES);
        if (aDevices[i].Device)
            continue;
        aDevices[i].Device = DevNode;
        RTStrPrintf(aDevices[i].szPath, sizeof(aDevices[i].szPath),
                    "%s", pszPath);
        AssertCompile(sizeof(aDevices[i].szDesc) == sizeof(szDesc));
        strcpy(aDevices[i].szDesc, szDesc);
        AssertCompile(sizeof(aDevices[i].szUdi) == sizeof(szUdi));
        strcpy(aDevices[i].szUdi, szUdi);
        if (i == MAX_DEVICE_NODES - 1)
            break;
        continue;

        /* Recurse into subdirectories. */
        if (   (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN)
            && !RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
            continue;
        if (Entry.enmType != RTDIRENTRYTYPE_DIRECTORY)
            continue;
        if (Entry.szName[0] == '.')
            continue;

        if (devFindDeviceRecursive(pszPath, cchPath, aDevices, wantDVD))
            break;
    }
    RTDirClose(pDir);
    return aDevices[MAX_DEVICE_NODES - 1].Device ? true : false;
}
static int solarisWalkDeviceNode(di_node_t Node, void *pvArg)
{
    PUSBDEVICELIST pList = (PUSBDEVICELIST)pvArg;
    AssertPtrReturn(pList, DI_WALK_TERMINATE);

    /*
     * Check if it's a USB device in the first place.
     */
    bool fUSBDevice = false;
    char *pszCompatNames = NULL;
    int cCompatNames = di_compatible_names(Node, &pszCompatNames);
    for (int i = 0; i < cCompatNames; i++, pszCompatNames += strlen(pszCompatNames) + 1)
        if (!strncmp(pszCompatNames, "usb", 3))
        {
            fUSBDevice = true;
            break;
        }

    if (!fUSBDevice)
        return DI_WALK_CONTINUE;

    /*
     * Check if it's a device node or interface.
     */
    int *pInt = NULL;
    char *pStr = NULL;
    int rc = DI_WALK_CONTINUE;
    if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "interface", &pInt) < 0)
    {
        /* It's a device node. */
        char *pszDevicePath = di_devfs_path(Node);
        PUSBDEVICE pCur = (PUSBDEVICE)RTMemAllocZ(sizeof(*pCur));
        if (!pCur)
        {
            LogRel(("USBService: failed to allocate %d bytes for PUSBDEVICE.\n", sizeof(*pCur)));
            return DI_WALK_TERMINATE;
        }

        bool fValidDevice = false;
        do
        {
            AssertBreak(pszDevicePath);

            char *pszDriverName = di_driver_name(Node);

            /*
             * Skip hubs
             */
            if (   pszDriverName
                && !strcmp(pszDriverName, "hubd"))
            {
                break;
            }

            /*
             * Mandatory.
             * snv_85 and above have usb-dev-descriptor node properties, but older one's do not.
             * So if we cannot obtain the entire device descriptor, we try falling back to the
             * individual properties (those must not fail, if it does we drop the device).
             */
            uchar_t *pDevData = NULL;
            int cbProp = di_prop_lookup_bytes(DDI_DEV_T_ANY, Node, "usb-dev-descriptor", &pDevData);
            if (   cbProp > 0
                && pDevData)
            {
                usb_dev_descr_t *pDeviceDescriptor = (usb_dev_descr_t *)pDevData;
                pCur->bDeviceClass = pDeviceDescriptor->bDeviceClass;
                pCur->bDeviceSubClass = pDeviceDescriptor->bDeviceSubClass;
                pCur->bDeviceProtocol = pDeviceDescriptor->bDeviceProtocol;
                pCur->idVendor = pDeviceDescriptor->idVendor;
                pCur->idProduct = pDeviceDescriptor->idProduct;
                pCur->bcdDevice = pDeviceDescriptor->bcdDevice;
                pCur->bcdUSB = pDeviceDescriptor->bcdUSB;
                pCur->bNumConfigurations = pDeviceDescriptor->bNumConfigurations;
                pCur->fPartialDescriptor = false;
            }
            else
            {
                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-vendor-id", &pInt) > 0);
                pCur->idVendor = (uint16_t)*pInt;

                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-product-id", &pInt) > 0);
                pCur->idProduct = (uint16_t)*pInt;

                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-revision-id", &pInt) > 0);
                pCur->bcdDevice = (uint16_t)*pInt;

                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-release", &pInt) > 0);
                pCur->bcdUSB = (uint16_t)*pInt;

                pCur->fPartialDescriptor = true;
            }

            char *pszPortAddr = di_bus_addr(Node);
            if (pszPortAddr)
                pCur->bPort = RTStrToUInt8(pszPortAddr);     /* Bus & Port are mixed up (kernel driver/userland) */
            else
                pCur->bPort = 0;

            char pathBuf[PATH_MAX];
            RTStrPrintf(pathBuf, sizeof(pathBuf), "%s", pszDevicePath);
            RTPathStripFilename(pathBuf);

            char szBuf[PATH_MAX + 48];
            RTStrPrintf(szBuf, sizeof(szBuf), "%#x:%#x:%d:%s", pCur->idVendor, pCur->idProduct, pCur->bcdDevice, pathBuf);
            pCur->pszAddress = RTStrDup(szBuf);

            pCur->pszDevicePath = RTStrDup(pszDevicePath);
            AssertBreak(pCur->pszDevicePath);

            /*
             * Optional (some devices don't have all these)
             */
            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-product-name", &pStr) > 0)
                pCur->pszProduct = RTStrDup(pStr);

            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-vendor-name", &pStr) > 0)
                pCur->pszManufacturer = RTStrDup(pStr);

            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-serialno", &pStr) > 0)
                pCur->pszSerialNumber = RTStrDup(pStr);

            if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "low-speed", &pInt) >= 0)
                pCur->enmSpeed = USBDEVICESPEED_LOW;
            else if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "high-speed", &pInt) >= 0)
                pCur->enmSpeed = USBDEVICESPEED_HIGH;
            else
                pCur->enmSpeed = USBDEVICESPEED_FULL;

            /* Determine state of the USB device. */
            pCur->enmState = solarisDetermineUSBDeviceState(pCur, Node);

            /*
             * Valid device, add it to the list.
             */
            fValidDevice = true;
            pCur->pPrev = pList->pTail;
            if (pList->pTail)
                pList->pTail = pList->pTail->pNext = pCur;
            else
                pList->pTail = pList->pHead = pCur;

            rc = DI_WALK_CONTINUE;
        } while(0);

        di_devfs_path_free(pszDevicePath);
        if (!fValidDevice)
            solarisFreeUSBDevice(pCur);
    }
    return rc;
}
Beispiel #7
0
/**
 * Initializes a SG list from an mbuf.
 *
 * @returns Number of segments.
 * @param   pThis               The instance.
 * @param   pMBuf               The mbuf.
 * @param   pSG                 The SG.
 * @param   pvFrame             The frame pointer, optional.
 * @param   cSegs               The number of segments allocated for the SG.
 *                              This should match the number in the mbuf exactly!
 * @param   fSrc                The source of the frame.
 */
DECLINLINE(void) vboxNetFltDarwinMBufToSG(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
{
    NOREF(pThis);

    /*
     * Walk the chain and convert the buffers to segments.  Works INTNETSG::cbTotal.
     */
    unsigned iSeg = 0;
    IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/);
    for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur))
    {
        size_t cbSeg = mbuf_len(pCur);
        if (cbSeg)
        {
            void *pvSeg = mbuf_data(pCur);

            /* deal with pvFrame */
            if (!iSeg && pvFrame && pvFrame != pvSeg)
            {
                void     *pvStart   = mbuf_datastart(pMBuf);
                uintptr_t offSeg    = (uintptr_t)pvSeg - (uintptr_t)pvStart;
                uintptr_t offSegEnd = offSeg + cbSeg;
                Assert(pvStart && pvSeg && offSeg < mbuf_maxlen(pMBuf) && offSegEnd <= mbuf_maxlen(pMBuf)); NOREF(offSegEnd);
                uintptr_t offFrame  = (uintptr_t)pvFrame - (uintptr_t)pvStart;
                if (RT_LIKELY(offFrame < offSeg))
                {
                    pvSeg = pvFrame;
                    cbSeg += offSeg - offFrame;
                }
                else
                    AssertMsgFailed(("pvFrame=%p pvStart=%p pvSeg=%p offSeg=%p cbSeg=%#zx offSegEnd=%p offFrame=%p maxlen=%#zx\n",
                                     pvFrame, pvStart, pvSeg, offSeg, cbSeg, offSegEnd, offFrame, mbuf_maxlen(pMBuf)));
                pvFrame = NULL;
            }

            AssertBreak(iSeg < cSegs);
            pSG->cbTotal += cbSeg;
            pSG->aSegs[iSeg].cb = cbSeg;
            pSG->aSegs[iSeg].pv = pvSeg;
            pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
            iSeg++;
        }
        /* The pvFrame might be in a now empty buffer. */
        else if (   !iSeg
                 && pvFrame
                 && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf))
        {
            cbSeg = (uintptr_t)mbuf_datastart(pMBuf) + mbuf_maxlen(pMBuf) - (uintptr_t)pvFrame;
            pSG->cbTotal += cbSeg;
            pSG->aSegs[iSeg].cb = cbSeg;
            pSG->aSegs[iSeg].pv = pvFrame;
            pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
            iSeg++;
            pvFrame = NULL;
        }
    }

    Assert(iSeg && iSeg <= cSegs);
    pSG->cSegsUsed = iSeg;

#ifdef PADD_RUNT_FRAMES_FROM_HOST
    /*
     * Add a trailer if the frame is too small.
     *
     * Since we're getting to the packet before it is framed, it has not
     * yet been padded. The current solution is to add a segment pointing
     * to a buffer containing all zeros and pray that works for all frames...
     */
    if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
    {
        AssertReturnVoid(iSeg < cSegs);

        static uint8_t const s_abZero[128] = {0};
        pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
        pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
        pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
        pSG->cbTotal = 60;
        pSG->cSegsUsed++;
    }
#endif

#ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE
    /*
     * Redistribute the segments.
     */
    if (pSG->cSegsUsed < pSG->cSegsAlloc)
    {
        /* copy the segments to the end. */
        int iSrc = pSG->cSegsUsed;
        int iDst = pSG->cSegsAlloc;
        while (iSrc > 0)
        {
            iDst--;
            iSrc--;
            pSG->aSegs[iDst] = pSG->aSegs[iSrc];
        }

        /* create small segments from the start. */
        pSG->cSegsUsed = pSG->cSegsAlloc;
        iSrc = iDst;
        iDst = 0;
        while (     iDst < iSrc
               &&   iDst < pSG->cSegsAlloc)
        {
            pSG->aSegs[iDst].Phys = NIL_RTHCPHYS;
            pSG->aSegs[iDst].pv = pSG->aSegs[iSrc].pv;
            pSG->aSegs[iDst].cb = RT_MIN(pSG->aSegs[iSrc].cb, VBOXNETFLT_DARWIN_TEST_SEG_SIZE);
            if (pSG->aSegs[iDst].cb != pSG->aSegs[iSrc].cb)
            {
                pSG->aSegs[iSrc].cb -= pSG->aSegs[iDst].cb;
                pSG->aSegs[iSrc].pv = (uint8_t *)pSG->aSegs[iSrc].pv + pSG->aSegs[iDst].cb;
            }
            else if (++iSrc >= pSG->cSegsAlloc)
            {
                pSG->cSegsUsed = iDst + 1;
                break;
            }
            iDst++;
        }
    }
#endif

    AssertMsg(!pvFrame, ("pvFrame=%p pMBuf=%p iSeg=%d\n", pvFrame, pMBuf, iSeg));
}
STDMETHODIMP GuestEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
{
    switch (aType)
    {
    case VBoxEventType_OnGuestSessionRegistered:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestSessionRegisteredEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestSession> pSession;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
            AssertBreak(!pSession.isNull());
            BOOL fRegistered;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
            Bstr strName;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));
            ULONG uID;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));

            RTPrintf("Session ID=%RU32 \"%s\" %s\n",
                     uID, Utf8Str(strName).c_str(),
                     fRegistered ? "registered" : "unregistered");
            if (fRegistered)
            {
                if (mfVerbose)
                    RTPrintf("Registering ...\n");

                /* Register for IGuestSession events. */
                ComObjPtr<GuestSessionEventListenerImpl> pListener;
                pListener.createObject();
                CHECK_ERROR_BREAK(pListener, init(new GuestSessionEventListener()));

                ComPtr<IEventSource> es;
                CHECK_ERROR_BREAK(pSession, COMGETTER(EventSource)(es.asOutParam()));
                com::SafeArray<VBoxEventType_T> eventTypes;
                eventTypes.push_back(VBoxEventType_OnGuestFileRegistered);
                eventTypes.push_back(VBoxEventType_OnGuestProcessRegistered);
                CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
                                                       true /* Active listener */));

                GuestSessionStats sessionStats(pListener);
                mSessions[pSession] = sessionStats;
            }
            else
            {
                GuestEventSessions::iterator itSession = mSessions.find(pSession);
                if (itSession != mSessions.end())
                {
                    if (mfVerbose)
                        RTPrintf("Unregistering ...\n");

                    if (!itSession->first.isNull())
                    {
                        /* Listener unregistration. */
                        ComPtr<IEventSource> pES;
                        CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam()));
                        if (!pES.isNull())
                            CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener));
                        itSession->first->Release();
                    }

                    mSessions.erase(itSession);
                }
            }

        } while (0);
        break;
    }

    default:
        AssertFailed();
    }

    return S_OK;
}
STDMETHODIMP GuestSessionEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
{
    switch (aType)
    {
    case VBoxEventType_OnGuestFileRegistered:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestFileRegisteredEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestFile> pFile;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pFile.asOutParam()));
            AssertBreak(!pFile.isNull());
            BOOL fRegistered;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
            Bstr strPath;
            CHECK_ERROR_BREAK(pFile, COMGETTER(FileName)(strPath.asOutParam()));

            RTPrintf("File \"%s\" %s\n",
                     Utf8Str(strPath).c_str(),
                     fRegistered ? "registered" : "unregistered");
            if (fRegistered)
            {
                if (mfVerbose)
                    RTPrintf("Registering ...\n");

                /* Register for IGuestFile events. */
                ComObjPtr<GuestFileEventListenerImpl> pListener;
                pListener.createObject();
                CHECK_ERROR_BREAK(pListener, init(new GuestFileEventListener()));

                ComPtr<IEventSource> es;
                CHECK_ERROR_BREAK(pFile, COMGETTER(EventSource)(es.asOutParam()));
                com::SafeArray<VBoxEventType_T> eventTypes;
                eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
                CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
                                                       true /* Active listener */));

                GuestFileStats fileStats(pListener);
                mFiles[pFile] = fileStats;
            }
            else
            {
                GuestEventFiles::iterator itFile = mFiles.find(pFile);
                if (itFile != mFiles.end())
                {
                    if (mfVerbose)
                        RTPrintf("Unregistering file ...\n");

                    if (!itFile->first.isNull())
                    {
                        /* Listener unregistration. */
                        ComPtr<IEventSource> pES;
                        CHECK_ERROR(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
                        if (!pES.isNull())
                            CHECK_ERROR(pES, UnregisterListener(itFile->second.mListener));
                        itFile->first->Release();
                    }

                    mFiles.erase(itFile);
                }
            }

        } while (0);
        break;
    }

    case VBoxEventType_OnGuestProcessRegistered:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestProcessRegisteredEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestProcess> pProcess;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam()));
            AssertBreak(!pProcess.isNull());
            BOOL fRegistered;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
            Bstr strPath;
            CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam()));

            RTPrintf("Process \"%s\" %s\n",
                     Utf8Str(strPath).c_str(),
                     fRegistered ? "registered" : "unregistered");
            if (fRegistered)
            {
                if (mfVerbose)
                    RTPrintf("Registering ...\n");

                /* Register for IGuestProcess events. */
                ComObjPtr<GuestProcessEventListenerImpl> pListener;
                pListener.createObject();
                CHECK_ERROR_BREAK(pListener, init(new GuestProcessEventListener()));

                ComPtr<IEventSource> es;
                CHECK_ERROR_BREAK(pProcess, COMGETTER(EventSource)(es.asOutParam()));
                com::SafeArray<VBoxEventType_T> eventTypes;
                eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
                CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
                                                       true /* Active listener */));

                GuestProcStats procStats(pListener);
                mProcs[pProcess] = procStats;
            }
            else
            {
                GuestEventProcs::iterator itProc = mProcs.find(pProcess);
                if (itProc != mProcs.end())
                {
                    if (mfVerbose)
                        RTPrintf("Unregistering process ...\n");

                    if (!itProc->first.isNull())
                    {
                        /* Listener unregistration. */
                        ComPtr<IEventSource> pES;
                        CHECK_ERROR(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
                        if (!pES.isNull())
                            CHECK_ERROR(pES, UnregisterListener(itProc->second.mListener));
                        itProc->first->Release();
                    }

                    mProcs.erase(itProc);
                }
            }

        } while (0);
        break;
    }

    case VBoxEventType_OnGuestSessionStateChanged:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestSessionStateChangedEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());
            ComPtr<IGuestSession> pSession;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
            AssertBreak(!pSession.isNull());

            GuestSessionStatus_T sessSts;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Status)(&sessSts));
            ULONG uID;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));
            Bstr strName;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));

            RTPrintf("Session ID=%RU32 \"%s\" changed status to [%s]\n",
                     uID, Utf8Str(strName).c_str(), gctlGuestSessionStatusToText(sessSts));

        } while (0);
        break;
    }

    default:
        AssertFailed();
    }

    return S_OK;
}