Application layer and driver layer communication DeviceIoControl

The communication between the driver layer and the application layer is through DeviceIoControl,

First, the driver layer needs to implement:

pDriverObject->DriverUnload = MyDriverUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreate;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = MyClose;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDispatchDeviceControl;

Where MyDispatchDeviceControl is used to communicate with the application layer through DeviceIoControl

NTSTATUS
MyDispatchDeviceControl(
 IN PDEVICE_OBJECT DeviceObject,
 IN PIRP Irp
 )
{
NTSTATUS             status = STATUS_SUCCESS;
PVOID                context;
KEVENT waitEvent;
PIO_STACK_LOCATION   irpSp;
ULONG ioControlCode = 0;


PAGED_CODE();


//DbgPrint(("MyDispatchDeviceControlbegin \n"));


//if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) 
//{
//
//}


DbgPrint("%s begin... \r\n", __FUNCTION__);


irpSp = IoGetCurrentIrpStackLocation (Irp);


//control code
ioControlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;


DbgPrint("[%d, %d] \r\n", irpSp->MajorFunction, irpSp->MinorFunction);


switch(ioControlCode)
{
case 4096://4096 just temporarily defines a value
{
DbgPrint("get iocontrol code %x \r\n", 
ioControlCode);

//Input buffer size, buffer data, if the application layer passes in more than a simple string, it is best to print hexadecimal instead of %s
DbgPrint("in: size %d [%s] \r\n", 
irpSp->Parameters.DeviceIoControl.InputBufferLength,
Irp-> AssociatedIrp.SystemBuffer);


//Assign the input buffer and set its size,
RtlCopyMemory((char*)Irp->AssociatedIrp.SystemBuffer, "i get it", strlen("i get it"));
Irp-> IoStatus.Information = strlen ((char *) Irp-> AssociatedIrp.SystemBuffer) + 1;

//Print the output data, which can be compared with the data obtained by the application layer
DbgPrint("out : size %d [%s] \r\n", 
Irp-> IoStatus.Information, 
Irp-> AssociatedIrp.SystemBuffer);
}
break;
default:
{
DbgPrint("unknow control code \r\n");
}
break;
}


Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (Irp, IO_NO_INCREMENT);


return status;
}

Then the application layer needs to open the device link symbol of the driver layer to get the handle, and the communication of DeviceIoControl depends on the handle

void TestDriver()
{
FILE               *pFile = NULL;
HANDLE             hDevice = INVALID_HANDLE_VALUE;
DWORD              retCount = 0;
char               szControl[100];
char               szRet[100];


hDevice = CreateFile(SYMBOLLINK_NAME,  
GENERIC_WRITE | GENERIC_READ,  
FILE_SHARE_WRITE|FILE_SHARE_READ,  
NULL,  
OPEN_EXISTING,  
FILE_ATTRIBUTE_NORMAL,  
NULL);  


if( hDevice != INVALID_HANDLE_VALUE )  
{
_tprintf(_T("Create Device %s ok ! \r\n"), SYMBOLLINK_NAME);  
}
else  
{
_tprintf(_T("Create Device %s faild %d ! \r\n"), SYMBOLLINK_NAME, GetLastError() );


return;
 }


do 
{


scanf("%s", szControl);
//strcpy(szControl, "hello world");

//retCount = 100;

//4096 just temporarily defines a value
DeviceIoControl(hDevice, 4096, szControl, strlen(szControl), szRet, sizeof(szRet), &retCount, NULL);

// Print the data returned by the driver layer, which can be compared with the internal printing of the driver layer
_tprintf(_T("device io control done\r\n"));
printf("get %d %s \r\n", retCount, szRet);


if ('q' == szControl[0])
{
break;
}


} while (1);


CloseHandle( hDevice );
}





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325553418&siteId=291194637