This document describes how to use ctl_code to communicate with a Windows NT driver. generally, user-Mode Applications can communicate with kernel-mode drivers by calling createfile and deviceiocontrol, if a driver in the kernel state wants to perform similar operations with another driver, how can this problem be achieved? Next, we will provide a detailed description.
The main idea is to first get the handle of another driver, then construct an IRP, assign necessary parameters, and then send this IRP to another driver, wait for another driver to obtain the returned data after processing.
The Code is as follows:
Pirp smbirp;
Pio_stack_location irpstack;
Rtlinitunicodestring (& usdevicetofilter, l "\ device \ advsmbus ");
Status = iogetdeviceobjectpointer (& usdevicetofilter,
File_write_data, & smbusobject, & g_lm87data.smbhc );
If (! Nt_success (Status ))
{
Kdprint ("lm87: Can't Get SMBus host! "));
}
Smbirp = ioallocateirp (g_lm87data.smbhc-> stacksize, false );
If (! Smbirp)
{
Kdprint ("lm87: allocate IRP failed! "));
}
Irpstack = iogetnextirpstacklocation (smbirp );
G_lm87data.smbushostdata.address = lm87_smbus_address;
G_lm87data.smbushostdata.offset = lm87_inter_temp_register;
G_lm87data.smbushostdata.data = 0x0;
Irpstack-> majorfunction = irp_mj_device_control;
Irpstack-> parameters. deviceiocontrol. iocontrolcode = ioctl_smbus_read_byte;
Irpstack-> parameters. deviceiocontrol. inputbufferlength = sizeof (smbus_host );
Irpstack-> parameters. deviceiocontrol. outputbufferlength = sizeof (smbus_host );
Smbirp-> associatedirp. systembuffer = & g_lm87data.smbushostdata;
Iosetcompletionroutine (smbirp, lm87requestcomplete, & g_lm87data.syncevent, true );
Iocalldriver (g_lm87data.smbhc, smbirp );
Kewaitforsingleobject (& g_lm87data.syncevent, executive, kernelmode, false, null );
Kdprint ("lm87: query result is [% x]", g_lm87data.smbushostdata.data ));
Result [1] = g_lm87data.smbushostdata.data * 10; // compatible with diaganywhere
Iofreeirp (smbirp );
In the above Code, we first useIogetdeviceobjectpointer obtains the handle of another driver.,
Then an IRP is generated using ioallocateirp.,After necessary parameters are assigned, send them to another driver through iocalldriver.Note that there is an iosetcompletionroution call before iocalldriver. When another driver finishes processing this IRP, it enters the roution it sets, through an event, we know that the IRP has been processed and we can get the desired data.
Ideas:
Step 1: iogetdeviceobjectpointer to get the handle of another driver
Step 2: Use ioallocateirp to generate an IRP
Step 3: Send the required parameters to another driver through iocalldriver
Note:
Iosetcompletionroution is called before iocalldriver. When another driver finishes processing this IRP, it enters the roution it sets. Through an event, we know that the IRP has been processed, we can get the desired data.
Ntstatus
Lm87requestcomplete (
In pdevice_object deviceobject,
In pirp,
In pvoid Context
)
{
Pkevent event;
Event = (pkevent) context;
Kesetevent (event, io_no_increment, false );
Return status_more_processing_required;
}
In this way, the communication between a driver in the kernel state and another driver is realized.
Another method is to implement workitem and iobuilddeviceiocontrolrequest. We will not detail it here.