Drive development will certainly encounter the application layer and the core layer of communication problems, first of all, the kernel layer and the application layer of communication can be divided into two aspects, the first is the application layer to the core layer of the active delivery message, the second is the core layer of active communication with the application layer. Below we will discuss two aspects separately.
Let's first look at how the application layer passes to the kernel layer:
BOOL DeviceIoControl (
HANDLE hdevice,//device handle
DWORD Dwiocontrolcode,//IOCTL request operation code
LPVOID Lpinbuffer,//input Buffer Address
DWORD ninbuffersize,//input buffer size
lpvoid lpoutbuffer,//Output buffer address
DWORD noutbuffersize,//output buffer size
Lpdword lpbytesreturned,//holding pointer returning byte number
lpoverlapped lpoverlapped//OVERLAPPED structure pointer for synchronous operation
;
DeviceIoControl This function is the focus of the key, almost all the application layer and the kernel layer of communication with this function, send control code directly to the specified device driver, so that the appropriate mobile device to perform the appropriate operation.
The driver can combine a Ctl_code macro to define a control code and operate the control code in the Irp_mj_device_control implementation. The control code is represented in the driver layer irpstack->parameters.deviceiocontrol.iocontrolcode.
One of the things we have to mention here is the IRP:
The IRP (IO request package) is used for Win32 and driver communication, and the NT kernel has a component called IO Manager. The IO Manager is responsible for the distribution of the IRP, when the driver creates the device and creates a good symbolic link, the WIN32 can load the driver. To allow a driver to handle the IRP, it is necessary to add an IRP processing routine to the driver.
The added method is to driverentry the inside of the drive object DriverObject the operation. The parameter is a pointer to the driver object, and a majorfunction array is inside the drive object, and the type of the array is
NTSTATUS (*pdriver_dispatch) (in Pdevice_object deviceobject,in pirp Irp). This is a function pointer that points to the processing routines for each IRP. Finally, the corresponding routines are implemented for all IRP that need to be processed.
The application layer sends instructions to the kernel layer through DeviceIoControl, and the kernel layer takes a series of actions to retrieve the data of the buffer by the judgment of the message header.
Generally speaking, there is a DeviceIoControl, the application layer to the kernel layer of the message is a relaxed and enjoyable thing, I simply put a little bit of application layer and kernel layer of code, we can do reference:
Application layer:
BOOL BOK =::D Eviceiocontrol (Hadapter, Ioctl_ptuserio_open_adapter,
pszadaptername, Nbufferlength, NULL, 0, & Dwbytesreturn, NULL);
Check results
if (!bok)
{
:: CloseHandle (hadapter);
return invalid_handle_value;
}
return hadapter;
Drive layer:
NTSTATUS Deviocontrol (pdevice_object pdeviceobject, pirp pirp)
{
//Assume failure
NTSTATUS status = Status_invalid_ Device_request;
Gets the I/O stack pointer for this IRP (PIRP)
pio_stack_location pirpstack = iogetcurrentirpstacklocation (PIRP);
Get I/O control code
ULONG Uiocontrolcode = pirpstack->parameters.deviceiocontrol.iocontrolcode;
Gets the I/O buffer pointer and its length
pvoid piobuffer = pirp->associatedirp.systembuffer;
ULONG uinsize = pirpstack->parameters.deviceiocontrol.inputbufferlength;
ULONG uoutsize = pirpstack->parameters.deviceiocontrol.outputbufferlength;
ULONG utranslen = 0;
Dbgprint ("Deviocontrol. \ n"));
Switch (Uiocontrolcode)
{
Case Ioctl_ptuserio_open_adapter://According to the control code response
{
The driver can then take data from the set buffer to operate.
The second step is to talk about how the drive layer proactively sends messages to the application layer:
In many cases, we need to drive the message to the application layer, such as we write a network card driver, which filters the delivery of packets, when the packet passed, we need to drive the message to the application layer, the simple deviceiocontrol can not be achieved, Then we can use shared events plus shared memory to implement.
Principle: Create an event by Ring3 and pass the event to RING0, Ring3 create a monitoring thread and wait for RING0 to initiate the event, which is a shared event for the application-tier drive layer. At the same time, RING0 allocates nonpaged memory in the kernel and passes it to Ring3 through DeviceIoControl, which shares memory for the application-tier drive layer. Because of the transfer of buffer in the DeviceIoControl, involves the kernel data copy, large amount of data under the use of low efficiency, so the use of shared memory method.
Application Layer Code:
M_hevent = CreateEvent (null, FALSE, FALSE, NULL); Create event
//Send event to ring 0
if (0 = = DeviceIoControl (hfile, set_event, &m_hevent, sizeof (HANDLE), NULL, 0, &uret Bytes,null))
{
CloseHandle (hfile);
CloseHandle (m_hevent);
printf ("Set_event failed\n");
return FALSE;
}
Get the ring 0 shared memory
pvoid add = NULL;
if (0 = = DeviceIoControl (hfile, Ioctl_get_share_add, NULL, 0, &add, sizeof (PVOID), &uretbytes,null))
{
closehandle (hfile);
CloseHandle (m_hevent);
return FALSE;
}
M_psharemem = (pvoid) add;
return TRUE;
while (1)
{
WaitForSingleObject (m_hevent, INFINITE);
{
<span style= "White-space:pre" > </span>//Wait for event to occur
}
}
Kernel layer:
G_psysadd = ExAllocatePool (NonPagedPool, 2048*3);
G_PMDL = ioallocatemdl (G_psysadd, 2048*3, False, False, NULL);
Mmbuildmdlfornonpagedpool (G_PMDL);//Create Shared memory
USERADDR = Mmmaplockedpagesspecifycache (g_pmdl, UserMode, NonPagedPool, NULL, FALSE, normalpagepriority);
* ((pvoid*) piobuffer) = useraddr;//transfer the drive-built memory address to the application
memset (g_psysadd,0,2048*3);
Rtlcopymemory (G_psysadd, test, (DataOffset-54) *2);//write the required data to memory
kesetevent ((pkevent) g_pevent, 0,false); Notifies the application layer that it can read
Next we can read the data in the application layer, the address is the address we get through the DeviceIoControl.