📄 pnp.c
字号:
}
#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 + -