⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tape.c

📁 This directory builds the Tape class driver for Microsoft&reg Windows&reg Server 2003. The class dri
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -