You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

驱动中DriverObject指定的MajorFunction调用形式及IRP_MJ_WRITE调用方法问询

回答

Alright, let's break this down clearly for you. First, let's clarify how those MajorFunction handlers get invoked, then we'll cover exactly how to trigger your IRP_MJ_WRITE handler, and throw in some concrete examples to make it tangible.


一、How MajorFunction Handlers Are Invoked

The functions you assigned to DriverObject->MajorFunction aren't meant to be called directly by your code. They're callback functions triggered by the Windows I/O Manager. Here's the flow:

  1. When an I/O request (like a write operation) is initiated (from user mode or kernel mode), the I/O Manager constructs an IRP (I/O Request Packet) that describes the request.
  2. The I/O Manager looks up the MajorFunction code in the IRP (e.g., IRP_MJ_WRITE), then fetches the corresponding function pointer from your driver's DriverObject.
  3. It then invokes your handler (in this case, ctlDevicePut) to process the IRP.

So you don't "call" these handlers directly—you trigger them by sending valid I/O requests to your driver's device.


二、Triggering IRP_MJ_WRITE (Your ctlDevicePut Handler)

There are two main ways to trigger a write request to your driver: from user mode, or from kernel mode. Here are examples for both:

1. User-Mode Trigger (Most Common)

Use standard Win32 APIs like CreateFile to open your driver's device, then WriteFile to send a write request. This will automatically trigger the IRP_MJ_WRITE handler in your driver.

#include <windows.h>
#include <iostream>

int main() {
    // Replace with your driver's device name (matches what you set in IoCreateDevice)
    LPCWSTR devicePath = L"\\\\.\\YourDeviceSymbolicLink";

    // Open the driver device
    HANDLE hDevice = CreateFile(
        devicePath,
        GENERIC_WRITE,          // Request write access
        0,                      // No shared access
        NULL,                   // Default security attributes
        OPEN_EXISTING,          // Open existing device
        FILE_ATTRIBUTE_NORMAL,  // Standard attributes
        NULL                    // No template file
    );

    if (hDevice == INVALID_HANDLE_VALUE) {
        std::cout << "Failed to open device. Error code: " << GetLastError() << std::endl;
        return 1;
    }

    // Data to write to the driver
    const char* writeData = "Hello from user mode to driver!";
    DWORD bytesWritten = 0;

    // Send write request
    BOOL writeSuccess = WriteFile(
        hDevice,
        writeData,
        strlen(writeData),  // Length of data to write
        &bytesWritten,     // Output: bytes actually written
        NULL               // No overlapped I/O
    );

    if (writeSuccess) {
        std::cout << "Successfully wrote " << bytesWritten << " bytes to driver." << std::endl;
    } else {
        std::cout << "WriteFile failed. Error code: " << GetLastError() << std::endl;
    }

    // Cleanup
    CloseHandle(hDevice);
    return 0;
}

2. Kernel-Mode Trigger

If you need to send a write request from another kernel-mode driver, you can use ZwWriteFile (simpler) or manually construct and send an IRP (more low-level).

Example with ZwWriteFile:

NTSTATUS TriggerDriverWrite(PDEVICE_OBJECT targetDevice) {
    NTSTATUS status;
    HANDLE deviceHandle;
    OBJECT_ATTRIBUTES objAttr;
    IO_STATUS_BLOCK ioStatus;

    // Initialize object attributes for the target device
    InitializeObjectAttributes(
        &objAttr,
        &targetDevice->DeviceName,
        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
        NULL,
        NULL
    );

    // Open the target device
    status = ZwCreateFile(
        &deviceHandle,
        GENERIC_WRITE,
        &objAttr,
        &ioStatus,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        0,
        FILE_OPEN,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0
    );

    if (!NT_SUCCESS(status)) {
        return status;
    }

    // Data to write
    CHAR writeBuffer[] = "Hello from kernel mode to driver!";
    ULONG bufferSize = sizeof(writeBuffer);

    // Send write request
    status = ZwWriteFile(
        deviceHandle,
        NULL,               // No event
        NULL,               // No APC routine
        NULL,               // No context
        &ioStatus,
        writeBuffer,
        bufferSize,
        NULL,               // No byte offset (adjust if your driver uses it)
        NULL                // No key
    );

    // Cleanup
    ZwClose(deviceHandle);
    return status;
}

三、Debugging Tip: Why You Can't Find the "Call Location"

Your debugger won't show a direct function call to ctlDevicePut because the I/O Manager invokes it via a function pointer stored in DriverObject->MajorFunction[IRP_MJ_WRITE]. Instead of looking for a caller:

  1. Set a breakpoint directly on ctlDevicePut (in WinDbg, use bp ctlDevicePut).
  2. When you trigger a write request (using the examples above), the debugger will break into your handler.
  3. Check the call stack—you'll see I/O Manager functions (like IofCallDriver or NtWriteFile) at the top, which are responsible for invoking your handler.

内容的提问来源于stack exchange,提问作者szefitoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:48:13