Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55244
  • 博文数量: 13
  • 博客积分: 850
  • 博客等级: 准尉
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-10 16:20
文章存档

2008年(13)

我的朋友
最近访客

分类: WINDOWS

2008-10-30 21:59:31

首先每个驱动程序都有一个入口:DriverEntry.
原型:NTSTATUS  DriverEntry(  IN PDRIVER_OBJECT  DriverObject,  //驱动对象
                             IN PUNICODE_STRING  RegistryPath); //注册表路径
A driver's DriverEntry routine executes in a system thread context at IRQL = PASSIVE_LEVEL.
也就是他是系统回调的。
DriverEntry is the first routine called after a driver is loaded, and is responsible for initializing the driver.
它在驱动加载的时候执行,主要用于初始化驱动内容。比如全局变量,功能函数等.
除了DriverEntry最重要外,对于具体Pnp硬件还有一个函数也非常重要。那就是AddDevice.
原型:NTSTATUS
   AddDevice(IN PDRIVER_OBJECT  DriverObject,
             IN PDEVICE_OBJECT  PhysicalDeviceObject);
他的功能和DriverEntry类似,也是初始化的,也是系统自动调用。DriverEntry是初始驱动对象,那么AddDevice是初始化设备对象.在WDM模型中,设备对象就是PDEVICE_OBJECT。
The driver's DriverEntry routine must store the AddDevice routine's address in DriverObject->DriverExtension->AddDevice.
这里面的设备对象就是我们主要定义的内容,DriverExtension代表着每个设备基本设施。而且是开发人员自定义.
An AddDevice routine's primary responsibilities are calling IoCreateDevice to create a device object, then calling IoAttachDeviceToDeviceStack to attach the device object to the device stack.
这个函数是在设备加入设备栈的时候调用的,表明我们已经有一个设备插入了系统.
设备基本操作,主要依靠I/O管理器创建的IRP(I/O request packet,即IO请求包)以及IO_STACK_LOCATION(IO本地栈)控制.这两个数据结构可以说是驱动程序的血液.
typedef struct _IRP {//这里仅列举主要内容
  .
  .
  PMDL  MdlAddress;              //它本身是描述用户模式虚拟地址,但同时也有该缓冲区锁定的物理地址.
  ULONG  Flags;                  // IRP_NOCACHE
        IRP_PAGING_IO
     IRP_MOUNT_COMPLETION
     IRP_SYNCHRONOUS_API
     IRP_ASSOCIATED_IRP
     IRP_BUFFERED_IO
     IRP_DEALLOCATE_BUFFER
     IRP_INPUT_OPERATION
     IRP_SYNCHRONOUS_PAGING_IO
     IRP_CREATE_OPERATION
     IRP_READ_OPERATION
     IRP_WRITE_OPERATION
     IRP_CLOSE_OPERATION
     IRP_DEFER_IO_COMPLETION
  union {                        
    struct _IRP  *MasterIrp;
    .
    .
    PVOID  SystemBuffer;
  } AssociatedIrp;              //三个联合结构的指针,只有一个有效.这里编程主要用到的是SystemBuffer域.
  .
  .
  IO_STATUS_BLOCK  IoStatus;    //这个结构很重要,IRP整个流程都经常判断,他有两个域,NTSTATUS Status和ULONG_PTR Information,前者状态,后者一般用于保存临时数据
  KPROCESSOR_MODE  RequestorMode; //显然,表示模式状态,用户模式还是内核模式.
  BOOLEAN PendingReturned;        //TRUE表示有驱动正在处理
  .
  .
  BOOLEAN  Cancel;                //TRUE,表示已经IoCancelIrp已经调用,请求取消.
  KIRQL  CancelIrql;              //显然是一个IRQL值
  .
  .
  PDRIVER_CANCEL  CancelRoutine;  //这里指明取消例程
  PVOID UserBuffer;                 //显然表示用户缓冲区
  union {
    struct {
    .
    .
    union {
      KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
      struct {
        PVOID  DriverContext[4];
      };
    };
    .
    .
    PETHREAD  Thread;
    .
    .
    LIST_ENTRY  ListEntry;
    .
    .
    } Overlay;
  .
  .
  } Tail;
} IRP, *PIRP;

Tail.Overlay.DeviceQueueEntry
If IRPs are queued in the device queue associated with the driver’s device object, this field links IRPs in the device queue. These links can be used only while the driver is processing the IRP.
//关联驱动设备对象的入口点
Tail.Overlay.DriverContext
If IRPs are not queued in the device queue associated with the driver’s device object, this field can be used by the driver to store up to four pointers. This field can be used only while the driver owns the IRP.
//如果没有被关联到设备对象队列中,那么只有这个字段能被IRP使用.
Tail.Overlay.Thread
Is a pointer to the caller’s thread control block. Higher-level drivers that allocate IRPs for lower-level removable-media drivers must set this field in the IRPs they allocate. Otherwise, the FSD cannot determine which thread to notify if the underlying device driver indicates that the media requires verification.
//指向一个调用控制线程.
Tail.Overlay.ListEntry
If a driver manages its own internal queues of IRPs, it uses this field to link one IRP to the next. These links can be used only while the driver is holding the IRP in its queue or is processing the IRP.
//一个驱动程序内部IRP链.

typedef struct _IO_STACK_LOCATION {
  UCHAR  MajorFunction;                                    //主功能号
  UCHAR  MinorFunction;                                   //次功能号
  UCHAR  Flags;
  UCHAR  Control;
//Drivers can check this member to determine whether it is set with SL_PENDING_RETURNED. Drivers have read-only access to this member.
//驱动程序检查是否被正在处理中,驱动对它有只读权限.
  union {
        //
        // Parameters for IRP_MJ_CREATE
        //
        struct {
            PIO_SECURITY_CONTEXT SecurityContext;
            ULONG Options;
            USHORT POINTER_ALIGNMENT FileAttributes;
            USHORT ShareAccess;
            ULONG POINTER_ALIGNMENT EaLength;
        } Create;
        //
        // Parameters for IRP_MJ_READ
        //
        struct {
            ULONG Length;
            ULONG POINTER_ALIGNMENT Key;
            LARGE_INTEGER ByteOffset;
        } Read;
        //
        // Parameters for IRP_MJ_WRITE
        //
        struct {
            ULONG Length;
            ULONG POINTER_ALIGNMENT Key;
            LARGE_INTEGER ByteOffset;
        } Write;
        //
        // Parameters for IRP_MJ_QUERY_INFORMATION
        //
        struct {
            ULONG Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
        } QueryFile;
        //
        // Parameters for IRP_MJ_SET_INFORMATION
        //
        struct {
            ULONG Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
            PFILE_OBJECT FileObject;
            union {
                struct {
                    BOOLEAN ReplaceIfExists;
                    BOOLEAN AdvanceOnly;
                };
                ULONG ClusterCount;
                HANDLE DeleteHandle;
            };
        } SetFile;
        //
        // Parameters for IRP_MJ_QUERY_VOLUME_INFORMATION
        //
        struct {
            ULONG Length;
            FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
        } QueryVolume;
        //
        // Parameters for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
        //
        struct {
            ULONG OutputBufferLength;
            ULONG POINTER_ALIGNMENT InputBufferLength;
            ULONG POINTER_ALIGNMENT IoControlCode;
            PVOID Type3InputBuffer;
        } DeviceIoControl;
        //
        // Nonsystem service parameters.
        //
        // Parameters for IRP_MN_MOUNT_VOLUME
        //
        struct {
            PVOID DoNotUse1;
            PDEVICE_OBJECT DeviceObject;
        } MountVolume;
        //
        // Parameters for IRP_MN_VERIFY_VOLUME
        //
        struct {
            PVOID DoNotUse1;
            PDEVICE_OBJECT DeviceObject;
        } VerifyVolume;
        //
        // Parameters for Scsi using IRP_MJ_INTERNAL_DEVICE_CONTROL
        //
        struct {
            struct _SCSI_REQUEST_BLOCK *Srb;
        } Scsi;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_RELATIONS
        //
        struct {
            DEVICE_RELATION_TYPE Type;
        } QueryDeviceRelations;
        //
        // Parameters for IRP_MN_QUERY_INTERFACE
        //
        struct {
            CONST GUID *InterfaceType;
            USHORT Size;
            USHORT Version;
            PINTERFACE Interface;
            PVOID InterfaceSpecificData;
        } QueryInterface;
        //
        // Parameters for IRP_MN_QUERY_CAPABILITIES
        //
        struct {
            PDEVICE_CAPABILITIES Capabilities;
        } DeviceCapabilities;
        //
        // Parameters for IRP_MN_FILTER_RESOURCE_REQUIREMENTS
        //
        struct {
            PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList;
        } FilterResourceRequirements;
        //
        // Parameters for IRP_MN_READ_CONFIG and IRP_MN_WRITE_CONFIG
        //
        struct {
            ULONG WhichSpace;
            PVOID Buffer;
            ULONG Offset;
            ULONG POINTER_ALIGNMENT Length;
        } ReadWriteConfig;
        //
        // Parameters for IRP_MN_SET_LOCK
        //
        struct {
            BOOLEAN Lock;
        } SetLock;
        //
        // Parameters for IRP_MN_QUERY_ID
        //
        struct {
            BUS_QUERY_ID_TYPE IdType;
        } QueryId;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_TEXT
        //
        struct {
            DEVICE_TEXT_TYPE DeviceTextType;
            LCID POINTER_ALIGNMENT LocaleId;
        } QueryDeviceText;
        //
        // Parameters for IRP_MN_DEVICE_USAGE_NOTIFICATION
        //
        struct {
            BOOLEAN InPath;
            BOOLEAN Reserved[3];
            DEVICE_USAGE_NOTIFICATION_TYPE POINTER_ALIGNMENT Type;
        } UsageNotification;
        //
        // Parameters for IRP_MN_WAIT_WAKE
        //
        struct {
            SYSTEM_POWER_STATE PowerState;
        } WaitWake;
        //
        // Parameter for IRP_MN_POWER_SEQUENCE
        //
        struct {
            PPOWER_SEQUENCE PowerSequence;
        } PowerSequence;
        //
        // Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER
        //
        struct {
            ULONG SystemContext;
            POWER_STATE_TYPE POINTER_ALIGNMENT Type;
            POWER_STATE POINTER_ALIGNMENT State;
            POWER_ACTION POINTER_ALIGNMENT ShutdownType;
        } Power;
        //
        // Parameters for IRP_MN_START_DEVICE
        //
        struct {
            PCM_RESOURCE_LIST AllocatedResources;
            PCM_RESOURCE_LIST AllocatedResourcesTranslated;
        } StartDevice;
        //
        // Parameters for WMI Minor IRPs
        //
        struct {
            ULONG_PTR ProviderId;
            PVOID DataPath;
            ULONG BufferSize;
            PVOID Buffer;
        } WMI;
        //
        // Others - driver-specific
        //
        struct {
            PVOID Argument1;
            PVOID Argument2;
            PVOID Argument3;
            PVOID Argument4;
        } Others;
    } Parameters;
//A union that depends on the major and minor IRP function code values contained in MajorFunction and MinorFunction.
//一个仅依靠主功能号和次功能号的联合.
  PDEVICE_OBJECT  DeviceObject;
//处理这个IRP的设备对象
  PFILE_OBJECT  FileObject;
//驱动程序文件对象.
  .
  .
} IO_STACK_LOCATION, *PIO_STACK_LOCATION;
看到以上的Parameters是不是想起了LINUX下的file_operation呢,其实都差不多,只不多原理不一样,Linux依靠的是filesystem,而Windows则依靠I/O Manager,相比WINDOWS更先进些。
上面多次提到过I/O缓冲。其实I/O Manager管理IRP是有一套策略的。这在设计驱动时候,就得先设计好。
处理IRP用到I/O缓冲的,就那几种IRP,读写及控制.
先看读写的策略。(3种)DO_BUFFER_IO,DO_DIRECT_IO.两都皆不是。
DO_BUFFER_IO,
  IRP_MJ_READ指的是驱动读应用程序里,此时用到AssociatedIrp.SystemBuffer和UserBuffer
  IRP_MJ_WRITE就是应用程序写驱动,此时UserBuffer为NULL,只涉及到AssociatedIrp.SystemBuffer.
DO_DIRECT_IO
  程序将一地址放到MdlAddress 域内,让驱动读或者写。当然驱动程序通常是调用MmGetSystemAddressForMdl得到这个地址.
两都皆不是,这种情况很少,需要驱动程序自己处理缓冲。
看完了IRP_MJ_READ和IRP_MJ_WRITE,再看IRP_MJ_CONTROL.
IOCTL有四种策略:Method_Buffered,Method_IN_Direct,Method_OUT_Direct,Method_Neither.
Method_Buffered:(输入输出缓冲IO)
       这个也是用到了AssociatedIrp.SystemBuffer(此时是驱动程序用的,使用缓冲,缓冲输入)和UserBuffer(作为用户缓冲输出地址).
       输入缓冲区:IoctlBuffer 输出缓冲区:IoctlBuffer
Method_IN_Direct:(直接输入缓冲输出)
       这个也是用到了AssociatedIrp.SystemBuffer(此时是驱动程序用的,没用缓冲,直接输入)和UserBuffer(作为用户缓冲输出地址).
       输入缓冲区:IoctlBuffer 输出缓冲区:Mdl
Method_OUT_Direct:(直接输出缓冲输入)
       AssociatedIrp.SystemBuffer,使用缓冲把这个数据拷贝到缓冲区,UserBuffer=NULL
       输入缓冲区:IoctlBuffer 输出缓冲区:Mdl
Method_Neither:输入缓冲地址放到I/O堆栈单元Parameters.DeveiceIoControl.TypeInputBuffer域中,UserBuffer输出.
          输入缓冲区:Type3InputBuffer  输出缓冲区:UserBuffer
 
阅读(1164) | 评论(0) | 转发(0) |
0

上一篇:DriverWork基本类

下一篇:RSA算法

给主人留下些什么吧!~~