Esempio n. 1
0
NTSTATUS
Bus_EjectDevice (
    PBUSENUM_EJECT_HARDWARE     Eject,
    PFDO_DEVICE_DATA            FdoData
    )
/*++
Routine Description:
    The user application has told us to eject the device from the bus.
    In a real situation the driver gets notified by an interrupt when the
    user presses the Eject button on the device.

Arguments:

    Eject   - pointer to Eject hardware structure.
    FdoData - contains the list to iterate over

Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/
{
    PLIST_ENTRY         entry;
    PPDO_DEVICE_DATA    pdoData;
    BOOLEAN             found = FALSE, ejectAll;

    PAGED_CODE ();

    ejectAll = (0 == Eject->SerialNo);

    ExAcquireFastMutex (&FdoData->Mutex);

    if (ejectAll) {
        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE,
                      ("Ejecting all the pdos!\n"));
    } else {
        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE,
                      ("Ejecting %d\n", Eject->SerialNo));
    }

    if (FdoData->NumPDOs == 0) {
        //
        // Somebody in user space isn't playing nice!!!
        //
        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_ERROR,
                      ("No devices to eject!\n"));
        ExReleaseFastMutex (&FdoData->Mutex);
        return STATUS_NO_SUCH_DEVICE;
    }

    //
    // Scan the list to find matching PDOs
    //
    for (entry = FdoData->ListOfPDOs.Flink;
         entry != &FdoData->ListOfPDOs;
         entry = entry->Flink) {

        pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);

        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE,
                      ("found device %d\n", pdoData->SerialNo));

        if (ejectAll || Eject->SerialNo == pdoData->SerialNo) {
            Bus_KdPrint (FdoData, BUS_DBG_IOCTL_INFO,
                          ("Ejected %d\n", pdoData->SerialNo));
            found = TRUE;
            IoRequestDeviceEject(pdoData->Self);
            if (!ejectAll) {
                break;
            }
        }
    }
    ExReleaseFastMutex (&FdoData->Mutex);

    if (found) {
        return STATUS_SUCCESS;
    }

    Bus_KdPrint (FdoData, BUS_DBG_IOCTL_ERROR,
                  ("Device %d is not present\n", Eject->SerialNo));

    return STATUS_INVALID_PARAMETER;
}
Esempio n. 2
0
NTSTATUS
NdasPortFdoDeviceControlEjectOrUnplugLogicalUnit(
	PNDASPORT_FDO_EXTENSION FdoExtension,
	PNDAS_LOGICALUNIT_ADDRESS LogicalUnitAddress,
	ULONG Flags,
	BOOLEAN Eject)
{
	NTSTATUS status;
	PNDASPORT_PDO_EXTENSION targetPdo;
	PLIST_ENTRY entry;

	PAGED_CODE();

	LogicalUnitAddress->PortNumber = FdoExtension->PortNumber;

	status = STATUS_DEVICE_DOES_NOT_EXIST;

	ExAcquireFastMutex (&FdoExtension->Mutex);

	for (entry = FdoExtension->ListOfPDOs.Flink;
		entry != &FdoExtension->ListOfPDOs;
		entry = entry->Flink) 
	{
		targetPdo = CONTAINING_RECORD(entry, NDASPORT_PDO_EXTENSION, Link);

		if (LogicalUnitAddress->Address == targetPdo->LogicalUnitAddress.Address)
		{
			//
			// Temporary pdo is regarded as none
			//
			if (targetPdo->IsTemporary)
			{
				status = STATUS_DEVICE_NOT_READY;
				break;
			}

			if (!targetPdo->IsDeviceRelationReported)
			{
				//
				// Pdo is not yet reported to Pnp bus relations.
				// If we call IoRequestDeviceEject before completing 
				// the bus relation query, it will lead pnp bug check.
				//
				status = STATUS_DEVICE_BUSY;
				break;
			}

			status = STATUS_SUCCESS;

			if (Eject)
			{
				// Nothing to do here
			}
			else
			{
				//
				// To be unplugged in the next invalidate device relations
				//
				targetPdo->Present = FALSE;
			}
			break;
		}
	}

	ExReleaseFastMutex (&FdoExtension->Mutex); 

	if (NT_SUCCESS(status))
	{
		if (Eject)
		{
			IoRequestDeviceEject(targetPdo->DeviceObject);
		}
		else
		{
			IoInvalidateDeviceRelations(
				FdoExtension->LowerPdo, 
				BusRelations);
		}
	}

	return status;
}