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

📄 pnp.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 3 页
字号:

        RtlInitUnicodeString(&interfaceName, NULL);

        status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
                                           (LPGUID) &DiskClassGuid,
                                           NULL,
                                           &interfaceName);

        if(NT_SUCCESS(status)) {

            diskData->DiskInterfaceString = interfaceName;
            status = IoSetDeviceInterfaceState(&interfaceName, TRUE);

        } else {
            interfaceName.Buffer = NULL;
        }

        if(!NT_SUCCESS(status)) {

            DebugPrint((1, "DiskInitFdo: Unable to register or set disk DCA "
                           "for fdo %p [%lx]\n", Fdo, status));

            RtlFreeUnicodeString(&interfaceName);
            RtlInitUnicodeString(&(diskData->DiskInterfaceString), NULL);
        }
    }

    DiskCreateSymbolicLinks(Fdo);

    //
    // Determine the type of disk and enable failure preiction in the hardware
    // and enable failure prediction polling.
    //

    if (*InitSafeBootMode == 0)
    {
        DiskDetectFailurePrediction(fdoExtension,
                                  &diskData->FailurePredictionCapability);

        if (diskData->FailurePredictionCapability != FailurePredictionNone)
        {
            //
            // Cool, we've got some sort of failure prediction, enable it
            // at the hardware and then enable polling for it
            //

            //
            // By default we allow performance to be degradeded if failure
            // prediction is enabled.
            //
            // TODO: Make a registry entry ?
            //

            diskData->AllowFPPerfHit = TRUE;

            //
            // Enable polling only after Atapi and SBP2 add support for the new
            // SRB flag that indicates that the request should not reset the
            // drive spin down idle timer.
            //

            status = DiskEnableDisableFailurePredictPolling(fdoExtension,
                                          TRUE,
                                          DISK_DEFAULT_FAILURE_POLLING_PERIOD);

            DebugPrint((3, "DiskInitFdo: Failure Prediction Poll enabled as "
                           "%d for device %p\n",
                     diskData->FailurePredictionCapability,
                     Fdo));
        }
    } else {

        //
        // In safe boot mode we do not enable failure prediction, as perhaps
        // it is the reason why normal boot does not work
        //

        diskData->FailurePredictionCapability = FailurePredictionNone;

    }

    //
    // Initialize the verify mutex
    //

    KeInitializeMutex(&diskData->VerifyMutex, MAX_SECTORS_PER_VERIFY);

    return(STATUS_SUCCESS);

} // end DiskInitFdo()


NTSTATUS
DiskInitPdo(
    IN PDEVICE_OBJECT Pdo
    )

/*++

Routine Description:

    This routine will create the well known names for a PDO and register
    it's device interfaces.

--*/

{
    PCOMMON_DEVICE_EXTENSION pdoExtension = Pdo->DeviceExtension;
    PDISK_DATA diskData = pdoExtension->DriverData;

    UNICODE_STRING interfaceName;

    NTSTATUS status;

    PAGED_CODE();

    DiskCreateSymbolicLinks(Pdo);

    //
    // Register interfaces for this device
    //

    RtlInitUnicodeString(&interfaceName, NULL);

    status = IoRegisterDeviceInterface(Pdo,
                                       (LPGUID) &PartitionClassGuid,
                                       NULL,
                                       &interfaceName);

    if(NT_SUCCESS(status)) {

        diskData->PartitionInterfaceString = interfaceName;
        status = IoSetDeviceInterfaceState(&interfaceName, TRUE);

    } else {
        interfaceName.Buffer = NULL;
    }

    if(!NT_SUCCESS(status)) {
        DebugPrint((1, "DiskInitPdo: Unable to register partition DCA for "
                    "pdo %p [%lx]\n", Pdo, status));

        RtlFreeUnicodeString(&interfaceName);
        RtlInitUnicodeString(&(diskData->PartitionInterfaceString), NULL);
    }

    return STATUS_SUCCESS;
}


NTSTATUS
DiskStartPdo(
    IN PDEVICE_OBJECT Pdo
    )

/*++

Routine Description:

    This routine will create the well known names for a PDO and register
    it's device interfaces.

--*/

{
    PAGED_CODE();

    return STATUS_SUCCESS;
}

NTSTATUS
DiskStopDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR Type
    )

{
    PFUNCTIONAL_DEVICE_EXTENSION fdo = DeviceObject->DeviceExtension;

    if(fdo->CommonExtension.IsFdo) {
        DiskAcquirePartitioningLock(fdo);
        DiskInvalidatePartitionTable(fdo, TRUE);
        DiskReleasePartitioningLock(fdo);
    }

    return STATUS_SUCCESS;
}


NTSTATUS
DiskQueryId(
    IN PDEVICE_OBJECT Pdo,
    IN BUS_QUERY_ID_TYPE IdType,
    IN PUNICODE_STRING UnicodeIdString
    )

/*++

Routine Description:

    This routine generates the PNP id's for the disk's "children".  If the
    specified ID isn't one that the routine can generate it must return
    STATUS_NOT_IMPLEMENTED so classpnp will know not to do anything with the
    PNP request's status.

    This routine allocates the buffer for the UnicodeIdString.  It is the
    caller's responsibility to free the buffer when it's done.

Arguments:

    Pdo - a pointer to the PDO we are to generate an ID for

    IdType - the type of ID to be generated

    UnicodeIdString - a string to put the results into.

Return Value:

    STATUS_SUCCCESS if successful

    STATUS_NOT_IMPLEMENTED if the IdType is not one supported by this routine

    error status otherwise.

--*/

{
    ANSI_STRING ansiIdString;

    NTSTATUS status;

    PAGED_CODE();
    ASSERT_PDO(Pdo);

    if(IdType == BusQueryDeviceID) {

        if((Pdo->Characteristics & FILE_REMOVABLE_MEDIA) == 0) {
            RtlInitAnsiString(&ansiIdString, "STORAGE\\Partition");
            return RtlAnsiStringToUnicodeString(UnicodeIdString, &ansiIdString, TRUE);
        }

        RtlInitAnsiString(&ansiIdString,
                          "STORAGE\\RemovableMedia");

        return RtlAnsiStringToUnicodeString(UnicodeIdString, &ansiIdString, TRUE);
    }

    if(IdType == BusQueryInstanceID) {

        PPHYSICAL_DEVICE_EXTENSION pdoExtension = Pdo->DeviceExtension;
        PCOMMON_DEVICE_EXTENSION commonExtension = Pdo->DeviceExtension;
        PDISK_DATA diskData = commonExtension->PartitionZeroExtension->CommonExtension.DriverData;

        UCHAR string[64];

        if((Pdo->Characteristics & FILE_REMOVABLE_MEDIA) == 0) {

            if (diskData->PartitionStyle == PARTITION_STYLE_MBR) {
                sprintf(string, "S%08lx_O%I64lx_L%I64lx",
                        diskData->Mbr.Signature,
                        commonExtension->StartingOffset,
                        commonExtension->PartitionLength);
            } else {
                sprintf(string,
                        "S%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02xS_O%I64lx_L%I64lx",
                        diskData->Efi.DiskId.Data1,
                        diskData->Efi.DiskId.Data2,
                        diskData->Efi.DiskId.Data3,
                        diskData->Efi.DiskId.Data4[0],
                        diskData->Efi.DiskId.Data4[1],
                        diskData->Efi.DiskId.Data4[2],
                        diskData->Efi.DiskId.Data4[3],
                        diskData->Efi.DiskId.Data4[4],
                        diskData->Efi.DiskId.Data4[5],
                        diskData->Efi.DiskId.Data4[6],
                        diskData->Efi.DiskId.Data4[7],
                        commonExtension->StartingOffset,
                        commonExtension->PartitionLength);
            }
        } else {
            sprintf(string, "RM");
        }

        RtlInitAnsiString(&ansiIdString, string);

        return RtlAnsiStringToUnicodeString(UnicodeIdString, &ansiIdString, TRUE);
    }

    if((IdType == BusQueryHardwareIDs) || (IdType == BusQueryCompatibleIDs)) {

        RtlInitAnsiString(&ansiIdString, "STORAGE\\Volume");

        UnicodeIdString->MaximumLength = (USHORT) RtlAnsiStringToUnicodeSize(&ansiIdString) + sizeof(UNICODE_NULL);

        UnicodeIdString->Buffer = ExAllocatePoolWithTag(PagedPool,
                                                        UnicodeIdString->MaximumLength,
                                                        DISK_TAG_PNP_ID);

        if(UnicodeIdString->Buffer == NULL) {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlZeroMemory(UnicodeIdString->Buffer, UnicodeIdString->MaximumLength);

        return RtlAnsiStringToUnicodeString(UnicodeIdString,
                                            &ansiIdString,
                                            FALSE);
    }

    return STATUS_NOT_IMPLEMENTED;
}


NTSTATUS
DiskGenerateDeviceName(
    IN BOOLEAN IsFdo,
    IN ULONG DeviceNumber,
    IN OPTIONAL ULONG PartitionNumber,
    IN OPTIONAL PLARGE_INTEGER StartingOffset,
    IN OPTIONAL PLARGE_INTEGER PartitionLength,
    OUT PUCHAR *RawName
    )

/*++

Routine Description:

    This routine will allocate a unicode string buffer and then fill it in
    with a generated name for the specified device object.

    It is the responsibility of the user to allocate a UNICODE_STRING structure
    to pass in and to free UnicodeName->Buffer when done with it.

Arguments:

    DeviceObject - a pointer to the device object

    UnicodeName - a unicode string to put the name buffer into

Return Value:

    status

--*/

//#define PDO_NAME_FORMAT "\\Device\\Harddisk%d\\DP(%d)%d"
#define PDO_NAME_FORMAT "\\Device\\Harddisk%d\\DP(%d)%#I64x-%#I64x+%lx"
#define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d"

//#define PDO_NAME_FORMAT (PDO_BASE_NAME "+%#I64x+%#I64x+%#lx")

{
    UCHAR rawName[64];
    static ULONG diskDeviceSequenceNumber = 0;

    PAGED_CODE();

    if(!IsFdo) {

        ASSERT(ARGUMENT_PRESENT((PVOID)(ULONG_PTR) PartitionNumber));
        ASSERT(ARGUMENT_PRESENT(PartitionLength));
        ASSERT(ARGUMENT_PRESENT(StartingOffset));

        sprintf(rawName, PDO_NAME_FORMAT, DeviceNumber, PartitionNumber,
                                          StartingOffset->QuadPart,
                                          PartitionLength->QuadPart,
                                          diskDeviceSequenceNumber++);
    } else {

        ASSERT(!ARGUMENT_PRESENT((PVOID)(ULONG_PTR) PartitionNumber));
        ASSERT(!ARGUMENT_PRESENT(PartitionLength));
        ASSERT(!ARGUMENT_PRESENT(StartingOffset));

        sprintf(rawName, FDO_NAME_FORMAT, DeviceNumber,
                                          diskDeviceSequenceNumber++);

    }

    *RawName = ExAllocatePoolWithTag(PagedPool,
                                     strlen(rawName) + 1,
                                     DISK_TAG_NAME);

    if(*RawName == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    strcpy(*RawName, rawName);

    DebugPrint((2, "DiskGenerateDeviceName: generated \"%s\"\n", rawName));

    return STATUS_SUCCESS;
}


VOID
DiskCreateSymbolicLinks(
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine will generate a symbolic link for the specified device object
    using the well known form \\Device\HarddiskX\PartitionY, where X and Y are
    filled in using the partition information in the device object's extension.

    This routine will not try to delete any previous symbolic link for the
    same generated name - the caller must make sure the symbolic link has
    been broken before calling this routine.

Arguments:

    DeviceObject - the device object to make a well known name for

Return Value:

    STATUS

--*/

{
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;

    PDISK_DATA diskData = commonExtension->DriverData;

    WCHAR wideSourceName[64];
    UNICODE_STRING unicodeSourceName;

    NTSTATUS status;

    PAGED_CODE();

    //
    // Build the destination for the link first using the device name
    // stored in the device object
    //

    ASSERT(commonExtension->DeviceName.Buffer);

    if(!diskData->LinkStatus.WellKnownNameCreated) {
        //
        // Put together the source name using the partition and device number
        // in the device extension and disk data segment
        //

        swprintf(wideSourceName, L"\\Device\\Harddisk%d\\Partition%d",
                 commonExtension->PartitionZeroExtension->DeviceNumber,
                 (commonExtension->IsFdo ?
                    0 :
                    commonExtension->PartitionNumber));

        RtlInitUnicodeString(&unicodeSourceName, wideSourceName);

        DebugPrint((1, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
                   &unicodeSourceName,
                   &commonExtension->DeviceName));

        status = IoCreateSymbolicLink(&unicodeSourceName,
                                      &commonExtension->DeviceName);

    #if DBG

        if((status == STATUS_OBJECT_NAME_EXISTS) ||
           (status == STATUS_OBJECT_NAME_COLLISION)) {

            DebugPrint((1, "DiskCreateSymbolicLink: name %wZ already exists\n",
                        &unicodeSourceName));

⌨️ 快捷键说明

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