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

📄 pnp.c

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

        if(NT_SUCCESS(status)){
            diskData->LinkStatus.WellKnownNameCreated = TRUE;
        }
    }

    if((!diskData->LinkStatus.PhysicalDriveLinkCreated) &&
       (commonExtension->IsFdo)) {

        //
        // Create a physical drive N link using the device number we saved
        // away during AddDevice.
        //

        swprintf(wideSourceName,
                 L"\\DosDevices\\PhysicalDrive%d",
                 commonExtension->PartitionZeroExtension->DeviceNumber);

        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));
        }
#endif

        if(NT_SUCCESS(status)) {
            diskData->LinkStatus.PhysicalDriveLinkCreated = TRUE;
        }
    } else if(commonExtension->IsFdo == FALSE) {
        diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE;
    }

    return;
}


VOID
DiskDeleteSymbolicLinks(
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine will delete the well known name (symlink) for the specified
    device.  It generates the link name using information stored in the
    device extension

Arguments:

    DeviceObject - the device object we are unlinking

Return Value:

    status

--*/

{
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = commonExtension->DriverData;

    WCHAR wideLinkName[64];
    UNICODE_STRING unicodeLinkName;

    PAGED_CODE();

    if(diskData->LinkStatus.WellKnownNameCreated) {

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

        RtlInitUnicodeString(&unicodeLinkName, wideLinkName);

        IoDeleteSymbolicLink(&unicodeLinkName);

        diskData->LinkStatus.WellKnownNameCreated = FALSE;
    }

    if(diskData->LinkStatus.PhysicalDriveLinkCreated) {

        ASSERT_FDO(DeviceObject);

        swprintf(wideLinkName,
                 L"\\DosDevices\\PhysicalDrive%d",
                 commonExtension->PartitionZeroExtension->DeviceNumber);

        RtlInitUnicodeString(&unicodeLinkName, wideLinkName);

        IoDeleteSymbolicLink(&unicodeLinkName);

        diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE;
    }

    return;
}


NTSTATUS
DiskRemoveDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR Type
    )

/*++

Routine Description:

    This routine will release any resources the device may have allocated for
    this device object and return.

Arguments:

    DeviceObject - the device object being removed

Return Value:

    status

--*/

{
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = commonExtension->DriverData;

    PAGED_CODE();

    //
    // Handle query and cancel
    //

    if((Type == IRP_MN_QUERY_REMOVE_DEVICE) ||
       (Type == IRP_MN_CANCEL_REMOVE_DEVICE))  {
        return STATUS_SUCCESS;
    }

    if(commonExtension->IsFdo) {

        PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
            DeviceObject->DeviceExtension;

        //
        // Purge the cached partition table (if any).
        //

        DiskAcquirePartitioningLock(fdoExtension);
        DiskInvalidatePartitionTable(fdoExtension, TRUE);
        DiskReleasePartitioningLock(fdoExtension);

        //
        // Delete our object directory.
        //

        if(fdoExtension->AdapterDescriptor) {
            ExFreePool(fdoExtension->AdapterDescriptor);
            fdoExtension->AdapterDescriptor = NULL;
        }

        if(fdoExtension->DeviceDescriptor) {
            ExFreePool(fdoExtension->DeviceDescriptor);
            fdoExtension->DeviceDescriptor = NULL;
        }

        if(fdoExtension->SenseData) {
            ExFreePool(fdoExtension->SenseData);
            fdoExtension->SenseData = NULL;
        }

        if(fdoExtension->DeviceDirectory != NULL) {
            ZwMakeTemporaryObject(fdoExtension->DeviceDirectory);
            ZwClose(fdoExtension->DeviceDirectory);
            fdoExtension->DeviceDirectory = NULL;
        }

        if(Type == IRP_MN_REMOVE_DEVICE) {
            IoGetConfigurationInformation()->DiskCount--;
        }

    } else {

        PPHYSICAL_DEVICE_EXTENSION pdoExtension = DeviceObject->DeviceExtension;

    }

    DiskDeleteSymbolicLinks(DeviceObject);

    //
    // Release the mounted device interface if we've set it.
    //

    if(diskData->PartitionInterfaceString.Buffer != NULL) {
        IoSetDeviceInterfaceState(&(diskData->PartitionInterfaceString), FALSE);
        RtlFreeUnicodeString(&(diskData->PartitionInterfaceString));
        RtlInitUnicodeString(&(diskData->PartitionInterfaceString), NULL);
    }
    if(diskData->DiskInterfaceString.Buffer != NULL) {
        IoSetDeviceInterfaceState(&(diskData->DiskInterfaceString), FALSE);
        RtlFreeUnicodeString(&(diskData->DiskInterfaceString));
        RtlInitUnicodeString(&(diskData->DiskInterfaceString), NULL);
    }

    ClassDeleteSrbLookasideList(commonExtension);
    return STATUS_SUCCESS;
}


NTSTATUS
DiskStartFdo(
    IN PDEVICE_OBJECT Fdo
    )

/*++

Routine Description:

    This routine will query the underlying device for any information necessary
    to complete initialization of the device.  This will include physical
    disk geometry, mode sense information and such.

    This routine does not perform partition enumeration - that is left to the
    re-enumeration routine

    If this routine fails it will return an error value.  It does not clean up
    any resources - that is left for the Stop/Remove routine.

Arguments:

    Fdo - a pointer to the functional device object for this device

Return Value:

    status

--*/

{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
    PDISK_DATA diskData = commonExtension->DriverData;
    STORAGE_HOTPLUG_INFO hotplugInfo;
    ULONG writeCacheOverride = DiskWriteCacheDefault;
    DISK_CACHE_INFORMATION cacheInfo;
    NTSTATUS status;

    PAGED_CODE();

    //
    // Get the hotplug information, so we can turn off write cache if needed
    //
    // NOTE: Capabilities info is not good enough to determine hotplugedness
    //       as  we cannot determine device relations  information and other
    //       dependencies. Get the hotplug info instead
    //

    {
        PIRP irp;
        KEVENT event;
        IO_STATUS_BLOCK statusBlock;

        KeInitializeEvent(&event, SynchronizationEvent, FALSE);
        RtlZeroMemory(&hotplugInfo, sizeof(STORAGE_HOTPLUG_INFO));

        irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_HOTPLUG_INFO,
                                            Fdo,
                                            NULL,
                                            0L,
                                            &hotplugInfo,
                                            sizeof(STORAGE_HOTPLUG_INFO),
                                            FALSE,
                                            &event,
                                            &statusBlock);

        if (irp != NULL) {

            // send to self -- classpnp handles this
            status = IoCallDriver(Fdo, irp);
            if (status == STATUS_PENDING) {
                KeWaitForSingleObject(&event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL);
                status = statusBlock.Status;
            }
        }
    }

    //
    // Clear the DEV_WRITE_CACHE flag now  and set
    // it below only if we read that from the disk
    //

    CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);

    if (TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_DISABLE_WRITE_CACHE))
    {
        //
        // This flag overrides the user's  setting, because  faulty firmware
        // may cause the filesystem to refuse to format media on this device
        //
        DebugPrint((1,
                    "DiskStartFdo: Shutting off write cache for %p due to %s\n",
                    Fdo,
                    "Possible Firmware Issue"));

        writeCacheOverride = DiskWriteCacheDisable;
    }
    else
    {
        //
        // Look into the registry to  see if the user
        // has chosen to override the default setting
        //
        ClassGetDeviceParameter(fdoExtension,
                                DiskDeviceParameterSubkey,
                                DiskDeviceUserWriteCacheSetting,
                                &writeCacheOverride);

        if (writeCacheOverride == DiskWriteCacheDefault)
        {
            //
            // The user has not overridden the default settings
            //
            if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
            {
                DebugPrint((1,
                            "DiskStartFdo: Shutting off write cache for %p due to %s\n",
                            Fdo,
                            "Hotplug Device"));

                writeCacheOverride = DiskWriteCacheDisable;
            }
            else if (hotplugInfo.MediaHotplug)
            {
                DebugPrint((1,
                            "DiskStartFdo: Shutting off write cache for %p due to %s\n",
                            Fdo,
                            "Hotplug (unlockable) Media"));

                writeCacheOverride = DiskWriteCacheDisable;
            }
            else
            {
                //
                // We enable write cache if this device has no specific issues
                //
                writeCacheOverride = DiskWriteCacheEnable;
            }
        }
    }

    //
    // Query the disk to see if write cache is enabled
    // and  set the DEV_WRITE_CACHE flag appropriately
    //

    RtlZeroMemory(&cacheInfo, sizeof(DISK_CACHE_INFORMATION));

    status = DiskGetCacheInformation(fdoExtension, &cacheInfo);

    if (NT_SUCCESS(status))
    {
        if (cacheInfo.WriteCacheEnabled == TRUE)
        {
            if (writeCacheOverride == DiskWriteCacheDisable)
            {
                //
                // Write cache is currently enabled on this
                // device, but we would like to turn it off
                //
                cacheInfo.WriteCacheEnabled = FALSE;

                status = DiskSetCacheInformation(fdoExtension, &cacheInfo);
            }
            else
            {
                //
                // The write cache setting either matches
                // our needs or we don't care
                //
                SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
            }
        }
        else
        {
            if (writeCacheOverride == DiskWriteCacheEnable)
            {
                //
                // Write cache is currently disabled on this
                // device, but we  would  like to turn it on
                //
                cacheInfo.WriteCacheEnabled = TRUE;

                status = DiskSetCacheInformation(fdoExtension, &cacheInfo);

                SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
            }
        }
    }

    //
    // In the event that there's a cached partition table flush it now.
    //

    DiskAcquirePartitioningLock(fdoExtension);
    DiskInvalidatePartitionTable(fdoExtension, TRUE);
    DiskReleasePartitioningLock(fdoExtension);

    //
    // Get the SCSI address if it's available for use with SMART ioctls.
    //

    {
        PIRP irp;
        KEVENT event;
        IO_STATUS_BLOCK statusBlock;

        KeInitializeEvent(&event, SynchronizationEvent, FALSE);

        irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS,
                                            commonExtension->LowerDeviceObject,
                                            NULL,
                                            0L,
                                            &(diskData->ScsiAddress),
                                            sizeof(SCSI_ADDRESS),
                                            FALSE,
                                            &event,
                                            &statusBlock);

        if(irp != NULL) {


            status = IoCallDriver(commonExtension->LowerDeviceObject, irp);

            if(status == STATUS_PENDING) {
                KeWaitForSingleObject(&event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL);
                status = statusBlock.Status;
            }
        }
    }

    return STATUS_SUCCESS;

} // end DiskStartFdo()

⌨️ 快捷键说明

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