📄 pnp.c
字号:
status = IoCreateSymbolicLink(&unicodeSourceName,
&commonExtension->DeviceName);
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.
//
_snwprintf(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
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(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] = { 0 };
UNICODE_STRING unicodeLinkName;
PAGED_CODE();
if(diskData->LinkStatus.WellKnownNameCreated) {
_snwprintf(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
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);
_snwprintf(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
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->DeviceDirectory != NULL) {
ZwMakeTemporaryObject(fdoExtension->DeviceDirectory);
ZwClose(fdoExtension->DeviceDirectory);
fdoExtension->DeviceDirectory = NULL;
}
if(Type == IRP_MN_REMOVE_DEVICE) {
if(fdoExtension->SenseData) {
ExFreePool(fdoExtension->SenseData);
fdoExtension->SenseData = NULL;
}
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);
}
if (Type == IRP_MN_REMOVE_DEVICE)
{
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 = { 0 };
DISK_CACHE_INFORMATION cacheInfo = { 0 };
ULONG isPowerProtected = 0;
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 = { 0 };
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
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);
diskData->WriteCacheOverride = DiskWriteCacheDefault;
//
// Look into the registry to see if the user
// has chosen to override the default setting
//
ClassGetDeviceParameter(fdoExtension,
DiskDeviceParameterSubkey,
DiskDeviceUserWriteCacheSetting,
(PULONG)&diskData->WriteCacheOverride);
if (diskData->WriteCacheOverride == DiskWriteCacheDefault)
{
//
// The user has not overridden the default settings
//
if (TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_DISABLE_WRITE_CACHE))
{
//
// This flag indicates that we have faulty firmware and this
// may cause the filesystem to refuse to mount on this media
//
DebugPrint((ClassDebugWarning, "DiskStartFdo: Turning off write cache for %p due to a firmware issue\n", Fdo));
diskData->WriteCacheOverride = DiskWriteCacheDisable;
}
else if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
{
//
// This flag indicates that the device is hotpluggable making it unsafe to enable caching
//
DebugPrint((ClassDebugWarning, "DiskStartFdo: Turning off write cache for %p due to hotpluggable device\n", Fdo));
diskData->WriteCacheOverride = DiskWriteCacheDisable;
}
else if (hotplugInfo.MediaHotplug)
{
//
// This flag indicates that the media in the device cannot be reliably locked
//
DebugPrint((ClassDebugWarning, "DiskStartFdo: Turning off write cache for %p due to unlockable media\n", Fdo));
diskData->WriteCacheOverride = DiskWriteCacheDisable;
}
else
{
//
// Even though the device does not seem to have any obvious problems
// we leave it to the user to modify the previous write cache setting
//
}
}
//
// Query the disk to see if write cache is enabled
// and set the DEV_WRITE_CACHE flag appropriately
//
status = DiskGetCacheInformation(fdoExtension, &cacheInfo);
if (NT_SUCCESS(status))
{
if (cacheInfo.WriteCacheEnabled == TRUE)
{
SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
if (diskData->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
{
if (diskData->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);
}
}
}
//
// Query the registry to see if this disk is power-protected or not
//
CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
ClassGetDeviceParameter(fdoExtension, DiskDeviceParameterSubkey, DiskDeviceCacheIsPowerProtected, &isPowerProtected);
if (isPowerProtected == 1)
{
SET_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
}
//
// 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 = { 0 };
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 + -