Windows驱动的IOCTL

                  

       虽然目前,没有具体的项目,但是Direct3D学习还是会继续。其实很多东西,虽然看起来现在没多大用处,说不定将来有很

大的用处。这个无法衡量,多学点,总是有好处的。后面,断断续续,会把另外的几个方向,WDDM 驱动,数据结构算法,也开始捡

起来继续。现在需要的是,将知识变成体系。所以,需要大量的总结。

       我们今天看一下Windows驱动中的IOCTL,IOCTL顾名思义,就是IO控制码。也就是输入输出控制码。Window驱动中大量充斥着

这样的控制码。前面的文章,我们知道,所有在驱动中的流都是以IRP的形式进行的。而用来标识IRP的就是这些IOCTL码。回忆一下

MSDN中的IRP的结构。
 typedef struct _IRP {
    .
    .
    PMDL  MdlAddress;
    ULONG  Flags;
    union {
      struct _IRP  *MasterIrp;
       .
       .
       PVOID  SystemBuffer;
     } AssociatedIrp;
     .
     .
     IO_STATUS_BLOCK  IoStatus;
     KPROCESSOR_MODE  RequestorMode;
     BOOLEAN PendingReturned;
     .
     .
     BOOLEAN  Cancel;
     KIRQL  CancelIrql;
     .
     .
     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;

                我们知道IRP的一些信息都是存储在IO的堆栈中的:
  typedef struct _IO_STACK_LOCATION {
       UCHAR  MajorFunction;
       UCHAR  MinorFunction;
       UCHAR  Flags;
       UCHAR  Control;
        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;
     PDEVICE_OBJECT  DeviceObject;
     PFILE_OBJECT  FileObject;
     .
     .
  } IO_STACK_LOCATION, *PIO_STACK_LOCATION;


           在IO堆栈中,我们看到了大量的IOCTL。这个是在WDM中的,在WDF对其进行了封装。我们在WDF中,一般使用如下的3个函

数向其他模块发送这些IRP.我认为REQUEST是WDM中的IRP和IO_STATION_LOCATION的封装。

           看一下异步函数:   

WdfIoTargetFormatRequestForInternalIoctl,WdfIoTargetFormatRequestForInternalIoctlOthers,WdfIoTargetFormatRequestForI

octl,WdfIoTargetFormatRequestForRead,WdfIoTargetFormatRequestForWrite,这是是异步的,后面需要设置完成例程,和真正发

送请求。
    再看一下同步的:
WdfIoTargetSendInternalIoctlOthersSynchronously,WdfIoTargetSendInternalIoctlSynchronously,

WdfIoTargetSendIoctlSynchronously,WdfIoTargetSendReadSynchronously,WdfIoTargetSendWriteSynchronously,同步需要等待

,所以可以直接发。

    先看一下异步的例子:
    NTSTATUS
NICSendOidRequestToTargetAsync(
    IN WDFIOTARGET  IoTarget,
    IN WDFREQUEST  Request,
    IN PFILE_OBJECT  FileObject,
    IN ULONG  IoctlControlCode,
    IN OUT PVOID  InputBuffer,
    IN ULONG  InputBufferLength,
    IN OUT PVOID  OutputBuffer,
    IN ULONG  OutputBufferLength,
    OUT PULONG  BytesReadOrWritten
    )
{
    NTSTATUS  status;
    PREQUEST_CONTEXT  reqContext;
    WDF_REQUEST_REUSE_PARAMS  params;
    WDFMEMORY  inputMem, outputMem;
   
    WDF_REQUEST_REUSE_PARAMS_INIT(
                                  &params,
                                  WDF_REQUEST_REUSE_NO_FLAGS,
                                  STATUS_SUCCESS
                                  );
    status = WdfRequestReuse(Request, &params);
    if (!NT_SUCCESS(status)){
        return status;
    }

    reqContext = GetRequestContext(Request);

    inputMem = outputMem = NULL;
   
    if (InputBuffer != NULL) {
        status = WdfMemoryAssignBuffer(
                                       reqContext->InputMemory,
                                       InputBuffer,
                                       InputBufferLength
                                       );
        if (!NT_SUCCESS(status)) {
             return status;
        }
        inputMem = reqContext->InputMemory;
    }

    if (OutputBuffer != NULL) {
        status = WdfMemoryAssignBuffer(
                                       reqContext->OutputMemory,
                                       OutputBuffer,
                                       OutputBufferLength
                                       );
        if (!NT_SUCCESS(status)) {
            return status;
        }
        outputMem = reqContext->OutputMemory;
    }

    status = WdfIoTargetFormatRequestForIoctl(
                                              IoTarget,
                                              Request,
                                              IoctlControlCode,
                                              inputMem,
                                              NULL,
                                              outputMem,
                                              NULL
                                              );
    if (!NT_SUCCESS(status)) {
        return status;
    }

    WdfRequestSetCompletionRoutine(
                                   Request,
                                   NICSendOidRequestToTargetAsyncCompletionRoutine,
                                   BytesReadOrWritten
                                   );

    if (WdfRequestSend(
                       Request,
                       IoTarget,
                       WDF_NO_SEND_OPTIONS
                       ) == FALSE) {
        status = WdfRequestGetStatus(Request);
    }
    return status;
}

 再看一下同步的:
 
WDF_MEMORY_DESCRIPTOR  outputDescriptor;
NTSTATUS  status;
HID_COLLECTION_INFORMATION  collectionInformation;

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
                                  &outputDescriptor,
                                  (PVOID) &collectionInformation,
                                  sizeof(HID_COLLECTION_INFORMATION)
                                  );

status = WdfIoTargetSendIoctlSynchronously(
                                           hidTarget,
                                           NULL,
                                           IOCTL_HID_GET_COLLECTION_INFORMATION,
                                           NULL,
                                           &outputDescriptor,
                                           NULL,
                                           NULL
                                           )

上面是发送,我们在驱动中如何进行处理这些IOCTL了,有些IOCTL,已经被WDF封装了,直接成为了驱动对象的一些域了,比如

IRP_MN_START_DEVICE,IRP_MN_FILTER_RESOURCE_REQUIREMENTS 等。有些我们自己定义的流给应用程序的接口,我们需要在请求对象

中获取。调用函数

   WdfRequestGetParameters(
       IN WDFREQUEST  Request,
      OUT PWDF_REQUEST_PARAMETERS  Parameters
     );
           请求对象会在队列处理函数中,以参数的形式传给你,所以,你可以得到请求的参数,以确定IOCTL,而做不同的操作。
回忆一下请求参数:

typedef struct _WDF_REQUEST_PARAMETERS {
    USHORT Size;
    UCHAR MinorFunction;
    WDF_REQUEST_TYPE Type;
    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 {
            size_t Length;
            ULONG POINTER_ALIGNMENT Key;
            LONGLONG DeviceOffset;
        } Read;
        //
        // Parameters for IRP_MJ_WRITE
        //
        struct {
            size_t Length;
            ULONG POINTER_ALIGNMENT Key;
            LONGLONG DeviceOffset;
        } Write;
        //
        // Parameters for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
        //
        struct {
            size_t OutputBufferLength;
            size_t POINTER_ALIGNMENT InputBufferLength;
            ULONG POINTER_ALIGNMENT IoControlCode;
            PVOID Type3InputBuffer;
        } DeviceIoControl;
        struct {
            PVOID Arg1;
            PVOID  Arg2;
            ULONG POINTER_ALIGNMENT IoControlCode;
            PVOID Arg4;
        } Others;
    } Parameters;
} WDF_REQUEST_PARAMETERS, *PWDF_REQUEST_PARAMETERS;

这里,我们就可以很方便的得到控制码进行操作了。

    
  
    

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值