⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hellowdm.cpp

📁 学写驱动程序的第一步需要看的列子含源代码!
💻 CPP
字号:
/***************************************************************
程序名称:Hello World for WDM
文件名称:HelloWDM.cpp
作者:罗聪
日期:2002-8-16
***************************************************************/

//一定要的头文件,声明了函数模块和变量:
#include "HelloWDM.h"
#include "Ioctl.h"


KSPIN_LOCK BufferLock;
PUCHAR	Buffer = NULL;
ULONG	BufferSize = 0;

/***************************************************************
函数名称:DriverEntry()
功能描述:WDM程序入口
***************************************************************/
//extern "C"是必须的,表示“用C链接”。如果你的文件名是HelloWDM.c的话,这句可以省略。
extern "C"
NTSTATUS DriverEntry(    IN PDRIVER_OBJECT DriverObject,
                        IN PUNICODE_STRING RegistryPath)
{
    DbgPrint("Starting DriverEntry()\n");
    
    //指定“添加设备”消息由函数“HelloWDMAddDevice()”来处理:
    DriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
    DriverObject->DriverUnload = Wdm1Unload;
    //指定“即插即用”消息由函数“HelloWDMPnp()”来处理:
    DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
    
    DriverObject->MajorFunction[IRP_MJ_CREATE] = Wdm1Create;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = Wdm1Close;

	DriverObject->MajorFunction[IRP_MJ_READ] = Wdm1Read;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = Wdm1Write;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Wdm1DeviceControl;
	
	KeInitializeSpinLock(&BufferLock);
	DbgPrint("DriverEntry completed");    

    //返回一个NTSTATUS值STATUS_SUCCESS。几乎所有的驱动程序例程都必须返回一个NTSTATUS值,这些值在NTSTATUS.H DDK头文件中有详细的定义。
    return STATUS_SUCCESS;
}

NTSTATUS Wdm1Create(IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
	DbgPrint( "Create File is %T", &(IrpStack->FileObject->FileName));

	// Complete successfully
	return CompleteIrp(Irp,STATUS_SUCCESS,0);
}

NTSTATUS Wdm1Close(	IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	DbgPrint("Wdm1Close");

	// Complete successfully
	return CompleteIrp(Irp,STATUS_SUCCESS,0);
}

NTSTATUS Wdm1DeviceControl(	IN PDEVICE_OBJECT fdo,
							IN PIRP Irp)
{
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
	NTSTATUS status = STATUS_SUCCESS;
	ULONG BytesTxd = 0;

	ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	DbgPrint("DeviceIoControl: Control code %x InputLength %d OutputLength %d",
				ControlCode, InputLength, OutputLength);

	// Get access to the shared buffer
	KIRQL irql;
	KeAcquireSpinLock(&BufferLock,&irql);
	switch( ControlCode)
	{
	///////	Zero Buffer
	case IOCTL_WDM1_ZERO_BUFFER:
		// Zero the buffer
		if( Buffer!=NULL && BufferSize>0)
			RtlZeroMemory(Buffer,BufferSize);
		break;

	///////	Remove Buffer
	case IOCTL_WDM1_REMOVE_BUFFER:
		if( Buffer!=NULL)
		{
			ExFreePool(Buffer);
			Buffer = NULL;
			BufferSize = 0;
		}
		break;

	///////	Get Buffer Size as ULONG
	case IOCTL_WDM1_GET_BUFFER_SIZE:
		if( OutputLength<sizeof(ULONG))
			status = STATUS_INVALID_PARAMETER;
		else
		{
			BytesTxd = sizeof(ULONG);
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&BufferSize,sizeof(ULONG));
		}
		break;

	///////	Get Buffer
	case IOCTL_WDM1_GET_BUFFER:
		if( OutputLength>BufferSize)
			status = STATUS_INVALID_PARAMETER;
		else
		{
			BytesTxd = OutputLength;
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,Buffer,BytesTxd);
		}
		break;

	///////	Invalid request
	default:
		status = STATUS_INVALID_DEVICE_REQUEST;
	}
	// Release shared buffer
	KeReleaseSpinLock(&BufferLock,irql);

	DbgPrint("DeviceIoControl: %d bytes written",(int)BytesTxd);

	// Complete IRP
	return CompleteIrp(Irp,status,BytesTxd);
}

NTSTATUS Wdm1Read(IN PDEVICE_OBJECT fdo,
				  IN PIRP Irp)
{
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
	NTSTATUS status = STATUS_SUCCESS;
	LONG BytesTxd = 0;

	// Get call parameters
	LONGLONG FilePointer = IrpStack->Parameters.Read.ByteOffset.QuadPart;
	ULONG ReadLen = IrpStack->Parameters.Read.Length;
	DbgPrint("Read %d bytes from file pointer %d",(int)ReadLen,(int)FilePointer);

	// Get access to the shared buffer
	KIRQL irql;
	KeAcquireSpinLock(&BufferLock,&irql);

	// Check file pointer
	if( FilePointer<0)
		status = STATUS_INVALID_PARAMETER;
	if( FilePointer>=(LONGLONG)BufferSize)
		status = STATUS_END_OF_FILE;

	if( status==STATUS_SUCCESS)
	{
		// Get transfer count
		if( ((ULONG)FilePointer)+ReadLen>BufferSize)
		{
			BytesTxd = BufferSize - (ULONG)FilePointer;
			if( BytesTxd<0) BytesTxd = 0;
		}
		else
			BytesTxd = ReadLen;

		// Read from shared buffer
		if( BytesTxd>0 && Buffer!=NULL)
			RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, Buffer+FilePointer, BytesTxd);
	}

	// Release shared buffer
	KeReleaseSpinLock(&BufferLock,irql);

	DbgPrint("Read: %d bytes returned",(int)BytesTxd);

	// Complete IRP
	return CompleteIrp(Irp,status,BytesTxd);
}

NTSTATUS Wdm1Write(	IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
	NTSTATUS status = STATUS_SUCCESS;
	LONG BytesTxd = 0;

	// Get call parameters
	LONGLONG FilePointer = IrpStack->Parameters.Write.ByteOffset.QuadPart;
	ULONG WriteLen = IrpStack->Parameters.Write.Length;
	DbgPrint("Write %d bytes from file pointer %d",(int)WriteLen,(int)FilePointer);

	if( FilePointer<0)
		status = STATUS_INVALID_PARAMETER;
	else
	{
		// Get access to the shared buffer
		KIRQL irql;
		KeAcquireSpinLock(&BufferLock,&irql);

		BytesTxd = WriteLen;

		// (Re)allocate buffer if necessary
		if( ((ULONG)FilePointer)+WriteLen>BufferSize)
		{
			ULONG NewBufferSize = ((ULONG)FilePointer)+WriteLen;
			PVOID NewBuffer = ExAllocatePool(NonPagedPool,NewBufferSize);
			if( NewBuffer==NULL)
			{
				BytesTxd = BufferSize - (ULONG)FilePointer;
				if( BytesTxd<0) BytesTxd = 0;
			}
			else
			{
				RtlZeroMemory(NewBuffer,NewBufferSize);
				if( Buffer!=NULL)
				{
					RtlCopyMemory(NewBuffer,Buffer,BufferSize);
					ExFreePool(Buffer);
				}
				Buffer = (PUCHAR)NewBuffer;
				BufferSize = NewBufferSize;
			}
		}

		// Write to shared memory
		if( BytesTxd>0 && Buffer!=NULL)
			RtlCopyMemory( Buffer+FilePointer, Irp->AssociatedIrp.SystemBuffer, BytesTxd);

		// Release shared buffer
		KeReleaseSpinLock(&BufferLock,irql);
	}

	DbgPrint("Write: %d bytes written",(int)BytesTxd);

	// Complete IRP
	return CompleteIrp(Irp,status,BytesTxd);
}




NTSTATUS CompleteIrp( PIRP Irp, NTSTATUS status, ULONG info)
{
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = info;
	IoCompleteRequest(Irp,IO_NO_INCREMENT);
	return status;
}



/***************************************************************
函数名称:HelloWDMAddDevice()
功能描述:处理“添加设备”消息
***************************************************************/
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT PhysicalDeviceObject)
{
    //定义一个NTSTATUS类型的返回值:
    NTSTATUS status;
    //定义一个功能设备对象(Functional Device Object):
    PDEVICE_OBJECT fdo;

	UNICODE_STRING ntDeviceName; 
	UNICODE_STRING win32DeviceName; 
	RtlInitUnicodeString(&ntDeviceName, L"\\Device\\Twdm1");
	RtlInitUnicodeString(&win32DeviceName, L"\\DosDevices\\Twdm1");    
    
    DbgPrint("Starting AddDevice()\n");

    //创建我们的功能设备对象,并储存到fdo中:
    status = IoCreateDevice(
        DriverObject,                //驱动程序对象
        sizeof(DEVICE_EXTENSION),    //要求的设备扩展的大小
        &ntDeviceName,                        //设备名称,这里为NULL
        FILE_DEVICE_UNKNOWN,        //设备的类型,在标准头文件WDM.H或NTDDK.H中列出的FILE_DEVICE_xxx值之一
        0,                            //各种常量用OR组合在一起,指示可删除介质、只读等。
        FALSE,                        //如果一次只有一个线程可以访问该设备,为TRUE,否则为FALSE
        &fdo);                        //返回的设备对象

    //NT_SUCCESS宏用于测试IoCreateDevice内核是否成功完成。不要忘记检查对内核的所有调用是否成功。
    //NT_ERROR宏不等同于!NT_SUCCESS,最好使用!NT_SUCCESS,因为除了错误外,它还截获警告信息。
    if( !NT_SUCCESS(status))
    {
    	DbgPrint("AddDevice(): IoCreateDevice failed!");
        return status;
    }
    else
    {
    	DbgPrint("AddDevice(): IoCreateDevice OK!");
    }

	status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName ); 
	if (!NT_SUCCESS(status)) 
	{ 
		DbgPrint("TWDM: IoCreateSymbolicLink() faild ! \n"); 
	} 
	else 
	{ 
		DbgPrint("TWDM: IoCreateSymbolicLink() ok ! \n"); 
	} 

    //创建一个设备扩展对象dx,用于存储指向fdo的指针:
    PDEVICE_EXTENSION dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
    dx->fdo = fdo;

    //用IoAttachDeviceToDeviceStack函数把HelloWDM设备挂接到设备栈:
    dx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

    //设置fdo的flags。有两个“位”是必须改变的,一个是必须清除DO_DEVICE_INITIALIZING标志,如果在DriverEntry例程中调用IoCreateDevice(),就不需要清除这个标志位。还有一个是必须设置DO_BUFFER_IO标志位:
    fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
    fdo->Flags &= ~DO_DEVICE_INITIALIZING;
    
    DbgPrint("AddDevice() OK!\n");

    //返回值:
    return STATUS_SUCCESS;
}


/***************************************************************
函数名称:HelloWDMPnp()
功能描述:处理“即插即用”消息
***************************************************************/
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                        IN PIRP Irp)
{
    //创建一个设备扩展对象dx,用于存储指向fdo的指针:
    PDEVICE_EXTENSION dx=(PDEVICE_EXTENSION)fdo->DeviceExtension;

    //首先要通过函数IoGetCurrentIrpStackLocation()得到当前的IRP,并由此得到Minor Function:
    PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG MinorFunction = IrpStack->MinorFunction;

    //然后把这个Minor Function传递给下一个设备栈:
    IoSkipCurrentIrpStackLocation(Irp);
    NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp);

    //处理“即插即用”次功能代码:
    //当Minor Function等于IRP_MN_REMOVE_DEVICE时,说明有设备被拔出或卸下,这时要取消资源分配并删除设备:
    if( MinorFunction==IRP_MN_REMOVE_DEVICE)
    {
        //取消设备接口:
        IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
        RtlFreeUnicodeString(&dx->ifSymLinkName);
        
        //调用IoDetachDevice()把fdo从设备栈中脱开:
        if (dx->NextStackDevice)
            IoDetachDevice(dx->NextStackDevice);
        //删除fdo:
        IoDeleteDevice(fdo);
    }

    //返回值:
    return status;
}

VOID Wdm1Unload(IN PDRIVER_OBJECT DriverObject)
{
	// Free buffer (do not need to acquire spin lock)
	if( Buffer!=NULL)
		ExFreePool(Buffer);

	DbgPrint("Wdm1Unload");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -