📄 tape.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1994 - 1999
Module Name:
scsitape.c
Abstract:
This is the tape class driver.
Environment:
kernel mode only
Revision History:
--*/
#include "tape.h"
//
// Define the maximum inquiry data length.
//
#define MAXIMUM_TAPE_INQUIRY_DATA 252
#define UNDEFINED_BLOCK_SIZE ((ULONG) -1)
#define TAPE_SRB_LIST_SIZE 4
#define TAPE_BUFFER_MAXCOUNT 64
#define TAPE_REGISTRY_CONTROL_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Tape"
#define TAPE_REGISTRY_SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tape"
#define TAPE_PERSISTENCE_KEYVALUE L"Persistence"
#define TAPE_PERSISTENCE_PRIVATE L"PersistencePrivateCopy"
#define TAPE_DEVICE_UIDTYPE L"UIDType"
#define TAPE_DEVICE_UNIQUEID L"UniqueId"
#define TAPE_DOS_DEVICES_PREFIX_W L"\\DosDevices"
#define TAPE_DOS_DEVICES_PREFIX_A "\\DosDevices"
#define TAPE_DEVICE_PREFIX_W L"\\Device"
#define TAPE_DEVICE_PREFIX_A "\\Device"
#define TAPE_DEVICE_NAME_PREFIX_W L"\\TapeDrive%u"
#define TAPE_DEVICE_NAME_PREFIX_A "\\TapeDrive%u"
#define TAPE_DEVICE_NAME_FORMAT_W L"TapeDrive%u"
#define TAPE_DEVICE_NAME_FORMAT_A "TapeDrive%u"
#define TAPE_DEVICE_NAME_PREFIX_LEGACY_W L"\\Tape%u"
#define TAPE_DEVICE_NAME_PREFIX_LEGACY_A "\\Tape%u"
#define TAPE_NAME_PREFIX_W L"\\Tape%u"
#define TAPE_NAME_PREFIX_A "\\Tape%u"
#define TAPE_NAME_FORMAT_W L"Tape%u"
#define TAPE_NAME_FORMAT_A "Tape%u"
typedef enum _TAPE_UID_TYPE {
TAPE_UID_CUSTOM = 1
} TAPE_UID_TYPE, *PTAPE_UID_TYPE;
typedef enum _TAPE_PERSISTENCE_OPERATION {
TAPE_PERSISTENCE_QUERY = 1,
TAPE_PERSISTENCE_SET
} TAPE_PERSISTENCE_OPERATION, *PTAPE_PERSISTENCE_OPERATION;
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
VOID
TapeUnload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
TapeAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo
);
NTSTATUS
TapeStartDevice(
IN PDEVICE_OBJECT Fdo
);
NTSTATUS
CreateTapeDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PTAPE_INIT_DATA_EX TapeInitData,
IN BOOLEAN LegacyNameFormat
);
VOID
TapeError(
IN PDEVICE_OBJECT DeviceObject,
IN PSCSI_REQUEST_BLOCK Srb,
IN OUT PNTSTATUS Status,
IN OUT PBOOLEAN Retry
);
NTSTATUS
TapeReadWriteVerification(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
TapeReadWrite(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp
);
VOID
SplitTapeRequest(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp,
IN ULONG MaximumBytes
);
NTSTATUS
TapeIoCompleteAssociated(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
TapeDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
TapeInitDevice(
IN PDEVICE_OBJECT Fdo
);
NTSTATUS
TapeRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Type
);
NTSTATUS
TapeStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Type
);
NTSTATUS
TapeSymbolicNamePersistencePreference(
IN PDRIVER_OBJECT DriverObject,
IN PWCHAR KeyName,
IN TAPE_PERSISTENCE_OPERATION Operation,
IN PWCHAR ValueName,
IN OUT PBOOLEAN PersistencePreference
);
NTSTATUS
TapeCreateSymbolicName(
IN PDEVICE_OBJECT Fdo,
IN BOOLEAN PersistencePreference
);
NTSTATUS
TapeCreateUniqueId(
IN PDEVICE_OBJECT Fdo,
IN TAPE_UID_TYPE UIDType,
OUT PUCHAR *UniqueId,
OUT PULONG UniqueIdLen
);
BOOLEAN
TapeCompareUniqueId(
IN PUCHAR UniqueId1,
IN ULONG UniqueId1Len,
IN PUCHAR UniqueId2,
IN ULONG UniqueId2Len,
IN TAPE_UID_TYPE Type
);
NTSTATUS
TapeGetSubKeyByIndex(
IN HANDLE RootKey,
IN ULONG SubKeyIndex,
OUT PHANDLE SubKey,
OUT PWCHAR ReturnString
);
NTSTATUS
TapeGetValuePartialInfo(
IN HANDLE Key,
IN PUNICODE_STRING ValueName,
OUT PKEY_VALUE_PARTIAL_INFORMATION *KeyValueInfo,
OUT PULONG KeyValueInfoSize
);
NTSTATUS
TapeCreateNewDeviceSubKey(
IN HANDLE RootKey,
IN OUT PULONG FirstNumeralToUse,
OUT PHANDLE NewSubKey,
OUT PWCHAR NewSubKeyName
);
NTSTATUS
TapeCreateNonPersistentSymbolicName(
IN HANDLE RootKey,
IN OUT PULONG FirstNumeralToUse,
OUT PWCHAR NonPersistentSymbolicName
);
NTSTATUS
TapeAssignSymbolicLink(
IN ULONG DeviceNumber,
IN PUNICODE_STRING RegDeviceName,
IN BOOLEAN LegacyNameFormat,
IN PWCHAR SymbolicNamePrefix,
OUT PULONG SymbolicNameNumeral
);
NTSTATUS
TapeDeassignSymbolicLink(
IN PWCHAR SymbolicNamePrefix,
IN ULONG SymbolicNameNumeral,
IN BOOLEAN LegacyNameFormat
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, TapeUnload)
#pragma alloc_text(PAGE, TapeClassInitialize)
#pragma alloc_text(PAGE, TapeAddDevice)
#pragma alloc_text(PAGE, CreateTapeDeviceObject)
#pragma alloc_text(PAGE, TapeStartDevice)
#pragma alloc_text(PAGE, TapeInitDevice)
#pragma alloc_text(PAGE, TapeRemoveDevice)
#pragma alloc_text(PAGE, TapeStopDevice)
#pragma alloc_text(PAGE, TapeDeviceControl)
#pragma alloc_text(PAGE, TapeReadWriteVerification)
#pragma alloc_text(PAGE, TapeReadWrite)
#pragma alloc_text(PAGE, SplitTapeRequest)
#pragma alloc_text(PAGE, ScsiTapeFreeSrbBuffer)
#pragma alloc_text(PAGE, TapeClassZeroMemory)
#pragma alloc_text(PAGE, TapeClassCompareMemory)
#pragma alloc_text(PAGE, TapeClassLiDiv)
#pragma alloc_text(PAGE, GetTimeoutDeltaFromRegistry)
#pragma alloc_text(PAGE, TapeSymbolicNamePersistencePreference)
#pragma alloc_text(PAGE, TapeCreateSymbolicName)
#pragma alloc_text(PAGE, TapeCreateUniqueId)
#pragma alloc_text(PAGE, TapeCompareUniqueId)
#pragma alloc_text(PAGE, TapeGetSubKeyByIndex)
#pragma alloc_text(PAGE, TapeGetValuePartialInfo)
#pragma alloc_text(PAGE, TapeCreateNewDeviceSubKey)
#pragma alloc_text(PAGE, TapeCreateNonPersistentSymbolicName)
#pragma alloc_text(PAGE, TapeAssignSymbolicLink)
#pragma alloc_text(PAGE, TapeDeassignSymbolicLink)
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This is the entry point for this EXPORT DRIVER. It does nothing.
--*/
{
return STATUS_SUCCESS;
}
ULONG
TapeClassInitialize(
IN PVOID Argument1,
IN PVOID Argument2,
IN PTAPE_INIT_DATA_EX TapeInitData
)
/*++
Routine Description:
This routine is called by a tape mini-class driver during its
DriverEntry routine to initialize the driver.
Arguments:
Argument1 - Supplies the first argument to DriverEntry.
Argument2 - Supplies the second argument to DriverEntry.
TapeInitData - Supplies the tape initialization data.
Return Value:
A valid return code for a DriverEntry routine.
--*/
{
PDRIVER_OBJECT driverObject = Argument1;
PUNICODE_STRING registryPath = Argument2;
PTAPE_INIT_DATA_EX driverExtension;
NTSTATUS status;
CLASS_INIT_DATA initializationData;
TAPE_INIT_DATA_EX tmpInitData;
PAGED_CODE();
DebugPrint((1,"\n\nSCSI Tape Class Driver\n"));
//
// Zero InitData
//
RtlZeroMemory (&tmpInitData, sizeof(TAPE_INIT_DATA_EX));
//
// Save the tape init data passed in from the miniclass driver. When AddDevice gets called, it will be used.
// First a check for 4.0 vs. later miniclass drivers.
//
if (TapeInitData->InitDataSize != sizeof(TAPE_INIT_DATA_EX)) {
//
// Earlier rev. Copy the bits around so that the EX structure is correct.
//
RtlCopyMemory(&tmpInitData.VerifyInquiry, TapeInitData, sizeof(TAPE_INIT_DATA));
//
// Mark it as an earlier rev.
//
tmpInitData.InitDataSize = sizeof(TAPE_INIT_DATA);
} else {
RtlCopyMemory(&tmpInitData, TapeInitData, sizeof(TAPE_INIT_DATA_EX));
}
//
// Get the driverExtension
status = IoAllocateDriverObjectExtension(driverObject,
TapeClassInitialize,
sizeof(TAPE_INIT_DATA_EX),
&driverExtension);
if (!NT_SUCCESS(status)) {
if (status == STATUS_OBJECT_NAME_COLLISION) {
//
// An extension already exists for this key. Get a pointer to it
//
driverExtension = IoGetDriverObjectExtension(driverObject,
TapeClassInitialize);
if (driverExtension == NULL) {
DebugPrint((1, "TapeClassInitialize : driverExtension NULL\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
} else {
//
// As this failed, the tape init data won't be able to be stored.
//
DebugPrint((1, "TapeClassInitialize: Error %x allocating driver extension.\n",
status));
return status;
}
}
RtlCopyMemory(driverExtension, &tmpInitData, sizeof(TAPE_INIT_DATA_EX));
RtlZeroMemory (&initializationData, sizeof(CLASS_INIT_DATA));
//
// Set sizes
//
initializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
initializationData.FdoData.DeviceExtensionSize = sizeof(FUNCTIONAL_DEVICE_EXTENSION) +
sizeof(TAPE_DATA) + tmpInitData.MinitapeExtensionSize;
initializationData.FdoData.DeviceType = FILE_DEVICE_TAPE;
initializationData.FdoData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA |
FILE_DEVICE_SECURE_OPEN;
//
// Set entry points
//
initializationData.FdoData.ClassStartDevice = TapeStartDevice;
initializationData.FdoData.ClassStopDevice = TapeStopDevice;
initializationData.FdoData.ClassInitDevice = TapeInitDevice;
initializationData.FdoData.ClassRemoveDevice = TapeRemoveDevice;
initializationData.ClassAddDevice = TapeAddDevice;
initializationData.FdoData.ClassError = TapeError;
initializationData.FdoData.ClassReadWriteVerification = TapeReadWriteVerification;
initializationData.FdoData.ClassDeviceControl = TapeDeviceControl;
initializationData.FdoData.ClassShutdownFlush = NULL;
initializationData.FdoData.ClassCreateClose = NULL;
//
// Routines for WMI support
//
initializationData.FdoData.ClassWmiInfo.GuidCount = 6;
initializationData.FdoData.ClassWmiInfo.GuidRegInfo = TapeWmiGuidList;
initializationData.FdoData.ClassWmiInfo.ClassQueryWmiRegInfo = TapeQueryWmiRegInfo;
initializationData.FdoData.ClassWmiInfo.ClassQueryWmiDataBlock = TapeQueryWmiDataBlock;
initializationData.FdoData.ClassWmiInfo.ClassSetWmiDataBlock = TapeSetWmiDataBlock;
initializationData.FdoData.ClassWmiInfo.ClassSetWmiDataItem = TapeSetWmiDataItem;
initializationData.FdoData.ClassWmiInfo.ClassExecuteWmiMethod = TapeExecuteWmiMethod;
initializationData.FdoData.ClassWmiInfo.ClassWmiFunctionControl = TapeWmiFunctionControl;
initializationData.ClassUnload = TapeUnload;
//
// Call the class init routine last, so can cleanup if it fails
//
status = ClassInitialize( driverObject, registryPath, &initializationData);
if (!NT_SUCCESS(status)) {
DebugPrint((1, "TapeClassInitialize: Error %x from classinit\n", status));
TapeUnload(driverObject);
}
return status;
}
VOID
TapeUnload(
IN PDRIVER_OBJECT DriverObject
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER(DriverObject);
return;
}
NTSTATUS
TapeAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine creates and initializes a new FDO for the corresponding
PDO. It may perform property queries on the FDO but cannot do any
media access operations.
Arguments:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -