zoukankan      html  css  js  c++  java
  • IO设备控制操作

    除了 读设备和  写设备 外  还可以有一个API DeviceIoControl 操作设备 创建一个IRP_MJ_DEVICE_CONTROL 类型的IRP 

    DeviceIoControl
    
    hDevice Long,设备句柄
    dwIoControlCode Long,应用程序调用驱动程序的控制命令,就是IOCTL_XXX IOCTLs。
    lpInBuffer Any,应用程序传递给驱动程序的数据缓冲区地址。
    nInBufferSize Long,应用程序传递给驱动程序的数据缓冲区大小,字节数。
    lpOutBuffer Any,驱动程序返回给应用程序的数据缓冲区地址。
    nOutBufferSize Long,驱动程序返回给应用程序的数据缓冲区大小,字节数。
    lpBytesReturned Long,驱动程序实际返回给应用程序的数据字节数地址。
    lpOverlapped OVERLAPPED,这个结构用于重叠操作。针对同步操作,请用ByVal As Long传递零值


    应用程序 源码:

    头文件:

    #ifndef IOCTLS_H
    #define IOCTLS_H
    
    
    #ifndef CTL_CODE
    	#pragma message("CTL_CODE undefined. Include winioctl.h or wdm.h")
    #endif
    
    
    #define IOCTL_TEST1 CTL_CODE(
    			FILE_DEVICE_UNKNOWN, 
    			0x800, 
    			METHOD_BUFFERED, 
    			FILE_ANY_ACCESS)
    
    
    #define IOCTL_TEST2 CTL_CODE(
    			FILE_DEVICE_UNKNOWN, 
    			0x801, 
    			METHOD_IN_DIRECT, 
    			FILE_ANY_ACCESS)
    
    
    #define IOCTL_TEST3 CTL_CODE(
    			FILE_DEVICE_UNKNOWN, 
    			0x802, 
    			METHOD_NEITHER, 
    			FILE_ANY_ACCESS)
    
    
    #endif
    CPP文件:

    #include <windows.h>
    #include <stdio.h>
    //使用CTL_CODE必须加入winioctl.h
    #include <winioctl.h>
    #include "..NT_DriverIoctls.h"
    
    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: %d
    ",
    			"MyWDMDevice", GetLastError() );
    		return 1;
    	}
    
    	UCHAR InputBuffer[10];
    	UCHAR OutputBuffer[10];
    	//将输入缓冲区全部置成0XBB
    	memset(InputBuffer,0xBB,10);
    	DWORD dwOutput;
    	//输入缓冲区作为输入,输出缓冲区作为输出
    
    	BOOL bRet;
    	//缓冲内存模式  IOCTL////////////////////////////////////////////////
    	bRet = DeviceIoControl(hDevice, IOCTL_TEST1, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);
    	//InputBuffer 为输入缓冲区		OutputBuffer为接收的缓冲区
    	if (bRet)
    	{
    		printf("Output buffer:%d bytes
    ",dwOutput);
    		for (int i=0;i<(int)dwOutput;i++)
    		{
    			printf("%02X ",OutputBuffer[i]);
    		}
    		printf("
    ");
    	}
    	//直接内存模式  IOCTL////////////////////////////////////////////////
    	bRet = DeviceIoControl(hDevice, IOCTL_TEST2, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);
    	if (bRet)
    	{
    		printf("Output buffer:%d bytes
    ",dwOutput);
    		for (int i=0;i<(int)dwOutput;i++)
    		{
    			printf("%02X ",OutputBuffer[i]);
    		}
    		printf("
    ");
    	}
    	//其他内存模式  IOCTL////////////////////////////////////////////////
     	bRet = DeviceIoControl(hDevice, IOCTL_TEST3, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);
    	if (bRet)
    	{
    		printf("Output buffer:%d bytes
    ",dwOutput);
    		for (int i=0;i<(int)dwOutput;i++)
    		{
    			printf("%02X ",OutputBuffer[i]);
    		}
    		printf("
    ");
    	}
    
    	CloseHandle(hDevice);
    
    	return 0;
    }
    内核模式  显示  应用程序字符串:

    #pragma PAGEDCODE
    NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj,
    								 IN PIRP pIrp)
    {
    	NTSTATUS status = STATUS_SUCCESS;
    	KdPrint(("Enter HelloDDKDeviceIOControl
    "));
    	//得到当前堆栈
    	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
    	//得到输入缓冲区大小
    	ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
    	//得到输出缓冲区大小
    	ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
    	//得到IOCTL码
    	ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
    
    	ULONG info = 0;
    
    	switch (code)
    	{						// process request
    		case IOCTL_TEST1:
    		{
    			KdPrint(("IOCTL_TEST1
    "));
    			//缓冲区方式IOCTL
    			//显示输入缓冲区数据
     			UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
    			for (ULONG i=0;i<cbin;i++)
    			{
    				KdPrint(("%X
    ",InputBuffer[i]));
    			}
    
    			//操作输出缓冲区
    			UCHAR* OutputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
    			memset(OutputBuffer,0xAA,cbout);
    			//设置实际操作输出缓冲区长度
     			info = cbout;
    			break;
    		}
    		case IOCTL_TEST2:
    		{
    			KdPrint(("IOCTL_TEST2
    "));
    			//缓冲区方式IOCTL
    			//显示输入缓冲区数据
    
    			//缓冲区方式IOCTL
    			//显示输入缓冲区数据
     			UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
    			for (ULONG i=0;i<cbin;i++)
    			{
    				KdPrint(("%X
    ",InputBuffer[i]));
    			}
    
    			//pIrp->MdlAddress为DeviceIoControl输出缓冲区地址相同
    			KdPrint(("User Address:0X%08X
    ",MmGetMdlVirtualAddress(pIrp->MdlAddress)));
    
     			UCHAR* OutputBuffer = (UCHAR*)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority);
     			//InputBuffer被映射到内核模式下的内存地址,必定在0X80000000-0XFFFFFFFF之间
     			memset(OutputBuffer,0xAA,cbout);
    			//设置实际操作输出缓冲区长度
     			info = cbout;
    			break;
    		}
    		case IOCTL_TEST3:
    		{
    			KdPrint(("IOCTL_TEST3
    "));
    
    			//缓冲区方式IOCTL
    			//显示输入缓冲区数据
     			UCHAR* UserInputBuffer = (UCHAR*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
    			KdPrint(("UserInputBuffer:0X%0X
    ",UserInputBuffer));
    
    			//得到用户模式地址
    			PVOID UserOutputBuffer = pIrp->UserBuffer;
    			
    			KdPrint(("UserOutputBuffer:0X%0X
    ",UserOutputBuffer));
    
    			__try
    			{
    				KdPrint(("Enter __try block
    "));
    
    				//判断指针是否可读
    				ProbeForRead(UserInputBuffer,cbin,4);
    				//显示输入缓冲区内容
    				for (ULONG i=0;i<cbin;i++)
    				{
    					KdPrint(("%X
    ",UserInputBuffer[i]));
    				}
    
    				//判断指针是否可写
    				ProbeForWrite(UserOutputBuffer,cbout,4);
    
    				//操作输出缓冲区
    				memset(UserOutputBuffer,0xAA,cbout);
    
    				//由于在上面引发异常,所以以后语句不会被执行!
    				info = cbout;
    
    				KdPrint(("Leave __try block
    "));
    			}
    			__except(EXCEPTION_EXECUTE_HANDLER)
    			{
    				KdPrint(("Catch the exception
    "));
    				KdPrint(("The program will keep going
    "));
    				status = STATUS_UNSUCCESSFUL;
    			}
    
     			info = cbout;
    			break;
    		}
    
    		default:
    			status = STATUS_INVALID_VARIANT;
    	}
    
    	// 完成IRP
    	pIrp->IoStatus.Status = status;
    	pIrp->IoStatus.Information = info;	// bytes xfered
    	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    
    	KdPrint(("Leave HelloDDKDeviceIOControl
    "));
    
    	return status;
    }






  • 相关阅读:
    【源码笔记】BlogEngine.Net 中的权限管理
    Asp.Net MVC 分页、检索、排序整体实现
    AngularJS 初印象------对比 Asp.net MVC
    Asp.Net MVC Filter 实现方式和作用范围控制
    上传图片压缩+水印(文字、图片)+验证码
    2014年及五年计划
    【读书笔记】Asp.Net MVC 上传图片到数据库(会的绕行)
    VS2012 生成事件
    CSS position绝对定位absolute relative
    CSS兼容性解决方法!important的IE7,Firefox问题
  • 原文地址:https://www.cnblogs.com/zcc1414/p/3982508.html
Copyright © 2011-2022 走看看