如何在 Driver.c controlFunction 接收使用 DeviceIoControl 发送的数据? IOCTL,驱动程序
How to receive data send with DeviceIoControl at the Driver.c controlFunction? IOCTL,Driver
假设我有以下代码。加载、卸载、驱动程序输入等工作。
Driver.c
#define IO_INCREMENT_VALUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_RECEIVE_RANDOM_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
ULONG BytesIO = 0;
const IO_STACK_LOCATION stack = *IoGetCurrentIrpStackLocation(Irp);
const ULONG ControlCode = stack.Parameters.DeviceIoControl.IoControlCode;
if (ControlCode == IO_INCREMENT_VALUE)
{
//How to receive LPVOID lpInBuffer,
// DWORD nInBufferSize,
// LPVOID lpOutBuffer,
// DWORD nOutBufferSize,
//send from DeviceIoControl
}
else if (ControlCode == IO_RECEIVE_RANDOM_BUFFER)
{
//How to receive LPVOID lpInBuffer,
// DWORD nInBufferSize,
// LPVOID lpOutBuffer,
// DWORD nOutBufferSize,
// /send from DeviceIoControl
/*
DWORD nOutBufferSize = ;
for(DWORD i = 0; i< nOutBufferSize; ++i)
{
}
*/
}
// Complete the request
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesIO;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
及以下 UserMode.cpp
constexpr auto IO_INCREMENT_VALUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS);
constexpr auto IO_RECEIVE_RANDOM_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS);
int main()
{
//Find our Driver we want to Communicate with
//https://docs.microsoft.com/de-de/windows/win32/api/fileapi/nf-fileapi-createfilea
const LPCSTR lpFileName = R"(\.\test)"; //Equals the Name we specified at DriverEntry
const DWORD dwDesiredAccess = GENERIC_ALL;
const DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
const LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr;
const DWORD dwCreationDisposition = OPEN_EXISTING;
const DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
const HANDLE hTemplateFile = nullptr;
const HANDLE driver = CreateFile(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
);
if (driver == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
//Example 1: Send an uint64_t and receive the value + 1.
uint64_t in_example1 = 1;
uint64_t out_example1 = 0;
LPDWORD lpBytesReturned = nullptr;
DeviceIoControl(driver, IO_INCREMENT_VALUE, &in_example1,
sizeof(in_example1), &out_example1, sizeof(out_example1), lpBytesReturned, nullptr);
std::cout << out_example1 << "\n"; //should return 2
//Example 2: Get a buffer with random values. Should be later the readMemory()
const UINT_PTR bytes_to_be_read = 357096;
//Any Buffer should be possible
char* data = new char[bytes_to_be_read];
uint64_t* data2 = new uint64_t[bytes_to_be_read];
DeviceIoControl(driver, IO_RECEIVE_RANDOM_BUFFER, nullptr,
0, data, bytes_to_be_read, lpBytesReturned, nullptr);
//should return data or data2 with some random values
}
"The DeviceIoControl function provides a device input and output control (IOCTL) interface through which an application can communicate directly with a device driver."
但是我如何接收
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
从 Driver.c I/O 函数内的 DeviceIoControl 发送?
完整度:
使用的链接:
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp
https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_stack_location
IO_STACK_LOCATION 仅提供对
的访问
Parameters.DeviceIoControl
Parameters.DeviceIoControl.OutputBufferLength
Parameters.DeviceIoControl.InputBufferLength
Parameters.DeviceIoControl.IoControlCode
Parameters.DeviceIoControl.Type3InputBuffer
通过使用 Buffer I/O 方法,I/O 管理器将输入缓冲区分配给 non-paged 池并将指向该内存的指针存储在 Irp->AssociatedIrp.SystemBuffer
中,然后 IoContorl
将开始。
稍后,当请求完成时,I/O 管理器获取 SystemBuffer
并将字节数(根据 Irp->IoStatus.Information
)复制到输出缓冲区。
话虽如此,这是解决方案:
#define IO_INCREMENT_VALUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_RECEIVE_RANDOM_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
ULONG BytesIO = 0;
const IO_STACK_LOCATION stack = *IoGetCurrentIrpStackLocation(Irp);
const ULONG ControlCode = stack.Parameters.DeviceIoControl.IoControlCode;
if (ControlCode == IO_INCREMENT_VALUE)
{
// Check input buffer size
ULONG bytes = stack.Parameters.DeviceIoControl.InputBufferLength;
if (bytes < sizeof(long long)) {
// Error - should complete the request
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Must return the same value as Irp.IoStatus.Status
return STATUS_INVALID_BUFFER_SIZE;
}
long long* input = (long long*)Irp->AssociatedIrp.SystemBuffer;
InterlockedAdd64(input, 1);
// Same SystemBuffer is used for input and output so we just need
// to complete the request with the appropriate bytes written.
Status = STATUS_SUCCESS;
BytesIO = sizeof(*input);
}
else if (ControlCode == IO_RECEIVE_RANDOM_BUFFER)
{
// Check input buffer size
ULONG bytes = stack.Parameters.DeviceIoControl.InputBufferLength;
if (bytes == 0) {
// Error - should complete the request
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Must return the same value as Irp.IoStatus.Status
return STATUS_INVALID_BUFFER_SIZE;
}
PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
memset(buffer, 0, bytes);
Status = STATUS_SUCCESS;
BytesIO = bytes;
}
// Complete the request
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesIO;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
假设我有以下代码。加载、卸载、驱动程序输入等工作。
Driver.c
#define IO_INCREMENT_VALUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_RECEIVE_RANDOM_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
ULONG BytesIO = 0;
const IO_STACK_LOCATION stack = *IoGetCurrentIrpStackLocation(Irp);
const ULONG ControlCode = stack.Parameters.DeviceIoControl.IoControlCode;
if (ControlCode == IO_INCREMENT_VALUE)
{
//How to receive LPVOID lpInBuffer,
// DWORD nInBufferSize,
// LPVOID lpOutBuffer,
// DWORD nOutBufferSize,
//send from DeviceIoControl
}
else if (ControlCode == IO_RECEIVE_RANDOM_BUFFER)
{
//How to receive LPVOID lpInBuffer,
// DWORD nInBufferSize,
// LPVOID lpOutBuffer,
// DWORD nOutBufferSize,
// /send from DeviceIoControl
/*
DWORD nOutBufferSize = ;
for(DWORD i = 0; i< nOutBufferSize; ++i)
{
}
*/
}
// Complete the request
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesIO;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
及以下 UserMode.cpp
constexpr auto IO_INCREMENT_VALUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS);
constexpr auto IO_RECEIVE_RANDOM_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS);
int main()
{
//Find our Driver we want to Communicate with
//https://docs.microsoft.com/de-de/windows/win32/api/fileapi/nf-fileapi-createfilea
const LPCSTR lpFileName = R"(\.\test)"; //Equals the Name we specified at DriverEntry
const DWORD dwDesiredAccess = GENERIC_ALL;
const DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
const LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr;
const DWORD dwCreationDisposition = OPEN_EXISTING;
const DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
const HANDLE hTemplateFile = nullptr;
const HANDLE driver = CreateFile(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
);
if (driver == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
//Example 1: Send an uint64_t and receive the value + 1.
uint64_t in_example1 = 1;
uint64_t out_example1 = 0;
LPDWORD lpBytesReturned = nullptr;
DeviceIoControl(driver, IO_INCREMENT_VALUE, &in_example1,
sizeof(in_example1), &out_example1, sizeof(out_example1), lpBytesReturned, nullptr);
std::cout << out_example1 << "\n"; //should return 2
//Example 2: Get a buffer with random values. Should be later the readMemory()
const UINT_PTR bytes_to_be_read = 357096;
//Any Buffer should be possible
char* data = new char[bytes_to_be_read];
uint64_t* data2 = new uint64_t[bytes_to_be_read];
DeviceIoControl(driver, IO_RECEIVE_RANDOM_BUFFER, nullptr,
0, data, bytes_to_be_read, lpBytesReturned, nullptr);
//should return data or data2 with some random values
}
"The DeviceIoControl function provides a device input and output control (IOCTL) interface through which an application can communicate directly with a device driver."
但是我如何接收
LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
从 Driver.c I/O 函数内的 DeviceIoControl 发送?
完整度:
使用的链接:
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp
https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_stack_location
IO_STACK_LOCATION 仅提供对
的访问Parameters.DeviceIoControl
Parameters.DeviceIoControl.OutputBufferLength
Parameters.DeviceIoControl.InputBufferLength
Parameters.DeviceIoControl.IoControlCode
Parameters.DeviceIoControl.Type3InputBuffer
通过使用 Buffer I/O 方法,I/O 管理器将输入缓冲区分配给 non-paged 池并将指向该内存的指针存储在 Irp->AssociatedIrp.SystemBuffer
中,然后 IoContorl
将开始。
稍后,当请求完成时,I/O 管理器获取 SystemBuffer
并将字节数(根据 Irp->IoStatus.Information
)复制到输出缓冲区。
话虽如此,这是解决方案:
#define IO_INCREMENT_VALUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_RECEIVE_RANDOM_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
ULONG BytesIO = 0;
const IO_STACK_LOCATION stack = *IoGetCurrentIrpStackLocation(Irp);
const ULONG ControlCode = stack.Parameters.DeviceIoControl.IoControlCode;
if (ControlCode == IO_INCREMENT_VALUE)
{
// Check input buffer size
ULONG bytes = stack.Parameters.DeviceIoControl.InputBufferLength;
if (bytes < sizeof(long long)) {
// Error - should complete the request
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Must return the same value as Irp.IoStatus.Status
return STATUS_INVALID_BUFFER_SIZE;
}
long long* input = (long long*)Irp->AssociatedIrp.SystemBuffer;
InterlockedAdd64(input, 1);
// Same SystemBuffer is used for input and output so we just need
// to complete the request with the appropriate bytes written.
Status = STATUS_SUCCESS;
BytesIO = sizeof(*input);
}
else if (ControlCode == IO_RECEIVE_RANDOM_BUFFER)
{
// Check input buffer size
ULONG bytes = stack.Parameters.DeviceIoControl.InputBufferLength;
if (bytes == 0) {
// Error - should complete the request
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Must return the same value as Irp.IoStatus.Status
return STATUS_INVALID_BUFFER_SIZE;
}
PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
memset(buffer, 0, bytes);
Status = STATUS_SUCCESS;
BytesIO = bytes;
}
// Complete the request
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesIO;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}