栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

回顾驱动与用户层通信

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

回顾驱动与用户层通信


环境:win10 64位

先关签名 有时这样不行 得去恢复 高级选项那禁止强制签名重启

bcdedit.exe /set nointegritychecks on

1。缓冲区方式读写 

桥梁是用一个buf

将数据存储在AssociatedIrp.SystemBuffer

pDevObj->Flags |= DO_BUFFERED_IO

用户层

main.cpp

#include

#include

#define GetFilePointer(hFile) SetFilePointer(hFile, 0, NULL, FILE_CURRENT)

int main()

{

    HANDLE hDevice =

        CreateFile("\\.\HelloDDK",

            GENERIC_READ | GENERIC_WRITE,

            0,      // share mode none

            NULL,   // no security

            OPEN_EXISTING,

            FILE_ATTRIBUTE_NORMAL,

            NULL);      // no template

    if (hDevice == INVALID_HANDLE_VALUE)

    {

        printf("Failed to obtain file handle to device: "

            "%s with Win32 error code: %dn",

            "MyWDMDevice", GetLastError());

        //return 1;

    }

    UCHAR buffer[10];

    memset(buffer, 0xBB, 10);

    ULONG ulRead;

    ULONG ulWrite;

    BOOL bRet;

    bRet = WriteFile(hDevice, buffer, 10, &ulWrite, NULL);

    if (bRet)

    {

        printf("Write %d bytesn", ulWrite);

    }

    bRet = ReadFile(hDevice, buffer, 10, &ulRead, NULL);

    if (bRet)

    {

        printf("Read %d bytes:", ulRead);

        for (int i = 0; i<(int)ulRead; i++)

        {

            printf("%02X ", buffer[i]);

        }

        printf("n");

    }

    printf("file length:%dn", GetFileSize(hDevice, NULL));

    CloseHandle(hDevice);

    getchar();

    return 0;

}

驱动层

test.c

#include "Driver.h"

#pragma INITCODE

 NTSTATUS DriverEntry(

    IN PDRIVER_OBJECT pDriverObject,

    IN PUNICODE_STRING pRegistryPath)

{

    NTSTATUS status;

    KdPrint(("Enter DriverEntryn"));

    //设置卸载函数

    pDriverObject->DriverUnload = HelloDDKUnload;

    //设置派遣函数

    for (int i = 0; i < arraysize(pDriverObject->MajorFunction); ++i)

        pDriverObject->MajorFunction[i] = HelloDDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDWrite;

    pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;

    //用户层获取文件长度时用产生这个irp

    pDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = HelloDDKQueryInfomation;

    //创建驱动设备对象

    status = CreateDevice(pDriverObject);

    KdPrint(("Leave DriverEntryn"));

    return status;

}

#pragma INITCODE

NTSTATUS CreateDevice(

    IN PDRIVER_OBJECT   pDriverObject)

{

    NTSTATUS status;

    PDEVICE_OBJECT pDevObj;

    PDEVICE_EXTENSION pDevExt;

    //创建设备名称

    UNICODE_STRING devName;

    RtlInitUnicodeString(&devName, L"\Device\MyDDKDevice");

    //创建设备

    status = IoCreateDevice(pDriverObject,

        sizeof(DEVICE_EXTENSION),

        &devName,

        FILE_DEVICE_UNKNOWN,

        0, TRUE,

        &pDevObj);

    if (!NT_SUCCESS(status))

        return status;

    pDevObj->Flags |= DO_BUFFERED_IO;

    pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    pDevExt->pDevice = pDevObj;

    pDevExt->ustrDeviceName = devName;

    //申请模拟文件的缓冲区

    pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool, MAX_FILE_LENGTH);

    //设置模拟文件大小

    pDevExt->file_length = 0;

    //创建符号链接

    UNICODE_STRING symlinkName;

    RtlInitUnicodeString(&symlinkName, L"\??\HelloDDK");

    pDevExt->ustrSymlinkName = symlinkName;

    status = IoCreateSymboliclink(&symlinkName, &devName);

    if (!NT_SUCCESS(status))

    {

        IoDeleteDevice(pDevObj);

        return status;

    }

    return STATUS_SUCCESS;

}

#pragma PAGEDCODE

VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject)

{

    PDEVICE_OBJECT  pNextObj;

    KdPrint(("Enter DriverUnloadn"));

    pNextObj = pDriverObject->DeviceObject;

    while (pNextObj != NULL)

    {

        PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)

            pNextObj->DeviceExtension;

        if (pDevExt->buffer)

        {

            ExFreePool(pDevExt->buffer);

            pDevExt->buffer = NULL;

        }

        //删除符号链接

        UNICODE_STRING plinkName = pDevExt->ustrSymlinkName;

        IoDeleteSymboliclink(&plinkName);

        pNextObj = pNextObj->NextDevice;

        IoDeleteDevice(pDevExt->pDevice);

    }

}

#pragma PAGEDCODE

NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp)

{

    KdPrint(("Enter HelloDDKDispatchRoutinn"));

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    //建立一个字符串数组与IRP类型对应起来

    static char* irpname[] =

    {

        "IRP_MJ_CREATE",

        "IRP_MJ_CREATE_NAMED_PIPE",

        "IRP_MJ_CLOSE",

        "IRP_MJ_READ",

        "IRP_MJ_WRITE",

        "IRP_MJ_QUERY_INFORMATION",

        "IRP_MJ_SET_INFORMATION",

        "IRP_MJ_QUERY_EA",

        "IRP_MJ_SET_EA",

        "IRP_MJ_FLUSH_BUFFERS",

        "IRP_MJ_QUERY_VOLUME_INFORMATION",

        "IRP_MJ_SET_VOLUME_INFORMATION",

        "IRP_MJ_DIRECTORY_CONTROL",

        "IRP_MJ_FILE_SYSTEM_CONTROL",

        "IRP_MJ_DEVICE_CONTROL",

        "IRP_MJ_INTERNAL_DEVICE_CONTROL",

        "IRP_MJ_SHUTDOWN",

        "IRP_MJ_LOCK_CONTROL",

        "IRP_MJ_CLEANUP",

        "IRP_MJ_CREATE_MAILSLOT",

        "IRP_MJ_QUERY_SECURITY",

        "IRP_MJ_SET_SECURITY",

        "IRP_MJ_POWER",

        "IRP_MJ_SYSTEM_CONTROL",

        "IRP_MJ_DEVICE_CHANGE",

        "IRP_MJ_QUERY_QUOTA",

        "IRP_MJ_SET_QUOTA",

        "IRP_MJ_PNP",

    };

    UCHAR type = stack->MajorFunction;

    if (type >= arraysize(irpname))

        KdPrint((" - Unknown IRP, major type %Xn", type));

    else

        KdPrint(("t%sn", irpname[type]));

    //对一般IRP的简单操作,后面会介绍对IRP更复杂的操作

    NTSTATUS status = STATUS_SUCCESS;

    // 完成IRP

    pIrp->IoStatus.Status = status;

    pIrp->IoStatus.Information = 0; // bytes xfered

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    KdPrint(("Leave HelloDDKDispatchRoutinn"));

    return status;

}

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp)

{

    KdPrint(("Enter HelloDDKReadn"));

    //在 IoCreateDevice申请模拟文件的缓冲区

    //pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool, MAX_FILE_LENGTH);

    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    NTSTATUS status = STATUS_SUCCESS;

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    ULONG ulReadLength = stack->Parameters.Read.Length;

    ULONG ulReadOffset = (ULONG)stack->Parameters.Read.ByteOffset.QuadPart;

    if (ulReadOffset + ulReadLength>MAX_FILE_LENGTH)

    {

        status = STATUS_FILE_INVALID;

        ulReadLength = 0;

    }

    else

    {

        //将数据存储在AssociatedIrp.SystemBuffer,以便应用程序使用

        memcpy(pIrp->AssociatedIrp.SystemBuffer, pDevExt->buffer + ulReadOffset, ulReadLength);

        status = STATUS_SUCCESS;

    }

    pIrp->IoStatus.Status = status;

    pIrp->IoStatus.Information = ulReadLength;  // bytes xfered

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    KdPrint(("Leave HelloDDKReadn"));

    return status;

}

NTSTATUS HelloDDWrite(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp)

{

    KdPrint(("Enter HelloDDWriten"));

    NTSTATUS status = STATUS_SUCCESS;

    //在 IoCreateDevice申请模拟文件的缓冲区

    //pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool, MAX_FILE_LENGTH);

    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    //获取存储的长度

    ULONG ulWriteLength = stack->Parameters.Write.Length;

    //获取存储的偏移量 就是buffer中从哪里开始

    ULONG ulWriteOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart;

    if (ulWriteOffset + ulWriteLength>MAX_FILE_LENGTH)

    {

        //如果存储长度+偏移量大于缓冲区长度,则返回无效

        status = STATUS_FILE_INVALID;

        ulWriteLength = 0;

    }

    else

    {

        //将写入的数据,存储在缓冲区内

        memcpy(pDevExt->buffer + ulWriteOffset, pIrp->AssociatedIrp.SystemBuffer, ulWriteLength);

        status = STATUS_SUCCESS;

        //设置新的文件长度

        if (ulWriteLength + ulWriteOffset>pDevExt->file_length)

        {

            pDevExt->file_length = ulWriteLength + ulWriteOffset;

        }

    }

    pIrp->IoStatus.Status = status;

    //用户的返回值是这个

    pIrp->IoStatus.Information = ulWriteLength; // bytes xfered

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    KdPrint(("Leave HelloDDWriten"));

    return status;

}

NTSTATUS HelloDDKQueryInfomation(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp)

{

    KdPrint(("Enter HelloDDKQueryInfomationn"));

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    FILE_INFORMATION_CLASS info = stack->Parameters.QueryFile.FileInformationClass;

    if (info == FileStandardInformation)

    {

        KdPrint(("FileStandardInformationn"));

        PFILE_STANDARD_INFORMATION file_info =

            (PFILE_STANDARD_INFORMATION)pIrp->AssociatedIrp.SystemBuffer;

        file_info->EndOfFile = RtlConvertLongToLargeInteger(pDevExt->file_length);

    }

    NTSTATUS status = STATUS_SUCCESS;

    // 完成IRP

    pIrp->IoStatus.Status = status;

    pIrp->IoStatus.Information = stack->Parameters.QueryFile.Length;    // bytes xfered

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    KdPrint(("Leave HelloDDKQueryInfomationn"));

    return status;

}

//Driver.h

#pragma once

#ifdef __cplusplus

extern "C"

{

#endif

#include

#ifdef __cplusplus

}

#endif 

#define PAGEDCODE code_seg("PAGE")

#define LOCKEDCODE code_seg()

#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")

#define LOCKEDDATA data_seg()

#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

#define MAX_FILE_LENGTH 1024

typedef struct _DEVICE_EXTENSION {

    PDEVICE_OBJECT pDevice;

    UNICODE_STRING ustrDeviceName;  //设备名称

    UNICODE_STRING ustrSymlinkName; //符号链接名

    PUCHAR buffer;//缓冲区

    ULONG file_length;//模拟的文件长度,必须小于MAX_FILE_LENGTH

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

// 函数声明

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject);

VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject);

NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp);

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp);

NTSTATUS HelloDDWrite(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp);

NTSTATUS HelloDDKQueryInfomation(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp);

回顾驱动与用户层通信

2。直接方式

pDevObj->Flags |= DO_DIRECT_IO;

用户层

main.cpp

#include

#include

#define GetFilePointer(hFile) SetFilePointer(hFile, 0, NULL, FILE_CURRENT)

int main()

{

    HANDLE hDevice = 

        CreateFile("\\.\HelloDDK",

                    GENERIC_READ | GENERIC_WRITE,

                    0,      // share mode none

                    NULL,   // no security

                    OPEN_EXISTING,

                    FILE_ATTRIBUTE_NORMAL,

                    NULL );     // no template

    if (hDevice == INVALID_HANDLE_VALUE)

    {

        printf("Failed to obtain file handle to device: "

            "%s with Win32 error code: %dn",

            "MyWDMDevice", GetLastError() );

        return 1;

    }

    UCHAR buffer[10];

    memset(buffer,0xBB,10);

    ULONG ulRead;

    BOOL bRet;

    bRet = ReadFile(hDevice,buffer,10,&ulRead,NULL);

    if (bRet)

    {

        printf("Address 0X%08Xn",buffer);

        printf("(Read %d bytes):",ulRead);

        for (int i=0;i<(int)ulRead;i++)

        {

            printf("%02X ",buffer[i]);

        }

        printf("n");

    }

    CloseHandle(hDevice);

    return 0;

}

驱动层

test.c

#include "Driver.h"

#pragma INITCODE

 NTSTATUS DriverEntry (

            IN PDRIVER_OBJECT pDriverObject,

            IN PUNICODE_STRING pRegistryPath    ) 

{

    NTSTATUS status;

    KdPrint(("Enter DriverEntryn"));

    //设置卸载函数

    pDriverObject->DriverUnload = HelloDDKUnload;

    //设置派遣函数

    for (int i = 0; i < arraysize(pDriverObject->MajorFunction); ++i)

        pDriverObject->MajorFunction[i] = HelloDDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;

    //创建驱动设备对象

    status = CreateDevice(pDriverObject);

    KdPrint(("Leave DriverEntryn"));

    return status;

}

#pragma INITCODE

NTSTATUS CreateDevice (

        IN PDRIVER_OBJECT   pDriverObject) 

{

    NTSTATUS status;

    PDEVICE_OBJECT pDevObj;

    PDEVICE_EXTENSION pDevExt;

    //创建设备名称

    UNICODE_STRING devName;

    RtlInitUnicodeString(&devName,L"\Device\MyDDKDevice");

    //创建设备

    status = IoCreateDevice( pDriverObject,

                        sizeof(DEVICE_EXTENSION),

                        &(UNICODE_STRING)devName,

                        FILE_DEVICE_UNKNOWN,

                        0, TRUE,

                        &pDevObj );

    if (!NT_SUCCESS(status))

        return status;

    pDevObj->Flags |= DO_DIRECT_IO;

    pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    pDevExt->pDevice = pDevObj;

    pDevExt->ustrDeviceName = devName;

    //申请模拟文件的缓冲区

    pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool,MAX_FILE_LENGTH);

    //设置模拟文件大小

    pDevExt->file_length = 0;

    //创建符号链接

    UNICODE_STRING symlinkName;

    RtlInitUnicodeString(&symlinkName,L"\??\HelloDDK");

    pDevExt->ustrSymlinkName = symlinkName;

    status = IoCreateSymboliclink( &symlinkName,&devName );

    if (!NT_SUCCESS(status)) 

    {

        IoDeleteDevice( pDevObj );

        return status;

    }

    return STATUS_SUCCESS;

}

#pragma PAGEDCODE

VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) 

{

    PDEVICE_OBJECT  pNextObj;

    KdPrint(("Enter DriverUnloadn"));

    pNextObj = pDriverObject->DeviceObject;

    while (pNextObj != NULL) 

    {

        PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)

            pNextObj->DeviceExtension;

        if (pDevExt->buffer)

        {

            ExFreePool(pDevExt->buffer);

            pDevExt->buffer = NULL;

        }

        //删除符号链接

        UNICODE_STRING plinkName = pDevExt->ustrSymlinkName;

        IoDeleteSymboliclink(&plinkName);

        pNextObj = pNextObj->NextDevice;

        IoDeleteDevice( pDevExt->pDevice );

    }

}

#pragma PAGEDCODE

NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,

                                 IN PIRP pIrp) 

{

    KdPrint(("Enter HelloDDKDispatchRoutinn"));

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    //建立一个字符串数组与IRP类型对应起来

    static char* irpname[] = 

    {

        "IRP_MJ_CREATE",

        "IRP_MJ_CREATE_NAMED_PIPE",

        "IRP_MJ_CLOSE",

        "IRP_MJ_READ",

        "IRP_MJ_WRITE",

        "IRP_MJ_QUERY_INFORMATION",

        "IRP_MJ_SET_INFORMATION",

        "IRP_MJ_QUERY_EA",

        "IRP_MJ_SET_EA",

        "IRP_MJ_FLUSH_BUFFERS",

        "IRP_MJ_QUERY_VOLUME_INFORMATION",

        "IRP_MJ_SET_VOLUME_INFORMATION",

        "IRP_MJ_DIRECTORY_CONTROL",

        "IRP_MJ_FILE_SYSTEM_CONTROL",

        "IRP_MJ_DEVICE_CONTROL",

        "IRP_MJ_INTERNAL_DEVICE_CONTROL",

        "IRP_MJ_SHUTDOWN",

        "IRP_MJ_LOCK_CONTROL",

        "IRP_MJ_CLEANUP",

        "IRP_MJ_CREATE_MAILSLOT",

        "IRP_MJ_QUERY_SECURITY",

        "IRP_MJ_SET_SECURITY",

        "IRP_MJ_POWER",

        "IRP_MJ_SYSTEM_CONTROL",

        "IRP_MJ_DEVICE_CHANGE",

        "IRP_MJ_QUERY_QUOTA",

        "IRP_MJ_SET_QUOTA",

        "IRP_MJ_PNP",

    };

    UCHAR type = stack->MajorFunction;

    if (type >= arraysize(irpname))

        KdPrint((" - Unknown IRP, major type %Xn", type));

    else

        KdPrint(("t%sn", irpname[type]));

    NTSTATUS status = STATUS_SUCCESS;

    // 完成IRP

    pIrp->IoStatus.Status = status;

    pIrp->IoStatus.Information = 0; // bytes xfered

    IoCompleteRequest( pIrp, IO_NO_INCREMENT );

    KdPrint(("Leave HelloDDKDispatchRoutinn"));

    return status;

}

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,

                                 IN PIRP pIrp) 

{

    KdPrint(("Enter HelloDDKReadn"));

    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    NTSTATUS status = STATUS_SUCCESS;

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    ULONG ulReadLength = stack->Parameters.Read.Length;

    KdPrint(("ulReadLength:%dn",ulReadLength));

    ULONG mdl_length = MmGetMdlByteCount(pIrp->MdlAddress);

    PVOID mdl_address = MmGetMdlVirtualAddress(pIrp->MdlAddress);

    ULONG mdl_offset = MmGetMdlByteOffset(pIrp->MdlAddress);

    KdPrint(("mdl_address:0X%08Xn",mdl_address));

    KdPrint(("mdl_length:%dn",mdl_length));

    KdPrint(("mdl_offset:%dn",mdl_offset));

    if (mdl_length!=ulReadLength)

    {

        //MDL的长度应该和读长度相等,否则该操作应该设为不成功

        pIrp->IoStatus.Information = 0;

        status = STATUS_UNSUCCESSFUL;

    }else

    {

        //用MmGetSystemAddressForMdlSafe得到MDL在内核模式下的映射 就是用户中的buffer映射

        PVOID kernel_address = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority);

        KdPrint(("kernel_address:0X%08Xn",kernel_address));

        //修改数据

        memset(kernel_address,0xAA,ulReadLength);

        pIrp->IoStatus.Information = ulReadLength;  // bytes xfered

    }

    pIrp->IoStatus.Status = status;

    IoCompleteRequest( pIrp, IO_NO_INCREMENT );

    KdPrint(("Leave HelloDDKReadn"));

    return status;

}

//Driver.h

#pragma once

#ifdef __cplusplus

extern "C"

{

#endif

#include

#ifdef __cplusplus

}

#endif 

#define PAGEDCODE code_seg("PAGE")

#define LOCKEDCODE code_seg()

#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")

#define LOCKEDDATA data_seg()

#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

#define MAX_FILE_LENGTH 1024

typedef struct _DEVICE_EXTENSION {

    PDEVICE_OBJECT pDevice;

    UNICODE_STRING ustrDeviceName;  //设备名称

    UNICODE_STRING ustrSymlinkName; //符号链接名

    PUCHAR buffer;//缓冲区

    ULONG file_length;//模拟的文件长度,必须小于MAX_FILE_LENGTH

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

// 函数声明

NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);

VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);

NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,

                                 IN PIRP pIrp);

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,

                                 IN PIRP pIrp);

NTSTATUS HelloDDWrite(IN PDEVICE_OBJECT pDevObj,

                                 IN PIRP pIrp);

NTSTATUS HelloDDKQueryInfomation(IN PDEVICE_OBJECT pDevObj,

                                 IN PIRP pIrp);

©著作权归作者所有:来自51CTO博客作者土匪猿的原创作品,如需转载,请注明出处,否则将追究法律责任


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/232588.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号