首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

驱动高手来看看奇怪的有关问题,为什么简单的往用户写数据会蓝屏

2012-04-11 
驱动高手来看看奇怪的问题,为什么简单的往用户写数据会蓝屏用DeviceIoControl和驱动通信,原来没事 ,现在不

驱动高手来看看奇怪的问题,为什么简单的往用户写数据会蓝屏

用DeviceIoControl和驱动通信,原来没事 ,现在不知道出现蓝屏,困惑很长时间了也不知道原因,请高手指教,

主要问题在 requestControl 函数中.







#include "stdio.h"
#include "pch.h"
#include "..\intrface.h"
#include "ntddk.h"

char dataBuffer[4096]={'\0'};
char zml[]="zheshizml";
PDRIVER_OBJECT thisDriverObject;
UNICODE_STRING ustrSymLinkName;
typedef struct _DEVICE_EXTENSION

{

  PDEVICE_OBJECT fdo; //功能设备对象FDO
  PDEVICE_OBJECT NextStackDevice; //FDO的下层驱动设备
  UNICODE_STRING ustrDeviceName; //设备名
  UNICODE_STRING ustrSymLinkName; //符号链接
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;


typedef struct _SERVICE_DESCRIPTOR_TABLE
{
  PVOID ServiceTableBase;
  PULONG ServiceCounterTableBase;
  ULONG NumberOfService;
  ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

//__declspec(dllimport) ServiceDescriptorTableEntry KeServiceDescriptorTable;



NTSTATUS addDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS jiChaJiYong(IN PDEVICE_OBJECT fdo,
IN PIRP Irp);

NTSTATUS requestControl(IN PDEVICE_OBJECT DeviceObject, 

IN PIRP Irp);

NTSTATUS UnloadDriver (IN PDRIVER_OBJECT DriverObject);
NTSTATUS dataCopy ( void* newAddress,void* oldAddress,int copyLength );
NTSTATUS fileDispath (IN PDEVICE_OBJECT DeviceObject, 
IN PIRP Irp);

NTSTATUS DriverEntry(
  IN PDRIVER_OBJECT DriverObject,
  IN PUNICODE_STRING RegistryPath
  )
{ DEVICE_OBJECT pdo;
  DriverObject->DriverExtension->AddDevice =addDevice;
  DriverObject->MajorFunction[IRP_MJ_PNP] = jiChaJiYong;
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=requestControl; 
  DriverObject->MajorFunction[IRP_MJ_CREATE]=fileDispath;
  DriverObject->MajorFunction[IRP_MJ_CLOSE]=fileDispath;
  DriverObject->DriverUnload=UnloadDriver;
  thisDriverObject=DriverObject;
  addDevice(DriverObject,&pdo);

  return STATUS_SUCCESS; }
   
NTSTATUS addDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject) {
 NTSTATUS status;
 PDEVICE_OBJECT device_object;
 PDEVICE_EXTENSION device_extension;
 UNICODE_STRING devName,symLinkName;
 WCHAR deviceNameBuffer[] = L"\\Device\\hello66";
 WCHAR dosDeviceNameBuffer[] = L"\\??\\hello66";

 RtlInitUnicodeString(&devName,deviceNameBuffer);
 RtlInitUnicodeString(&symLinkName,dosDeviceNameBuffer);
 
 status= IoCreateDevice ( DriverObject,sizeof(DEVICE_EXTENSION),
&devName,FILE_DEVICE_UNKNOWN,0,FALSE,&device_object);
 if ( !NT_SUCCESS (status ) ) {
return status ; }
 device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension;
 device_extension->fdo=device_object;
 //device_extension->NextStackDevice =
 //IoAttachDeviceToDeviceStack(device_object, PhysicalDeviceObject);
 device_object->Flags |=DO_DIRECT_IO|DO_BUFFERED_IO;
 device_object->Flags &= ~DO_DEVICE_INITIALIZING;
 device_extension->ustrSymLinkName=symLinkName;
 //device_object->Flags|= DO_BUFFERED_IO | DO_POWER_PAGABLE;


 IoCreateSymbolicLink(&symLinkName,&devName);
 ustrSymLinkName=symLinkName;


return STATUS_SUCCESS; }


NTSTATUS jiChaJiYong(IN PDEVICE_OBJECT fdo,
IN PIRP Irp)

 NTSTATUS status;
 PDEVICE_EXTENSION dx=(PDEVICE_EXTENSION)fdo->DeviceExtension;
 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
 ULONG MinorFunction = IrpStack->MinorFunction;
 IoSkipCurrentIrpStackLocation(Irp);
 // status = IoCallDriver( dx->NextStackDevice, Irp);
 /*if( MinorFunction==IRP_MN_REMOVE_DEVICE)
 {
//取消设备接口:
  //IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
  // RtlFreeUnicodeString(&dx->ifSymLinkName);

  //调用IoDetachDevice()把fdo从设备栈中脱开:
if (dx->NextStackDevice) {
IoDetachDevice(dx->NextStackDevice); }
//删除fdo:
  IoDeleteDevice(fdo);
}

//返回值:
  return status;
}*/
//Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
return STATUS_SUCCESS; }






NTSTATUS requestControl(IN PDEVICE_OBJECT DeviceObject, 

IN PIRP Irp) 

{  
typedef struct _readWriteMode {
void* address;
int length; } RWMODE,*PRWMODE;

void *inputData,*outDataAddress=NULL;
PIO_STACK_LOCATION IrpStack; 
  ULONG ControlCode; 
  ULONG InputLength,OutputLength; 
  NTSTATUS status=STATUS_SUCCESS; 
  RWMODE rwmode={0};
  IrpStack=IoGetCurrentIrpStackLocation(Irp); //获取当前IRP所在的I/O堆栈 
  ControlCode=IrpStack->Parameters.DeviceIoControl.IoControlCode; //取得控制码 
  InputLength=IrpStack->Parameters.DeviceIoControl.InputBufferLength; 

//取输入缓冲区大小
  OutputLength=IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
#define MY_IOCTL_READ 0X90
#define MY_IOCTL_WRITE 0X91
#define MY_IOCTL_KETABLE 0x92
#define MY_IOCTL_OUTADDRESS 0x93

//取输出缓冲区大小
switch(ControlCode) { 
  case MY_IOCTL_WRITE: 
  //pIrp->AssociatedIrp.SystemBuffer;
  
  inputData=(char*)Irp->AssociatedIrp.SystemBuffer;
  
  if ( InputLength < sizeof ( rwmode) ) { 
break ; }
  dataCopy(&rwmode,inputData,sizeof ( rwmode));
  if( rwmode.length>4096) { rwmode.length=4096; }  
  dataCopy(dataBuffer,rwmode.address,rwmode.length );
  break ;

   
  //向调试器输出字符串  
  break; 
  case 0x100:
  outDataAddress=(char*)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, 
  NormalPagePriority);
  if ( outDataAddress==NULL ) {break; }
  //dataCopy (outDataAddress,dataBuffer,OutputLength);
  RtlCopyMemory (outDataAddress,zml,9);
  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information =OutputLength;
break;
  case MY_IOCTL_OUTADDRESS :
  outDataAddress=(char*)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, 
  NormalPagePriority);
  dataCopy(outDataAddress,&outDataAddress,OutputLength);
  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information =OutputLength;
  break;

  case MY_IOCTL_KETABLE :
  outDataAddress=(char*)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, 
  NormalPagePriority);
dataCopy(outDataAddress,KeServiceDescriptorTable,OutputLength);
Irp->IoStatus.Status = STATUS_SUCCESS;


  Irp->IoStatus.Information =OutputLength;
  break;
  case 0x90 : 
outDataAddress=(char*)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, 
  NormalPagePriority);
strcpy(outDataAddress,zml);
Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information =9;
break;
  default: 
  status=STATUS_INVALID_DEVICE_REQUEST; 

//输入的控制码不支持 


  IoCompleteRequest(Irp, IO_NO_INCREMENT); 
  return status ;
 
  }

NTSTATUS UnloadDriver (IN PDRIVER_OBJECT DriverObject) {
NTSTATUS status=STATUS_SUCCESS;
PDEVICE_EXTENSION p=(PDEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension;
status= IoDeleteSymbolicLink
(&(p->ustrSymLinkName));
if ( !NT_SUCCESS (status ) ) {
status=IoDeleteSymbolicLink( &ustrSymLinkName); }
IoDeleteDevice(DriverObject->DeviceObject); 
return status;
}


NTSTATUS dataCopy ( void* newAddress,void* oldAddress,int copyLength ) {
char* add1=(char*)newAddress;
char* add2=(char*)oldAddress;
int i=0;
for ( i=0;i<=copyLength;i++ ) {
*add1=*add2;
add1++;
add2++; }
return STATUS_SUCCESS; }
NTSTATUS fileDispath ( IN PDEVICE_OBJECT DeviceObject, 
IN PIRP Irp ) {
return STATUS_SUCCESS; }

[解决办法]
建议把格式调整好不然看着头疼
[解决办法]
表示看起来很有压力
[解决办法]
请把蓝屏时的信息贴出来
或者给dump
[解决办法]
在函数 内,有两个IOCTL CODE,
 其中,case 0x100:
有语句 RtlCopyMemory (outDataAddress,zml,9),如果输出缓冲区大小不到9,可能会缓冲区越界。
 还有,case 0x90 :
有语句:strcpy(outDataAddress,zml);如果输出缓冲区SIZE小于字符串zml的长度,也可能越界。
看看是不是这个原因?

热点排行