#ifndef CTL_CODE_H_89749_9961731
#define CTL_CODE_H_89749_9961731
#define CTL_BUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN,0x850,METHOD_BUFFERED,FILE_ANY_ACCESS)
//METHOD_OUT_DIRECT 该方式既可以使用输入缓冲区.也可以使用输出缓冲区
#define CTL_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN,0x851,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
#endif
此驱动为支持PNP的驱动
采用METHOD_BUFFERED方式通信时,获取的输入缓冲区可以当成输出缓冲区使用,直接写入值就可以返回给3环
而METHOD_OUT_DIRECT通信方式,输入缓冲区和输出缓冲区是不一样的,需要单独获取,才能给3环返回值
#include "Queue.h"
#include "IOCTL.h"
#include "Device.h"
#include <ntstatus.h>
//I/O内部设备控制
VOID EvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
{
KdPrint(("有io请求\n"));
PULONG Buffer = NULL;
size_t Length = 0;
switch (IoControlCode)
{
case CTL_BUFFERED:
KdPrint(("进入CTL_BUFFERED方式处理请求\n"));
//获取缓冲区
WdfRequestRetrieveInputBuffer(Request, 1,&Buffer,&Length );
if (*Buffer==0x13)
{
WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &Length);
*Buffer = 5;
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 4);
return;
}
else
{
*Buffer = 0x500;
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 4);
}
break;
case CTL_DIRECT:
//获取缓冲区
KdPrint(("进入CTL_DIRECT方式处理请求\n"));
//获取缓冲区
WdfRequestRetrieveInputBuffer(Request, 1, &Buffer, &Length);
if (*Buffer == 0x13)
{
WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &Length);
*Buffer = 5;
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 4);
return;
}
else
{
WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &Length);
*Buffer = 0x500;
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 4);
}
break;
default:
WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0);
}
}
// WDFuser.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<windows.h>
#include <stdio.h>
#include <InitGuid.h>
#include <SetupAPI.h>
#include "IOCTL.h"
#pragma comment(lib,"SetupAPI.lib")
DEFINE_GUID(WDF_GUID, 0xb184f9a, 0xe875, 0x49c2, 0xb0, 0xdc, 0xcf, 0x58, 0xa8, 0x56, 0x1f, 0x8e);
//使用VS的生成GUID工具,选择第二种方式生成。
PWCHAR GetDeviceViaInterface(const GUID* pGuid)
{
//SetupDiGetClassDevs 通过GUID找到对应的设备接口
HDEVINFO info = SetupDiGetClassDevs(pGuid,
NULL, //总线类型 虚拟设备不用管这个值
NULL, //父窗口
DIGCF_PRESENT | //设备在系统中
DIGCF_INTERFACEDEVICE); //查找的是接口
if (info == INVALID_HANDLE_VALUE)
{
printf("No HDEVINFO available for this GUID\n");
return NULL;
}
// Get interface data for the requested instance
SP_INTERFACE_DEVICE_DATA IfData;
IfData.cbSize = sizeof(IfData);
//枚举设备接口 一个驱动设备可以创建多个接口 插入一个相同设备就会创建一个设备接口.
// i 指定了多个设备中的其中一个设备序号 如果没有这个序号就会枚举失败
if (!SetupDiEnumDeviceInterfaces(info, NULL, pGuid, 0, &IfData))
{
SetupDiDestroyDeviceInfoList(info);
return NULL;
}
DWORD ReqLen;
//获取指定接口的详细信息 主要是获得ReqLen
SetupDiGetDeviceInterfaceDetail(info, &IfData, NULL, 0, &ReqLen, NULL);
//分配符号链接名长度的内存
PSP_INTERFACE_DEVICE_DETAIL_DATA IfDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)(new char[ReqLen]);
if (IfDetail == NULL)
{
SetupDiDestroyDeviceInfoList(info);
return NULL;
}
// Get symbolic link name
IfDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(info, &IfData, IfDetail, ReqLen, NULL, NULL))
{
SetupDiDestroyDeviceInfoList(info);
delete IfDetail;
return NULL;
}
printf("Symbolic link is %S\n", IfDetail->DevicePath);
return IfDetail->DevicePath;
}
int _tmain(int argc, _TCHAR* argv[])
{
PWCHAR pInterfaceLink = GetDeviceViaInterface(&WDF_GUID);
// Open file
HANDLE hDevice = CreateFile(pInterfaceLink,
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("设备接口打开失败,ErrorCode=%x", GetLastError());
return false;
}
/*
delete ifDetail;
SetupDiDestroyDeviceInfoList(info);
*/
DWORD dwRet = 0;
CHAR InBuffer[10] = { '5','3' };
DWORD InBufferSize = 10;
UCHAR OutBuffer[10] = { 0 };
DWORD OutBufferSize = 10;
DeviceIoControl(hDevice, CTL_CONVERT, InBuffer, InBufferSize,OutBuffer ,OutBufferSize, &dwRet, 0);
CloseHandle(hDevice);
if(dwRet>0)
{
printf("OutBuffer=%x\n 返回的字节数=%x", *(PUCHAR)OutBuffer,dwRet);
}
getchar();
return 0;
}