Anonymous
Тестовое приложение, вызывая Winapi Readfile в драйвер устройства, всегда возвращает код ошибки 87 (параметр неверный)
Сообщение
Anonymous » 25 июн 2025, 19:12
intro < /h2>
У меня есть это решение. < /p>
mnwe - (минимальный пример неработающего) < /h4>
Chatgpt дал мне следующее тестовое приложение: < /p>
Код: Выделить всё
#include
#include
#define DEVICE_PATH "\\\\.\\MemoryGraveyard"
#define BUFF_SIZE 1024
__declspec(align(512)) BYTE readBuffer[BUFF_SIZE];
void readWithOverlapped(HANDLE device, DWORD offset, DWORD length) {
OVERLAPPED overlapped = { 0 };
overlapped.Offset = offset;
overlapped.OffsetHigh = 0;
DWORD bytesRead = 0;
printf("[INFO] Reading with OVERLAPPED (offset: %u, length: %u)\n", offset, length);
BOOL success = ReadFile(
device,
readBuffer,
length,
&bytesRead,
&overlapped);
if (!success) {
DWORD err = GetLastError();
if (err == ERROR_IO_PENDING) {
// Wait for the async I/O to complete
if (GetOverlappedResult(device, &overlapped, &bytesRead, TRUE)) {
printf("[OK] Read %lu bytes: '%.*s'\n", bytesRead, bytesRead, readBuffer);
}
else {
printf("[ERROR] GetOverlappedResult failed: %lu\n", GetLastError());
}
}
else {
printf("[ERROR] ReadFile (OVERLAPPED) failed: %lu\n", err);
}
}
else {
printf("[OK] Read %lu bytes: '%.*s'\n", bytesRead, bytesRead, readBuffer);
}
}
void readWithSetFilePointer(HANDLE device, DWORD offset, DWORD length) {
LARGE_INTEGER li;
li.QuadPart = offset;
DWORD bytesRead = 0;
printf("[INFO] Reading with SetFilePointerEx (offset: %u, length: %u)\n", offset, length);
if (!SetFilePointerEx(device, li, NULL, FILE_BEGIN)) {
printf("[ERROR] SetFilePointerEx failed: %lu\n", GetLastError());
return;
}
BOOL success = ReadFile(
device,
readBuffer,
length,
&bytesRead,
NULL);
if (!success) {
printf("[ERROR] ReadFile failed: %lu\n", GetLastError());
return;
}
printf("[OK] Read %lu bytes: '%.*s'\n", bytesRead, bytesRead, readBuffer);
}
int main() {
HANDLE device = CreateFileA(
DEVICE_PATH,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // needed for OVERLAPPED I/O
NULL);
if (device == INVALID_HANDLE_VALUE) {
printf("[ERROR] Failed to open device: %lu\n", GetLastError());
return 1;
}
printf("[INFO] Device opened successfully.\n");
// Example usage
readWithOverlapped(device, 0, 16);
readWithSetFilePointer(device, 32, 16);
CloseHandle(device);
return 0;
}
< /code>
Излишне говорить, что я получаю: < /p>
[INFO] Device opened successfully.
[INFO] Reading with OVERLAPPED (offset: 0, length: 16)
[ERROR] ReadFile (OVERLAPPED) failed: 87
[INFO] Reading with SetFilePointerEx (offset: 32, length: 16)
[ERROR] SetFilePointerEx failed: 1
< /code>
код моего драйвера: < /p>
#include
/*
This device driver is not supposed to synchronize access to the graveyard buffer.
Also, it is not supposed to initialize the graveyard.
*/
#define BUFF_SIZE 1024
static char graveyard[BUFF_SIZE];
// Marks the Irp as completed and returns an error status for bad parameters:
static NTSTATUS badParamsReturn(PIRP Irp) {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
// Marks the Irp as completed and returns a normal status with transferred bytes:
static NTSTATUS normalReturn(PIRP Irp,
ULONG transferred = 0) {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = transferred;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
// Checks if the parameters are valid:
static bool badParams(PVOID userBuffer,
ULONGLONG offsetBytes,
ULONG lengthBytes) {
if (userBuffer == nullptr || lengthBytes == 0) return true;
// The size of the graveyard buffer:
ULONGLONG graveyardSize = sizeof(graveyard);
if (offsetBytes >= graveyardSize) {
return true;
}
return lengthBytes > graveyardSize - offsetBytes;
}
// Read handler:
static void serveReadRequest(PVOID userBuffer,
ULONGLONG offset,
ULONG length) {
RtlCopyMemory(userBuffer,
&graveyard[(size_t) offset],
length);
}
// Write handler:
static void serveWriteRequest(PVOID userBuffer,
ULONGLONG offset,
ULONG length) {
RtlCopyMemory(&graveyard[(size_t) offset],
userBuffer,
length);
}
// The read handler for the driver:
NTSTATUS MyRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) {
UNREFERENCED_PARAMETER(DeviceObject);
auto stack = IoGetCurrentIrpStackLocation(Irp);
auto length = stack->Parameters.Read.Length;
auto offset = stack->Parameters.Read.ByteOffset.QuadPart;
DbgPrint("MyRead: offset %llu, length %lu\n",
offset,
length);
PVOID userBuffer = Irp->AssociatedIrp.SystemBuffer;
if (badParams(userBuffer, offset, length)) {
return badParamsReturn(Irp);
}
serveReadRequest(userBuffer,
offset,
length);
return normalReturn(Irp,
length);
}
// The write handler for the driver:
NTSTATUS MyWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) {
UNREFERENCED_PARAMETER(DeviceObject);
auto stack = IoGetCurrentIrpStackLocation(Irp);
auto length = stack->Parameters.Write.Length;
auto offset = stack->Parameters.Write.ByteOffset.QuadPart;
DbgPrint("MyWrite: offset %llu, length %lu\n",
offset,
length);
PVOID userBuffer = Irp->AssociatedIrp.SystemBuffer;
if (badParams(userBuffer, offset, length)) {
return badParamsReturn(Irp);
}
serveWriteRequest(userBuffer,
offset,
length);
return normalReturn(Irp,
length);
}
NTSTATUS MyCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) {
UNREFERENCED_PARAMETER(DeviceObject);
return normalReturn(Irp);
}
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) {
UNICODE_STRING symbolicLink = RTL_CONSTANT_STRING(L"\\??\\MemoryGraveyard");
IoDeleteSymbolicLink(&symbolicLink);
IoDeleteDevice(DriverObject->DeviceObject);
DbgPrint("MemoryGraveyard driver unloaded.\n");
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
UNREFERENCED_PARAMETER(RegistryPath);
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(L"\\Device\\MemoryGraveyard");
UNICODE_STRING symbolicLink = RTL_CONSTANT_STRING(L"\\??\\MemoryGraveyard");
PDEVICE_OBJECT DeviceObject = nullptr;
NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(status)) return status;
//DriverObject->Flags |= DO_BUFFERED_IO;
status = IoCreateSymbolicLink(&symbolicLink, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(DeviceObject);
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = MyRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite;
DriverObject->DriverUnload = DriverUnload;
DbgPrint("MemoryGraveyard driver loaded.\n");
return STATUS_SUCCESS;
}
in driverentry , я установил DriverObject-> Flags | = do_buffered_io; .
Итак, я полагаю, что ошибка находится в длине /
Параметры, но я понятия не имею, как решить эту проблему. Есть помощь?
Подробнее здесь:
https://stackoverflow.com/questions/796 ... error-code
1750867920
Anonymous
intro < /h2> У меня есть это решение. < /p> mnwe - (минимальный пример неработающего) < /h4> Chatgpt дал мне следующее тестовое приложение: < /p> [code]#include #include #define DEVICE_PATH "\\\\.\\MemoryGraveyard" #define BUFF_SIZE 1024 __declspec(align(512)) BYTE readBuffer[BUFF_SIZE]; void readWithOverlapped(HANDLE device, DWORD offset, DWORD length) { OVERLAPPED overlapped = { 0 }; overlapped.Offset = offset; overlapped.OffsetHigh = 0; DWORD bytesRead = 0; printf("[INFO] Reading with OVERLAPPED (offset: %u, length: %u)\n", offset, length); BOOL success = ReadFile( device, readBuffer, length, &bytesRead, &overlapped); if (!success) { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) { // Wait for the async I/O to complete if (GetOverlappedResult(device, &overlapped, &bytesRead, TRUE)) { printf("[OK] Read %lu bytes: '%.*s'\n", bytesRead, bytesRead, readBuffer); } else { printf("[ERROR] GetOverlappedResult failed: %lu\n", GetLastError()); } } else { printf("[ERROR] ReadFile (OVERLAPPED) failed: %lu\n", err); } } else { printf("[OK] Read %lu bytes: '%.*s'\n", bytesRead, bytesRead, readBuffer); } } void readWithSetFilePointer(HANDLE device, DWORD offset, DWORD length) { LARGE_INTEGER li; li.QuadPart = offset; DWORD bytesRead = 0; printf("[INFO] Reading with SetFilePointerEx (offset: %u, length: %u)\n", offset, length); if (!SetFilePointerEx(device, li, NULL, FILE_BEGIN)) { printf("[ERROR] SetFilePointerEx failed: %lu\n", GetLastError()); return; } BOOL success = ReadFile( device, readBuffer, length, &bytesRead, NULL); if (!success) { printf("[ERROR] ReadFile failed: %lu\n", GetLastError()); return; } printf("[OK] Read %lu bytes: '%.*s'\n", bytesRead, bytesRead, readBuffer); } int main() { HANDLE device = CreateFileA( DEVICE_PATH, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // needed for OVERLAPPED I/O NULL); if (device == INVALID_HANDLE_VALUE) { printf("[ERROR] Failed to open device: %lu\n", GetLastError()); return 1; } printf("[INFO] Device opened successfully.\n"); // Example usage readWithOverlapped(device, 0, 16); readWithSetFilePointer(device, 32, 16); CloseHandle(device); return 0; } < /code> Излишне говорить, что я получаю: < /p> [INFO] Device opened successfully. [INFO] Reading with OVERLAPPED (offset: 0, length: 16) [ERROR] ReadFile (OVERLAPPED) failed: 87 [INFO] Reading with SetFilePointerEx (offset: 32, length: 16) [ERROR] SetFilePointerEx failed: 1 < /code> код моего драйвера: < /p> #include /* This device driver is not supposed to synchronize access to the graveyard buffer. Also, it is not supposed to initialize the graveyard. */ #define BUFF_SIZE 1024 static char graveyard[BUFF_SIZE]; // Marks the Irp as completed and returns an error status for bad parameters: static NTSTATUS badParamsReturn(PIRP Irp) { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_PARAMETER; } // Marks the Irp as completed and returns a normal status with transferred bytes: static NTSTATUS normalReturn(PIRP Irp, ULONG transferred = 0) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = transferred; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } // Checks if the parameters are valid: static bool badParams(PVOID userBuffer, ULONGLONG offsetBytes, ULONG lengthBytes) { if (userBuffer == nullptr || lengthBytes == 0) return true; // The size of the graveyard buffer: ULONGLONG graveyardSize = sizeof(graveyard); if (offsetBytes >= graveyardSize) { return true; } return lengthBytes > graveyardSize - offsetBytes; } // Read handler: static void serveReadRequest(PVOID userBuffer, ULONGLONG offset, ULONG length) { RtlCopyMemory(userBuffer, &graveyard[(size_t) offset], length); } // Write handler: static void serveWriteRequest(PVOID userBuffer, ULONGLONG offset, ULONG length) { RtlCopyMemory(&graveyard[(size_t) offset], userBuffer, length); } // The read handler for the driver: NTSTATUS MyRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { UNREFERENCED_PARAMETER(DeviceObject); auto stack = IoGetCurrentIrpStackLocation(Irp); auto length = stack->Parameters.Read.Length; auto offset = stack->Parameters.Read.ByteOffset.QuadPart; DbgPrint("MyRead: offset %llu, length %lu\n", offset, length); PVOID userBuffer = Irp->AssociatedIrp.SystemBuffer; if (badParams(userBuffer, offset, length)) { return badParamsReturn(Irp); } serveReadRequest(userBuffer, offset, length); return normalReturn(Irp, length); } // The write handler for the driver: NTSTATUS MyWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { UNREFERENCED_PARAMETER(DeviceObject); auto stack = IoGetCurrentIrpStackLocation(Irp); auto length = stack->Parameters.Write.Length; auto offset = stack->Parameters.Write.ByteOffset.QuadPart; DbgPrint("MyWrite: offset %llu, length %lu\n", offset, length); PVOID userBuffer = Irp->AssociatedIrp.SystemBuffer; if (badParams(userBuffer, offset, length)) { return badParamsReturn(Irp); } serveWriteRequest(userBuffer, offset, length); return normalReturn(Irp, length); } NTSTATUS MyCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { UNREFERENCED_PARAMETER(DeviceObject); return normalReturn(Irp); } VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING symbolicLink = RTL_CONSTANT_STRING(L"\\??\\MemoryGraveyard"); IoDeleteSymbolicLink(&symbolicLink); IoDeleteDevice(DriverObject->DeviceObject); DbgPrint("MemoryGraveyard driver unloaded.\n"); } extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); UNICODE_STRING deviceName = RTL_CONSTANT_STRING(L"\\Device\\MemoryGraveyard"); UNICODE_STRING symbolicLink = RTL_CONSTANT_STRING(L"\\??\\MemoryGraveyard"); PDEVICE_OBJECT DeviceObject = nullptr; NTSTATUS status = IoCreateDevice( DriverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) return status; //DriverObject->Flags |= DO_BUFFERED_IO; status = IoCreateSymbolicLink(&symbolicLink, &deviceName); if (!NT_SUCCESS(status)) { IoDeleteDevice(DeviceObject); return status; } DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyCreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = MyRead; DriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite; DriverObject->DriverUnload = DriverUnload; DbgPrint("MemoryGraveyard driver loaded.\n"); return STATUS_SUCCESS; } [/code] in driverentry , я установил DriverObject-> Flags | = do_buffered_io; . Итак, я полагаю, что ошибка находится в длине /[code]offset[/code] Параметры, но я понятия не имею, как решить эту проблему. Есть помощь? Подробнее здесь: [url]https://stackoverflow.com/questions/79678473/a-test-app-calling-winapi-readfile-to-a-device-driver-always-returns-error-code[/url]