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

📄 disk.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
    //
    // Call port driver to get adapter capabilities.
    //

    status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);

    if (!NT_SUCCESS(status)) {
        DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
        return(FALSE);
    }

    //
    // Call port driver to get inquiry information to find disks.
    //

    status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);

    if (!NT_SUCCESS(status)) {
        DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
        return(FALSE);
    }

    //
    // Do a quick scan of the devices on this adapter to determine how many
    // disks are on this adapter.  This is used to determine the number of
    // SRB zone elements to allocate.
    //

    adapterDisk = 0;
    adapterInfo = (PVOID) buffer;

    adapterDisk = ScsiClassFindUnclaimedDevices(InitializationData, adapterInfo);

    //
    // Allocate a zone of SRB for disks on this adapter.
    //

    if (adapterDisk == 0) {

        //
        // No free disks were found.
        //

        return(FALSE);
    }

    //
    // Get the number of disks already initialized.
    //

    configurationInformation = IoGetConfigurationInformation();
    diskCount = &configurationInformation->DiskCount;

    //
    // For each SCSI bus this adapter supports ...
    //

    for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) {

        //
        // Get the SCSI bus scan data for this bus.
        //

        lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);

        //
        // Search list for unclaimed disk devices.
        //

        while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {

            inquiryData = (PVOID)lunInfo->InquiryData;

            if (((inquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
                (inquiryData->DeviceType == OPTICAL_DEVICE)) &&
                inquiryData->DeviceTypeQualifier == 0 &&
                (!lunInfo->DeviceClaimed)) {

                DebugPrint((1,
                            "FindScsiDevices: Vendor string is %.24s\n",
                            inquiryData->VendorId));

                //
                // Create device objects for disk
                //

                status = CreateDiskDeviceObject(DriverObject,
                                                RegistryPath,
                                                PortDeviceObject,
                                                PortNumber,
                                                diskCount,
                                                portCapabilities,
                                                lunInfo,
                                                InitializationData);

                if (NT_SUCCESS(status)) {

                    //
                    // Increment system disk device count.
                    //

                    (*diskCount)++;
                    foundOne = TRUE;

                }
            }

            //
            // Get next LunInfo.
            //

            if (lunInfo->NextInquiryDataOffset == 0) {
                break;
            }

            lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);

        }
    }

    //
    // Buffer is allocated by ScsiClassGetInquiryData and must be free returning.
    //

    ExFreePool(buffer);

    return(foundOne);

} // end FindScsiDisks()


NTSTATUS
STDCALL
CreateDiskDeviceObject(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath,
    IN PDEVICE_OBJECT PortDeviceObject,
    IN ULONG PortNumber,
    IN PULONG DeviceCount,
    IN PIO_SCSI_CAPABILITIES PortCapabilities,
    IN PSCSI_INQUIRY_DATA LunInfo,
    IN PCLASS_INIT_DATA InitData
    )

/*++

Routine Description:

    This routine creates an object for the physical device and then searches
    the device for partitions and creates an object for each partition.

Arguments:

    DriverObject - Pointer to driver object created by system.

    PortDeviceObject - Miniport device object.

    PortNumber   - port number.  Used in creating disk objects.

    DeviceCount  - Number of previously installed devices.

    PortCapabilities - Capabilities of this SCSI port.

    LunInfo      - LUN specific information.

Return Value:

    NTSTATUS

--*/
{
    CCHAR          ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
    STRING         ntNameString;
    UNICODE_STRING ntUnicodeString;
    ULONG          partitionNumber = 0;
    OBJECT_ATTRIBUTES objectAttributes;
    HANDLE         handle;
    NTSTATUS       status;
    PDEVICE_OBJECT deviceObject = NULL;
    PDEVICE_OBJECT physicalDevice;
    PDISK_GEOMETRY diskGeometry = NULL;
    PDRIVE_LAYOUT_INFORMATION partitionList;
    PDEVICE_EXTENSION deviceExtension = NULL;
    PDEVICE_EXTENSION physicalDeviceExtension;
    PDISK_DATA     diskData;
    ULONG          bytesPerSector;
    UCHAR          sectorShift;
    UCHAR          pathId = LunInfo->PathId;
    UCHAR          targetId = LunInfo->TargetId;
    UCHAR          lun = LunInfo->Lun;
    BOOLEAN        writeCache;
    PVOID          senseData = NULL;
    ULONG          srbFlags;
    ULONG          dmByteSkew = 0;
    PULONG         dmSkew;
    BOOLEAN        dmActive = FALSE;
    ULONG          timeOut = 0;
    ULONG          numberListElements = 0;
    BOOLEAN        srbListInitialized = FALSE;


    PAGED_CODE();

    //
    // Set up an object directory to contain the objects for this
    // device and all its partitions.
    //

    sprintf(ntNameBuffer,
            "\\Device\\Harddisk%lu",
            *DeviceCount);

    RtlInitString(&ntNameString,
                  ntNameBuffer);

    status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
                                          &ntNameString,
                                          TRUE);

    if (!NT_SUCCESS(status)) {
        return(status);
    }

    InitializeObjectAttributes(&objectAttributes,
                               &ntUnicodeString,
                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                               NULL,
                               NULL);

    status = ZwCreateDirectoryObject(&handle,
                                     DIRECTORY_ALL_ACCESS,
                                     &objectAttributes);

    RtlFreeUnicodeString(&ntUnicodeString);

    if (!NT_SUCCESS(status)) {

        DebugPrint((1,
                    "CreateDiskDeviceObjects: Could not create directory %s\n",
                    ntNameBuffer));

        return(status);
    }

    //
    // Claim the device.
    //

    status = ScsiClassClaimDevice(PortDeviceObject,
                                  LunInfo,
                                  FALSE,
                                  &PortDeviceObject);

    if (!NT_SUCCESS(status)) {
        ZwMakeTemporaryObject(handle);
        ZwClose(handle);
        return status;
    }

    //
    // Create a device object for this device. Each physical disk will
    // have at least one device object. The required device object
    // describes the entire device. Its directory path is
    // \Device\HarddiskN\Partition0, where N = device number.
    //

    sprintf(ntNameBuffer,
            "\\Device\\Harddisk%lu\\Partition0",
            *DeviceCount);


    status = ScsiClassCreateDeviceObject(DriverObject,
                                         ntNameBuffer,
                                         NULL,
                                         &deviceObject,
                                         InitData);

    if (!NT_SUCCESS(status)) {

        DebugPrint((1,
                    "CreateDiskDeviceObjects: Can not create device object %s\n",
                    ntNameBuffer));

        goto CreateDiskDeviceObjectsExit;
    }

    //
    // Indicate that IRPs should include MDLs for data transfers.
    //

    deviceObject->Flags |= DO_DIRECT_IO;

    //
    // Check if this is during initialization. If not indicate that
    // system initialization already took place and this disk is ready
    // to be accessed.
    //

    if (!RegistryPath) {
        deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    }

    //
    // Check for removable media support.
    //

    if (((PINQUIRYDATA)LunInfo->InquiryData)->RemovableMedia) {
        deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
    }

    //
    // Set up required stack size in device object.
    //

    deviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;

    deviceExtension = deviceObject->DeviceExtension;

    //
    // Allocate spinlock for split request completion.
    //

    KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);

    //
    // Initialize lock count to zero. The lock count is used to
    // disable the ejection mechanism on devices that support
    // removable media. Only the lock count in the physical
    // device extension is used.
    //

    deviceExtension->LockCount = 0;

    //
    // Save system disk number.
    //

    deviceExtension->DeviceNumber = *DeviceCount;

    //
    // Copy port device object pointer to the device extension.
    //

    deviceExtension->PortDeviceObject = PortDeviceObject;

    //
    // Set the alignment requirements for the device based on the
    // host adapter requirements
    //

    if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
        deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
    }

    //
    // This is the physical device object.
    //

    physicalDevice = deviceObject;
    physicalDeviceExtension = deviceExtension;

    //
    // Save address of port driver capabilities.
    //

    deviceExtension->PortCapabilities = PortCapabilities;

    //
    // Build the lookaside list for srb's for the physical disk. Should only
    // need a couple.
    //

    ScsiClassInitializeSrbLookasideList(deviceExtension,
                                        PARTITION0_LIST_SIZE);

    srbListInitialized = TRUE;

    //
    // Initialize the srb flags.
    //

    if (((PINQUIRYDATA)LunInfo->InquiryData)->CommandQueue &&
        PortCapabilities->TaggedQueuing) {

        deviceExtension->SrbFlags  = SRB_FLAGS_QUEUE_ACTION_ENABLE;

    } else {

        deviceExtension->SrbFlags  = 0;

    }

    //
    // Allow queued requests if this is not removable media.
    //

    if (!(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {

        deviceExtension->SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE;

    }

    //
    // Look for controller that require special flags.
    //

    ScanForSpecial(deviceObject,
                    LunInfo,
                    PortCapabilities);

    srbFlags = deviceExtension->SrbFlags;

    //
    // Allocate buffer for drive geometry.
    //

    diskGeometry = ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));

    if (diskGeometry == NULL) {

        DebugPrint((1,
           "CreateDiskDeviceObjects: Can not allocate disk geometry buffer\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto CreateDiskDeviceObjectsExit;
    }

    deviceExtension->DiskGeometry = diskGeometry;

    //
    // Allocate request sense buffer.
    //

    senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

    if (senseData == NULL) {

        //
        // The buffer can not be allocated.
        //

        DebugPrint((1,
           "CreateDiskDeviceObjects: Can not allocate request sense buffer\n"));

        status = STATUS_INSUFFICIENT_RESOURCES;
        goto CreateDiskDeviceObjectsExit;
    }

    //
    // Set the sense data pointer in the device extension.
    //

    deviceExtension->SenseData = senseData;

    //
    // Physical device object will describe the entire
    // device, starting at byte offset 0.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -