IO设备控制操作--DeviceIoControl

1.除了ReadFile和WirteFile以外,应用程序还可以通过另外一个API DeviceIoControl 操作设备。DeviceIoControl内部会使操作系统创建一个IRP_MJ_DEVICE_CONTROL类型的IRP,然后操作系统会将这个IRP转发到派遣函数中。


2.I/O控制码(IOCTL)一个32位值。DDK提供一个宏CTL_CODE(devicetype,Function,Method,Access)


devicetype: 设备对象类型,这个类型应和创建设备(IoCreateDevice)时的类型相匹配。一般是形如FILE_DEVICE_XX的宏。
Function:这是驱动程序定义的IOCTL  0x000-0x7FFF保留,0x800-0xfff,自己用
Method: 这个是操作模式,可以使下列4中模式:
METHOD_BUFFERED
METHOD_IN_DIRECT
METHOD_OUT_DIRECT
METHOD_NEITHER

Access: 访问权限,如果没有特殊要求,一般使用FILE_ANY_ACCESS.


控制码:

#define IOCTL_BASE        0x800
#define MY_CTL_CODE(i)                                              \
	CTL_CODE                                                        \
	(                                                               \
	FILE_DEVICE_UNKNOWN,  /* 欲控制的驱动类型 */                    \
	IOCTL_BASE + i,       /* 0x800~0xFFF是可由程序员自定义的部分 */ \
	METHOD_BUFFERED,      /* 操作模式:使用缓冲区方式操作 */        \
	FILE_ANY_ACCESS       /* 访问权限:全部 */                      \
	)
#define IOCTL_OCTRL      MY_CTL_CODE(0)
#define IOCTL_1CTRL      MY_CTL_CODE(1)

派遣函数:

NTSTATUS MyDeviceIoCtl(PDEVICE_OBJECT pDevObj,PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDevObj);
	UNREFERENCED_PARAMETER(pIrp);
	NTSTATUS  status=STATUS_SUCCESS;
	DbgPrint("Enter MyDeviceIoCtl");
	PIO_STACK_LOCATION stack=IoGetCurrentIrpStackLocation(pIrp);

	//ULONG cbIn=stack->Parameters.DeviceIoControl.InputBufferLength;
	//ULONG cbOut=stack->Parameters.DeviceIoControl.OutputBufferLength;

	//得到控制码
	ULONG code=stack->Parameters.DeviceIoControl.IoControlCode;
	switch (code)
	{
	case IOCTL_OCTRL:
		DbgPrint("IOCTL_OCTRL");
		break;
	case IOCTL_1CTRL:
		DbgPrint("IOCTL_1CTRL");
		break;
	default:
		break;
	}
	pIrp->IoStatus.Status=STATUS_SUCCESS;

	pIrp->IoStatus.Information=0;
	IoCompleteRequest(pIrp,IO_NO_INCREMENT);

	return status;
}

测试代码:

#include
using namespace std;
#include
int main()
{
	//会触发IRP_MJ_CREATE
	HANDLE hFile=CreateFile(L"\\\\.\\MyLinkDevice",
							GENERIC_READ|GENERIC_WRITE,
							0,
							NULL,
							OPEN_EXISTING,
							FILE_ATTRIBUTE_NORMAL,
							0);
	if(hFile==INVALID_HANDLE_VALUE)
		MessageBox(0,L"failed",0,0);
	int n=GetLastError();

	// 会触发IRP_MJ_DEVICE_CONTROL
	DWORD dwRead;
	DeviceIoControl(hFile,0x800,0,0,0,0,&dwRead,0);
	
	//关闭句柄会触发 IRP_MJ_CLEANUP IRP_MJ_CLOSE
	CloseHandle(hFile);
	getchar();
	return 0;
}


结果如下:

IO设备控制操作--DeviceIoControl_第1张图片




你可能感兴趣的:(内核)