让U盘只读(wdm)包括安装过程

参考资料为《windows驱动开发详解》

.h

#include "ntddk.h"
#include "ntddkbd.h"
#include "string.h"
#include "interface.h"
#include "scsi.h"

#if !defined(_FILTER_H_)  //注意这个位置不能乱放,我的认识是要放在加载的头文件的下面
#define _FILTER_H_

#define DISK_TAG_SRB           'SDcS'  // "ScDS" - srb allocation

#define MAXLEN 256

#define NTDEVICE_NAME_STRING	L"\\Device\\Usbstorfilter"
#define SYMBOLIC_NAME_STRING    L"\\DosDevices\\Usbstorfilter"


#ifndef STATUS_CONTINUE_COMPLETION
#define STATUS_CONTINUE_COMPLETION STATUS_SUCCESS
#endif

#define POOL_TAG 'liFT'


typedef struct _DEVICE_EXTENSION 
{
	PDEVICE_OBJECT	Self;
	PDEVICE_OBJECT	NextLowerDriver;
	IO_REMOVE_LOCK	 RemoveLock;
} DEVICE_EXTENSION,*PDEVICE_EXTENSION;

typedef struct _CONTROL_DEVICE_EXTENSION {

	ULONG   Deleted;	 // False if the deviceobject is valid, TRUE if it's deleted
    
    PVOID   ControlData; // Store your control data here
} CONTROL_DEVICE_EXTENSION, *PCONTROL_DEVICE_EXTENSION;


EXTERN_C
NTSTATUS
FilterAddDevice(
	IN PDRIVER_OBJECT DriverObject,
	IN PDEVICE_OBJECT PhysicalDeviceObject
	);

EXTERN_C
NTSTATUS
FilterDispatchPnp(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	);

EXTERN_C
VOID
FilterUnload(
	IN PDRIVER_OBJECT DriverObject		 
	);

EXTERN_C
NTSTATUS
FilterPass(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp   
	);

EXTERN_C
NTSTATUS
DriverEntry(
	IN PDRIVER_OBJECT	DriverObject,
	IN PUNICODE_STRING	RegistryPath
	);

EXTERN_C
NTSTATUS
FilterStartCompletionRoutine(
	IN PDEVICE_OBJECT	DeviceObject,						 
	IN PIRP				Irp,
	IN PVOID			Context
	);

EXTERN_C
NTSTATUS 
USBSCSIPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

EXTERN_C
NTSTATUS 
USBSCSICompletion( IN PDEVICE_OBJECT DeviceObject,
                            IN PIRP Irp,
                            IN PVOID Context );



#endif


 

.c

#include "Driver.h"

ULONG	   InstanceCount = 0;

int			flag=1;


#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, FilterAddDevice)
#pragma alloc_text (PAGE, FilterDispatchPnp)
#pragma alloc_text (PAGE, FilterUnload)
#endif


PDEVICE_OBJECT	ControlDeviceObject;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
	NTSTATUS	status = STATUS_SUCCESS;

	DbgPrint("Enter DriverEntry\n");

	UNREFERENCED_PARAMETER (RegistryPath);

	for (ULONG ulIndex=0; ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; ulIndex++ )
	{
		DriverObject->MajorFunction[ulIndex] = FilterPass;
	}

	DriverObject->DriverUnload = FilterUnload;
	DriverObject->DriverExtension->AddDevice = FilterAddDevice;

	DriverObject->MajorFunction[IRP_MJ_SCSI]=USBSCSIPassThrough;
	DriverObject->MajorFunction[IRP_MJ_PNP] = FilterDispatchPnp;

	return	status;
}

VOID FilterUnload(IN PDRIVER_OBJECT DriverObject)
{
	PAGED_CODE();
	ASSERT(DriverObject->DeviceObject == NULL);
	DbgPrint("Entry FilterUnload\n");
	return;
}

NTSTATUS FilterAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject )
{
	NTSTATUS			status = STATUS_SUCCESS;
	PDEVICE_OBJECT		deviceObject=NULL;
	PDEVICE_EXTENSION	deviceExtension;

	UNICODE_STRING      ntName;

	RtlInitUnicodeString(&ntName, L"\\Device\\dnmm");

	DbgPrint("Entry FilterAddDevice\n");

	PAGED_CODE();

	status=IoCreateDevice(
		DriverObject,
		sizeof (DEVICE_EXTENSION),
		&ntName,
		FILE_DEVICE_DISK,
		FILE_DEVICE_SECURE_OPEN,
		FALSE,
		&deviceObject
		);

	if (!NT_SUCCESS(status))
	{
		return	status;
	}

	deviceExtension=(PDEVICE_EXTENSION)deviceObject->DeviceExtension;

	deviceExtension->NextLowerDriver=IoAttachDeviceToDeviceStack(
										deviceObject,
										PhysicalDeviceObject);

	if (NULL==deviceExtension->NextLowerDriver)
	{
		DbgPrint("IoAttachDeviceToDeviceStack fail\n");
		IoDeleteDevice(deviceObject);
		return	STATUS_UNSUCCESSFUL;
	}

	deviceObject->Flags |= deviceExtension->NextLowerDriver->Flags&(DO_BUFFERED_IO|DO_DIRECT_IO|DO_POWER_PAGABLE);

	deviceExtension->Self=deviceObject;

	IoInitializeRemoveLock(&deviceExtension->RemoveLock,POOL_TAG,1,100);

	deviceObject->Flags&=~DO_DEVICE_INITIALIZING;

	return	STATUS_SUCCESS;
}

NTSTATUS FilterPass(	IN PDEVICE_OBJECT DeviceObject,	IN PIRP Irp	)
{
	PDEVICE_EXTENSION		deviceExtension;
	NTSTATUS				status;
	
	deviceExtension=(PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
	status=IoAcquireRemoveLock(&deviceExtension->RemoveLock,Irp);

	if (!NT_SUCCESS(status))
	{
		Irp->IoStatus.Status=status;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);
		return status;
	}
	
	IoSkipCurrentIrpStackLocation(Irp);
	status=IoCallDriver(deviceExtension->NextLowerDriver,Irp);
	IoReleaseRemoveLock(&deviceExtension->RemoveLock,Irp);
	DbgPrint(("I am FilterPass\n"));
	return	status;
}

NTSTATUS FilterDispatchPnp(	IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
	PDEVICE_EXTENSION	deviceExtension;
	PIO_STACK_LOCATION	irpStack;
	NTSTATUS			status;
	KEVENT				event;

	DbgPrint("----------------- FilterDispatchPnp.\n");

	PAGED_CODE();

	deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
	irpStack = IoGetCurrentIrpStackLocation(Irp);

	status = IoAcquireRemoveLock(&deviceExtension->RemoveLock,Irp);

	if (!NT_SUCCESS(status))
	{
		Irp->IoStatus.Status = status;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);
		return	status;
	}

	switch(irpStack->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
	
		DbgPrint(":-----------------------IRP_MN_START_DEVICE:\n");

		KeInitializeEvent(&event,NotificationEvent,FALSE);
		IoCopyCurrentIrpStackLocationToNext(Irp);
		IoSetCompletionRoutine(Irp,
							   (PIO_COMPLETION_ROUTINE) FilterStartCompletionRoutine,
							   &event,
							   TRUE,
							   TRUE,
							   TRUE);

		status = IoCallDriver(deviceExtension->NextLowerDriver,Irp);

		if (status == STATUS_PENDING)
		{
			KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,NULL);
			status = Irp->IoStatus.Status;
		}

		if (NT_SUCCESS(status))
		{
			if (deviceExtension->NextLowerDriver->Characteristics & FILE_REMOVABLE_MEDIA)
			{
				DeviceObject->Characteristics|=FILE_REMOVABLE_MEDIA;
			}
		}

		Irp->IoStatus.Status = status;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);
		IoReleaseRemoveLock(&deviceExtension->RemoveLock,Irp);

		return	status;

	case IRP_MN_REMOVE_DEVICE:

		DbgPrint(":---------------------IRP_MN_REMOV_DEVICE:\n");
		IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock,Irp);
		IoSkipCurrentIrpStackLocation(Irp);
		status = IoCallDriver(deviceExtension->NextLowerDriver,Irp);

		IoDetachDevice(deviceExtension->NextLowerDriver);
		IoDeleteDevice(DeviceObject);
		return	status;


	default:

		DbgPrint(":---------------------default:\n");
		status = Irp->IoStatus.Status;
        break;
	}
	
	Irp->IoStatus.Status = status;
	IoSkipCurrentIrpStackLocation(Irp);
	status = IoCallDriver(deviceExtension->NextLowerDriver,Irp);
	IoReleaseRemoveLock(&deviceExtension->RemoveLock,Irp);

	return	status;
}

NTSTATUS FilterStartCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{
	PKEVENT		event = (PKEVENT)Context;
	DbgPrint("Entry FilterStartCompletionRoutine!\n");

	if (Irp->PendingReturned == TRUE)
	{
		KeSetEvent(event,IO_NO_INCREMENT,FALSE);
	}
	return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS USBSCSIPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
	PDEVICE_EXTENSION StorExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension; 
	DbgPrint("SCSI-Pass-Through-begin --\n");
	IoCopyCurrentIrpStackLocationToNext( Irp );
	IoSetCompletionRoutine( Irp,
		USBSCSICompletion,
		DeviceObject,
		TRUE,
		TRUE,
		TRUE ); 

	IoAcquireRemoveLock(&StorExtension->RemoveLock,Irp);
	IoReleaseRemoveLock(&StorExtension->RemoveLock,Irp);
	DbgPrint("SCSI-Pass-Through-end -Write-\n");
	return IoCallDriver( StorExtension->NextLowerDriver, Irp );
} 


NTSTATUS USBSCSICompletion( IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context )
{
	PMODE_PARAMETER_HEADER	modeData;

	PCDB	cdb ;
	UCHAR	opCode;

    PDEVICE_EXTENSION StorExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;

	IoAcquireRemoveLock(&StorExtension->RemoveLock,Irp);

	DbgPrint("+++USBSCSICompletionWrite\n");

    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );

	PSCSI_REQUEST_BLOCK CurSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool,
								sizeof(SCSI_REQUEST_BLOCK),
								DISK_TAG_SRB);
	if (CurSrb == NULL) 
	{
		DbgPrint("ERROR");
		ASSERT(0);
	}

	RtlZeroMemory(CurSrb, SCSI_REQUEST_BLOCK_SIZE); 

	if ( irpStack->MajorFunction == IRP_MJ_SCSI )
	{
		CurSrb=irpStack->Parameters.Scsi.Srb; 
		cdb = (PCDB)CurSrb->Cdb;	
		opCode=cdb->CDB6GENERIC.OperationCode; 

			DbgPrint("++=====================+:Write Private 2\n");
		if (opCode==SCSIOP_MODE_SENSE)
		{
			DbgPrint("++3+:Write Private 2\n");
			modeData = (PMODE_PARAMETER_HEADER)CurSrb->DataBuffer;
			modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
		} 

	}

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


 安装方法:

1. 直接修改注册表

    这个驱动生成之后为  FSSSS.sys

    要对某一个型号的U盘过滤(以kingston为例)。

    step1:将FSSSS.sys拷贝到system32\Drivers下

    step2:在注册表中找到  过滤U盘的位置。例如  

         HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR\DISK&Ven_Kingston&Prod_DataTraveler_2.0&Rev_PMAP\5B821D00025A&0

         在这个条目中添加一个REG_SZ类型  KeyValue对为( LowerFilters    FSSSS)。注意,如果无法修改需要先修改权限

    step3:在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\中新建一个Key为FSSSS,得到

          HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\FSSSS

          在这个里面添加3个键值对  REG_DWORD(ErrorControl    1)      REG_DWORD(Start 3)   REG_DWORD(Type 1)

    step4:Disable  Enable设备就OK了

 

你可能感兴趣的:(让U盘只读(wdm)包括安装过程)