无法通过 CreateFile 打开设备,ERROR_INVALID_FUNCTION

Posted

技术标签:

【中文标题】无法通过 CreateFile 打开设备,ERROR_INVALID_FUNCTION【英文标题】:Can`t open device by CreateFile, ERROR_INVALID_FUNCTION 【发布时间】:2017-11-04 21:04:00 【问题描述】:

我尝试通过 CreateFile 和 DeviceIoControl 打开设备对象并向我的驱动程序发送请求,但 CreateFile 失败并显示 ERROR_INVALID_FUNCTION,如果我尝试在 WinObj 中打开设备 - 我也会遇到同样的错误,那么如何解决这个问题以及是什么是什么意思?

test_driver.c

#include "test_driver.h"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 
    NTSTATUS status;
    PDEVICE_OBJECT deviceObject;
    UNICODE_STRING dNameString, dLinkString;

    RtlInitUnicodeString(&dNameString, NT_DEVICE_NAME);
    status = IoCreateDevice(DriverObject, sizeof(65533), &dNameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);

    if (!NT_SUCCESS(status)) 
        return status;
    

    RtlInitUnicodeString(&dLinkString, DOS_DEVICE_NAME);
    status = IoCreateSymbolicLink(&dLinkString, &dNameString);

    if (!NT_SUCCESS(status)) 
        IoDeleteDevice(deviceObject);
        return status;
    

    DriverObject -> MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDeviceControl;
    DriverObject -> DriverUnload = DriverUnload;

    DbgPrint("Driver loaded!");
    return STATUS_SUCCESS;


NTSTATUS DriverDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
    ULONG ioControlCode;
    PULONG ioBuffer;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);

    ioBuffer = Irp -> AssociatedIrp.SystemBuffer;
    ioControlCode = irpStack -> Parameters.DeviceIoControl.IoControlCode;
    Irp -> iostatus.Status = STATUS_SUCCESS;
    Irp -> IoStatus.Information = 0;

    switch (ioControlCode) 
        case TEST_SMTH:
            ioBuffer[0] = (ULONG)DriverEntry;
            Irp -> IoStatus.Information = 4;
            break;

        default:
            Irp -> IoStatus.Status = STATUS_INVALID_PARAMETER;
            break;
    

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    DbgPrint("Request complete!");
    return Irp -> IoStatus.Status;


VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) 
    UNICODE_STRING dLinkString;

    RtlInitUnicodeString(&dLinkString, DOS_DEVICE_NAME);
    IoDeleteSymbolicLink(&dLinkString);
    IoDeleteDevice(DriverObject -> DeviceObject);
    DbgPrint("Driver unloaded!");

test_driver.h

#include <ntddk.h>

#define NT_DEVICE_NAME  L"\\Device\\testDrv" 
#define DOS_DEVICE_NAME L"\\DosDevices\\testDrv"

#define FIRST_IOCTL_INDEX 0x800
#define FILE_DEVICE_testDRV 0x00008000
#define TEST_SMTH CTL_CODE(FILE_DEVICE_testDRV, FIRST_IOCTL_INDEX + 101, METHOD_BUFFERED, FILE_ANY_ACCESS)

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS DriverDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);

来自程序来源:

HANDLE device = CreateFile("\\\\.\\testDrv", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

我知道要从 NT 空间打开对象,必须使用 NtCreateFile,但我在驱动程序中创建了一个符号链接,因此 CreateFile 必须运行良好。

【问题讨论】:

Eerrr .. 您的错误在您的测试程序中,但您没有共享代码。你是什​​么意思你创建了一个 symbolic link ?你的意思是弱符号 你想要什么?你没有设置DriverObject -&gt; MajorFunction[IRP_MJ_CREATE]。默认处理程序返回 STATUS_INVALID_DEVICE_REQUEST 转换为 ERROR_INVALID_FUNCTION 我不知道有必要,正如我从一些文章中了解到的那样。我添加了 IRP_MJ_CREATE 和 IRP_MJ_CLOSE 函数,它可以工作,谢谢。我的意思是我通过 IoCreateSymbolicLink 为设备名称创建了链接。 你还需要IRP_MJ_CLEANUP sizeof(65533)代替4有什么意义? 【参考方案1】:

当有人尝试在设备DeviceObject 上打开文件时,会调用DeviceObject-&gt;DriverObject-&gt;MajorFunction[IRP_MJ_CREATE]。现在的问题——这点在哪里?你不要改变这个单元格。你只初始化IRP_MJ_DEVICE_CONTROL 单元格。结果称为默认处理程序 - IopInvalidDeviceRequest。此例程只需完成状态为STATUS_INVALID_DEVICE_REQUEST 的请求。 win32 将其转换为ERROR_INVALID_FUNCTION。所以你必须得到这个错误。如果我们想在我们的设备上打开文件 - 需要实现 IRP_MJ_CREATEIRP_MJ_CLEANUPIRP_MJ_CLOSE 最低限度

【讨论】:

以上是关于无法通过 CreateFile 打开设备,ERROR_INVALID_FUNCTION的主要内容,如果未能解决你的问题,请参考以下文章

CreateFile打开文件或者打开目录

无法使用 CreateFile 函数打开文件

CreateFile DeviceIoControl dwIoControlCode——应用程序与驱动程序通信

使用 CreateFile 打开一个套接字

CreateFile,ReadFile等API详解(或者说MSDN的翻译)

VMware Workstation 打开虚拟机提示:传输(VMDB)错误-14: Pipe connection has been broken 无法待机/Transport (VMDB) erro