燕狂徒写的驱动挂钩,限制磁盘只读,
用于保证涉密计算机的稳定,相当于将磁盘变成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

转载于:https://www.cnblogs.com/carekee/articles/1747688.html

C/C++底层实现指定磁盘只读相关推荐

  1. 解决Linux“Device is busy”与磁盘只读

    在Linux系统中,如使用存储链路抖动或远程数据传输到本地未及时交互完成 都可能会出现磁盘只读的情况,当然本文所概述的只针对磁盘分区只读,针对系统所有目录只读则无法使用指令修复,需重启OS.      ...

  2. Tomcat映射虚拟路径到指定磁盘(eclipse)

    用WangEditor富文本编辑,上传图片的时候,本文主要记录一下Tomcat映射虚拟路径到指定磁盘,保存到指定路径中,且能实现页面预览. 在实现之前wangeditor的简单实用请参照博主小道仙的后 ...

  3. linux 修复磁盘 只读,服务器磁盘只读修复过程

    服务器的磁盘也没有做监控,其实我也不知道如何对磁盘的状态做监控,突然查看不到新数据,上去看了一下磁盘的情况,发现磁盘出现只读的情况,无法写入数据,要是大家谁知道怎么可以监控磁盘只读的方法,可以告诉我下 ...

  4. mysql数据存储到指定位置_Mysql数据库表分区存储到指定磁盘路径

    . 前提: mysql5.6.6以上的版本以上的版本才支持单表指定目录,且目录权限是MySQL:mysql.  在mysql中数据文件存放于在my.cnf中datadir指定的路径,使用的表引擎不同产 ...

  5. linux 指定磁盘盘符,使用udev指定盘符

    .目标: 项目中遇到本地磁盘与SAN用到的设备驱动是同一驱动模块,这导致了我们通常使用的改变系统启动时加载模块顺序以实现盘符顺序的方式,那么幸好linux有udev,动态的建立/dev下的设备,并运行 ...

  6. 一文了解,如何在VMware指定磁盘分区 扩容

    VMware是一个很常用的虚拟机,随着安装在VMware上应用的不断增多,久而久之,原先设定的容量可能不太合适了,需要对分区进行管理.下面聊聊怎样对虚拟机进行扩容,在分区完成后,不会丢失数据(使用GP ...

  7. 系统服务器如何给指定磁盘扩容_刀片服务器如何选择操作系统?

    由于Windows系统,操作简单,管理方便,所以相比于Linux系统刀片服务器用户青睐于Windows系统.但是Windows有多个版本,分别是32位和64位. 那么,我们该如何选择呢?当然,在选择W ...

  8. linux共享磁盘给指定ip,Linux 磁盘挂载和mount共享

    其中根据文章http://blog.163.com/luoxiaoyu1010@126/blog/static/16581022720108162830579/也配置 原文:http://blog.c ...

  9. Linux数据文件自动迁移,linux下增加磁盘改变指定文件路径分区挂载点和迁移数据...

    Centos7 系统上原有目录/data 挂载根目录下,空间有点小,我们需要把/data目录挂载到另一个磁盘,同时把数据迁移. 1.查看分区情况 fdisk -l 2.查看路径对应分区情况 df -l ...

  10. linux下增加磁盘改变指定文件路径分区挂载点和迁移数据

    Centos7 系统上原有目录/data 挂载根目录下,空间有点小,我们需要把/data目录挂载到另一个磁盘,同时把数据迁移. 1.查看分区情况 fdisk -l 2.查看路径对应分区情况 df -l ...

最新文章

  1. 重写了博客上的代码着色脚本
  2. 2013 Multi-University Training Contest 6 部分解题报告
  3. CTFshow php特性 web113
  4. 15-奇怪的Js文件引用问题
  5. 超适合新手的基础Linux命令
  6. leetcode1094. 拼车
  7. LigoWave(力格微)无线网桥稳定性探秘——私有协议
  8. select, poll, epoll
  9. python pytest mark
  10. Hadoop MapReduce InputFormat基础
  11. 滴滴出行回应导航崩了;微信支付正式上线「向手机号转账」功能;Guns 6.0 发布 | 极客头条...
  12. 5. 使用字符串库函数
  13. Java将多张图片合并保存到同一页PDF中
  14. linux查询本机IP地址(可用于SSH访问)
  15. 论Flutter开发如何改善套娃地狱问题
  16. 完整VI项目设计书(转)
  17. BZOJ4372: 烁烁的游戏(动态点分治)
  18. GC详解---JVM(三)
  19. elastica php yii,Yii 1.1.*集成elasticsearch php 客户端Elastica
  20. 论文检测系统如何选择?

热门文章

  1. 阶段5 3.微服务项目【学成在线】_day04 页面静态化_08-freemarker基础-空值处理
  2. Tomcat启动报:The Server time zone value 'XXXXX' 乱码问题解决
  3. [NOIP2016]愤怒的小鸟
  4. ucore 地址映射的几个阶段
  5. 未格式化的硬盘识别失败
  6. div居中和table居中,jQuery获取下拉列表值
  7. Python常用模块实战之ATM和购物车系统再升级
  8. 移动端数据爬取和Scrapy框架
  9. Java入门——第九天
  10. .NET Core跨平台:.NET Core项目部署到linux(Centos7)