📄 floppy.c
字号:
// The thread must know which diskette to operate on, but the
// request list only passes the IRP. So we'll stick a pointer
// to the diskette extension in Type3InputBuffer, which is
// a field that isn't used for floppy ioctls.
//
//
// Add the request to the queue, and wake up the thread to
// process it.
//
// irpSp->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)
// disketteExtension;
FloppyDump(
FLOPIRPPATH,
("Floppy: Enqueing up IRP: %p\n",Irp)
);
ntStatus = FlQueueIrpToThread(Irp, disketteExtension);
break;
case IOCTL_DISK_GET_MEDIA_TYPES:
case IOCTL_STORAGE_GET_MEDIA_TYPES: {
FloppyDump(
FLOPSHOW,
("Floppy: IOCTL_DISK_GET_MEDIA_TYPES called\n")
);
lowestDriveMediaType = DriveMediaLimits[
disketteExtension->DriveType].LowestDriveMediaType;
highestDriveMediaType = DriveMediaLimits[
disketteExtension->DriveType].HighestDriveMediaType;
outputBufferLength =
irpSp->Parameters.DeviceIoControl.OutputBufferLength;
//
// Make sure that the input buffer has enough room to return
// at least one descriptions of a supported media type.
//
if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) ) ) {
FloppyDump(
FLOPDBGP,
("Floppy: invalid GET_MEDIA_TYPES buffer size\n")
);
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Assume success, although we might modify it to a buffer
// overflow warning below (if the buffer isn't big enough
// to hold ALL of the media descriptions).
//
ntStatus = STATUS_SUCCESS;
if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) *
( highestDriveMediaType - lowestDriveMediaType + 1 ) ) ) {
//
// The buffer is too small for all of the descriptions;
// calculate what CAN fit in the buffer.
//
FloppyDump(
FLOPDBGP,
("Floppy: GET_MEDIA_TYPES buffer size too small\n")
);
ntStatus = STATUS_BUFFER_OVERFLOW;
highestDriveMediaType =
(DRIVE_MEDIA_TYPE)( ( lowestDriveMediaType - 1 ) +
( outputBufferLength /
sizeof( DISK_GEOMETRY ) ) );
}
outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
for (
i = (UCHAR)lowestDriveMediaType;
i <= (UCHAR)highestDriveMediaType;
i++ ) {
outputBuffer->MediaType = DriveMediaConstants[i].MediaType;
outputBuffer->Cylinders.LowPart =
DriveMediaConstants[i].MaximumTrack + 1;
outputBuffer->Cylinders.HighPart = 0;
outputBuffer->TracksPerCylinder =
DriveMediaConstants[i].NumberOfHeads;
outputBuffer->SectorsPerTrack =
DriveMediaConstants[i].SectorsPerTrack;
outputBuffer->BytesPerSector =
DriveMediaConstants[i].BytesPerSector;
FloppyDump(
FLOPSHOW,
("Floppy: media types supported [%d]\n"
"------- Cylinders low: 0x%x\n"
"------- Cylinders high: 0x%x\n"
"------- Track/Cyl: 0x%x\n"
"------- Sectors/Track: 0x%x\n"
"------- Bytes/Sector: 0x%x\n"
"------- Media Type: %d\n",
i,
outputBuffer->Cylinders.LowPart,
outputBuffer->Cylinders.HighPart,
outputBuffer->TracksPerCylinder,
outputBuffer->SectorsPerTrack,
outputBuffer->BytesPerSector,
outputBuffer->MediaType)
);
outputBuffer++;
Irp->IoStatus.Information += sizeof( DISK_GEOMETRY );
}
break;
}
case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: {
if (IsNEC_98) {
PMOUNTDEV_SUGGESTED_LINK_NAME suggestedName;
WCHAR driveLetterNameBuffer[10];
RTL_QUERY_REGISTRY_TABLE queryTable[2];
PWSTR valueName;
UNICODE_STRING driveLetterName;
FloppyDump(FLOPDBGP,("FLOPPY: IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME to device %#08lx"
" through irp %#08lx\n",
DeviceObject, Irp));
if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
ntStatus = STATUS_NOT_FOUND;
break;
}
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
valueName = ExAllocatePool(PagedPool, sizeof(WCHAR) * 64);
if (!valueName) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory( valueName, sizeof(WCHAR) * 64 );
RtlCopyMemory( valueName,
disketteExtension->DeviceName.Buffer,
disketteExtension->DeviceName.Length );
driveLetterName.Buffer = driveLetterNameBuffer;
driveLetterName.MaximumLength = 20;
driveLetterName.Length = 0;
RtlZeroMemory(queryTable, 2*sizeof(RTL_QUERY_REGISTRY_TABLE));
queryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
RTL_QUERY_REGISTRY_DIRECT;
queryTable[0].Name = valueName;
queryTable[0].EntryContext = &driveLetterName;
ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
L"\\Registry\\Machine\\System\\DISK",
queryTable, NULL, NULL);
if (!NT_SUCCESS(ntStatus)) {
ExFreePool(valueName);
break;
}
if (driveLetterName.Length != 4 ||
driveLetterName.Buffer[0] < 'A' ||
driveLetterName.Buffer[0] > 'Z' ||
driveLetterName.Buffer[1] != ':') {
ntStatus = STATUS_NOT_FOUND;
ExFreePool(valueName);
break;
}
suggestedName = Irp->AssociatedIrp.SystemBuffer;
suggestedName->UseOnlyIfThereAreNoOtherLinks = TRUE;
suggestedName->NameLength = 28;
Irp->IoStatus.Information =
FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME, Name) + 28;
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
Irp->IoStatus.Information) {
Irp->IoStatus.Information =
sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
ntStatus = STATUS_BUFFER_OVERFLOW;
ExFreePool(valueName);
break;
}
RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE,
L"\\Registry\\Machine\\System\\DISK",
valueName);
ExFreePool(valueName);
RtlCopyMemory(suggestedName->Name, L"\\DosDevices\\", 24);
suggestedName->Name[12] = driveLetterName.Buffer[0];
suggestedName->Name[13] = ':';
break;
} // (IsNEC_98)
// Pass this to the default.
}
case IOCTL_DISK_SENSE_DEVICE: {
if (IsNEC_98) {
FloppyDump(
FLOPDBGP,
("Floppy: SENSE_DEVISE_STATUS \n")
);
//
// Make sure that we got all the necessary IOCTL read write parameters.
//
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof( SENSE_DEVISE_STATUS_PTOS ) ) {
FloppyDump(
FLOPDBGP,
("Floppy: invalid SENSE_DEVISE_STATUS buffer length\n")
);
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
// irpSp->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)
// disketteExtension;
FloppyDump(
FLOPIRPPATH,
("Floppy: Enqueing up IRP: %p\n",Irp)
);
ntStatus = FlQueueIrpToThread(Irp, disketteExtension);
break;
} // (IsNEC_98)
}
default: {
//
// We pass down IOCTL's because ACPI uses this as a communications
// method. ACPI *should* have used a PNP Interface mechanism, but
// it's too late now.
//
#if 0
FloppyDump(
FLOPDBGP,
("Floppy: invalid device request %x\n",
irpSp->Parameters.DeviceIoControl.IoControlCode)
);
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
#endif
IoSkipCurrentIrpStackLocation( Irp );
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
return ntStatus;
}
}
if ( ntStatus != STATUS_PENDING ) {
Irp->IoStatus.Status = ntStatus;
if (!NT_SUCCESS( ntStatus ) &&
IoIsErrorUserInduced( ntStatus )) {
IoSetHardErrorOrVerifyDevice( Irp, DeviceObject );
}
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}
return ntStatus;
}
NTSTATUS
FloppyPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
--*/
{
PIO_STACK_LOCATION irpSp;
PDISKETTE_EXTENSION disketteExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG i;
FloppyDump( FLOPSHOW, ("FloppyPnp:\n") );
//
// Lock down the driver if it is not already locked.
//
FloppyResetDriverPaging();
disketteExtension = DeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation( Irp );
if ( disketteExtension->IsRemoved ) {
//
// Since the device is stopped, but we don't hold IRPs,
// this is a surprise removal. Just fail it.
//
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return STATUS_DELETE_PENDING;
}
switch ( irpSp->MinorFunction ) {
case IRP_MN_START_DEVICE:
ntStatus = FloppyStartDevice( DeviceObject, Irp );
break;
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
if ( irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE ) {
FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_QUERY_STOP_DEVICE - Irp: %p\n", Irp) );
} else {
FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_QUERY_REMOVE_DEVICE - Irp: %p\n", Irp) );
}
if ( !disketteExtension->IsStarted ) {
//
// If we aren't started, we'll just pass the irp down.
//
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
return ntStatus;
}
//
// Hold all new requests.
//
ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
disketteExtension->HoldNewRequests = TRUE;
ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));
//
// Queue this irp to the floppy thread, this will shutdown the
// floppy thread without waiting for the typical 3 second motor
// timeout.
//
ntStatus = FlQueueIrpToThread( Irp, disketteExtension );
//
// Wait for the floppy thread to finish. This could take a few hundred
// milliseconds if the motor needs to be shut down.
//
if ( ntStatus == STATUS_PENDING ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -