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 );
}