📄 ide.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 1995 - 1998 OSR Open Systems Resources, Inc.
// All Rights Reserved
// Based on a previous work by Microsoft Corporation
// Copyright (c) 1991, 1992, 1993 Microsoft Corporation
//
// This sofware is supplied for instructional purposes only.
//
// OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
// for this software. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
// PURPOSE. THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
// WITH YOU. OSR's entire liability and your exclusive remedy shall not
// exceed the price paid for this material. In no event shall OSR or its
// suppliers be liable for any damages whatsoever (including, without
// limitation, damages for loss of business profit, business interruption,
// loss of business information, or any other pecuniary loss) arising out
// of the use or inability to use this software, even if OSR has been
// advised of the possibility of such damages. Because some states/
// jurisdictions do not allow the exclusion or limitation of liability for
// consequential or incidental damages, the above limitation may not apply
// to you.
//
// This driver is the example Programmed I/O device driver that
// accompanies the book Windows NT Device Driver Development, by
// Peter Viscarola and W. Anthony Mason, (c) 1998 OSR Open Systems
// Resources, Inc. and published by MacMillan Technical Publishing
// ISBN 1578700582.
//
//
// OSR Open Systems Resources, Inc.
// 105 Route 101A Suite 19
// Amherst, NH 03031 (603) 595-6500 FAX: (603) 595-6503
// email bugs to: bugs@osr.com
//
//
// MODULE:
//
// $Workfile: ide.c $
//
// ABSTRACT:
//
// This file contains the initial entry point for the OSR Sample
// Programmed I/O device driver for the IDE (AT) Disk Controller.
//
// AUTHOR:
//
// Open Systems Resources, Inc.
//
// REVISION:
//
//
///////////////////////////////////////////////////////////////////////////////
#include "ntddk.h" // main NT include
#include "ntdddisk.h" // disk driver IOCTL definitions
#include "ntddscsi.h" // scsi IOCTL defintions
#include "hw.h" // the access macro/definitions
#include "ide.h" // general declarations/structures
#include "utils.h" // IdeWaitController utilities
//
// static forward declarations
//
static VOID
FinishIrp(IN PIDE_DEV_EXT devExt,
IN NTSTATUS NtStatus);
static BOOLEAN
ResetDisk(IN PVOID Context);
///////////////////////////////////////////////////////////////////////////////
//
// IdeDispatchCreateClose
//
// This routine handles the Create and Close IRPs. Since we're a
// disk driver, this only completes the IRP
//
// INPUTS:
//
// DeviceObject - pointer to our device object
// Irp - pointer to the IRP
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_SUCCESS, any time, all the time
//
// IRQL:
//
// IRQL_PASSIVE_LEVEL
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
IdeDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp)
{
//
// Nothing to do... Just complete the request with success and return
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Complete the irp with no increase in priority
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// return the success
//
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
//
// IdeDispatchDeviceControl
//
// This routine handles the device control IRPs
//
// INPUTS:
//
// DeviceObject - pointer to our device object
// Irp - pointer to the IRP
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_SUCCESS upon completion of the request, otherwise
// STATUS_INVALID_DEVICE_REQUEST , STATUS_INVALID_PARAMETER
//
// IRQL:
//
// IRQL_PASSIVE_LEVEL
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
IdeDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp)
{
PPARTITION_DATA partitionData;
PIDE_DEV_EXT devExt;
PCONTROLLER_DATA controllerData;
PIO_STACK_LOCATION ioStack;
NTSTATUS ntStatus;
//
// Set up some locals
//
partitionData = DeviceObject->DeviceExtension;
devExt = partitionData->Partition0;
controllerData = devExt->ControllerData;
//
// Get the current stack location
//
ioStack = IoGetCurrentIrpStackLocation(Irp);
//
// Determine which I/O control code was specified.
// In this sample driver, we support the absolute minimum IOCTL
// necessar. See NTDDDISK.H for the complete set of definitions.
//
switch (ioStack->Parameters.DeviceIoControl.IoControlCode) {
//
// Return the drive geometry
//
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
//
// Validate the size of the requestor's buffer
//
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DISK_GEOMETRY)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
} else {
PDISK_GEOMETRY obuf;
//
// Since the IOCTL is specified as METHOD_BUFFERED, the
// output buffer is in system pool, pointed to by the
// AssociatedIrp.SystemBuffer field in the IRP
//
obuf = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
//
// This is known to be a fixed hard disk, so we return
// FixedMedia (defined in NTDDDISK.H)
//
obuf->MediaType = FixedMedia;
//
// The actual disk geometry is retrieved from the
// devExt structure. This was filled in during
// device initialization (see InitializeDisk())
//
obuf->Cylinders.QuadPart = devExt->PretendNumberOfCylinders;
obuf->TracksPerCylinder = devExt->PretendTracksPerCylinder;
obuf->SectorsPerTrack = devExt->PretendSectorsPerTrack;
obuf->BytesPerSector = devExt->BytesPerSector;
//
// Fill in the I/O Status Block for completion
//
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break ;
//
// Return the information about the partition specified by the
// device object.
//
case IOCTL_DISK_GET_PARTITION_INFO:
//
// Validate the size of the requestor's buffer
//
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
} else {
//
// Is this request for the physical device (i.e. Partition0)?
//
if (partitionData == (PPARTITION_DATA)devExt) {
//
// The request is for the physical device. This isn't
// a sensible request... so fail it.
//
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
} else {
PPARTITION_INFORMATION obuf;
//
// The request is for an actual partition on the drive,
// not the physical device.
//
// Since this IOCTL uses METHOD_BUFFERED, we locate
// the intermediate buffer to be used to return data to
// the requestor in AssociatedIrp.SystemBuffer
//
obuf = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
//
// Fill in the partition information obtained during
// the initilaization process (see InitalizeDisk()
//
obuf->PartitionType = partitionData->Pi.PartitionType;
obuf->BootIndicator = partitionData->Pi.BootIndicator;
//
// If it wasn't regcognized, we wouldn't have a partition
// device object...
//
obuf->RecognizedPartition = TRUE;
obuf->RewritePartition = FALSE;
obuf->PartitionNumber = partitionData->Pi.PartitionNumber;
obuf->StartingOffset = partitionData->Pi.StartingOffset;
obuf->PartitionLength = partitionData->Pi.PartitionLength;
obuf->HiddenSectors = partitionData->Pi.HiddenSectors;
//
// Set the length of the returned data in the Information
// field and set the STATUS_SUCCESS for the Irp
//
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
}
break ;
//
// Set some partition information
//
case IOCTL_DISK_SET_PARTITION_INFO:
//
// Validate the input buffer size. If it's not correct,
// complete the IRP with an error status.
//
if (ioStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SET_PARTITION_INFORMATION)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
} else {
//
// Is the requestor trying to set partition info for
// Partion zero, which is the physical disk?
//
if (partitionData == (PPARTITION_DATA)devExt) {
//
// Can't set the part info on a physical disk, silly!
//
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
} else {
PSET_PARTITION_INFORMATION inputBuffer;
//
// Since the IOCTL uses METHOD_BUFFERED, we locate
// the intermediate buffer with the requestor's set
// partition information in it.
//
inputBuffer =
(PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
//
// Invoke the kernel function to set the partition information
//
//
// If this were a REAL IDE driver, we might want to VALIDATE
// the partition information being set before lofting this
// request down to the I/O Manager. But seeing as how
// this is just a sample...
//
ntStatus = IoSetPartitionInformation(devExt->DeviceObject,
devExt->BytesPerSector,
partitionData->PartitionOrdinal,
inputBuffer->PartitionType);
//
// Update our information
//
if (NT_SUCCESS(ntStatus)) {
partitionData->Pi.PartitionType = inputBuffer->PartitionType;
}
//
//
//
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
}
}
break ;
//
// Return the partition layout for the physical drive. Note that
// the layout is returned for the actual physical drive, regardless
// of which partition was specified for the request.
//
case IOCTL_DISK_GET_DRIVE_LAYOUT:
//
// Check that the input buffer is of the correct size.
// If not, then return an error
//
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DRIVE_LAYOUT_INFORMATION)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
} else {
PDRIVE_LAYOUT_INFORMATION partitionList;
//
// Call the service to read the partition table. The
// result will be stored in a "partition buffer" allocated
// by the IoReadPartitionTable() function in non-paged
// pool. We free this memory below...
//
ntStatus = IoReadPartitionTable(devExt->DeviceObject,
devExt->BytesPerSector,
FALSE,
&partitionList);
//
// if the read fails, then set the status
//
if (!NT_SUCCESS(ntStatus)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = ntStatus;
} else {
ULONG tempSize;
//
// The disk layout has been returned in the partitionList
// buffer.
//
// First, we must determine the size of the returned
// information to see if the data will fit into the
// IOCTL buffer. The DRIVE_LAYOUT_INFORMATION
// structure (defined in NTDDDISK.H) consists of a
// variable number of PARTITION_INFORMATION structures
// (also defined in NTDDDISK.H). So, first we use the
// MACRO FIELD_OFFSET (defined in NTDEF.H) which
// will determine the size of the DRIVE_LAYOUT_INFORMATION
// structure less the start of the PARTITION_INFORMATION
// structures.
//
tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
PartitionEntry[0]);
//
// We now add to tempSize the size of all of the
// PARTITION_INFORMATION structures
//
tempSize += partitionList->PartitionCount *
sizeof(PARTITION_INFORMATION);
//
// If this total size is larger than the requestor's
// OutputBufferLength, then return an error
//
if (tempSize >
ioStack->Parameters.DeviceIoControl.OutputBufferLength) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
} else {
//
// The buffer is large enough, so move the data
//
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
partitionList,
tempSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -