Exemplo n.º 1
0
/**
 * Performs the required actions when a device has been added.
 *
 * This means things like running filters and subsequent capturing and
 * VM attaching. This may result in IPC and temporary lock abandonment.
 *
 * @param   aDevice     The device in question.
 * @param   aUSBDevice  The USB device structure.
 */
void USBProxyService::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice,
                                  SessionMachinesList &llOpenedMachines,
                                  PUSBDEVICE aUSBDevice)
{
    /*
     * Validate preconditions.
     */
    AssertReturnVoid(!isWriteLockOnCurrentThread());
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n",
                     (HostUSBDevice *)aDevice,
                     aDevice->getName().c_str(),
                     aDevice->getStateName(),
                     aDevice->getId().raw()));

    /*
     * Run filters on the device.
     */
    if (aDevice->isCapturableOrHeld())
    {
        devLock.release();
        HRESULT rc = runAllFiltersOnDevice(aDevice, llOpenedMachines, NULL /* aIgnoreMachine */);
        AssertComRC(rc);
    }

    NOREF(aUSBDevice);
}
Exemplo n.º 2
0
/**
 * Handle a device which state changed in some significant way.
 *
 * This means things like running filters and subsequent capturing and
 * VM attaching. This may result in IPC and temporary lock abandonment.
 *
 * @param   aDevice         The device.
 * @param   pllOpenedMachines list of running session machines (VirtualBox::getOpenedMachines()); if NULL, we don't run filters
 * @param   aIgnoreMachine  Machine to ignore when running filters.
 */
void USBProxyService::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, SessionMachine *aIgnoreMachine)
{
    /*
     * Validate preconditions.
     */
    AssertReturnVoid(!isWriteLockOnCurrentThread());
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid} aRunFilters=%RTbool aIgnoreMachine=%p\n",
                     (HostUSBDevice *)aDevice,
                     aDevice->getName().c_str(),
                     aDevice->getStateName(),
                     aDevice->getId().raw(),
                     (pllOpenedMachines != NULL),       // used to be "bool aRunFilters"
                     aIgnoreMachine));
    devLock.release();

    /*
     * Run filters if requested to do so.
     */
    if (pllOpenedMachines)
    {
        HRESULT rc = runAllFiltersOnDevice(aDevice, *pllOpenedMachines, aIgnoreMachine);
        AssertComRC(rc);
    }
}
Exemplo n.º 3
0
CmtFileBase*
CmtFat::FileCreate( cpchar fname, int32 msMode ) {
  FatDirEntry1x *ptr = 0;
  CmtFileBase *file = 0;
  devLock();
  if( msMode & CMT_CREATE_WRITE ) {
    //Открыть для записи
    ptr = FindFile( fname );
    //Если уже существует, то удалить файл
    if( ptr && (msMode & CMT_FILE_RESET) ) {
      DeleteFileEntry( ptr );
      ptr = 0;
      }
    //Создать новый файл
    if( ptr == 0 )
      ptr = CreateFileName( fname );
    }
  else if( msMode & CMT_CREATE_READ ) {
    //Открыть для чтения
    ptr = FindFile( fname );
    }
  if( ptr ) {
    //Файл найден
    file = new CmtFatFile( this, ptr, msMode );
    }
  devUnLock();
  return file;
  }
Exemplo n.º 4
0
/**
 * Apply filters for the machine to all eligible USB devices.
 *
 * This is in an interface for SessionMachine::CaptureUSBDevice(), which
 * is an internal worker used by Console::AutoCaptureUSBDevices() from the
 * VM process at VM startup.
 *
 * Matching devices will be attached to the VM and may result IPC back
 * to the VM process via SessionMachine::onUSBDeviceAttach() depending
 * on whether the device needs to be captured or not. If capture is
 * required, SessionMachine::onUSBDeviceAttach() will be called
 * asynchronously by the USB proxy service thread.
 *
 * @param   aMachine        The machine to capture devices for.
 *
 * @returns COM status code, perhaps with error info.
 *
 * @remarks Temporarily locks this object, the machine object and some USB
 *          device, and the called methods will lock similar objects.
 */
HRESULT USBProxyService::autoCaptureDevicesForVM(SessionMachine *aMachine)
{
    LogFlowThisFunc(("aMachine=%p{%s}\n",
                     aMachine,
                     aMachine->getName().c_str()));

    /*
     * Make a copy of the list because we cannot hold the lock protecting it.
     * (This will not make copies of any HostUSBDevice objects, only reference them.)
     */
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    HostUSBDeviceList ListCopy = mDevices;
    alock.release();

    for (HostUSBDeviceList::iterator it = ListCopy.begin();
         it != ListCopy.end();
         ++it)
    {
        ComObjPtr<HostUSBDevice> device = *it;
        AutoReadLock devLock(device COMMA_LOCKVAL_SRC_POS);
        if (   device->getUnistate() == kHostUSBDeviceState_HeldByProxy
            || device->getUnistate() == kHostUSBDeviceState_Unused
            || device->getUnistate() == kHostUSBDeviceState_Capturable)
        {
            devLock.release();
            runMachineFilters(aMachine, device);
        }
    }

    return S_OK;
}
Exemplo n.º 5
0
int32
CmtFat::GetFileAttr( cpchar fname, CMT_FILE_ATTR *attr ) {
  devLock();
  FatDirEntry1x *ptr = FindFile( fname );
  if( ptr ) {
    //Файл найден
    ptr->FillAttr( fname, attr );
    devUnLock();
    return CMTE_OK;
    }
  devUnLock();
  return CMTE_FS_NO_FILE;
  }
Exemplo n.º 6
0
bool USBProxyBackendUsbIp::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters,
                                             SessionMachine **aIgnoreMachine)
{
    AssertReturn(aDevice, false);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    if (    aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE
        &&  aDevice->i_getUsbData()->enmState == USBDEVICESTATE_USED_BY_HOST)
        LogRel(("USBProxy: Device %04x:%04x (%s) has become accessible.\n",
                aUSBDevice->idVendor, aUSBDevice->idProduct, aUSBDevice->pszAddress));
    devLock.release();
    return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
}
Exemplo n.º 7
0
int32
CmtFat::FileDelete( cpchar fname ) {
  devLock();
  FatDirEntry1x *ptr = FindFile( fname );
  //Если уже существует, то удалить файл
  if( ptr ) {
    DeleteFileEntry( ptr );
    devUnLock();
    return CMTE_OK;
    }
  devUnLock();
  return CMTE_FS_NO_FILE;
  }
Exemplo n.º 8
0
int32
CmtFat::FileRename( cpchar sour, cpchar dest ) {
  FatDirEntry1x *ptr;
  devLock();
  //Открыть для записи
  ptr = FindFile( sour );
  //Если уже существует, то переименовать
  //if( ptr ) {
    //FatDirEntry1x temp;
    //memcpy( &temp, ptr, sizeof(F))
    //}
  devUnLock();
  return CMTE_OK;
  }
Exemplo n.º 9
0
int32
CmtFat::SetFileAttr( cpchar fname, CMT_FILE_ATTR *lpFileAttr ) {
  devLock();
  FatDirEntry1x *ptr = FindFile( fname );
  if( ptr ) {
    //Файл найден
    ptr->mAttrib = lpFileAttr->fileAttributes;
    dirtyDirSector = 1;
    devUnLock();
    return CMTE_OK;
    }
  devUnLock();
  return CMTE_FS_NO_FILE;
  }
Exemplo n.º 10
0
int USBProxyServiceDarwin::releaseDevice(HostUSBDevice *aDevice)
{
    /*
     * Check preconditions.
     */
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));

    Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);

#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
    /*
     * Fake it.
     */
    ASMAtomicWriteBool(&mFakeAsync, true);
    devLock.release();
    interruptWait();
    return VINF_SUCCESS;

#else
    /*
     * Create a one-shot ignore filter for the device
     * and trigger a re-enumeration of it.
     */
    USBFILTER Filter;
    USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
    initFilterFromDevice(&Filter, aDevice);
    Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
    Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));

    void *pvId = USBLibAddFilter(&Filter);
    if (!pvId)
        return VERR_GENERAL_FAILURE;

    int rc = DarwinReEnumerateUSBDevice(aDevice->mUsb);
    if (RT_SUCCESS(rc))
        aDevice->mOneShotId = pvId;
    else
    {
        USBLibRemoveFilter(pvId);
        pvId = NULL;
    }
    LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
    return rc;
#endif
}
Exemplo n.º 11
0
/**
 * A device was added, we need to adjust mUdevPolls.
 *
 * See USBProxyService::deviceAdded for details.
 */
void USBProxyBackendLinux::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines,
                                       PUSBDEVICE aUSBDevice)
{
    AssertReturnVoid(aDevice);
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    if (aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST)
    {
        LogRel(("USBProxy: Device %04x:%04x (%s) isn't accessible. giving udev a few seconds to fix this...\n",
                aUSBDevice->idVendor, aUSBDevice->idProduct, aUSBDevice->pszAddress));
        mUdevPolls = 10; /* (10 * 500ms = 5s) */
    }

    devLock.release();
    USBProxyBackend::deviceAdded(aDevice, llOpenedMachines, aUSBDevice);
}
Exemplo n.º 12
0
int USBProxyBackendFreeBSD::releaseDevice(HostUSBDevice *aDevice)
{
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));

    /*
     * We're not really holding it atm., just fake it.
     */
    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost);
    devLock.release();
    interruptWait();

    return VINF_SUCCESS;
}
/**
 * Detach all USB devices currently attached to a VM.
 *
 * This is in an interface for SessionMachine::DetachAllUSBDevices(), which
 * is an internal worker used by Console::powerDown() from the VM process
 * at VM startup, and SessionMachine::uninit() at VM abend.
 *
 * This is, like #detachDeviceFromVM(), normally a two stage journey
 * where \a aDone indicates where we are. In addition we may be called
 * to clean up VMs that have abended, in which case there will be no
 * preparatory call. Filters will be applied to the devices in the final
 * call with the risk that we have to do some IPC when attaching them
 * to other VMs.
 *
 * @param   aMachine        The machine to detach devices from.
 *
 * @returns COM status code, perhaps with error info.
 *
 * @remarks Write locks the host object and may temporarily abandon
 *          its locks to perform IPC.
 */
HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine *aMachine, bool aDone, bool aAbnormal)
{
    // get a list of all running machines while we're outside the lock
    // (getOpenedMachines requests locks which are incompatible with the host object lock)
    SessionMachinesList llOpenedMachines;
    mHost->i_parent()->i_getOpenedMachines(llOpenedMachines);

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    /*
     * Make a copy of the device list (not the HostUSBDevice objects, just
     * the list) since we may end up performing IPC and temporarily have
     * to abandon locks when applying filters.
     */
    HostUSBDeviceList ListCopy = mDevices;

    for (HostUSBDeviceList::iterator it = ListCopy.begin();
         it != ListCopy.end();
         ++it)
    {
        ComObjPtr<HostUSBDevice> pHostDevice = *it;
        AutoWriteLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS);
        if (pHostDevice->i_getMachine() == aMachine)
        {
            /*
             * Same procedure as in detachUSBDevice().
             */
            bool fRunFilters = false;
            HRESULT hrc = pHostDevice->i_onDetachFromVM(aMachine, aDone, &fRunFilters, aAbnormal);
            if (    SUCCEEDED(hrc)
                &&  fRunFilters)
            {
                Assert(   aDone
                       && pHostDevice->i_getUnistate() == kHostUSBDeviceState_HeldByProxy
                       && pHostDevice->i_getMachine().isNull());
                devLock.release();
                alock.release();
                HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine);
                ComAssertComRC(hrc2);
                alock.acquire();
            }
        }
    }

    return S_OK;
}
Exemplo n.º 14
0
int USBProxyBackendFreeBSD::captureDevice(HostUSBDevice *aDevice)
{
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));

    /*
     * Don't think we need to do anything when the device is held... fake it.
     */
    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing);
    devLock.release();
    interruptWait();

    return VINF_SUCCESS;
}
int USBProxyServiceWindows::releaseDevice(HostUSBDevice *aDevice)
{
    /*
     * Check preconditions.
     */
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));

    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost);

    /*
     * Create a one-shot ignore filter for the device
     * and trigger a re-enumeration of it.
     */
    USBFILTER Filter;
    USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
    initFilterFromDevice(&Filter, aDevice);
    Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
    Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));

    void *pvId = USBLibAddFilter(&Filter);
    if (!pvId)
    {
        AssertMsgFailed(("Add one-shot Filter failed\n"));
        return VERR_GENERAL_FAILURE;
    }

    int rc = USBLibRunFilters();
    if (!RT_SUCCESS(rc))
    {
        AssertMsgFailed(("Run Filters failed\n"));
        USBLibRemoveFilter(pvId);
        return rc;
    }


    return VINF_SUCCESS;
}
Exemplo n.º 16
0
/**
 * Notification from VM process about USB device detaching progress.
 *
 * This is in an interface for SessionMachine::DetachUSBDevice(), which is
 * an internal worker used by Console::DetachUSBDevice() from the VM process.
 *
 * @param   aMachine        The machine which is sending the notification.
 * @param   aId             The UUID of the USB device is concerns.
 * @param   aDone           \a false for the pre-action notification (necessary
 *                          for advancing the device state to avoid confusing
 *                          the guest).
 *                          \a true for the post-action notification. The device
 *                          will be subjected to all filters except those of
 *                          of \a Machine.
 *
 * @returns COM status code.
 *
 * @remarks When \a aDone is \a true this method may end up doing IPC to other
 *          VMs when running filters. In these cases it will temporarily
 *          abandon its locks.
 */
HRESULT USBProxyService::detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aId, bool aDone)
{
    LogFlowThisFunc(("aMachine=%p{%s} aId={%RTuuid} aDone=%RTbool\n",
                     aMachine,
                     aMachine->getName().c_str(),
                     Guid(aId).raw(),
                     aDone));

    // get a list of all running machines while we're outside the lock
    // (getOpenedMachines requests locks which are incompatible with the lock of the machines list)
    SessionMachinesList llOpenedMachines;
    mHost->parent()->getOpenedMachines(llOpenedMachines);

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    ComObjPtr<HostUSBDevice> pHostDevice = findDeviceById(aId);
    ComAssertRet(!pHostDevice.isNull(), E_FAIL);
    AutoWriteLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS);

    /*
     * Work the state machine.
     */
    LogFlowThisFunc(("id={%RTuuid} state=%s aDone=%RTbool name={%s}\n",
                     pHostDevice->getId().raw(), pHostDevice->getStateName(), aDone, pHostDevice->getName().c_str()));
    bool fRunFilters = false;
    HRESULT hrc = pHostDevice->onDetachFromVM(aMachine, aDone, &fRunFilters);

    /*
     * Run filters if necessary.
     */
    if (    SUCCEEDED(hrc)
        &&  fRunFilters)
    {
        Assert(aDone && pHostDevice->getUnistate() == kHostUSBDeviceState_HeldByProxy && pHostDevice->getMachine().isNull());
        devLock.release();
        alock.release();
        HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine);
        ComAssertComRC(hrc2);
    }
    return hrc;
}
Exemplo n.º 17
0
/**
 * Remove device notification hook for the OS specific code.
 *
 * This is means things like
 *
 * @param   aDevice     The device in question.
 */
void USBProxyService::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice)
{
    /*
     * Validate preconditions.
     */
    AssertReturnVoid(!isWriteLockOnCurrentThread());
    AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
    AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n",
                     (HostUSBDevice *)aDevice,
                     aDevice->getName().c_str(),
                     aDevice->getStateName(),
                     aDevice->getId().raw()));

    /*
     * Detach the device from any machine currently using it,
     * reset all data and uninitialize the device object.
     */
    devLock.release();
    aDevice->onPhysicalDetached();
}
int USBProxyBackendSolaris::releaseDevice(HostUSBDevice *aDevice)
{
    /*
     * Check preconditions.
     */
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));

    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost);
    AssertReturn(aDevice->i_getUsbData(), VERR_INVALID_POINTER);

    /*
     * Create a one-shot ignore filter for the device and reset it.
     */
    USBFILTER Filter;
    USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
    initFilterFromDevice(&Filter, aDevice);

    void *pvId = USBLibAddFilter(&Filter);
    if (!pvId)
    {
        LogRel(("USBService: Adding ignore filter failed!\n"));
        return VERR_GENERAL_FAILURE;
    }

    PUSBDEVICE pDev = aDevice->i_getUsbData();
    int rc = USBLibResetDevice(pDev->pszDevicePath, true /* Re-attach */);
    if (RT_SUCCESS(rc))
        aDevice->i_setBackendUserData(pvId);
    else
    {
        USBLibRemoveFilter(pvId);
        pvId = NULL;
    }
    LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
    return rc;
}
int USBProxyServiceSolaris::captureDevice(HostUSBDevice *aDevice)
{
    /*
     * Check preconditions.
     */
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);

    AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));

    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing);
    AssertReturn(aDevice->mUsb, VERR_INVALID_POINTER);

    /*
     * Create a one-shot capture filter for the device and reset the device.
     */
    USBFILTER Filter;
    USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_CAPTURE);
    initFilterFromDevice(&Filter, aDevice);

    void *pvId = USBLibAddFilter(&Filter);
    if (!pvId)
    {
        LogRel(("USBService: failed to add filter\n"));
        return VERR_GENERAL_FAILURE;
    }

    PUSBDEVICE pDev = aDevice->mUsb;
    int rc = USBLibResetDevice(pDev->pszDevicePath, true);
    if (RT_SUCCESS(rc))
        aDevice->mOneShotId = pvId;
    else
    {
        USBLibRemoveFilter(pvId);
        pvId = NULL;
    }
    LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
    return rc;
}
Exemplo n.º 20
0
CmtFinderBase*
CmtFat::FindFirst( cpchar pattern, int32 findFlag, CMT_FILE_ATTR *lpFileAttr ) {
  CmtFinderBase *finderBase = 0;
  uint32 subDir = 0; //Начальный кластер поддиректория
  devLock();
  //Войти в поддиректорий
  cpchar pat = GetSubDir( pattern, &subDir );
  if( pat ) {
    //Успешно вошли в поддиректорий
    FatDirEntry1x *ptr;
    CmtFatFinder finder( subDir );
    //Место для длинного имени
    char longName[CMT_MAX_PATH];
    longName[0] = 0;
    while(1) {
      ptr = GetNextFileEntry( &finder );
      if( ptr == 0 ) break; //Ничего не найдено
      if( ptr->CheckLongName( longName ) ) continue;
      //Найден очередной элемент директория
      if( ptr->PatternName( longName, pat, (uint8)findFlag ) ) {
        if( lpFileAttr ) {
          ptr->FillAttr( longName, lpFileAttr );
          //Создать поисковик
          finderBase = new CmtFatFileFinder( this, pat, &finder, (uint8)findFlag );
          }
        else {
          //Требуется только определить наличие
          finderBase = (CmtFinderBase*)1;
          }
        break;
        }
      longName[0] = 0;
      }
    }
  devUnLock();
  return finderBase; //Нет директория
  }
Exemplo n.º 21
0
/**
 * Process any relevant changes in the attached USB devices.
 *
 * Except for the first call, this is always running on the service thread.
 */
void USBProxyService::processChanges(void)
{
    LogFlowThisFunc(("\n"));

    /*
     * Get the sorted list of USB devices.
     */
    PUSBDEVICE pDevices = getDevices();
    pDevices = sortDevices(pDevices);

    // get a list of all running machines while we're outside the lock
    // (getOpenedMachines requests higher priority locks)
    SessionMachinesList llOpenedMachines;
    mHost->parent()->getOpenedMachines(llOpenedMachines);

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    /*
     * Compare previous list with the new list of devices
     * and merge in any changes while notifying Host.
     */
    HostUSBDeviceList::iterator it = this->mDevices.begin();
    while (    it != mDevices.end()
            || pDevices)
    {
        ComObjPtr<HostUSBDevice> pHostDevice;

        if (it != mDevices.end())
            pHostDevice = *it;

        /*
         * Assert that the object is still alive (we still reference it in
         * the collection and we're the only one who calls uninit() on it.
         */
        AutoCaller devCaller(pHostDevice.isNull() ? NULL : pHostDevice);
        AssertComRC(devCaller.rc());

        /*
         * Lock the device object since we will read/write its
         * properties. All Host callbacks also imply the object is locked.
         */
        AutoWriteLock devLock(pHostDevice.isNull() ? NULL : pHostDevice
                              COMMA_LOCKVAL_SRC_POS);

        /*
         * Compare.
         */
        int iDiff;
        if (pHostDevice.isNull())
            iDiff = 1;
        else
        {
            if (!pDevices)
                iDiff = -1;
            else
                iDiff = pHostDevice->compare(pDevices);
        }
        if (!iDiff)
        {
            /*
             * The device still there, update the state and move on. The PUSBDEVICE
             * structure is eaten by updateDeviceState / HostUSBDevice::updateState().
             */
            PUSBDEVICE pCur = pDevices;
            pDevices = pDevices->pNext;
            pCur->pPrev = pCur->pNext = NULL;

            bool fRunFilters = false;
            SessionMachine *pIgnoreMachine = NULL;
            devLock.release();
            alock.release();
            if (updateDeviceState(pHostDevice, pCur, &fRunFilters, &pIgnoreMachine))
                deviceChanged(pHostDevice,
                              (fRunFilters ? &llOpenedMachines : NULL),
                              pIgnoreMachine);
            alock.acquire();
            it++;
        }
        else
        {
            if (iDiff > 0)
            {
                /*
                 * Head of pDevices was attached.
                 */
                PUSBDEVICE pNew = pDevices;
                pDevices = pDevices->pNext;
                pNew->pPrev = pNew->pNext = NULL;

                ComObjPtr<HostUSBDevice> NewObj;
                NewObj.createObject();
                NewObj->init(pNew, this);
                Log(("USBProxyService::processChanges: attached %p {%s} %s / %p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n",
                     (HostUSBDevice *)NewObj,
                     NewObj->getName().c_str(),
                     NewObj->getStateName(),
                     pNew,
                     pNew->idVendor,
                     pNew->idProduct,
                     pNew->pszProduct,
                     pNew->pszManufacturer));

                mDevices.insert(it, NewObj);

                devLock.release();
                alock.release();
                deviceAdded(NewObj, llOpenedMachines, pNew);
                alock.acquire();
            }
            else
            {
                /*
                 * Check if the device was actually detached or logically detached
                 * as the result of a re-enumeration.
                 */
                if (!pHostDevice->wasActuallyDetached())
                    it++;
                else
                {
                    it = mDevices.erase(it);
                    devLock.release();
                    alock.release();
                    deviceRemoved(pHostDevice);
                    Log(("USBProxyService::processChanges: detached %p {%s}\n",
                         (HostUSBDevice *)pHostDevice,
                         pHostDevice->getName().c_str()));

                    /* from now on, the object is no more valid,
                     * uninitialize to avoid abuse */
                    devCaller.release();
                    pHostDevice->uninit();
                    alock.acquire();
                }
            }
        }
    } /* while */

    LogFlowThisFunc(("returns void\n"));
}
Exemplo n.º 22
0
/**
 * Runs all the filters on the specified device.
 *
 * All filters mean global and active VM, with the exception of those
 * belonging to \a aMachine. If a global ignore filter matched or if
 * none of the filters matched, the device will be released back to
 * the host.
 *
 * The device calling us here will be in the HeldByProxy, Unused, or
 * Capturable state. The caller is aware that locks held might have
 * to be abandond because of IPC and that the device might be in
 * almost any state upon return.
 *
 *
 * @returns COM status code (only parameter & state checks will fail).
 * @param   aDevice         The USB device to apply filters to.
 * @param   aIgnoreMachine  The machine to ignore filters from (we've just
 *                          detached the device from this machine).
 *
 * @note    The caller is expected to own no locks.
 */
HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,
                                               SessionMachinesList &llOpenedMachines,
                                               SessionMachine *aIgnoreMachine)
{
    LogFlowThisFunc(("{%s} ignoring=%p\n", aDevice->getName().c_str(), aIgnoreMachine));

    /*
     * Verify preconditions.
     */
    AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
    AssertReturn(!aDevice->isWriteLockOnCurrentThread(), E_FAIL);
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
    AssertMsgReturn(aDevice->isCapturableOrHeld(), ("{%s} %s\n", aDevice->getName().c_str(), aDevice->getStateName()), E_FAIL);

    /*
     * Get the lists we'll iterate.
     */
    Host::USBDeviceFilterList globalFilters;

    mHost->getUSBFilters(&globalFilters);

    /*
     * Run global filters filters first.
     */
    bool fHoldIt = false;
    for (Host::USBDeviceFilterList::const_iterator it = globalFilters.begin();
         it != globalFilters.end();
         ++it)
    {
        AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
        const HostUSBDeviceFilter::Data &data = (*it)->getData();
        if (aDevice->isMatch(data))
        {
            USBDeviceFilterAction_T action = USBDeviceFilterAction_Null;
            (*it)->COMGETTER(Action)(&action);
            if (action == USBDeviceFilterAction_Ignore)
            {
                /*
                 * Release the device to the host and we're done.
                 */
                filterLock.release();
                devLock.release();
                alock.release();
                aDevice->requestReleaseToHost();
                return S_OK;
            }
            if (action == USBDeviceFilterAction_Hold)
            {
                /*
                 * A device held by the proxy needs to be subjected
                 * to the machine filters.
                 */
                fHoldIt = true;
                break;
            }
            AssertMsgFailed(("action=%d\n", action));
        }
    }
    globalFilters.clear();

    /*
     * Run the per-machine filters.
     */
    for (SessionMachinesList::const_iterator it = llOpenedMachines.begin();
         it != llOpenedMachines.end();
         ++it)
    {
        ComObjPtr<SessionMachine> pMachine = *it;

        /* Skip the machine the device was just detached from. */
        if (    aIgnoreMachine
            &&  pMachine == aIgnoreMachine)
            continue;

        /* runMachineFilters takes care of checking the machine state. */
        devLock.release();
        alock.release();
        if (runMachineFilters(pMachine, aDevice))
        {
            LogFlowThisFunc(("{%s} attached to %p\n", aDevice->getName().c_str(), (void *)pMachine));
            return S_OK;
        }
        alock.acquire();
        devLock.acquire();
    }

    /*
     * No matching machine, so request hold or release depending
     * on global filter match.
     */
    devLock.release();
    alock.release();
    if (fHoldIt)
        aDevice->requestHold();
    else
        aDevice->requestReleaseToHost();
    return S_OK;
}
Exemplo n.º 23
0
int32
CmtFat::CreateDirectory( cpchar dirName ) {
  FatDirEntry1x *ptr = 0;
  devLock();
  //Открыть для записи
  ptr = FindFile( dirName );
  //Если уже существует, то невозможно создать
  if( ptr ) {
    devUnLock();
    return CMTE_FS_DIR_PRESENT;
    }
  uint32 subDir = 0; //Обозначение кластера директория верхнего уровня
  GetSubDir( dirName, &subDir );
  ptr = CreateFileName( dirName );
  if( ptr ) {
    //Обозначить как директорий
    ptr->mAttrib = FA_DIRECTORY;
    uint16 time = ptr->mCreationTime;
    uint16 date = ptr->mCreationDate;
    uint32 cluster = ptr->GetFirstCluster32();

    //Инициализировать кластер
    InitDirCluster( cluster );

    //Сформировать пустой директорий

    //Заполнить начальные записи директория
    ptr = GetDirRecord( SectorFromCluster(cluster), 0 );
    memcpy( ptr->mFileName, ".          ", 11 );
    ptr->mAttrib = FA_DIRECTORY;
    ptr->mReserved[0] = ptr->mReserved[1] = 0;
    ptr->mUpdateTime =     //time create/update
    ptr->mCreationTime = time;
    ptr->mUpdateDate =     //date create/update
    ptr->mAccessDate =
    ptr->mCreationDate = date;
    ptr->mFirstClusterHigh = 0; // higher
    ptr->mFileSize = 0;
    ptr->SetFirstCluster32( cluster );

    //Объявить сектор грязным
    dirtyDirSector = 1;

    ptr = GetDirRecord( curDirSector, 1 );
    memcpy( ptr->mFileName, "..         ", 11 );
    ptr->mAttrib = FA_DIRECTORY;
    ptr->mReserved[0] = ptr->mReserved[1] = 0;
    ptr->mUpdateTime =     //time create/update
    ptr->mCreationTime = time;
    ptr->mUpdateDate =     //date create/update
    ptr->mAccessDate =
    ptr->mCreationDate = date;
    ptr->mFirstClusterHigh = 0; // higher
    ptr->mFileSize = 0;
    ptr->SetFirstCluster32( subDir );

    //Объявить сектор грязным
    dirtyDirSector = 1;

    devUnLock();
    return CMTE_OK;
    }
  devUnLock();
  return CMTE_FAIL;
  }