📄 tape.c
字号:
DriverObject - Tape class driver object.
Pdo - the physical device object we are being added to
Return Value:
status
--*/
{
PTAPE_INIT_DATA_EX tapeInitData;
NTSTATUS status;
PULONG tapeCount;
BOOLEAN persistence = FALSE;
BOOLEAN legacyNameFormat = !persistence;
PAGED_CODE();
//
// Get the saved-off tape init data.
//
tapeInitData = IoGetDriverObjectExtension(DriverObject, TapeClassInitialize);
ASSERT(tapeInitData);
//
// Get the address of the count of the number of tape devices already initialized.
//
tapeCount = &IoGetConfigurationInformation()->TapeCount;
//
// If this is the first device, we will read the Persistence value off
// of the Control key (user's choice) and update the private copy of
// under Services key which will be value that will actually be used.
// This way, if a user makes a change to the value of Persistence after
// some devices have showed up, we won't get into the situation where
// the device before the change use the old value of Persistence and
// the new devices that show up after the change use the new value.
//
// Using the private copy, all devices will use the same value and the
// change made to Persistence (for the key under Control branch) will
// take effect only on next reboot.
//
if (*tapeCount == 0) {
//
// Query User's preference for persistence
//
if (!NT_SUCCESS(TapeSymbolicNamePersistencePreference(DriverObject,
TAPE_REGISTRY_CONTROL_KEY,
TAPE_PERSISTENCE_QUERY,
TAPE_PERSISTENCE_KEYVALUE,
&persistence))) {
ASSERT(FALSE);
}
//
// Set persistence for this entire up-time until next reboot.
// If we failed to read the user's preference, assume non-persistent
// symbolic name.
//
if (!NT_SUCCESS(TapeSymbolicNamePersistencePreference(DriverObject,
TAPE_REGISTRY_SERVICES_KEY,
TAPE_PERSISTENCE_SET,
TAPE_PERSISTENCE_PRIVATE,
&persistence))) {
ASSERT(FALSE);
}
} else {
//
// Since this isn't the first device, just read the value of Persistence
// from the Services branch.
//
if (!NT_SUCCESS(TapeSymbolicNamePersistencePreference(DriverObject,
TAPE_REGISTRY_SERVICES_KEY,
TAPE_PERSISTENCE_QUERY,
TAPE_PERSISTENCE_PRIVATE,
&persistence))) {
ASSERT(FALSE);
}
}
legacyNameFormat = !persistence;
status = CreateTapeDeviceObject(DriverObject,
PhysicalDeviceObject,
tapeInitData,
legacyNameFormat);
if (NT_SUCCESS(status)) {
(*tapeCount)++;
}
return status;
}
NTSTATUS
CreateTapeDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PTAPE_INIT_DATA_EX TapeInitData,
IN BOOLEAN LegacyNameFormat
)
/*++
Routine Description:
This routine creates an object for the device.
If legacy name format is going to be used, then we will create \Device\TapeN for an N that
doesn't cause an object name clash and symbolic names \DosDevices\TapeN and \Device\TapeDriveN
will be later created. This implicitly means that the symbolic names will not persist.
However, if legacy name format is not reguired, we will create \Device\TapeDriveN and later create
symbolic names \DosDevices\TapeM and \Device\TapeM (where M may or may not be the same as N).
Arguments:
DriverObject - Pointer to driver object created by system.
PhysicalDeviceObject - DeviceObject of the attached to device.
TapeInitData - Supplies the tape initialization data.
LegacyNameFormat - decides device name format as old (legacy) format \Device\TapeN or new format \Device\TapeDriveN
Return Value:
NTSTATUS
--*/
{
UCHAR deviceNameBuffer[TAPE_BUFFER_MAXCOUNT] = {0};
NTSTATUS status;
PDEVICE_OBJECT deviceObject;
PTAPE_INIT_DATA_EX tapeInitData;
PDEVICE_OBJECT lowerDevice;
PTAPE_DATA tapeData;
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
ULONG tapeCount;
PAGED_CODE();
DebugPrint((3,"CreateDeviceObject: Enter routine\n"));
lowerDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);
//
// Claim the device. Note that any errors after this
// will goto the generic handler, where the device will
// be released.
//
status = ClassClaimDevice(lowerDevice, FALSE);
if (!NT_SUCCESS(status)) {
//
// Someone already had this device - we're in trouble
//
ObDereferenceObject(lowerDevice);
return status;
}
//
// Create device object for this device.
//
tapeCount = 0;
do {
strcpy(deviceNameBuffer, TAPE_DEVICE_PREFIX_A);
sprintf(deviceNameBuffer + strlen(deviceNameBuffer),
(LegacyNameFormat ? TAPE_DEVICE_NAME_PREFIX_LEGACY_A : TAPE_DEVICE_NAME_PREFIX_A),
tapeCount);
status = ClassCreateDeviceObject(DriverObject,
deviceNameBuffer,
PhysicalDeviceObject,
TRUE,
&deviceObject);
tapeCount++;
} while (status == STATUS_OBJECT_NAME_COLLISION && tapeCount < MAXLONG);
if (!NT_SUCCESS(status)) {
DebugPrint((1,"CreateTapeDeviceObjects: Can not create device %s\n",
deviceNameBuffer));
goto CreateTapeDeviceObjectExit;
}
//
// Indicate that IRPs should include MDLs.
//
deviceObject->Flags |= DO_DIRECT_IO;
fdoExtension = deviceObject->DeviceExtension;
//
// Back pointer to device object.
//
fdoExtension->CommonExtension.DeviceObject = deviceObject;
//
// This is the physical device.
//
fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension;
//
// Initialize lock count to zero. The lock count is used to
// disable the ejection mechanism when media is mounted.
//
fdoExtension->LockCount = 0;
//
// Put in a bogus value for now. It will be updated on StartDevice once we
// create a symbolic link successfully.
//
fdoExtension->DeviceNumber = MAXLONG;
//
// Set the alignment requirements for the device based on the
// host adapter requirements
//
if (lowerDevice->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = lowerDevice->AlignmentRequirement;
}
//
// Save the device descriptors
//
fdoExtension->AdapterDescriptor = NULL;
fdoExtension->DeviceDescriptor = NULL;
//
// Attach to the PDO
//
fdoExtension->LowerPdo = PhysicalDeviceObject;
fdoExtension->CommonExtension.LowerDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
if (fdoExtension->CommonExtension.LowerDeviceObject == NULL) {
//
// The attach failed. Cleanup and return.
//
status = STATUS_UNSUCCESSFUL;
goto CreateTapeDeviceObjectExit;
}
//
// Save the tape initialization data.
//
RtlCopyMemory(fdoExtension->CommonExtension.DriverData, TapeInitData,sizeof(TAPE_INIT_DATA_EX));
//
// Initialize the splitrequest spinlock.
//
tapeData = (PTAPE_DATA)fdoExtension->CommonExtension.DriverData;
//
// Save system tape number
//
tapeData->PnpNameDeviceNumber = tapeCount - 1;
KeInitializeSpinLock(&tapeData->SplitRequestSpinLock);
//
// The device is initialized properly - mark it as such.
//
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
ObDereferenceObject(lowerDevice);
return(STATUS_SUCCESS);
CreateTapeDeviceObjectExit:
//
// Release the device since an error occured.
//
// ClassClaimDevice(PortDeviceObject,
// LunInfo,
// TRUE,
// NULL);
ObDereferenceObject(lowerDevice);
if (deviceObject != NULL) {
IoDeleteDevice(deviceObject);
}
return status;
} // end CreateTapeDeviceObject()
NTSTATUS
TapeStartDevice(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine is called after InitDevice, and creates the symbolic link,
and sets up information in the registry.
The routine could be called multiple times, in the event of a StopDevice.
Arguments:
Fdo - a pointer to the functional device object for this device
Return Value:
status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PTAPE_DATA tapeData;
PTAPE_INIT_DATA_EX tapeInitData;
PINQUIRYDATA inquiryData;
ULONG inquiryLength;
SCSI_REQUEST_BLOCK srb;
PCDB cdb;
NTSTATUS status;
PVOID minitapeExtension;
PMODE_CAP_PAGE capPage = NULL ;
PMODE_CAPABILITIES_PAGE capabilitiesPage;
ULONG pageLength;
PAGED_CODE();
//
// Build and send request to get inquiry data.
//
inquiryData = ExAllocatePool(NonPagedPoolCacheAligned, MAXIMUM_TAPE_INQUIRY_DATA);
if (!inquiryData) {
//
// The buffer cannot be allocated.
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Get the tape init data again.
//
tapeData = (PTAPE_DATA)(fdoExtension->CommonExtension.DriverData);
tapeInitData = &tapeData->TapeInitData;
RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
//
// Set timeout value.
//
srb.TimeOutValue = 2;
srb.CdbLength = 6;
cdb = (PCDB)srb.Cdb;
//
// Set CDB operation code.
//
cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
//
// Set allocation length to inquiry data buffer size.
//
cdb->CDB6INQUIRY.AllocationLength = MAXIMUM_TAPE_INQUIRY_DATA;
status = ClassSendSrbSynchronous(Fdo,
&srb,
inquiryData,
MAXIMUM_TAPE_INQUIRY_DATA,
FALSE);
if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_SUCCESS ||
SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
srb.SrbStatus = SRB_STATUS_SUCCESS;
}
if (srb.SrbStatus == SRB_STATUS_SUCCESS) {
inquiryLength = inquiryData->AdditionalLength + FIELD_OFFSET(INQUIRYDATA, Reserved);
if (inquiryLength > srb.DataTransferLength) {
inquiryLength = srb.DataTransferLength;
}
//
// Verify that we really want this device.
//
if (tapeInitData->QueryModeCapabilitiesPage ) {
capPage = ExAllocatePool(NonPagedPoolCacheAligned,
sizeof(MODE_CAP_PAGE));
}
if (capPage) {
pageLength = ClassModeSense(Fdo,
(PCHAR) capPage,
sizeof(MODE_CAP_PAGE),
MODE_PAGE_CAPABILITIES);
if (pageLength == 0) {
pageLength = ClassModeSense(Fdo,
(PCHAR) capPage,
sizeof(MODE_CAP_PAGE),
MODE_PAGE_CAPABILITIES);
}
if (pageLength < (sizeof(MODE_CAP_PAGE) - 1)) {
ExFreePool(capPage);
capPage = NULL;
}
}
if (capPage) {
capabilitiesPage = &(capPage->CapabilitiesPage);
} else {
capabilitiesPage = NULL;
}
//
// Initialize the minitape extension.
//
if (tapeInitData->ExtensionInit) {
minitapeExtension = tapeData + 1;
tapeInitData->ExtensionInit(minitapeExtension,
inquiryData,
capabilitiesPage);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -