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

📄 tape.c

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