int vboxNetAdpCreate(PINTNETTRUNKFACTORY pIfFactory, PVBOXNETADP *ppNew)
{
    int rc;
    unsigned i;
    PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));

    for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
    {
        RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
        PVBOXNETADP pThis = &pGlobals->aAdapters[i];

        if (vboxNetAdpCheckAndSetState(pThis, kVBoxNetAdpState_Invalid, kVBoxNetAdpState_Transitional))
        {
            /* Found an empty slot -- use it. */
            uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
            Assert(cRefs == 1);
            RTMAC Mac;
            vboxNetAdpComposeMACAddress(pThis, &Mac);
            rc = vboxNetAdpOsCreate(pThis, &Mac);
            *ppNew = pThis;
            RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
            vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available);
            RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp);
            return rc;
        }
    }

    /* All slots in adapter array are busy. */
    return VERR_OUT_OF_RESOURCES;
}
int vboxNetAdpCreate(PVBOXNETADP *ppNew, const char *pcszName)
{
    int rc;
    unsigned i;
    for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
    {
        PVBOXNETADP pThis = &g_aAdapters[i];

        if (ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Invalid))
        {
            RTMAC Mac;
            /* Found an empty slot -- use it. */
            Log(("vboxNetAdpCreate: found empty slot: %d\n", i));
            if (pcszName)
            {
                Log(("vboxNetAdpCreate: using name: %s\n", pcszName));
                pThis->iUnit = vboxNetAdpGetUnitByName(pcszName);
                strncpy(pThis->szName, pcszName, sizeof(pThis->szName));
                pThis->szName[sizeof(pThis->szName) - 1] = '\0';
            }
            else
            {
                pThis->iUnit = vboxNetAdpGetNextAvailableUnit();
                pThis->szName[0] = '\0';
            }
            if (pThis->iUnit < 0)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                vboxNetAdpComposeMACAddress(pThis, &Mac);
                rc = vboxNetAdpOsCreate(pThis, &Mac);
                Log(("vboxNetAdpCreate: pThis=%p pThis->iUnit=%d, pThis->szName=%s\n",
                     pThis, pThis->iUnit, pThis->szName));
            }
            if (RT_SUCCESS(rc))
            {
                *ppNew = pThis;
                ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Active);
                Log2(("VBoxNetAdpCreate: Created %s\n", g_aAdapters[i].szName));
            }
            else
            {
                ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
                Log(("vboxNetAdpCreate: vboxNetAdpOsCreate failed with '%Rrc'.\n", rc));
            }
            for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
                Log2(("VBoxNetAdpCreate: Scanning entry: state=%d unit=%d name=%s\n",
                      g_aAdapters[i].enmState, g_aAdapters[i].iUnit, g_aAdapters[i].szName));
            return rc;
        }
    }
    Log(("vboxNetAdpCreate: no empty slots!\n"));

    /* All slots in adapter array are busy. */
    return VERR_OUT_OF_RESOURCES;
}
static void vboxNetAdpDarwinComposeUUID(PVBOXNETADP pThis, PRTUUID pUuid)
{
    /* Generate UUID from name and MAC address. */
    RTUuidClear(pUuid);
    memcpy(pUuid->au8, "vboxnet", 7);
    pUuid->Gen.u8ClockSeqHiAndReserved = (pUuid->Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
    pUuid->Gen.u16TimeHiAndVersion = (pUuid->Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
    pUuid->Gen.u8ClockSeqLow = pThis->iUnit;
    vboxNetAdpComposeMACAddress(pThis, (PRTMAC)pUuid->Gen.au8Node);
}