C/C++底层实现指定磁盘只读

燕狂徒写的驱动挂钩,限制磁盘只读,

用于保证涉密计算机的稳定,相当于将磁盘变成ROM

#include "ntddk.h"
#include <srb.h>
#include <scsi.h>

#define DRIVERNAME "OnlyRead(GongXiPeng!)"     // for use in messages

typedef struct tagDEVICE_EXTENSION {
 PDEVICE_OBJECT DeviceObject;   // device object this extension belongs to
 PDEVICE_OBJECT LowerDeviceObject;  // next lower driver in same stack
 PDEVICE_OBJECT Pdo;      // the PDO
 IO_REMOVE_LOCK RemoveLock;
 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;

VOID RemoveDevice(IN PDEVICE_OBJECT fdo);
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info);
NTSTATUS DispatchForSCSI(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);

NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp);
ULONG GetDeviceTypeToUse(PDEVICE_OBJECT pdo);
NTSTATUS StartDeviceCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx);
NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx);

VOID DriverUnload(IN PDRIVER_OBJECT fido);

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
 int i;
 
 KdPrint(("准备驱动加载"));
 UNREFERENCED_PARAMETER(RegistryPath);
 DriverObject->DriverUnload = DriverUnload;
 DriverObject->DriverExtension->AddDevice = AddDevice;
 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
  DriverObject->MajorFunction[i] = DispatchAny;
 DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
 DriverObject->MajorFunction[IRP_MJ_SCSI] = DispatchForSCSI;

 return(STATUS_SUCCESS);
}

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{       // DriverUnload
 PAGED_CODE();
 //UNREFERENCED_PARAMETER(DriverObject);
 KdPrint((DRIVERNAME " - Entering DriverUnload: DriverObject %8.8lX\n", DriverObject));
}

NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{       // AddDevice
 
 NTSTATUS status;
 PDEVICE_OBJECT fido;
 PDEVICE_EXTENSION pdx;
 PDEVICE_OBJECT fdo;

 PAGED_CODE();

 status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL,
  GetDeviceTypeToUse(pdo), 0, FALSE, &fido);
 if (!NT_SUCCESS(status))
 {      // can't create device object
  KdPrint((DRIVERNAME " - IoCreateDevice failed - %X\n", status));
  return status;
 }      // can't create device object
 
 pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
 do
 {      // finish initialization
  IoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 0);
  pdx->DeviceObject = fido;
  pdx->Pdo = pdo;
  //将过滤驱动附加在底层驱动之上
  fdo = IoAttachDeviceToDeviceStack(fido, pdo);
  if (!fdo)
  {     // can't attach         
   KdPrint((DRIVERNAME " - IoAttachDeviceToDeviceStack failed\n"));
   status = STATUS_DEVICE_REMOVED;
   break;
  }     // can't attach
  //记录底层驱动
  pdx->LowerDeviceObject = fdo;
  //由于不知道底层驱动是直接IO还是BufferIO,因此将标志都置上
  fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE);
  // Clear the "initializing" flag so that we can get IRPs
  fido->Flags &= ~DO_DEVICE_INITIALIZING;
 } while (FALSE);     // finish initialization

 if (!NT_SUCCESS(status))
 {     // need to cleanup
  if (pdx->LowerDeviceObject)
   IoDetachDevice(pdx->LowerDeviceObject);
  IoDeleteDevice(fido);
 }     // need to cleanup

 return status;
}       // AddDevice

///////////////////////////////////////////////////////////////////////////////
// GetDeviceTypeToUse returns the device object type of the next lower device
// object. This helps overcome a bug in some Win2K file systems which expect the
// topmost FiDO in a storage stack to have a VPB and, hence, to have been created
// with a type such as FILE_DEVICE_DISK.
#pragma PAGEDCODE
ULONG GetDeviceTypeToUse(PDEVICE_OBJECT pdo)
{       // GetDeviceTypeToUse
 PDEVICE_OBJECT ldo;
 ULONG devtype;
 ldo = IoGetAttachedDeviceReference(pdo);
 if (!ldo)
  return FILE_DEVICE_UNKNOWN;
 devtype = ldo->DeviceType;
 ObDereferenceObject(ldo);
 return devtype;
}       // GetDeviceTypeToUse

///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE    // make no assumptions about pageability of dispatch fcns
NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{       // DispatchAny
 NTSTATUS status;
 PDEVICE_EXTENSION pdx;
 PIO_STACK_LOCATION stack;

#if DBG
 static char* irpname[] = 
 {
  "IRP_MJ_CREATE",
  "IRP_MJ_CREATE_NAMED_PIPE",
  "IRP_MJ_CLOSE",
  "IRP_MJ_READ",
  "IRP_MJ_WRITE",
  "IRP_MJ_QUERY_INFORMATION",
  "IRP_MJ_SET_INFORMATION",
  "IRP_MJ_QUERY_EA",
  "IRP_MJ_SET_EA",
  "IRP_MJ_FLUSH_BUFFERS",
  "IRP_MJ_QUERY_VOLUME_INFORMATION",
  "IRP_MJ_SET_VOLUME_INFORMATION",
  "IRP_MJ_DIRECTORY_CONTROL",
  "IRP_MJ_FILE_SYSTEM_CONTROL",
  "IRP_MJ_DEVICE_CONTROL",
  "IRP_MJ_INTERNAL_DEVICE_CONTROL",
  "IRP_MJ_SHUTDOWN",
  "IRP_MJ_LOCK_CONTROL",
  "IRP_MJ_CLEANUP",
  "IRP_MJ_CREATE_MAILSLOT",
  "IRP_MJ_QUERY_SECURITY",
  "IRP_MJ_SET_SECURITY",
  "IRP_MJ_POWER",
  "IRP_MJ_SYSTEM_CONTROL",
  "IRP_MJ_DEVICE_CHANGE",
  "IRP_MJ_QUERY_QUOTA",
  "IRP_MJ_SET_QUOTA",
  "IRP_MJ_PNP",
 };
 UCHAR type;
#endif
 
 pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
 stack = IoGetCurrentIrpStackLocation(Irp);
#if DBG
 type = stack->MajorFunction;
 if (type >= IRP_MJ_MAXIMUM_FUNCTION)
  KdPrint((DRIVERNAME " - Unknown IRP, major type %X\n", type));
 else
  KdPrint((DRIVERNAME " - %s\n", irpname[type]));
#endif
 // Pass request down without additional processing
 status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
 if (!NT_SUCCESS(status))
  return CompleteRequest(Irp, status, 0);
 IoSkipCurrentIrpStackLocation(Irp);
 status = IoCallDriver(pdx->LowerDeviceObject, Irp);
 IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
 return status;
}       // DispatchAny

///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info)
{       // CompleteRequest
 Irp->IoStatus.Status = status;
 Irp->IoStatus.Information = info;
 IoCompleteRequest(Irp, IO_NO_INCREMENT);
 return status;
}       // CompleteRequest

NTSTATUS
USBSCSICompletion( IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp,
                   IN PVOID Context )
{
 PDEVICE_EXTENSION pdx;
 PIO_STACK_LOCATION irpStack;
 PSCSI_REQUEST_BLOCK CurSrb;
 PCDB cdb;
 UCHAR opCode;
 PMODE_PARAMETER_HEADER modeData;
    
 pdx = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
 IoAcquireRemoveLock(&pdx->RemoveLock,Irp);
    irpStack = IoGetCurrentIrpStackLocation( Irp );

 CurSrb=irpStack->Parameters.Scsi.Srb; 
 cdb = (PCDB)CurSrb->Cdb; 
 opCode=cdb->CDB6GENERIC.OperationCode; 
 if(opCode==SCSIOP_MODE_SENSE  && CurSrb->DataBuffer 
  && CurSrb->DataTransferLength >= 
  sizeof(MODE_PARAMETER_HEADER))
 {
  KdPrint(("SCSIOP_MODE_SENSE comming!\n"));
  modeData = (PMODE_PARAMETER_HEADER)CurSrb->DataBuffer;
  modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
 } 

 if ( Irp->PendingReturned )
 {
  IoMarkIrpPending( Irp );
 } 
 IoReleaseRemoveLock(&pdx->RemoveLock,Irp);
 return Irp->IoStatus.Status ;

///////////////////////////////////////////////////////////////////////////////
NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{       // DispatchPower
/*
#if DBG
 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
 ULONG fcn = stack->MinorFunction;
 static char* fcnname[] = 
 {
  "IRP_MN_WAIT_WAKE",
  "IRP_MN_POWER_SEQUENCE",
  "IRP_MN_SET_POWER",
  "IRP_MN_QUERY_POWER",
 };

 if (fcn == IRP_MN_SET_POWER || fcn == IRP_MN_QUERY_POWER)
 {
  static char* sysstate[] = 
  {
   "PowerSystemUnspecified",
   "PowerSystemWorking",
   "PowerSystemSleeping1",
   "PowerSystemSleeping2",
   "PowerSystemSleeping3",
   "PowerSystemHibernate",
   "PowerSystemShutdown",
   "PowerSystemMaximum",
  };

  static char* devstate[] = 
  {
   "PowerDeviceUnspecified",
   "PowerDeviceD0",
   "PowerDeviceD1",
   "PowerDeviceD2",
   "PowerDeviceD3",
   "PowerDeviceMaximum",
  };

  ULONG context = stack->Parameters.Power.SystemContext;
  POWER_STATE_TYPE type = stack->Parameters.Power.Type;
  KdPrint((DRIVERNAME " - IRP_MJ_POWER (%s)", fcnname[fcn]));
  if (type == SystemPowerState)
   KdPrint((", SystemPowerState = %s\n", sysstate[stack->Parameters.Power.State.SystemState]));
  else
   KdPrint((", DevicePowerState = %s\n", devstate[stack->Parameters.Power.State.DeviceState]));
 }
 else if (fcn < arraysize(fcnname))
  KdPrint((DRIVERNAME " - IRP_MJ_POWER (%s)\n", fcnname[fcn]));
 else
  KdPrint((DRIVERNAME " - IRP_MJ_POWER (%2.2X)\n", fcn));
#endif // DBG
*/
 PDEVICE_EXTENSION pdx;
 NTSTATUS status;

 pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
 PoStartNextPowerIrp(Irp); // must be done while we own the IRP
 status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
 if (!NT_SUCCESS(status))
  return CompleteRequest(Irp, status, 0);
 IoSkipCurrentIrpStackLocation(Irp);
 status = PoCallDriver(pdx->LowerDeviceObject, Irp);
 IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
 return status;
}       // DispatchPower

///////////////////////////////////////////////////////////////////////////////
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{       // DispatchPnp
 PIO_STACK_LOCATION stack;
 ULONG fcn; 
 NTSTATUS status;
 PDEVICE_EXTENSION pdx;
 
 stack = IoGetCurrentIrpStackLocation(Irp);
 fcn = stack->MinorFunction;
 pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
 status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
 if (!NT_SUCCESS(status))
  return CompleteRequest(Irp, status, 0);
 // Handle usage notification specially in order to track power pageable
 // flag correctly. We need to avoid allowing a non-pageable handler to be
 // layered on top of a pageable handler.
 if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION)
 {      // usage notification
  if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE))
   fido->Flags |= DO_POWER_PAGABLE;
  IoCopyCurrentIrpStackLocationToNext(Irp);
  IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine,
   (PVOID) pdx, TRUE, TRUE, TRUE);
  return IoCallDriver(pdx->LowerDeviceObject, Irp);
 }      // usage notification

 // Handle start device specially in order to correctly inherit
 // FILE_REMOVABLE_MEDIA
 if (fcn == IRP_MN_START_DEVICE)
 {      // device start
  IoCopyCurrentIrpStackLocationToNext(Irp);
  IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine,
   (PVOID) pdx, TRUE, TRUE, TRUE);
  return IoCallDriver(pdx->LowerDeviceObject, Irp);
 }      // device start

 // Handle remove device specially in order to cleanup device stack
 if (fcn == IRP_MN_REMOVE_DEVICE)
 {      // remove device
  IoSkipCurrentIrpStackLocation(Irp);
  status = IoCallDriver(pdx->LowerDeviceObject, Irp);
  IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
  RemoveDevice(fido);
  return status;
 }      // remove device

 // Simply forward any other type of PnP request
 IoSkipCurrentIrpStackLocation(Irp);
 status = IoCallDriver(pdx->LowerDeviceObject, Irp);
 IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
 return status;

///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID RemoveDevice(IN PDEVICE_OBJECT fido)
{       // RemoveDevice
 PDEVICE_EXTENSION pdx;

 KdPrint(("Enter RemoveDevice"));
 PAGED_CODE();
 pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
 if (pdx->LowerDeviceObject)
  IoDetachDevice(pdx->LowerDeviceObject);
 IoDeleteDevice(fido);

///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS StartDeviceCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx)
{       // StartDeviceCompletionRoutine
 if (Irp->PendingReturned)
  IoMarkIrpPending(Irp);
 // Inherit FILE_REMOVABLE_MEDIA flag from lower object. This is necessary
 // for a disk filter, but it isn't available until start-device time. Drivers
 // above us may examine the flag as part of their own start-device processing, too.
 if (pdx->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
  fido->Characteristics |= FILE_REMOVABLE_MEDIA;
 IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
 return STATUS_SUCCESS;
}       // StartDeviceCompletionRoutine

///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx)
{       // UsageNotificationCompletionRoutine
 if (Irp->PendingReturned)
  IoMarkIrpPending(Irp);
 // If lower driver cleared pageable flag, we must do the same
 if (!(pdx->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
  fido->Flags &= ~DO_POWER_PAGABLE;
 IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
 return STATUS_SUCCESS;
}       // UsageNotificationCompletionRoutine

#pragma LOCKEDCODE    // force inline functions into nonpaged code


#pragma LOCKEDCODE
NTSTATUS DispatchForSCSI(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{
 PDEVICE_EXTENSION pdx;
 PIO_STACK_LOCATION irpStack; 
 NTSTATUS status;

 // KdPrint((DRIVERNAME " - Enter DispatchForSCSI \n"));
 pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
 irpStack = IoGetCurrentIrpStackLocation(Irp); 
 // Pass request down without additional processing
 status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
 if (!NT_SUCCESS(status))
  return CompleteRequest(Irp, status, 0);
 IoCopyCurrentIrpStackLocationToNext(Irp);
 IoSetCompletionRoutine( Irp,
       USBSCSICompletion,
       NULL,
       TRUE,
       TRUE,
       TRUE ); 
 status = IoCallDriver(pdx->LowerDeviceObject, Irp);
 IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
 return status;
}
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE    // make no assumptions about pageability of dispatch fcns
posted on 2010-05-30 22:05  carekee  阅读(741)  评论(0编辑  收藏  举报