Windows 内核开发设备句柄无效的句柄值

Posted

技术标签:

【中文标题】Windows 内核开发设备句柄无效的句柄值【英文标题】:Windows kernel development devicehandle Invalid Handle Value 【发布时间】:2020-02-10 19:55:46 【问题描述】:

所以我目前正在关注本教程:https://www.youtube.com/watch?v=VaIMgJz05wI&t=2s 关于内核开发。当我尝试在我的用户模式程序中单击“打开设备”时,设备句柄返回一个无效的句柄值,尽管我正确映射了我的驱动程序并且我的设备链接是相同的。

用户模式代码:

HANDLE devicehandle = NULL;

void CKMDFDriverTut1userDlg::OnBnClickedButton1()

    // TODO: Add your control notification handler code here
    devicehandle = CreateFile(L"\\\\.\\myDeviceLink123", GENERIC_ALL, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
    if (devicehandle == INVALID_HANDLE_VALUE) 
        MessageBox(L"not valid value", 0, 0);
        return;
    
    //do your ting if valid
    MessageBox(L"valid value", 0, 0);

内核模式:

DRIVER_INITIALIZE DriverEntry;

UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\myDevice123");
UNICODE_STRING SymLinkName = RTL_CONSTANT_STRING(L"\\??\\myDeviceLink123");

PDEVICE_OBJECT DeviceObject = NULL;

VOID Unload(PDRIVER_OBJECT DriverObject) 

    IoDeleteSymbolicLink(&SymLinkName);
    IoDeleteDevice(DeviceObject);
    KdPrint(("Driver Unload \r\n"));


NTSTATUS DispatchPassThru(PDEVICE_OBJECT DeviceObject, PIRP Irp)

    PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS status = STATUS_SUCCESS;

    switch (irpsp->MajorFunction)
    
    case IRP_MJ_CREATE:
        KdPrint(("create request \r\n"));
        break;
    case IRP_MJ_CLOSE:
        KdPrint(("close resuest \r\n"));
        break;
    case IRP_MJ_READ:
        KdPrint(("read request \r\n"));
        break;
    case IRP_MJ_WRITE:
        KdPrint(("write resuest \r\n"));
        break;
    default:
        break;
    

    Irp->iostatus.Information = 0;
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath
)


    NTSTATUS status = STATUS_SUCCESS;
    int i;
    DriverObject->DriverUnload = Unload;

    status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);

    if (!NT_SUCCESS(status)) 
        KdPrint(("Creating device failed \r\n"));
        return status;
    

    status = IoCreateSymbolicLink(&SymLinkName, &DeviceName);

    if (!NT_SUCCESS(status)) 
        KdPrint(("creating symbolic link failed \r\n"));
        IoDeleteDevice(DeviceObject);
        return status;
    

    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) 
        DriverObject->MajorFunction[i] = DispatchPassThru;
    

    //DriverObject->MajorFunction[IRP_MJ_READ] = DispatchCustom;
    //DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchCustom1;

    KdPrint(("Driver load \r\n"));

    return status;

预期的输出是,当我单击 Button1 时,会出现一个消息框并显示“有效值”,但会出现一个消息框,显示“无效值”,这意味着我的设备句柄错误。非常感谢您的帮助,谢谢。

The device was successfully created

【问题讨论】:

你忘了DeviceObject-&gt;Flags &amp;= ~DO_DEVICE_INITIALIZING;。以及您为设备创建符号链接的目的是什么? 非常感谢您修复它:D 如果你在CreateFile 失败后调用RtlGetLastNtStatus() 或者更好的直接调用NtOpenFile/NtCreateFile - 你得到错误STATUS_NO_SUCH_DEVICE 这将是提示,为什么。和 main - 你不需要创建任何符号链接,即使是 CreateFile 调用。使用 \\\\?\\globalroot\\Device\\myDevice123 路径 哦,我不知道。感谢您的帮助:D 【参考方案1】:

作为调试此类问题的第一步,我的建议是验证并确认您的设备已成功创建为对象并在命名空间中可见。一种方法是使用 Microsoft 的工具:WinObj。此工具可在https://docs.microsoft.com/en-us/sysinternals/downloads/winobj 获得

【讨论】:

设备创建成功,在WinObj中可见 在您的用户模式代码中,请在您的代码通过调用 CreateFile() 收到 INVALID_HANDLE_VALUE 后获取扩展错误信息。使用 GetLastError() 获取扩展的错误信息,这将为您的问题提供一些启示。 非常感谢您的帮助。 RbMm 指出了我忘记的内容并修复了它:D【参考方案2】:

当您访问\\.\ 区域中的设备时,这意味着通过DosDevice 名称访问。因此,必须在驱动端的DosDevice区域创建符号链接。

以下链接会对您有所帮助。

https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-ms-dos-device-names

【讨论】:

我以为我在这里创建了一个符号链接:status = IoCreateSymbolicLink(&SymLinkName, &DeviceName); WinObj 还可以显示存在的符号链接。 @DaRealHeroofHell 尝试将符号链接名称设置为 \DosDevices\ 区域。 @reinhard v.z 非常感谢您的帮助。 RbMm 指出了我忘记的内容并修复了它:D

以上是关于Windows 内核开发设备句柄无效的句柄值的主要内容,如果未能解决你的问题,请参考以下文章

内核对象&句柄&泄漏&检测

句柄表(私有句柄表)

内核对象&句柄

win32进程概念之句柄表,以及内核对象.

羽夏看Win系统内核——句柄表篇

Windows核心编程(第5版)----关闭内核对象