IRP,系统就调用相应的处理IRP_MJ_DEVICE_CONTROL的派遣函数,你在派遣函数中判断MinorFunction ,是自定义的控制码你就进行相应的处理。...驱动程序输出数据时,还可以向pIrp->AssociatedIrp.SystemBuffer中写入,操作系统会将此地址的数据复制到DeviceIoControl的输出缓冲区。...派遣函数中通过下面代码得到输入缓冲区输出缓冲的大小以及IOCTL //得到当前堆栈 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp...直接内存模式中,操作系统会将DeviceIoControl指定的输出缓冲区锁定,然后在内核模式地址下重新映射一段地址。...派遣函数中IRP中的pIrp->MdlAddress记录DeviceIoControl指定的输出缓冲区。
我们可以在\include\w2k\ntddk.inc文件中找到一组FILE_DEVICE_XXX 符号常量,这些值都是微软保留的 值,我们可以使用其中的FILE_DEVICE_UNKNOWN。...往驱动中Input数据:在Win32 APIDeviceIoControl函数的内部,用户提供的输入缓冲区的内容被复制到IRP的pIRP->AssociatedIrp.SystemBuffer的内存地址...从驱动中Output数据:操作系统会为DeviceIoControl指定的输出缓冲区锁定,然后在内核模式地址下重新映射到一段地址。...在派遣函数中可以先获取DeviceIoControl指定的输出缓冲区(lpOutBufferb被记录在pIrp->AssociateIrp.SystemBuffer),然后再通过MmGetSystemAddressForMdlSafe...获取其在核地址中的映射值。
前言: 最近需要对Windows中的设备进行编程操作,其中涉及到非常重要的函数DeviceIoControl,在使用的时候也比较的复杂,国内这一块中文资料比较少,在学习之余顺便将其翻译出来,以供参考...lpBytesReturned [out, optional] (可选)指向一个变量的指针,该变量接收存储在输出缓冲区中的数据的大小。...如果输出缓冲区太小,无法接收任何数据,则GetLastError返回ERROR_INSUFFICIENT_BUFFER,错误代码122(0x7a),此时lpBytesReturned是零。...如果输出缓冲区太小而无法保存所有数据,但可以保存一些条目,某些驱动程序将返回尽可能多的数据,在这种情况下,调用失败,GetLastError返回ERROR_MORE_DATA,错误代码234,lpBytesReturned...即使操作没有返回输出数据并且lpOutBuffer为NULL,DeviceIoControl也会使用lpBytesReturned。
与内存传输的关系 1..METHOD_BUFFERED:缓冲区模式 inbuffer的内容被复制到IRP中的pIrp->AssociatedIrp.SystemBuffer复制的长度是DeviceIoControl...直接内存模式中,操作系统会将DeviceIoControl指定的输出缓冲区锁定,然后在内核模式地址下重新映射一段地址。...派遣函数中IRP中的pIrp->MdlAddress记录DeviceIoControl指定的输出缓冲区。...派遣函数应该使用MmGetSystemAddressForMdlSafe将这段内存映射到内核模式下的内存地址。 得到输入输出缓冲区的大小以及IOCTL的方式与缓冲区模式相同。...驱动通过pIrp->UserBuffer得到输出缓冲区。 得到输入输出缓冲区的长度与IOCTL的方式与前两种相同。
之前写过一篇关于通过DeviceIoControl函数来使应用程序与驱动程序通信的博客,这次再通过这个完整的代码来简要疏通总结一下。 ...这样Ring3输出缓冲区在驱动程序完成I/O请求之前,都是无法访问的,从一定程度上保障了安全性。如图21.1.14所示。...对于Ring3的输出缓冲区,首先由系统锁定,并使用pIrp->MdlAddress来描述这段内存,驱动程序需要使用MmGetSystemAddressForMdlSafe函数将这段内存映射到内核内存地址...输出缓冲区可以通过pIrp->UserBuffer得到。由于驱动中的派遣函数不能保证传递进来的用户输入和输出地址,因此最好不要直接去读写这些地址的缓冲区。...METHOD_ NEITHER方式是不进行缓冲的,在驱动中可以直接使用Ring3的输入输出内存地址, 驱动程序可以通过pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer
在串口编程中,IOCTL_SERIAL_GET_HANDFLOW是一个重要的IOCTL命令代码,用于获取串口通讯中的流控制参数。...FlowReplace:指定流控制行为的位掩码。XonLimit:XON 限制。当内部接收缓冲区中的字符数低于 XON 限制时,串行控制器驱动程序使用流控制信号来告知发送方继续发送字符。...当内部接收缓冲区中的字符数达到 XOFF 限制时,串行控制器驱动程序使用流控制信号来告知发送方停止发送字符。3....使用IOCTL_SERIAL_GET_HANDFLOW在应用程序中,可以通过DeviceIoControl函数发送IOCTL_SERIAL_GET_HANDFLOW命令。..., // 输入缓冲区 0, // 输入缓冲区长度 &serialHandFlow, // 输出缓冲区 sizeof(SERIAL_HANDFLOW), // 输出缓冲区长度
} IRP, *PIRP; 2.2 读取 写入 控制等IRP的大小获取 在我们的派遣函数中如果指定了缓冲区模式。那么我们从IRP中获取 SystemBuffer 使用即可。...传出写入那么就是往 OutBuffer中写。 总结来说,如果是缓冲区模式,那么输入输出缓冲区都是一个缓冲区,在内核中都会封装到 Irp中的SystemBuffer中。...此方式的特点如下: 输入缓冲区会被 转换为内核中的 Irp->AssociatedIrp.SystemBuffer 复制的字节就是从 Irp堆栈中的 DeviceIoControl域拿到的(可以拿到输入输出的字节...参考5.3) 输出缓冲区会被内核锁定,锁定之后 Irp->MdlAddress记录着。 如果想要使用必须使用API MmGetSystemAddressForMdlSafe 来获取内核中映射的地址。...DeviceIoControl->Type3InputBuffer 记录着输入缓冲区 Irp->UserBuffer 记录着输出缓冲区 其中输入输出缓冲区的长度还是在 DeviceIoControl
中,并将输出缓冲区锁定,然后在内核模式下重新映射一段地址,这样也是比较安全的。 ...这样Ring3输出缓冲区在驱动程序完成I/O请求之前,都是无法访问的,从一定程度上保障了安全性。如图21.1.14所示。...对于Ring3的输出缓冲区,首先由系统锁定,并使用pIrp->MdlAddress来描述这段内存,驱动程序需要使用MmGetSystemAddressForMdlSafe函数将这段内存映射到内核内存地址...输出缓冲区可以通过pIrp->UserBuffer得到。由于驱动中的派遣函数不能保证传递进来的用户输入和输出地址,因此最好不要直接去读写这些地址的缓冲区。...METHOD_ NEITHER方式是不进行缓冲的,在驱动中可以直接使用Ring3的输入输出内存地址, 驱动程序可以通过pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer
在Windows操作系统中,串口通信是一种常见的硬件通信方式,它允许计算机与其他设备进行数据交换。...在串口编程中,IOCTL_SERIAL_GET_CHARS是一个重要的IOCTL命令代码,用于获取串口通讯中的特殊字符参数。这些参数包括控制字符、停止位、奇偶校验位等,对于确保数据的正确传输至关重要。...使用IOCTL_SERIAL_GET_CHARS在应用程序中,可以通过DeviceIoControl函数发送IOCTL_SERIAL_GET_CHARS命令。...输入缓冲区 0, // 输入缓冲区长度 &serialChars, // 输出缓冲区 sizeof(SERIAL_CHARS), // 输出缓冲区长度 &bytesReturned...在调用DeviceIoControl之前,确保SERIAL_CHARS结构体已经被正确初始化。检查DeviceIoControl函数的返回值,以确定操作是否成功,并根据需要进行错误处理。
当时我推测可能是句柄为NULL,或者DeviceIoControl中哪个缓冲区不能为NULL,为了知道是哪的问题,我在调用DeviceIoControl之前加了一条输出语句,我发现这条语句输出的句柄值是正常的...,那就肯定是DeviceIoControl的问题,我先试着吧所有的输入输出缓冲区都给定了一个值,通过排查最后发现是倒数第二个参数不能为NULL,这个参数表示的是驱动层实际返回的缓冲区的大小。...通过dwIoControlCode向驱动下发控制码,这个控制码在驱动中可以通过IO_STACK_LOCATION 结构中的Parameters.DeviceIoControl.IoControlCode...答案就是通过Irp->IoStatus.Information这个值,I/O管理器取这个值,将它填充到lpBytesReturned所指向的内存中,既然我们在驱动中指定了这个值为0,自然要给它在应用层分配相应的缓冲区了...DeviceIoControl函数,如果不需要跟驱动层进行交互,那么他的输入输出缓冲区是可以给NULL的,但是由于I/O管理器会像它返回驱动层实际返回的数据的大小,所以这个真实大小的缓冲区一定不能为NULL
在“进程内存管理器中”的一个Ring0,Ring3层通信问题,之前也见过这样的代码,这次拆分出来详细总结一下。 ..., //输出缓冲区的大小 _Out_opt_ LPDWORD lpBytesReturned, //实际返回的字节数,对应驱动程序中pIrp->IoStatus.Information。...lpInBuffer 由用户层发送的缓冲区数据。在“进程内存管理器“程序中,我们是通过进程ID来查询进程内存,故传入的是进程ID.在驱动层,依传输类型的不同,输入缓冲区的位置亦不同,见下表。...lpOutBuffer 由用户层指定,用于接收驱动层返回数据的缓冲区。在驱动层,依传输类型的不同,输出缓冲区的位置亦不同,见下表。...而你的驱动程序将使用这个系统缓冲区工作。 I/O管理器负责在系统缓冲区和用户模式缓冲区之间复制数据。
函数中的第6个参数也就是输出缓冲区!...DeviceIoControl函数的输入输出缓冲区长度都再stack->Parameters.DeviceioControl.InputBufferLength/OutputBufferLength中...4缓冲内存IOCTL,在DeviceIoControl函数第二个参数的时候,使用CTL_CODE来产生该常数,其中Method字段设置为METHOD_BUFFERED,在内核模式中输入缓冲区很输出缓冲区都为...对于第4中的区别是输入缓冲区还在pIrp->AssocatedIrp.Systembuffer中,但是输出缓冲区却是pIrp->MdlAddress,因此在内核对输出的写应该写在MmGetSystemAddressForMdlSafe...(pIrp->MdlAddress)中, 6其他方式IOCTL,在DeviceIoControl函数第二个参数的时候,使用CTL_CODE来产生该常数,其中Method字段设置为MEHTOD_NEITHER
A 在NT/2000/XP中,应用程序可以通过API函数DeviceIoControl来实现对设备的访问—获取信息,发送命令,交换数据等。...输入输出数据缓冲区是否需要,是何种结构,以及占多少字节空间,完全由不同设备的不同操作类型决定。在头文件winioctl.h中,已经为标准设备预定义了一些输入输出数据结构。...A 这里有一个从MSDN上摘抄来的demo程序,演示在NT/2000/XP中如何通过DeviceIoControl获取硬盘的基本参数。...Q 使用这些I/O控制码,需要什么样的输入输出数据格式呢? A DeviceIoControl使用这两个控制码时,都不需要输入数据。...\drivers目录中) Yariv Kaplan的主页:http://www.internals.com 实战DeviceIoControl 之七:在Windows 9X中读写磁盘扇区 在Windows
在 C# 中,有不同类型的变量(用不同的关键字定义),例如: int - 存储整数(没有小数点的整数),如 123 或 -123 double - 存储浮点数,有小数点,如 19.99 或 -19.99...存储值 6 然后我们使用 WriteLine() 方法来显示 x + y 的值,即 11 C# 多个变量 声明多个变量: 要声明同一类型的多个变量,请使用逗号分隔的列表: int x = 5, y =...(x + y + z); 在第一个示例中,我们声明了三个 int 类型的变量(x、y 和 z),并为它们赋了不同的值。...在第二个示例中,我们声明了三个 int 类型的变量,然后将它们都赋予了相同的值 50。 C# 标识符 所有的 C# 变量都必须使用唯一的名称来标识。 这些唯一的名称被称为标识符。...注意: 建议使用描述性名称,以创建易于理解和维护的代码: // 好的 int minutesPerHour = 60; // 可以,但不容易理解 m 实际上是什么 int m = 60; 命名变量的一般规则是
内核中执行代码后需要将结果动态显示给应用层的用户,DeviceIoControl 是直接发送控制代码到指定的设备驱动程序,使相应的移动设备以执行相应的操作的函数,如下代码是一个经典的驱动开发模板框架,在开发经典驱动时会用到的一个通用案例...;Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);// 指定通信方式为缓冲区...;// 输入和输出的缓冲区(DeviceIoControl的InBuffer和OutBuffer都是它)pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;// EXE...发送传入数据的BUFFER长度(DeviceIoControl的nInBufferSize)uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength...;// EXE接收传出数据的BUFFER长度(DeviceIoControl的nOutBufferSize)uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength
内核中执行代码后需要将结果动态显示给应用层的用户,DeviceIoControl 是直接发送控制代码到指定的设备驱动程序,使相应的移动设备以执行相应的操作的函数,如下代码是一个经典的驱动开发模板框架,在开发经典驱动时会用到的一个通用案例...; // 输入和输出的缓冲区(DeviceIoControl的InBuffer和OutBuffer都是它) pIoBuffer = pIrp->AssociatedIrp.SystemBuffer...; // EXE发送传入数据的BUFFER长度(DeviceIoControl的nInBufferSize) uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength...; // EXE接收传出数据的BUFFER长度(DeviceIoControl的nOutBufferSize) uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength...; else pIrp->IoStatus.Information = 0; // 设定DeviceIoControl的返回值是成功还是失败 pIrp->IoStatus.Status =
DeviceIoControl是用来控制我们指定设备的输入输出操作,使设备按照我们发的指令去工作。...DeviceIoControl是kernel32中的函数,需要包含的头文件是winbase.h,先看函数原型 BOOL DeviceIoControl( HANDLE hDevice, DWORD dwIoControlCode...dwIoControlCode: 当然就是控制设备的指令了,指令怎么来是个问题,微软已经定义好了很多种操作,在winioctl.h文件中,但最终都是通过CTL_CODE宏来实现的,其实这就是一种通信协议...CTL_CODE的具体用法在最后来介绍。...(别忘记上面DeviceIOControl中缓冲区的定义哦)是如何与I/O和文件系统数据缓冲区进行数据传递的方式(具体取值查看msdn)我们最常用的就是METHOD_BUFFERED Function
在前面的文章《驱动开发:运用MDL映射实现多次通信》LyShark教大家使用MDL的方式灵活的实现了内核态多次输出结构体的效果,但是此种方法并不推荐大家使用原因很简单首先内核空间比较宝贵,其次内核里面不能分配太大且每次传出的结构体最大不能超过...1024个,而最终这些内存由于无法得到更好的释放从而导致坏堆的产生,这样的程序显然是无法在生产环境中使用的,如下LyShark将教大家通过在应用层申请空间来实现同等效果,此类传递方式也是多数ARK反内核工具中最常采用的一种...与MDL映射相反,MDL多数处理流程在内核代码中,而应用层开堆复杂代码则在应用层,但内核层中同样还是需要使用指针,只是这里的指针仅仅只是保留基本要素即可,通过EnumProcess()模拟枚举进程操作,...: 内核代码中是如何通信的,首先从用户态接收pIoBuffer到分配的缓冲区数据,并转换为pBufferPointer结构,ProbeForWrite用于检查地址是否可写入,接着会调用EnumProcess...;// 输入和输出的缓冲区(DeviceIoControl的InBuffer和OutBuffer都是它)pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;// EXE
A 在NT/2000/XP中,应用程序能够通过API函数DeviceIoControl来实现对设备的訪问—获取信息,发送命令,交换数据等。...LPVOID lpOutBuffer, // 输出数据缓冲区指针 DWORD nOutBufferSize, // 输出数据缓冲区长度 LPDWORD...发送不同的控制码,能够调用设备驱动程序的不同类型的功能。在头文件winioctl.h中,提前定义的标准设备控制码,都以IOCTL或FSCTL开头。...输入输出数据缓冲区是否须要,是何种结构,以及占多少字节空间,全然由不同设备的不同操作类型决定。在头文件winioctl.h中,已经为标准设备提前定义了一些输入输出数据结构。...A 这里有一个从MSDN上摘抄来的demo程序,演示在NT/2000/XP中怎样通过DeviceIoControl获取硬盘的基本參数。
在应用层打开设备 在应用层一般通过设备名称打开驱动中的设备对象,设备名称一般只能在内核层使用,应用层能看到的是设备的符号链接名,符号链接名一般以”\??...在本层的设备中可以使用函数IoGetCurrentIrpStackLocation得到本层设备对应的IO_STACK_LOCATION结构,下面是它对应的结构图 缓冲区方式读写操作 在调用IoCreateDeivce...DO_DIRECT_IO:内核直接通过地址映射的方式将那块缓冲区映射为内核地址,然后在驱动中使用。...当使用这种方式时内核可以在IO_STACK_LOCATION结构中的MdlAddress拿到这块内存,通过函数MmGetSystemAddressFromMdlSafe传入MdlAddress值可以得到应用层传下来的缓冲区地址..., //驱动传出数据的缓冲 DWORD nOutBufferSize, //输出数据缓冲区的大小 LPDWORD lpBytesReturned, //实际返回数据的大小 LPOVERLAPPED
领取专属 10元无门槛券
手把手带您无忧上云