📄 tape.c
字号:
if (capPage) {
ExFreePool(capPage);
}
} else {
inquiryLength = 0;
}
TapeSymbolicNamePersistencePreference(Fdo->DriverObject,
TAPE_REGISTRY_SERVICES_KEY,
TAPE_PERSISTENCE_QUERY,
TAPE_PERSISTENCE_PRIVATE,
&tapeData->PersistencePreferred);
//
// Don't care about success. If this routine fails for any reason, we will
// assume old behavior (non persistent symbolic name) is preferred.
//
if (!tapeData->DosNameCreated) {
status = TapeCreateSymbolicName(Fdo, tapeData->PersistencePreferred);
//
// If we couldn't create a symbolic name, too bad!
// Just continue. A user mode application won't be able to open a handle
// to the device using the symbolic name however.
// But we'll update the Device Number that will be returned in response
// to IOCTL_STORAGE_GET_DEVICE_NUMBER, to something more meaningful than
// the bogus value we initialized it to.
//
if (!NT_SUCCESS(status)) {
ASSERT(NT_SUCCESS(status));
fdoExtension->DeviceNumber = tapeData->PnpNameDeviceNumber;
}
}
//
// Add tape device number to registry
//
ClassUpdateInformationInRegistry(Fdo,
"Tape",
fdoExtension->DeviceNumber,
inquiryData,
inquiryLength);
ExFreePool(inquiryData);
status = IoSetDeviceInterfaceState(&(tapeData->TapeInterfaceString),
TRUE);
if (!NT_SUCCESS(status)) {
DebugPrint((1,
"TapeStartDevice: Unable to register TapeDrive%x (NT Name) interface name - %x.\n",
tapeData->PnpNameDeviceNumber,
status));
}
return STATUS_SUCCESS;
}
NTSTATUS
TapeInitDevice(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine will complete the tape miniclass initialization. This includes
allocating sense info buffers and srb s-lists.
This routine will not clean up allocate resources if it fails - that
is left for device stop/removal
Arguments:
Fdo - a pointer to the functional device object for this device
Return Value:
status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PVOID senseData = NULL;
PTAPE_DATA tapeData;
PTAPE_INIT_DATA_EX tapeInitData;
NTSTATUS status;
PVOID minitapeExtension;
STORAGE_PROPERTY_ID propertyId;
UNICODE_STRING interfaceName;
PAGED_CODE();
//
// Allocate request sense buffer.
//
senseData = ExAllocatePool(NonPagedPoolCacheAligned,
SENSE_BUFFER_SIZE);
if (senseData == NULL) {
//
// The buffer cannot be allocated.
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple.
//
ClassInitializeSrbLookasideList(&(fdoExtension->CommonExtension),
TAPE_SRB_LIST_SIZE);
//
// Set the sense data pointer in the device extension.
//
fdoExtension->SenseData = senseData;
fdoExtension->DiskGeometry.BytesPerSector = UNDEFINED_BLOCK_SIZE;
//
// Get the tape init data again.
//
tapeData = (PTAPE_DATA)(fdoExtension->CommonExtension.DriverData);
tapeInitData = &tapeData->TapeInitData;
//
// Set timeout value in seconds.
//
if (tapeInitData->DefaultTimeOutValue) {
fdoExtension->TimeOutValue = tapeInitData->DefaultTimeOutValue;
} else {
fdoExtension->TimeOutValue = 180;
}
//
// Used to keep track of the last time a drive clean
// notification was sent by the driver
//
tapeData->LastDriveCleanRequestTime.QuadPart = 0;
//
// SRB Timeout delta is used to increase the timeout for certain
// commands - typically, commands such as SET_POSITION, ERASE, etc.
//
tapeData->SrbTimeoutDelta = GetTimeoutDeltaFromRegistry(fdoExtension->LowerPdo);
if ((tapeData->SrbTimeoutDelta) == 0) {
tapeData->SrbTimeoutDelta = fdoExtension->TimeOutValue;
}
//
// Call port driver to get adapter capabilities.
//
propertyId = StorageAdapterProperty;
status = ClassGetDescriptor(fdoExtension->CommonExtension.LowerDeviceObject,
&propertyId,
&(fdoExtension->AdapterDescriptor));
if (!NT_SUCCESS(status)) {
DebugPrint((1,
"TapeStartDevice: Unable to get adapter descriptor. Status %x\n",
status));
ExFreePool(senseData);
return status;
}
//
// Register for media change notification
//
ClassInitializeMediaChangeDetection(fdoExtension,
"Tape");
//
// Register interfaces for this device.
//
RtlInitUnicodeString(&tapeData->TapeInterfaceString, NULL);
//
// Register the device interface. However, enable it only after creating a
// symbolic link.
//
status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
(LPGUID) &TapeClassGuid,
NULL,
&(tapeData->TapeInterfaceString));
if (!NT_SUCCESS(status)) {
DebugPrint((1,
"TapeInitDevice: Unable to register TapeDrive%x (NT Name) interface name - %x.\n",
tapeData->PnpNameDeviceNumber,
status));
status = STATUS_SUCCESS;
}
return STATUS_SUCCESS;
} // End TapeInitDevice
NTSTATUS
TapeRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Type
)
/*++
Routine Description:
This routine is responsible for releasing any resources in use by the
tape driver.
Arguments:
DeviceObject - the device object being removed
Return Value:
none - this routine may not fail
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PTAPE_DATA tapeData = (PTAPE_DATA)fdoExtension->CommonExtension.DriverData;
NTSTATUS status;
PAGED_CODE();
if ((Type == IRP_MN_QUERY_REMOVE_DEVICE) ||
(Type == IRP_MN_CANCEL_REMOVE_DEVICE)) {
return STATUS_SUCCESS;
}
//
// Free all allocated memory.
//
if (Type == IRP_MN_REMOVE_DEVICE) {
if (fdoExtension->DeviceDescriptor) {
ExFreePool(fdoExtension->DeviceDescriptor);
fdoExtension->DeviceDescriptor = NULL;
}
if (fdoExtension->AdapterDescriptor) {
ExFreePool(fdoExtension->AdapterDescriptor);
fdoExtension->AdapterDescriptor = NULL;
}
if (fdoExtension->SenseData) {
ExFreePool(fdoExtension->SenseData);
fdoExtension->SenseData = NULL;
}
ClassDeleteSrbLookasideList(&fdoExtension->CommonExtension);
}
//
// Disable the interface before deleting the symbolic link.
//
if (tapeData->TapeInterfaceString.Buffer != NULL) {
IoSetDeviceInterfaceState(&(tapeData->TapeInterfaceString),
FALSE);
RtlFreeUnicodeString(&(tapeData->TapeInterfaceString));
//
// Clear it.
//
RtlInitUnicodeString(&(tapeData->TapeInterfaceString), NULL);
}
//
// If a PnP StopDevice already happened, the symbolic link has already been
// deleted.
//
if (tapeData->DosNameCreated) {
//
// Delete the symbolic link \DosDevices\TapeN.
//
TapeDeassignSymbolicLink(TAPE_DOS_DEVICES_PREFIX_W,
tapeData->SymbolicNameDeviceNumber,
FALSE);
tapeData->DosNameCreated = FALSE;
}
if (tapeData->PnpNameLinkCreated) {
//
// Delete the symbolic link \Device\TapeN or \Device\TapeDriveN depending
// on persistence preference. (Remember that legacy name format and
// persistence preference are mutually exclusive).
//
TapeDeassignSymbolicLink(TAPE_DEVICE_PREFIX_W,
tapeData->SymbolicNameDeviceNumber,
!tapeData->PersistencePreferred);
tapeData->PnpNameLinkCreated = FALSE;
}
IoGetConfigurationInformation()->TapeCount--;
return STATUS_SUCCESS;
}
NTSTATUS
TapeStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Type
)
{
//
// Since the symlinks are created in StartDevice and the device interface is
// also enabled there, this would be the place to delete the symlinks and
// to disable the device interface. However, classpnp will not call our
// StartDevice even when the device receives a PnP StartDevice IRP, because
// the device was already initialized (after the first Start).
// So we shall delete symlinks and disable device interface only in
// RemoveDevice.
//
PAGED_CODE();
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Type);
return STATUS_SUCCESS;
}
BOOLEAN
ScsiTapeNtStatusToTapeStatus(
IN NTSTATUS NtStatus,
OUT PTAPE_STATUS TapeStatus
)
/*++
Routine Description:
This routine translates an NT status code to a TAPE status code.
Arguments:
NtStatus - Supplies the NT status code.
TapeStatus - Returns the tape status code.
Return Value:
FALSE - No tranlation was possible.
TRUE - Success.
--*/
{
switch (NtStatus) {
case STATUS_SUCCESS:
*TapeStatus = TAPE_STATUS_SUCCESS;
break;
case STATUS_INSUFFICIENT_RESOURCES:
*TapeStatus = TAPE_STATUS_INSUFFICIENT_RESOURCES;
break;
case STATUS_NOT_IMPLEMENTED:
*TapeStatus = TAPE_STATUS_NOT_IMPLEMENTED;
break;
case STATUS_INVALID_DEVICE_REQUEST:
*TapeStatus = TAPE_STATUS_INVALID_DEVICE_REQUEST;
break;
case STATUS_INVALID_PARAMETER:
*TapeStatus = TAPE_STATUS_INVALID_PARAMETER;
break;
case STATUS_VERIFY_REQUIRED:
case STATUS_MEDIA_CHANGED:
*TapeStatus = TAPE_STATUS_MEDIA_CHANGED;
break;
case STATUS_BUS_RESET:
*TapeStatus = TAPE_STATUS_BUS_RESET;
break;
case STATUS_SETMARK_DETECTED:
*TapeStatus = TAPE_STATUS_SETMARK_DETECTED;
break;
case STATUS_FILEMARK_DETECTED:
*TapeStatus = TAPE_STATUS_FILEMARK_DETECTED;
break;
case STATUS_BEGINNING_OF_MEDIA:
*TapeStatus = TAPE_STATUS_BEGINNING_OF_MEDIA;
break;
case STATUS_END_OF_MEDIA:
*TapeStatus = TAPE_STATUS_END_OF_MEDIA;
break;
case STATUS_BUFFER_OVERFLOW:
*TapeStatus = TAPE_STATUS_BUFFER_OVERFLOW;
break;
case STATUS_NO_DATA_DETECTED:
*TapeStatus = TAPE_STATUS_NO_DATA_DETECTED;
break;
case STATUS_EOM_OVERFLOW:
*TapeStatus = TAPE_STATUS_EOM_OVERFLOW;
break;
case STATUS_NO_MEDIA:
case STATUS_NO_MEDIA_IN_DEVICE:
*TapeStatus = TAPE_STATUS_NO_MEDIA;
break;
case STATUS_IO_DEVICE_ERROR:
case STATUS_NONEXISTENT_SECTOR:
*TapeStatus = TAPE_STATUS_IO_DEVICE_ERROR;
break;
case STATUS_UNRECOGNIZED_MEDIA:
*TapeStatus = TAPE_STATUS_UNRECOGNIZED_MEDIA;
break;
case STATUS_DEVICE_NOT_READY:
*TapeStatus = TAPE_STATUS_DEVICE_NOT_READY;
break;
case STATUS_MEDIA_WRITE_PROTECTED:
*TapeStatus = TAPE_STATUS_MEDIA_WRITE_PROTECTED;
break;
case STATUS_DEVICE_DATA_ERROR:
*TapeStatus = TAPE_STATUS_DEVICE_DATA_ERROR;
break;
case STATUS_NO_SUCH_DEVICE:
*TapeStatus = TAPE_STATUS_NO_SUCH_DEVICE;
break;
case STATUS_INVALID_BLOCK_LENGTH:
*TapeStatus = TAPE_STATUS_INVALID_BLOCK_LENGTH;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -