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; }
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; }