[WDM]驱动程序框架 我还没写完 好忙 没时间玩

时间:2022-04-25 15:58:43

#ifdef __cplusplus

extern "C"
{
#endif

#include "F://WINDDK//3790//inc//ddk//w2k//ntddk.h"

#ifdef __cplusplus
}
#endif

typedef struct _DEVICE_EXTENSION
{
    PDEVICE_OBJECT    fdo;
    PDEVICE_OBJECT    NextStackDevice;
    UNICODE_STRING    ifSymLinkName;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

#define NT_DEVICE_NAME  L"//Device//HHH"
#define DOS_DEVICE_NAME  L"//DosDevices//HHH"


NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT PhysicalDeviceObject);

NTSTATUS Pnp(IN PDEVICE_OBJECT fdo,
                        IN PIRP Irp);

NTSTATUS DrvDispatch(IN PDEVICE_OBJECT device,IN PIRP Irp);
void DrvUnload(IN PDRIVER_OBJECT DriverObject);

#define USER_CONTROL_CODE  1000

#include "main.h"

//-------------------------------------------------------------------------
// Function Name    :DriverEntry
// Parameter(s)     :PDRIVER_OBJECT DriverObject 指向驱动程序对象的指针
//     :PUNICODE_STRING RegistryPath 驱动程序的服务主键
// Return           :NTSTATUS
// Memo             :驱动程序入口
//-------------------------------------------------------------------------
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
      IN PUNICODE_STRING RegistryPath)
{
 DbgPrint( "DriverEntry/n" );

 NTSTATUS status = STATUS_SUCCESS;

 // 创建设备
 PDEVICE_OBJECT lpDeviceObject = 0;
 UNICODE_STRING DevNameString;
 RtlInitUnicodeString( &DevNameString, NT_DEVICE_NAME);
 status = IoCreateDevice( DriverObject //驱动程序对象
  , 0         //扩展设备的大小,由于不需要,所以置0
  , &DevNameString     //设备名称
  , FILE_DEVICE_UNKNOWN    //设备类型
  , 0         //指示设备允许的操作
  , FALSE        //如果为TRUE,表示只能有一个线程使用该设备,为FALSE,则没有限制
  , &lpDeviceObject     //返回的设备对象
  );
 if( !NT_SUCCESS(status) )
  return status;

 


 // 创建符号连接
 UNICODE_STRING DevLinkString;
 RtlInitUnicodeString( &DevLinkString, DOS_DEVICE_NAME);
 status = IoCreateSymbolicLink( &DevLinkString, &DevNameString);

 if( NT_SUCCESS(status) )
 {
  // 设置函数指针
  DriverObject->DriverExtension->AddDevice = AddDevice;
  DriverObject->MajorFunction[IRP_MJ_PNP] = Pnp;
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
  DriverObject->DriverUnload = DrvUnload;
 }
 
 return status;
}

//-------------------------------------------------------------------------
// Function Name    :DrvUnload
// Parameter(s)     :PDRIVER_OBJECT DriverObject 指向驱动程序对象的指针
// Return           :void
// Memo             :删除设备
//-------------------------------------------------------------------------
void DrvUnload(IN PDRIVER_OBJECT DriverObject)
{
 UNICODE_STRING DeviceLinkString;
 
 RtlInitUnicodeString( &DeviceLinkString, DOS_DEVICE_NAME);
 IoDeleteSymbolicLink( &DeviceLinkString);  //删除符号连接
 
 PDEVICE_OBJECT DeviceObjectTemp1=NULL;
 PDEVICE_OBJECT DeviceObjectTemp2=NULL;
 if( DriverObject != NULL )
 {
  DeviceObjectTemp1 = DriverObject->DeviceObject;
  
  //删除设备
  while( DeviceObjectTemp1 != NULL )
  {
   DeviceObjectTemp2 = DeviceObjectTemp1;
   DeviceObjectTemp1 = DeviceObjectTemp1->NextDevice;
   IoDeleteDevice(DeviceObjectTemp2);
  }
 }
}


//-------------------------------------------------------------------------
// Function Name    :DrvDispatch
// Parameter(s)     :
//     :
// Return           :
// Memo             :驱动消息分发
//-------------------------------------------------------------------------
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
 NTSTATUS status = STATUS_SUCCESS;
    ULONG IoControlCodes = 0;             //I/O控制代码
   
 //得到当前调用者的IRP
 PIO_STACK_LOCATION IrpStack = NULL;
 IrpStack = IoGetCurrentIrpStackLocation(pIrp);   

 //设置IRP状态
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;
 
    switch (IrpStack->MajorFunction)
    {
 case IRP_MJ_CREATE:
  break;
  
 case IRP_MJ_CLOSE:
  break;
  
 case IRP_MJ_DEVICE_CONTROL:
  {
   //取得I/O控制代码
   IoControlCodes = IrpStack->Parameters.DeviceIoControl.IoControlCode;
   
   switch(IoControlCodes)
   {
    
   // 自定义控制码
   case USER_CONTROL_CODE:
    DbgPrint("Starting /"Hello World/"/n");
    break;
    
   default:
    pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    break;
   }   
   break;
  }// case IRP_MJ_DEVICE_CONTROL
  
  
  default:
   break;
    }
 
    status = pIrp->IoStatus.Status; 
    IoCompleteRequest( pIrp, IO_NO_INCREMENT);
 
    return status;
}


//-------------------------------------------------------------------------
// Function Name    :WDMAddDevice
// Parameter(s)     :
//     :
// Return           :
// Memo             :添加设备
//-------------------------------------------------------------------------
NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject,
       IN PDEVICE_OBJECT PhysicalDeviceObject)
{
 //定义一个NTSTATUS类型的返回值:
 NTSTATUS status;
 //定义一个功能设备对象(Functional Device Object):
 PDEVICE_OBJECT fdo;
 
 //创建我们的功能设备对象,并储存到fdo中:
 status = IoCreateDevice(
  DriverObject,//驱动程序对象
  sizeof(DEVICE_EXTENSION),//要求的设备扩展的大小
  NULL,//设备名称,这里为NULL
  FILE_DEVICE_UNKNOWN,//设备的类型,在标准头文件WDM.H或NTDDK.H中列出的FILE_DEVICE_xxx值之一
  0,//各种常量用OR组合在一起,指示可删除介质、只读等。
  FALSE,//如果一次只有一个线程可以访问该设备,为TRUE,否则为FALSE
  &fdo);//返回的设备对象
 
 //NT_SUCCESS宏用于测试IoCreateDevice内核是否成功完成。不要忘记检查对内核的所有调用是否成功。NT_ERROR宏不等同于!NT_SUCCESS,最好使用!NT_SUCCESS,因为除了错误外,它还截获警告信息。
 if( !NT_SUCCESS(status))
  return status;
 
 //创建一个设备扩展对象dx,用于存储指向fdo的指针:
 PDEVICE_EXTENSION dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
 dx->fdo = fdo;
 
 //用IoAttachDeviceToDeviceStack函数把HelloWDM设备挂接到设备栈:
 dx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
 
 //设置fdo的flags。有两个“位”是必须改变的,一个是必须清除DO_DEVICE_INITIALIZING标志,如果在DriverEntry例程中调用IoCreateDevice(),就不需要清除这个标志位。还有一个是必须设置DO_BUFFER_IO标志位:
 fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
 fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
 //返回值:
 return STATUS_SUCCESS;
}


//-------------------------------------------------------------------------
// Function Name    :WDMPnp
// Parameter(s)     :
//     :
// Return           :
// Memo             :处理“即插即用”消息
//-------------------------------------------------------------------------
NTSTATUS Pnp(IN PDEVICE_OBJECT fdo,
    IN PIRP Irp)
{
 //创建一个设备扩展对象dx,用于存储指向fdo的指针:
 PDEVICE_EXTENSION dx=(PDEVICE_EXTENSION)fdo->DeviceExtension;
 
 //首先要通过函数IoGetCurrentIrpStackLocation()得到当前的IRP,并由此得到Minor Function:
 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
 ULONG MinorFunction = IrpStack->MinorFunction;
 
 //然后把这个Minor Function传递给下一个设备栈:
 IoSkipCurrentIrpStackLocation(Irp);
 NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp);
 
 //处理“即插即用”次功能代码:
 //当Minor Function等于IRP_MN_REMOVE_DEVICE时,说明有设备被拔出或卸下,这时要取消资源分配并删除设备:
 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;
}