派遣函数学习1)缓冲区方式读写


符号   \??\HelloDDK    -》\\.\

\??\HelloDDK ->\\.\HelloDDK   ->  C语言字符串   \\\\.\\HelloDDK

HANDLE hDevice = 
		CreateFile("\\\\.\\HelloDDK",
					GENERIC_READ | GENERIC_WRITE,
					0,		// share mode none
					NULL,	// no security
					OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL,
					NULL );		// no template

	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("Failed to obtain file handle to device: "
			"%s with Win32 error code: %d\n",
			"MyWDMDevice", GetLastError() );
		return 1;
	}

	CloseHandle(hDevice);//触发MJ_CLEANUP  MJ_CLOSE
设备对象一共有3中读写方式:

1)缓冲区方式读写

	//创建设备
	status = IoCreateDevice( pDriverObject,
						sizeof(DEVICE_EXTENSION),
						&(UNICODE_STRING)devName,
						FILE_DEVICE_UNKNOWN,
						0, TRUE,
						&pDevObj );
	if (!NT_SUCCESS(status))
		return status;

	pDevObj->Flags |= DO_BUFFERED_IO;

用程序提供缓冲区的数据复制到内核模式下的中,无论操作系统怎么切换,内核模式地址都不会改变

缺点:   影响了运行效率

下面为 利用缓冲区 方式读设备:(写入数据   

pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;

IRP_MJ_READ  的派遣函数主要任务是把任务断的数据复制到AssociatedIrp.SystemBuffer


NTSTATUS HelloDDKRead(IN PDEV0CE_OBJECT pDevObj,
								 IN PIRP pIrp) 
{
	KdPrint(("Enter HelloDDKRead\n"));

	//对一般IRP的简单操作,后面会介绍对IRP更复杂的操作
	NTSTATUS status = STATUS_SUCCESS;

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
	ULONG ulReadLength = stack->Parameters.Read.Length;
	
	// 完成IRP
	//设置IRP完成状态
	pIrp->IoStatus.Status = status;

	//设置IRP操作了多少字节
	pIrp->IoStatus.Information = ulReadLength;	// bytes xfered

	memset(pIrp->AssociatedIrp.SystemBuffer,0xAA,ulReadLength);

	//处理IRP
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );

	KdPrint(("Leave HelloDDKRead\n"));

	return status;
}

下面为 程序 读取

	HANDLE hDevice = 
		CreateFile("\\\\.\\HelloDDK",
					GENERIC_READ | GENERIC_WRITE,
					0,		// share mode none
					NULL,	// no security
					OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL,
					NULL );		// no template


	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("Failed to obtain file handle to device: "
			"%s with Win32 error code: %d\n",
			"MyWDMDevice", GetLastError() );
		return 1;
	}


	UCHAR buffer[10];
	ULONG ulRead;
	BOOL bRet = ReadFile(hDevice,buffer,10,&ulRead,NULL);
	if (bRet)
	{
		printf("Read %d bytes:",ulRead);
		for (int i=0;i<(int)ulRead;i++)
		{
			printf("%02X ",buffer[i]);
		}


		printf("\n");
	}


	CloseHandle(hDevice);
	return 0;

下面是程序写入设备 WriteFile 内部产生 IRP_MJ_WRITE 类型的IRP

派遣函数需要将传送进来的数据保存起来,以便读取该设备的时候读取

NTSTATUS HelloDDKWrite(IN PDEVICE_OBJECT pDevObj,
					  IN PIRP pIrp) 
{
	KdPrint(("Enter HelloDDKWrite\n"));
	
	//对一般IRP的简单操作,后面会介绍对IRP更复杂的操作
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
	ULONG ulWriteLength = stack->Parameters.Write.Length;
	
	ULONG ulWriteOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart;

	if (ulWriteOffset + ulWriteLength > 1024)
	{
		status = STATUS_FILE_INVALID;
		ulWriteOffset = 0;
	}
	else
	{
		memcpy(pDevExt->buffer+ulWriteOffset,\
			pIrp->AssociatedIrp.SystemBuffer,\
			ulWriteLength);
		status = STATUS_SUCCESS;
		if (ulWriteLength + ulWriteOffset > pDevExt->File_length)
		{
			pDevExt->File_length = ulWriteLength + ulWriteOffset;
		}
	}
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = ulWriteLength;

	//处理IRP
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	
	KdPrint(("Leave HelloDDKWrite\n"));
	
	return status;
}




















转载于:https://www.cnblogs.com/zcc1414/p/3982513.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值