当用户模式的程序调用驱动的时候,怎么传递数据呢?
通常用户模式程序和驱动的数据交互有3种办法:buffer方式,direct方式和其他方式。可以看之前我写的WDM驱动模型:http://blog.csdn.net/zj510/article/details/8212032
那么在WDF里面又如何操作呢?我们考虑给WDF驱动增加一个功能:将WRITE请求的数据写入设备对象上下文,然后当READ请求过来的时候,将设备对象上下文里面的数据读出来并且返回给用户模式程序。
WdfRequestRetrieveInputBuffer和WdfRequestRetrieveOutputBuffer函数
WDF提供了2个函数,这2个函数可以获得请求的输入输出缓冲。READ请求只有OutputBuffer,WRITE请求只有InputBuffer. IO control请求同时拥有输入输出缓冲。
比如
char* in_buf = NULL;
WdfRequestRetrieveInputBuffer(Request, 10, &in_buf, NULL);
通过上面的代码,可以获得Request的输入请求,in_buf是一个指针,如果函数调用成功的话,那么in_buf将指向一个输入缓冲。in_buf指向一个内核模式下的地址。我们可以直接使用这个指针,比如读取或者写入数据。
如果是READ请求的话,上面的函数会失败,因为READ请求是没有输入缓冲的。如果是WRITE请求的话,那么就可以成功获取输入缓冲。
实现一个写入读取的功能
这里给驱动增加一个简单的功能,将WRITE请求的数据写入设备上下文,然后当有READ请求过来的时候,将设备上下文里面的数据读出来,并且存入READ请求的输出缓冲。代码如下:
static VOID EvtIoPDPControlDevice( WDFQUEUE Queue , WDFREQUEST Request )
{
WDF_REQUEST_PARAMETERS Params;
WDFREQUEST req;
NTSTATUS status;
WDFDEVICE hDevice;
DEVICE_CONTEXT* dev_ctx = NULL;
//buffer
char* in_buf = NULL;
char* out_buf = NULL;
//获取请求的参数
WDF_REQUEST_PARAMETERS_INIT(&Params);
WdfRequestGetParameters(Request,&Params);
KdPrint(("EvtIoPDPControlDevice, type: %x\n", Params.Type));
status = WdfRequestRetrieveInputBuffer(Request, 10, &in_buf, NULL);
KdPrint(("Get input buffer, ret: %x, buffer: %x", status, in_buf));
status = WdfRequestRetrieveOutputBuffer(Request, 10, &out_buf, NULL);
KdPrint(("Get output buffer, ret: %x, buffer: %x", status, out_buf));
//获得Queue关联的设备对象
hDevice = WdfIoQueueGetDevice(Queue);
//获得设备对象的上下文
dev_ctx = WdfObjectGetTypedContext(hDevice, DEVICE_CONTEXT);
KdPrint(("Get the context of current device, %x", dev_ctx));
switch(Params.Type)
{
case WdfRequestTypeRead:
{
if(out_buf != NULL)
{
out_buf[0] = '1';
KdPrint(("write the data in context buffer into READ request\n"));
//将设备对象上下文里面的数据返回给用户模式程序
RtlCopyMemory(out_buf, dev_ctx->_Buffer, 10);
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 10);
}
}
break;
case WdfRequestTypeWrite:
{
if(in_buf != NULL)
{
KdPrint